Prechádzať zdrojové kódy

websocket和cow功能

wuroy.eth 3 dní pred
rodič
commit
f61916374b
100 zmenil súbory, kde vykonal 21867 pridanie a 11 odobranie
  1. 34 0
      database/dao/wechat/model/agent.gen.go
  2. 35 0
      database/dao/wechat/model/aliyun_avatar.gen.go
  3. 30 0
      database/dao/wechat/model/alloc_agent.gen.go
  4. 47 0
      database/dao/wechat/model/batch_msg.gen.go
  5. 36 0
      database/dao/wechat/model/batch_msg_copy1.gen.go
  6. 28 0
      database/dao/wechat/model/category.gen.go
  7. 32 0
      database/dao/wechat/model/chat_records.gen.go
  8. 30 0
      database/dao/wechat/model/chat_session.gen.go
  9. 53 0
      database/dao/wechat/model/contact.gen.go
  10. 31 0
      database/dao/wechat/model/credit_balance.gen.go
  11. 36 0
      database/dao/wechat/model/credit_usage.gen.go
  12. 47 0
      database/dao/wechat/model/employee.gen.go
  13. 30 0
      database/dao/wechat/model/employee_config.gen.go
  14. 32 0
      database/dao/wechat/model/form_records.gen.go
  15. 33 0
      database/dao/wechat/model/intent_org.gen.go
  16. 32 0
      database/dao/wechat/model/intent_records.gen.go
  17. 33 0
      database/dao/wechat/model/label.gen.go
  18. 30 0
      database/dao/wechat/model/label_relationship.gen.go
  19. 32 0
      database/dao/wechat/model/label_tagging.gen.go
  20. 40 0
      database/dao/wechat/model/message_records.gen.go
  21. 38 0
      database/dao/wechat/model/mismatch_records.gen.go
  22. 34 0
      database/dao/wechat/model/msg.gen.go
  23. 33 0
      database/dao/wechat/model/pay_recharge.gen.go
  24. 35 0
      database/dao/wechat/model/records.gen.go
  25. 31 0
      database/dao/wechat/model/server.gen.go
  26. 38 0
      database/dao/wechat/model/sop_node.gen.go
  27. 37 0
      database/dao/wechat/model/sop_stage.gen.go
  28. 35 0
      database/dao/wechat/model/sop_task.gen.go
  29. 36 0
      database/dao/wechat/model/token.gen.go
  30. 31 0
      database/dao/wechat/model/tutorial.gen.go
  31. 39 0
      database/dao/wechat/model/usage_detail.gen.go
  32. 40 0
      database/dao/wechat/model/usage_statistic_day.gen.go
  33. 40 0
      database/dao/wechat/model/usage_statistic_hour.gen.go
  34. 40 0
      database/dao/wechat/model/usage_statistic_month.gen.go
  35. 33 0
      database/dao/wechat/model/usage_total.gen.go
  36. 44 0
      database/dao/wechat/model/whatsapp.gen.go
  37. 35 0
      database/dao/wechat/model/whatsapp_channel.gen.go
  38. 32 0
      database/dao/wechat/model/work_experience.gen.go
  39. 34 0
      database/dao/wechat/model/wp_chatroom.gen.go
  40. 31 0
      database/dao/wechat/model/wp_chatroom_member.gen.go
  41. 45 0
      database/dao/wechat/model/wx.gen.go
  42. 41 0
      database/dao/wechat/model/wx_card.gen.go
  43. 36 0
      database/dao/wechat/model/wx_card_user.gen.go
  44. 29 0
      database/dao/wechat/model/wx_card_visit.gen.go
  45. 31 0
      database/dao/wechat/model/xunji_contact.gen.go
  46. 424 0
      database/dao/wechat/query/agent.gen.go
  47. 429 0
      database/dao/wechat/query/aliyun_avatar.gen.go
  48. 408 0
      database/dao/wechat/query/alloc_agent.gen.go
  49. 477 0
      database/dao/wechat/query/batch_msg.gen.go
  50. 433 0
      database/dao/wechat/query/batch_msg_copy1.gen.go
  51. 400 0
      database/dao/wechat/query/category.gen.go
  52. 417 0
      database/dao/wechat/query/chat_records.gen.go
  53. 409 0
      database/dao/wechat/query/chat_session.gen.go
  54. 500 0
      database/dao/wechat/query/contact.gen.go
  55. 409 0
      database/dao/wechat/query/credit_balance.gen.go
  56. 429 0
      database/dao/wechat/query/credit_usage.gen.go
  57. 477 0
      database/dao/wechat/query/employee.gen.go
  58. 408 0
      database/dao/wechat/query/employee_config.gen.go
  59. 424 0
      database/dao/wechat/query/form_records.gen.go
  60. 455 0
      database/dao/wechat/query/gen.go
  61. 420 0
      database/dao/wechat/query/intent_org.gen.go
  62. 424 0
      database/dao/wechat/query/intent_records.gen.go
  63. 420 0
      database/dao/wechat/query/label.gen.go
  64. 408 0
      database/dao/wechat/query/label_relationship.gen.go
  65. 416 0
      database/dao/wechat/query/label_tagging.gen.go
  66. 448 0
      database/dao/wechat/query/message_records.gen.go
  67. 448 0
      database/dao/wechat/query/mismatch_records.gen.go
  68. 425 0
      database/dao/wechat/query/msg.gen.go
  69. 417 0
      database/dao/wechat/query/pay_recharge.gen.go
  70. 436 0
      database/dao/wechat/query/records.gen.go
  71. 412 0
      database/dao/wechat/query/server.gen.go
  72. 440 0
      database/dao/wechat/query/sop_node.gen.go
  73. 436 0
      database/dao/wechat/query/sop_stage.gen.go
  74. 428 0
      database/dao/wechat/query/sop_task.gen.go
  75. 433 0
      database/dao/wechat/query/token.gen.go
  76. 413 0
      database/dao/wechat/query/tutorial.gen.go
  77. 444 0
      database/dao/wechat/query/usage_detail.gen.go
  78. 448 0
      database/dao/wechat/query/usage_statistic_day.gen.go
  79. 448 0
      database/dao/wechat/query/usage_statistic_hour.gen.go
  80. 448 0
      database/dao/wechat/query/usage_statistic_month.gen.go
  81. 420 0
      database/dao/wechat/query/usage_total.gen.go
  82. 465 0
      database/dao/wechat/query/whatsapp.gen.go
  83. 429 0
      database/dao/wechat/query/whatsapp_channel.gen.go
  84. 417 0
      database/dao/wechat/query/work_experience.gen.go
  85. 424 0
      database/dao/wechat/query/wp_chatroom.gen.go
  86. 412 0
      database/dao/wechat/query/wp_chatroom_member.gen.go
  87. 468 0
      database/dao/wechat/query/wx.gen.go
  88. 453 0
      database/dao/wechat/query/wx_card.gen.go
  89. 433 0
      database/dao/wechat/query/wx_card_user.gen.go
  90. 405 0
      database/dao/wechat/query/wx_card_visit.gen.go
  91. 412 0
      database/dao/wechat/query/xunji_contact.gen.go
  92. 61 0
      database/gorm_gen.go
  93. 20 0
      database/gorm_gen_test.go
  94. 37 0
      database/gorm_init.go
  95. 77 0
      database/gorm_logger.go
  96. 17 6
      etc/wechat.yaml
  97. 15 0
      go.mod
  98. 61 5
      go.sum
  99. 2 0
      internal/config/config.go
  100. 129 0
      internal/pkg/customer_of_im/channel/channel.go

+ 34 - 0
database/dao/wechat/model/agent.gen.go

@@ -0,0 +1,34 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameAgent = "agent"
+
+// Agent mapped from table <agent>
+type Agent struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time      `gorm:"column:created_at;not null;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	Status         int64          `gorm:"column:status;default:1;comment:状态 1 正常 2 禁用" json:"status"`              // 状态 1 正常 2 禁用
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`          // Delete Time | 删除日期
+	Name           string         `gorm:"column:name;comment:agent 名称" json:"name"`                                // agent 名称
+	Role           string         `gorm:"column:role;comment:角色设定" json:"role"`                                    // 角色设定
+	Background     string         `gorm:"column:background;comment:背景介绍" json:"background"`                        // 背景介绍
+	Examples       string         `gorm:"column:examples;comment:对话案例" json:"examples"`                            // 对话案例
+	OrganizationID int64          `gorm:"column:organization_id;default:1;comment:机构 ID" json:"organization_id"`   // 机构 ID
+	DatasetID      string         `gorm:"column:dataset_id;comment:知识库ID" json:"dataset_id"`                       // 知识库ID
+	CollectionID   string         `gorm:"column:collection_id;comment:集合ID" json:"collection_id"`                  // 集合ID
+}
+
+// TableName Agent's table name
+func (*Agent) TableName() string {
+	return TableNameAgent
+}

+ 35 - 0
database/dao/wechat/model/aliyun_avatar.gen.go

@@ -0,0 +1,35 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameAliyunAvatar = "aliyun_avatar"
+
+// AliyunAvatar 阿里云数字人记录表
+type AliyunAvatar struct {
+	ID              int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt       time.Time      `gorm:"column:created_at;not null;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt       time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	DeletedAt       gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`          // Delete Time | 删除日期
+	UserID          int64          `gorm:"column:user_id;comment:userID" json:"user_id"`                            // userID
+	BizID           string         `gorm:"column:biz_id;comment:bizId" json:"biz_id"`                               // bizId
+	AccessKeyID     string         `gorm:"column:access_key_id" json:"access_key_id"`
+	AccessKeySecret string         `gorm:"column:access_key_secret" json:"access_key_secret"`
+	AppID           string         `gorm:"column:app_id" json:"app_id"`
+	TenantID        string         `gorm:"column:tenant_id" json:"tenant_id"`
+	Response        string         `gorm:"column:response" json:"response"`
+	Token           string         `gorm:"column:token" json:"token"`
+	SessionID       string         `gorm:"column:session_id" json:"session_id"`
+}
+
+// TableName AliyunAvatar's table name
+func (*AliyunAvatar) TableName() string {
+	return TableNameAliyunAvatar
+}

+ 30 - 0
database/dao/wechat/model/alloc_agent.gen.go

@@ -0,0 +1,30 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameAllocAgent = "alloc_agent"
+
+// AllocAgent mapped from table <alloc_agent>
+type AllocAgent struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time      `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	Status         int64          `gorm:"column:status;not null;default:1;comment:状态 1 正常 2 禁用" json:"status"`                               // 状态 1 正常 2 禁用
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                    // Delete Time | 删除日期
+	UserID         string         `gorm:"column:user_id;comment:前台用户ID" json:"user_id"`                                                      // 前台用户ID
+	OrganizationID int64          `gorm:"column:organization_id;comment:机构 ID" json:"organization_id"`                                       // 机构 ID
+	Agents         string         `gorm:"column:agents;comment:分配的智能体ID" json:"agents"`                                                      // 分配的智能体ID
+}
+
+// TableName AllocAgent's table name
+func (*AllocAgent) TableName() string {
+	return TableNameAllocAgent
+}

+ 47 - 0
database/dao/wechat/model/batch_msg.gen.go

@@ -0,0 +1,47 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameBatchMsg = "batch_msg"
+
+// BatchMsg 批量消息表
+type BatchMsg struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time      `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"`                           // Update Time | 修改日期
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                    // Delete Time | 删除日期
+	TaskName       string         `gorm:"column:task_name;comment:群发任务名称" json:"task_name"`                                                  // 群发任务名称
+	Status         int64          `gorm:"column:status;comment:状态 0 未开始 1 发送中 2 发送完成 3 发送中止" json:"status"`                                  // 状态 0 未开始 1 发送中 2 发送完成 3 发送中止
+	BatchNo        string         `gorm:"column:batch_no;comment:批次号" json:"batch_no"`                                                       // 批次号
+	Fromwxid       string         `gorm:"column:fromwxid;comment:发送方微信ID" json:"fromwxid"`                                                   // 发送方微信ID
+	Msg            string         `gorm:"column:msg;comment:内容" json:"msg"`                                                                  // 内容
+	Tagids         string         `gorm:"column:tagids;comment:需要发送的tagids" json:"tagids"`                                                   // 需要发送的tagids
+	Tag            string         `gorm:"column:tag;comment:发送规则 all 全部 tag1,tag2 按tag发送" json:"tag"`                                        // 发送规则 all 全部 tag1,tag2 按tag发送
+	Total          int64          `gorm:"column:total;comment:总数" json:"total"`                                                              // 总数
+	Success        int64          `gorm:"column:success;comment:成功数量" json:"success"`                                                        // 成功数量
+	Fail           int64          `gorm:"column:fail;comment:失败数量" json:"fail"`                                                              // 失败数量
+	StartTime      time.Time      `gorm:"column:start_time;comment:开始时间" json:"start_time"`                                                  // 开始时间
+	StopTime       time.Time      `gorm:"column:stop_time;comment:结束时间" json:"stop_time"`                                                    // 结束时间
+	SendTime       time.Time      `gorm:"column:send_time;comment:发送时间" json:"send_time"`                                                    // 发送时间
+	Type           int64          `gorm:"column:type;default:1;comment:1-群发消息 2-群发朋友圈" json:"type"`                                          // 1-群发消息 2-群发朋友圈
+	OrganizationID int64          `gorm:"column:organization_id;comment:机构ID" json:"organization_id"`                                        // 机构ID
+	Ctype          int64          `gorm:"column:ctype;default:1;comment:内容类型:1-微信 2-whatsapp 3-企微" json:"ctype"`                             // 内容类型:1-微信 2-whatsapp 3-企微
+	Cc             string         `gorm:"column:cc;comment:国家区号" json:"cc"`                                                                  // 国家区号
+	Phone          string         `gorm:"column:phone;comment:手机号" json:"phone"`                                                             // 手机号
+	TemplateName   string         `gorm:"column:template_name;comment:模板名" json:"template_name"`                                             // 模板名
+	TemplateCode   string         `gorm:"column:template_code;comment:模板code" json:"template_code"`                                          // 模板code
+	Lang           string         `gorm:"column:lang;comment:模板语言" json:"lang"`                                                              // 模板语言
+}
+
+// TableName BatchMsg's table name
+func (*BatchMsg) TableName() string {
+	return TableNameBatchMsg
+}

+ 36 - 0
database/dao/wechat/model/batch_msg_copy1.gen.go

@@ -0,0 +1,36 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameBatchMsgCopy1 = "batch_msg_copy1"
+
+// BatchMsgCopy1 批量消息表
+type BatchMsgCopy1 struct {
+	ID        int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt time.Time      `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"`                           // Update Time | 修改日期
+	DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                    // Delete Time | 删除日期
+	Status    int64          `gorm:"column:status;comment:状态 0 未开始 1 发送中 2 发送完成 3 发送中止" json:"status"`                                  // 状态 0 未开始 1 发送中 2 发送完成 3 发送中止
+	BatchNo   string         `gorm:"column:batch_no;comment:批次号" json:"batch_no"`                                                       // 批次号
+	Fromwxid  string         `gorm:"column:fromwxid;comment:发送方微信ID" json:"fromwxid"`                                                   // 发送方微信ID
+	Msg       string         `gorm:"column:msg;comment:内容" json:"msg"`                                                                  // 内容
+	Tag       string         `gorm:"column:tag;comment:发送规则 all 全部 tag1,tag2 按tag发送" json:"tag"`                                        // 发送规则 all 全部 tag1,tag2 按tag发送
+	Total     int64          `gorm:"column:total;comment:总数" json:"total"`                                                              // 总数
+	Success   int64          `gorm:"column:success;comment:成功数量" json:"success"`                                                        // 成功数量
+	Fail      int64          `gorm:"column:fail;comment:失败数量" json:"fail"`                                                              // 失败数量
+	StartTime time.Time      `gorm:"column:start_time;comment:开始时间" json:"start_time"`                                                  // 开始时间
+	StopTime  time.Time      `gorm:"column:stop_time;comment:结束时间" json:"stop_time"`                                                    // 结束时间
+}
+
+// TableName BatchMsgCopy1's table name
+func (*BatchMsgCopy1) TableName() string {
+	return TableNameBatchMsgCopy1
+}

+ 28 - 0
database/dao/wechat/model/category.gen.go

@@ -0,0 +1,28 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameCategory = "category"
+
+// Category mapped from table <category>
+type Category struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time      `gorm:"column:created_at;not null;comment:Create Time | 创建日期" json:"created_at"`      // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"`      // Update Time | 修改日期
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`               // Delete Time | 删除日期
+	Name           string         `gorm:"column:name;comment:name | agent 名称" json:"name"`                              // name | agent 名称
+	OrganizationID int64          `gorm:"column:organization_id;comment:organization_id | 租户id" json:"organization_id"` // organization_id | 租户id
+}
+
+// TableName Category's table name
+func (*Category) TableName() string {
+	return TableNameCategory
+}

+ 32 - 0
database/dao/wechat/model/chat_records.gen.go

@@ -0,0 +1,32 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameChatRecord = "chat_records"
+
+// ChatRecord 聊天历史记录
+type ChatRecord struct {
+	ID          int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt   time.Time      `gorm:"column:created_at;not null;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt   time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	DeletedAt   gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`          // Delete Time | 删除日期
+	Content     string         `gorm:"column:content;comment:内容" json:"content"`                                // 内容
+	ContentType int64          `gorm:"column:content_type;default:1;comment:类型:1-提问 2-回答" json:"content_type"`  // 类型:1-提问 2-回答
+	SessionID   int64          `gorm:"column:session_id;not null;comment:会话ID" json:"session_id"`               // 会话ID
+	UserID      int64          `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"`                     // 用户ID
+	BotID       int64          `gorm:"column:bot_id;not null;comment:聊天ID" json:"bot_id"`                       // 聊天ID
+	BotType     int64          `gorm:"column:bot_type;comment:用户类型:1-微信 2-小程序 3-智能体" json:"bot_type"`           // 用户类型:1-微信 2-小程序 3-智能体
+}
+
+// TableName ChatRecord's table name
+func (*ChatRecord) TableName() string {
+	return TableNameChatRecord
+}

+ 30 - 0
database/dao/wechat/model/chat_session.gen.go

@@ -0,0 +1,30 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameChatSession = "chat_session"
+
+// ChatSession 聊天会话表
+type ChatSession struct {
+	ID        int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt time.Time      `gorm:"column:created_at;not null;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`          // Delete Time | 删除日期
+	Name      string         `gorm:"column:name;comment:会话名称" json:"name"`                                    // 会话名称
+	UserID    int64          `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"`                     // 用户ID
+	BotID     int64          `gorm:"column:bot_id;comment:聊天 ID" json:"bot_id"`                               // 聊天 ID
+	BotType   int64          `gorm:"column:bot_type;comment:类型:1-微信 2-小程序 3-智能体" json:"bot_type"`             // 类型:1-微信 2-小程序 3-智能体
+}
+
+// TableName ChatSession's table name
+func (*ChatSession) TableName() string {
+	return TableNameChatSession
+}

+ 53 - 0
database/dao/wechat/model/contact.gen.go

@@ -0,0 +1,53 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameContact = "contact"
+
+// Contact mapped from table <contact>
+type Contact struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time      `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	Status         int64          `gorm:"column:status;default:1;comment:Status 1: normal 2: ban | 状态 1 正常 2 禁用" json:"status"`              // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                    // Delete Time | 删除日期
+	WxWxid         string         `gorm:"column:wx_wxid;comment:属主微信id" json:"wx_wxid"`                                                      // 属主微信id
+	Type           int64          `gorm:"column:type;default:1;comment:联系人类型:1好友,2群组,3公众号,4企业微信联系人" json:"type"`                             // 联系人类型:1好友,2群组,3公众号,4企业微信联系人
+	Wxid           string         `gorm:"column:wxid;not null;comment:微信id 公众号微信ID" json:"wxid"`                                             // 微信id 公众号微信ID
+	Account        string         `gorm:"column:account;not null;comment:微信账号" json:"account"`                                               // 微信账号
+	Nickname       string         `gorm:"column:nickname;not null;comment:微信昵称 群备注名称" json:"nickname"`                                       // 微信昵称 群备注名称
+	Markname       string         `gorm:"column:markname;not null;comment:备注名" json:"markname"`                                              // 备注名
+	Headimg        string         `gorm:"column:headimg;not null;comment:头像" json:"headimg"`                                                 // 头像
+	Sex            int64          `gorm:"column:sex;not null;comment:性别 0未知 1男 2女" json:"sex"`                                               // 性别 0未知 1男 2女
+	Starrole       string         `gorm:"column:starrole;not null;comment:星标 65/67=星标 1/3=未星标" json:"starrole"`                              // 星标 65/67=星标 1/3=未星标
+	Dontseeit      int64          `gorm:"column:dontseeit;not null;comment:不让他看我的朋友圈 0可以看 1不让看" json:"dontseeit"`                            // 不让他看我的朋友圈 0可以看 1不让看
+	Dontseeme      int64          `gorm:"column:dontseeme;not null;comment:不看他的朋友圈 0可以看 1不看 1=开启了不看他 128/129=仅聊天" json:"dontseeme"`          // 不看他的朋友圈 0可以看 1不看 1=开启了不看他 128/129=仅聊天
+	Lag            string         `gorm:"column:lag;not null;comment:所属标签id清单,多开会用逗号隔开" json:"lag"`                                          // 所属标签id清单,多开会用逗号隔开
+	Gid            string         `gorm:"column:gid;not null;comment:群组id" json:"gid"`                                                       // 群组id
+	Gname          string         `gorm:"column:gname;not null;comment:群组名称" json:"gname"`                                                   // 群组名称
+	V3             string         `gorm:"column:v3;not null;comment:v3数据" json:"v3"`                                                         // v3数据
+	OrganizationID int64          `gorm:"column:organization_id;default:1;comment:机构 ID" json:"organization_id"`                             // 机构 ID
+	Ctype          int64          `gorm:"column:ctype;default:1;comment:内容类型:1-微信 2-whatsapp 3-企微" json:"ctype"`                             // 内容类型:1-微信 2-whatsapp 3-企微
+	Cc             string         `gorm:"column:cc;comment:国家区号" json:"cc"`                                                                  // 国家区号
+	Phone          string         `gorm:"column:phone;comment:手机号" json:"phone"`                                                             // 手机号
+	Cname          string         `gorm:"column:cname;comment:姓名" json:"cname"`                                                              // 姓名
+	Cage           int64          `gorm:"column:cage;comment:年龄" json:"cage"`                                                                // 年龄
+	Carea          string         `gorm:"column:carea;comment:地区" json:"carea"`                                                              // 地区
+	Cbirthday      string         `gorm:"column:cbirthday;comment:出生日期" json:"cbirthday"`                                                    // 出生日期
+	Cbirtharea     string         `gorm:"column:cbirtharea;comment:出生地" json:"cbirtharea"`                                                   // 出生地
+	CidcardNo      string         `gorm:"column:cidcard_no;comment:身份证号" json:"cidcard_no"`                                                  // 身份证号
+	Ctitle         string         `gorm:"column:ctitle;comment:称呼" json:"ctitle"`                                                            // 称呼
+}
+
+// TableName Contact's table name
+func (*Contact) TableName() string {
+	return TableNameContact
+}

+ 31 - 0
database/dao/wechat/model/credit_balance.gen.go

@@ -0,0 +1,31 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"github.com/shopspring/decimal"
+	"gorm.io/gorm"
+)
+
+const TableNameCreditBalance = "credit_balance"
+
+// CreditBalance 积分余额表
+type CreditBalance struct {
+	ID             int64           `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time       `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt      time.Time       `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	Status         int64           `gorm:"column:status;not null;default:1;comment:状态 1 正常 2 禁用" json:"status"`                               // 状态 1 正常 2 禁用
+	DeletedAt      gorm.DeletedAt  `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                    // Delete Time | 删除日期
+	UserID         string          `gorm:"column:user_id;not null;default:1;comment:用户ID" json:"user_id"`                                     // 用户ID
+	Balance        decimal.Decimal `gorm:"column:balance;not null;default:0.0000;comment:积分余额" json:"balance"`                                // 积分余额
+	OrganizationID int64           `gorm:"column:organization_id;not null;comment:机构 ID" json:"organization_id"`                              // 机构 ID
+}
+
+// TableName CreditBalance's table name
+func (*CreditBalance) TableName() string {
+	return TableNameCreditBalance
+}

+ 36 - 0
database/dao/wechat/model/credit_usage.gen.go

@@ -0,0 +1,36 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"github.com/shopspring/decimal"
+	"gorm.io/gorm"
+)
+
+const TableNameCreditUsage = "credit_usage"
+
+// CreditUsage 积分变化明细表
+type CreditUsage struct {
+	ID             int64           `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time       `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt      time.Time       `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	Status         int64           `gorm:"column:status;not null;default:1;comment:状态 1 正常 2 禁用" json:"status"`                               // 状态 1 正常 2 禁用
+	DeletedAt      gorm.DeletedAt  `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                    // Delete Time | 删除日期
+	UserID         string          `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"`                                               // 用户ID
+	Number         decimal.Decimal `gorm:"column:number;not null;default:0.0000;comment:积分改变量" json:"number"`                                 // 积分改变量
+	Ntype          int64           `gorm:"column:ntype;not null;default:1;comment:积分变化类型:1-消耗 2-增加" json:"ntype"`                             // 积分变化类型:1-消耗 2-增加
+	MTable         string          `gorm:"column:table;not null;comment:积分变化表名" json:"table"`                                                 // 积分变化表名
+	Nid            int64           `gorm:"column:nid;not null;comment:积分变化关联信息ID" json:"nid"`                                                 // 积分变化关联信息ID
+	Reason         string          `gorm:"column:reason;comment:积分变动原因" json:"reason"`                                                        // 积分变动原因
+	Operator       string          `gorm:"column:operator;comment:积分调整人" json:"operator"`                                                     // 积分调整人
+	OrganizationID int64           `gorm:"column:organization_id;not null;default:1;comment:机构 ID" json:"organization_id"`                    // 机构 ID
+}
+
+// TableName CreditUsage's table name
+func (*CreditUsage) TableName() string {
+	return TableNameCreditUsage
+}

+ 47 - 0
database/dao/wechat/model/employee.gen.go

@@ -0,0 +1,47 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameEmployee = "employee"
+
+// Employee 数字员工表
+type Employee struct {
+	ID               int64          `gorm:"column:id;primaryKey;autoIncrement:true;comment:ID" json:"id"`   // ID
+	CreatedAt        time.Time      `gorm:"column:created_at;comment:创建时间" json:"created_at"`               // 创建时间
+	UpdatedAt        time.Time      `gorm:"column:updated_at;comment:修改时间" json:"updated_at"`               // 修改时间
+	DeletedAt        gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"`               // 删除时间
+	Title            string         `gorm:"column:title;comment:标题" json:"title"`                           // 标题
+	Avatar           string         `gorm:"column:avatar;comment:头像URL" json:"avatar"`                      // 头像URL
+	Tags             string         `gorm:"column:tags;comment:Tag列表 用,连接多个" json:"tags"`                   // Tag列表 用,连接多个
+	HireCount        int64          `gorm:"column:hire_count;comment:被雇佣次数" json:"hire_count"`              // 被雇佣次数
+	ServiceCount     int64          `gorm:"column:service_count;comment:服务次数" json:"service_count"`         // 服务次数
+	AchievementCount int64          `gorm:"column:achievement_count;comment:业绩单数" json:"achievement_count"` // 业绩单数
+	Intro            string         `gorm:"column:intro;comment:个人介绍" json:"intro"`                         // 个人介绍
+	Estimate         string         `gorm:"column:estimate;comment:自我评价" json:"estimate"`                   // 自我评价
+	Skill            string         `gorm:"column:skill;comment:技能卡" json:"skill"`                          // 技能卡
+	AbilityType      string         `gorm:"column:ability_type;comment:能力类型 用,连接" json:"ability_type"`      // 能力类型 用,连接
+	Scene            string         `gorm:"column:scene;comment:使用场景 用,连接" json:"scene"`                    // 使用场景 用,连接
+	SwitchIn         string         `gorm:"column:switch_in;comment:支持接入 用,连接" json:"switch_in"`            // 支持接入 用,连接
+	Tutorial         string         `gorm:"column:tutorial;comment:使用教程" json:"tutorial"`                   // 使用教程
+	VideoURL         string         `gorm:"column:video_url;comment:视频" json:"video_url"`                   // 视频
+	OrganizationID   int64          `gorm:"column:organization_id;comment:机构ID" json:"organization_id"`     // 机构ID
+	CategoryID       int64          `gorm:"column:category_id;comment:分类ID" json:"category_id"`             // 分类ID
+	APIBase          string         `gorm:"column:api_base" json:"api_base"`
+	APIKey           string         `gorm:"column:api_key" json:"api_key"`
+	IsVip            int64          `gorm:"column:is_vip;comment:是否VIP:0-否 1-是" json:"is_vip"` // 是否VIP:0-否 1-是
+	AiInfo           string         `gorm:"column:ai_info;comment:AI信息" json:"ai_info"`        // AI信息
+	ChatURL          string         `gorm:"column:chat_url;comment:聊天URL" json:"chat_url"`     // 聊天URL
+}
+
+// TableName Employee's table name
+func (*Employee) TableName() string {
+	return TableNameEmployee
+}

+ 30 - 0
database/dao/wechat/model/employee_config.gen.go

@@ -0,0 +1,30 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameEmployeeConfig = "employee_config"
+
+// EmployeeConfig mapped from table <employee_config>
+type EmployeeConfig struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time      `gorm:"column:created_at;not null;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`          // Delete Time | 删除日期
+	Stype          string         `gorm:"column:stype;not null;comment:配置类型" json:"stype"`                         // 配置类型
+	Title          string         `gorm:"column:title;comment:标题" json:"title"`                                    // 标题
+	Photo          string         `gorm:"column:photo;comment:图片" json:"photo"`                                    // 图片
+	OrganizationID int64          `gorm:"column:organization_id;default:1;comment:机构 ID" json:"organization_id"`   // 机构 ID
+}
+
+// TableName EmployeeConfig's table name
+func (*EmployeeConfig) TableName() string {
+	return TableNameEmployeeConfig
+}

+ 32 - 0
database/dao/wechat/model/form_records.gen.go

@@ -0,0 +1,32 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+)
+
+const TableNameFormRecord = "form_records"
+
+// FormRecord mapped from table <form_records>
+type FormRecord struct {
+	ID           string    `gorm:"column:id;primaryKey;comment:主键id" json:"id"`                                 // 主键id
+	ExternalID   string    `gorm:"column:external_id;not null;comment:外部id" json:"external_id"`                 // 外部id
+	IndustryType int64     `gorm:"column:industry_type;not null;comment:评分规则代码 0 通用 1 教育" json:"industry_type"` // 评分规则代码 0 通用 1 教育
+	ChatHistory  string    `gorm:"column:chat_history;not null;comment:通话记录" json:"chat_history"`               // 通话记录
+	FormData     string    `gorm:"column:form_data;comment:表单数据" json:"form_data"`                              // 表单数据
+	FormValue    string    `gorm:"column:form_value;comment:表单结果" json:"form_value"`                            // 表单结果
+	OrgID        int64     `gorm:"column:org_id;not null;comment:机构 ID" json:"org_id"`                          // 机构 ID
+	Status       int64     `gorm:"column:status;not null;comment:状态 1 入库 2 已判断 3 已回调" json:"status"`            // 状态 1 入库 2 已判断 3 已回调
+	RequestData  string    `gorm:"column:request_data" json:"request_data"`
+	ResponseData string    `gorm:"column:response_data" json:"response_data"`
+	CreatedAt    time.Time `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt    time.Time `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+}
+
+// TableName FormRecord's table name
+func (*FormRecord) TableName() string {
+	return TableNameFormRecord
+}

+ 33 - 0
database/dao/wechat/model/intent_org.gen.go

@@ -0,0 +1,33 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameIntentOrg = "intent_org"
+
+// IntentOrg mapped from table <intent_org>
+type IntentOrg struct {
+	ID               int64          `gorm:"column:id;primaryKey" json:"id"`
+	Name             string         `gorm:"column:name;comment:机构名称" json:"name"` // 机构名称
+	APIKey           string         `gorm:"column:api_key" json:"api_key"`
+	OpenaiBase       string         `gorm:"column:openai_base" json:"openai_base"`
+	OpenaiKey        string         `gorm:"column:openai_key" json:"openai_key"`
+	IntentCallback   string         `gorm:"column:intent_callback;comment:意向度结果推送地址" json:"intent_callback"`                                   // 意向度结果推送地址
+	MismatchCallback string         `gorm:"column:mismatch_callback;comment:未匹配结果推送地址" json:"mismatch_callback"`                               // 未匹配结果推送地址
+	Status           int64          `gorm:"column:status;not null;default:1;comment:状态 1 正常 2 禁用" json:"status"`                               // 状态 1 正常 2 禁用
+	DeletedAt        gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                    // Delete Time | 删除日期
+	CreatedAt        time.Time      `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt        time.Time      `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+}
+
+// TableName IntentOrg's table name
+func (*IntentOrg) TableName() string {
+	return TableNameIntentOrg
+}

+ 32 - 0
database/dao/wechat/model/intent_records.gen.go

@@ -0,0 +1,32 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+)
+
+const TableNameIntentRecord = "intent_records"
+
+// IntentRecord mapped from table <intent_records>
+type IntentRecord struct {
+	ID           string    `gorm:"column:id;primaryKey;comment:主键id" json:"id"`                                 // 主键id
+	ExternalID   string    `gorm:"column:external_id;not null;comment:外部id" json:"external_id"`                 // 外部id
+	IndustryType int64     `gorm:"column:industry_type;not null;comment:评分规则代码 0 通用 1 教育" json:"industry_type"` // 评分规则代码 0 通用 1 教育
+	ChatHistory  string    `gorm:"column:chat_history;not null;comment:通话记录" json:"chat_history"`               // 通话记录
+	ManualIntent int64     `gorm:"column:manual_intent;comment:人工意向度 1 有意向 2 无意向 3 其他" json:"manual_intent"`    // 人工意向度 1 有意向 2 无意向 3 其他
+	LlmIntent    int64     `gorm:"column:llm_intent;comment:大模型意向度 1 有意向 2 无意向 3 不确定" json:"llm_intent"`        // 大模型意向度 1 有意向 2 无意向 3 不确定
+	OrgID        int64     `gorm:"column:org_id;not null;comment:机构 ID" json:"org_id"`                          // 机构 ID
+	Status       int64     `gorm:"column:status;not null;comment:状态 1 入库 2 已判断 3 已回调" json:"status"`            // 状态 1 入库 2 已判断 3 已回调
+	RequestData  string    `gorm:"column:request_data" json:"request_data"`
+	ResponseData string    `gorm:"column:response_data" json:"response_data"`
+	CreatedAt    time.Time `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt    time.Time `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+}
+
+// TableName IntentRecord's table name
+func (*IntentRecord) TableName() string {
+	return TableNameIntentRecord
+}

+ 33 - 0
database/dao/wechat/model/label.gen.go

@@ -0,0 +1,33 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameLabel = "label"
+
+// Label mapped from table <label>
+type Label struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time      `gorm:"column:created_at;not null;comment:Create Time | 创建日期" json:"created_at"`              // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"`              // Update Time | 修改日期
+	Status         int64          `gorm:"column:status;default:1;comment:Status 1: normal 2: ban | 状态 1 正常 2 禁用" json:"status"` // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                       // Delete Time | 删除日期
+	Type           int64          `gorm:"column:type;default:1;comment:标签类型:1好友,2群组,3公众号,4企业微信联系人" json:"type"`                 // 标签类型:1好友,2群组,3公众号,4企业微信联系人
+	Name           string         `gorm:"column:name;not null;comment:标签名称" json:"name"`                                        // 标签名称
+	From           int64          `gorm:"column:from;not null;comment:标签来源:1后台创建 2个微同步" json:"from"`                            // 标签来源:1后台创建 2个微同步
+	Mode           int64          `gorm:"column:mode;not null;comment:标签模式:1动态 2静态" json:"mode"`                                // 标签模式:1动态 2静态
+	Conditions     string         `gorm:"column:conditions;comment:标签的触达条件" json:"conditions"`                                  // 标签的触达条件
+	OrganizationID int64          `gorm:"column:organization_id;default:1;comment:机构 ID" json:"organization_id"`                // 机构 ID
+}
+
+// TableName Label's table name
+func (*Label) TableName() string {
+	return TableNameLabel
+}

+ 30 - 0
database/dao/wechat/model/label_relationship.gen.go

@@ -0,0 +1,30 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameLabelRelationship = "label_relationship"
+
+// LabelRelationship mapped from table <label_relationship>
+type LabelRelationship struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time      `gorm:"column:created_at;not null;comment:Create Time | 创建日期" json:"created_at"`              // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"`              // Update Time | 修改日期
+	Status         int64          `gorm:"column:status;default:1;comment:Status 1: normal 2: ban | 状态 1 正常 2 禁用" json:"status"` // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                       // Delete Time | 删除日期
+	LabelID        int64          `gorm:"column:label_id;not null" json:"label_id"`
+	ContactID      int64          `gorm:"column:contact_id;not null" json:"contact_id"`
+	OrganizationID int64          `gorm:"column:organization_id;default:1;comment:机构 ID" json:"organization_id"` // 机构 ID
+}
+
+// TableName LabelRelationship's table name
+func (*LabelRelationship) TableName() string {
+	return TableNameLabelRelationship
+}

+ 32 - 0
database/dao/wechat/model/label_tagging.gen.go

@@ -0,0 +1,32 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameLabelTagging = "label_tagging"
+
+// LabelTagging mapped from table <label_tagging>
+type LabelTagging struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time      `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	Status         int64          `gorm:"column:status;not null;default:1;comment:状态 1 正常 2 禁用" json:"status"`                               // 状态 1 正常 2 禁用
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                    // Delete Time | 删除日期
+	OrganizationID int64          `gorm:"column:organization_id;not null;default:1;comment:机构 ID" json:"organization_id"`                    // 机构 ID
+	Type           int64          `gorm:"column:type;not null;default:1;comment:标签类型:1好友,2群组,3公众号,4企业微信联系人" json:"type"`                     // 标签类型:1好友,2群组,3公众号,4企业微信联系人
+	Conditions     string         `gorm:"column:conditions;comment:标签的触达条件" json:"conditions"`                                               // 标签的触达条件
+	ActionLabelAdd string         `gorm:"column:action_label_add;comment:命中后需要打的标签" json:"action_label_add"`                                 // 命中后需要打的标签
+	ActionLabelDel string         `gorm:"column:action_label_del;comment:命中后需要打的标签" json:"action_label_del"`                                 // 命中后需要打的标签
+}
+
+// TableName LabelTagging's table name
+func (*LabelTagging) TableName() string {
+	return TableNameLabelTagging
+}

+ 40 - 0
database/dao/wechat/model/message_records.gen.go

@@ -0,0 +1,40 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameMessageRecord = "message_records"
+
+// MessageRecord mapped from table <message_records>
+type MessageRecord struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time      `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	Status         int64          `gorm:"column:status;default:1;comment:发送状态:1 未发送  2  发送中  3 发送成功 4 发送失败 ….(待定)" json:"status"`            // 发送状态:1 未发送  2  发送中  3 发送成功 4 发送失败 ….(待定)
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                    // Delete Time | 删除日期
+	BotWxid        string         `gorm:"column:bot_wxid;comment:机器人微信 id" json:"bot_wxid"`                                                  // 机器人微信 id
+	ContactID      int64          `gorm:"column:contact_id;comment:联系人 id" json:"contact_id"`                                                // 联系人 id
+	ContactType    int64          `gorm:"column:contact_type;comment:类型:1好友,2群组,3企业微信联系人" json:"contact_type"`                               // 类型:1好友,2群组,3企业微信联系人
+	ContactWxid    string         `gorm:"column:contact_wxid;comment:接收方微信 id" json:"contact_wxid"`                                          // 接收方微信 id
+	ContentType    int64          `gorm:"column:content_type;comment:内容类型 1 文本 2 文件" json:"content_type"`                                    // 内容类型 1 文本 2 文件
+	Content        string         `gorm:"column:content;comment:发送内容" json:"content"`                                                        // 发送内容
+	Meta           string         `gorm:"column:meta;comment:元数据(如文件名)" json:"meta"`                                                         // 元数据(如文件名)
+	ErrorDetail    string         `gorm:"column:error_detail;comment:异常原因" json:"error_detail"`                                              // 异常原因
+	SendTime       time.Time      `gorm:"column:send_time;comment:发送时间" json:"send_time"`                                                    // 发送时间
+	SourceType     int64          `gorm:"column:source_type;comment:源类型 1 点发 2 群发 3 SOP 阶段 4 SOP 节点" json:"source_type"`                     // 源类型 1 点发 2 群发 3 SOP 阶段 4 SOP 节点
+	SourceID       int64          `gorm:"column:source_id;comment:源 ID" json:"source_id"`                                                    // 源 ID
+	SubSourceID    int64          `gorm:"column:sub_source_id;comment:次源 ID" json:"sub_source_id"`                                           // 次源 ID
+	OrganizationID int64          `gorm:"column:organization_id;default:1;comment:机构 ID" json:"organization_id"`                             // 机构 ID
+}
+
+// TableName MessageRecord's table name
+func (*MessageRecord) TableName() string {
+	return TableNameMessageRecord
+}

+ 38 - 0
database/dao/wechat/model/mismatch_records.gen.go

@@ -0,0 +1,38 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+)
+
+const TableNameMismatchRecord = "mismatch_records"
+
+// MismatchRecord mapped from table <mismatch_records>
+type MismatchRecord struct {
+	ID                 string    `gorm:"column:id;primaryKey;comment:主键id" json:"id"`                                 // 主键id
+	ExternalID         string    `gorm:"column:external_id;not null;comment:外部id" json:"external_id"`                 // 外部id
+	IndustryType       int64     `gorm:"column:industry_type;not null;comment:评分规则代码 0 通用 1 教育" json:"industry_type"` // 评分规则代码 0 通用 1 教育
+	ChatHistory        string    `gorm:"column:chat_history;not null;comment:通话记录" json:"chat_history"`               // 通话记录
+	Missed             string    `gorm:"column:missed;not null;comment:未匹配内容" json:"missed"`                          // 未匹配内容
+	Ignore             int64     `gorm:"column:ignore;not null;comment:0 自动过滤(默认) 1 手动标记忽略 2 不忽略强制分析" json:"ignore"`  // 0 自动过滤(默认) 1 手动标记忽略 2 不忽略强制分析
+	LlmIgnore          int64     `gorm:"column:llm_ignore;not null;comment:0 未过滤 1被忽略 2未被忽略" json:"llm_ignore"`       // 0 未过滤 1被忽略 2未被忽略
+	OrgID              int64     `gorm:"column:org_id;not null;comment:机构 ID" json:"org_id"`                          // 机构 ID
+	Status             int64     `gorm:"column:status;not null;comment:状态 1 入库 2 已判断 3 已回调" json:"status"`            // 状态 1 入库 2 已判断 3 已回调
+	IgnoreResponseData string    `gorm:"column:ignore_response_data" json:"ignore_response_data"`
+	RequestData        string    `gorm:"column:request_data" json:"request_data"`
+	ResponseData       string    `gorm:"column:response_data" json:"response_data"`
+	CreatedAt          time.Time `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt          time.Time `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	UserIntent         string    `gorm:"column:user_intent;comment:针对未匹配内容,推理用户的真实目的" json:"user_intent"`                          // 针对未匹配内容,推理用户的真实目的
+	SimilarReply       string    `gorm:"column:similar_reply;comment:针对未匹配内容,生成类似的回复" json:"similar_reply"`                        // 针对未匹配内容,生成类似的回复
+	Keywords           string    `gorm:"column:keywords;comment:生成辅助关键词" json:"keywords"`                                          // 生成辅助关键词
+	Regular            string    `gorm:"column:regular;comment:生成辅助正则表达式" json:"regular"`                                          // 生成辅助正则表达式
+}
+
+// TableName MismatchRecord's table name
+func (*MismatchRecord) TableName() string {
+	return TableNameMismatchRecord
+}

+ 34 - 0
database/dao/wechat/model/msg.gen.go

@@ -0,0 +1,34 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameMsg = "msg"
+
+// Msg 消息表
+type Msg struct {
+	ID        int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt time.Time      `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt time.Time      `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                           // Delete Time | 删除日期
+	Status    int64          `gorm:"column:status;comment:Status 1: normal 2: ban | 状态 1 正常 2 禁用" json:"status"`               // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	Fromwxid  string         `gorm:"column:fromwxid;comment:发送方微信ID" json:"fromwxid"`                                          // 发送方微信ID
+	Toid      string         `gorm:"column:toid;comment:接收人微信ID/群ID" json:"toid"`                                              // 接收人微信ID/群ID
+	Msgtype   int64          `gorm:"column:msgtype;comment:消息类型" json:"msgtype"`                                               // 消息类型
+	Msg       string         `gorm:"column:msg;comment:消息" json:"msg"`                                                         // 消息
+	BatchNo   string         `gorm:"column:batch_no;comment:批次号" json:"batch_no"`                                              // 批次号
+	Cc        string         `gorm:"column:cc;comment:国家区号" json:"cc"`                                                         // 国家区号
+	Phone     string         `gorm:"column:phone;comment:手机号" json:"phone"`                                                    // 手机号
+}
+
+// TableName Msg's table name
+func (*Msg) TableName() string {
+	return TableNameMsg
+}

+ 33 - 0
database/dao/wechat/model/pay_recharge.gen.go

@@ -0,0 +1,33 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"github.com/shopspring/decimal"
+	"gorm.io/gorm"
+)
+
+const TableNamePayRecharge = "pay_recharge"
+
+// PayRecharge 充值表
+type PayRecharge struct {
+	ID             int64           `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time       `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt      time.Time       `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	Status         int64           `gorm:"column:status;not null;default:1;comment:状态 1 正常 2 禁用" json:"status"`                               // 状态 1 正常 2 禁用
+	DeletedAt      gorm.DeletedAt  `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                    // Delete Time | 删除日期
+	UserID         string          `gorm:"column:user_id;not null;default:1;comment:用户ID" json:"user_id"`                                     // 用户ID
+	Number         decimal.Decimal `gorm:"column:number;not null;default:0.0000;comment:变化积分数" json:"number"`                                 // 变化积分数
+	Money          decimal.Decimal `gorm:"column:money;default:0.0000;comment:充值钱数" json:"money"`                                             // 充值钱数
+	OutTradeNo     string          `gorm:"column:out_trade_no;comment:外部订单号" json:"out_trade_no"`                                             // 外部订单号
+	OrganizationID int64           `gorm:"column:organization_id;not null;default:1;comment:机构 ID" json:"organization_id"`                    // 机构 ID
+}
+
+// TableName PayRecharge's table name
+func (*PayRecharge) TableName() string {
+	return TableNamePayRecharge
+}

+ 35 - 0
database/dao/wechat/model/records.gen.go

@@ -0,0 +1,35 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+)
+
+const TableNameRecord = "records"
+
+// Record mapped from table <records>
+type Record struct {
+	ID         int64     `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt  time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt  time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	Body       string    `gorm:"column:body;comment:获取原始数据" json:"body"`                                                            // 获取原始数据
+	StaffNo    string    `gorm:"column:staff_no;comment:坐席工号" json:"staff_no"`                                                      // 坐席工号
+	Caller     string    `gorm:"column:caller;comment:主叫号码" json:"caller"`                                                          // 主叫号码
+	Callee     string    `gorm:"column:callee;comment:被叫号码" json:"callee"`                                                          // 被叫号码
+	RecordFile string    `gorm:"column:record_file;comment:录音文件" json:"record_file"`                                                // 录音文件
+	Session    string    `gorm:"column:session;comment:通话标识" json:"session"`                                                        // 通话标识
+	AliTrans   string    `gorm:"column:ali_trans;comment:阿里语音识别原始结果" json:"ali_trans"`                                              // 阿里语音识别原始结果
+	AliTaskID  string    `gorm:"column:ali_task_id;comment:阿里语音识别任务ID" json:"ali_task_id"`                                          // 阿里语音识别任务ID
+	Chats      string    `gorm:"column:chats;comment:提取的对话记录" json:"chats"`                                                         // 提取的对话记录
+	UserIntent string    `gorm:"column:user_intent;comment:判断的用户意图" json:"user_intent"`                                             // 判断的用户意图
+	Basis      string    `gorm:"column:basis;comment:用户意图命中的原始文本" json:"basis"`                                                     // 用户意图命中的原始文本
+	Accept     int64     `gorm:"column:accept;comment:用户是否接受邀请 0 未判断  1 接受 2 不接受" json:"accept"`                                    // 用户是否接受邀请 0 未判断  1 接受 2 不接受
+}
+
+// TableName Record's table name
+func (*Record) TableName() string {
+	return TableNameRecord
+}

+ 31 - 0
database/dao/wechat/model/server.gen.go

@@ -0,0 +1,31 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameServer = "server"
+
+// Server mapped from table <server>
+type Server struct {
+	ID        int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt time.Time      `gorm:"column:created_at;not null;comment:Create Time | 创建日期" json:"created_at"`              // Create Time | 创建日期
+	UpdatedAt time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"`              // Update Time | 修改日期
+	Status    int64          `gorm:"column:status;default:1;comment:Status 1: normal 2: ban | 状态 1 正常 2 禁用" json:"status"` // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                       // Delete Time | 删除日期
+	Name      string         `gorm:"column:name;not null;comment:名称" json:"name"`                                          // 名称
+	PublicIP  string         `gorm:"column:public_ip;not null;comment:公网ip" json:"public_ip"`                              // 公网ip
+	PrivateIP string         `gorm:"column:private_ip;not null;comment:内网ip" json:"private_ip"`                            // 内网ip
+	AdminPort string         `gorm:"column:admin_port;not null;comment:管理端口" json:"admin_port"`                            // 管理端口
+}
+
+// TableName Server's table name
+func (*Server) TableName() string {
+	return TableNameServer
+}

+ 38 - 0
database/dao/wechat/model/sop_node.gen.go

@@ -0,0 +1,38 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameSopNode = "sop_node"
+
+// SopNode mapped from table <sop_node>
+type SopNode struct {
+	ID               int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt        time.Time      `gorm:"column:created_at;not null;comment:Create Time | 创建日期" json:"created_at"`                // Create Time | 创建日期
+	UpdatedAt        time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"`                // Update Time | 修改日期
+	Status           int64          `gorm:"column:status;default:1;comment:状态 1 正常 2 禁用" json:"status"`                             // 状态 1 正常 2 禁用
+	DeletedAt        gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                         // Delete Time | 删除日期
+	StageID          int64          `gorm:"column:stage_id;comment:阶段 ID" json:"stage_id"`                                          // 阶段 ID
+	ParentID         int64          `gorm:"column:parent_id;comment:父节点 ID" json:"parent_id"`                                       // 父节点 ID
+	Name             string         `gorm:"column:name;comment:节点名称" json:"name"`                                                   // 节点名称
+	ConditionType    int64          `gorm:"column:condition_type;default:1;comment:触发条件类型 1 客户回复后触发 2 超时后触发" json:"condition_type"` // 触发条件类型 1 客户回复后触发 2 超时后触发
+	ConditionList    string         `gorm:"column:condition_list;comment:触发语义列表 当为空时则代表用户回复任意内容后触发" json:"condition_list"`          // 触发语义列表 当为空时则代表用户回复任意内容后触发
+	NoReplyCondition int64          `gorm:"column:no_reply_condition;comment:超时触发时间(分钟)" json:"no_reply_condition"`                 // 超时触发时间(分钟)
+	ActionMessage    string         `gorm:"column:action_message;comment:命中后发送的消息内容" json:"action_message"`                         // 命中后发送的消息内容
+	ActionLabelAdd   string         `gorm:"column:action_label_add;comment:命中后需要打的标签" json:"action_label_add"`                      // 命中后需要打的标签
+	ActionForward    string         `gorm:"column:action_forward;comment:命中后转发的消息" json:"action_forward"`                           // 命中后转发的消息
+	NoReplyUnit      string         `gorm:"column:no_reply_unit;comment:超时触发时间单位" json:"no_reply_unit"`                             // 超时触发时间单位
+	ActionLabelDel   string         `gorm:"column:action_label_del;comment:命中后需要打的标签" json:"action_label_del"`                      // 命中后需要打的标签
+}
+
+// TableName SopNode's table name
+func (*SopNode) TableName() string {
+	return TableNameSopNode
+}

+ 37 - 0
database/dao/wechat/model/sop_stage.gen.go

@@ -0,0 +1,37 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameSopStage = "sop_stage"
+
+// SopStage mapped from table <sop_stage>
+type SopStage struct {
+	ID                int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt         time.Time      `gorm:"column:created_at;not null;comment:Create Time | 创建日期" json:"created_at"`                        // Create Time | 创建日期
+	UpdatedAt         time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"`                        // Update Time | 修改日期
+	Status            int64          `gorm:"column:status;default:1;comment:状态 1 正常 2 禁用" json:"status"`                                     // 状态 1 正常 2 禁用
+	DeletedAt         gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                 // Delete Time | 删除日期
+	TaskID            int64          `gorm:"column:task_id;comment:SOP 任务 ID" json:"task_id"`                                                // SOP 任务 ID
+	Name              string         `gorm:"column:name;comment:阶段名称" json:"name"`                                                           // 阶段名称
+	ConditionType     int64          `gorm:"column:condition_type;default:1;comment:客群筛选条件类型  1 按标签筛选 2 按客户基本信息筛选" json:"condition_type"`    // 客群筛选条件类型  1 按标签筛选 2 按客户基本信息筛选
+	ConditionOperator int64          `gorm:"column:condition_operator;comment:筛选条件关系  1 满足所有条件(and) 2 满足任意条件(or)" json:"condition_operator"` // 筛选条件关系  1 满足所有条件(and) 2 满足任意条件(or)
+	ConditionList     string         `gorm:"column:condition_list;comment:筛选条件列表" json:"condition_list"`                                     // 筛选条件列表
+	ActionMessage     string         `gorm:"column:action_message;comment:命中后发送的消息内容" json:"action_message"`                                 // 命中后发送的消息内容
+	ActionLabelAdd    string         `gorm:"column:action_label_add;comment:命中后需要打的标签" json:"action_label_add"`                              // 命中后需要打的标签
+	ActionForward     string         `gorm:"column:action_forward;comment:命中后转发的消息" json:"action_forward"`                                   // 命中后转发的消息
+	IndexSort         int64          `gorm:"column:index_sort;comment:阶段顺序" json:"index_sort"`                                               // 阶段顺序
+	ActionLabelDel    string         `gorm:"column:action_label_del;comment:命中后需要打的标签" json:"action_label_del"`                              // 命中后需要打的标签
+}
+
+// TableName SopStage's table name
+func (*SopStage) TableName() string {
+	return TableNameSopStage
+}

+ 35 - 0
database/dao/wechat/model/sop_task.gen.go

@@ -0,0 +1,35 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameSopTask = "sop_task"
+
+// SopTask mapped from table <sop_task>
+type SopTask struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time      `gorm:"column:created_at;not null;comment:Create Time | 创建日期" json:"created_at"`      // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"`      // Update Time | 修改日期
+	Status         int64          `gorm:"column:status;default:1;comment:状态 1 草稿 2 未开始 3 已开始 4 已结束 5 禁用" json:"status"` // 状态 1 草稿 2 未开始 3 已开始 4 已结束 5 禁用
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`               // Delete Time | 删除日期
+	Name           string         `gorm:"column:name;comment:SOP 任务名称" json:"name"`                                     // SOP 任务名称
+	BotWxidList    string         `gorm:"column:bot_wxid_list;comment:机器人微信 id 列表" json:"bot_wxid_list"`                // 机器人微信 id 列表
+	Type           int64          `gorm:"column:type;default:1;comment:标签类型:1好友,2群组,3企业微信联系人" json:"type"`              // 标签类型:1好友,2群组,3企业微信联系人
+	PlanStartTime  time.Time      `gorm:"column:plan_start_time;comment:任务计划开始时间" json:"plan_start_time"`               // 任务计划开始时间
+	PlanEndTime    time.Time      `gorm:"column:plan_end_time;comment:任务计划结束时间" json:"plan_end_time"`                   // 任务计划结束时间
+	CreatorID      string         `gorm:"column:creator_id;comment:创建者 id" json:"creator_id"`                           // 创建者 id
+	OrganizationID int64          `gorm:"column:organization_id;default:1;comment:机构 ID" json:"organization_id"`        // 机构 ID
+	Token          string         `gorm:"column:token" json:"token"`
+}
+
+// TableName SopTask's table name
+func (*SopTask) TableName() string {
+	return TableNameSopTask
+}

+ 36 - 0
database/dao/wechat/model/token.gen.go

@@ -0,0 +1,36 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameToken = "token"
+
+// Token Token表
+type Token struct {
+	ID              int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt       time.Time      `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt       time.Time      `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	DeletedAt       gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除时间" json:"deleted_at"`                                    // Delete Time | 删除时间
+	ExpireAt        time.Time      `gorm:"column:expire_at;comment:过期时间" json:"expire_at"`                                                    // 过期时间
+	Token           string         `gorm:"column:token;comment:Token" json:"token"`                                                           // Token
+	Mac             string         `gorm:"column:mac;comment:Mac地址" json:"mac"`                                                               // Mac地址
+	Remark          string         `gorm:"column:remark;comment:备注" json:"remark"`                                                            // 备注
+	OrganizationID  int64          `gorm:"column:organization_id;comment:租户ID" json:"organization_id"`                                        // 租户ID
+	AgentID         int64          `gorm:"column:agent_id;comment:0 定制" json:"agent_id"`                                                      // 0 定制
+	CustomAgentBase string         `gorm:"column:custom_agent_base;comment:定制agent服务地址" json:"custom_agent_base"`                             // 定制agent服务地址
+	CustomAgentKey  string         `gorm:"column:custom_agent_key;comment:定制agent服务密钥" json:"custom_agent_key"`                               // 定制agent服务密钥
+	OpenaiBase      string         `gorm:"column:openai_base;comment:大模型服务地址" json:"openai_base"`                                             // 大模型服务地址
+	OpenaiKey       string         `gorm:"column:openai_key;comment:大模型服务密钥" json:"openai_key"`                                               // 大模型服务密钥
+}
+
+// TableName Token's table name
+func (*Token) TableName() string {
+	return TableNameToken
+}

+ 31 - 0
database/dao/wechat/model/tutorial.gen.go

@@ -0,0 +1,31 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameTutorial = "tutorial"
+
+// Tutorial 数字员工使用教程表
+type Tutorial struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	EmployeeID     int64          `gorm:"column:employee_id;comment:员工ID" json:"employee_id"`             // 员工ID
+	CreatedAt      time.Time      `gorm:"column:created_at;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"` // Delete Time | 删除日期
+	Index          int64          `gorm:"column:index;comment:序号" json:"index"`                           // 序号
+	Title          string         `gorm:"column:title;comment:标题" json:"title"`                           // 标题
+	Content        string         `gorm:"column:content;comment:内容" json:"content"`                       // 内容
+	OrganizationID int64          `gorm:"column:organization_id;comment:机构ID" json:"organization_id"`     // 机构ID
+}
+
+// TableName Tutorial's table name
+func (*Tutorial) TableName() string {
+	return TableNameTutorial
+}

+ 39 - 0
database/dao/wechat/model/usage_detail.gen.go

@@ -0,0 +1,39 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameUsageDetail = "usage_detail"
+
+// UsageDetail mapped from table <usage_detail>
+type UsageDetail struct {
+	ID               int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt        time.Time      `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"`                     // Create Time | 创建日期
+	UpdatedAt        time.Time      `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"`                     // Update Time | 修改日期
+	Status           int64          `gorm:"column:status;not null;default:1;comment:状态 1 正常 2 禁用" json:"status"`                                                   // 状态 1 正常 2 禁用
+	DeletedAt        gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                                        // Delete Time | 删除日期
+	Type             int64          `gorm:"column:type;not null;default:1;comment:1 微信 2 名片" json:"type"`                                                          // 1 微信 2 名片
+	BotID            string         `gorm:"column:bot_id;not null;comment:微信或名片id" json:"bot_id"`                                                                  // 微信或名片id
+	ReceiverID       string         `gorm:"column:receiver_id;not null;comment:微信id或open_id" json:"receiver_id"`                                                   // 微信id或open_id
+	App              int64          `gorm:"column:app;comment:1 cow-basic 2 cow-agent-优化 3 cow-agent 4 cow-sop-阶段 5cow-sop-节点 6 mp-card 7 mp-employee" json:"app"` // 1 cow-basic 2 cow-agent-优化 3 cow-agent 4 cow-sop-阶段 5cow-sop-节点 6 mp-card 7 mp-employee
+	SessionID        int64          `gorm:"column:session_id;not null;comment:名片会话id" json:"session_id"`                                                           // 名片会话id
+	Request          string         `gorm:"column:request;comment:请求内容" json:"request"`                                                                            // 请求内容
+	Response         string         `gorm:"column:response;comment:响应内容" json:"response"`                                                                          // 响应内容
+	OriginalData     string         `gorm:"column:original_data;comment:原始数据" json:"original_data"`                                                                // 原始数据
+	TotalTokens      int64          `gorm:"column:total_tokens;not null;comment:使用token总数" json:"total_tokens"`                                                    // 使用token总数
+	PromptTokens     int64          `gorm:"column:prompt_tokens;comment:请求token数" json:"prompt_tokens"`                                                            // 请求token数
+	CompletionTokens int64          `gorm:"column:completion_tokens;comment:响应token数" json:"completion_tokens"`                                                    // 响应token数
+	OrganizationID   int64          `gorm:"column:organization_id;not null;default:1;comment:机构 ID" json:"organization_id"`                                        // 机构 ID
+}
+
+// TableName UsageDetail's table name
+func (*UsageDetail) TableName() string {
+	return TableNameUsageDetail
+}

+ 40 - 0
database/dao/wechat/model/usage_statistic_day.gen.go

@@ -0,0 +1,40 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameUsageStatisticDay = "usage_statistic_day"
+
+// UsageStatisticDay mapped from table <usage_statistic_day>
+type UsageStatisticDay struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time      `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	Status         int64          `gorm:"column:status;not null;default:1;comment:状态 1 正常 2 禁用" json:"status"`                               // 状态 1 正常 2 禁用
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                    // Delete Time | 删除日期
+	Addtime        int64          `gorm:"column:addtime;comment:写入年月日" json:"addtime"`                                                       // 写入年月日
+	Type           int64          `gorm:"column:type;default:1;comment:1-微信 2-名片" json:"type"`                                               // 1-微信 2-名片
+	BotID          string         `gorm:"column:bot_id;comment:微信或名片id" json:"bot_id"`                                                       // 微信或名片id
+	OrganizationID int64          `gorm:"column:organization_id;not null;default:1;comment:机构 ID" json:"organization_id"`                    // 机构 ID
+	AiResponse     int64          `gorm:"column:ai_response;comment:AI回复次数" json:"ai_response"`                                              // AI回复次数
+	SopRun         int64          `gorm:"column:sop_run;comment:SOP运行次数" json:"sop_run"`                                                     // SOP运行次数
+	TotalFriend    int64          `gorm:"column:total_friend;comment:好友总数" json:"total_friend"`                                              // 好友总数
+	TotalGroup     int64          `gorm:"column:total_group;comment:群总数" json:"total_group"`                                                 // 群总数
+	AccountBalance int64          `gorm:"column:account_balance;comment:账户余额(单位:分)" json:"account_balance"`                                  // 账户余额(单位:分)
+	ConsumeToken   int64          `gorm:"column:consume_token;comment:消耗token数" json:"consume_token"`                                        // 消耗token数
+	ActiveUser     int64          `gorm:"column:active_user;comment:活跃用户数" json:"active_user"`                                               // 活跃用户数
+	NewUser        int64          `gorm:"column:new_user;comment:新增用户数" json:"new_user"`                                                     // 新增用户数
+	LabelDist      string         `gorm:"column:label_dist;comment:标签分布" json:"label_dist"`                                                  // 标签分布
+}
+
+// TableName UsageStatisticDay's table name
+func (*UsageStatisticDay) TableName() string {
+	return TableNameUsageStatisticDay
+}

+ 40 - 0
database/dao/wechat/model/usage_statistic_hour.gen.go

@@ -0,0 +1,40 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameUsageStatisticHour = "usage_statistic_hour"
+
+// UsageStatisticHour mapped from table <usage_statistic_hour>
+type UsageStatisticHour struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time      `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	Status         int64          `gorm:"column:status;not null;default:1;comment:状态 1 正常 2 禁用" json:"status"`                               // 状态 1 正常 2 禁用
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                    // Delete Time | 删除日期
+	Addtime        int64          `gorm:"column:addtime;comment:写入小时" json:"addtime"`                                                        // 写入小时
+	Type           int64          `gorm:"column:type;default:1;comment:1-微信 2-名片" json:"type"`                                               // 1-微信 2-名片
+	BotID          string         `gorm:"column:bot_id;comment:微信或名片id" json:"bot_id"`                                                       // 微信或名片id
+	OrganizationID int64          `gorm:"column:organization_id;not null;default:1;comment:机构 ID" json:"organization_id"`                    // 机构 ID
+	AiResponse     int64          `gorm:"column:ai_response;comment:AI回复次数" json:"ai_response"`                                              // AI回复次数
+	SopRun         int64          `gorm:"column:sop_run;comment:SOP运行次数" json:"sop_run"`                                                     // SOP运行次数
+	TotalFriend    int64          `gorm:"column:total_friend;comment:好友总数" json:"total_friend"`                                              // 好友总数
+	TotalGroup     int64          `gorm:"column:total_group;comment:群总数" json:"total_group"`                                                 // 群总数
+	AccountBalance int64          `gorm:"column:account_balance;comment:账户余额(单位:分)" json:"account_balance"`                                  // 账户余额(单位:分)
+	ConsumeToken   int64          `gorm:"column:consume_token;comment:消耗token数" json:"consume_token"`                                        // 消耗token数
+	ActiveUser     int64          `gorm:"column:active_user;comment:活跃用户数" json:"active_user"`                                               // 活跃用户数
+	NewUser        int64          `gorm:"column:new_user;comment:新增用户数" json:"new_user"`                                                     // 新增用户数
+	LabelDist      string         `gorm:"column:label_dist;comment:标签分布" json:"label_dist"`                                                  // 标签分布
+}
+
+// TableName UsageStatisticHour's table name
+func (*UsageStatisticHour) TableName() string {
+	return TableNameUsageStatisticHour
+}

+ 40 - 0
database/dao/wechat/model/usage_statistic_month.gen.go

@@ -0,0 +1,40 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameUsageStatisticMonth = "usage_statistic_month"
+
+// UsageStatisticMonth mapped from table <usage_statistic_month>
+type UsageStatisticMonth struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time      `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	Status         int64          `gorm:"column:status;not null;default:1;comment:状态 1 正常 2 禁用" json:"status"`                               // 状态 1 正常 2 禁用
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                    // Delete Time | 删除日期
+	Addtime        int64          `gorm:"column:addtime;comment:写入年月" json:"addtime"`                                                        // 写入年月
+	Type           int64          `gorm:"column:type;default:1;comment:1-微信 2-名片" json:"type"`                                               // 1-微信 2-名片
+	BotID          string         `gorm:"column:bot_id;comment:微信或名片id" json:"bot_id"`                                                       // 微信或名片id
+	OrganizationID int64          `gorm:"column:organization_id;not null;default:1;comment:机构 ID" json:"organization_id"`                    // 机构 ID
+	AiResponse     int64          `gorm:"column:ai_response;comment:AI回复次数" json:"ai_response"`                                              // AI回复次数
+	SopRun         int64          `gorm:"column:sop_run;comment:SOP运行次数" json:"sop_run"`                                                     // SOP运行次数
+	TotalFriend    int64          `gorm:"column:total_friend;comment:好友总数" json:"total_friend"`                                              // 好友总数
+	TotalGroup     int64          `gorm:"column:total_group;comment:群总数" json:"total_group"`                                                 // 群总数
+	AccountBalance int64          `gorm:"column:account_balance;comment:账户余额(单位:分)" json:"account_balance"`                                  // 账户余额(单位:分)
+	ConsumeToken   int64          `gorm:"column:consume_token;comment:消耗token数" json:"consume_token"`                                        // 消耗token数
+	ActiveUser     int64          `gorm:"column:active_user;comment:活跃用户数" json:"active_user"`                                               // 活跃用户数
+	NewUser        int64          `gorm:"column:new_user;comment:新增用户数" json:"new_user"`                                                     // 新增用户数
+	LabelDist      string         `gorm:"column:label_dist;comment:标签分布" json:"label_dist"`                                                  // 标签分布
+}
+
+// TableName UsageStatisticMonth's table name
+func (*UsageStatisticMonth) TableName() string {
+	return TableNameUsageStatisticMonth
+}

+ 33 - 0
database/dao/wechat/model/usage_total.gen.go

@@ -0,0 +1,33 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameUsageTotal = "usage_total"
+
+// UsageTotal mapped from table <usage_total>
+type UsageTotal struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time      `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	Status         int64          `gorm:"column:status;not null;default:1;comment:状态 1 正常 2 禁用" json:"status"`                               // 状态 1 正常 2 禁用
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                    // Delete Time | 删除日期
+	Type           int64          `gorm:"column:type;not null;default:1;comment:1 微信 2 名片" json:"type"`                                      // 1 微信 2 名片
+	BotID          string         `gorm:"column:bot_id;not null;comment:微信或名片id" json:"bot_id"`                                              // 微信或名片id
+	TotalTokens    int64          `gorm:"column:total_tokens;not null;comment:使用token总数" json:"total_tokens"`                                // 使用token总数
+	StartIndex     int64          `gorm:"column:start_index;not null;comment:重制后的起始usage_detail 索引" json:"start_index"`                      // 重制后的起始usage_detail 索引
+	EndIndex       int64          `gorm:"column:end_index;not null;comment:usage_detail 索引" json:"end_index"`                                // usage_detail 索引
+	OrganizationID int64          `gorm:"column:organization_id;not null;default:1;comment:机构 ID" json:"organization_id"`                    // 机构 ID
+}
+
+// TableName UsageTotal's table name
+func (*UsageTotal) TableName() string {
+	return TableNameUsageTotal
+}

+ 44 - 0
database/dao/wechat/model/whatsapp.gen.go

@@ -0,0 +1,44 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameWhatsapp = "whatsapp"
+
+// Whatsapp whatsapp手机号表
+type Whatsapp struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time      `gorm:"column:created_at;not null;comment:Create Time | 创建日期" json:"created_at"`              // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"`              // Update Time | 修改日期
+	Status         int64          `gorm:"column:status;default:1;comment:Status 1: normal 2: ban | 状态 1 正常 2 禁用" json:"status"` // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                       // Delete Time | 删除日期
+	WaID           string         `gorm:"column:wa_id;not null;comment:wa通道ID" json:"wa_id"`                                    // wa通道ID
+	WaName         string         `gorm:"column:wa_name;comment:通道名" json:"wa_name"`                                            // 通道名
+	Callback       string         `gorm:"column:callback;not null;comment:回调地址" json:"callback"`                                // 回调地址
+	AgentID        int64          `gorm:"column:agent_id;comment:AI角色ID" json:"agent_id"`                                       // AI角色ID
+	Account        string         `gorm:"column:account;comment:账户" json:"account"`                                             // 账户
+	Cc             string         `gorm:"column:cc;comment:国家区号" json:"cc"`                                                     // 国家区号
+	Phone          string         `gorm:"column:phone;comment:手机号" json:"phone"`                                                // 手机号
+	CcPhone        string         `gorm:"column:cc_phone;comment:国家区号 + 手机号" json:"cc_phone"`                                   // 国家区号 + 手机号
+	PhoneName      string         `gorm:"column:phone_name;comment:号码名称" json:"phone_name"`                                     // 号码名称
+	PhoneStatus    int64          `gorm:"column:phone_status;comment:号码状态" json:"phone_status"`                                 // 号码状态
+	APIBase        string         `gorm:"column:api_base" json:"api_base"`
+	APIKey         string         `gorm:"column:api_key" json:"api_key"`
+	AllowList      string         `gorm:"column:allow_list;comment:白名单,以数组存储wxid。当包含 ALL 字符串时为全部允许" json:"allow_list"`              // 白名单,以数组存储wxid。当包含 ALL 字符串时为全部允许
+	GroupAllowList string         `gorm:"column:group_allow_list;comment:群白名单,以数组存储wxid。当包含 ALL 字符串时为全部允许" json:"group_allow_list"` // 群白名单,以数组存储wxid。当包含 ALL 字符串时为全部允许
+	BlockList      string         `gorm:"column:block_list;comment:黑名单,以数组存储wxid。当包含 ALL 字符串时为全部拒绝" json:"block_list"`              // 黑名单,以数组存储wxid。当包含 ALL 字符串时为全部拒绝
+	GroupBlockList string         `gorm:"column:group_block_list;comment:群黑名单,以数组存储wxid。当包含 ALL 字符串时为全部拒绝" json:"group_block_list"` // 群黑名单,以数组存储wxid。当包含 ALL 字符串时为全部拒绝
+	OrganizationID int64          `gorm:"column:organization_id;comment:机构ID" json:"organization_id"`                               // 机构ID
+}
+
+// TableName Whatsapp's table name
+func (*Whatsapp) TableName() string {
+	return TableNameWhatsapp
+}

+ 35 - 0
database/dao/wechat/model/whatsapp_channel.gen.go

@@ -0,0 +1,35 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameWhatsappChannel = "whatsapp_channel"
+
+// WhatsappChannel Whatsapp通道表
+type WhatsappChannel struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time      `gorm:"column:created_at;not null;comment:Create Time | 创建日期" json:"created_at"`              // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"`              // Update Time | 修改日期
+	Status         int64          `gorm:"column:status;default:1;comment:Status 1: normal 2: ban | 状态 1 正常 2 禁用" json:"status"` // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                       // Delete Time | 删除日期
+	Ak             string         `gorm:"column:ak" json:"ak"`
+	Sk             string         `gorm:"column:sk" json:"sk"`
+	WaID           string         `gorm:"column:wa_id;not null;comment:通道ID" json:"wa_id"`                       // 通道ID
+	WaName         string         `gorm:"column:wa_name;not null;comment:通道名" json:"wa_name"`                    // 通道名
+	OrganizationID int64          `gorm:"column:organization_id;default:1;comment:机构 ID" json:"organization_id"` // 机构 ID
+	WabaID         int64          `gorm:"column:waba_id;not null;comment:WABA ID" json:"waba_id"`                // WABA ID
+	BusinessID     int64          `gorm:"column:business_id;not null;comment:商品平台ID" json:"business_id"`         // 商品平台ID
+	VerifyAccount  string         `gorm:"column:verify_account;not null;comment:认证主体" json:"verify_account"`     // 认证主体
+}
+
+// TableName WhatsappChannel's table name
+func (*WhatsappChannel) TableName() string {
+	return TableNameWhatsappChannel
+}

+ 32 - 0
database/dao/wechat/model/work_experience.gen.go

@@ -0,0 +1,32 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameWorkExperience = "work_experience"
+
+// WorkExperience 数字员工工作经验表
+type WorkExperience struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	EmployeeID     int64          `gorm:"column:employee_id;comment:员工ID" json:"employee_id"`             // 员工ID
+	CreatedAt      time.Time      `gorm:"column:created_at;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"` // Delete Time | 删除日期
+	StartDate      time.Time      `gorm:"column:start_date;comment:开始时间" json:"start_date"`               // 开始时间
+	EndDate        time.Time      `gorm:"column:end_date;comment:结束时间" json:"end_date"`                   // 结束时间
+	Company        string         `gorm:"column:company;comment:公司名" json:"company"`                      // 公司名
+	Experience     string         `gorm:"column:experience;comment:工作内容" json:"experience"`               // 工作内容
+	OrganizationID int64          `gorm:"column:organization_id;comment:机构ID" json:"organization_id"`     // 机构ID
+}
+
+// TableName WorkExperience's table name
+func (*WorkExperience) TableName() string {
+	return TableNameWorkExperience
+}

+ 34 - 0
database/dao/wechat/model/wp_chatroom.gen.go

@@ -0,0 +1,34 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameWpChatroom = "wp_chatroom"
+
+// WpChatroom mapped from table <wp_chatroom>
+type WpChatroom struct {
+	ID           int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt    time.Time      `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt    time.Time      `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	Status       int64          `gorm:"column:status;default:1;comment:Status 1: normal 2: ban | 状态 1 正常 2 禁用" json:"status"`              // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt    gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                    // Delete Time | 删除日期
+	WxWxid       string         `gorm:"column:wx_wxid;comment:属主微信id" json:"wx_wxid"`                                                      // 属主微信id
+	ChatroomID   string         `gorm:"column:chatroom_id;not null;comment:微信id 公众号微信ID" json:"chatroom_id"`                               // 微信id 公众号微信ID
+	Nickname     string         `gorm:"column:nickname;not null;comment:微信昵称 群备注名称" json:"nickname"`                                       // 微信昵称 群备注名称
+	Owner        string         `gorm:"column:owner;comment:群主微信id" json:"owner"`                                                          // 群主微信id
+	Avatar       string         `gorm:"column:avatar;not null;comment:头像" json:"avatar"`                                                   // 头像
+	MemberList   string         `gorm:"column:member_list" json:"member_list"`
+	ShowNameList string         `gorm:"column:show_name_list" json:"show_name_list"`
+}
+
+// TableName WpChatroom's table name
+func (*WpChatroom) TableName() string {
+	return TableNameWpChatroom
+}

+ 31 - 0
database/dao/wechat/model/wp_chatroom_member.gen.go

@@ -0,0 +1,31 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameWpChatroomMember = "wp_chatroom_member"
+
+// WpChatroomMember mapped from table <wp_chatroom_member>
+type WpChatroomMember struct {
+	ID        int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt time.Time      `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt time.Time      `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	Status    int64          `gorm:"column:status;default:1;comment:Status 1: normal 2: ban | 状态 1 正常 2 禁用" json:"status"`              // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                    // Delete Time | 删除日期
+	WxWxid    string         `gorm:"column:wx_wxid;comment:属主微信id" json:"wx_wxid"`                                                      // 属主微信id
+	Wxid      string         `gorm:"column:wxid;comment:微信id" json:"wxid"`                                                              // 微信id
+	Nickname  string         `gorm:"column:nickname;not null;comment:微信昵称 群备注名称" json:"nickname"`                                       // 微信昵称 群备注名称
+	Avatar    string         `gorm:"column:avatar;not null;comment:头像" json:"avatar"`                                                   // 头像
+}
+
+// TableName WpChatroomMember's table name
+func (*WpChatroomMember) TableName() string {
+	return TableNameWpChatroomMember
+}

+ 45 - 0
database/dao/wechat/model/wx.gen.go

@@ -0,0 +1,45 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameWx = "wx"
+
+// Wx mapped from table <wx>
+type Wx struct {
+	ID             int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt      time.Time      `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt      time.Time      `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	Status         int64          `gorm:"column:status;default:1;comment:Status 1: normal 2: ban | 状态 1 正常 2 禁用" json:"status"`              // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt      gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                                    // Delete Time | 删除日期
+	Port           string         `gorm:"column:port;not null;comment:端口号" json:"port"`                                                      // 端口号
+	ProcessID      string         `gorm:"column:process_id;not null;comment:进程号" json:"process_id"`                                          // 进程号
+	Callback       string         `gorm:"column:callback;not null;comment:回调地址" json:"callback"`                                             // 回调地址
+	Wxid           string         `gorm:"column:wxid;not null;comment:微信id" json:"wxid"`                                                     // 微信id
+	Account        string         `gorm:"column:account;not null;comment:微信账号" json:"account"`                                               // 微信账号
+	Nickname       string         `gorm:"column:nickname;not null;comment:微信昵称" json:"nickname"`                                             // 微信昵称
+	Tel            string         `gorm:"column:tel;not null;comment:手机号" json:"tel"`                                                        // 手机号
+	HeadBig        string         `gorm:"column:head_big;not null;comment:微信头像" json:"head_big"`                                             // 微信头像
+	ServerID       int64          `gorm:"column:server_id;comment:服务器id" json:"server_id"`                                                   // 服务器id
+	OrganizationID int64          `gorm:"column:organization_id;default:1;comment:机构 ID" json:"organization_id"`                             // 机构 ID
+	AgentID        int64          `gorm:"column:agent_id;not null;comment:0 fastgpt" json:"agent_id"`                                        // 0 fastgpt
+	APIBase        string         `gorm:"column:api_base" json:"api_base"`
+	APIKey         string         `gorm:"column:api_key" json:"api_key"`
+	AllowList      string         `gorm:"column:allow_list;comment:白名单,以数组存储wxid。当包含 ALL 字符串时为全部允许" json:"allow_list"`              // 白名单,以数组存储wxid。当包含 ALL 字符串时为全部允许
+	GroupAllowList string         `gorm:"column:group_allow_list;comment:群白名单,以数组存储wxid。当包含 ALL 字符串时为全部允许" json:"group_allow_list"` // 群白名单,以数组存储wxid。当包含 ALL 字符串时为全部允许
+	BlockList      string         `gorm:"column:block_list;comment:黑名单,以数组存储wxid。当包含 ALL 字符串时为全部拒绝" json:"block_list"`              // 黑名单,以数组存储wxid。当包含 ALL 字符串时为全部拒绝
+	GroupBlockList string         `gorm:"column:group_block_list;comment:群黑名单,以数组存储wxid。当包含 ALL 字符串时为全部拒绝" json:"group_block_list"` // 群黑名单,以数组存储wxid。当包含 ALL 字符串时为全部拒绝
+	Ctype          int64          `gorm:"column:ctype;default:1;comment:内容类型:1-个微 3-企微" json:"ctype"`                               // 内容类型:1-个微 3-企微
+}
+
+// TableName Wx's table name
+func (*Wx) TableName() string {
+	return TableNameWx
+}

+ 41 - 0
database/dao/wechat/model/wx_card.gen.go

@@ -0,0 +1,41 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameWxCard = "wx_card"
+
+// WxCard 名片表
+type WxCard struct {
+	ID              int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt       time.Time      `gorm:"column:created_at;not null;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt       time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	DeletedAt       gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`          // Delete Time | 删除日期
+	UserID          int64          `gorm:"column:user_id;not null;comment:use表ID" json:"user_id"`                   // use表ID
+	WxUserID        int64          `gorm:"column:wx_user_id;not null;comment:wx表ID" json:"wx_user_id"`              // wx表ID
+	Avatar          string         `gorm:"column:avatar;comment:头像" json:"avatar"`                                  // 头像
+	Logo            string         `gorm:"column:logo;comment:Logo" json:"logo"`                                    // Logo
+	Name            string         `gorm:"column:name;comment:名称" json:"name"`                                      // 名称
+	Company         string         `gorm:"column:company;comment:公司" json:"company"`                                // 公司
+	Address         string         `gorm:"column:address;comment:地址" json:"address"`                                // 地址
+	Phone           string         `gorm:"column:phone;comment:手机号" json:"phone"`                                   // 手机号
+	OfficialAccount string         `gorm:"column:official_account;comment:公众号" json:"official_account"`             // 公众号
+	WechatAccount   string         `gorm:"column:wechat_account;comment:微信号" json:"wechat_account"`                 // 微信号
+	Email           string         `gorm:"column:email;comment:邮箱" json:"email"`                                    // 邮箱
+	APIBase         string         `gorm:"column:api_base;comment:fastgpt-base" json:"api_base"`                    // fastgpt-base
+	APIKey          string         `gorm:"column:api_key;comment:fastgpt-key" json:"api_key"`                       // fastgpt-key
+	AiInfo          string         `gorm:"column:ai_info;comment:AI信息" json:"ai_info"`                              // AI信息
+	Intro           string         `gorm:"column:intro;comment:简介" json:"intro"`                                    // 简介
+}
+
+// TableName WxCard's table name
+func (*WxCard) TableName() string {
+	return TableNameWxCard
+}

+ 36 - 0
database/dao/wechat/model/wx_card_user.gen.go

@@ -0,0 +1,36 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameWxCardUser = "wx_card_user"
+
+// WxCardUser 微信用户表
+type WxCardUser struct {
+	ID         int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt  time.Time      `gorm:"column:created_at;not null;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt  time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	DeletedAt  gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`          // Delete Time | 删除日期
+	Wxid       string         `gorm:"column:wxid;not null;comment:微信id" json:"wxid"`                           // 微信id
+	Account    string         `gorm:"column:account;comment:微信账号" json:"account"`                              // 微信账号
+	Nickname   string         `gorm:"column:nickname;comment:微信昵称" json:"nickname"`                            // 微信昵称
+	Remark     string         `gorm:"column:remark;comment:备注名" json:"remark"`                                 // 备注名
+	Avatar     string         `gorm:"column:avatar;comment:头像" json:"avatar"`                                  // 头像
+	Phone      string         `gorm:"column:phone;comment:手机号" json:"phone"`                                   // 手机号
+	OpenID     string         `gorm:"column:open_id;comment:OpenId" json:"open_id"`                            // OpenId
+	UnionID    string         `gorm:"column:union_id;comment:UnionId" json:"union_id"`                         // UnionId
+	SessionKey string         `gorm:"column:session_key;comment:SessionKey" json:"session_key"`                // SessionKey
+	IsVip      int64          `gorm:"column:is_vip;comment:是否VIP:0-否 1-是" json:"is_vip"`                       // 是否VIP:0-否 1-是
+}
+
+// TableName WxCardUser's table name
+func (*WxCardUser) TableName() string {
+	return TableNameWxCardUser
+}

+ 29 - 0
database/dao/wechat/model/wx_card_visit.gen.go

@@ -0,0 +1,29 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameWxCardVisit = "wx_card_visit"
+
+// WxCardVisit 名片访问记录表
+type WxCardVisit struct {
+	ID        int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt time.Time      `gorm:"column:created_at;not null;comment:Create Time | 创建日期" json:"created_at"` // Create Time | 创建日期
+	UpdatedAt time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"` // Update Time | 修改日期
+	DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`          // Delete Time | 删除日期
+	UserID    int64          `gorm:"column:user_id;comment:访客 ID" json:"user_id"`                             // 访客 ID
+	BotID     int64          `gorm:"column:bot_id;comment:被访ID" json:"bot_id"`                                // 被访ID
+	BotType   int64          `gorm:"column:bot_type;comment:类型:1-微信 2-小程序 3-智能体" json:"bot_type"`             // 类型:1-微信 2-小程序 3-智能体
+}
+
+// TableName WxCardVisit's table name
+func (*WxCardVisit) TableName() string {
+	return TableNameWxCardVisit
+}

+ 31 - 0
database/dao/wechat/model/xunji_contact.gen.go

@@ -0,0 +1,31 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+const TableNameXunjiContact = "xunji_contact"
+
+// XunjiContact mapped from table <xunji_contact>
+type XunjiContact struct {
+	ID        int64          `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CreatedAt time.Time      `gorm:"column:created_at;not null;comment:Create Time | 创建日期" json:"created_at"`              // Create Time | 创建日期
+	UpdatedAt time.Time      `gorm:"column:updated_at;not null;comment:Update Time | 修改日期" json:"updated_at"`              // Update Time | 修改日期
+	Status    int64          `gorm:"column:status;default:1;comment:Status 1: normal 2: ban | 状态 1 正常 2 禁用" json:"status"` // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:Delete Time | 删除日期" json:"deleted_at"`                       // Delete Time | 删除日期
+	RobotID   string         `gorm:"column:robot_id;comment:机器人ID" json:"robot_id"`                                        // 机器人ID
+	AccountID string         `gorm:"column:account_id;comment:客户ID" json:"account_id"`                                     // 客户ID
+	Nickname  string         `gorm:"column:nickname;comment:昵称" json:"nickname"`                                           // 昵称
+	Avatar    string         `gorm:"column:avatar;comment:头像" json:"avatar"`                                               // 头像
+}
+
+// TableName XunjiContact's table name
+func (*XunjiContact) TableName() string {
+	return TableNameXunjiContact
+}

+ 424 - 0
database/dao/wechat/query/agent.gen.go

@@ -0,0 +1,424 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newAgent(db *gorm.DB, opts ...gen.DOOption) agent {
+	_agent := agent{}
+
+	_agent.agentDo.UseDB(db, opts...)
+	_agent.agentDo.UseModel(&model.Agent{})
+
+	tableName := _agent.agentDo.TableName()
+	_agent.ALL = field.NewAsterisk(tableName)
+	_agent.ID = field.NewInt64(tableName, "id")
+	_agent.CreatedAt = field.NewTime(tableName, "created_at")
+	_agent.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_agent.Status = field.NewInt64(tableName, "status")
+	_agent.DeletedAt = field.NewField(tableName, "deleted_at")
+	_agent.Name = field.NewString(tableName, "name")
+	_agent.Role = field.NewString(tableName, "role")
+	_agent.Background = field.NewString(tableName, "background")
+	_agent.Examples = field.NewString(tableName, "examples")
+	_agent.OrganizationID = field.NewInt64(tableName, "organization_id")
+	_agent.DatasetID = field.NewString(tableName, "dataset_id")
+	_agent.CollectionID = field.NewString(tableName, "collection_id")
+
+	_agent.fillFieldMap()
+
+	return _agent
+}
+
+type agent struct {
+	agentDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	Status         field.Int64  // 状态 1 正常 2 禁用
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	Name           field.String // agent 名称
+	Role           field.String // 角色设定
+	Background     field.String // 背景介绍
+	Examples       field.String // 对话案例
+	OrganizationID field.Int64  // 机构 ID
+	DatasetID      field.String // 知识库ID
+	CollectionID   field.String // 集合ID
+
+	fieldMap map[string]field.Expr
+}
+
+func (a agent) Table(newTableName string) *agent {
+	a.agentDo.UseTable(newTableName)
+	return a.updateTableName(newTableName)
+}
+
+func (a agent) As(alias string) *agent {
+	a.agentDo.DO = *(a.agentDo.As(alias).(*gen.DO))
+	return a.updateTableName(alias)
+}
+
+func (a *agent) updateTableName(table string) *agent {
+	a.ALL = field.NewAsterisk(table)
+	a.ID = field.NewInt64(table, "id")
+	a.CreatedAt = field.NewTime(table, "created_at")
+	a.UpdatedAt = field.NewTime(table, "updated_at")
+	a.Status = field.NewInt64(table, "status")
+	a.DeletedAt = field.NewField(table, "deleted_at")
+	a.Name = field.NewString(table, "name")
+	a.Role = field.NewString(table, "role")
+	a.Background = field.NewString(table, "background")
+	a.Examples = field.NewString(table, "examples")
+	a.OrganizationID = field.NewInt64(table, "organization_id")
+	a.DatasetID = field.NewString(table, "dataset_id")
+	a.CollectionID = field.NewString(table, "collection_id")
+
+	a.fillFieldMap()
+
+	return a
+}
+
+func (a *agent) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := a.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (a *agent) fillFieldMap() {
+	a.fieldMap = make(map[string]field.Expr, 12)
+	a.fieldMap["id"] = a.ID
+	a.fieldMap["created_at"] = a.CreatedAt
+	a.fieldMap["updated_at"] = a.UpdatedAt
+	a.fieldMap["status"] = a.Status
+	a.fieldMap["deleted_at"] = a.DeletedAt
+	a.fieldMap["name"] = a.Name
+	a.fieldMap["role"] = a.Role
+	a.fieldMap["background"] = a.Background
+	a.fieldMap["examples"] = a.Examples
+	a.fieldMap["organization_id"] = a.OrganizationID
+	a.fieldMap["dataset_id"] = a.DatasetID
+	a.fieldMap["collection_id"] = a.CollectionID
+}
+
+func (a agent) clone(db *gorm.DB) agent {
+	a.agentDo.ReplaceConnPool(db.Statement.ConnPool)
+	return a
+}
+
+func (a agent) replaceDB(db *gorm.DB) agent {
+	a.agentDo.ReplaceDB(db)
+	return a
+}
+
+type agentDo struct{ gen.DO }
+
+type IAgentDo interface {
+	gen.SubQuery
+	Debug() IAgentDo
+	WithContext(ctx context.Context) IAgentDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IAgentDo
+	WriteDB() IAgentDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IAgentDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IAgentDo
+	Not(conds ...gen.Condition) IAgentDo
+	Or(conds ...gen.Condition) IAgentDo
+	Select(conds ...field.Expr) IAgentDo
+	Where(conds ...gen.Condition) IAgentDo
+	Order(conds ...field.Expr) IAgentDo
+	Distinct(cols ...field.Expr) IAgentDo
+	Omit(cols ...field.Expr) IAgentDo
+	Join(table schema.Tabler, on ...field.Expr) IAgentDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IAgentDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IAgentDo
+	Group(cols ...field.Expr) IAgentDo
+	Having(conds ...gen.Condition) IAgentDo
+	Limit(limit int) IAgentDo
+	Offset(offset int) IAgentDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IAgentDo
+	Unscoped() IAgentDo
+	Create(values ...*model.Agent) error
+	CreateInBatches(values []*model.Agent, batchSize int) error
+	Save(values ...*model.Agent) error
+	First() (*model.Agent, error)
+	Take() (*model.Agent, error)
+	Last() (*model.Agent, error)
+	Find() ([]*model.Agent, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Agent, err error)
+	FindInBatches(result *[]*model.Agent, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.Agent) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IAgentDo
+	Assign(attrs ...field.AssignExpr) IAgentDo
+	Joins(fields ...field.RelationField) IAgentDo
+	Preload(fields ...field.RelationField) IAgentDo
+	FirstOrInit() (*model.Agent, error)
+	FirstOrCreate() (*model.Agent, error)
+	FindByPage(offset int, limit int) (result []*model.Agent, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IAgentDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (a agentDo) Debug() IAgentDo {
+	return a.withDO(a.DO.Debug())
+}
+
+func (a agentDo) WithContext(ctx context.Context) IAgentDo {
+	return a.withDO(a.DO.WithContext(ctx))
+}
+
+func (a agentDo) ReadDB() IAgentDo {
+	return a.Clauses(dbresolver.Read)
+}
+
+func (a agentDo) WriteDB() IAgentDo {
+	return a.Clauses(dbresolver.Write)
+}
+
+func (a agentDo) Session(config *gorm.Session) IAgentDo {
+	return a.withDO(a.DO.Session(config))
+}
+
+func (a agentDo) Clauses(conds ...clause.Expression) IAgentDo {
+	return a.withDO(a.DO.Clauses(conds...))
+}
+
+func (a agentDo) Returning(value interface{}, columns ...string) IAgentDo {
+	return a.withDO(a.DO.Returning(value, columns...))
+}
+
+func (a agentDo) Not(conds ...gen.Condition) IAgentDo {
+	return a.withDO(a.DO.Not(conds...))
+}
+
+func (a agentDo) Or(conds ...gen.Condition) IAgentDo {
+	return a.withDO(a.DO.Or(conds...))
+}
+
+func (a agentDo) Select(conds ...field.Expr) IAgentDo {
+	return a.withDO(a.DO.Select(conds...))
+}
+
+func (a agentDo) Where(conds ...gen.Condition) IAgentDo {
+	return a.withDO(a.DO.Where(conds...))
+}
+
+func (a agentDo) Order(conds ...field.Expr) IAgentDo {
+	return a.withDO(a.DO.Order(conds...))
+}
+
+func (a agentDo) Distinct(cols ...field.Expr) IAgentDo {
+	return a.withDO(a.DO.Distinct(cols...))
+}
+
+func (a agentDo) Omit(cols ...field.Expr) IAgentDo {
+	return a.withDO(a.DO.Omit(cols...))
+}
+
+func (a agentDo) Join(table schema.Tabler, on ...field.Expr) IAgentDo {
+	return a.withDO(a.DO.Join(table, on...))
+}
+
+func (a agentDo) LeftJoin(table schema.Tabler, on ...field.Expr) IAgentDo {
+	return a.withDO(a.DO.LeftJoin(table, on...))
+}
+
+func (a agentDo) RightJoin(table schema.Tabler, on ...field.Expr) IAgentDo {
+	return a.withDO(a.DO.RightJoin(table, on...))
+}
+
+func (a agentDo) Group(cols ...field.Expr) IAgentDo {
+	return a.withDO(a.DO.Group(cols...))
+}
+
+func (a agentDo) Having(conds ...gen.Condition) IAgentDo {
+	return a.withDO(a.DO.Having(conds...))
+}
+
+func (a agentDo) Limit(limit int) IAgentDo {
+	return a.withDO(a.DO.Limit(limit))
+}
+
+func (a agentDo) Offset(offset int) IAgentDo {
+	return a.withDO(a.DO.Offset(offset))
+}
+
+func (a agentDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IAgentDo {
+	return a.withDO(a.DO.Scopes(funcs...))
+}
+
+func (a agentDo) Unscoped() IAgentDo {
+	return a.withDO(a.DO.Unscoped())
+}
+
+func (a agentDo) Create(values ...*model.Agent) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return a.DO.Create(values)
+}
+
+func (a agentDo) CreateInBatches(values []*model.Agent, batchSize int) error {
+	return a.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (a agentDo) Save(values ...*model.Agent) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return a.DO.Save(values)
+}
+
+func (a agentDo) First() (*model.Agent, error) {
+	if result, err := a.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Agent), nil
+	}
+}
+
+func (a agentDo) Take() (*model.Agent, error) {
+	if result, err := a.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Agent), nil
+	}
+}
+
+func (a agentDo) Last() (*model.Agent, error) {
+	if result, err := a.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Agent), nil
+	}
+}
+
+func (a agentDo) Find() ([]*model.Agent, error) {
+	result, err := a.DO.Find()
+	return result.([]*model.Agent), err
+}
+
+func (a agentDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Agent, err error) {
+	buf := make([]*model.Agent, 0, batchSize)
+	err = a.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (a agentDo) FindInBatches(result *[]*model.Agent, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return a.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (a agentDo) Attrs(attrs ...field.AssignExpr) IAgentDo {
+	return a.withDO(a.DO.Attrs(attrs...))
+}
+
+func (a agentDo) Assign(attrs ...field.AssignExpr) IAgentDo {
+	return a.withDO(a.DO.Assign(attrs...))
+}
+
+func (a agentDo) Joins(fields ...field.RelationField) IAgentDo {
+	for _, _f := range fields {
+		a = *a.withDO(a.DO.Joins(_f))
+	}
+	return &a
+}
+
+func (a agentDo) Preload(fields ...field.RelationField) IAgentDo {
+	for _, _f := range fields {
+		a = *a.withDO(a.DO.Preload(_f))
+	}
+	return &a
+}
+
+func (a agentDo) FirstOrInit() (*model.Agent, error) {
+	if result, err := a.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Agent), nil
+	}
+}
+
+func (a agentDo) FirstOrCreate() (*model.Agent, error) {
+	if result, err := a.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Agent), nil
+	}
+}
+
+func (a agentDo) FindByPage(offset int, limit int) (result []*model.Agent, count int64, err error) {
+	result, err = a.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = a.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (a agentDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = a.Count()
+	if err != nil {
+		return
+	}
+
+	err = a.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (a agentDo) Scan(result interface{}) (err error) {
+	return a.DO.Scan(result)
+}
+
+func (a agentDo) Delete(models ...*model.Agent) (result gen.ResultInfo, err error) {
+	return a.DO.Delete(models)
+}
+
+func (a *agentDo) withDO(do gen.Dao) *agentDo {
+	a.DO = *do.(*gen.DO)
+	return a
+}

+ 429 - 0
database/dao/wechat/query/aliyun_avatar.gen.go

@@ -0,0 +1,429 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newAliyunAvatar(db *gorm.DB, opts ...gen.DOOption) aliyunAvatar {
+	_aliyunAvatar := aliyunAvatar{}
+
+	_aliyunAvatar.aliyunAvatarDo.UseDB(db, opts...)
+	_aliyunAvatar.aliyunAvatarDo.UseModel(&model.AliyunAvatar{})
+
+	tableName := _aliyunAvatar.aliyunAvatarDo.TableName()
+	_aliyunAvatar.ALL = field.NewAsterisk(tableName)
+	_aliyunAvatar.ID = field.NewInt64(tableName, "id")
+	_aliyunAvatar.CreatedAt = field.NewTime(tableName, "created_at")
+	_aliyunAvatar.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_aliyunAvatar.DeletedAt = field.NewField(tableName, "deleted_at")
+	_aliyunAvatar.UserID = field.NewInt64(tableName, "user_id")
+	_aliyunAvatar.BizID = field.NewString(tableName, "biz_id")
+	_aliyunAvatar.AccessKeyID = field.NewString(tableName, "access_key_id")
+	_aliyunAvatar.AccessKeySecret = field.NewString(tableName, "access_key_secret")
+	_aliyunAvatar.AppID = field.NewString(tableName, "app_id")
+	_aliyunAvatar.TenantID = field.NewString(tableName, "tenant_id")
+	_aliyunAvatar.Response = field.NewString(tableName, "response")
+	_aliyunAvatar.Token = field.NewString(tableName, "token")
+	_aliyunAvatar.SessionID = field.NewString(tableName, "session_id")
+
+	_aliyunAvatar.fillFieldMap()
+
+	return _aliyunAvatar
+}
+
+// aliyunAvatar 阿里云数字人记录表
+type aliyunAvatar struct {
+	aliyunAvatarDo
+
+	ALL             field.Asterisk
+	ID              field.Int64
+	CreatedAt       field.Time   // Create Time | 创建日期
+	UpdatedAt       field.Time   // Update Time | 修改日期
+	DeletedAt       field.Field  // Delete Time | 删除日期
+	UserID          field.Int64  // userID
+	BizID           field.String // bizId
+	AccessKeyID     field.String
+	AccessKeySecret field.String
+	AppID           field.String
+	TenantID        field.String
+	Response        field.String
+	Token           field.String
+	SessionID       field.String
+
+	fieldMap map[string]field.Expr
+}
+
+func (a aliyunAvatar) Table(newTableName string) *aliyunAvatar {
+	a.aliyunAvatarDo.UseTable(newTableName)
+	return a.updateTableName(newTableName)
+}
+
+func (a aliyunAvatar) As(alias string) *aliyunAvatar {
+	a.aliyunAvatarDo.DO = *(a.aliyunAvatarDo.As(alias).(*gen.DO))
+	return a.updateTableName(alias)
+}
+
+func (a *aliyunAvatar) updateTableName(table string) *aliyunAvatar {
+	a.ALL = field.NewAsterisk(table)
+	a.ID = field.NewInt64(table, "id")
+	a.CreatedAt = field.NewTime(table, "created_at")
+	a.UpdatedAt = field.NewTime(table, "updated_at")
+	a.DeletedAt = field.NewField(table, "deleted_at")
+	a.UserID = field.NewInt64(table, "user_id")
+	a.BizID = field.NewString(table, "biz_id")
+	a.AccessKeyID = field.NewString(table, "access_key_id")
+	a.AccessKeySecret = field.NewString(table, "access_key_secret")
+	a.AppID = field.NewString(table, "app_id")
+	a.TenantID = field.NewString(table, "tenant_id")
+	a.Response = field.NewString(table, "response")
+	a.Token = field.NewString(table, "token")
+	a.SessionID = field.NewString(table, "session_id")
+
+	a.fillFieldMap()
+
+	return a
+}
+
+func (a *aliyunAvatar) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := a.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (a *aliyunAvatar) fillFieldMap() {
+	a.fieldMap = make(map[string]field.Expr, 13)
+	a.fieldMap["id"] = a.ID
+	a.fieldMap["created_at"] = a.CreatedAt
+	a.fieldMap["updated_at"] = a.UpdatedAt
+	a.fieldMap["deleted_at"] = a.DeletedAt
+	a.fieldMap["user_id"] = a.UserID
+	a.fieldMap["biz_id"] = a.BizID
+	a.fieldMap["access_key_id"] = a.AccessKeyID
+	a.fieldMap["access_key_secret"] = a.AccessKeySecret
+	a.fieldMap["app_id"] = a.AppID
+	a.fieldMap["tenant_id"] = a.TenantID
+	a.fieldMap["response"] = a.Response
+	a.fieldMap["token"] = a.Token
+	a.fieldMap["session_id"] = a.SessionID
+}
+
+func (a aliyunAvatar) clone(db *gorm.DB) aliyunAvatar {
+	a.aliyunAvatarDo.ReplaceConnPool(db.Statement.ConnPool)
+	return a
+}
+
+func (a aliyunAvatar) replaceDB(db *gorm.DB) aliyunAvatar {
+	a.aliyunAvatarDo.ReplaceDB(db)
+	return a
+}
+
+type aliyunAvatarDo struct{ gen.DO }
+
+type IAliyunAvatarDo interface {
+	gen.SubQuery
+	Debug() IAliyunAvatarDo
+	WithContext(ctx context.Context) IAliyunAvatarDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IAliyunAvatarDo
+	WriteDB() IAliyunAvatarDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IAliyunAvatarDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IAliyunAvatarDo
+	Not(conds ...gen.Condition) IAliyunAvatarDo
+	Or(conds ...gen.Condition) IAliyunAvatarDo
+	Select(conds ...field.Expr) IAliyunAvatarDo
+	Where(conds ...gen.Condition) IAliyunAvatarDo
+	Order(conds ...field.Expr) IAliyunAvatarDo
+	Distinct(cols ...field.Expr) IAliyunAvatarDo
+	Omit(cols ...field.Expr) IAliyunAvatarDo
+	Join(table schema.Tabler, on ...field.Expr) IAliyunAvatarDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IAliyunAvatarDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IAliyunAvatarDo
+	Group(cols ...field.Expr) IAliyunAvatarDo
+	Having(conds ...gen.Condition) IAliyunAvatarDo
+	Limit(limit int) IAliyunAvatarDo
+	Offset(offset int) IAliyunAvatarDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IAliyunAvatarDo
+	Unscoped() IAliyunAvatarDo
+	Create(values ...*model.AliyunAvatar) error
+	CreateInBatches(values []*model.AliyunAvatar, batchSize int) error
+	Save(values ...*model.AliyunAvatar) error
+	First() (*model.AliyunAvatar, error)
+	Take() (*model.AliyunAvatar, error)
+	Last() (*model.AliyunAvatar, error)
+	Find() ([]*model.AliyunAvatar, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.AliyunAvatar, err error)
+	FindInBatches(result *[]*model.AliyunAvatar, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.AliyunAvatar) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IAliyunAvatarDo
+	Assign(attrs ...field.AssignExpr) IAliyunAvatarDo
+	Joins(fields ...field.RelationField) IAliyunAvatarDo
+	Preload(fields ...field.RelationField) IAliyunAvatarDo
+	FirstOrInit() (*model.AliyunAvatar, error)
+	FirstOrCreate() (*model.AliyunAvatar, error)
+	FindByPage(offset int, limit int) (result []*model.AliyunAvatar, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IAliyunAvatarDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (a aliyunAvatarDo) Debug() IAliyunAvatarDo {
+	return a.withDO(a.DO.Debug())
+}
+
+func (a aliyunAvatarDo) WithContext(ctx context.Context) IAliyunAvatarDo {
+	return a.withDO(a.DO.WithContext(ctx))
+}
+
+func (a aliyunAvatarDo) ReadDB() IAliyunAvatarDo {
+	return a.Clauses(dbresolver.Read)
+}
+
+func (a aliyunAvatarDo) WriteDB() IAliyunAvatarDo {
+	return a.Clauses(dbresolver.Write)
+}
+
+func (a aliyunAvatarDo) Session(config *gorm.Session) IAliyunAvatarDo {
+	return a.withDO(a.DO.Session(config))
+}
+
+func (a aliyunAvatarDo) Clauses(conds ...clause.Expression) IAliyunAvatarDo {
+	return a.withDO(a.DO.Clauses(conds...))
+}
+
+func (a aliyunAvatarDo) Returning(value interface{}, columns ...string) IAliyunAvatarDo {
+	return a.withDO(a.DO.Returning(value, columns...))
+}
+
+func (a aliyunAvatarDo) Not(conds ...gen.Condition) IAliyunAvatarDo {
+	return a.withDO(a.DO.Not(conds...))
+}
+
+func (a aliyunAvatarDo) Or(conds ...gen.Condition) IAliyunAvatarDo {
+	return a.withDO(a.DO.Or(conds...))
+}
+
+func (a aliyunAvatarDo) Select(conds ...field.Expr) IAliyunAvatarDo {
+	return a.withDO(a.DO.Select(conds...))
+}
+
+func (a aliyunAvatarDo) Where(conds ...gen.Condition) IAliyunAvatarDo {
+	return a.withDO(a.DO.Where(conds...))
+}
+
+func (a aliyunAvatarDo) Order(conds ...field.Expr) IAliyunAvatarDo {
+	return a.withDO(a.DO.Order(conds...))
+}
+
+func (a aliyunAvatarDo) Distinct(cols ...field.Expr) IAliyunAvatarDo {
+	return a.withDO(a.DO.Distinct(cols...))
+}
+
+func (a aliyunAvatarDo) Omit(cols ...field.Expr) IAliyunAvatarDo {
+	return a.withDO(a.DO.Omit(cols...))
+}
+
+func (a aliyunAvatarDo) Join(table schema.Tabler, on ...field.Expr) IAliyunAvatarDo {
+	return a.withDO(a.DO.Join(table, on...))
+}
+
+func (a aliyunAvatarDo) LeftJoin(table schema.Tabler, on ...field.Expr) IAliyunAvatarDo {
+	return a.withDO(a.DO.LeftJoin(table, on...))
+}
+
+func (a aliyunAvatarDo) RightJoin(table schema.Tabler, on ...field.Expr) IAliyunAvatarDo {
+	return a.withDO(a.DO.RightJoin(table, on...))
+}
+
+func (a aliyunAvatarDo) Group(cols ...field.Expr) IAliyunAvatarDo {
+	return a.withDO(a.DO.Group(cols...))
+}
+
+func (a aliyunAvatarDo) Having(conds ...gen.Condition) IAliyunAvatarDo {
+	return a.withDO(a.DO.Having(conds...))
+}
+
+func (a aliyunAvatarDo) Limit(limit int) IAliyunAvatarDo {
+	return a.withDO(a.DO.Limit(limit))
+}
+
+func (a aliyunAvatarDo) Offset(offset int) IAliyunAvatarDo {
+	return a.withDO(a.DO.Offset(offset))
+}
+
+func (a aliyunAvatarDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IAliyunAvatarDo {
+	return a.withDO(a.DO.Scopes(funcs...))
+}
+
+func (a aliyunAvatarDo) Unscoped() IAliyunAvatarDo {
+	return a.withDO(a.DO.Unscoped())
+}
+
+func (a aliyunAvatarDo) Create(values ...*model.AliyunAvatar) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return a.DO.Create(values)
+}
+
+func (a aliyunAvatarDo) CreateInBatches(values []*model.AliyunAvatar, batchSize int) error {
+	return a.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (a aliyunAvatarDo) Save(values ...*model.AliyunAvatar) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return a.DO.Save(values)
+}
+
+func (a aliyunAvatarDo) First() (*model.AliyunAvatar, error) {
+	if result, err := a.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.AliyunAvatar), nil
+	}
+}
+
+func (a aliyunAvatarDo) Take() (*model.AliyunAvatar, error) {
+	if result, err := a.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.AliyunAvatar), nil
+	}
+}
+
+func (a aliyunAvatarDo) Last() (*model.AliyunAvatar, error) {
+	if result, err := a.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.AliyunAvatar), nil
+	}
+}
+
+func (a aliyunAvatarDo) Find() ([]*model.AliyunAvatar, error) {
+	result, err := a.DO.Find()
+	return result.([]*model.AliyunAvatar), err
+}
+
+func (a aliyunAvatarDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.AliyunAvatar, err error) {
+	buf := make([]*model.AliyunAvatar, 0, batchSize)
+	err = a.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (a aliyunAvatarDo) FindInBatches(result *[]*model.AliyunAvatar, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return a.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (a aliyunAvatarDo) Attrs(attrs ...field.AssignExpr) IAliyunAvatarDo {
+	return a.withDO(a.DO.Attrs(attrs...))
+}
+
+func (a aliyunAvatarDo) Assign(attrs ...field.AssignExpr) IAliyunAvatarDo {
+	return a.withDO(a.DO.Assign(attrs...))
+}
+
+func (a aliyunAvatarDo) Joins(fields ...field.RelationField) IAliyunAvatarDo {
+	for _, _f := range fields {
+		a = *a.withDO(a.DO.Joins(_f))
+	}
+	return &a
+}
+
+func (a aliyunAvatarDo) Preload(fields ...field.RelationField) IAliyunAvatarDo {
+	for _, _f := range fields {
+		a = *a.withDO(a.DO.Preload(_f))
+	}
+	return &a
+}
+
+func (a aliyunAvatarDo) FirstOrInit() (*model.AliyunAvatar, error) {
+	if result, err := a.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.AliyunAvatar), nil
+	}
+}
+
+func (a aliyunAvatarDo) FirstOrCreate() (*model.AliyunAvatar, error) {
+	if result, err := a.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.AliyunAvatar), nil
+	}
+}
+
+func (a aliyunAvatarDo) FindByPage(offset int, limit int) (result []*model.AliyunAvatar, count int64, err error) {
+	result, err = a.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = a.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (a aliyunAvatarDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = a.Count()
+	if err != nil {
+		return
+	}
+
+	err = a.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (a aliyunAvatarDo) Scan(result interface{}) (err error) {
+	return a.DO.Scan(result)
+}
+
+func (a aliyunAvatarDo) Delete(models ...*model.AliyunAvatar) (result gen.ResultInfo, err error) {
+	return a.DO.Delete(models)
+}
+
+func (a *aliyunAvatarDo) withDO(do gen.Dao) *aliyunAvatarDo {
+	a.DO = *do.(*gen.DO)
+	return a
+}

+ 408 - 0
database/dao/wechat/query/alloc_agent.gen.go

@@ -0,0 +1,408 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newAllocAgent(db *gorm.DB, opts ...gen.DOOption) allocAgent {
+	_allocAgent := allocAgent{}
+
+	_allocAgent.allocAgentDo.UseDB(db, opts...)
+	_allocAgent.allocAgentDo.UseModel(&model.AllocAgent{})
+
+	tableName := _allocAgent.allocAgentDo.TableName()
+	_allocAgent.ALL = field.NewAsterisk(tableName)
+	_allocAgent.ID = field.NewInt64(tableName, "id")
+	_allocAgent.CreatedAt = field.NewTime(tableName, "created_at")
+	_allocAgent.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_allocAgent.Status = field.NewInt64(tableName, "status")
+	_allocAgent.DeletedAt = field.NewField(tableName, "deleted_at")
+	_allocAgent.UserID = field.NewString(tableName, "user_id")
+	_allocAgent.OrganizationID = field.NewInt64(tableName, "organization_id")
+	_allocAgent.Agents = field.NewString(tableName, "agents")
+
+	_allocAgent.fillFieldMap()
+
+	return _allocAgent
+}
+
+type allocAgent struct {
+	allocAgentDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	Status         field.Int64  // 状态 1 正常 2 禁用
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	UserID         field.String // 前台用户ID
+	OrganizationID field.Int64  // 机构 ID
+	Agents         field.String // 分配的智能体ID
+
+	fieldMap map[string]field.Expr
+}
+
+func (a allocAgent) Table(newTableName string) *allocAgent {
+	a.allocAgentDo.UseTable(newTableName)
+	return a.updateTableName(newTableName)
+}
+
+func (a allocAgent) As(alias string) *allocAgent {
+	a.allocAgentDo.DO = *(a.allocAgentDo.As(alias).(*gen.DO))
+	return a.updateTableName(alias)
+}
+
+func (a *allocAgent) updateTableName(table string) *allocAgent {
+	a.ALL = field.NewAsterisk(table)
+	a.ID = field.NewInt64(table, "id")
+	a.CreatedAt = field.NewTime(table, "created_at")
+	a.UpdatedAt = field.NewTime(table, "updated_at")
+	a.Status = field.NewInt64(table, "status")
+	a.DeletedAt = field.NewField(table, "deleted_at")
+	a.UserID = field.NewString(table, "user_id")
+	a.OrganizationID = field.NewInt64(table, "organization_id")
+	a.Agents = field.NewString(table, "agents")
+
+	a.fillFieldMap()
+
+	return a
+}
+
+func (a *allocAgent) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := a.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (a *allocAgent) fillFieldMap() {
+	a.fieldMap = make(map[string]field.Expr, 8)
+	a.fieldMap["id"] = a.ID
+	a.fieldMap["created_at"] = a.CreatedAt
+	a.fieldMap["updated_at"] = a.UpdatedAt
+	a.fieldMap["status"] = a.Status
+	a.fieldMap["deleted_at"] = a.DeletedAt
+	a.fieldMap["user_id"] = a.UserID
+	a.fieldMap["organization_id"] = a.OrganizationID
+	a.fieldMap["agents"] = a.Agents
+}
+
+func (a allocAgent) clone(db *gorm.DB) allocAgent {
+	a.allocAgentDo.ReplaceConnPool(db.Statement.ConnPool)
+	return a
+}
+
+func (a allocAgent) replaceDB(db *gorm.DB) allocAgent {
+	a.allocAgentDo.ReplaceDB(db)
+	return a
+}
+
+type allocAgentDo struct{ gen.DO }
+
+type IAllocAgentDo interface {
+	gen.SubQuery
+	Debug() IAllocAgentDo
+	WithContext(ctx context.Context) IAllocAgentDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IAllocAgentDo
+	WriteDB() IAllocAgentDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IAllocAgentDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IAllocAgentDo
+	Not(conds ...gen.Condition) IAllocAgentDo
+	Or(conds ...gen.Condition) IAllocAgentDo
+	Select(conds ...field.Expr) IAllocAgentDo
+	Where(conds ...gen.Condition) IAllocAgentDo
+	Order(conds ...field.Expr) IAllocAgentDo
+	Distinct(cols ...field.Expr) IAllocAgentDo
+	Omit(cols ...field.Expr) IAllocAgentDo
+	Join(table schema.Tabler, on ...field.Expr) IAllocAgentDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IAllocAgentDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IAllocAgentDo
+	Group(cols ...field.Expr) IAllocAgentDo
+	Having(conds ...gen.Condition) IAllocAgentDo
+	Limit(limit int) IAllocAgentDo
+	Offset(offset int) IAllocAgentDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IAllocAgentDo
+	Unscoped() IAllocAgentDo
+	Create(values ...*model.AllocAgent) error
+	CreateInBatches(values []*model.AllocAgent, batchSize int) error
+	Save(values ...*model.AllocAgent) error
+	First() (*model.AllocAgent, error)
+	Take() (*model.AllocAgent, error)
+	Last() (*model.AllocAgent, error)
+	Find() ([]*model.AllocAgent, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.AllocAgent, err error)
+	FindInBatches(result *[]*model.AllocAgent, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.AllocAgent) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IAllocAgentDo
+	Assign(attrs ...field.AssignExpr) IAllocAgentDo
+	Joins(fields ...field.RelationField) IAllocAgentDo
+	Preload(fields ...field.RelationField) IAllocAgentDo
+	FirstOrInit() (*model.AllocAgent, error)
+	FirstOrCreate() (*model.AllocAgent, error)
+	FindByPage(offset int, limit int) (result []*model.AllocAgent, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IAllocAgentDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (a allocAgentDo) Debug() IAllocAgentDo {
+	return a.withDO(a.DO.Debug())
+}
+
+func (a allocAgentDo) WithContext(ctx context.Context) IAllocAgentDo {
+	return a.withDO(a.DO.WithContext(ctx))
+}
+
+func (a allocAgentDo) ReadDB() IAllocAgentDo {
+	return a.Clauses(dbresolver.Read)
+}
+
+func (a allocAgentDo) WriteDB() IAllocAgentDo {
+	return a.Clauses(dbresolver.Write)
+}
+
+func (a allocAgentDo) Session(config *gorm.Session) IAllocAgentDo {
+	return a.withDO(a.DO.Session(config))
+}
+
+func (a allocAgentDo) Clauses(conds ...clause.Expression) IAllocAgentDo {
+	return a.withDO(a.DO.Clauses(conds...))
+}
+
+func (a allocAgentDo) Returning(value interface{}, columns ...string) IAllocAgentDo {
+	return a.withDO(a.DO.Returning(value, columns...))
+}
+
+func (a allocAgentDo) Not(conds ...gen.Condition) IAllocAgentDo {
+	return a.withDO(a.DO.Not(conds...))
+}
+
+func (a allocAgentDo) Or(conds ...gen.Condition) IAllocAgentDo {
+	return a.withDO(a.DO.Or(conds...))
+}
+
+func (a allocAgentDo) Select(conds ...field.Expr) IAllocAgentDo {
+	return a.withDO(a.DO.Select(conds...))
+}
+
+func (a allocAgentDo) Where(conds ...gen.Condition) IAllocAgentDo {
+	return a.withDO(a.DO.Where(conds...))
+}
+
+func (a allocAgentDo) Order(conds ...field.Expr) IAllocAgentDo {
+	return a.withDO(a.DO.Order(conds...))
+}
+
+func (a allocAgentDo) Distinct(cols ...field.Expr) IAllocAgentDo {
+	return a.withDO(a.DO.Distinct(cols...))
+}
+
+func (a allocAgentDo) Omit(cols ...field.Expr) IAllocAgentDo {
+	return a.withDO(a.DO.Omit(cols...))
+}
+
+func (a allocAgentDo) Join(table schema.Tabler, on ...field.Expr) IAllocAgentDo {
+	return a.withDO(a.DO.Join(table, on...))
+}
+
+func (a allocAgentDo) LeftJoin(table schema.Tabler, on ...field.Expr) IAllocAgentDo {
+	return a.withDO(a.DO.LeftJoin(table, on...))
+}
+
+func (a allocAgentDo) RightJoin(table schema.Tabler, on ...field.Expr) IAllocAgentDo {
+	return a.withDO(a.DO.RightJoin(table, on...))
+}
+
+func (a allocAgentDo) Group(cols ...field.Expr) IAllocAgentDo {
+	return a.withDO(a.DO.Group(cols...))
+}
+
+func (a allocAgentDo) Having(conds ...gen.Condition) IAllocAgentDo {
+	return a.withDO(a.DO.Having(conds...))
+}
+
+func (a allocAgentDo) Limit(limit int) IAllocAgentDo {
+	return a.withDO(a.DO.Limit(limit))
+}
+
+func (a allocAgentDo) Offset(offset int) IAllocAgentDo {
+	return a.withDO(a.DO.Offset(offset))
+}
+
+func (a allocAgentDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IAllocAgentDo {
+	return a.withDO(a.DO.Scopes(funcs...))
+}
+
+func (a allocAgentDo) Unscoped() IAllocAgentDo {
+	return a.withDO(a.DO.Unscoped())
+}
+
+func (a allocAgentDo) Create(values ...*model.AllocAgent) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return a.DO.Create(values)
+}
+
+func (a allocAgentDo) CreateInBatches(values []*model.AllocAgent, batchSize int) error {
+	return a.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (a allocAgentDo) Save(values ...*model.AllocAgent) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return a.DO.Save(values)
+}
+
+func (a allocAgentDo) First() (*model.AllocAgent, error) {
+	if result, err := a.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.AllocAgent), nil
+	}
+}
+
+func (a allocAgentDo) Take() (*model.AllocAgent, error) {
+	if result, err := a.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.AllocAgent), nil
+	}
+}
+
+func (a allocAgentDo) Last() (*model.AllocAgent, error) {
+	if result, err := a.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.AllocAgent), nil
+	}
+}
+
+func (a allocAgentDo) Find() ([]*model.AllocAgent, error) {
+	result, err := a.DO.Find()
+	return result.([]*model.AllocAgent), err
+}
+
+func (a allocAgentDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.AllocAgent, err error) {
+	buf := make([]*model.AllocAgent, 0, batchSize)
+	err = a.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (a allocAgentDo) FindInBatches(result *[]*model.AllocAgent, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return a.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (a allocAgentDo) Attrs(attrs ...field.AssignExpr) IAllocAgentDo {
+	return a.withDO(a.DO.Attrs(attrs...))
+}
+
+func (a allocAgentDo) Assign(attrs ...field.AssignExpr) IAllocAgentDo {
+	return a.withDO(a.DO.Assign(attrs...))
+}
+
+func (a allocAgentDo) Joins(fields ...field.RelationField) IAllocAgentDo {
+	for _, _f := range fields {
+		a = *a.withDO(a.DO.Joins(_f))
+	}
+	return &a
+}
+
+func (a allocAgentDo) Preload(fields ...field.RelationField) IAllocAgentDo {
+	for _, _f := range fields {
+		a = *a.withDO(a.DO.Preload(_f))
+	}
+	return &a
+}
+
+func (a allocAgentDo) FirstOrInit() (*model.AllocAgent, error) {
+	if result, err := a.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.AllocAgent), nil
+	}
+}
+
+func (a allocAgentDo) FirstOrCreate() (*model.AllocAgent, error) {
+	if result, err := a.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.AllocAgent), nil
+	}
+}
+
+func (a allocAgentDo) FindByPage(offset int, limit int) (result []*model.AllocAgent, count int64, err error) {
+	result, err = a.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = a.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (a allocAgentDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = a.Count()
+	if err != nil {
+		return
+	}
+
+	err = a.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (a allocAgentDo) Scan(result interface{}) (err error) {
+	return a.DO.Scan(result)
+}
+
+func (a allocAgentDo) Delete(models ...*model.AllocAgent) (result gen.ResultInfo, err error) {
+	return a.DO.Delete(models)
+}
+
+func (a *allocAgentDo) withDO(do gen.Dao) *allocAgentDo {
+	a.DO = *do.(*gen.DO)
+	return a
+}

+ 477 - 0
database/dao/wechat/query/batch_msg.gen.go

@@ -0,0 +1,477 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newBatchMsg(db *gorm.DB, opts ...gen.DOOption) batchMsg {
+	_batchMsg := batchMsg{}
+
+	_batchMsg.batchMsgDo.UseDB(db, opts...)
+	_batchMsg.batchMsgDo.UseModel(&model.BatchMsg{})
+
+	tableName := _batchMsg.batchMsgDo.TableName()
+	_batchMsg.ALL = field.NewAsterisk(tableName)
+	_batchMsg.ID = field.NewInt64(tableName, "id")
+	_batchMsg.CreatedAt = field.NewTime(tableName, "created_at")
+	_batchMsg.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_batchMsg.DeletedAt = field.NewField(tableName, "deleted_at")
+	_batchMsg.TaskName = field.NewString(tableName, "task_name")
+	_batchMsg.Status = field.NewInt64(tableName, "status")
+	_batchMsg.BatchNo = field.NewString(tableName, "batch_no")
+	_batchMsg.Fromwxid = field.NewString(tableName, "fromwxid")
+	_batchMsg.Msg = field.NewString(tableName, "msg")
+	_batchMsg.Tagids = field.NewString(tableName, "tagids")
+	_batchMsg.Tag = field.NewString(tableName, "tag")
+	_batchMsg.Total = field.NewInt64(tableName, "total")
+	_batchMsg.Success = field.NewInt64(tableName, "success")
+	_batchMsg.Fail = field.NewInt64(tableName, "fail")
+	_batchMsg.StartTime = field.NewTime(tableName, "start_time")
+	_batchMsg.StopTime = field.NewTime(tableName, "stop_time")
+	_batchMsg.SendTime = field.NewTime(tableName, "send_time")
+	_batchMsg.Type = field.NewInt64(tableName, "type")
+	_batchMsg.OrganizationID = field.NewInt64(tableName, "organization_id")
+	_batchMsg.Ctype = field.NewInt64(tableName, "ctype")
+	_batchMsg.Cc = field.NewString(tableName, "cc")
+	_batchMsg.Phone = field.NewString(tableName, "phone")
+	_batchMsg.TemplateName = field.NewString(tableName, "template_name")
+	_batchMsg.TemplateCode = field.NewString(tableName, "template_code")
+	_batchMsg.Lang = field.NewString(tableName, "lang")
+
+	_batchMsg.fillFieldMap()
+
+	return _batchMsg
+}
+
+// batchMsg 批量消息表
+type batchMsg struct {
+	batchMsgDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	TaskName       field.String // 群发任务名称
+	Status         field.Int64  // 状态 0 未开始 1 发送中 2 发送完成 3 发送中止
+	BatchNo        field.String // 批次号
+	Fromwxid       field.String // 发送方微信ID
+	Msg            field.String // 内容
+	Tagids         field.String // 需要发送的tagids
+	Tag            field.String // 发送规则 all 全部 tag1,tag2 按tag发送
+	Total          field.Int64  // 总数
+	Success        field.Int64  // 成功数量
+	Fail           field.Int64  // 失败数量
+	StartTime      field.Time   // 开始时间
+	StopTime       field.Time   // 结束时间
+	SendTime       field.Time   // 发送时间
+	Type           field.Int64  // 1-群发消息 2-群发朋友圈
+	OrganizationID field.Int64  // 机构ID
+	Ctype          field.Int64  // 内容类型:1-微信 2-whatsapp 3-企微
+	Cc             field.String // 国家区号
+	Phone          field.String // 手机号
+	TemplateName   field.String // 模板名
+	TemplateCode   field.String // 模板code
+	Lang           field.String // 模板语言
+
+	fieldMap map[string]field.Expr
+}
+
+func (b batchMsg) Table(newTableName string) *batchMsg {
+	b.batchMsgDo.UseTable(newTableName)
+	return b.updateTableName(newTableName)
+}
+
+func (b batchMsg) As(alias string) *batchMsg {
+	b.batchMsgDo.DO = *(b.batchMsgDo.As(alias).(*gen.DO))
+	return b.updateTableName(alias)
+}
+
+func (b *batchMsg) updateTableName(table string) *batchMsg {
+	b.ALL = field.NewAsterisk(table)
+	b.ID = field.NewInt64(table, "id")
+	b.CreatedAt = field.NewTime(table, "created_at")
+	b.UpdatedAt = field.NewTime(table, "updated_at")
+	b.DeletedAt = field.NewField(table, "deleted_at")
+	b.TaskName = field.NewString(table, "task_name")
+	b.Status = field.NewInt64(table, "status")
+	b.BatchNo = field.NewString(table, "batch_no")
+	b.Fromwxid = field.NewString(table, "fromwxid")
+	b.Msg = field.NewString(table, "msg")
+	b.Tagids = field.NewString(table, "tagids")
+	b.Tag = field.NewString(table, "tag")
+	b.Total = field.NewInt64(table, "total")
+	b.Success = field.NewInt64(table, "success")
+	b.Fail = field.NewInt64(table, "fail")
+	b.StartTime = field.NewTime(table, "start_time")
+	b.StopTime = field.NewTime(table, "stop_time")
+	b.SendTime = field.NewTime(table, "send_time")
+	b.Type = field.NewInt64(table, "type")
+	b.OrganizationID = field.NewInt64(table, "organization_id")
+	b.Ctype = field.NewInt64(table, "ctype")
+	b.Cc = field.NewString(table, "cc")
+	b.Phone = field.NewString(table, "phone")
+	b.TemplateName = field.NewString(table, "template_name")
+	b.TemplateCode = field.NewString(table, "template_code")
+	b.Lang = field.NewString(table, "lang")
+
+	b.fillFieldMap()
+
+	return b
+}
+
+func (b *batchMsg) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := b.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (b *batchMsg) fillFieldMap() {
+	b.fieldMap = make(map[string]field.Expr, 25)
+	b.fieldMap["id"] = b.ID
+	b.fieldMap["created_at"] = b.CreatedAt
+	b.fieldMap["updated_at"] = b.UpdatedAt
+	b.fieldMap["deleted_at"] = b.DeletedAt
+	b.fieldMap["task_name"] = b.TaskName
+	b.fieldMap["status"] = b.Status
+	b.fieldMap["batch_no"] = b.BatchNo
+	b.fieldMap["fromwxid"] = b.Fromwxid
+	b.fieldMap["msg"] = b.Msg
+	b.fieldMap["tagids"] = b.Tagids
+	b.fieldMap["tag"] = b.Tag
+	b.fieldMap["total"] = b.Total
+	b.fieldMap["success"] = b.Success
+	b.fieldMap["fail"] = b.Fail
+	b.fieldMap["start_time"] = b.StartTime
+	b.fieldMap["stop_time"] = b.StopTime
+	b.fieldMap["send_time"] = b.SendTime
+	b.fieldMap["type"] = b.Type
+	b.fieldMap["organization_id"] = b.OrganizationID
+	b.fieldMap["ctype"] = b.Ctype
+	b.fieldMap["cc"] = b.Cc
+	b.fieldMap["phone"] = b.Phone
+	b.fieldMap["template_name"] = b.TemplateName
+	b.fieldMap["template_code"] = b.TemplateCode
+	b.fieldMap["lang"] = b.Lang
+}
+
+func (b batchMsg) clone(db *gorm.DB) batchMsg {
+	b.batchMsgDo.ReplaceConnPool(db.Statement.ConnPool)
+	return b
+}
+
+func (b batchMsg) replaceDB(db *gorm.DB) batchMsg {
+	b.batchMsgDo.ReplaceDB(db)
+	return b
+}
+
+type batchMsgDo struct{ gen.DO }
+
+type IBatchMsgDo interface {
+	gen.SubQuery
+	Debug() IBatchMsgDo
+	WithContext(ctx context.Context) IBatchMsgDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IBatchMsgDo
+	WriteDB() IBatchMsgDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IBatchMsgDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IBatchMsgDo
+	Not(conds ...gen.Condition) IBatchMsgDo
+	Or(conds ...gen.Condition) IBatchMsgDo
+	Select(conds ...field.Expr) IBatchMsgDo
+	Where(conds ...gen.Condition) IBatchMsgDo
+	Order(conds ...field.Expr) IBatchMsgDo
+	Distinct(cols ...field.Expr) IBatchMsgDo
+	Omit(cols ...field.Expr) IBatchMsgDo
+	Join(table schema.Tabler, on ...field.Expr) IBatchMsgDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IBatchMsgDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IBatchMsgDo
+	Group(cols ...field.Expr) IBatchMsgDo
+	Having(conds ...gen.Condition) IBatchMsgDo
+	Limit(limit int) IBatchMsgDo
+	Offset(offset int) IBatchMsgDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IBatchMsgDo
+	Unscoped() IBatchMsgDo
+	Create(values ...*model.BatchMsg) error
+	CreateInBatches(values []*model.BatchMsg, batchSize int) error
+	Save(values ...*model.BatchMsg) error
+	First() (*model.BatchMsg, error)
+	Take() (*model.BatchMsg, error)
+	Last() (*model.BatchMsg, error)
+	Find() ([]*model.BatchMsg, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.BatchMsg, err error)
+	FindInBatches(result *[]*model.BatchMsg, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.BatchMsg) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IBatchMsgDo
+	Assign(attrs ...field.AssignExpr) IBatchMsgDo
+	Joins(fields ...field.RelationField) IBatchMsgDo
+	Preload(fields ...field.RelationField) IBatchMsgDo
+	FirstOrInit() (*model.BatchMsg, error)
+	FirstOrCreate() (*model.BatchMsg, error)
+	FindByPage(offset int, limit int) (result []*model.BatchMsg, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IBatchMsgDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (b batchMsgDo) Debug() IBatchMsgDo {
+	return b.withDO(b.DO.Debug())
+}
+
+func (b batchMsgDo) WithContext(ctx context.Context) IBatchMsgDo {
+	return b.withDO(b.DO.WithContext(ctx))
+}
+
+func (b batchMsgDo) ReadDB() IBatchMsgDo {
+	return b.Clauses(dbresolver.Read)
+}
+
+func (b batchMsgDo) WriteDB() IBatchMsgDo {
+	return b.Clauses(dbresolver.Write)
+}
+
+func (b batchMsgDo) Session(config *gorm.Session) IBatchMsgDo {
+	return b.withDO(b.DO.Session(config))
+}
+
+func (b batchMsgDo) Clauses(conds ...clause.Expression) IBatchMsgDo {
+	return b.withDO(b.DO.Clauses(conds...))
+}
+
+func (b batchMsgDo) Returning(value interface{}, columns ...string) IBatchMsgDo {
+	return b.withDO(b.DO.Returning(value, columns...))
+}
+
+func (b batchMsgDo) Not(conds ...gen.Condition) IBatchMsgDo {
+	return b.withDO(b.DO.Not(conds...))
+}
+
+func (b batchMsgDo) Or(conds ...gen.Condition) IBatchMsgDo {
+	return b.withDO(b.DO.Or(conds...))
+}
+
+func (b batchMsgDo) Select(conds ...field.Expr) IBatchMsgDo {
+	return b.withDO(b.DO.Select(conds...))
+}
+
+func (b batchMsgDo) Where(conds ...gen.Condition) IBatchMsgDo {
+	return b.withDO(b.DO.Where(conds...))
+}
+
+func (b batchMsgDo) Order(conds ...field.Expr) IBatchMsgDo {
+	return b.withDO(b.DO.Order(conds...))
+}
+
+func (b batchMsgDo) Distinct(cols ...field.Expr) IBatchMsgDo {
+	return b.withDO(b.DO.Distinct(cols...))
+}
+
+func (b batchMsgDo) Omit(cols ...field.Expr) IBatchMsgDo {
+	return b.withDO(b.DO.Omit(cols...))
+}
+
+func (b batchMsgDo) Join(table schema.Tabler, on ...field.Expr) IBatchMsgDo {
+	return b.withDO(b.DO.Join(table, on...))
+}
+
+func (b batchMsgDo) LeftJoin(table schema.Tabler, on ...field.Expr) IBatchMsgDo {
+	return b.withDO(b.DO.LeftJoin(table, on...))
+}
+
+func (b batchMsgDo) RightJoin(table schema.Tabler, on ...field.Expr) IBatchMsgDo {
+	return b.withDO(b.DO.RightJoin(table, on...))
+}
+
+func (b batchMsgDo) Group(cols ...field.Expr) IBatchMsgDo {
+	return b.withDO(b.DO.Group(cols...))
+}
+
+func (b batchMsgDo) Having(conds ...gen.Condition) IBatchMsgDo {
+	return b.withDO(b.DO.Having(conds...))
+}
+
+func (b batchMsgDo) Limit(limit int) IBatchMsgDo {
+	return b.withDO(b.DO.Limit(limit))
+}
+
+func (b batchMsgDo) Offset(offset int) IBatchMsgDo {
+	return b.withDO(b.DO.Offset(offset))
+}
+
+func (b batchMsgDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IBatchMsgDo {
+	return b.withDO(b.DO.Scopes(funcs...))
+}
+
+func (b batchMsgDo) Unscoped() IBatchMsgDo {
+	return b.withDO(b.DO.Unscoped())
+}
+
+func (b batchMsgDo) Create(values ...*model.BatchMsg) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return b.DO.Create(values)
+}
+
+func (b batchMsgDo) CreateInBatches(values []*model.BatchMsg, batchSize int) error {
+	return b.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (b batchMsgDo) Save(values ...*model.BatchMsg) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return b.DO.Save(values)
+}
+
+func (b batchMsgDo) First() (*model.BatchMsg, error) {
+	if result, err := b.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.BatchMsg), nil
+	}
+}
+
+func (b batchMsgDo) Take() (*model.BatchMsg, error) {
+	if result, err := b.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.BatchMsg), nil
+	}
+}
+
+func (b batchMsgDo) Last() (*model.BatchMsg, error) {
+	if result, err := b.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.BatchMsg), nil
+	}
+}
+
+func (b batchMsgDo) Find() ([]*model.BatchMsg, error) {
+	result, err := b.DO.Find()
+	return result.([]*model.BatchMsg), err
+}
+
+func (b batchMsgDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.BatchMsg, err error) {
+	buf := make([]*model.BatchMsg, 0, batchSize)
+	err = b.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (b batchMsgDo) FindInBatches(result *[]*model.BatchMsg, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return b.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (b batchMsgDo) Attrs(attrs ...field.AssignExpr) IBatchMsgDo {
+	return b.withDO(b.DO.Attrs(attrs...))
+}
+
+func (b batchMsgDo) Assign(attrs ...field.AssignExpr) IBatchMsgDo {
+	return b.withDO(b.DO.Assign(attrs...))
+}
+
+func (b batchMsgDo) Joins(fields ...field.RelationField) IBatchMsgDo {
+	for _, _f := range fields {
+		b = *b.withDO(b.DO.Joins(_f))
+	}
+	return &b
+}
+
+func (b batchMsgDo) Preload(fields ...field.RelationField) IBatchMsgDo {
+	for _, _f := range fields {
+		b = *b.withDO(b.DO.Preload(_f))
+	}
+	return &b
+}
+
+func (b batchMsgDo) FirstOrInit() (*model.BatchMsg, error) {
+	if result, err := b.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.BatchMsg), nil
+	}
+}
+
+func (b batchMsgDo) FirstOrCreate() (*model.BatchMsg, error) {
+	if result, err := b.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.BatchMsg), nil
+	}
+}
+
+func (b batchMsgDo) FindByPage(offset int, limit int) (result []*model.BatchMsg, count int64, err error) {
+	result, err = b.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = b.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (b batchMsgDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = b.Count()
+	if err != nil {
+		return
+	}
+
+	err = b.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (b batchMsgDo) Scan(result interface{}) (err error) {
+	return b.DO.Scan(result)
+}
+
+func (b batchMsgDo) Delete(models ...*model.BatchMsg) (result gen.ResultInfo, err error) {
+	return b.DO.Delete(models)
+}
+
+func (b *batchMsgDo) withDO(do gen.Dao) *batchMsgDo {
+	b.DO = *do.(*gen.DO)
+	return b
+}

+ 433 - 0
database/dao/wechat/query/batch_msg_copy1.gen.go

@@ -0,0 +1,433 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newBatchMsgCopy1(db *gorm.DB, opts ...gen.DOOption) batchMsgCopy1 {
+	_batchMsgCopy1 := batchMsgCopy1{}
+
+	_batchMsgCopy1.batchMsgCopy1Do.UseDB(db, opts...)
+	_batchMsgCopy1.batchMsgCopy1Do.UseModel(&model.BatchMsgCopy1{})
+
+	tableName := _batchMsgCopy1.batchMsgCopy1Do.TableName()
+	_batchMsgCopy1.ALL = field.NewAsterisk(tableName)
+	_batchMsgCopy1.ID = field.NewInt64(tableName, "id")
+	_batchMsgCopy1.CreatedAt = field.NewTime(tableName, "created_at")
+	_batchMsgCopy1.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_batchMsgCopy1.DeletedAt = field.NewField(tableName, "deleted_at")
+	_batchMsgCopy1.Status = field.NewInt64(tableName, "status")
+	_batchMsgCopy1.BatchNo = field.NewString(tableName, "batch_no")
+	_batchMsgCopy1.Fromwxid = field.NewString(tableName, "fromwxid")
+	_batchMsgCopy1.Msg = field.NewString(tableName, "msg")
+	_batchMsgCopy1.Tag = field.NewString(tableName, "tag")
+	_batchMsgCopy1.Total = field.NewInt64(tableName, "total")
+	_batchMsgCopy1.Success = field.NewInt64(tableName, "success")
+	_batchMsgCopy1.Fail = field.NewInt64(tableName, "fail")
+	_batchMsgCopy1.StartTime = field.NewTime(tableName, "start_time")
+	_batchMsgCopy1.StopTime = field.NewTime(tableName, "stop_time")
+
+	_batchMsgCopy1.fillFieldMap()
+
+	return _batchMsgCopy1
+}
+
+// batchMsgCopy1 批量消息表
+type batchMsgCopy1 struct {
+	batchMsgCopy1Do
+
+	ALL       field.Asterisk
+	ID        field.Int64
+	CreatedAt field.Time   // Create Time | 创建日期
+	UpdatedAt field.Time   // Update Time | 修改日期
+	DeletedAt field.Field  // Delete Time | 删除日期
+	Status    field.Int64  // 状态 0 未开始 1 发送中 2 发送完成 3 发送中止
+	BatchNo   field.String // 批次号
+	Fromwxid  field.String // 发送方微信ID
+	Msg       field.String // 内容
+	Tag       field.String // 发送规则 all 全部 tag1,tag2 按tag发送
+	Total     field.Int64  // 总数
+	Success   field.Int64  // 成功数量
+	Fail      field.Int64  // 失败数量
+	StartTime field.Time   // 开始时间
+	StopTime  field.Time   // 结束时间
+
+	fieldMap map[string]field.Expr
+}
+
+func (b batchMsgCopy1) Table(newTableName string) *batchMsgCopy1 {
+	b.batchMsgCopy1Do.UseTable(newTableName)
+	return b.updateTableName(newTableName)
+}
+
+func (b batchMsgCopy1) As(alias string) *batchMsgCopy1 {
+	b.batchMsgCopy1Do.DO = *(b.batchMsgCopy1Do.As(alias).(*gen.DO))
+	return b.updateTableName(alias)
+}
+
+func (b *batchMsgCopy1) updateTableName(table string) *batchMsgCopy1 {
+	b.ALL = field.NewAsterisk(table)
+	b.ID = field.NewInt64(table, "id")
+	b.CreatedAt = field.NewTime(table, "created_at")
+	b.UpdatedAt = field.NewTime(table, "updated_at")
+	b.DeletedAt = field.NewField(table, "deleted_at")
+	b.Status = field.NewInt64(table, "status")
+	b.BatchNo = field.NewString(table, "batch_no")
+	b.Fromwxid = field.NewString(table, "fromwxid")
+	b.Msg = field.NewString(table, "msg")
+	b.Tag = field.NewString(table, "tag")
+	b.Total = field.NewInt64(table, "total")
+	b.Success = field.NewInt64(table, "success")
+	b.Fail = field.NewInt64(table, "fail")
+	b.StartTime = field.NewTime(table, "start_time")
+	b.StopTime = field.NewTime(table, "stop_time")
+
+	b.fillFieldMap()
+
+	return b
+}
+
+func (b *batchMsgCopy1) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := b.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (b *batchMsgCopy1) fillFieldMap() {
+	b.fieldMap = make(map[string]field.Expr, 14)
+	b.fieldMap["id"] = b.ID
+	b.fieldMap["created_at"] = b.CreatedAt
+	b.fieldMap["updated_at"] = b.UpdatedAt
+	b.fieldMap["deleted_at"] = b.DeletedAt
+	b.fieldMap["status"] = b.Status
+	b.fieldMap["batch_no"] = b.BatchNo
+	b.fieldMap["fromwxid"] = b.Fromwxid
+	b.fieldMap["msg"] = b.Msg
+	b.fieldMap["tag"] = b.Tag
+	b.fieldMap["total"] = b.Total
+	b.fieldMap["success"] = b.Success
+	b.fieldMap["fail"] = b.Fail
+	b.fieldMap["start_time"] = b.StartTime
+	b.fieldMap["stop_time"] = b.StopTime
+}
+
+func (b batchMsgCopy1) clone(db *gorm.DB) batchMsgCopy1 {
+	b.batchMsgCopy1Do.ReplaceConnPool(db.Statement.ConnPool)
+	return b
+}
+
+func (b batchMsgCopy1) replaceDB(db *gorm.DB) batchMsgCopy1 {
+	b.batchMsgCopy1Do.ReplaceDB(db)
+	return b
+}
+
+type batchMsgCopy1Do struct{ gen.DO }
+
+type IBatchMsgCopy1Do interface {
+	gen.SubQuery
+	Debug() IBatchMsgCopy1Do
+	WithContext(ctx context.Context) IBatchMsgCopy1Do
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IBatchMsgCopy1Do
+	WriteDB() IBatchMsgCopy1Do
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IBatchMsgCopy1Do
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IBatchMsgCopy1Do
+	Not(conds ...gen.Condition) IBatchMsgCopy1Do
+	Or(conds ...gen.Condition) IBatchMsgCopy1Do
+	Select(conds ...field.Expr) IBatchMsgCopy1Do
+	Where(conds ...gen.Condition) IBatchMsgCopy1Do
+	Order(conds ...field.Expr) IBatchMsgCopy1Do
+	Distinct(cols ...field.Expr) IBatchMsgCopy1Do
+	Omit(cols ...field.Expr) IBatchMsgCopy1Do
+	Join(table schema.Tabler, on ...field.Expr) IBatchMsgCopy1Do
+	LeftJoin(table schema.Tabler, on ...field.Expr) IBatchMsgCopy1Do
+	RightJoin(table schema.Tabler, on ...field.Expr) IBatchMsgCopy1Do
+	Group(cols ...field.Expr) IBatchMsgCopy1Do
+	Having(conds ...gen.Condition) IBatchMsgCopy1Do
+	Limit(limit int) IBatchMsgCopy1Do
+	Offset(offset int) IBatchMsgCopy1Do
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IBatchMsgCopy1Do
+	Unscoped() IBatchMsgCopy1Do
+	Create(values ...*model.BatchMsgCopy1) error
+	CreateInBatches(values []*model.BatchMsgCopy1, batchSize int) error
+	Save(values ...*model.BatchMsgCopy1) error
+	First() (*model.BatchMsgCopy1, error)
+	Take() (*model.BatchMsgCopy1, error)
+	Last() (*model.BatchMsgCopy1, error)
+	Find() ([]*model.BatchMsgCopy1, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.BatchMsgCopy1, err error)
+	FindInBatches(result *[]*model.BatchMsgCopy1, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.BatchMsgCopy1) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IBatchMsgCopy1Do
+	Assign(attrs ...field.AssignExpr) IBatchMsgCopy1Do
+	Joins(fields ...field.RelationField) IBatchMsgCopy1Do
+	Preload(fields ...field.RelationField) IBatchMsgCopy1Do
+	FirstOrInit() (*model.BatchMsgCopy1, error)
+	FirstOrCreate() (*model.BatchMsgCopy1, error)
+	FindByPage(offset int, limit int) (result []*model.BatchMsgCopy1, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IBatchMsgCopy1Do
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (b batchMsgCopy1Do) Debug() IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Debug())
+}
+
+func (b batchMsgCopy1Do) WithContext(ctx context.Context) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.WithContext(ctx))
+}
+
+func (b batchMsgCopy1Do) ReadDB() IBatchMsgCopy1Do {
+	return b.Clauses(dbresolver.Read)
+}
+
+func (b batchMsgCopy1Do) WriteDB() IBatchMsgCopy1Do {
+	return b.Clauses(dbresolver.Write)
+}
+
+func (b batchMsgCopy1Do) Session(config *gorm.Session) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Session(config))
+}
+
+func (b batchMsgCopy1Do) Clauses(conds ...clause.Expression) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Clauses(conds...))
+}
+
+func (b batchMsgCopy1Do) Returning(value interface{}, columns ...string) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Returning(value, columns...))
+}
+
+func (b batchMsgCopy1Do) Not(conds ...gen.Condition) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Not(conds...))
+}
+
+func (b batchMsgCopy1Do) Or(conds ...gen.Condition) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Or(conds...))
+}
+
+func (b batchMsgCopy1Do) Select(conds ...field.Expr) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Select(conds...))
+}
+
+func (b batchMsgCopy1Do) Where(conds ...gen.Condition) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Where(conds...))
+}
+
+func (b batchMsgCopy1Do) Order(conds ...field.Expr) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Order(conds...))
+}
+
+func (b batchMsgCopy1Do) Distinct(cols ...field.Expr) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Distinct(cols...))
+}
+
+func (b batchMsgCopy1Do) Omit(cols ...field.Expr) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Omit(cols...))
+}
+
+func (b batchMsgCopy1Do) Join(table schema.Tabler, on ...field.Expr) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Join(table, on...))
+}
+
+func (b batchMsgCopy1Do) LeftJoin(table schema.Tabler, on ...field.Expr) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.LeftJoin(table, on...))
+}
+
+func (b batchMsgCopy1Do) RightJoin(table schema.Tabler, on ...field.Expr) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.RightJoin(table, on...))
+}
+
+func (b batchMsgCopy1Do) Group(cols ...field.Expr) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Group(cols...))
+}
+
+func (b batchMsgCopy1Do) Having(conds ...gen.Condition) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Having(conds...))
+}
+
+func (b batchMsgCopy1Do) Limit(limit int) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Limit(limit))
+}
+
+func (b batchMsgCopy1Do) Offset(offset int) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Offset(offset))
+}
+
+func (b batchMsgCopy1Do) Scopes(funcs ...func(gen.Dao) gen.Dao) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Scopes(funcs...))
+}
+
+func (b batchMsgCopy1Do) Unscoped() IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Unscoped())
+}
+
+func (b batchMsgCopy1Do) Create(values ...*model.BatchMsgCopy1) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return b.DO.Create(values)
+}
+
+func (b batchMsgCopy1Do) CreateInBatches(values []*model.BatchMsgCopy1, batchSize int) error {
+	return b.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (b batchMsgCopy1Do) Save(values ...*model.BatchMsgCopy1) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return b.DO.Save(values)
+}
+
+func (b batchMsgCopy1Do) First() (*model.BatchMsgCopy1, error) {
+	if result, err := b.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.BatchMsgCopy1), nil
+	}
+}
+
+func (b batchMsgCopy1Do) Take() (*model.BatchMsgCopy1, error) {
+	if result, err := b.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.BatchMsgCopy1), nil
+	}
+}
+
+func (b batchMsgCopy1Do) Last() (*model.BatchMsgCopy1, error) {
+	if result, err := b.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.BatchMsgCopy1), nil
+	}
+}
+
+func (b batchMsgCopy1Do) Find() ([]*model.BatchMsgCopy1, error) {
+	result, err := b.DO.Find()
+	return result.([]*model.BatchMsgCopy1), err
+}
+
+func (b batchMsgCopy1Do) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.BatchMsgCopy1, err error) {
+	buf := make([]*model.BatchMsgCopy1, 0, batchSize)
+	err = b.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (b batchMsgCopy1Do) FindInBatches(result *[]*model.BatchMsgCopy1, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return b.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (b batchMsgCopy1Do) Attrs(attrs ...field.AssignExpr) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Attrs(attrs...))
+}
+
+func (b batchMsgCopy1Do) Assign(attrs ...field.AssignExpr) IBatchMsgCopy1Do {
+	return b.withDO(b.DO.Assign(attrs...))
+}
+
+func (b batchMsgCopy1Do) Joins(fields ...field.RelationField) IBatchMsgCopy1Do {
+	for _, _f := range fields {
+		b = *b.withDO(b.DO.Joins(_f))
+	}
+	return &b
+}
+
+func (b batchMsgCopy1Do) Preload(fields ...field.RelationField) IBatchMsgCopy1Do {
+	for _, _f := range fields {
+		b = *b.withDO(b.DO.Preload(_f))
+	}
+	return &b
+}
+
+func (b batchMsgCopy1Do) FirstOrInit() (*model.BatchMsgCopy1, error) {
+	if result, err := b.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.BatchMsgCopy1), nil
+	}
+}
+
+func (b batchMsgCopy1Do) FirstOrCreate() (*model.BatchMsgCopy1, error) {
+	if result, err := b.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.BatchMsgCopy1), nil
+	}
+}
+
+func (b batchMsgCopy1Do) FindByPage(offset int, limit int) (result []*model.BatchMsgCopy1, count int64, err error) {
+	result, err = b.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = b.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (b batchMsgCopy1Do) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = b.Count()
+	if err != nil {
+		return
+	}
+
+	err = b.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (b batchMsgCopy1Do) Scan(result interface{}) (err error) {
+	return b.DO.Scan(result)
+}
+
+func (b batchMsgCopy1Do) Delete(models ...*model.BatchMsgCopy1) (result gen.ResultInfo, err error) {
+	return b.DO.Delete(models)
+}
+
+func (b *batchMsgCopy1Do) withDO(do gen.Dao) *batchMsgCopy1Do {
+	b.DO = *do.(*gen.DO)
+	return b
+}

+ 400 - 0
database/dao/wechat/query/category.gen.go

@@ -0,0 +1,400 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newCategory(db *gorm.DB, opts ...gen.DOOption) category {
+	_category := category{}
+
+	_category.categoryDo.UseDB(db, opts...)
+	_category.categoryDo.UseModel(&model.Category{})
+
+	tableName := _category.categoryDo.TableName()
+	_category.ALL = field.NewAsterisk(tableName)
+	_category.ID = field.NewInt64(tableName, "id")
+	_category.CreatedAt = field.NewTime(tableName, "created_at")
+	_category.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_category.DeletedAt = field.NewField(tableName, "deleted_at")
+	_category.Name = field.NewString(tableName, "name")
+	_category.OrganizationID = field.NewInt64(tableName, "organization_id")
+
+	_category.fillFieldMap()
+
+	return _category
+}
+
+type category struct {
+	categoryDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	Name           field.String // name | agent 名称
+	OrganizationID field.Int64  // organization_id | 租户id
+
+	fieldMap map[string]field.Expr
+}
+
+func (c category) Table(newTableName string) *category {
+	c.categoryDo.UseTable(newTableName)
+	return c.updateTableName(newTableName)
+}
+
+func (c category) As(alias string) *category {
+	c.categoryDo.DO = *(c.categoryDo.As(alias).(*gen.DO))
+	return c.updateTableName(alias)
+}
+
+func (c *category) updateTableName(table string) *category {
+	c.ALL = field.NewAsterisk(table)
+	c.ID = field.NewInt64(table, "id")
+	c.CreatedAt = field.NewTime(table, "created_at")
+	c.UpdatedAt = field.NewTime(table, "updated_at")
+	c.DeletedAt = field.NewField(table, "deleted_at")
+	c.Name = field.NewString(table, "name")
+	c.OrganizationID = field.NewInt64(table, "organization_id")
+
+	c.fillFieldMap()
+
+	return c
+}
+
+func (c *category) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := c.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (c *category) fillFieldMap() {
+	c.fieldMap = make(map[string]field.Expr, 6)
+	c.fieldMap["id"] = c.ID
+	c.fieldMap["created_at"] = c.CreatedAt
+	c.fieldMap["updated_at"] = c.UpdatedAt
+	c.fieldMap["deleted_at"] = c.DeletedAt
+	c.fieldMap["name"] = c.Name
+	c.fieldMap["organization_id"] = c.OrganizationID
+}
+
+func (c category) clone(db *gorm.DB) category {
+	c.categoryDo.ReplaceConnPool(db.Statement.ConnPool)
+	return c
+}
+
+func (c category) replaceDB(db *gorm.DB) category {
+	c.categoryDo.ReplaceDB(db)
+	return c
+}
+
+type categoryDo struct{ gen.DO }
+
+type ICategoryDo interface {
+	gen.SubQuery
+	Debug() ICategoryDo
+	WithContext(ctx context.Context) ICategoryDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() ICategoryDo
+	WriteDB() ICategoryDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) ICategoryDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) ICategoryDo
+	Not(conds ...gen.Condition) ICategoryDo
+	Or(conds ...gen.Condition) ICategoryDo
+	Select(conds ...field.Expr) ICategoryDo
+	Where(conds ...gen.Condition) ICategoryDo
+	Order(conds ...field.Expr) ICategoryDo
+	Distinct(cols ...field.Expr) ICategoryDo
+	Omit(cols ...field.Expr) ICategoryDo
+	Join(table schema.Tabler, on ...field.Expr) ICategoryDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) ICategoryDo
+	RightJoin(table schema.Tabler, on ...field.Expr) ICategoryDo
+	Group(cols ...field.Expr) ICategoryDo
+	Having(conds ...gen.Condition) ICategoryDo
+	Limit(limit int) ICategoryDo
+	Offset(offset int) ICategoryDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) ICategoryDo
+	Unscoped() ICategoryDo
+	Create(values ...*model.Category) error
+	CreateInBatches(values []*model.Category, batchSize int) error
+	Save(values ...*model.Category) error
+	First() (*model.Category, error)
+	Take() (*model.Category, error)
+	Last() (*model.Category, error)
+	Find() ([]*model.Category, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Category, err error)
+	FindInBatches(result *[]*model.Category, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.Category) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) ICategoryDo
+	Assign(attrs ...field.AssignExpr) ICategoryDo
+	Joins(fields ...field.RelationField) ICategoryDo
+	Preload(fields ...field.RelationField) ICategoryDo
+	FirstOrInit() (*model.Category, error)
+	FirstOrCreate() (*model.Category, error)
+	FindByPage(offset int, limit int) (result []*model.Category, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) ICategoryDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (c categoryDo) Debug() ICategoryDo {
+	return c.withDO(c.DO.Debug())
+}
+
+func (c categoryDo) WithContext(ctx context.Context) ICategoryDo {
+	return c.withDO(c.DO.WithContext(ctx))
+}
+
+func (c categoryDo) ReadDB() ICategoryDo {
+	return c.Clauses(dbresolver.Read)
+}
+
+func (c categoryDo) WriteDB() ICategoryDo {
+	return c.Clauses(dbresolver.Write)
+}
+
+func (c categoryDo) Session(config *gorm.Session) ICategoryDo {
+	return c.withDO(c.DO.Session(config))
+}
+
+func (c categoryDo) Clauses(conds ...clause.Expression) ICategoryDo {
+	return c.withDO(c.DO.Clauses(conds...))
+}
+
+func (c categoryDo) Returning(value interface{}, columns ...string) ICategoryDo {
+	return c.withDO(c.DO.Returning(value, columns...))
+}
+
+func (c categoryDo) Not(conds ...gen.Condition) ICategoryDo {
+	return c.withDO(c.DO.Not(conds...))
+}
+
+func (c categoryDo) Or(conds ...gen.Condition) ICategoryDo {
+	return c.withDO(c.DO.Or(conds...))
+}
+
+func (c categoryDo) Select(conds ...field.Expr) ICategoryDo {
+	return c.withDO(c.DO.Select(conds...))
+}
+
+func (c categoryDo) Where(conds ...gen.Condition) ICategoryDo {
+	return c.withDO(c.DO.Where(conds...))
+}
+
+func (c categoryDo) Order(conds ...field.Expr) ICategoryDo {
+	return c.withDO(c.DO.Order(conds...))
+}
+
+func (c categoryDo) Distinct(cols ...field.Expr) ICategoryDo {
+	return c.withDO(c.DO.Distinct(cols...))
+}
+
+func (c categoryDo) Omit(cols ...field.Expr) ICategoryDo {
+	return c.withDO(c.DO.Omit(cols...))
+}
+
+func (c categoryDo) Join(table schema.Tabler, on ...field.Expr) ICategoryDo {
+	return c.withDO(c.DO.Join(table, on...))
+}
+
+func (c categoryDo) LeftJoin(table schema.Tabler, on ...field.Expr) ICategoryDo {
+	return c.withDO(c.DO.LeftJoin(table, on...))
+}
+
+func (c categoryDo) RightJoin(table schema.Tabler, on ...field.Expr) ICategoryDo {
+	return c.withDO(c.DO.RightJoin(table, on...))
+}
+
+func (c categoryDo) Group(cols ...field.Expr) ICategoryDo {
+	return c.withDO(c.DO.Group(cols...))
+}
+
+func (c categoryDo) Having(conds ...gen.Condition) ICategoryDo {
+	return c.withDO(c.DO.Having(conds...))
+}
+
+func (c categoryDo) Limit(limit int) ICategoryDo {
+	return c.withDO(c.DO.Limit(limit))
+}
+
+func (c categoryDo) Offset(offset int) ICategoryDo {
+	return c.withDO(c.DO.Offset(offset))
+}
+
+func (c categoryDo) Scopes(funcs ...func(gen.Dao) gen.Dao) ICategoryDo {
+	return c.withDO(c.DO.Scopes(funcs...))
+}
+
+func (c categoryDo) Unscoped() ICategoryDo {
+	return c.withDO(c.DO.Unscoped())
+}
+
+func (c categoryDo) Create(values ...*model.Category) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return c.DO.Create(values)
+}
+
+func (c categoryDo) CreateInBatches(values []*model.Category, batchSize int) error {
+	return c.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (c categoryDo) Save(values ...*model.Category) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return c.DO.Save(values)
+}
+
+func (c categoryDo) First() (*model.Category, error) {
+	if result, err := c.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Category), nil
+	}
+}
+
+func (c categoryDo) Take() (*model.Category, error) {
+	if result, err := c.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Category), nil
+	}
+}
+
+func (c categoryDo) Last() (*model.Category, error) {
+	if result, err := c.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Category), nil
+	}
+}
+
+func (c categoryDo) Find() ([]*model.Category, error) {
+	result, err := c.DO.Find()
+	return result.([]*model.Category), err
+}
+
+func (c categoryDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Category, err error) {
+	buf := make([]*model.Category, 0, batchSize)
+	err = c.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (c categoryDo) FindInBatches(result *[]*model.Category, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return c.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (c categoryDo) Attrs(attrs ...field.AssignExpr) ICategoryDo {
+	return c.withDO(c.DO.Attrs(attrs...))
+}
+
+func (c categoryDo) Assign(attrs ...field.AssignExpr) ICategoryDo {
+	return c.withDO(c.DO.Assign(attrs...))
+}
+
+func (c categoryDo) Joins(fields ...field.RelationField) ICategoryDo {
+	for _, _f := range fields {
+		c = *c.withDO(c.DO.Joins(_f))
+	}
+	return &c
+}
+
+func (c categoryDo) Preload(fields ...field.RelationField) ICategoryDo {
+	for _, _f := range fields {
+		c = *c.withDO(c.DO.Preload(_f))
+	}
+	return &c
+}
+
+func (c categoryDo) FirstOrInit() (*model.Category, error) {
+	if result, err := c.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Category), nil
+	}
+}
+
+func (c categoryDo) FirstOrCreate() (*model.Category, error) {
+	if result, err := c.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Category), nil
+	}
+}
+
+func (c categoryDo) FindByPage(offset int, limit int) (result []*model.Category, count int64, err error) {
+	result, err = c.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = c.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (c categoryDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = c.Count()
+	if err != nil {
+		return
+	}
+
+	err = c.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (c categoryDo) Scan(result interface{}) (err error) {
+	return c.DO.Scan(result)
+}
+
+func (c categoryDo) Delete(models ...*model.Category) (result gen.ResultInfo, err error) {
+	return c.DO.Delete(models)
+}
+
+func (c *categoryDo) withDO(do gen.Dao) *categoryDo {
+	c.DO = *do.(*gen.DO)
+	return c
+}

+ 417 - 0
database/dao/wechat/query/chat_records.gen.go

@@ -0,0 +1,417 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newChatRecord(db *gorm.DB, opts ...gen.DOOption) chatRecord {
+	_chatRecord := chatRecord{}
+
+	_chatRecord.chatRecordDo.UseDB(db, opts...)
+	_chatRecord.chatRecordDo.UseModel(&model.ChatRecord{})
+
+	tableName := _chatRecord.chatRecordDo.TableName()
+	_chatRecord.ALL = field.NewAsterisk(tableName)
+	_chatRecord.ID = field.NewInt64(tableName, "id")
+	_chatRecord.CreatedAt = field.NewTime(tableName, "created_at")
+	_chatRecord.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_chatRecord.DeletedAt = field.NewField(tableName, "deleted_at")
+	_chatRecord.Content = field.NewString(tableName, "content")
+	_chatRecord.ContentType = field.NewInt64(tableName, "content_type")
+	_chatRecord.SessionID = field.NewInt64(tableName, "session_id")
+	_chatRecord.UserID = field.NewInt64(tableName, "user_id")
+	_chatRecord.BotID = field.NewInt64(tableName, "bot_id")
+	_chatRecord.BotType = field.NewInt64(tableName, "bot_type")
+
+	_chatRecord.fillFieldMap()
+
+	return _chatRecord
+}
+
+// chatRecord 聊天历史记录
+type chatRecord struct {
+	chatRecordDo
+
+	ALL         field.Asterisk
+	ID          field.Int64
+	CreatedAt   field.Time   // Create Time | 创建日期
+	UpdatedAt   field.Time   // Update Time | 修改日期
+	DeletedAt   field.Field  // Delete Time | 删除日期
+	Content     field.String // 内容
+	ContentType field.Int64  // 类型:1-提问 2-回答
+	SessionID   field.Int64  // 会话ID
+	UserID      field.Int64  // 用户ID
+	BotID       field.Int64  // 聊天ID
+	BotType     field.Int64  // 用户类型:1-微信 2-小程序 3-智能体
+
+	fieldMap map[string]field.Expr
+}
+
+func (c chatRecord) Table(newTableName string) *chatRecord {
+	c.chatRecordDo.UseTable(newTableName)
+	return c.updateTableName(newTableName)
+}
+
+func (c chatRecord) As(alias string) *chatRecord {
+	c.chatRecordDo.DO = *(c.chatRecordDo.As(alias).(*gen.DO))
+	return c.updateTableName(alias)
+}
+
+func (c *chatRecord) updateTableName(table string) *chatRecord {
+	c.ALL = field.NewAsterisk(table)
+	c.ID = field.NewInt64(table, "id")
+	c.CreatedAt = field.NewTime(table, "created_at")
+	c.UpdatedAt = field.NewTime(table, "updated_at")
+	c.DeletedAt = field.NewField(table, "deleted_at")
+	c.Content = field.NewString(table, "content")
+	c.ContentType = field.NewInt64(table, "content_type")
+	c.SessionID = field.NewInt64(table, "session_id")
+	c.UserID = field.NewInt64(table, "user_id")
+	c.BotID = field.NewInt64(table, "bot_id")
+	c.BotType = field.NewInt64(table, "bot_type")
+
+	c.fillFieldMap()
+
+	return c
+}
+
+func (c *chatRecord) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := c.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (c *chatRecord) fillFieldMap() {
+	c.fieldMap = make(map[string]field.Expr, 10)
+	c.fieldMap["id"] = c.ID
+	c.fieldMap["created_at"] = c.CreatedAt
+	c.fieldMap["updated_at"] = c.UpdatedAt
+	c.fieldMap["deleted_at"] = c.DeletedAt
+	c.fieldMap["content"] = c.Content
+	c.fieldMap["content_type"] = c.ContentType
+	c.fieldMap["session_id"] = c.SessionID
+	c.fieldMap["user_id"] = c.UserID
+	c.fieldMap["bot_id"] = c.BotID
+	c.fieldMap["bot_type"] = c.BotType
+}
+
+func (c chatRecord) clone(db *gorm.DB) chatRecord {
+	c.chatRecordDo.ReplaceConnPool(db.Statement.ConnPool)
+	return c
+}
+
+func (c chatRecord) replaceDB(db *gorm.DB) chatRecord {
+	c.chatRecordDo.ReplaceDB(db)
+	return c
+}
+
+type chatRecordDo struct{ gen.DO }
+
+type IChatRecordDo interface {
+	gen.SubQuery
+	Debug() IChatRecordDo
+	WithContext(ctx context.Context) IChatRecordDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IChatRecordDo
+	WriteDB() IChatRecordDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IChatRecordDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IChatRecordDo
+	Not(conds ...gen.Condition) IChatRecordDo
+	Or(conds ...gen.Condition) IChatRecordDo
+	Select(conds ...field.Expr) IChatRecordDo
+	Where(conds ...gen.Condition) IChatRecordDo
+	Order(conds ...field.Expr) IChatRecordDo
+	Distinct(cols ...field.Expr) IChatRecordDo
+	Omit(cols ...field.Expr) IChatRecordDo
+	Join(table schema.Tabler, on ...field.Expr) IChatRecordDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IChatRecordDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IChatRecordDo
+	Group(cols ...field.Expr) IChatRecordDo
+	Having(conds ...gen.Condition) IChatRecordDo
+	Limit(limit int) IChatRecordDo
+	Offset(offset int) IChatRecordDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IChatRecordDo
+	Unscoped() IChatRecordDo
+	Create(values ...*model.ChatRecord) error
+	CreateInBatches(values []*model.ChatRecord, batchSize int) error
+	Save(values ...*model.ChatRecord) error
+	First() (*model.ChatRecord, error)
+	Take() (*model.ChatRecord, error)
+	Last() (*model.ChatRecord, error)
+	Find() ([]*model.ChatRecord, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.ChatRecord, err error)
+	FindInBatches(result *[]*model.ChatRecord, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.ChatRecord) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IChatRecordDo
+	Assign(attrs ...field.AssignExpr) IChatRecordDo
+	Joins(fields ...field.RelationField) IChatRecordDo
+	Preload(fields ...field.RelationField) IChatRecordDo
+	FirstOrInit() (*model.ChatRecord, error)
+	FirstOrCreate() (*model.ChatRecord, error)
+	FindByPage(offset int, limit int) (result []*model.ChatRecord, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IChatRecordDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (c chatRecordDo) Debug() IChatRecordDo {
+	return c.withDO(c.DO.Debug())
+}
+
+func (c chatRecordDo) WithContext(ctx context.Context) IChatRecordDo {
+	return c.withDO(c.DO.WithContext(ctx))
+}
+
+func (c chatRecordDo) ReadDB() IChatRecordDo {
+	return c.Clauses(dbresolver.Read)
+}
+
+func (c chatRecordDo) WriteDB() IChatRecordDo {
+	return c.Clauses(dbresolver.Write)
+}
+
+func (c chatRecordDo) Session(config *gorm.Session) IChatRecordDo {
+	return c.withDO(c.DO.Session(config))
+}
+
+func (c chatRecordDo) Clauses(conds ...clause.Expression) IChatRecordDo {
+	return c.withDO(c.DO.Clauses(conds...))
+}
+
+func (c chatRecordDo) Returning(value interface{}, columns ...string) IChatRecordDo {
+	return c.withDO(c.DO.Returning(value, columns...))
+}
+
+func (c chatRecordDo) Not(conds ...gen.Condition) IChatRecordDo {
+	return c.withDO(c.DO.Not(conds...))
+}
+
+func (c chatRecordDo) Or(conds ...gen.Condition) IChatRecordDo {
+	return c.withDO(c.DO.Or(conds...))
+}
+
+func (c chatRecordDo) Select(conds ...field.Expr) IChatRecordDo {
+	return c.withDO(c.DO.Select(conds...))
+}
+
+func (c chatRecordDo) Where(conds ...gen.Condition) IChatRecordDo {
+	return c.withDO(c.DO.Where(conds...))
+}
+
+func (c chatRecordDo) Order(conds ...field.Expr) IChatRecordDo {
+	return c.withDO(c.DO.Order(conds...))
+}
+
+func (c chatRecordDo) Distinct(cols ...field.Expr) IChatRecordDo {
+	return c.withDO(c.DO.Distinct(cols...))
+}
+
+func (c chatRecordDo) Omit(cols ...field.Expr) IChatRecordDo {
+	return c.withDO(c.DO.Omit(cols...))
+}
+
+func (c chatRecordDo) Join(table schema.Tabler, on ...field.Expr) IChatRecordDo {
+	return c.withDO(c.DO.Join(table, on...))
+}
+
+func (c chatRecordDo) LeftJoin(table schema.Tabler, on ...field.Expr) IChatRecordDo {
+	return c.withDO(c.DO.LeftJoin(table, on...))
+}
+
+func (c chatRecordDo) RightJoin(table schema.Tabler, on ...field.Expr) IChatRecordDo {
+	return c.withDO(c.DO.RightJoin(table, on...))
+}
+
+func (c chatRecordDo) Group(cols ...field.Expr) IChatRecordDo {
+	return c.withDO(c.DO.Group(cols...))
+}
+
+func (c chatRecordDo) Having(conds ...gen.Condition) IChatRecordDo {
+	return c.withDO(c.DO.Having(conds...))
+}
+
+func (c chatRecordDo) Limit(limit int) IChatRecordDo {
+	return c.withDO(c.DO.Limit(limit))
+}
+
+func (c chatRecordDo) Offset(offset int) IChatRecordDo {
+	return c.withDO(c.DO.Offset(offset))
+}
+
+func (c chatRecordDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IChatRecordDo {
+	return c.withDO(c.DO.Scopes(funcs...))
+}
+
+func (c chatRecordDo) Unscoped() IChatRecordDo {
+	return c.withDO(c.DO.Unscoped())
+}
+
+func (c chatRecordDo) Create(values ...*model.ChatRecord) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return c.DO.Create(values)
+}
+
+func (c chatRecordDo) CreateInBatches(values []*model.ChatRecord, batchSize int) error {
+	return c.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (c chatRecordDo) Save(values ...*model.ChatRecord) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return c.DO.Save(values)
+}
+
+func (c chatRecordDo) First() (*model.ChatRecord, error) {
+	if result, err := c.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.ChatRecord), nil
+	}
+}
+
+func (c chatRecordDo) Take() (*model.ChatRecord, error) {
+	if result, err := c.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.ChatRecord), nil
+	}
+}
+
+func (c chatRecordDo) Last() (*model.ChatRecord, error) {
+	if result, err := c.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.ChatRecord), nil
+	}
+}
+
+func (c chatRecordDo) Find() ([]*model.ChatRecord, error) {
+	result, err := c.DO.Find()
+	return result.([]*model.ChatRecord), err
+}
+
+func (c chatRecordDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.ChatRecord, err error) {
+	buf := make([]*model.ChatRecord, 0, batchSize)
+	err = c.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (c chatRecordDo) FindInBatches(result *[]*model.ChatRecord, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return c.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (c chatRecordDo) Attrs(attrs ...field.AssignExpr) IChatRecordDo {
+	return c.withDO(c.DO.Attrs(attrs...))
+}
+
+func (c chatRecordDo) Assign(attrs ...field.AssignExpr) IChatRecordDo {
+	return c.withDO(c.DO.Assign(attrs...))
+}
+
+func (c chatRecordDo) Joins(fields ...field.RelationField) IChatRecordDo {
+	for _, _f := range fields {
+		c = *c.withDO(c.DO.Joins(_f))
+	}
+	return &c
+}
+
+func (c chatRecordDo) Preload(fields ...field.RelationField) IChatRecordDo {
+	for _, _f := range fields {
+		c = *c.withDO(c.DO.Preload(_f))
+	}
+	return &c
+}
+
+func (c chatRecordDo) FirstOrInit() (*model.ChatRecord, error) {
+	if result, err := c.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.ChatRecord), nil
+	}
+}
+
+func (c chatRecordDo) FirstOrCreate() (*model.ChatRecord, error) {
+	if result, err := c.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.ChatRecord), nil
+	}
+}
+
+func (c chatRecordDo) FindByPage(offset int, limit int) (result []*model.ChatRecord, count int64, err error) {
+	result, err = c.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = c.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (c chatRecordDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = c.Count()
+	if err != nil {
+		return
+	}
+
+	err = c.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (c chatRecordDo) Scan(result interface{}) (err error) {
+	return c.DO.Scan(result)
+}
+
+func (c chatRecordDo) Delete(models ...*model.ChatRecord) (result gen.ResultInfo, err error) {
+	return c.DO.Delete(models)
+}
+
+func (c *chatRecordDo) withDO(do gen.Dao) *chatRecordDo {
+	c.DO = *do.(*gen.DO)
+	return c
+}

+ 409 - 0
database/dao/wechat/query/chat_session.gen.go

@@ -0,0 +1,409 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newChatSession(db *gorm.DB, opts ...gen.DOOption) chatSession {
+	_chatSession := chatSession{}
+
+	_chatSession.chatSessionDo.UseDB(db, opts...)
+	_chatSession.chatSessionDo.UseModel(&model.ChatSession{})
+
+	tableName := _chatSession.chatSessionDo.TableName()
+	_chatSession.ALL = field.NewAsterisk(tableName)
+	_chatSession.ID = field.NewInt64(tableName, "id")
+	_chatSession.CreatedAt = field.NewTime(tableName, "created_at")
+	_chatSession.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_chatSession.DeletedAt = field.NewField(tableName, "deleted_at")
+	_chatSession.Name = field.NewString(tableName, "name")
+	_chatSession.UserID = field.NewInt64(tableName, "user_id")
+	_chatSession.BotID = field.NewInt64(tableName, "bot_id")
+	_chatSession.BotType = field.NewInt64(tableName, "bot_type")
+
+	_chatSession.fillFieldMap()
+
+	return _chatSession
+}
+
+// chatSession 聊天会话表
+type chatSession struct {
+	chatSessionDo
+
+	ALL       field.Asterisk
+	ID        field.Int64
+	CreatedAt field.Time   // Create Time | 创建日期
+	UpdatedAt field.Time   // Update Time | 修改日期
+	DeletedAt field.Field  // Delete Time | 删除日期
+	Name      field.String // 会话名称
+	UserID    field.Int64  // 用户ID
+	BotID     field.Int64  // 聊天 ID
+	BotType   field.Int64  // 类型:1-微信 2-小程序 3-智能体
+
+	fieldMap map[string]field.Expr
+}
+
+func (c chatSession) Table(newTableName string) *chatSession {
+	c.chatSessionDo.UseTable(newTableName)
+	return c.updateTableName(newTableName)
+}
+
+func (c chatSession) As(alias string) *chatSession {
+	c.chatSessionDo.DO = *(c.chatSessionDo.As(alias).(*gen.DO))
+	return c.updateTableName(alias)
+}
+
+func (c *chatSession) updateTableName(table string) *chatSession {
+	c.ALL = field.NewAsterisk(table)
+	c.ID = field.NewInt64(table, "id")
+	c.CreatedAt = field.NewTime(table, "created_at")
+	c.UpdatedAt = field.NewTime(table, "updated_at")
+	c.DeletedAt = field.NewField(table, "deleted_at")
+	c.Name = field.NewString(table, "name")
+	c.UserID = field.NewInt64(table, "user_id")
+	c.BotID = field.NewInt64(table, "bot_id")
+	c.BotType = field.NewInt64(table, "bot_type")
+
+	c.fillFieldMap()
+
+	return c
+}
+
+func (c *chatSession) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := c.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (c *chatSession) fillFieldMap() {
+	c.fieldMap = make(map[string]field.Expr, 8)
+	c.fieldMap["id"] = c.ID
+	c.fieldMap["created_at"] = c.CreatedAt
+	c.fieldMap["updated_at"] = c.UpdatedAt
+	c.fieldMap["deleted_at"] = c.DeletedAt
+	c.fieldMap["name"] = c.Name
+	c.fieldMap["user_id"] = c.UserID
+	c.fieldMap["bot_id"] = c.BotID
+	c.fieldMap["bot_type"] = c.BotType
+}
+
+func (c chatSession) clone(db *gorm.DB) chatSession {
+	c.chatSessionDo.ReplaceConnPool(db.Statement.ConnPool)
+	return c
+}
+
+func (c chatSession) replaceDB(db *gorm.DB) chatSession {
+	c.chatSessionDo.ReplaceDB(db)
+	return c
+}
+
+type chatSessionDo struct{ gen.DO }
+
+type IChatSessionDo interface {
+	gen.SubQuery
+	Debug() IChatSessionDo
+	WithContext(ctx context.Context) IChatSessionDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IChatSessionDo
+	WriteDB() IChatSessionDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IChatSessionDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IChatSessionDo
+	Not(conds ...gen.Condition) IChatSessionDo
+	Or(conds ...gen.Condition) IChatSessionDo
+	Select(conds ...field.Expr) IChatSessionDo
+	Where(conds ...gen.Condition) IChatSessionDo
+	Order(conds ...field.Expr) IChatSessionDo
+	Distinct(cols ...field.Expr) IChatSessionDo
+	Omit(cols ...field.Expr) IChatSessionDo
+	Join(table schema.Tabler, on ...field.Expr) IChatSessionDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IChatSessionDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IChatSessionDo
+	Group(cols ...field.Expr) IChatSessionDo
+	Having(conds ...gen.Condition) IChatSessionDo
+	Limit(limit int) IChatSessionDo
+	Offset(offset int) IChatSessionDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IChatSessionDo
+	Unscoped() IChatSessionDo
+	Create(values ...*model.ChatSession) error
+	CreateInBatches(values []*model.ChatSession, batchSize int) error
+	Save(values ...*model.ChatSession) error
+	First() (*model.ChatSession, error)
+	Take() (*model.ChatSession, error)
+	Last() (*model.ChatSession, error)
+	Find() ([]*model.ChatSession, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.ChatSession, err error)
+	FindInBatches(result *[]*model.ChatSession, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.ChatSession) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IChatSessionDo
+	Assign(attrs ...field.AssignExpr) IChatSessionDo
+	Joins(fields ...field.RelationField) IChatSessionDo
+	Preload(fields ...field.RelationField) IChatSessionDo
+	FirstOrInit() (*model.ChatSession, error)
+	FirstOrCreate() (*model.ChatSession, error)
+	FindByPage(offset int, limit int) (result []*model.ChatSession, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IChatSessionDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (c chatSessionDo) Debug() IChatSessionDo {
+	return c.withDO(c.DO.Debug())
+}
+
+func (c chatSessionDo) WithContext(ctx context.Context) IChatSessionDo {
+	return c.withDO(c.DO.WithContext(ctx))
+}
+
+func (c chatSessionDo) ReadDB() IChatSessionDo {
+	return c.Clauses(dbresolver.Read)
+}
+
+func (c chatSessionDo) WriteDB() IChatSessionDo {
+	return c.Clauses(dbresolver.Write)
+}
+
+func (c chatSessionDo) Session(config *gorm.Session) IChatSessionDo {
+	return c.withDO(c.DO.Session(config))
+}
+
+func (c chatSessionDo) Clauses(conds ...clause.Expression) IChatSessionDo {
+	return c.withDO(c.DO.Clauses(conds...))
+}
+
+func (c chatSessionDo) Returning(value interface{}, columns ...string) IChatSessionDo {
+	return c.withDO(c.DO.Returning(value, columns...))
+}
+
+func (c chatSessionDo) Not(conds ...gen.Condition) IChatSessionDo {
+	return c.withDO(c.DO.Not(conds...))
+}
+
+func (c chatSessionDo) Or(conds ...gen.Condition) IChatSessionDo {
+	return c.withDO(c.DO.Or(conds...))
+}
+
+func (c chatSessionDo) Select(conds ...field.Expr) IChatSessionDo {
+	return c.withDO(c.DO.Select(conds...))
+}
+
+func (c chatSessionDo) Where(conds ...gen.Condition) IChatSessionDo {
+	return c.withDO(c.DO.Where(conds...))
+}
+
+func (c chatSessionDo) Order(conds ...field.Expr) IChatSessionDo {
+	return c.withDO(c.DO.Order(conds...))
+}
+
+func (c chatSessionDo) Distinct(cols ...field.Expr) IChatSessionDo {
+	return c.withDO(c.DO.Distinct(cols...))
+}
+
+func (c chatSessionDo) Omit(cols ...field.Expr) IChatSessionDo {
+	return c.withDO(c.DO.Omit(cols...))
+}
+
+func (c chatSessionDo) Join(table schema.Tabler, on ...field.Expr) IChatSessionDo {
+	return c.withDO(c.DO.Join(table, on...))
+}
+
+func (c chatSessionDo) LeftJoin(table schema.Tabler, on ...field.Expr) IChatSessionDo {
+	return c.withDO(c.DO.LeftJoin(table, on...))
+}
+
+func (c chatSessionDo) RightJoin(table schema.Tabler, on ...field.Expr) IChatSessionDo {
+	return c.withDO(c.DO.RightJoin(table, on...))
+}
+
+func (c chatSessionDo) Group(cols ...field.Expr) IChatSessionDo {
+	return c.withDO(c.DO.Group(cols...))
+}
+
+func (c chatSessionDo) Having(conds ...gen.Condition) IChatSessionDo {
+	return c.withDO(c.DO.Having(conds...))
+}
+
+func (c chatSessionDo) Limit(limit int) IChatSessionDo {
+	return c.withDO(c.DO.Limit(limit))
+}
+
+func (c chatSessionDo) Offset(offset int) IChatSessionDo {
+	return c.withDO(c.DO.Offset(offset))
+}
+
+func (c chatSessionDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IChatSessionDo {
+	return c.withDO(c.DO.Scopes(funcs...))
+}
+
+func (c chatSessionDo) Unscoped() IChatSessionDo {
+	return c.withDO(c.DO.Unscoped())
+}
+
+func (c chatSessionDo) Create(values ...*model.ChatSession) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return c.DO.Create(values)
+}
+
+func (c chatSessionDo) CreateInBatches(values []*model.ChatSession, batchSize int) error {
+	return c.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (c chatSessionDo) Save(values ...*model.ChatSession) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return c.DO.Save(values)
+}
+
+func (c chatSessionDo) First() (*model.ChatSession, error) {
+	if result, err := c.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.ChatSession), nil
+	}
+}
+
+func (c chatSessionDo) Take() (*model.ChatSession, error) {
+	if result, err := c.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.ChatSession), nil
+	}
+}
+
+func (c chatSessionDo) Last() (*model.ChatSession, error) {
+	if result, err := c.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.ChatSession), nil
+	}
+}
+
+func (c chatSessionDo) Find() ([]*model.ChatSession, error) {
+	result, err := c.DO.Find()
+	return result.([]*model.ChatSession), err
+}
+
+func (c chatSessionDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.ChatSession, err error) {
+	buf := make([]*model.ChatSession, 0, batchSize)
+	err = c.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (c chatSessionDo) FindInBatches(result *[]*model.ChatSession, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return c.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (c chatSessionDo) Attrs(attrs ...field.AssignExpr) IChatSessionDo {
+	return c.withDO(c.DO.Attrs(attrs...))
+}
+
+func (c chatSessionDo) Assign(attrs ...field.AssignExpr) IChatSessionDo {
+	return c.withDO(c.DO.Assign(attrs...))
+}
+
+func (c chatSessionDo) Joins(fields ...field.RelationField) IChatSessionDo {
+	for _, _f := range fields {
+		c = *c.withDO(c.DO.Joins(_f))
+	}
+	return &c
+}
+
+func (c chatSessionDo) Preload(fields ...field.RelationField) IChatSessionDo {
+	for _, _f := range fields {
+		c = *c.withDO(c.DO.Preload(_f))
+	}
+	return &c
+}
+
+func (c chatSessionDo) FirstOrInit() (*model.ChatSession, error) {
+	if result, err := c.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.ChatSession), nil
+	}
+}
+
+func (c chatSessionDo) FirstOrCreate() (*model.ChatSession, error) {
+	if result, err := c.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.ChatSession), nil
+	}
+}
+
+func (c chatSessionDo) FindByPage(offset int, limit int) (result []*model.ChatSession, count int64, err error) {
+	result, err = c.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = c.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (c chatSessionDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = c.Count()
+	if err != nil {
+		return
+	}
+
+	err = c.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (c chatSessionDo) Scan(result interface{}) (err error) {
+	return c.DO.Scan(result)
+}
+
+func (c chatSessionDo) Delete(models ...*model.ChatSession) (result gen.ResultInfo, err error) {
+	return c.DO.Delete(models)
+}
+
+func (c *chatSessionDo) withDO(do gen.Dao) *chatSessionDo {
+	c.DO = *do.(*gen.DO)
+	return c
+}

+ 500 - 0
database/dao/wechat/query/contact.gen.go

@@ -0,0 +1,500 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newContact(db *gorm.DB, opts ...gen.DOOption) contact {
+	_contact := contact{}
+
+	_contact.contactDo.UseDB(db, opts...)
+	_contact.contactDo.UseModel(&model.Contact{})
+
+	tableName := _contact.contactDo.TableName()
+	_contact.ALL = field.NewAsterisk(tableName)
+	_contact.ID = field.NewInt64(tableName, "id")
+	_contact.CreatedAt = field.NewTime(tableName, "created_at")
+	_contact.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_contact.Status = field.NewInt64(tableName, "status")
+	_contact.DeletedAt = field.NewField(tableName, "deleted_at")
+	_contact.WxWxid = field.NewString(tableName, "wx_wxid")
+	_contact.Type = field.NewInt64(tableName, "type")
+	_contact.Wxid = field.NewString(tableName, "wxid")
+	_contact.Account = field.NewString(tableName, "account")
+	_contact.Nickname = field.NewString(tableName, "nickname")
+	_contact.Markname = field.NewString(tableName, "markname")
+	_contact.Headimg = field.NewString(tableName, "headimg")
+	_contact.Sex = field.NewInt64(tableName, "sex")
+	_contact.Starrole = field.NewString(tableName, "starrole")
+	_contact.Dontseeit = field.NewInt64(tableName, "dontseeit")
+	_contact.Dontseeme = field.NewInt64(tableName, "dontseeme")
+	_contact.Lag = field.NewString(tableName, "lag")
+	_contact.Gid = field.NewString(tableName, "gid")
+	_contact.Gname = field.NewString(tableName, "gname")
+	_contact.V3 = field.NewString(tableName, "v3")
+	_contact.OrganizationID = field.NewInt64(tableName, "organization_id")
+	_contact.Ctype = field.NewInt64(tableName, "ctype")
+	_contact.Cc = field.NewString(tableName, "cc")
+	_contact.Phone = field.NewString(tableName, "phone")
+	_contact.Cname = field.NewString(tableName, "cname")
+	_contact.Cage = field.NewInt64(tableName, "cage")
+	_contact.Carea = field.NewString(tableName, "carea")
+	_contact.Cbirthday = field.NewString(tableName, "cbirthday")
+	_contact.Cbirtharea = field.NewString(tableName, "cbirtharea")
+	_contact.CidcardNo = field.NewString(tableName, "cidcard_no")
+	_contact.Ctitle = field.NewString(tableName, "ctitle")
+
+	_contact.fillFieldMap()
+
+	return _contact
+}
+
+type contact struct {
+	contactDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	Status         field.Int64  // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	WxWxid         field.String // 属主微信id
+	Type           field.Int64  // 联系人类型:1好友,2群组,3公众号,4企业微信联系人
+	Wxid           field.String // 微信id 公众号微信ID
+	Account        field.String // 微信账号
+	Nickname       field.String // 微信昵称 群备注名称
+	Markname       field.String // 备注名
+	Headimg        field.String // 头像
+	Sex            field.Int64  // 性别 0未知 1男 2女
+	Starrole       field.String // 星标 65/67=星标 1/3=未星标
+	Dontseeit      field.Int64  // 不让他看我的朋友圈 0可以看 1不让看
+	Dontseeme      field.Int64  // 不看他的朋友圈 0可以看 1不看 1=开启了不看他 128/129=仅聊天
+	Lag            field.String // 所属标签id清单,多开会用逗号隔开
+	Gid            field.String // 群组id
+	Gname          field.String // 群组名称
+	V3             field.String // v3数据
+	OrganizationID field.Int64  // 机构 ID
+	Ctype          field.Int64  // 内容类型:1-微信 2-whatsapp 3-企微
+	Cc             field.String // 国家区号
+	Phone          field.String // 手机号
+	Cname          field.String // 姓名
+	Cage           field.Int64  // 年龄
+	Carea          field.String // 地区
+	Cbirthday      field.String // 出生日期
+	Cbirtharea     field.String // 出生地
+	CidcardNo      field.String // 身份证号
+	Ctitle         field.String // 称呼
+
+	fieldMap map[string]field.Expr
+}
+
+func (c contact) Table(newTableName string) *contact {
+	c.contactDo.UseTable(newTableName)
+	return c.updateTableName(newTableName)
+}
+
+func (c contact) As(alias string) *contact {
+	c.contactDo.DO = *(c.contactDo.As(alias).(*gen.DO))
+	return c.updateTableName(alias)
+}
+
+func (c *contact) updateTableName(table string) *contact {
+	c.ALL = field.NewAsterisk(table)
+	c.ID = field.NewInt64(table, "id")
+	c.CreatedAt = field.NewTime(table, "created_at")
+	c.UpdatedAt = field.NewTime(table, "updated_at")
+	c.Status = field.NewInt64(table, "status")
+	c.DeletedAt = field.NewField(table, "deleted_at")
+	c.WxWxid = field.NewString(table, "wx_wxid")
+	c.Type = field.NewInt64(table, "type")
+	c.Wxid = field.NewString(table, "wxid")
+	c.Account = field.NewString(table, "account")
+	c.Nickname = field.NewString(table, "nickname")
+	c.Markname = field.NewString(table, "markname")
+	c.Headimg = field.NewString(table, "headimg")
+	c.Sex = field.NewInt64(table, "sex")
+	c.Starrole = field.NewString(table, "starrole")
+	c.Dontseeit = field.NewInt64(table, "dontseeit")
+	c.Dontseeme = field.NewInt64(table, "dontseeme")
+	c.Lag = field.NewString(table, "lag")
+	c.Gid = field.NewString(table, "gid")
+	c.Gname = field.NewString(table, "gname")
+	c.V3 = field.NewString(table, "v3")
+	c.OrganizationID = field.NewInt64(table, "organization_id")
+	c.Ctype = field.NewInt64(table, "ctype")
+	c.Cc = field.NewString(table, "cc")
+	c.Phone = field.NewString(table, "phone")
+	c.Cname = field.NewString(table, "cname")
+	c.Cage = field.NewInt64(table, "cage")
+	c.Carea = field.NewString(table, "carea")
+	c.Cbirthday = field.NewString(table, "cbirthday")
+	c.Cbirtharea = field.NewString(table, "cbirtharea")
+	c.CidcardNo = field.NewString(table, "cidcard_no")
+	c.Ctitle = field.NewString(table, "ctitle")
+
+	c.fillFieldMap()
+
+	return c
+}
+
+func (c *contact) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := c.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (c *contact) fillFieldMap() {
+	c.fieldMap = make(map[string]field.Expr, 31)
+	c.fieldMap["id"] = c.ID
+	c.fieldMap["created_at"] = c.CreatedAt
+	c.fieldMap["updated_at"] = c.UpdatedAt
+	c.fieldMap["status"] = c.Status
+	c.fieldMap["deleted_at"] = c.DeletedAt
+	c.fieldMap["wx_wxid"] = c.WxWxid
+	c.fieldMap["type"] = c.Type
+	c.fieldMap["wxid"] = c.Wxid
+	c.fieldMap["account"] = c.Account
+	c.fieldMap["nickname"] = c.Nickname
+	c.fieldMap["markname"] = c.Markname
+	c.fieldMap["headimg"] = c.Headimg
+	c.fieldMap["sex"] = c.Sex
+	c.fieldMap["starrole"] = c.Starrole
+	c.fieldMap["dontseeit"] = c.Dontseeit
+	c.fieldMap["dontseeme"] = c.Dontseeme
+	c.fieldMap["lag"] = c.Lag
+	c.fieldMap["gid"] = c.Gid
+	c.fieldMap["gname"] = c.Gname
+	c.fieldMap["v3"] = c.V3
+	c.fieldMap["organization_id"] = c.OrganizationID
+	c.fieldMap["ctype"] = c.Ctype
+	c.fieldMap["cc"] = c.Cc
+	c.fieldMap["phone"] = c.Phone
+	c.fieldMap["cname"] = c.Cname
+	c.fieldMap["cage"] = c.Cage
+	c.fieldMap["carea"] = c.Carea
+	c.fieldMap["cbirthday"] = c.Cbirthday
+	c.fieldMap["cbirtharea"] = c.Cbirtharea
+	c.fieldMap["cidcard_no"] = c.CidcardNo
+	c.fieldMap["ctitle"] = c.Ctitle
+}
+
+func (c contact) clone(db *gorm.DB) contact {
+	c.contactDo.ReplaceConnPool(db.Statement.ConnPool)
+	return c
+}
+
+func (c contact) replaceDB(db *gorm.DB) contact {
+	c.contactDo.ReplaceDB(db)
+	return c
+}
+
+type contactDo struct{ gen.DO }
+
+type IContactDo interface {
+	gen.SubQuery
+	Debug() IContactDo
+	WithContext(ctx context.Context) IContactDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IContactDo
+	WriteDB() IContactDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IContactDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IContactDo
+	Not(conds ...gen.Condition) IContactDo
+	Or(conds ...gen.Condition) IContactDo
+	Select(conds ...field.Expr) IContactDo
+	Where(conds ...gen.Condition) IContactDo
+	Order(conds ...field.Expr) IContactDo
+	Distinct(cols ...field.Expr) IContactDo
+	Omit(cols ...field.Expr) IContactDo
+	Join(table schema.Tabler, on ...field.Expr) IContactDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IContactDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IContactDo
+	Group(cols ...field.Expr) IContactDo
+	Having(conds ...gen.Condition) IContactDo
+	Limit(limit int) IContactDo
+	Offset(offset int) IContactDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IContactDo
+	Unscoped() IContactDo
+	Create(values ...*model.Contact) error
+	CreateInBatches(values []*model.Contact, batchSize int) error
+	Save(values ...*model.Contact) error
+	First() (*model.Contact, error)
+	Take() (*model.Contact, error)
+	Last() (*model.Contact, error)
+	Find() ([]*model.Contact, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Contact, err error)
+	FindInBatches(result *[]*model.Contact, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.Contact) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IContactDo
+	Assign(attrs ...field.AssignExpr) IContactDo
+	Joins(fields ...field.RelationField) IContactDo
+	Preload(fields ...field.RelationField) IContactDo
+	FirstOrInit() (*model.Contact, error)
+	FirstOrCreate() (*model.Contact, error)
+	FindByPage(offset int, limit int) (result []*model.Contact, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IContactDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (c contactDo) Debug() IContactDo {
+	return c.withDO(c.DO.Debug())
+}
+
+func (c contactDo) WithContext(ctx context.Context) IContactDo {
+	return c.withDO(c.DO.WithContext(ctx))
+}
+
+func (c contactDo) ReadDB() IContactDo {
+	return c.Clauses(dbresolver.Read)
+}
+
+func (c contactDo) WriteDB() IContactDo {
+	return c.Clauses(dbresolver.Write)
+}
+
+func (c contactDo) Session(config *gorm.Session) IContactDo {
+	return c.withDO(c.DO.Session(config))
+}
+
+func (c contactDo) Clauses(conds ...clause.Expression) IContactDo {
+	return c.withDO(c.DO.Clauses(conds...))
+}
+
+func (c contactDo) Returning(value interface{}, columns ...string) IContactDo {
+	return c.withDO(c.DO.Returning(value, columns...))
+}
+
+func (c contactDo) Not(conds ...gen.Condition) IContactDo {
+	return c.withDO(c.DO.Not(conds...))
+}
+
+func (c contactDo) Or(conds ...gen.Condition) IContactDo {
+	return c.withDO(c.DO.Or(conds...))
+}
+
+func (c contactDo) Select(conds ...field.Expr) IContactDo {
+	return c.withDO(c.DO.Select(conds...))
+}
+
+func (c contactDo) Where(conds ...gen.Condition) IContactDo {
+	return c.withDO(c.DO.Where(conds...))
+}
+
+func (c contactDo) Order(conds ...field.Expr) IContactDo {
+	return c.withDO(c.DO.Order(conds...))
+}
+
+func (c contactDo) Distinct(cols ...field.Expr) IContactDo {
+	return c.withDO(c.DO.Distinct(cols...))
+}
+
+func (c contactDo) Omit(cols ...field.Expr) IContactDo {
+	return c.withDO(c.DO.Omit(cols...))
+}
+
+func (c contactDo) Join(table schema.Tabler, on ...field.Expr) IContactDo {
+	return c.withDO(c.DO.Join(table, on...))
+}
+
+func (c contactDo) LeftJoin(table schema.Tabler, on ...field.Expr) IContactDo {
+	return c.withDO(c.DO.LeftJoin(table, on...))
+}
+
+func (c contactDo) RightJoin(table schema.Tabler, on ...field.Expr) IContactDo {
+	return c.withDO(c.DO.RightJoin(table, on...))
+}
+
+func (c contactDo) Group(cols ...field.Expr) IContactDo {
+	return c.withDO(c.DO.Group(cols...))
+}
+
+func (c contactDo) Having(conds ...gen.Condition) IContactDo {
+	return c.withDO(c.DO.Having(conds...))
+}
+
+func (c contactDo) Limit(limit int) IContactDo {
+	return c.withDO(c.DO.Limit(limit))
+}
+
+func (c contactDo) Offset(offset int) IContactDo {
+	return c.withDO(c.DO.Offset(offset))
+}
+
+func (c contactDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IContactDo {
+	return c.withDO(c.DO.Scopes(funcs...))
+}
+
+func (c contactDo) Unscoped() IContactDo {
+	return c.withDO(c.DO.Unscoped())
+}
+
+func (c contactDo) Create(values ...*model.Contact) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return c.DO.Create(values)
+}
+
+func (c contactDo) CreateInBatches(values []*model.Contact, batchSize int) error {
+	return c.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (c contactDo) Save(values ...*model.Contact) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return c.DO.Save(values)
+}
+
+func (c contactDo) First() (*model.Contact, error) {
+	if result, err := c.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Contact), nil
+	}
+}
+
+func (c contactDo) Take() (*model.Contact, error) {
+	if result, err := c.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Contact), nil
+	}
+}
+
+func (c contactDo) Last() (*model.Contact, error) {
+	if result, err := c.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Contact), nil
+	}
+}
+
+func (c contactDo) Find() ([]*model.Contact, error) {
+	result, err := c.DO.Find()
+	return result.([]*model.Contact), err
+}
+
+func (c contactDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Contact, err error) {
+	buf := make([]*model.Contact, 0, batchSize)
+	err = c.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (c contactDo) FindInBatches(result *[]*model.Contact, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return c.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (c contactDo) Attrs(attrs ...field.AssignExpr) IContactDo {
+	return c.withDO(c.DO.Attrs(attrs...))
+}
+
+func (c contactDo) Assign(attrs ...field.AssignExpr) IContactDo {
+	return c.withDO(c.DO.Assign(attrs...))
+}
+
+func (c contactDo) Joins(fields ...field.RelationField) IContactDo {
+	for _, _f := range fields {
+		c = *c.withDO(c.DO.Joins(_f))
+	}
+	return &c
+}
+
+func (c contactDo) Preload(fields ...field.RelationField) IContactDo {
+	for _, _f := range fields {
+		c = *c.withDO(c.DO.Preload(_f))
+	}
+	return &c
+}
+
+func (c contactDo) FirstOrInit() (*model.Contact, error) {
+	if result, err := c.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Contact), nil
+	}
+}
+
+func (c contactDo) FirstOrCreate() (*model.Contact, error) {
+	if result, err := c.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Contact), nil
+	}
+}
+
+func (c contactDo) FindByPage(offset int, limit int) (result []*model.Contact, count int64, err error) {
+	result, err = c.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = c.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (c contactDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = c.Count()
+	if err != nil {
+		return
+	}
+
+	err = c.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (c contactDo) Scan(result interface{}) (err error) {
+	return c.DO.Scan(result)
+}
+
+func (c contactDo) Delete(models ...*model.Contact) (result gen.ResultInfo, err error) {
+	return c.DO.Delete(models)
+}
+
+func (c *contactDo) withDO(do gen.Dao) *contactDo {
+	c.DO = *do.(*gen.DO)
+	return c
+}

+ 409 - 0
database/dao/wechat/query/credit_balance.gen.go

@@ -0,0 +1,409 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newCreditBalance(db *gorm.DB, opts ...gen.DOOption) creditBalance {
+	_creditBalance := creditBalance{}
+
+	_creditBalance.creditBalanceDo.UseDB(db, opts...)
+	_creditBalance.creditBalanceDo.UseModel(&model.CreditBalance{})
+
+	tableName := _creditBalance.creditBalanceDo.TableName()
+	_creditBalance.ALL = field.NewAsterisk(tableName)
+	_creditBalance.ID = field.NewInt64(tableName, "id")
+	_creditBalance.CreatedAt = field.NewTime(tableName, "created_at")
+	_creditBalance.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_creditBalance.Status = field.NewInt64(tableName, "status")
+	_creditBalance.DeletedAt = field.NewField(tableName, "deleted_at")
+	_creditBalance.UserID = field.NewString(tableName, "user_id")
+	_creditBalance.Balance = field.NewField(tableName, "balance")
+	_creditBalance.OrganizationID = field.NewInt64(tableName, "organization_id")
+
+	_creditBalance.fillFieldMap()
+
+	return _creditBalance
+}
+
+// creditBalance 积分余额表
+type creditBalance struct {
+	creditBalanceDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	Status         field.Int64  // 状态 1 正常 2 禁用
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	UserID         field.String // 用户ID
+	Balance        field.Field  // 积分余额
+	OrganizationID field.Int64  // 机构 ID
+
+	fieldMap map[string]field.Expr
+}
+
+func (c creditBalance) Table(newTableName string) *creditBalance {
+	c.creditBalanceDo.UseTable(newTableName)
+	return c.updateTableName(newTableName)
+}
+
+func (c creditBalance) As(alias string) *creditBalance {
+	c.creditBalanceDo.DO = *(c.creditBalanceDo.As(alias).(*gen.DO))
+	return c.updateTableName(alias)
+}
+
+func (c *creditBalance) updateTableName(table string) *creditBalance {
+	c.ALL = field.NewAsterisk(table)
+	c.ID = field.NewInt64(table, "id")
+	c.CreatedAt = field.NewTime(table, "created_at")
+	c.UpdatedAt = field.NewTime(table, "updated_at")
+	c.Status = field.NewInt64(table, "status")
+	c.DeletedAt = field.NewField(table, "deleted_at")
+	c.UserID = field.NewString(table, "user_id")
+	c.Balance = field.NewField(table, "balance")
+	c.OrganizationID = field.NewInt64(table, "organization_id")
+
+	c.fillFieldMap()
+
+	return c
+}
+
+func (c *creditBalance) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := c.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (c *creditBalance) fillFieldMap() {
+	c.fieldMap = make(map[string]field.Expr, 8)
+	c.fieldMap["id"] = c.ID
+	c.fieldMap["created_at"] = c.CreatedAt
+	c.fieldMap["updated_at"] = c.UpdatedAt
+	c.fieldMap["status"] = c.Status
+	c.fieldMap["deleted_at"] = c.DeletedAt
+	c.fieldMap["user_id"] = c.UserID
+	c.fieldMap["balance"] = c.Balance
+	c.fieldMap["organization_id"] = c.OrganizationID
+}
+
+func (c creditBalance) clone(db *gorm.DB) creditBalance {
+	c.creditBalanceDo.ReplaceConnPool(db.Statement.ConnPool)
+	return c
+}
+
+func (c creditBalance) replaceDB(db *gorm.DB) creditBalance {
+	c.creditBalanceDo.ReplaceDB(db)
+	return c
+}
+
+type creditBalanceDo struct{ gen.DO }
+
+type ICreditBalanceDo interface {
+	gen.SubQuery
+	Debug() ICreditBalanceDo
+	WithContext(ctx context.Context) ICreditBalanceDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() ICreditBalanceDo
+	WriteDB() ICreditBalanceDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) ICreditBalanceDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) ICreditBalanceDo
+	Not(conds ...gen.Condition) ICreditBalanceDo
+	Or(conds ...gen.Condition) ICreditBalanceDo
+	Select(conds ...field.Expr) ICreditBalanceDo
+	Where(conds ...gen.Condition) ICreditBalanceDo
+	Order(conds ...field.Expr) ICreditBalanceDo
+	Distinct(cols ...field.Expr) ICreditBalanceDo
+	Omit(cols ...field.Expr) ICreditBalanceDo
+	Join(table schema.Tabler, on ...field.Expr) ICreditBalanceDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) ICreditBalanceDo
+	RightJoin(table schema.Tabler, on ...field.Expr) ICreditBalanceDo
+	Group(cols ...field.Expr) ICreditBalanceDo
+	Having(conds ...gen.Condition) ICreditBalanceDo
+	Limit(limit int) ICreditBalanceDo
+	Offset(offset int) ICreditBalanceDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) ICreditBalanceDo
+	Unscoped() ICreditBalanceDo
+	Create(values ...*model.CreditBalance) error
+	CreateInBatches(values []*model.CreditBalance, batchSize int) error
+	Save(values ...*model.CreditBalance) error
+	First() (*model.CreditBalance, error)
+	Take() (*model.CreditBalance, error)
+	Last() (*model.CreditBalance, error)
+	Find() ([]*model.CreditBalance, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.CreditBalance, err error)
+	FindInBatches(result *[]*model.CreditBalance, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.CreditBalance) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) ICreditBalanceDo
+	Assign(attrs ...field.AssignExpr) ICreditBalanceDo
+	Joins(fields ...field.RelationField) ICreditBalanceDo
+	Preload(fields ...field.RelationField) ICreditBalanceDo
+	FirstOrInit() (*model.CreditBalance, error)
+	FirstOrCreate() (*model.CreditBalance, error)
+	FindByPage(offset int, limit int) (result []*model.CreditBalance, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) ICreditBalanceDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (c creditBalanceDo) Debug() ICreditBalanceDo {
+	return c.withDO(c.DO.Debug())
+}
+
+func (c creditBalanceDo) WithContext(ctx context.Context) ICreditBalanceDo {
+	return c.withDO(c.DO.WithContext(ctx))
+}
+
+func (c creditBalanceDo) ReadDB() ICreditBalanceDo {
+	return c.Clauses(dbresolver.Read)
+}
+
+func (c creditBalanceDo) WriteDB() ICreditBalanceDo {
+	return c.Clauses(dbresolver.Write)
+}
+
+func (c creditBalanceDo) Session(config *gorm.Session) ICreditBalanceDo {
+	return c.withDO(c.DO.Session(config))
+}
+
+func (c creditBalanceDo) Clauses(conds ...clause.Expression) ICreditBalanceDo {
+	return c.withDO(c.DO.Clauses(conds...))
+}
+
+func (c creditBalanceDo) Returning(value interface{}, columns ...string) ICreditBalanceDo {
+	return c.withDO(c.DO.Returning(value, columns...))
+}
+
+func (c creditBalanceDo) Not(conds ...gen.Condition) ICreditBalanceDo {
+	return c.withDO(c.DO.Not(conds...))
+}
+
+func (c creditBalanceDo) Or(conds ...gen.Condition) ICreditBalanceDo {
+	return c.withDO(c.DO.Or(conds...))
+}
+
+func (c creditBalanceDo) Select(conds ...field.Expr) ICreditBalanceDo {
+	return c.withDO(c.DO.Select(conds...))
+}
+
+func (c creditBalanceDo) Where(conds ...gen.Condition) ICreditBalanceDo {
+	return c.withDO(c.DO.Where(conds...))
+}
+
+func (c creditBalanceDo) Order(conds ...field.Expr) ICreditBalanceDo {
+	return c.withDO(c.DO.Order(conds...))
+}
+
+func (c creditBalanceDo) Distinct(cols ...field.Expr) ICreditBalanceDo {
+	return c.withDO(c.DO.Distinct(cols...))
+}
+
+func (c creditBalanceDo) Omit(cols ...field.Expr) ICreditBalanceDo {
+	return c.withDO(c.DO.Omit(cols...))
+}
+
+func (c creditBalanceDo) Join(table schema.Tabler, on ...field.Expr) ICreditBalanceDo {
+	return c.withDO(c.DO.Join(table, on...))
+}
+
+func (c creditBalanceDo) LeftJoin(table schema.Tabler, on ...field.Expr) ICreditBalanceDo {
+	return c.withDO(c.DO.LeftJoin(table, on...))
+}
+
+func (c creditBalanceDo) RightJoin(table schema.Tabler, on ...field.Expr) ICreditBalanceDo {
+	return c.withDO(c.DO.RightJoin(table, on...))
+}
+
+func (c creditBalanceDo) Group(cols ...field.Expr) ICreditBalanceDo {
+	return c.withDO(c.DO.Group(cols...))
+}
+
+func (c creditBalanceDo) Having(conds ...gen.Condition) ICreditBalanceDo {
+	return c.withDO(c.DO.Having(conds...))
+}
+
+func (c creditBalanceDo) Limit(limit int) ICreditBalanceDo {
+	return c.withDO(c.DO.Limit(limit))
+}
+
+func (c creditBalanceDo) Offset(offset int) ICreditBalanceDo {
+	return c.withDO(c.DO.Offset(offset))
+}
+
+func (c creditBalanceDo) Scopes(funcs ...func(gen.Dao) gen.Dao) ICreditBalanceDo {
+	return c.withDO(c.DO.Scopes(funcs...))
+}
+
+func (c creditBalanceDo) Unscoped() ICreditBalanceDo {
+	return c.withDO(c.DO.Unscoped())
+}
+
+func (c creditBalanceDo) Create(values ...*model.CreditBalance) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return c.DO.Create(values)
+}
+
+func (c creditBalanceDo) CreateInBatches(values []*model.CreditBalance, batchSize int) error {
+	return c.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (c creditBalanceDo) Save(values ...*model.CreditBalance) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return c.DO.Save(values)
+}
+
+func (c creditBalanceDo) First() (*model.CreditBalance, error) {
+	if result, err := c.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.CreditBalance), nil
+	}
+}
+
+func (c creditBalanceDo) Take() (*model.CreditBalance, error) {
+	if result, err := c.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.CreditBalance), nil
+	}
+}
+
+func (c creditBalanceDo) Last() (*model.CreditBalance, error) {
+	if result, err := c.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.CreditBalance), nil
+	}
+}
+
+func (c creditBalanceDo) Find() ([]*model.CreditBalance, error) {
+	result, err := c.DO.Find()
+	return result.([]*model.CreditBalance), err
+}
+
+func (c creditBalanceDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.CreditBalance, err error) {
+	buf := make([]*model.CreditBalance, 0, batchSize)
+	err = c.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (c creditBalanceDo) FindInBatches(result *[]*model.CreditBalance, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return c.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (c creditBalanceDo) Attrs(attrs ...field.AssignExpr) ICreditBalanceDo {
+	return c.withDO(c.DO.Attrs(attrs...))
+}
+
+func (c creditBalanceDo) Assign(attrs ...field.AssignExpr) ICreditBalanceDo {
+	return c.withDO(c.DO.Assign(attrs...))
+}
+
+func (c creditBalanceDo) Joins(fields ...field.RelationField) ICreditBalanceDo {
+	for _, _f := range fields {
+		c = *c.withDO(c.DO.Joins(_f))
+	}
+	return &c
+}
+
+func (c creditBalanceDo) Preload(fields ...field.RelationField) ICreditBalanceDo {
+	for _, _f := range fields {
+		c = *c.withDO(c.DO.Preload(_f))
+	}
+	return &c
+}
+
+func (c creditBalanceDo) FirstOrInit() (*model.CreditBalance, error) {
+	if result, err := c.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.CreditBalance), nil
+	}
+}
+
+func (c creditBalanceDo) FirstOrCreate() (*model.CreditBalance, error) {
+	if result, err := c.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.CreditBalance), nil
+	}
+}
+
+func (c creditBalanceDo) FindByPage(offset int, limit int) (result []*model.CreditBalance, count int64, err error) {
+	result, err = c.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = c.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (c creditBalanceDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = c.Count()
+	if err != nil {
+		return
+	}
+
+	err = c.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (c creditBalanceDo) Scan(result interface{}) (err error) {
+	return c.DO.Scan(result)
+}
+
+func (c creditBalanceDo) Delete(models ...*model.CreditBalance) (result gen.ResultInfo, err error) {
+	return c.DO.Delete(models)
+}
+
+func (c *creditBalanceDo) withDO(do gen.Dao) *creditBalanceDo {
+	c.DO = *do.(*gen.DO)
+	return c
+}

+ 429 - 0
database/dao/wechat/query/credit_usage.gen.go

@@ -0,0 +1,429 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newCreditUsage(db *gorm.DB, opts ...gen.DOOption) creditUsage {
+	_creditUsage := creditUsage{}
+
+	_creditUsage.creditUsageDo.UseDB(db, opts...)
+	_creditUsage.creditUsageDo.UseModel(&model.CreditUsage{})
+
+	tableName := _creditUsage.creditUsageDo.TableName()
+	_creditUsage.ALL = field.NewAsterisk(tableName)
+	_creditUsage.ID = field.NewInt64(tableName, "id")
+	_creditUsage.CreatedAt = field.NewTime(tableName, "created_at")
+	_creditUsage.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_creditUsage.Status = field.NewInt64(tableName, "status")
+	_creditUsage.DeletedAt = field.NewField(tableName, "deleted_at")
+	_creditUsage.UserID = field.NewString(tableName, "user_id")
+	_creditUsage.Number = field.NewField(tableName, "number")
+	_creditUsage.Ntype = field.NewInt64(tableName, "ntype")
+	_creditUsage.MTable = field.NewString(tableName, "table")
+	_creditUsage.Nid = field.NewInt64(tableName, "nid")
+	_creditUsage.Reason = field.NewString(tableName, "reason")
+	_creditUsage.Operator = field.NewString(tableName, "operator")
+	_creditUsage.OrganizationID = field.NewInt64(tableName, "organization_id")
+
+	_creditUsage.fillFieldMap()
+
+	return _creditUsage
+}
+
+// creditUsage 积分变化明细表
+type creditUsage struct {
+	creditUsageDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	Status         field.Int64  // 状态 1 正常 2 禁用
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	UserID         field.String // 用户ID
+	Number         field.Field  // 积分改变量
+	Ntype          field.Int64  // 积分变化类型:1-消耗 2-增加
+	MTable         field.String // 积分变化表名
+	Nid            field.Int64  // 积分变化关联信息ID
+	Reason         field.String // 积分变动原因
+	Operator       field.String // 积分调整人
+	OrganizationID field.Int64  // 机构 ID
+
+	fieldMap map[string]field.Expr
+}
+
+func (c creditUsage) Table(newTableName string) *creditUsage {
+	c.creditUsageDo.UseTable(newTableName)
+	return c.updateTableName(newTableName)
+}
+
+func (c creditUsage) As(alias string) *creditUsage {
+	c.creditUsageDo.DO = *(c.creditUsageDo.As(alias).(*gen.DO))
+	return c.updateTableName(alias)
+}
+
+func (c *creditUsage) updateTableName(table string) *creditUsage {
+	c.ALL = field.NewAsterisk(table)
+	c.ID = field.NewInt64(table, "id")
+	c.CreatedAt = field.NewTime(table, "created_at")
+	c.UpdatedAt = field.NewTime(table, "updated_at")
+	c.Status = field.NewInt64(table, "status")
+	c.DeletedAt = field.NewField(table, "deleted_at")
+	c.UserID = field.NewString(table, "user_id")
+	c.Number = field.NewField(table, "number")
+	c.Ntype = field.NewInt64(table, "ntype")
+	c.MTable = field.NewString(table, "table")
+	c.Nid = field.NewInt64(table, "nid")
+	c.Reason = field.NewString(table, "reason")
+	c.Operator = field.NewString(table, "operator")
+	c.OrganizationID = field.NewInt64(table, "organization_id")
+
+	c.fillFieldMap()
+
+	return c
+}
+
+func (c *creditUsage) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := c.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (c *creditUsage) fillFieldMap() {
+	c.fieldMap = make(map[string]field.Expr, 13)
+	c.fieldMap["id"] = c.ID
+	c.fieldMap["created_at"] = c.CreatedAt
+	c.fieldMap["updated_at"] = c.UpdatedAt
+	c.fieldMap["status"] = c.Status
+	c.fieldMap["deleted_at"] = c.DeletedAt
+	c.fieldMap["user_id"] = c.UserID
+	c.fieldMap["number"] = c.Number
+	c.fieldMap["ntype"] = c.Ntype
+	c.fieldMap["table"] = c.MTable
+	c.fieldMap["nid"] = c.Nid
+	c.fieldMap["reason"] = c.Reason
+	c.fieldMap["operator"] = c.Operator
+	c.fieldMap["organization_id"] = c.OrganizationID
+}
+
+func (c creditUsage) clone(db *gorm.DB) creditUsage {
+	c.creditUsageDo.ReplaceConnPool(db.Statement.ConnPool)
+	return c
+}
+
+func (c creditUsage) replaceDB(db *gorm.DB) creditUsage {
+	c.creditUsageDo.ReplaceDB(db)
+	return c
+}
+
+type creditUsageDo struct{ gen.DO }
+
+type ICreditUsageDo interface {
+	gen.SubQuery
+	Debug() ICreditUsageDo
+	WithContext(ctx context.Context) ICreditUsageDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() ICreditUsageDo
+	WriteDB() ICreditUsageDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) ICreditUsageDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) ICreditUsageDo
+	Not(conds ...gen.Condition) ICreditUsageDo
+	Or(conds ...gen.Condition) ICreditUsageDo
+	Select(conds ...field.Expr) ICreditUsageDo
+	Where(conds ...gen.Condition) ICreditUsageDo
+	Order(conds ...field.Expr) ICreditUsageDo
+	Distinct(cols ...field.Expr) ICreditUsageDo
+	Omit(cols ...field.Expr) ICreditUsageDo
+	Join(table schema.Tabler, on ...field.Expr) ICreditUsageDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) ICreditUsageDo
+	RightJoin(table schema.Tabler, on ...field.Expr) ICreditUsageDo
+	Group(cols ...field.Expr) ICreditUsageDo
+	Having(conds ...gen.Condition) ICreditUsageDo
+	Limit(limit int) ICreditUsageDo
+	Offset(offset int) ICreditUsageDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) ICreditUsageDo
+	Unscoped() ICreditUsageDo
+	Create(values ...*model.CreditUsage) error
+	CreateInBatches(values []*model.CreditUsage, batchSize int) error
+	Save(values ...*model.CreditUsage) error
+	First() (*model.CreditUsage, error)
+	Take() (*model.CreditUsage, error)
+	Last() (*model.CreditUsage, error)
+	Find() ([]*model.CreditUsage, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.CreditUsage, err error)
+	FindInBatches(result *[]*model.CreditUsage, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.CreditUsage) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) ICreditUsageDo
+	Assign(attrs ...field.AssignExpr) ICreditUsageDo
+	Joins(fields ...field.RelationField) ICreditUsageDo
+	Preload(fields ...field.RelationField) ICreditUsageDo
+	FirstOrInit() (*model.CreditUsage, error)
+	FirstOrCreate() (*model.CreditUsage, error)
+	FindByPage(offset int, limit int) (result []*model.CreditUsage, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) ICreditUsageDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (c creditUsageDo) Debug() ICreditUsageDo {
+	return c.withDO(c.DO.Debug())
+}
+
+func (c creditUsageDo) WithContext(ctx context.Context) ICreditUsageDo {
+	return c.withDO(c.DO.WithContext(ctx))
+}
+
+func (c creditUsageDo) ReadDB() ICreditUsageDo {
+	return c.Clauses(dbresolver.Read)
+}
+
+func (c creditUsageDo) WriteDB() ICreditUsageDo {
+	return c.Clauses(dbresolver.Write)
+}
+
+func (c creditUsageDo) Session(config *gorm.Session) ICreditUsageDo {
+	return c.withDO(c.DO.Session(config))
+}
+
+func (c creditUsageDo) Clauses(conds ...clause.Expression) ICreditUsageDo {
+	return c.withDO(c.DO.Clauses(conds...))
+}
+
+func (c creditUsageDo) Returning(value interface{}, columns ...string) ICreditUsageDo {
+	return c.withDO(c.DO.Returning(value, columns...))
+}
+
+func (c creditUsageDo) Not(conds ...gen.Condition) ICreditUsageDo {
+	return c.withDO(c.DO.Not(conds...))
+}
+
+func (c creditUsageDo) Or(conds ...gen.Condition) ICreditUsageDo {
+	return c.withDO(c.DO.Or(conds...))
+}
+
+func (c creditUsageDo) Select(conds ...field.Expr) ICreditUsageDo {
+	return c.withDO(c.DO.Select(conds...))
+}
+
+func (c creditUsageDo) Where(conds ...gen.Condition) ICreditUsageDo {
+	return c.withDO(c.DO.Where(conds...))
+}
+
+func (c creditUsageDo) Order(conds ...field.Expr) ICreditUsageDo {
+	return c.withDO(c.DO.Order(conds...))
+}
+
+func (c creditUsageDo) Distinct(cols ...field.Expr) ICreditUsageDo {
+	return c.withDO(c.DO.Distinct(cols...))
+}
+
+func (c creditUsageDo) Omit(cols ...field.Expr) ICreditUsageDo {
+	return c.withDO(c.DO.Omit(cols...))
+}
+
+func (c creditUsageDo) Join(table schema.Tabler, on ...field.Expr) ICreditUsageDo {
+	return c.withDO(c.DO.Join(table, on...))
+}
+
+func (c creditUsageDo) LeftJoin(table schema.Tabler, on ...field.Expr) ICreditUsageDo {
+	return c.withDO(c.DO.LeftJoin(table, on...))
+}
+
+func (c creditUsageDo) RightJoin(table schema.Tabler, on ...field.Expr) ICreditUsageDo {
+	return c.withDO(c.DO.RightJoin(table, on...))
+}
+
+func (c creditUsageDo) Group(cols ...field.Expr) ICreditUsageDo {
+	return c.withDO(c.DO.Group(cols...))
+}
+
+func (c creditUsageDo) Having(conds ...gen.Condition) ICreditUsageDo {
+	return c.withDO(c.DO.Having(conds...))
+}
+
+func (c creditUsageDo) Limit(limit int) ICreditUsageDo {
+	return c.withDO(c.DO.Limit(limit))
+}
+
+func (c creditUsageDo) Offset(offset int) ICreditUsageDo {
+	return c.withDO(c.DO.Offset(offset))
+}
+
+func (c creditUsageDo) Scopes(funcs ...func(gen.Dao) gen.Dao) ICreditUsageDo {
+	return c.withDO(c.DO.Scopes(funcs...))
+}
+
+func (c creditUsageDo) Unscoped() ICreditUsageDo {
+	return c.withDO(c.DO.Unscoped())
+}
+
+func (c creditUsageDo) Create(values ...*model.CreditUsage) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return c.DO.Create(values)
+}
+
+func (c creditUsageDo) CreateInBatches(values []*model.CreditUsage, batchSize int) error {
+	return c.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (c creditUsageDo) Save(values ...*model.CreditUsage) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return c.DO.Save(values)
+}
+
+func (c creditUsageDo) First() (*model.CreditUsage, error) {
+	if result, err := c.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.CreditUsage), nil
+	}
+}
+
+func (c creditUsageDo) Take() (*model.CreditUsage, error) {
+	if result, err := c.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.CreditUsage), nil
+	}
+}
+
+func (c creditUsageDo) Last() (*model.CreditUsage, error) {
+	if result, err := c.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.CreditUsage), nil
+	}
+}
+
+func (c creditUsageDo) Find() ([]*model.CreditUsage, error) {
+	result, err := c.DO.Find()
+	return result.([]*model.CreditUsage), err
+}
+
+func (c creditUsageDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.CreditUsage, err error) {
+	buf := make([]*model.CreditUsage, 0, batchSize)
+	err = c.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (c creditUsageDo) FindInBatches(result *[]*model.CreditUsage, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return c.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (c creditUsageDo) Attrs(attrs ...field.AssignExpr) ICreditUsageDo {
+	return c.withDO(c.DO.Attrs(attrs...))
+}
+
+func (c creditUsageDo) Assign(attrs ...field.AssignExpr) ICreditUsageDo {
+	return c.withDO(c.DO.Assign(attrs...))
+}
+
+func (c creditUsageDo) Joins(fields ...field.RelationField) ICreditUsageDo {
+	for _, _f := range fields {
+		c = *c.withDO(c.DO.Joins(_f))
+	}
+	return &c
+}
+
+func (c creditUsageDo) Preload(fields ...field.RelationField) ICreditUsageDo {
+	for _, _f := range fields {
+		c = *c.withDO(c.DO.Preload(_f))
+	}
+	return &c
+}
+
+func (c creditUsageDo) FirstOrInit() (*model.CreditUsage, error) {
+	if result, err := c.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.CreditUsage), nil
+	}
+}
+
+func (c creditUsageDo) FirstOrCreate() (*model.CreditUsage, error) {
+	if result, err := c.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.CreditUsage), nil
+	}
+}
+
+func (c creditUsageDo) FindByPage(offset int, limit int) (result []*model.CreditUsage, count int64, err error) {
+	result, err = c.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = c.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (c creditUsageDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = c.Count()
+	if err != nil {
+		return
+	}
+
+	err = c.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (c creditUsageDo) Scan(result interface{}) (err error) {
+	return c.DO.Scan(result)
+}
+
+func (c creditUsageDo) Delete(models ...*model.CreditUsage) (result gen.ResultInfo, err error) {
+	return c.DO.Delete(models)
+}
+
+func (c *creditUsageDo) withDO(do gen.Dao) *creditUsageDo {
+	c.DO = *do.(*gen.DO)
+	return c
+}

+ 477 - 0
database/dao/wechat/query/employee.gen.go

@@ -0,0 +1,477 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newEmployee(db *gorm.DB, opts ...gen.DOOption) employee {
+	_employee := employee{}
+
+	_employee.employeeDo.UseDB(db, opts...)
+	_employee.employeeDo.UseModel(&model.Employee{})
+
+	tableName := _employee.employeeDo.TableName()
+	_employee.ALL = field.NewAsterisk(tableName)
+	_employee.ID = field.NewInt64(tableName, "id")
+	_employee.CreatedAt = field.NewTime(tableName, "created_at")
+	_employee.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_employee.DeletedAt = field.NewField(tableName, "deleted_at")
+	_employee.Title = field.NewString(tableName, "title")
+	_employee.Avatar = field.NewString(tableName, "avatar")
+	_employee.Tags = field.NewString(tableName, "tags")
+	_employee.HireCount = field.NewInt64(tableName, "hire_count")
+	_employee.ServiceCount = field.NewInt64(tableName, "service_count")
+	_employee.AchievementCount = field.NewInt64(tableName, "achievement_count")
+	_employee.Intro = field.NewString(tableName, "intro")
+	_employee.Estimate = field.NewString(tableName, "estimate")
+	_employee.Skill = field.NewString(tableName, "skill")
+	_employee.AbilityType = field.NewString(tableName, "ability_type")
+	_employee.Scene = field.NewString(tableName, "scene")
+	_employee.SwitchIn = field.NewString(tableName, "switch_in")
+	_employee.Tutorial = field.NewString(tableName, "tutorial")
+	_employee.VideoURL = field.NewString(tableName, "video_url")
+	_employee.OrganizationID = field.NewInt64(tableName, "organization_id")
+	_employee.CategoryID = field.NewInt64(tableName, "category_id")
+	_employee.APIBase = field.NewString(tableName, "api_base")
+	_employee.APIKey = field.NewString(tableName, "api_key")
+	_employee.IsVip = field.NewInt64(tableName, "is_vip")
+	_employee.AiInfo = field.NewString(tableName, "ai_info")
+	_employee.ChatURL = field.NewString(tableName, "chat_url")
+
+	_employee.fillFieldMap()
+
+	return _employee
+}
+
+// employee 数字员工表
+type employee struct {
+	employeeDo
+
+	ALL              field.Asterisk
+	ID               field.Int64  // ID
+	CreatedAt        field.Time   // 创建时间
+	UpdatedAt        field.Time   // 修改时间
+	DeletedAt        field.Field  // 删除时间
+	Title            field.String // 标题
+	Avatar           field.String // 头像URL
+	Tags             field.String // Tag列表 用,连接多个
+	HireCount        field.Int64  // 被雇佣次数
+	ServiceCount     field.Int64  // 服务次数
+	AchievementCount field.Int64  // 业绩单数
+	Intro            field.String // 个人介绍
+	Estimate         field.String // 自我评价
+	Skill            field.String // 技能卡
+	AbilityType      field.String // 能力类型 用,连接
+	Scene            field.String // 使用场景 用,连接
+	SwitchIn         field.String // 支持接入 用,连接
+	Tutorial         field.String // 使用教程
+	VideoURL         field.String // 视频
+	OrganizationID   field.Int64  // 机构ID
+	CategoryID       field.Int64  // 分类ID
+	APIBase          field.String
+	APIKey           field.String
+	IsVip            field.Int64  // 是否VIP:0-否 1-是
+	AiInfo           field.String // AI信息
+	ChatURL          field.String // 聊天URL
+
+	fieldMap map[string]field.Expr
+}
+
+func (e employee) Table(newTableName string) *employee {
+	e.employeeDo.UseTable(newTableName)
+	return e.updateTableName(newTableName)
+}
+
+func (e employee) As(alias string) *employee {
+	e.employeeDo.DO = *(e.employeeDo.As(alias).(*gen.DO))
+	return e.updateTableName(alias)
+}
+
+func (e *employee) updateTableName(table string) *employee {
+	e.ALL = field.NewAsterisk(table)
+	e.ID = field.NewInt64(table, "id")
+	e.CreatedAt = field.NewTime(table, "created_at")
+	e.UpdatedAt = field.NewTime(table, "updated_at")
+	e.DeletedAt = field.NewField(table, "deleted_at")
+	e.Title = field.NewString(table, "title")
+	e.Avatar = field.NewString(table, "avatar")
+	e.Tags = field.NewString(table, "tags")
+	e.HireCount = field.NewInt64(table, "hire_count")
+	e.ServiceCount = field.NewInt64(table, "service_count")
+	e.AchievementCount = field.NewInt64(table, "achievement_count")
+	e.Intro = field.NewString(table, "intro")
+	e.Estimate = field.NewString(table, "estimate")
+	e.Skill = field.NewString(table, "skill")
+	e.AbilityType = field.NewString(table, "ability_type")
+	e.Scene = field.NewString(table, "scene")
+	e.SwitchIn = field.NewString(table, "switch_in")
+	e.Tutorial = field.NewString(table, "tutorial")
+	e.VideoURL = field.NewString(table, "video_url")
+	e.OrganizationID = field.NewInt64(table, "organization_id")
+	e.CategoryID = field.NewInt64(table, "category_id")
+	e.APIBase = field.NewString(table, "api_base")
+	e.APIKey = field.NewString(table, "api_key")
+	e.IsVip = field.NewInt64(table, "is_vip")
+	e.AiInfo = field.NewString(table, "ai_info")
+	e.ChatURL = field.NewString(table, "chat_url")
+
+	e.fillFieldMap()
+
+	return e
+}
+
+func (e *employee) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := e.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (e *employee) fillFieldMap() {
+	e.fieldMap = make(map[string]field.Expr, 25)
+	e.fieldMap["id"] = e.ID
+	e.fieldMap["created_at"] = e.CreatedAt
+	e.fieldMap["updated_at"] = e.UpdatedAt
+	e.fieldMap["deleted_at"] = e.DeletedAt
+	e.fieldMap["title"] = e.Title
+	e.fieldMap["avatar"] = e.Avatar
+	e.fieldMap["tags"] = e.Tags
+	e.fieldMap["hire_count"] = e.HireCount
+	e.fieldMap["service_count"] = e.ServiceCount
+	e.fieldMap["achievement_count"] = e.AchievementCount
+	e.fieldMap["intro"] = e.Intro
+	e.fieldMap["estimate"] = e.Estimate
+	e.fieldMap["skill"] = e.Skill
+	e.fieldMap["ability_type"] = e.AbilityType
+	e.fieldMap["scene"] = e.Scene
+	e.fieldMap["switch_in"] = e.SwitchIn
+	e.fieldMap["tutorial"] = e.Tutorial
+	e.fieldMap["video_url"] = e.VideoURL
+	e.fieldMap["organization_id"] = e.OrganizationID
+	e.fieldMap["category_id"] = e.CategoryID
+	e.fieldMap["api_base"] = e.APIBase
+	e.fieldMap["api_key"] = e.APIKey
+	e.fieldMap["is_vip"] = e.IsVip
+	e.fieldMap["ai_info"] = e.AiInfo
+	e.fieldMap["chat_url"] = e.ChatURL
+}
+
+func (e employee) clone(db *gorm.DB) employee {
+	e.employeeDo.ReplaceConnPool(db.Statement.ConnPool)
+	return e
+}
+
+func (e employee) replaceDB(db *gorm.DB) employee {
+	e.employeeDo.ReplaceDB(db)
+	return e
+}
+
+type employeeDo struct{ gen.DO }
+
+type IEmployeeDo interface {
+	gen.SubQuery
+	Debug() IEmployeeDo
+	WithContext(ctx context.Context) IEmployeeDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IEmployeeDo
+	WriteDB() IEmployeeDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IEmployeeDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IEmployeeDo
+	Not(conds ...gen.Condition) IEmployeeDo
+	Or(conds ...gen.Condition) IEmployeeDo
+	Select(conds ...field.Expr) IEmployeeDo
+	Where(conds ...gen.Condition) IEmployeeDo
+	Order(conds ...field.Expr) IEmployeeDo
+	Distinct(cols ...field.Expr) IEmployeeDo
+	Omit(cols ...field.Expr) IEmployeeDo
+	Join(table schema.Tabler, on ...field.Expr) IEmployeeDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IEmployeeDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IEmployeeDo
+	Group(cols ...field.Expr) IEmployeeDo
+	Having(conds ...gen.Condition) IEmployeeDo
+	Limit(limit int) IEmployeeDo
+	Offset(offset int) IEmployeeDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IEmployeeDo
+	Unscoped() IEmployeeDo
+	Create(values ...*model.Employee) error
+	CreateInBatches(values []*model.Employee, batchSize int) error
+	Save(values ...*model.Employee) error
+	First() (*model.Employee, error)
+	Take() (*model.Employee, error)
+	Last() (*model.Employee, error)
+	Find() ([]*model.Employee, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Employee, err error)
+	FindInBatches(result *[]*model.Employee, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.Employee) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IEmployeeDo
+	Assign(attrs ...field.AssignExpr) IEmployeeDo
+	Joins(fields ...field.RelationField) IEmployeeDo
+	Preload(fields ...field.RelationField) IEmployeeDo
+	FirstOrInit() (*model.Employee, error)
+	FirstOrCreate() (*model.Employee, error)
+	FindByPage(offset int, limit int) (result []*model.Employee, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IEmployeeDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (e employeeDo) Debug() IEmployeeDo {
+	return e.withDO(e.DO.Debug())
+}
+
+func (e employeeDo) WithContext(ctx context.Context) IEmployeeDo {
+	return e.withDO(e.DO.WithContext(ctx))
+}
+
+func (e employeeDo) ReadDB() IEmployeeDo {
+	return e.Clauses(dbresolver.Read)
+}
+
+func (e employeeDo) WriteDB() IEmployeeDo {
+	return e.Clauses(dbresolver.Write)
+}
+
+func (e employeeDo) Session(config *gorm.Session) IEmployeeDo {
+	return e.withDO(e.DO.Session(config))
+}
+
+func (e employeeDo) Clauses(conds ...clause.Expression) IEmployeeDo {
+	return e.withDO(e.DO.Clauses(conds...))
+}
+
+func (e employeeDo) Returning(value interface{}, columns ...string) IEmployeeDo {
+	return e.withDO(e.DO.Returning(value, columns...))
+}
+
+func (e employeeDo) Not(conds ...gen.Condition) IEmployeeDo {
+	return e.withDO(e.DO.Not(conds...))
+}
+
+func (e employeeDo) Or(conds ...gen.Condition) IEmployeeDo {
+	return e.withDO(e.DO.Or(conds...))
+}
+
+func (e employeeDo) Select(conds ...field.Expr) IEmployeeDo {
+	return e.withDO(e.DO.Select(conds...))
+}
+
+func (e employeeDo) Where(conds ...gen.Condition) IEmployeeDo {
+	return e.withDO(e.DO.Where(conds...))
+}
+
+func (e employeeDo) Order(conds ...field.Expr) IEmployeeDo {
+	return e.withDO(e.DO.Order(conds...))
+}
+
+func (e employeeDo) Distinct(cols ...field.Expr) IEmployeeDo {
+	return e.withDO(e.DO.Distinct(cols...))
+}
+
+func (e employeeDo) Omit(cols ...field.Expr) IEmployeeDo {
+	return e.withDO(e.DO.Omit(cols...))
+}
+
+func (e employeeDo) Join(table schema.Tabler, on ...field.Expr) IEmployeeDo {
+	return e.withDO(e.DO.Join(table, on...))
+}
+
+func (e employeeDo) LeftJoin(table schema.Tabler, on ...field.Expr) IEmployeeDo {
+	return e.withDO(e.DO.LeftJoin(table, on...))
+}
+
+func (e employeeDo) RightJoin(table schema.Tabler, on ...field.Expr) IEmployeeDo {
+	return e.withDO(e.DO.RightJoin(table, on...))
+}
+
+func (e employeeDo) Group(cols ...field.Expr) IEmployeeDo {
+	return e.withDO(e.DO.Group(cols...))
+}
+
+func (e employeeDo) Having(conds ...gen.Condition) IEmployeeDo {
+	return e.withDO(e.DO.Having(conds...))
+}
+
+func (e employeeDo) Limit(limit int) IEmployeeDo {
+	return e.withDO(e.DO.Limit(limit))
+}
+
+func (e employeeDo) Offset(offset int) IEmployeeDo {
+	return e.withDO(e.DO.Offset(offset))
+}
+
+func (e employeeDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IEmployeeDo {
+	return e.withDO(e.DO.Scopes(funcs...))
+}
+
+func (e employeeDo) Unscoped() IEmployeeDo {
+	return e.withDO(e.DO.Unscoped())
+}
+
+func (e employeeDo) Create(values ...*model.Employee) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return e.DO.Create(values)
+}
+
+func (e employeeDo) CreateInBatches(values []*model.Employee, batchSize int) error {
+	return e.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (e employeeDo) Save(values ...*model.Employee) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return e.DO.Save(values)
+}
+
+func (e employeeDo) First() (*model.Employee, error) {
+	if result, err := e.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Employee), nil
+	}
+}
+
+func (e employeeDo) Take() (*model.Employee, error) {
+	if result, err := e.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Employee), nil
+	}
+}
+
+func (e employeeDo) Last() (*model.Employee, error) {
+	if result, err := e.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Employee), nil
+	}
+}
+
+func (e employeeDo) Find() ([]*model.Employee, error) {
+	result, err := e.DO.Find()
+	return result.([]*model.Employee), err
+}
+
+func (e employeeDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Employee, err error) {
+	buf := make([]*model.Employee, 0, batchSize)
+	err = e.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (e employeeDo) FindInBatches(result *[]*model.Employee, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return e.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (e employeeDo) Attrs(attrs ...field.AssignExpr) IEmployeeDo {
+	return e.withDO(e.DO.Attrs(attrs...))
+}
+
+func (e employeeDo) Assign(attrs ...field.AssignExpr) IEmployeeDo {
+	return e.withDO(e.DO.Assign(attrs...))
+}
+
+func (e employeeDo) Joins(fields ...field.RelationField) IEmployeeDo {
+	for _, _f := range fields {
+		e = *e.withDO(e.DO.Joins(_f))
+	}
+	return &e
+}
+
+func (e employeeDo) Preload(fields ...field.RelationField) IEmployeeDo {
+	for _, _f := range fields {
+		e = *e.withDO(e.DO.Preload(_f))
+	}
+	return &e
+}
+
+func (e employeeDo) FirstOrInit() (*model.Employee, error) {
+	if result, err := e.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Employee), nil
+	}
+}
+
+func (e employeeDo) FirstOrCreate() (*model.Employee, error) {
+	if result, err := e.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Employee), nil
+	}
+}
+
+func (e employeeDo) FindByPage(offset int, limit int) (result []*model.Employee, count int64, err error) {
+	result, err = e.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = e.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (e employeeDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = e.Count()
+	if err != nil {
+		return
+	}
+
+	err = e.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (e employeeDo) Scan(result interface{}) (err error) {
+	return e.DO.Scan(result)
+}
+
+func (e employeeDo) Delete(models ...*model.Employee) (result gen.ResultInfo, err error) {
+	return e.DO.Delete(models)
+}
+
+func (e *employeeDo) withDO(do gen.Dao) *employeeDo {
+	e.DO = *do.(*gen.DO)
+	return e
+}

+ 408 - 0
database/dao/wechat/query/employee_config.gen.go

@@ -0,0 +1,408 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newEmployeeConfig(db *gorm.DB, opts ...gen.DOOption) employeeConfig {
+	_employeeConfig := employeeConfig{}
+
+	_employeeConfig.employeeConfigDo.UseDB(db, opts...)
+	_employeeConfig.employeeConfigDo.UseModel(&model.EmployeeConfig{})
+
+	tableName := _employeeConfig.employeeConfigDo.TableName()
+	_employeeConfig.ALL = field.NewAsterisk(tableName)
+	_employeeConfig.ID = field.NewInt64(tableName, "id")
+	_employeeConfig.CreatedAt = field.NewTime(tableName, "created_at")
+	_employeeConfig.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_employeeConfig.DeletedAt = field.NewField(tableName, "deleted_at")
+	_employeeConfig.Stype = field.NewString(tableName, "stype")
+	_employeeConfig.Title = field.NewString(tableName, "title")
+	_employeeConfig.Photo = field.NewString(tableName, "photo")
+	_employeeConfig.OrganizationID = field.NewInt64(tableName, "organization_id")
+
+	_employeeConfig.fillFieldMap()
+
+	return _employeeConfig
+}
+
+type employeeConfig struct {
+	employeeConfigDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	Stype          field.String // 配置类型
+	Title          field.String // 标题
+	Photo          field.String // 图片
+	OrganizationID field.Int64  // 机构 ID
+
+	fieldMap map[string]field.Expr
+}
+
+func (e employeeConfig) Table(newTableName string) *employeeConfig {
+	e.employeeConfigDo.UseTable(newTableName)
+	return e.updateTableName(newTableName)
+}
+
+func (e employeeConfig) As(alias string) *employeeConfig {
+	e.employeeConfigDo.DO = *(e.employeeConfigDo.As(alias).(*gen.DO))
+	return e.updateTableName(alias)
+}
+
+func (e *employeeConfig) updateTableName(table string) *employeeConfig {
+	e.ALL = field.NewAsterisk(table)
+	e.ID = field.NewInt64(table, "id")
+	e.CreatedAt = field.NewTime(table, "created_at")
+	e.UpdatedAt = field.NewTime(table, "updated_at")
+	e.DeletedAt = field.NewField(table, "deleted_at")
+	e.Stype = field.NewString(table, "stype")
+	e.Title = field.NewString(table, "title")
+	e.Photo = field.NewString(table, "photo")
+	e.OrganizationID = field.NewInt64(table, "organization_id")
+
+	e.fillFieldMap()
+
+	return e
+}
+
+func (e *employeeConfig) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := e.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (e *employeeConfig) fillFieldMap() {
+	e.fieldMap = make(map[string]field.Expr, 8)
+	e.fieldMap["id"] = e.ID
+	e.fieldMap["created_at"] = e.CreatedAt
+	e.fieldMap["updated_at"] = e.UpdatedAt
+	e.fieldMap["deleted_at"] = e.DeletedAt
+	e.fieldMap["stype"] = e.Stype
+	e.fieldMap["title"] = e.Title
+	e.fieldMap["photo"] = e.Photo
+	e.fieldMap["organization_id"] = e.OrganizationID
+}
+
+func (e employeeConfig) clone(db *gorm.DB) employeeConfig {
+	e.employeeConfigDo.ReplaceConnPool(db.Statement.ConnPool)
+	return e
+}
+
+func (e employeeConfig) replaceDB(db *gorm.DB) employeeConfig {
+	e.employeeConfigDo.ReplaceDB(db)
+	return e
+}
+
+type employeeConfigDo struct{ gen.DO }
+
+type IEmployeeConfigDo interface {
+	gen.SubQuery
+	Debug() IEmployeeConfigDo
+	WithContext(ctx context.Context) IEmployeeConfigDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IEmployeeConfigDo
+	WriteDB() IEmployeeConfigDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IEmployeeConfigDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IEmployeeConfigDo
+	Not(conds ...gen.Condition) IEmployeeConfigDo
+	Or(conds ...gen.Condition) IEmployeeConfigDo
+	Select(conds ...field.Expr) IEmployeeConfigDo
+	Where(conds ...gen.Condition) IEmployeeConfigDo
+	Order(conds ...field.Expr) IEmployeeConfigDo
+	Distinct(cols ...field.Expr) IEmployeeConfigDo
+	Omit(cols ...field.Expr) IEmployeeConfigDo
+	Join(table schema.Tabler, on ...field.Expr) IEmployeeConfigDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IEmployeeConfigDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IEmployeeConfigDo
+	Group(cols ...field.Expr) IEmployeeConfigDo
+	Having(conds ...gen.Condition) IEmployeeConfigDo
+	Limit(limit int) IEmployeeConfigDo
+	Offset(offset int) IEmployeeConfigDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IEmployeeConfigDo
+	Unscoped() IEmployeeConfigDo
+	Create(values ...*model.EmployeeConfig) error
+	CreateInBatches(values []*model.EmployeeConfig, batchSize int) error
+	Save(values ...*model.EmployeeConfig) error
+	First() (*model.EmployeeConfig, error)
+	Take() (*model.EmployeeConfig, error)
+	Last() (*model.EmployeeConfig, error)
+	Find() ([]*model.EmployeeConfig, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.EmployeeConfig, err error)
+	FindInBatches(result *[]*model.EmployeeConfig, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.EmployeeConfig) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IEmployeeConfigDo
+	Assign(attrs ...field.AssignExpr) IEmployeeConfigDo
+	Joins(fields ...field.RelationField) IEmployeeConfigDo
+	Preload(fields ...field.RelationField) IEmployeeConfigDo
+	FirstOrInit() (*model.EmployeeConfig, error)
+	FirstOrCreate() (*model.EmployeeConfig, error)
+	FindByPage(offset int, limit int) (result []*model.EmployeeConfig, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IEmployeeConfigDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (e employeeConfigDo) Debug() IEmployeeConfigDo {
+	return e.withDO(e.DO.Debug())
+}
+
+func (e employeeConfigDo) WithContext(ctx context.Context) IEmployeeConfigDo {
+	return e.withDO(e.DO.WithContext(ctx))
+}
+
+func (e employeeConfigDo) ReadDB() IEmployeeConfigDo {
+	return e.Clauses(dbresolver.Read)
+}
+
+func (e employeeConfigDo) WriteDB() IEmployeeConfigDo {
+	return e.Clauses(dbresolver.Write)
+}
+
+func (e employeeConfigDo) Session(config *gorm.Session) IEmployeeConfigDo {
+	return e.withDO(e.DO.Session(config))
+}
+
+func (e employeeConfigDo) Clauses(conds ...clause.Expression) IEmployeeConfigDo {
+	return e.withDO(e.DO.Clauses(conds...))
+}
+
+func (e employeeConfigDo) Returning(value interface{}, columns ...string) IEmployeeConfigDo {
+	return e.withDO(e.DO.Returning(value, columns...))
+}
+
+func (e employeeConfigDo) Not(conds ...gen.Condition) IEmployeeConfigDo {
+	return e.withDO(e.DO.Not(conds...))
+}
+
+func (e employeeConfigDo) Or(conds ...gen.Condition) IEmployeeConfigDo {
+	return e.withDO(e.DO.Or(conds...))
+}
+
+func (e employeeConfigDo) Select(conds ...field.Expr) IEmployeeConfigDo {
+	return e.withDO(e.DO.Select(conds...))
+}
+
+func (e employeeConfigDo) Where(conds ...gen.Condition) IEmployeeConfigDo {
+	return e.withDO(e.DO.Where(conds...))
+}
+
+func (e employeeConfigDo) Order(conds ...field.Expr) IEmployeeConfigDo {
+	return e.withDO(e.DO.Order(conds...))
+}
+
+func (e employeeConfigDo) Distinct(cols ...field.Expr) IEmployeeConfigDo {
+	return e.withDO(e.DO.Distinct(cols...))
+}
+
+func (e employeeConfigDo) Omit(cols ...field.Expr) IEmployeeConfigDo {
+	return e.withDO(e.DO.Omit(cols...))
+}
+
+func (e employeeConfigDo) Join(table schema.Tabler, on ...field.Expr) IEmployeeConfigDo {
+	return e.withDO(e.DO.Join(table, on...))
+}
+
+func (e employeeConfigDo) LeftJoin(table schema.Tabler, on ...field.Expr) IEmployeeConfigDo {
+	return e.withDO(e.DO.LeftJoin(table, on...))
+}
+
+func (e employeeConfigDo) RightJoin(table schema.Tabler, on ...field.Expr) IEmployeeConfigDo {
+	return e.withDO(e.DO.RightJoin(table, on...))
+}
+
+func (e employeeConfigDo) Group(cols ...field.Expr) IEmployeeConfigDo {
+	return e.withDO(e.DO.Group(cols...))
+}
+
+func (e employeeConfigDo) Having(conds ...gen.Condition) IEmployeeConfigDo {
+	return e.withDO(e.DO.Having(conds...))
+}
+
+func (e employeeConfigDo) Limit(limit int) IEmployeeConfigDo {
+	return e.withDO(e.DO.Limit(limit))
+}
+
+func (e employeeConfigDo) Offset(offset int) IEmployeeConfigDo {
+	return e.withDO(e.DO.Offset(offset))
+}
+
+func (e employeeConfigDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IEmployeeConfigDo {
+	return e.withDO(e.DO.Scopes(funcs...))
+}
+
+func (e employeeConfigDo) Unscoped() IEmployeeConfigDo {
+	return e.withDO(e.DO.Unscoped())
+}
+
+func (e employeeConfigDo) Create(values ...*model.EmployeeConfig) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return e.DO.Create(values)
+}
+
+func (e employeeConfigDo) CreateInBatches(values []*model.EmployeeConfig, batchSize int) error {
+	return e.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (e employeeConfigDo) Save(values ...*model.EmployeeConfig) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return e.DO.Save(values)
+}
+
+func (e employeeConfigDo) First() (*model.EmployeeConfig, error) {
+	if result, err := e.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.EmployeeConfig), nil
+	}
+}
+
+func (e employeeConfigDo) Take() (*model.EmployeeConfig, error) {
+	if result, err := e.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.EmployeeConfig), nil
+	}
+}
+
+func (e employeeConfigDo) Last() (*model.EmployeeConfig, error) {
+	if result, err := e.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.EmployeeConfig), nil
+	}
+}
+
+func (e employeeConfigDo) Find() ([]*model.EmployeeConfig, error) {
+	result, err := e.DO.Find()
+	return result.([]*model.EmployeeConfig), err
+}
+
+func (e employeeConfigDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.EmployeeConfig, err error) {
+	buf := make([]*model.EmployeeConfig, 0, batchSize)
+	err = e.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (e employeeConfigDo) FindInBatches(result *[]*model.EmployeeConfig, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return e.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (e employeeConfigDo) Attrs(attrs ...field.AssignExpr) IEmployeeConfigDo {
+	return e.withDO(e.DO.Attrs(attrs...))
+}
+
+func (e employeeConfigDo) Assign(attrs ...field.AssignExpr) IEmployeeConfigDo {
+	return e.withDO(e.DO.Assign(attrs...))
+}
+
+func (e employeeConfigDo) Joins(fields ...field.RelationField) IEmployeeConfigDo {
+	for _, _f := range fields {
+		e = *e.withDO(e.DO.Joins(_f))
+	}
+	return &e
+}
+
+func (e employeeConfigDo) Preload(fields ...field.RelationField) IEmployeeConfigDo {
+	for _, _f := range fields {
+		e = *e.withDO(e.DO.Preload(_f))
+	}
+	return &e
+}
+
+func (e employeeConfigDo) FirstOrInit() (*model.EmployeeConfig, error) {
+	if result, err := e.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.EmployeeConfig), nil
+	}
+}
+
+func (e employeeConfigDo) FirstOrCreate() (*model.EmployeeConfig, error) {
+	if result, err := e.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.EmployeeConfig), nil
+	}
+}
+
+func (e employeeConfigDo) FindByPage(offset int, limit int) (result []*model.EmployeeConfig, count int64, err error) {
+	result, err = e.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = e.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (e employeeConfigDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = e.Count()
+	if err != nil {
+		return
+	}
+
+	err = e.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (e employeeConfigDo) Scan(result interface{}) (err error) {
+	return e.DO.Scan(result)
+}
+
+func (e employeeConfigDo) Delete(models ...*model.EmployeeConfig) (result gen.ResultInfo, err error) {
+	return e.DO.Delete(models)
+}
+
+func (e *employeeConfigDo) withDO(do gen.Dao) *employeeConfigDo {
+	e.DO = *do.(*gen.DO)
+	return e
+}

+ 424 - 0
database/dao/wechat/query/form_records.gen.go

@@ -0,0 +1,424 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newFormRecord(db *gorm.DB, opts ...gen.DOOption) formRecord {
+	_formRecord := formRecord{}
+
+	_formRecord.formRecordDo.UseDB(db, opts...)
+	_formRecord.formRecordDo.UseModel(&model.FormRecord{})
+
+	tableName := _formRecord.formRecordDo.TableName()
+	_formRecord.ALL = field.NewAsterisk(tableName)
+	_formRecord.ID = field.NewString(tableName, "id")
+	_formRecord.ExternalID = field.NewString(tableName, "external_id")
+	_formRecord.IndustryType = field.NewInt64(tableName, "industry_type")
+	_formRecord.ChatHistory = field.NewString(tableName, "chat_history")
+	_formRecord.FormData = field.NewString(tableName, "form_data")
+	_formRecord.FormValue = field.NewString(tableName, "form_value")
+	_formRecord.OrgID = field.NewInt64(tableName, "org_id")
+	_formRecord.Status = field.NewInt64(tableName, "status")
+	_formRecord.RequestData = field.NewString(tableName, "request_data")
+	_formRecord.ResponseData = field.NewString(tableName, "response_data")
+	_formRecord.CreatedAt = field.NewTime(tableName, "created_at")
+	_formRecord.UpdatedAt = field.NewTime(tableName, "updated_at")
+
+	_formRecord.fillFieldMap()
+
+	return _formRecord
+}
+
+type formRecord struct {
+	formRecordDo
+
+	ALL          field.Asterisk
+	ID           field.String // 主键id
+	ExternalID   field.String // 外部id
+	IndustryType field.Int64  // 评分规则代码 0 通用 1 教育
+	ChatHistory  field.String // 通话记录
+	FormData     field.String // 表单数据
+	FormValue    field.String // 表单结果
+	OrgID        field.Int64  // 机构 ID
+	Status       field.Int64  // 状态 1 入库 2 已判断 3 已回调
+	RequestData  field.String
+	ResponseData field.String
+	CreatedAt    field.Time // Create Time | 创建日期
+	UpdatedAt    field.Time // Update Time | 修改日期
+
+	fieldMap map[string]field.Expr
+}
+
+func (f formRecord) Table(newTableName string) *formRecord {
+	f.formRecordDo.UseTable(newTableName)
+	return f.updateTableName(newTableName)
+}
+
+func (f formRecord) As(alias string) *formRecord {
+	f.formRecordDo.DO = *(f.formRecordDo.As(alias).(*gen.DO))
+	return f.updateTableName(alias)
+}
+
+func (f *formRecord) updateTableName(table string) *formRecord {
+	f.ALL = field.NewAsterisk(table)
+	f.ID = field.NewString(table, "id")
+	f.ExternalID = field.NewString(table, "external_id")
+	f.IndustryType = field.NewInt64(table, "industry_type")
+	f.ChatHistory = field.NewString(table, "chat_history")
+	f.FormData = field.NewString(table, "form_data")
+	f.FormValue = field.NewString(table, "form_value")
+	f.OrgID = field.NewInt64(table, "org_id")
+	f.Status = field.NewInt64(table, "status")
+	f.RequestData = field.NewString(table, "request_data")
+	f.ResponseData = field.NewString(table, "response_data")
+	f.CreatedAt = field.NewTime(table, "created_at")
+	f.UpdatedAt = field.NewTime(table, "updated_at")
+
+	f.fillFieldMap()
+
+	return f
+}
+
+func (f *formRecord) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := f.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (f *formRecord) fillFieldMap() {
+	f.fieldMap = make(map[string]field.Expr, 12)
+	f.fieldMap["id"] = f.ID
+	f.fieldMap["external_id"] = f.ExternalID
+	f.fieldMap["industry_type"] = f.IndustryType
+	f.fieldMap["chat_history"] = f.ChatHistory
+	f.fieldMap["form_data"] = f.FormData
+	f.fieldMap["form_value"] = f.FormValue
+	f.fieldMap["org_id"] = f.OrgID
+	f.fieldMap["status"] = f.Status
+	f.fieldMap["request_data"] = f.RequestData
+	f.fieldMap["response_data"] = f.ResponseData
+	f.fieldMap["created_at"] = f.CreatedAt
+	f.fieldMap["updated_at"] = f.UpdatedAt
+}
+
+func (f formRecord) clone(db *gorm.DB) formRecord {
+	f.formRecordDo.ReplaceConnPool(db.Statement.ConnPool)
+	return f
+}
+
+func (f formRecord) replaceDB(db *gorm.DB) formRecord {
+	f.formRecordDo.ReplaceDB(db)
+	return f
+}
+
+type formRecordDo struct{ gen.DO }
+
+type IFormRecordDo interface {
+	gen.SubQuery
+	Debug() IFormRecordDo
+	WithContext(ctx context.Context) IFormRecordDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IFormRecordDo
+	WriteDB() IFormRecordDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IFormRecordDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IFormRecordDo
+	Not(conds ...gen.Condition) IFormRecordDo
+	Or(conds ...gen.Condition) IFormRecordDo
+	Select(conds ...field.Expr) IFormRecordDo
+	Where(conds ...gen.Condition) IFormRecordDo
+	Order(conds ...field.Expr) IFormRecordDo
+	Distinct(cols ...field.Expr) IFormRecordDo
+	Omit(cols ...field.Expr) IFormRecordDo
+	Join(table schema.Tabler, on ...field.Expr) IFormRecordDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IFormRecordDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IFormRecordDo
+	Group(cols ...field.Expr) IFormRecordDo
+	Having(conds ...gen.Condition) IFormRecordDo
+	Limit(limit int) IFormRecordDo
+	Offset(offset int) IFormRecordDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IFormRecordDo
+	Unscoped() IFormRecordDo
+	Create(values ...*model.FormRecord) error
+	CreateInBatches(values []*model.FormRecord, batchSize int) error
+	Save(values ...*model.FormRecord) error
+	First() (*model.FormRecord, error)
+	Take() (*model.FormRecord, error)
+	Last() (*model.FormRecord, error)
+	Find() ([]*model.FormRecord, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.FormRecord, err error)
+	FindInBatches(result *[]*model.FormRecord, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.FormRecord) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IFormRecordDo
+	Assign(attrs ...field.AssignExpr) IFormRecordDo
+	Joins(fields ...field.RelationField) IFormRecordDo
+	Preload(fields ...field.RelationField) IFormRecordDo
+	FirstOrInit() (*model.FormRecord, error)
+	FirstOrCreate() (*model.FormRecord, error)
+	FindByPage(offset int, limit int) (result []*model.FormRecord, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IFormRecordDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (f formRecordDo) Debug() IFormRecordDo {
+	return f.withDO(f.DO.Debug())
+}
+
+func (f formRecordDo) WithContext(ctx context.Context) IFormRecordDo {
+	return f.withDO(f.DO.WithContext(ctx))
+}
+
+func (f formRecordDo) ReadDB() IFormRecordDo {
+	return f.Clauses(dbresolver.Read)
+}
+
+func (f formRecordDo) WriteDB() IFormRecordDo {
+	return f.Clauses(dbresolver.Write)
+}
+
+func (f formRecordDo) Session(config *gorm.Session) IFormRecordDo {
+	return f.withDO(f.DO.Session(config))
+}
+
+func (f formRecordDo) Clauses(conds ...clause.Expression) IFormRecordDo {
+	return f.withDO(f.DO.Clauses(conds...))
+}
+
+func (f formRecordDo) Returning(value interface{}, columns ...string) IFormRecordDo {
+	return f.withDO(f.DO.Returning(value, columns...))
+}
+
+func (f formRecordDo) Not(conds ...gen.Condition) IFormRecordDo {
+	return f.withDO(f.DO.Not(conds...))
+}
+
+func (f formRecordDo) Or(conds ...gen.Condition) IFormRecordDo {
+	return f.withDO(f.DO.Or(conds...))
+}
+
+func (f formRecordDo) Select(conds ...field.Expr) IFormRecordDo {
+	return f.withDO(f.DO.Select(conds...))
+}
+
+func (f formRecordDo) Where(conds ...gen.Condition) IFormRecordDo {
+	return f.withDO(f.DO.Where(conds...))
+}
+
+func (f formRecordDo) Order(conds ...field.Expr) IFormRecordDo {
+	return f.withDO(f.DO.Order(conds...))
+}
+
+func (f formRecordDo) Distinct(cols ...field.Expr) IFormRecordDo {
+	return f.withDO(f.DO.Distinct(cols...))
+}
+
+func (f formRecordDo) Omit(cols ...field.Expr) IFormRecordDo {
+	return f.withDO(f.DO.Omit(cols...))
+}
+
+func (f formRecordDo) Join(table schema.Tabler, on ...field.Expr) IFormRecordDo {
+	return f.withDO(f.DO.Join(table, on...))
+}
+
+func (f formRecordDo) LeftJoin(table schema.Tabler, on ...field.Expr) IFormRecordDo {
+	return f.withDO(f.DO.LeftJoin(table, on...))
+}
+
+func (f formRecordDo) RightJoin(table schema.Tabler, on ...field.Expr) IFormRecordDo {
+	return f.withDO(f.DO.RightJoin(table, on...))
+}
+
+func (f formRecordDo) Group(cols ...field.Expr) IFormRecordDo {
+	return f.withDO(f.DO.Group(cols...))
+}
+
+func (f formRecordDo) Having(conds ...gen.Condition) IFormRecordDo {
+	return f.withDO(f.DO.Having(conds...))
+}
+
+func (f formRecordDo) Limit(limit int) IFormRecordDo {
+	return f.withDO(f.DO.Limit(limit))
+}
+
+func (f formRecordDo) Offset(offset int) IFormRecordDo {
+	return f.withDO(f.DO.Offset(offset))
+}
+
+func (f formRecordDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IFormRecordDo {
+	return f.withDO(f.DO.Scopes(funcs...))
+}
+
+func (f formRecordDo) Unscoped() IFormRecordDo {
+	return f.withDO(f.DO.Unscoped())
+}
+
+func (f formRecordDo) Create(values ...*model.FormRecord) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return f.DO.Create(values)
+}
+
+func (f formRecordDo) CreateInBatches(values []*model.FormRecord, batchSize int) error {
+	return f.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (f formRecordDo) Save(values ...*model.FormRecord) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return f.DO.Save(values)
+}
+
+func (f formRecordDo) First() (*model.FormRecord, error) {
+	if result, err := f.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.FormRecord), nil
+	}
+}
+
+func (f formRecordDo) Take() (*model.FormRecord, error) {
+	if result, err := f.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.FormRecord), nil
+	}
+}
+
+func (f formRecordDo) Last() (*model.FormRecord, error) {
+	if result, err := f.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.FormRecord), nil
+	}
+}
+
+func (f formRecordDo) Find() ([]*model.FormRecord, error) {
+	result, err := f.DO.Find()
+	return result.([]*model.FormRecord), err
+}
+
+func (f formRecordDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.FormRecord, err error) {
+	buf := make([]*model.FormRecord, 0, batchSize)
+	err = f.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (f formRecordDo) FindInBatches(result *[]*model.FormRecord, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return f.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (f formRecordDo) Attrs(attrs ...field.AssignExpr) IFormRecordDo {
+	return f.withDO(f.DO.Attrs(attrs...))
+}
+
+func (f formRecordDo) Assign(attrs ...field.AssignExpr) IFormRecordDo {
+	return f.withDO(f.DO.Assign(attrs...))
+}
+
+func (f formRecordDo) Joins(fields ...field.RelationField) IFormRecordDo {
+	for _, _f := range fields {
+		f = *f.withDO(f.DO.Joins(_f))
+	}
+	return &f
+}
+
+func (f formRecordDo) Preload(fields ...field.RelationField) IFormRecordDo {
+	for _, _f := range fields {
+		f = *f.withDO(f.DO.Preload(_f))
+	}
+	return &f
+}
+
+func (f formRecordDo) FirstOrInit() (*model.FormRecord, error) {
+	if result, err := f.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.FormRecord), nil
+	}
+}
+
+func (f formRecordDo) FirstOrCreate() (*model.FormRecord, error) {
+	if result, err := f.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.FormRecord), nil
+	}
+}
+
+func (f formRecordDo) FindByPage(offset int, limit int) (result []*model.FormRecord, count int64, err error) {
+	result, err = f.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = f.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (f formRecordDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = f.Count()
+	if err != nil {
+		return
+	}
+
+	err = f.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (f formRecordDo) Scan(result interface{}) (err error) {
+	return f.DO.Scan(result)
+}
+
+func (f formRecordDo) Delete(models ...*model.FormRecord) (result gen.ResultInfo, err error) {
+	return f.DO.Delete(models)
+}
+
+func (f *formRecordDo) withDO(do gen.Dao) *formRecordDo {
+	f.DO = *do.(*gen.DO)
+	return f
+}

+ 455 - 0
database/dao/wechat/query/gen.go

@@ -0,0 +1,455 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+	"database/sql"
+
+	"gorm.io/gorm"
+
+	"gorm.io/gen"
+
+	"gorm.io/plugin/dbresolver"
+)
+
+var (
+	Q                   = new(Query)
+	Agent               *agent
+	AliyunAvatar        *aliyunAvatar
+	AllocAgent          *allocAgent
+	BatchMsg            *batchMsg
+	BatchMsgCopy1       *batchMsgCopy1
+	Category            *category
+	ChatRecord          *chatRecord
+	ChatSession         *chatSession
+	Contact             *contact
+	CreditBalance       *creditBalance
+	CreditUsage         *creditUsage
+	Employee            *employee
+	EmployeeConfig      *employeeConfig
+	FormRecord          *formRecord
+	IntentOrg           *intentOrg
+	IntentRecord        *intentRecord
+	Label               *label
+	LabelRelationship   *labelRelationship
+	LabelTagging        *labelTagging
+	MessageRecord       *messageRecord
+	MismatchRecord      *mismatchRecord
+	Msg                 *msg
+	PayRecharge         *payRecharge
+	Record              *record
+	Server              *server
+	SopNode             *sopNode
+	SopStage            *sopStage
+	SopTask             *sopTask
+	Token               *token
+	Tutorial            *tutorial
+	UsageDetail         *usageDetail
+	UsageStatisticDay   *usageStatisticDay
+	UsageStatisticHour  *usageStatisticHour
+	UsageStatisticMonth *usageStatisticMonth
+	UsageTotal          *usageTotal
+	Whatsapp            *whatsapp
+	WhatsappChannel     *whatsappChannel
+	WorkExperience      *workExperience
+	WpChatroom          *wpChatroom
+	WpChatroomMember    *wpChatroomMember
+	Wx                  *wx
+	WxCard              *wxCard
+	WxCardUser          *wxCardUser
+	WxCardVisit         *wxCardVisit
+	XunjiContact        *xunjiContact
+)
+
+func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
+	*Q = *Use(db, opts...)
+	Agent = &Q.Agent
+	AliyunAvatar = &Q.AliyunAvatar
+	AllocAgent = &Q.AllocAgent
+	BatchMsg = &Q.BatchMsg
+	BatchMsgCopy1 = &Q.BatchMsgCopy1
+	Category = &Q.Category
+	ChatRecord = &Q.ChatRecord
+	ChatSession = &Q.ChatSession
+	Contact = &Q.Contact
+	CreditBalance = &Q.CreditBalance
+	CreditUsage = &Q.CreditUsage
+	Employee = &Q.Employee
+	EmployeeConfig = &Q.EmployeeConfig
+	FormRecord = &Q.FormRecord
+	IntentOrg = &Q.IntentOrg
+	IntentRecord = &Q.IntentRecord
+	Label = &Q.Label
+	LabelRelationship = &Q.LabelRelationship
+	LabelTagging = &Q.LabelTagging
+	MessageRecord = &Q.MessageRecord
+	MismatchRecord = &Q.MismatchRecord
+	Msg = &Q.Msg
+	PayRecharge = &Q.PayRecharge
+	Record = &Q.Record
+	Server = &Q.Server
+	SopNode = &Q.SopNode
+	SopStage = &Q.SopStage
+	SopTask = &Q.SopTask
+	Token = &Q.Token
+	Tutorial = &Q.Tutorial
+	UsageDetail = &Q.UsageDetail
+	UsageStatisticDay = &Q.UsageStatisticDay
+	UsageStatisticHour = &Q.UsageStatisticHour
+	UsageStatisticMonth = &Q.UsageStatisticMonth
+	UsageTotal = &Q.UsageTotal
+	Whatsapp = &Q.Whatsapp
+	WhatsappChannel = &Q.WhatsappChannel
+	WorkExperience = &Q.WorkExperience
+	WpChatroom = &Q.WpChatroom
+	WpChatroomMember = &Q.WpChatroomMember
+	Wx = &Q.Wx
+	WxCard = &Q.WxCard
+	WxCardUser = &Q.WxCardUser
+	WxCardVisit = &Q.WxCardVisit
+	XunjiContact = &Q.XunjiContact
+}
+
+func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
+	return &Query{
+		db:                  db,
+		Agent:               newAgent(db, opts...),
+		AliyunAvatar:        newAliyunAvatar(db, opts...),
+		AllocAgent:          newAllocAgent(db, opts...),
+		BatchMsg:            newBatchMsg(db, opts...),
+		BatchMsgCopy1:       newBatchMsgCopy1(db, opts...),
+		Category:            newCategory(db, opts...),
+		ChatRecord:          newChatRecord(db, opts...),
+		ChatSession:         newChatSession(db, opts...),
+		Contact:             newContact(db, opts...),
+		CreditBalance:       newCreditBalance(db, opts...),
+		CreditUsage:         newCreditUsage(db, opts...),
+		Employee:            newEmployee(db, opts...),
+		EmployeeConfig:      newEmployeeConfig(db, opts...),
+		FormRecord:          newFormRecord(db, opts...),
+		IntentOrg:           newIntentOrg(db, opts...),
+		IntentRecord:        newIntentRecord(db, opts...),
+		Label:               newLabel(db, opts...),
+		LabelRelationship:   newLabelRelationship(db, opts...),
+		LabelTagging:        newLabelTagging(db, opts...),
+		MessageRecord:       newMessageRecord(db, opts...),
+		MismatchRecord:      newMismatchRecord(db, opts...),
+		Msg:                 newMsg(db, opts...),
+		PayRecharge:         newPayRecharge(db, opts...),
+		Record:              newRecord(db, opts...),
+		Server:              newServer(db, opts...),
+		SopNode:             newSopNode(db, opts...),
+		SopStage:            newSopStage(db, opts...),
+		SopTask:             newSopTask(db, opts...),
+		Token:               newToken(db, opts...),
+		Tutorial:            newTutorial(db, opts...),
+		UsageDetail:         newUsageDetail(db, opts...),
+		UsageStatisticDay:   newUsageStatisticDay(db, opts...),
+		UsageStatisticHour:  newUsageStatisticHour(db, opts...),
+		UsageStatisticMonth: newUsageStatisticMonth(db, opts...),
+		UsageTotal:          newUsageTotal(db, opts...),
+		Whatsapp:            newWhatsapp(db, opts...),
+		WhatsappChannel:     newWhatsappChannel(db, opts...),
+		WorkExperience:      newWorkExperience(db, opts...),
+		WpChatroom:          newWpChatroom(db, opts...),
+		WpChatroomMember:    newWpChatroomMember(db, opts...),
+		Wx:                  newWx(db, opts...),
+		WxCard:              newWxCard(db, opts...),
+		WxCardUser:          newWxCardUser(db, opts...),
+		WxCardVisit:         newWxCardVisit(db, opts...),
+		XunjiContact:        newXunjiContact(db, opts...),
+	}
+}
+
+type Query struct {
+	db *gorm.DB
+
+	Agent               agent
+	AliyunAvatar        aliyunAvatar
+	AllocAgent          allocAgent
+	BatchMsg            batchMsg
+	BatchMsgCopy1       batchMsgCopy1
+	Category            category
+	ChatRecord          chatRecord
+	ChatSession         chatSession
+	Contact             contact
+	CreditBalance       creditBalance
+	CreditUsage         creditUsage
+	Employee            employee
+	EmployeeConfig      employeeConfig
+	FormRecord          formRecord
+	IntentOrg           intentOrg
+	IntentRecord        intentRecord
+	Label               label
+	LabelRelationship   labelRelationship
+	LabelTagging        labelTagging
+	MessageRecord       messageRecord
+	MismatchRecord      mismatchRecord
+	Msg                 msg
+	PayRecharge         payRecharge
+	Record              record
+	Server              server
+	SopNode             sopNode
+	SopStage            sopStage
+	SopTask             sopTask
+	Token               token
+	Tutorial            tutorial
+	UsageDetail         usageDetail
+	UsageStatisticDay   usageStatisticDay
+	UsageStatisticHour  usageStatisticHour
+	UsageStatisticMonth usageStatisticMonth
+	UsageTotal          usageTotal
+	Whatsapp            whatsapp
+	WhatsappChannel     whatsappChannel
+	WorkExperience      workExperience
+	WpChatroom          wpChatroom
+	WpChatroomMember    wpChatroomMember
+	Wx                  wx
+	WxCard              wxCard
+	WxCardUser          wxCardUser
+	WxCardVisit         wxCardVisit
+	XunjiContact        xunjiContact
+}
+
+func (q *Query) Available() bool { return q.db != nil }
+
+func (q *Query) clone(db *gorm.DB) *Query {
+	return &Query{
+		db:                  db,
+		Agent:               q.Agent.clone(db),
+		AliyunAvatar:        q.AliyunAvatar.clone(db),
+		AllocAgent:          q.AllocAgent.clone(db),
+		BatchMsg:            q.BatchMsg.clone(db),
+		BatchMsgCopy1:       q.BatchMsgCopy1.clone(db),
+		Category:            q.Category.clone(db),
+		ChatRecord:          q.ChatRecord.clone(db),
+		ChatSession:         q.ChatSession.clone(db),
+		Contact:             q.Contact.clone(db),
+		CreditBalance:       q.CreditBalance.clone(db),
+		CreditUsage:         q.CreditUsage.clone(db),
+		Employee:            q.Employee.clone(db),
+		EmployeeConfig:      q.EmployeeConfig.clone(db),
+		FormRecord:          q.FormRecord.clone(db),
+		IntentOrg:           q.IntentOrg.clone(db),
+		IntentRecord:        q.IntentRecord.clone(db),
+		Label:               q.Label.clone(db),
+		LabelRelationship:   q.LabelRelationship.clone(db),
+		LabelTagging:        q.LabelTagging.clone(db),
+		MessageRecord:       q.MessageRecord.clone(db),
+		MismatchRecord:      q.MismatchRecord.clone(db),
+		Msg:                 q.Msg.clone(db),
+		PayRecharge:         q.PayRecharge.clone(db),
+		Record:              q.Record.clone(db),
+		Server:              q.Server.clone(db),
+		SopNode:             q.SopNode.clone(db),
+		SopStage:            q.SopStage.clone(db),
+		SopTask:             q.SopTask.clone(db),
+		Token:               q.Token.clone(db),
+		Tutorial:            q.Tutorial.clone(db),
+		UsageDetail:         q.UsageDetail.clone(db),
+		UsageStatisticDay:   q.UsageStatisticDay.clone(db),
+		UsageStatisticHour:  q.UsageStatisticHour.clone(db),
+		UsageStatisticMonth: q.UsageStatisticMonth.clone(db),
+		UsageTotal:          q.UsageTotal.clone(db),
+		Whatsapp:            q.Whatsapp.clone(db),
+		WhatsappChannel:     q.WhatsappChannel.clone(db),
+		WorkExperience:      q.WorkExperience.clone(db),
+		WpChatroom:          q.WpChatroom.clone(db),
+		WpChatroomMember:    q.WpChatroomMember.clone(db),
+		Wx:                  q.Wx.clone(db),
+		WxCard:              q.WxCard.clone(db),
+		WxCardUser:          q.WxCardUser.clone(db),
+		WxCardVisit:         q.WxCardVisit.clone(db),
+		XunjiContact:        q.XunjiContact.clone(db),
+	}
+}
+
+func (q *Query) ReadDB() *Query {
+	return q.ReplaceDB(q.db.Clauses(dbresolver.Read))
+}
+
+func (q *Query) WriteDB() *Query {
+	return q.ReplaceDB(q.db.Clauses(dbresolver.Write))
+}
+
+func (q *Query) ReplaceDB(db *gorm.DB) *Query {
+	return &Query{
+		db:                  db,
+		Agent:               q.Agent.replaceDB(db),
+		AliyunAvatar:        q.AliyunAvatar.replaceDB(db),
+		AllocAgent:          q.AllocAgent.replaceDB(db),
+		BatchMsg:            q.BatchMsg.replaceDB(db),
+		BatchMsgCopy1:       q.BatchMsgCopy1.replaceDB(db),
+		Category:            q.Category.replaceDB(db),
+		ChatRecord:          q.ChatRecord.replaceDB(db),
+		ChatSession:         q.ChatSession.replaceDB(db),
+		Contact:             q.Contact.replaceDB(db),
+		CreditBalance:       q.CreditBalance.replaceDB(db),
+		CreditUsage:         q.CreditUsage.replaceDB(db),
+		Employee:            q.Employee.replaceDB(db),
+		EmployeeConfig:      q.EmployeeConfig.replaceDB(db),
+		FormRecord:          q.FormRecord.replaceDB(db),
+		IntentOrg:           q.IntentOrg.replaceDB(db),
+		IntentRecord:        q.IntentRecord.replaceDB(db),
+		Label:               q.Label.replaceDB(db),
+		LabelRelationship:   q.LabelRelationship.replaceDB(db),
+		LabelTagging:        q.LabelTagging.replaceDB(db),
+		MessageRecord:       q.MessageRecord.replaceDB(db),
+		MismatchRecord:      q.MismatchRecord.replaceDB(db),
+		Msg:                 q.Msg.replaceDB(db),
+		PayRecharge:         q.PayRecharge.replaceDB(db),
+		Record:              q.Record.replaceDB(db),
+		Server:              q.Server.replaceDB(db),
+		SopNode:             q.SopNode.replaceDB(db),
+		SopStage:            q.SopStage.replaceDB(db),
+		SopTask:             q.SopTask.replaceDB(db),
+		Token:               q.Token.replaceDB(db),
+		Tutorial:            q.Tutorial.replaceDB(db),
+		UsageDetail:         q.UsageDetail.replaceDB(db),
+		UsageStatisticDay:   q.UsageStatisticDay.replaceDB(db),
+		UsageStatisticHour:  q.UsageStatisticHour.replaceDB(db),
+		UsageStatisticMonth: q.UsageStatisticMonth.replaceDB(db),
+		UsageTotal:          q.UsageTotal.replaceDB(db),
+		Whatsapp:            q.Whatsapp.replaceDB(db),
+		WhatsappChannel:     q.WhatsappChannel.replaceDB(db),
+		WorkExperience:      q.WorkExperience.replaceDB(db),
+		WpChatroom:          q.WpChatroom.replaceDB(db),
+		WpChatroomMember:    q.WpChatroomMember.replaceDB(db),
+		Wx:                  q.Wx.replaceDB(db),
+		WxCard:              q.WxCard.replaceDB(db),
+		WxCardUser:          q.WxCardUser.replaceDB(db),
+		WxCardVisit:         q.WxCardVisit.replaceDB(db),
+		XunjiContact:        q.XunjiContact.replaceDB(db),
+	}
+}
+
+type queryCtx struct {
+	Agent               IAgentDo
+	AliyunAvatar        IAliyunAvatarDo
+	AllocAgent          IAllocAgentDo
+	BatchMsg            IBatchMsgDo
+	BatchMsgCopy1       IBatchMsgCopy1Do
+	Category            ICategoryDo
+	ChatRecord          IChatRecordDo
+	ChatSession         IChatSessionDo
+	Contact             IContactDo
+	CreditBalance       ICreditBalanceDo
+	CreditUsage         ICreditUsageDo
+	Employee            IEmployeeDo
+	EmployeeConfig      IEmployeeConfigDo
+	FormRecord          IFormRecordDo
+	IntentOrg           IIntentOrgDo
+	IntentRecord        IIntentRecordDo
+	Label               ILabelDo
+	LabelRelationship   ILabelRelationshipDo
+	LabelTagging        ILabelTaggingDo
+	MessageRecord       IMessageRecordDo
+	MismatchRecord      IMismatchRecordDo
+	Msg                 IMsgDo
+	PayRecharge         IPayRechargeDo
+	Record              IRecordDo
+	Server              IServerDo
+	SopNode             ISopNodeDo
+	SopStage            ISopStageDo
+	SopTask             ISopTaskDo
+	Token               ITokenDo
+	Tutorial            ITutorialDo
+	UsageDetail         IUsageDetailDo
+	UsageStatisticDay   IUsageStatisticDayDo
+	UsageStatisticHour  IUsageStatisticHourDo
+	UsageStatisticMonth IUsageStatisticMonthDo
+	UsageTotal          IUsageTotalDo
+	Whatsapp            IWhatsappDo
+	WhatsappChannel     IWhatsappChannelDo
+	WorkExperience      IWorkExperienceDo
+	WpChatroom          IWpChatroomDo
+	WpChatroomMember    IWpChatroomMemberDo
+	Wx                  IWxDo
+	WxCard              IWxCardDo
+	WxCardUser          IWxCardUserDo
+	WxCardVisit         IWxCardVisitDo
+	XunjiContact        IXunjiContactDo
+}
+
+func (q *Query) WithContext(ctx context.Context) *queryCtx {
+	return &queryCtx{
+		Agent:               q.Agent.WithContext(ctx),
+		AliyunAvatar:        q.AliyunAvatar.WithContext(ctx),
+		AllocAgent:          q.AllocAgent.WithContext(ctx),
+		BatchMsg:            q.BatchMsg.WithContext(ctx),
+		BatchMsgCopy1:       q.BatchMsgCopy1.WithContext(ctx),
+		Category:            q.Category.WithContext(ctx),
+		ChatRecord:          q.ChatRecord.WithContext(ctx),
+		ChatSession:         q.ChatSession.WithContext(ctx),
+		Contact:             q.Contact.WithContext(ctx),
+		CreditBalance:       q.CreditBalance.WithContext(ctx),
+		CreditUsage:         q.CreditUsage.WithContext(ctx),
+		Employee:            q.Employee.WithContext(ctx),
+		EmployeeConfig:      q.EmployeeConfig.WithContext(ctx),
+		FormRecord:          q.FormRecord.WithContext(ctx),
+		IntentOrg:           q.IntentOrg.WithContext(ctx),
+		IntentRecord:        q.IntentRecord.WithContext(ctx),
+		Label:               q.Label.WithContext(ctx),
+		LabelRelationship:   q.LabelRelationship.WithContext(ctx),
+		LabelTagging:        q.LabelTagging.WithContext(ctx),
+		MessageRecord:       q.MessageRecord.WithContext(ctx),
+		MismatchRecord:      q.MismatchRecord.WithContext(ctx),
+		Msg:                 q.Msg.WithContext(ctx),
+		PayRecharge:         q.PayRecharge.WithContext(ctx),
+		Record:              q.Record.WithContext(ctx),
+		Server:              q.Server.WithContext(ctx),
+		SopNode:             q.SopNode.WithContext(ctx),
+		SopStage:            q.SopStage.WithContext(ctx),
+		SopTask:             q.SopTask.WithContext(ctx),
+		Token:               q.Token.WithContext(ctx),
+		Tutorial:            q.Tutorial.WithContext(ctx),
+		UsageDetail:         q.UsageDetail.WithContext(ctx),
+		UsageStatisticDay:   q.UsageStatisticDay.WithContext(ctx),
+		UsageStatisticHour:  q.UsageStatisticHour.WithContext(ctx),
+		UsageStatisticMonth: q.UsageStatisticMonth.WithContext(ctx),
+		UsageTotal:          q.UsageTotal.WithContext(ctx),
+		Whatsapp:            q.Whatsapp.WithContext(ctx),
+		WhatsappChannel:     q.WhatsappChannel.WithContext(ctx),
+		WorkExperience:      q.WorkExperience.WithContext(ctx),
+		WpChatroom:          q.WpChatroom.WithContext(ctx),
+		WpChatroomMember:    q.WpChatroomMember.WithContext(ctx),
+		Wx:                  q.Wx.WithContext(ctx),
+		WxCard:              q.WxCard.WithContext(ctx),
+		WxCardUser:          q.WxCardUser.WithContext(ctx),
+		WxCardVisit:         q.WxCardVisit.WithContext(ctx),
+		XunjiContact:        q.XunjiContact.WithContext(ctx),
+	}
+}
+
+func (q *Query) Transaction(fc func(tx *Query) error, opts ...*sql.TxOptions) error {
+	return q.db.Transaction(func(tx *gorm.DB) error { return fc(q.clone(tx)) }, opts...)
+}
+
+func (q *Query) Begin(opts ...*sql.TxOptions) *QueryTx {
+	tx := q.db.Begin(opts...)
+	return &QueryTx{Query: q.clone(tx), Error: tx.Error}
+}
+
+type QueryTx struct {
+	*Query
+	Error error
+}
+
+func (q *QueryTx) Commit() error {
+	return q.db.Commit().Error
+}
+
+func (q *QueryTx) Rollback() error {
+	return q.db.Rollback().Error
+}
+
+func (q *QueryTx) SavePoint(name string) error {
+	return q.db.SavePoint(name).Error
+}
+
+func (q *QueryTx) RollbackTo(name string) error {
+	return q.db.RollbackTo(name).Error
+}

+ 420 - 0
database/dao/wechat/query/intent_org.gen.go

@@ -0,0 +1,420 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newIntentOrg(db *gorm.DB, opts ...gen.DOOption) intentOrg {
+	_intentOrg := intentOrg{}
+
+	_intentOrg.intentOrgDo.UseDB(db, opts...)
+	_intentOrg.intentOrgDo.UseModel(&model.IntentOrg{})
+
+	tableName := _intentOrg.intentOrgDo.TableName()
+	_intentOrg.ALL = field.NewAsterisk(tableName)
+	_intentOrg.ID = field.NewInt64(tableName, "id")
+	_intentOrg.Name = field.NewString(tableName, "name")
+	_intentOrg.APIKey = field.NewString(tableName, "api_key")
+	_intentOrg.OpenaiBase = field.NewString(tableName, "openai_base")
+	_intentOrg.OpenaiKey = field.NewString(tableName, "openai_key")
+	_intentOrg.IntentCallback = field.NewString(tableName, "intent_callback")
+	_intentOrg.MismatchCallback = field.NewString(tableName, "mismatch_callback")
+	_intentOrg.Status = field.NewInt64(tableName, "status")
+	_intentOrg.DeletedAt = field.NewField(tableName, "deleted_at")
+	_intentOrg.CreatedAt = field.NewTime(tableName, "created_at")
+	_intentOrg.UpdatedAt = field.NewTime(tableName, "updated_at")
+
+	_intentOrg.fillFieldMap()
+
+	return _intentOrg
+}
+
+type intentOrg struct {
+	intentOrgDo
+
+	ALL              field.Asterisk
+	ID               field.Int64
+	Name             field.String // 机构名称
+	APIKey           field.String
+	OpenaiBase       field.String
+	OpenaiKey        field.String
+	IntentCallback   field.String // 意向度结果推送地址
+	MismatchCallback field.String // 未匹配结果推送地址
+	Status           field.Int64  // 状态 1 正常 2 禁用
+	DeletedAt        field.Field  // Delete Time | 删除日期
+	CreatedAt        field.Time   // Create Time | 创建日期
+	UpdatedAt        field.Time   // Update Time | 修改日期
+
+	fieldMap map[string]field.Expr
+}
+
+func (i intentOrg) Table(newTableName string) *intentOrg {
+	i.intentOrgDo.UseTable(newTableName)
+	return i.updateTableName(newTableName)
+}
+
+func (i intentOrg) As(alias string) *intentOrg {
+	i.intentOrgDo.DO = *(i.intentOrgDo.As(alias).(*gen.DO))
+	return i.updateTableName(alias)
+}
+
+func (i *intentOrg) updateTableName(table string) *intentOrg {
+	i.ALL = field.NewAsterisk(table)
+	i.ID = field.NewInt64(table, "id")
+	i.Name = field.NewString(table, "name")
+	i.APIKey = field.NewString(table, "api_key")
+	i.OpenaiBase = field.NewString(table, "openai_base")
+	i.OpenaiKey = field.NewString(table, "openai_key")
+	i.IntentCallback = field.NewString(table, "intent_callback")
+	i.MismatchCallback = field.NewString(table, "mismatch_callback")
+	i.Status = field.NewInt64(table, "status")
+	i.DeletedAt = field.NewField(table, "deleted_at")
+	i.CreatedAt = field.NewTime(table, "created_at")
+	i.UpdatedAt = field.NewTime(table, "updated_at")
+
+	i.fillFieldMap()
+
+	return i
+}
+
+func (i *intentOrg) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := i.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (i *intentOrg) fillFieldMap() {
+	i.fieldMap = make(map[string]field.Expr, 11)
+	i.fieldMap["id"] = i.ID
+	i.fieldMap["name"] = i.Name
+	i.fieldMap["api_key"] = i.APIKey
+	i.fieldMap["openai_base"] = i.OpenaiBase
+	i.fieldMap["openai_key"] = i.OpenaiKey
+	i.fieldMap["intent_callback"] = i.IntentCallback
+	i.fieldMap["mismatch_callback"] = i.MismatchCallback
+	i.fieldMap["status"] = i.Status
+	i.fieldMap["deleted_at"] = i.DeletedAt
+	i.fieldMap["created_at"] = i.CreatedAt
+	i.fieldMap["updated_at"] = i.UpdatedAt
+}
+
+func (i intentOrg) clone(db *gorm.DB) intentOrg {
+	i.intentOrgDo.ReplaceConnPool(db.Statement.ConnPool)
+	return i
+}
+
+func (i intentOrg) replaceDB(db *gorm.DB) intentOrg {
+	i.intentOrgDo.ReplaceDB(db)
+	return i
+}
+
+type intentOrgDo struct{ gen.DO }
+
+type IIntentOrgDo interface {
+	gen.SubQuery
+	Debug() IIntentOrgDo
+	WithContext(ctx context.Context) IIntentOrgDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IIntentOrgDo
+	WriteDB() IIntentOrgDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IIntentOrgDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IIntentOrgDo
+	Not(conds ...gen.Condition) IIntentOrgDo
+	Or(conds ...gen.Condition) IIntentOrgDo
+	Select(conds ...field.Expr) IIntentOrgDo
+	Where(conds ...gen.Condition) IIntentOrgDo
+	Order(conds ...field.Expr) IIntentOrgDo
+	Distinct(cols ...field.Expr) IIntentOrgDo
+	Omit(cols ...field.Expr) IIntentOrgDo
+	Join(table schema.Tabler, on ...field.Expr) IIntentOrgDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IIntentOrgDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IIntentOrgDo
+	Group(cols ...field.Expr) IIntentOrgDo
+	Having(conds ...gen.Condition) IIntentOrgDo
+	Limit(limit int) IIntentOrgDo
+	Offset(offset int) IIntentOrgDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IIntentOrgDo
+	Unscoped() IIntentOrgDo
+	Create(values ...*model.IntentOrg) error
+	CreateInBatches(values []*model.IntentOrg, batchSize int) error
+	Save(values ...*model.IntentOrg) error
+	First() (*model.IntentOrg, error)
+	Take() (*model.IntentOrg, error)
+	Last() (*model.IntentOrg, error)
+	Find() ([]*model.IntentOrg, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.IntentOrg, err error)
+	FindInBatches(result *[]*model.IntentOrg, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.IntentOrg) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IIntentOrgDo
+	Assign(attrs ...field.AssignExpr) IIntentOrgDo
+	Joins(fields ...field.RelationField) IIntentOrgDo
+	Preload(fields ...field.RelationField) IIntentOrgDo
+	FirstOrInit() (*model.IntentOrg, error)
+	FirstOrCreate() (*model.IntentOrg, error)
+	FindByPage(offset int, limit int) (result []*model.IntentOrg, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IIntentOrgDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (i intentOrgDo) Debug() IIntentOrgDo {
+	return i.withDO(i.DO.Debug())
+}
+
+func (i intentOrgDo) WithContext(ctx context.Context) IIntentOrgDo {
+	return i.withDO(i.DO.WithContext(ctx))
+}
+
+func (i intentOrgDo) ReadDB() IIntentOrgDo {
+	return i.Clauses(dbresolver.Read)
+}
+
+func (i intentOrgDo) WriteDB() IIntentOrgDo {
+	return i.Clauses(dbresolver.Write)
+}
+
+func (i intentOrgDo) Session(config *gorm.Session) IIntentOrgDo {
+	return i.withDO(i.DO.Session(config))
+}
+
+func (i intentOrgDo) Clauses(conds ...clause.Expression) IIntentOrgDo {
+	return i.withDO(i.DO.Clauses(conds...))
+}
+
+func (i intentOrgDo) Returning(value interface{}, columns ...string) IIntentOrgDo {
+	return i.withDO(i.DO.Returning(value, columns...))
+}
+
+func (i intentOrgDo) Not(conds ...gen.Condition) IIntentOrgDo {
+	return i.withDO(i.DO.Not(conds...))
+}
+
+func (i intentOrgDo) Or(conds ...gen.Condition) IIntentOrgDo {
+	return i.withDO(i.DO.Or(conds...))
+}
+
+func (i intentOrgDo) Select(conds ...field.Expr) IIntentOrgDo {
+	return i.withDO(i.DO.Select(conds...))
+}
+
+func (i intentOrgDo) Where(conds ...gen.Condition) IIntentOrgDo {
+	return i.withDO(i.DO.Where(conds...))
+}
+
+func (i intentOrgDo) Order(conds ...field.Expr) IIntentOrgDo {
+	return i.withDO(i.DO.Order(conds...))
+}
+
+func (i intentOrgDo) Distinct(cols ...field.Expr) IIntentOrgDo {
+	return i.withDO(i.DO.Distinct(cols...))
+}
+
+func (i intentOrgDo) Omit(cols ...field.Expr) IIntentOrgDo {
+	return i.withDO(i.DO.Omit(cols...))
+}
+
+func (i intentOrgDo) Join(table schema.Tabler, on ...field.Expr) IIntentOrgDo {
+	return i.withDO(i.DO.Join(table, on...))
+}
+
+func (i intentOrgDo) LeftJoin(table schema.Tabler, on ...field.Expr) IIntentOrgDo {
+	return i.withDO(i.DO.LeftJoin(table, on...))
+}
+
+func (i intentOrgDo) RightJoin(table schema.Tabler, on ...field.Expr) IIntentOrgDo {
+	return i.withDO(i.DO.RightJoin(table, on...))
+}
+
+func (i intentOrgDo) Group(cols ...field.Expr) IIntentOrgDo {
+	return i.withDO(i.DO.Group(cols...))
+}
+
+func (i intentOrgDo) Having(conds ...gen.Condition) IIntentOrgDo {
+	return i.withDO(i.DO.Having(conds...))
+}
+
+func (i intentOrgDo) Limit(limit int) IIntentOrgDo {
+	return i.withDO(i.DO.Limit(limit))
+}
+
+func (i intentOrgDo) Offset(offset int) IIntentOrgDo {
+	return i.withDO(i.DO.Offset(offset))
+}
+
+func (i intentOrgDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IIntentOrgDo {
+	return i.withDO(i.DO.Scopes(funcs...))
+}
+
+func (i intentOrgDo) Unscoped() IIntentOrgDo {
+	return i.withDO(i.DO.Unscoped())
+}
+
+func (i intentOrgDo) Create(values ...*model.IntentOrg) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return i.DO.Create(values)
+}
+
+func (i intentOrgDo) CreateInBatches(values []*model.IntentOrg, batchSize int) error {
+	return i.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (i intentOrgDo) Save(values ...*model.IntentOrg) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return i.DO.Save(values)
+}
+
+func (i intentOrgDo) First() (*model.IntentOrg, error) {
+	if result, err := i.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.IntentOrg), nil
+	}
+}
+
+func (i intentOrgDo) Take() (*model.IntentOrg, error) {
+	if result, err := i.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.IntentOrg), nil
+	}
+}
+
+func (i intentOrgDo) Last() (*model.IntentOrg, error) {
+	if result, err := i.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.IntentOrg), nil
+	}
+}
+
+func (i intentOrgDo) Find() ([]*model.IntentOrg, error) {
+	result, err := i.DO.Find()
+	return result.([]*model.IntentOrg), err
+}
+
+func (i intentOrgDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.IntentOrg, err error) {
+	buf := make([]*model.IntentOrg, 0, batchSize)
+	err = i.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (i intentOrgDo) FindInBatches(result *[]*model.IntentOrg, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return i.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (i intentOrgDo) Attrs(attrs ...field.AssignExpr) IIntentOrgDo {
+	return i.withDO(i.DO.Attrs(attrs...))
+}
+
+func (i intentOrgDo) Assign(attrs ...field.AssignExpr) IIntentOrgDo {
+	return i.withDO(i.DO.Assign(attrs...))
+}
+
+func (i intentOrgDo) Joins(fields ...field.RelationField) IIntentOrgDo {
+	for _, _f := range fields {
+		i = *i.withDO(i.DO.Joins(_f))
+	}
+	return &i
+}
+
+func (i intentOrgDo) Preload(fields ...field.RelationField) IIntentOrgDo {
+	for _, _f := range fields {
+		i = *i.withDO(i.DO.Preload(_f))
+	}
+	return &i
+}
+
+func (i intentOrgDo) FirstOrInit() (*model.IntentOrg, error) {
+	if result, err := i.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.IntentOrg), nil
+	}
+}
+
+func (i intentOrgDo) FirstOrCreate() (*model.IntentOrg, error) {
+	if result, err := i.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.IntentOrg), nil
+	}
+}
+
+func (i intentOrgDo) FindByPage(offset int, limit int) (result []*model.IntentOrg, count int64, err error) {
+	result, err = i.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = i.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (i intentOrgDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = i.Count()
+	if err != nil {
+		return
+	}
+
+	err = i.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (i intentOrgDo) Scan(result interface{}) (err error) {
+	return i.DO.Scan(result)
+}
+
+func (i intentOrgDo) Delete(models ...*model.IntentOrg) (result gen.ResultInfo, err error) {
+	return i.DO.Delete(models)
+}
+
+func (i *intentOrgDo) withDO(do gen.Dao) *intentOrgDo {
+	i.DO = *do.(*gen.DO)
+	return i
+}

+ 424 - 0
database/dao/wechat/query/intent_records.gen.go

@@ -0,0 +1,424 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newIntentRecord(db *gorm.DB, opts ...gen.DOOption) intentRecord {
+	_intentRecord := intentRecord{}
+
+	_intentRecord.intentRecordDo.UseDB(db, opts...)
+	_intentRecord.intentRecordDo.UseModel(&model.IntentRecord{})
+
+	tableName := _intentRecord.intentRecordDo.TableName()
+	_intentRecord.ALL = field.NewAsterisk(tableName)
+	_intentRecord.ID = field.NewString(tableName, "id")
+	_intentRecord.ExternalID = field.NewString(tableName, "external_id")
+	_intentRecord.IndustryType = field.NewInt64(tableName, "industry_type")
+	_intentRecord.ChatHistory = field.NewString(tableName, "chat_history")
+	_intentRecord.ManualIntent = field.NewInt64(tableName, "manual_intent")
+	_intentRecord.LlmIntent = field.NewInt64(tableName, "llm_intent")
+	_intentRecord.OrgID = field.NewInt64(tableName, "org_id")
+	_intentRecord.Status = field.NewInt64(tableName, "status")
+	_intentRecord.RequestData = field.NewString(tableName, "request_data")
+	_intentRecord.ResponseData = field.NewString(tableName, "response_data")
+	_intentRecord.CreatedAt = field.NewTime(tableName, "created_at")
+	_intentRecord.UpdatedAt = field.NewTime(tableName, "updated_at")
+
+	_intentRecord.fillFieldMap()
+
+	return _intentRecord
+}
+
+type intentRecord struct {
+	intentRecordDo
+
+	ALL          field.Asterisk
+	ID           field.String // 主键id
+	ExternalID   field.String // 外部id
+	IndustryType field.Int64  // 评分规则代码 0 通用 1 教育
+	ChatHistory  field.String // 通话记录
+	ManualIntent field.Int64  // 人工意向度 1 有意向 2 无意向 3 其他
+	LlmIntent    field.Int64  // 大模型意向度 1 有意向 2 无意向 3 不确定
+	OrgID        field.Int64  // 机构 ID
+	Status       field.Int64  // 状态 1 入库 2 已判断 3 已回调
+	RequestData  field.String
+	ResponseData field.String
+	CreatedAt    field.Time // Create Time | 创建日期
+	UpdatedAt    field.Time // Update Time | 修改日期
+
+	fieldMap map[string]field.Expr
+}
+
+func (i intentRecord) Table(newTableName string) *intentRecord {
+	i.intentRecordDo.UseTable(newTableName)
+	return i.updateTableName(newTableName)
+}
+
+func (i intentRecord) As(alias string) *intentRecord {
+	i.intentRecordDo.DO = *(i.intentRecordDo.As(alias).(*gen.DO))
+	return i.updateTableName(alias)
+}
+
+func (i *intentRecord) updateTableName(table string) *intentRecord {
+	i.ALL = field.NewAsterisk(table)
+	i.ID = field.NewString(table, "id")
+	i.ExternalID = field.NewString(table, "external_id")
+	i.IndustryType = field.NewInt64(table, "industry_type")
+	i.ChatHistory = field.NewString(table, "chat_history")
+	i.ManualIntent = field.NewInt64(table, "manual_intent")
+	i.LlmIntent = field.NewInt64(table, "llm_intent")
+	i.OrgID = field.NewInt64(table, "org_id")
+	i.Status = field.NewInt64(table, "status")
+	i.RequestData = field.NewString(table, "request_data")
+	i.ResponseData = field.NewString(table, "response_data")
+	i.CreatedAt = field.NewTime(table, "created_at")
+	i.UpdatedAt = field.NewTime(table, "updated_at")
+
+	i.fillFieldMap()
+
+	return i
+}
+
+func (i *intentRecord) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := i.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (i *intentRecord) fillFieldMap() {
+	i.fieldMap = make(map[string]field.Expr, 12)
+	i.fieldMap["id"] = i.ID
+	i.fieldMap["external_id"] = i.ExternalID
+	i.fieldMap["industry_type"] = i.IndustryType
+	i.fieldMap["chat_history"] = i.ChatHistory
+	i.fieldMap["manual_intent"] = i.ManualIntent
+	i.fieldMap["llm_intent"] = i.LlmIntent
+	i.fieldMap["org_id"] = i.OrgID
+	i.fieldMap["status"] = i.Status
+	i.fieldMap["request_data"] = i.RequestData
+	i.fieldMap["response_data"] = i.ResponseData
+	i.fieldMap["created_at"] = i.CreatedAt
+	i.fieldMap["updated_at"] = i.UpdatedAt
+}
+
+func (i intentRecord) clone(db *gorm.DB) intentRecord {
+	i.intentRecordDo.ReplaceConnPool(db.Statement.ConnPool)
+	return i
+}
+
+func (i intentRecord) replaceDB(db *gorm.DB) intentRecord {
+	i.intentRecordDo.ReplaceDB(db)
+	return i
+}
+
+type intentRecordDo struct{ gen.DO }
+
+type IIntentRecordDo interface {
+	gen.SubQuery
+	Debug() IIntentRecordDo
+	WithContext(ctx context.Context) IIntentRecordDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IIntentRecordDo
+	WriteDB() IIntentRecordDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IIntentRecordDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IIntentRecordDo
+	Not(conds ...gen.Condition) IIntentRecordDo
+	Or(conds ...gen.Condition) IIntentRecordDo
+	Select(conds ...field.Expr) IIntentRecordDo
+	Where(conds ...gen.Condition) IIntentRecordDo
+	Order(conds ...field.Expr) IIntentRecordDo
+	Distinct(cols ...field.Expr) IIntentRecordDo
+	Omit(cols ...field.Expr) IIntentRecordDo
+	Join(table schema.Tabler, on ...field.Expr) IIntentRecordDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IIntentRecordDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IIntentRecordDo
+	Group(cols ...field.Expr) IIntentRecordDo
+	Having(conds ...gen.Condition) IIntentRecordDo
+	Limit(limit int) IIntentRecordDo
+	Offset(offset int) IIntentRecordDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IIntentRecordDo
+	Unscoped() IIntentRecordDo
+	Create(values ...*model.IntentRecord) error
+	CreateInBatches(values []*model.IntentRecord, batchSize int) error
+	Save(values ...*model.IntentRecord) error
+	First() (*model.IntentRecord, error)
+	Take() (*model.IntentRecord, error)
+	Last() (*model.IntentRecord, error)
+	Find() ([]*model.IntentRecord, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.IntentRecord, err error)
+	FindInBatches(result *[]*model.IntentRecord, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.IntentRecord) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IIntentRecordDo
+	Assign(attrs ...field.AssignExpr) IIntentRecordDo
+	Joins(fields ...field.RelationField) IIntentRecordDo
+	Preload(fields ...field.RelationField) IIntentRecordDo
+	FirstOrInit() (*model.IntentRecord, error)
+	FirstOrCreate() (*model.IntentRecord, error)
+	FindByPage(offset int, limit int) (result []*model.IntentRecord, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IIntentRecordDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (i intentRecordDo) Debug() IIntentRecordDo {
+	return i.withDO(i.DO.Debug())
+}
+
+func (i intentRecordDo) WithContext(ctx context.Context) IIntentRecordDo {
+	return i.withDO(i.DO.WithContext(ctx))
+}
+
+func (i intentRecordDo) ReadDB() IIntentRecordDo {
+	return i.Clauses(dbresolver.Read)
+}
+
+func (i intentRecordDo) WriteDB() IIntentRecordDo {
+	return i.Clauses(dbresolver.Write)
+}
+
+func (i intentRecordDo) Session(config *gorm.Session) IIntentRecordDo {
+	return i.withDO(i.DO.Session(config))
+}
+
+func (i intentRecordDo) Clauses(conds ...clause.Expression) IIntentRecordDo {
+	return i.withDO(i.DO.Clauses(conds...))
+}
+
+func (i intentRecordDo) Returning(value interface{}, columns ...string) IIntentRecordDo {
+	return i.withDO(i.DO.Returning(value, columns...))
+}
+
+func (i intentRecordDo) Not(conds ...gen.Condition) IIntentRecordDo {
+	return i.withDO(i.DO.Not(conds...))
+}
+
+func (i intentRecordDo) Or(conds ...gen.Condition) IIntentRecordDo {
+	return i.withDO(i.DO.Or(conds...))
+}
+
+func (i intentRecordDo) Select(conds ...field.Expr) IIntentRecordDo {
+	return i.withDO(i.DO.Select(conds...))
+}
+
+func (i intentRecordDo) Where(conds ...gen.Condition) IIntentRecordDo {
+	return i.withDO(i.DO.Where(conds...))
+}
+
+func (i intentRecordDo) Order(conds ...field.Expr) IIntentRecordDo {
+	return i.withDO(i.DO.Order(conds...))
+}
+
+func (i intentRecordDo) Distinct(cols ...field.Expr) IIntentRecordDo {
+	return i.withDO(i.DO.Distinct(cols...))
+}
+
+func (i intentRecordDo) Omit(cols ...field.Expr) IIntentRecordDo {
+	return i.withDO(i.DO.Omit(cols...))
+}
+
+func (i intentRecordDo) Join(table schema.Tabler, on ...field.Expr) IIntentRecordDo {
+	return i.withDO(i.DO.Join(table, on...))
+}
+
+func (i intentRecordDo) LeftJoin(table schema.Tabler, on ...field.Expr) IIntentRecordDo {
+	return i.withDO(i.DO.LeftJoin(table, on...))
+}
+
+func (i intentRecordDo) RightJoin(table schema.Tabler, on ...field.Expr) IIntentRecordDo {
+	return i.withDO(i.DO.RightJoin(table, on...))
+}
+
+func (i intentRecordDo) Group(cols ...field.Expr) IIntentRecordDo {
+	return i.withDO(i.DO.Group(cols...))
+}
+
+func (i intentRecordDo) Having(conds ...gen.Condition) IIntentRecordDo {
+	return i.withDO(i.DO.Having(conds...))
+}
+
+func (i intentRecordDo) Limit(limit int) IIntentRecordDo {
+	return i.withDO(i.DO.Limit(limit))
+}
+
+func (i intentRecordDo) Offset(offset int) IIntentRecordDo {
+	return i.withDO(i.DO.Offset(offset))
+}
+
+func (i intentRecordDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IIntentRecordDo {
+	return i.withDO(i.DO.Scopes(funcs...))
+}
+
+func (i intentRecordDo) Unscoped() IIntentRecordDo {
+	return i.withDO(i.DO.Unscoped())
+}
+
+func (i intentRecordDo) Create(values ...*model.IntentRecord) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return i.DO.Create(values)
+}
+
+func (i intentRecordDo) CreateInBatches(values []*model.IntentRecord, batchSize int) error {
+	return i.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (i intentRecordDo) Save(values ...*model.IntentRecord) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return i.DO.Save(values)
+}
+
+func (i intentRecordDo) First() (*model.IntentRecord, error) {
+	if result, err := i.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.IntentRecord), nil
+	}
+}
+
+func (i intentRecordDo) Take() (*model.IntentRecord, error) {
+	if result, err := i.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.IntentRecord), nil
+	}
+}
+
+func (i intentRecordDo) Last() (*model.IntentRecord, error) {
+	if result, err := i.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.IntentRecord), nil
+	}
+}
+
+func (i intentRecordDo) Find() ([]*model.IntentRecord, error) {
+	result, err := i.DO.Find()
+	return result.([]*model.IntentRecord), err
+}
+
+func (i intentRecordDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.IntentRecord, err error) {
+	buf := make([]*model.IntentRecord, 0, batchSize)
+	err = i.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (i intentRecordDo) FindInBatches(result *[]*model.IntentRecord, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return i.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (i intentRecordDo) Attrs(attrs ...field.AssignExpr) IIntentRecordDo {
+	return i.withDO(i.DO.Attrs(attrs...))
+}
+
+func (i intentRecordDo) Assign(attrs ...field.AssignExpr) IIntentRecordDo {
+	return i.withDO(i.DO.Assign(attrs...))
+}
+
+func (i intentRecordDo) Joins(fields ...field.RelationField) IIntentRecordDo {
+	for _, _f := range fields {
+		i = *i.withDO(i.DO.Joins(_f))
+	}
+	return &i
+}
+
+func (i intentRecordDo) Preload(fields ...field.RelationField) IIntentRecordDo {
+	for _, _f := range fields {
+		i = *i.withDO(i.DO.Preload(_f))
+	}
+	return &i
+}
+
+func (i intentRecordDo) FirstOrInit() (*model.IntentRecord, error) {
+	if result, err := i.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.IntentRecord), nil
+	}
+}
+
+func (i intentRecordDo) FirstOrCreate() (*model.IntentRecord, error) {
+	if result, err := i.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.IntentRecord), nil
+	}
+}
+
+func (i intentRecordDo) FindByPage(offset int, limit int) (result []*model.IntentRecord, count int64, err error) {
+	result, err = i.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = i.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (i intentRecordDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = i.Count()
+	if err != nil {
+		return
+	}
+
+	err = i.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (i intentRecordDo) Scan(result interface{}) (err error) {
+	return i.DO.Scan(result)
+}
+
+func (i intentRecordDo) Delete(models ...*model.IntentRecord) (result gen.ResultInfo, err error) {
+	return i.DO.Delete(models)
+}
+
+func (i *intentRecordDo) withDO(do gen.Dao) *intentRecordDo {
+	i.DO = *do.(*gen.DO)
+	return i
+}

+ 420 - 0
database/dao/wechat/query/label.gen.go

@@ -0,0 +1,420 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newLabel(db *gorm.DB, opts ...gen.DOOption) label {
+	_label := label{}
+
+	_label.labelDo.UseDB(db, opts...)
+	_label.labelDo.UseModel(&model.Label{})
+
+	tableName := _label.labelDo.TableName()
+	_label.ALL = field.NewAsterisk(tableName)
+	_label.ID = field.NewInt64(tableName, "id")
+	_label.CreatedAt = field.NewTime(tableName, "created_at")
+	_label.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_label.Status = field.NewInt64(tableName, "status")
+	_label.DeletedAt = field.NewField(tableName, "deleted_at")
+	_label.Type = field.NewInt64(tableName, "type")
+	_label.Name = field.NewString(tableName, "name")
+	_label.From = field.NewInt64(tableName, "from")
+	_label.Mode = field.NewInt64(tableName, "mode")
+	_label.Conditions = field.NewString(tableName, "conditions")
+	_label.OrganizationID = field.NewInt64(tableName, "organization_id")
+
+	_label.fillFieldMap()
+
+	return _label
+}
+
+type label struct {
+	labelDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	Status         field.Int64  // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	Type           field.Int64  // 标签类型:1好友,2群组,3公众号,4企业微信联系人
+	Name           field.String // 标签名称
+	From           field.Int64  // 标签来源:1后台创建 2个微同步
+	Mode           field.Int64  // 标签模式:1动态 2静态
+	Conditions     field.String // 标签的触达条件
+	OrganizationID field.Int64  // 机构 ID
+
+	fieldMap map[string]field.Expr
+}
+
+func (l label) Table(newTableName string) *label {
+	l.labelDo.UseTable(newTableName)
+	return l.updateTableName(newTableName)
+}
+
+func (l label) As(alias string) *label {
+	l.labelDo.DO = *(l.labelDo.As(alias).(*gen.DO))
+	return l.updateTableName(alias)
+}
+
+func (l *label) updateTableName(table string) *label {
+	l.ALL = field.NewAsterisk(table)
+	l.ID = field.NewInt64(table, "id")
+	l.CreatedAt = field.NewTime(table, "created_at")
+	l.UpdatedAt = field.NewTime(table, "updated_at")
+	l.Status = field.NewInt64(table, "status")
+	l.DeletedAt = field.NewField(table, "deleted_at")
+	l.Type = field.NewInt64(table, "type")
+	l.Name = field.NewString(table, "name")
+	l.From = field.NewInt64(table, "from")
+	l.Mode = field.NewInt64(table, "mode")
+	l.Conditions = field.NewString(table, "conditions")
+	l.OrganizationID = field.NewInt64(table, "organization_id")
+
+	l.fillFieldMap()
+
+	return l
+}
+
+func (l *label) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := l.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (l *label) fillFieldMap() {
+	l.fieldMap = make(map[string]field.Expr, 11)
+	l.fieldMap["id"] = l.ID
+	l.fieldMap["created_at"] = l.CreatedAt
+	l.fieldMap["updated_at"] = l.UpdatedAt
+	l.fieldMap["status"] = l.Status
+	l.fieldMap["deleted_at"] = l.DeletedAt
+	l.fieldMap["type"] = l.Type
+	l.fieldMap["name"] = l.Name
+	l.fieldMap["from"] = l.From
+	l.fieldMap["mode"] = l.Mode
+	l.fieldMap["conditions"] = l.Conditions
+	l.fieldMap["organization_id"] = l.OrganizationID
+}
+
+func (l label) clone(db *gorm.DB) label {
+	l.labelDo.ReplaceConnPool(db.Statement.ConnPool)
+	return l
+}
+
+func (l label) replaceDB(db *gorm.DB) label {
+	l.labelDo.ReplaceDB(db)
+	return l
+}
+
+type labelDo struct{ gen.DO }
+
+type ILabelDo interface {
+	gen.SubQuery
+	Debug() ILabelDo
+	WithContext(ctx context.Context) ILabelDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() ILabelDo
+	WriteDB() ILabelDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) ILabelDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) ILabelDo
+	Not(conds ...gen.Condition) ILabelDo
+	Or(conds ...gen.Condition) ILabelDo
+	Select(conds ...field.Expr) ILabelDo
+	Where(conds ...gen.Condition) ILabelDo
+	Order(conds ...field.Expr) ILabelDo
+	Distinct(cols ...field.Expr) ILabelDo
+	Omit(cols ...field.Expr) ILabelDo
+	Join(table schema.Tabler, on ...field.Expr) ILabelDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) ILabelDo
+	RightJoin(table schema.Tabler, on ...field.Expr) ILabelDo
+	Group(cols ...field.Expr) ILabelDo
+	Having(conds ...gen.Condition) ILabelDo
+	Limit(limit int) ILabelDo
+	Offset(offset int) ILabelDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) ILabelDo
+	Unscoped() ILabelDo
+	Create(values ...*model.Label) error
+	CreateInBatches(values []*model.Label, batchSize int) error
+	Save(values ...*model.Label) error
+	First() (*model.Label, error)
+	Take() (*model.Label, error)
+	Last() (*model.Label, error)
+	Find() ([]*model.Label, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Label, err error)
+	FindInBatches(result *[]*model.Label, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.Label) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) ILabelDo
+	Assign(attrs ...field.AssignExpr) ILabelDo
+	Joins(fields ...field.RelationField) ILabelDo
+	Preload(fields ...field.RelationField) ILabelDo
+	FirstOrInit() (*model.Label, error)
+	FirstOrCreate() (*model.Label, error)
+	FindByPage(offset int, limit int) (result []*model.Label, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) ILabelDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (l labelDo) Debug() ILabelDo {
+	return l.withDO(l.DO.Debug())
+}
+
+func (l labelDo) WithContext(ctx context.Context) ILabelDo {
+	return l.withDO(l.DO.WithContext(ctx))
+}
+
+func (l labelDo) ReadDB() ILabelDo {
+	return l.Clauses(dbresolver.Read)
+}
+
+func (l labelDo) WriteDB() ILabelDo {
+	return l.Clauses(dbresolver.Write)
+}
+
+func (l labelDo) Session(config *gorm.Session) ILabelDo {
+	return l.withDO(l.DO.Session(config))
+}
+
+func (l labelDo) Clauses(conds ...clause.Expression) ILabelDo {
+	return l.withDO(l.DO.Clauses(conds...))
+}
+
+func (l labelDo) Returning(value interface{}, columns ...string) ILabelDo {
+	return l.withDO(l.DO.Returning(value, columns...))
+}
+
+func (l labelDo) Not(conds ...gen.Condition) ILabelDo {
+	return l.withDO(l.DO.Not(conds...))
+}
+
+func (l labelDo) Or(conds ...gen.Condition) ILabelDo {
+	return l.withDO(l.DO.Or(conds...))
+}
+
+func (l labelDo) Select(conds ...field.Expr) ILabelDo {
+	return l.withDO(l.DO.Select(conds...))
+}
+
+func (l labelDo) Where(conds ...gen.Condition) ILabelDo {
+	return l.withDO(l.DO.Where(conds...))
+}
+
+func (l labelDo) Order(conds ...field.Expr) ILabelDo {
+	return l.withDO(l.DO.Order(conds...))
+}
+
+func (l labelDo) Distinct(cols ...field.Expr) ILabelDo {
+	return l.withDO(l.DO.Distinct(cols...))
+}
+
+func (l labelDo) Omit(cols ...field.Expr) ILabelDo {
+	return l.withDO(l.DO.Omit(cols...))
+}
+
+func (l labelDo) Join(table schema.Tabler, on ...field.Expr) ILabelDo {
+	return l.withDO(l.DO.Join(table, on...))
+}
+
+func (l labelDo) LeftJoin(table schema.Tabler, on ...field.Expr) ILabelDo {
+	return l.withDO(l.DO.LeftJoin(table, on...))
+}
+
+func (l labelDo) RightJoin(table schema.Tabler, on ...field.Expr) ILabelDo {
+	return l.withDO(l.DO.RightJoin(table, on...))
+}
+
+func (l labelDo) Group(cols ...field.Expr) ILabelDo {
+	return l.withDO(l.DO.Group(cols...))
+}
+
+func (l labelDo) Having(conds ...gen.Condition) ILabelDo {
+	return l.withDO(l.DO.Having(conds...))
+}
+
+func (l labelDo) Limit(limit int) ILabelDo {
+	return l.withDO(l.DO.Limit(limit))
+}
+
+func (l labelDo) Offset(offset int) ILabelDo {
+	return l.withDO(l.DO.Offset(offset))
+}
+
+func (l labelDo) Scopes(funcs ...func(gen.Dao) gen.Dao) ILabelDo {
+	return l.withDO(l.DO.Scopes(funcs...))
+}
+
+func (l labelDo) Unscoped() ILabelDo {
+	return l.withDO(l.DO.Unscoped())
+}
+
+func (l labelDo) Create(values ...*model.Label) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return l.DO.Create(values)
+}
+
+func (l labelDo) CreateInBatches(values []*model.Label, batchSize int) error {
+	return l.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (l labelDo) Save(values ...*model.Label) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return l.DO.Save(values)
+}
+
+func (l labelDo) First() (*model.Label, error) {
+	if result, err := l.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Label), nil
+	}
+}
+
+func (l labelDo) Take() (*model.Label, error) {
+	if result, err := l.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Label), nil
+	}
+}
+
+func (l labelDo) Last() (*model.Label, error) {
+	if result, err := l.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Label), nil
+	}
+}
+
+func (l labelDo) Find() ([]*model.Label, error) {
+	result, err := l.DO.Find()
+	return result.([]*model.Label), err
+}
+
+func (l labelDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Label, err error) {
+	buf := make([]*model.Label, 0, batchSize)
+	err = l.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (l labelDo) FindInBatches(result *[]*model.Label, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return l.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (l labelDo) Attrs(attrs ...field.AssignExpr) ILabelDo {
+	return l.withDO(l.DO.Attrs(attrs...))
+}
+
+func (l labelDo) Assign(attrs ...field.AssignExpr) ILabelDo {
+	return l.withDO(l.DO.Assign(attrs...))
+}
+
+func (l labelDo) Joins(fields ...field.RelationField) ILabelDo {
+	for _, _f := range fields {
+		l = *l.withDO(l.DO.Joins(_f))
+	}
+	return &l
+}
+
+func (l labelDo) Preload(fields ...field.RelationField) ILabelDo {
+	for _, _f := range fields {
+		l = *l.withDO(l.DO.Preload(_f))
+	}
+	return &l
+}
+
+func (l labelDo) FirstOrInit() (*model.Label, error) {
+	if result, err := l.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Label), nil
+	}
+}
+
+func (l labelDo) FirstOrCreate() (*model.Label, error) {
+	if result, err := l.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Label), nil
+	}
+}
+
+func (l labelDo) FindByPage(offset int, limit int) (result []*model.Label, count int64, err error) {
+	result, err = l.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = l.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (l labelDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = l.Count()
+	if err != nil {
+		return
+	}
+
+	err = l.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (l labelDo) Scan(result interface{}) (err error) {
+	return l.DO.Scan(result)
+}
+
+func (l labelDo) Delete(models ...*model.Label) (result gen.ResultInfo, err error) {
+	return l.DO.Delete(models)
+}
+
+func (l *labelDo) withDO(do gen.Dao) *labelDo {
+	l.DO = *do.(*gen.DO)
+	return l
+}

+ 408 - 0
database/dao/wechat/query/label_relationship.gen.go

@@ -0,0 +1,408 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newLabelRelationship(db *gorm.DB, opts ...gen.DOOption) labelRelationship {
+	_labelRelationship := labelRelationship{}
+
+	_labelRelationship.labelRelationshipDo.UseDB(db, opts...)
+	_labelRelationship.labelRelationshipDo.UseModel(&model.LabelRelationship{})
+
+	tableName := _labelRelationship.labelRelationshipDo.TableName()
+	_labelRelationship.ALL = field.NewAsterisk(tableName)
+	_labelRelationship.ID = field.NewInt64(tableName, "id")
+	_labelRelationship.CreatedAt = field.NewTime(tableName, "created_at")
+	_labelRelationship.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_labelRelationship.Status = field.NewInt64(tableName, "status")
+	_labelRelationship.DeletedAt = field.NewField(tableName, "deleted_at")
+	_labelRelationship.LabelID = field.NewInt64(tableName, "label_id")
+	_labelRelationship.ContactID = field.NewInt64(tableName, "contact_id")
+	_labelRelationship.OrganizationID = field.NewInt64(tableName, "organization_id")
+
+	_labelRelationship.fillFieldMap()
+
+	return _labelRelationship
+}
+
+type labelRelationship struct {
+	labelRelationshipDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time  // Create Time | 创建日期
+	UpdatedAt      field.Time  // Update Time | 修改日期
+	Status         field.Int64 // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt      field.Field // Delete Time | 删除日期
+	LabelID        field.Int64
+	ContactID      field.Int64
+	OrganizationID field.Int64 // 机构 ID
+
+	fieldMap map[string]field.Expr
+}
+
+func (l labelRelationship) Table(newTableName string) *labelRelationship {
+	l.labelRelationshipDo.UseTable(newTableName)
+	return l.updateTableName(newTableName)
+}
+
+func (l labelRelationship) As(alias string) *labelRelationship {
+	l.labelRelationshipDo.DO = *(l.labelRelationshipDo.As(alias).(*gen.DO))
+	return l.updateTableName(alias)
+}
+
+func (l *labelRelationship) updateTableName(table string) *labelRelationship {
+	l.ALL = field.NewAsterisk(table)
+	l.ID = field.NewInt64(table, "id")
+	l.CreatedAt = field.NewTime(table, "created_at")
+	l.UpdatedAt = field.NewTime(table, "updated_at")
+	l.Status = field.NewInt64(table, "status")
+	l.DeletedAt = field.NewField(table, "deleted_at")
+	l.LabelID = field.NewInt64(table, "label_id")
+	l.ContactID = field.NewInt64(table, "contact_id")
+	l.OrganizationID = field.NewInt64(table, "organization_id")
+
+	l.fillFieldMap()
+
+	return l
+}
+
+func (l *labelRelationship) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := l.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (l *labelRelationship) fillFieldMap() {
+	l.fieldMap = make(map[string]field.Expr, 8)
+	l.fieldMap["id"] = l.ID
+	l.fieldMap["created_at"] = l.CreatedAt
+	l.fieldMap["updated_at"] = l.UpdatedAt
+	l.fieldMap["status"] = l.Status
+	l.fieldMap["deleted_at"] = l.DeletedAt
+	l.fieldMap["label_id"] = l.LabelID
+	l.fieldMap["contact_id"] = l.ContactID
+	l.fieldMap["organization_id"] = l.OrganizationID
+}
+
+func (l labelRelationship) clone(db *gorm.DB) labelRelationship {
+	l.labelRelationshipDo.ReplaceConnPool(db.Statement.ConnPool)
+	return l
+}
+
+func (l labelRelationship) replaceDB(db *gorm.DB) labelRelationship {
+	l.labelRelationshipDo.ReplaceDB(db)
+	return l
+}
+
+type labelRelationshipDo struct{ gen.DO }
+
+type ILabelRelationshipDo interface {
+	gen.SubQuery
+	Debug() ILabelRelationshipDo
+	WithContext(ctx context.Context) ILabelRelationshipDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() ILabelRelationshipDo
+	WriteDB() ILabelRelationshipDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) ILabelRelationshipDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) ILabelRelationshipDo
+	Not(conds ...gen.Condition) ILabelRelationshipDo
+	Or(conds ...gen.Condition) ILabelRelationshipDo
+	Select(conds ...field.Expr) ILabelRelationshipDo
+	Where(conds ...gen.Condition) ILabelRelationshipDo
+	Order(conds ...field.Expr) ILabelRelationshipDo
+	Distinct(cols ...field.Expr) ILabelRelationshipDo
+	Omit(cols ...field.Expr) ILabelRelationshipDo
+	Join(table schema.Tabler, on ...field.Expr) ILabelRelationshipDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) ILabelRelationshipDo
+	RightJoin(table schema.Tabler, on ...field.Expr) ILabelRelationshipDo
+	Group(cols ...field.Expr) ILabelRelationshipDo
+	Having(conds ...gen.Condition) ILabelRelationshipDo
+	Limit(limit int) ILabelRelationshipDo
+	Offset(offset int) ILabelRelationshipDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) ILabelRelationshipDo
+	Unscoped() ILabelRelationshipDo
+	Create(values ...*model.LabelRelationship) error
+	CreateInBatches(values []*model.LabelRelationship, batchSize int) error
+	Save(values ...*model.LabelRelationship) error
+	First() (*model.LabelRelationship, error)
+	Take() (*model.LabelRelationship, error)
+	Last() (*model.LabelRelationship, error)
+	Find() ([]*model.LabelRelationship, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.LabelRelationship, err error)
+	FindInBatches(result *[]*model.LabelRelationship, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.LabelRelationship) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) ILabelRelationshipDo
+	Assign(attrs ...field.AssignExpr) ILabelRelationshipDo
+	Joins(fields ...field.RelationField) ILabelRelationshipDo
+	Preload(fields ...field.RelationField) ILabelRelationshipDo
+	FirstOrInit() (*model.LabelRelationship, error)
+	FirstOrCreate() (*model.LabelRelationship, error)
+	FindByPage(offset int, limit int) (result []*model.LabelRelationship, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) ILabelRelationshipDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (l labelRelationshipDo) Debug() ILabelRelationshipDo {
+	return l.withDO(l.DO.Debug())
+}
+
+func (l labelRelationshipDo) WithContext(ctx context.Context) ILabelRelationshipDo {
+	return l.withDO(l.DO.WithContext(ctx))
+}
+
+func (l labelRelationshipDo) ReadDB() ILabelRelationshipDo {
+	return l.Clauses(dbresolver.Read)
+}
+
+func (l labelRelationshipDo) WriteDB() ILabelRelationshipDo {
+	return l.Clauses(dbresolver.Write)
+}
+
+func (l labelRelationshipDo) Session(config *gorm.Session) ILabelRelationshipDo {
+	return l.withDO(l.DO.Session(config))
+}
+
+func (l labelRelationshipDo) Clauses(conds ...clause.Expression) ILabelRelationshipDo {
+	return l.withDO(l.DO.Clauses(conds...))
+}
+
+func (l labelRelationshipDo) Returning(value interface{}, columns ...string) ILabelRelationshipDo {
+	return l.withDO(l.DO.Returning(value, columns...))
+}
+
+func (l labelRelationshipDo) Not(conds ...gen.Condition) ILabelRelationshipDo {
+	return l.withDO(l.DO.Not(conds...))
+}
+
+func (l labelRelationshipDo) Or(conds ...gen.Condition) ILabelRelationshipDo {
+	return l.withDO(l.DO.Or(conds...))
+}
+
+func (l labelRelationshipDo) Select(conds ...field.Expr) ILabelRelationshipDo {
+	return l.withDO(l.DO.Select(conds...))
+}
+
+func (l labelRelationshipDo) Where(conds ...gen.Condition) ILabelRelationshipDo {
+	return l.withDO(l.DO.Where(conds...))
+}
+
+func (l labelRelationshipDo) Order(conds ...field.Expr) ILabelRelationshipDo {
+	return l.withDO(l.DO.Order(conds...))
+}
+
+func (l labelRelationshipDo) Distinct(cols ...field.Expr) ILabelRelationshipDo {
+	return l.withDO(l.DO.Distinct(cols...))
+}
+
+func (l labelRelationshipDo) Omit(cols ...field.Expr) ILabelRelationshipDo {
+	return l.withDO(l.DO.Omit(cols...))
+}
+
+func (l labelRelationshipDo) Join(table schema.Tabler, on ...field.Expr) ILabelRelationshipDo {
+	return l.withDO(l.DO.Join(table, on...))
+}
+
+func (l labelRelationshipDo) LeftJoin(table schema.Tabler, on ...field.Expr) ILabelRelationshipDo {
+	return l.withDO(l.DO.LeftJoin(table, on...))
+}
+
+func (l labelRelationshipDo) RightJoin(table schema.Tabler, on ...field.Expr) ILabelRelationshipDo {
+	return l.withDO(l.DO.RightJoin(table, on...))
+}
+
+func (l labelRelationshipDo) Group(cols ...field.Expr) ILabelRelationshipDo {
+	return l.withDO(l.DO.Group(cols...))
+}
+
+func (l labelRelationshipDo) Having(conds ...gen.Condition) ILabelRelationshipDo {
+	return l.withDO(l.DO.Having(conds...))
+}
+
+func (l labelRelationshipDo) Limit(limit int) ILabelRelationshipDo {
+	return l.withDO(l.DO.Limit(limit))
+}
+
+func (l labelRelationshipDo) Offset(offset int) ILabelRelationshipDo {
+	return l.withDO(l.DO.Offset(offset))
+}
+
+func (l labelRelationshipDo) Scopes(funcs ...func(gen.Dao) gen.Dao) ILabelRelationshipDo {
+	return l.withDO(l.DO.Scopes(funcs...))
+}
+
+func (l labelRelationshipDo) Unscoped() ILabelRelationshipDo {
+	return l.withDO(l.DO.Unscoped())
+}
+
+func (l labelRelationshipDo) Create(values ...*model.LabelRelationship) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return l.DO.Create(values)
+}
+
+func (l labelRelationshipDo) CreateInBatches(values []*model.LabelRelationship, batchSize int) error {
+	return l.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (l labelRelationshipDo) Save(values ...*model.LabelRelationship) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return l.DO.Save(values)
+}
+
+func (l labelRelationshipDo) First() (*model.LabelRelationship, error) {
+	if result, err := l.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.LabelRelationship), nil
+	}
+}
+
+func (l labelRelationshipDo) Take() (*model.LabelRelationship, error) {
+	if result, err := l.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.LabelRelationship), nil
+	}
+}
+
+func (l labelRelationshipDo) Last() (*model.LabelRelationship, error) {
+	if result, err := l.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.LabelRelationship), nil
+	}
+}
+
+func (l labelRelationshipDo) Find() ([]*model.LabelRelationship, error) {
+	result, err := l.DO.Find()
+	return result.([]*model.LabelRelationship), err
+}
+
+func (l labelRelationshipDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.LabelRelationship, err error) {
+	buf := make([]*model.LabelRelationship, 0, batchSize)
+	err = l.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (l labelRelationshipDo) FindInBatches(result *[]*model.LabelRelationship, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return l.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (l labelRelationshipDo) Attrs(attrs ...field.AssignExpr) ILabelRelationshipDo {
+	return l.withDO(l.DO.Attrs(attrs...))
+}
+
+func (l labelRelationshipDo) Assign(attrs ...field.AssignExpr) ILabelRelationshipDo {
+	return l.withDO(l.DO.Assign(attrs...))
+}
+
+func (l labelRelationshipDo) Joins(fields ...field.RelationField) ILabelRelationshipDo {
+	for _, _f := range fields {
+		l = *l.withDO(l.DO.Joins(_f))
+	}
+	return &l
+}
+
+func (l labelRelationshipDo) Preload(fields ...field.RelationField) ILabelRelationshipDo {
+	for _, _f := range fields {
+		l = *l.withDO(l.DO.Preload(_f))
+	}
+	return &l
+}
+
+func (l labelRelationshipDo) FirstOrInit() (*model.LabelRelationship, error) {
+	if result, err := l.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.LabelRelationship), nil
+	}
+}
+
+func (l labelRelationshipDo) FirstOrCreate() (*model.LabelRelationship, error) {
+	if result, err := l.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.LabelRelationship), nil
+	}
+}
+
+func (l labelRelationshipDo) FindByPage(offset int, limit int) (result []*model.LabelRelationship, count int64, err error) {
+	result, err = l.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = l.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (l labelRelationshipDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = l.Count()
+	if err != nil {
+		return
+	}
+
+	err = l.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (l labelRelationshipDo) Scan(result interface{}) (err error) {
+	return l.DO.Scan(result)
+}
+
+func (l labelRelationshipDo) Delete(models ...*model.LabelRelationship) (result gen.ResultInfo, err error) {
+	return l.DO.Delete(models)
+}
+
+func (l *labelRelationshipDo) withDO(do gen.Dao) *labelRelationshipDo {
+	l.DO = *do.(*gen.DO)
+	return l
+}

+ 416 - 0
database/dao/wechat/query/label_tagging.gen.go

@@ -0,0 +1,416 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newLabelTagging(db *gorm.DB, opts ...gen.DOOption) labelTagging {
+	_labelTagging := labelTagging{}
+
+	_labelTagging.labelTaggingDo.UseDB(db, opts...)
+	_labelTagging.labelTaggingDo.UseModel(&model.LabelTagging{})
+
+	tableName := _labelTagging.labelTaggingDo.TableName()
+	_labelTagging.ALL = field.NewAsterisk(tableName)
+	_labelTagging.ID = field.NewInt64(tableName, "id")
+	_labelTagging.CreatedAt = field.NewTime(tableName, "created_at")
+	_labelTagging.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_labelTagging.Status = field.NewInt64(tableName, "status")
+	_labelTagging.DeletedAt = field.NewField(tableName, "deleted_at")
+	_labelTagging.OrganizationID = field.NewInt64(tableName, "organization_id")
+	_labelTagging.Type = field.NewInt64(tableName, "type")
+	_labelTagging.Conditions = field.NewString(tableName, "conditions")
+	_labelTagging.ActionLabelAdd = field.NewString(tableName, "action_label_add")
+	_labelTagging.ActionLabelDel = field.NewString(tableName, "action_label_del")
+
+	_labelTagging.fillFieldMap()
+
+	return _labelTagging
+}
+
+type labelTagging struct {
+	labelTaggingDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	Status         field.Int64  // 状态 1 正常 2 禁用
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	OrganizationID field.Int64  // 机构 ID
+	Type           field.Int64  // 标签类型:1好友,2群组,3公众号,4企业微信联系人
+	Conditions     field.String // 标签的触达条件
+	ActionLabelAdd field.String // 命中后需要打的标签
+	ActionLabelDel field.String // 命中后需要打的标签
+
+	fieldMap map[string]field.Expr
+}
+
+func (l labelTagging) Table(newTableName string) *labelTagging {
+	l.labelTaggingDo.UseTable(newTableName)
+	return l.updateTableName(newTableName)
+}
+
+func (l labelTagging) As(alias string) *labelTagging {
+	l.labelTaggingDo.DO = *(l.labelTaggingDo.As(alias).(*gen.DO))
+	return l.updateTableName(alias)
+}
+
+func (l *labelTagging) updateTableName(table string) *labelTagging {
+	l.ALL = field.NewAsterisk(table)
+	l.ID = field.NewInt64(table, "id")
+	l.CreatedAt = field.NewTime(table, "created_at")
+	l.UpdatedAt = field.NewTime(table, "updated_at")
+	l.Status = field.NewInt64(table, "status")
+	l.DeletedAt = field.NewField(table, "deleted_at")
+	l.OrganizationID = field.NewInt64(table, "organization_id")
+	l.Type = field.NewInt64(table, "type")
+	l.Conditions = field.NewString(table, "conditions")
+	l.ActionLabelAdd = field.NewString(table, "action_label_add")
+	l.ActionLabelDel = field.NewString(table, "action_label_del")
+
+	l.fillFieldMap()
+
+	return l
+}
+
+func (l *labelTagging) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := l.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (l *labelTagging) fillFieldMap() {
+	l.fieldMap = make(map[string]field.Expr, 10)
+	l.fieldMap["id"] = l.ID
+	l.fieldMap["created_at"] = l.CreatedAt
+	l.fieldMap["updated_at"] = l.UpdatedAt
+	l.fieldMap["status"] = l.Status
+	l.fieldMap["deleted_at"] = l.DeletedAt
+	l.fieldMap["organization_id"] = l.OrganizationID
+	l.fieldMap["type"] = l.Type
+	l.fieldMap["conditions"] = l.Conditions
+	l.fieldMap["action_label_add"] = l.ActionLabelAdd
+	l.fieldMap["action_label_del"] = l.ActionLabelDel
+}
+
+func (l labelTagging) clone(db *gorm.DB) labelTagging {
+	l.labelTaggingDo.ReplaceConnPool(db.Statement.ConnPool)
+	return l
+}
+
+func (l labelTagging) replaceDB(db *gorm.DB) labelTagging {
+	l.labelTaggingDo.ReplaceDB(db)
+	return l
+}
+
+type labelTaggingDo struct{ gen.DO }
+
+type ILabelTaggingDo interface {
+	gen.SubQuery
+	Debug() ILabelTaggingDo
+	WithContext(ctx context.Context) ILabelTaggingDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() ILabelTaggingDo
+	WriteDB() ILabelTaggingDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) ILabelTaggingDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) ILabelTaggingDo
+	Not(conds ...gen.Condition) ILabelTaggingDo
+	Or(conds ...gen.Condition) ILabelTaggingDo
+	Select(conds ...field.Expr) ILabelTaggingDo
+	Where(conds ...gen.Condition) ILabelTaggingDo
+	Order(conds ...field.Expr) ILabelTaggingDo
+	Distinct(cols ...field.Expr) ILabelTaggingDo
+	Omit(cols ...field.Expr) ILabelTaggingDo
+	Join(table schema.Tabler, on ...field.Expr) ILabelTaggingDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) ILabelTaggingDo
+	RightJoin(table schema.Tabler, on ...field.Expr) ILabelTaggingDo
+	Group(cols ...field.Expr) ILabelTaggingDo
+	Having(conds ...gen.Condition) ILabelTaggingDo
+	Limit(limit int) ILabelTaggingDo
+	Offset(offset int) ILabelTaggingDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) ILabelTaggingDo
+	Unscoped() ILabelTaggingDo
+	Create(values ...*model.LabelTagging) error
+	CreateInBatches(values []*model.LabelTagging, batchSize int) error
+	Save(values ...*model.LabelTagging) error
+	First() (*model.LabelTagging, error)
+	Take() (*model.LabelTagging, error)
+	Last() (*model.LabelTagging, error)
+	Find() ([]*model.LabelTagging, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.LabelTagging, err error)
+	FindInBatches(result *[]*model.LabelTagging, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.LabelTagging) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) ILabelTaggingDo
+	Assign(attrs ...field.AssignExpr) ILabelTaggingDo
+	Joins(fields ...field.RelationField) ILabelTaggingDo
+	Preload(fields ...field.RelationField) ILabelTaggingDo
+	FirstOrInit() (*model.LabelTagging, error)
+	FirstOrCreate() (*model.LabelTagging, error)
+	FindByPage(offset int, limit int) (result []*model.LabelTagging, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) ILabelTaggingDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (l labelTaggingDo) Debug() ILabelTaggingDo {
+	return l.withDO(l.DO.Debug())
+}
+
+func (l labelTaggingDo) WithContext(ctx context.Context) ILabelTaggingDo {
+	return l.withDO(l.DO.WithContext(ctx))
+}
+
+func (l labelTaggingDo) ReadDB() ILabelTaggingDo {
+	return l.Clauses(dbresolver.Read)
+}
+
+func (l labelTaggingDo) WriteDB() ILabelTaggingDo {
+	return l.Clauses(dbresolver.Write)
+}
+
+func (l labelTaggingDo) Session(config *gorm.Session) ILabelTaggingDo {
+	return l.withDO(l.DO.Session(config))
+}
+
+func (l labelTaggingDo) Clauses(conds ...clause.Expression) ILabelTaggingDo {
+	return l.withDO(l.DO.Clauses(conds...))
+}
+
+func (l labelTaggingDo) Returning(value interface{}, columns ...string) ILabelTaggingDo {
+	return l.withDO(l.DO.Returning(value, columns...))
+}
+
+func (l labelTaggingDo) Not(conds ...gen.Condition) ILabelTaggingDo {
+	return l.withDO(l.DO.Not(conds...))
+}
+
+func (l labelTaggingDo) Or(conds ...gen.Condition) ILabelTaggingDo {
+	return l.withDO(l.DO.Or(conds...))
+}
+
+func (l labelTaggingDo) Select(conds ...field.Expr) ILabelTaggingDo {
+	return l.withDO(l.DO.Select(conds...))
+}
+
+func (l labelTaggingDo) Where(conds ...gen.Condition) ILabelTaggingDo {
+	return l.withDO(l.DO.Where(conds...))
+}
+
+func (l labelTaggingDo) Order(conds ...field.Expr) ILabelTaggingDo {
+	return l.withDO(l.DO.Order(conds...))
+}
+
+func (l labelTaggingDo) Distinct(cols ...field.Expr) ILabelTaggingDo {
+	return l.withDO(l.DO.Distinct(cols...))
+}
+
+func (l labelTaggingDo) Omit(cols ...field.Expr) ILabelTaggingDo {
+	return l.withDO(l.DO.Omit(cols...))
+}
+
+func (l labelTaggingDo) Join(table schema.Tabler, on ...field.Expr) ILabelTaggingDo {
+	return l.withDO(l.DO.Join(table, on...))
+}
+
+func (l labelTaggingDo) LeftJoin(table schema.Tabler, on ...field.Expr) ILabelTaggingDo {
+	return l.withDO(l.DO.LeftJoin(table, on...))
+}
+
+func (l labelTaggingDo) RightJoin(table schema.Tabler, on ...field.Expr) ILabelTaggingDo {
+	return l.withDO(l.DO.RightJoin(table, on...))
+}
+
+func (l labelTaggingDo) Group(cols ...field.Expr) ILabelTaggingDo {
+	return l.withDO(l.DO.Group(cols...))
+}
+
+func (l labelTaggingDo) Having(conds ...gen.Condition) ILabelTaggingDo {
+	return l.withDO(l.DO.Having(conds...))
+}
+
+func (l labelTaggingDo) Limit(limit int) ILabelTaggingDo {
+	return l.withDO(l.DO.Limit(limit))
+}
+
+func (l labelTaggingDo) Offset(offset int) ILabelTaggingDo {
+	return l.withDO(l.DO.Offset(offset))
+}
+
+func (l labelTaggingDo) Scopes(funcs ...func(gen.Dao) gen.Dao) ILabelTaggingDo {
+	return l.withDO(l.DO.Scopes(funcs...))
+}
+
+func (l labelTaggingDo) Unscoped() ILabelTaggingDo {
+	return l.withDO(l.DO.Unscoped())
+}
+
+func (l labelTaggingDo) Create(values ...*model.LabelTagging) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return l.DO.Create(values)
+}
+
+func (l labelTaggingDo) CreateInBatches(values []*model.LabelTagging, batchSize int) error {
+	return l.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (l labelTaggingDo) Save(values ...*model.LabelTagging) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return l.DO.Save(values)
+}
+
+func (l labelTaggingDo) First() (*model.LabelTagging, error) {
+	if result, err := l.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.LabelTagging), nil
+	}
+}
+
+func (l labelTaggingDo) Take() (*model.LabelTagging, error) {
+	if result, err := l.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.LabelTagging), nil
+	}
+}
+
+func (l labelTaggingDo) Last() (*model.LabelTagging, error) {
+	if result, err := l.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.LabelTagging), nil
+	}
+}
+
+func (l labelTaggingDo) Find() ([]*model.LabelTagging, error) {
+	result, err := l.DO.Find()
+	return result.([]*model.LabelTagging), err
+}
+
+func (l labelTaggingDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.LabelTagging, err error) {
+	buf := make([]*model.LabelTagging, 0, batchSize)
+	err = l.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (l labelTaggingDo) FindInBatches(result *[]*model.LabelTagging, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return l.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (l labelTaggingDo) Attrs(attrs ...field.AssignExpr) ILabelTaggingDo {
+	return l.withDO(l.DO.Attrs(attrs...))
+}
+
+func (l labelTaggingDo) Assign(attrs ...field.AssignExpr) ILabelTaggingDo {
+	return l.withDO(l.DO.Assign(attrs...))
+}
+
+func (l labelTaggingDo) Joins(fields ...field.RelationField) ILabelTaggingDo {
+	for _, _f := range fields {
+		l = *l.withDO(l.DO.Joins(_f))
+	}
+	return &l
+}
+
+func (l labelTaggingDo) Preload(fields ...field.RelationField) ILabelTaggingDo {
+	for _, _f := range fields {
+		l = *l.withDO(l.DO.Preload(_f))
+	}
+	return &l
+}
+
+func (l labelTaggingDo) FirstOrInit() (*model.LabelTagging, error) {
+	if result, err := l.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.LabelTagging), nil
+	}
+}
+
+func (l labelTaggingDo) FirstOrCreate() (*model.LabelTagging, error) {
+	if result, err := l.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.LabelTagging), nil
+	}
+}
+
+func (l labelTaggingDo) FindByPage(offset int, limit int) (result []*model.LabelTagging, count int64, err error) {
+	result, err = l.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = l.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (l labelTaggingDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = l.Count()
+	if err != nil {
+		return
+	}
+
+	err = l.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (l labelTaggingDo) Scan(result interface{}) (err error) {
+	return l.DO.Scan(result)
+}
+
+func (l labelTaggingDo) Delete(models ...*model.LabelTagging) (result gen.ResultInfo, err error) {
+	return l.DO.Delete(models)
+}
+
+func (l *labelTaggingDo) withDO(do gen.Dao) *labelTaggingDo {
+	l.DO = *do.(*gen.DO)
+	return l
+}

+ 448 - 0
database/dao/wechat/query/message_records.gen.go

@@ -0,0 +1,448 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newMessageRecord(db *gorm.DB, opts ...gen.DOOption) messageRecord {
+	_messageRecord := messageRecord{}
+
+	_messageRecord.messageRecordDo.UseDB(db, opts...)
+	_messageRecord.messageRecordDo.UseModel(&model.MessageRecord{})
+
+	tableName := _messageRecord.messageRecordDo.TableName()
+	_messageRecord.ALL = field.NewAsterisk(tableName)
+	_messageRecord.ID = field.NewInt64(tableName, "id")
+	_messageRecord.CreatedAt = field.NewTime(tableName, "created_at")
+	_messageRecord.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_messageRecord.Status = field.NewInt64(tableName, "status")
+	_messageRecord.DeletedAt = field.NewField(tableName, "deleted_at")
+	_messageRecord.BotWxid = field.NewString(tableName, "bot_wxid")
+	_messageRecord.ContactID = field.NewInt64(tableName, "contact_id")
+	_messageRecord.ContactType = field.NewInt64(tableName, "contact_type")
+	_messageRecord.ContactWxid = field.NewString(tableName, "contact_wxid")
+	_messageRecord.ContentType = field.NewInt64(tableName, "content_type")
+	_messageRecord.Content = field.NewString(tableName, "content")
+	_messageRecord.Meta = field.NewString(tableName, "meta")
+	_messageRecord.ErrorDetail = field.NewString(tableName, "error_detail")
+	_messageRecord.SendTime = field.NewTime(tableName, "send_time")
+	_messageRecord.SourceType = field.NewInt64(tableName, "source_type")
+	_messageRecord.SourceID = field.NewInt64(tableName, "source_id")
+	_messageRecord.SubSourceID = field.NewInt64(tableName, "sub_source_id")
+	_messageRecord.OrganizationID = field.NewInt64(tableName, "organization_id")
+
+	_messageRecord.fillFieldMap()
+
+	return _messageRecord
+}
+
+type messageRecord struct {
+	messageRecordDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	Status         field.Int64  // 发送状态:1 未发送  2  发送中  3 发送成功 4 发送失败 ….(待定)
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	BotWxid        field.String // 机器人微信 id
+	ContactID      field.Int64  // 联系人 id
+	ContactType    field.Int64  // 类型:1好友,2群组,3企业微信联系人
+	ContactWxid    field.String // 接收方微信 id
+	ContentType    field.Int64  // 内容类型 1 文本 2 文件
+	Content        field.String // 发送内容
+	Meta           field.String // 元数据(如文件名)
+	ErrorDetail    field.String // 异常原因
+	SendTime       field.Time   // 发送时间
+	SourceType     field.Int64  // 源类型 1 点发 2 群发 3 SOP 阶段 4 SOP 节点
+	SourceID       field.Int64  // 源 ID
+	SubSourceID    field.Int64  // 次源 ID
+	OrganizationID field.Int64  // 机构 ID
+
+	fieldMap map[string]field.Expr
+}
+
+func (m messageRecord) Table(newTableName string) *messageRecord {
+	m.messageRecordDo.UseTable(newTableName)
+	return m.updateTableName(newTableName)
+}
+
+func (m messageRecord) As(alias string) *messageRecord {
+	m.messageRecordDo.DO = *(m.messageRecordDo.As(alias).(*gen.DO))
+	return m.updateTableName(alias)
+}
+
+func (m *messageRecord) updateTableName(table string) *messageRecord {
+	m.ALL = field.NewAsterisk(table)
+	m.ID = field.NewInt64(table, "id")
+	m.CreatedAt = field.NewTime(table, "created_at")
+	m.UpdatedAt = field.NewTime(table, "updated_at")
+	m.Status = field.NewInt64(table, "status")
+	m.DeletedAt = field.NewField(table, "deleted_at")
+	m.BotWxid = field.NewString(table, "bot_wxid")
+	m.ContactID = field.NewInt64(table, "contact_id")
+	m.ContactType = field.NewInt64(table, "contact_type")
+	m.ContactWxid = field.NewString(table, "contact_wxid")
+	m.ContentType = field.NewInt64(table, "content_type")
+	m.Content = field.NewString(table, "content")
+	m.Meta = field.NewString(table, "meta")
+	m.ErrorDetail = field.NewString(table, "error_detail")
+	m.SendTime = field.NewTime(table, "send_time")
+	m.SourceType = field.NewInt64(table, "source_type")
+	m.SourceID = field.NewInt64(table, "source_id")
+	m.SubSourceID = field.NewInt64(table, "sub_source_id")
+	m.OrganizationID = field.NewInt64(table, "organization_id")
+
+	m.fillFieldMap()
+
+	return m
+}
+
+func (m *messageRecord) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := m.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (m *messageRecord) fillFieldMap() {
+	m.fieldMap = make(map[string]field.Expr, 18)
+	m.fieldMap["id"] = m.ID
+	m.fieldMap["created_at"] = m.CreatedAt
+	m.fieldMap["updated_at"] = m.UpdatedAt
+	m.fieldMap["status"] = m.Status
+	m.fieldMap["deleted_at"] = m.DeletedAt
+	m.fieldMap["bot_wxid"] = m.BotWxid
+	m.fieldMap["contact_id"] = m.ContactID
+	m.fieldMap["contact_type"] = m.ContactType
+	m.fieldMap["contact_wxid"] = m.ContactWxid
+	m.fieldMap["content_type"] = m.ContentType
+	m.fieldMap["content"] = m.Content
+	m.fieldMap["meta"] = m.Meta
+	m.fieldMap["error_detail"] = m.ErrorDetail
+	m.fieldMap["send_time"] = m.SendTime
+	m.fieldMap["source_type"] = m.SourceType
+	m.fieldMap["source_id"] = m.SourceID
+	m.fieldMap["sub_source_id"] = m.SubSourceID
+	m.fieldMap["organization_id"] = m.OrganizationID
+}
+
+func (m messageRecord) clone(db *gorm.DB) messageRecord {
+	m.messageRecordDo.ReplaceConnPool(db.Statement.ConnPool)
+	return m
+}
+
+func (m messageRecord) replaceDB(db *gorm.DB) messageRecord {
+	m.messageRecordDo.ReplaceDB(db)
+	return m
+}
+
+type messageRecordDo struct{ gen.DO }
+
+type IMessageRecordDo interface {
+	gen.SubQuery
+	Debug() IMessageRecordDo
+	WithContext(ctx context.Context) IMessageRecordDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IMessageRecordDo
+	WriteDB() IMessageRecordDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IMessageRecordDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IMessageRecordDo
+	Not(conds ...gen.Condition) IMessageRecordDo
+	Or(conds ...gen.Condition) IMessageRecordDo
+	Select(conds ...field.Expr) IMessageRecordDo
+	Where(conds ...gen.Condition) IMessageRecordDo
+	Order(conds ...field.Expr) IMessageRecordDo
+	Distinct(cols ...field.Expr) IMessageRecordDo
+	Omit(cols ...field.Expr) IMessageRecordDo
+	Join(table schema.Tabler, on ...field.Expr) IMessageRecordDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IMessageRecordDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IMessageRecordDo
+	Group(cols ...field.Expr) IMessageRecordDo
+	Having(conds ...gen.Condition) IMessageRecordDo
+	Limit(limit int) IMessageRecordDo
+	Offset(offset int) IMessageRecordDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IMessageRecordDo
+	Unscoped() IMessageRecordDo
+	Create(values ...*model.MessageRecord) error
+	CreateInBatches(values []*model.MessageRecord, batchSize int) error
+	Save(values ...*model.MessageRecord) error
+	First() (*model.MessageRecord, error)
+	Take() (*model.MessageRecord, error)
+	Last() (*model.MessageRecord, error)
+	Find() ([]*model.MessageRecord, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.MessageRecord, err error)
+	FindInBatches(result *[]*model.MessageRecord, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.MessageRecord) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IMessageRecordDo
+	Assign(attrs ...field.AssignExpr) IMessageRecordDo
+	Joins(fields ...field.RelationField) IMessageRecordDo
+	Preload(fields ...field.RelationField) IMessageRecordDo
+	FirstOrInit() (*model.MessageRecord, error)
+	FirstOrCreate() (*model.MessageRecord, error)
+	FindByPage(offset int, limit int) (result []*model.MessageRecord, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IMessageRecordDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (m messageRecordDo) Debug() IMessageRecordDo {
+	return m.withDO(m.DO.Debug())
+}
+
+func (m messageRecordDo) WithContext(ctx context.Context) IMessageRecordDo {
+	return m.withDO(m.DO.WithContext(ctx))
+}
+
+func (m messageRecordDo) ReadDB() IMessageRecordDo {
+	return m.Clauses(dbresolver.Read)
+}
+
+func (m messageRecordDo) WriteDB() IMessageRecordDo {
+	return m.Clauses(dbresolver.Write)
+}
+
+func (m messageRecordDo) Session(config *gorm.Session) IMessageRecordDo {
+	return m.withDO(m.DO.Session(config))
+}
+
+func (m messageRecordDo) Clauses(conds ...clause.Expression) IMessageRecordDo {
+	return m.withDO(m.DO.Clauses(conds...))
+}
+
+func (m messageRecordDo) Returning(value interface{}, columns ...string) IMessageRecordDo {
+	return m.withDO(m.DO.Returning(value, columns...))
+}
+
+func (m messageRecordDo) Not(conds ...gen.Condition) IMessageRecordDo {
+	return m.withDO(m.DO.Not(conds...))
+}
+
+func (m messageRecordDo) Or(conds ...gen.Condition) IMessageRecordDo {
+	return m.withDO(m.DO.Or(conds...))
+}
+
+func (m messageRecordDo) Select(conds ...field.Expr) IMessageRecordDo {
+	return m.withDO(m.DO.Select(conds...))
+}
+
+func (m messageRecordDo) Where(conds ...gen.Condition) IMessageRecordDo {
+	return m.withDO(m.DO.Where(conds...))
+}
+
+func (m messageRecordDo) Order(conds ...field.Expr) IMessageRecordDo {
+	return m.withDO(m.DO.Order(conds...))
+}
+
+func (m messageRecordDo) Distinct(cols ...field.Expr) IMessageRecordDo {
+	return m.withDO(m.DO.Distinct(cols...))
+}
+
+func (m messageRecordDo) Omit(cols ...field.Expr) IMessageRecordDo {
+	return m.withDO(m.DO.Omit(cols...))
+}
+
+func (m messageRecordDo) Join(table schema.Tabler, on ...field.Expr) IMessageRecordDo {
+	return m.withDO(m.DO.Join(table, on...))
+}
+
+func (m messageRecordDo) LeftJoin(table schema.Tabler, on ...field.Expr) IMessageRecordDo {
+	return m.withDO(m.DO.LeftJoin(table, on...))
+}
+
+func (m messageRecordDo) RightJoin(table schema.Tabler, on ...field.Expr) IMessageRecordDo {
+	return m.withDO(m.DO.RightJoin(table, on...))
+}
+
+func (m messageRecordDo) Group(cols ...field.Expr) IMessageRecordDo {
+	return m.withDO(m.DO.Group(cols...))
+}
+
+func (m messageRecordDo) Having(conds ...gen.Condition) IMessageRecordDo {
+	return m.withDO(m.DO.Having(conds...))
+}
+
+func (m messageRecordDo) Limit(limit int) IMessageRecordDo {
+	return m.withDO(m.DO.Limit(limit))
+}
+
+func (m messageRecordDo) Offset(offset int) IMessageRecordDo {
+	return m.withDO(m.DO.Offset(offset))
+}
+
+func (m messageRecordDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IMessageRecordDo {
+	return m.withDO(m.DO.Scopes(funcs...))
+}
+
+func (m messageRecordDo) Unscoped() IMessageRecordDo {
+	return m.withDO(m.DO.Unscoped())
+}
+
+func (m messageRecordDo) Create(values ...*model.MessageRecord) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return m.DO.Create(values)
+}
+
+func (m messageRecordDo) CreateInBatches(values []*model.MessageRecord, batchSize int) error {
+	return m.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (m messageRecordDo) Save(values ...*model.MessageRecord) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return m.DO.Save(values)
+}
+
+func (m messageRecordDo) First() (*model.MessageRecord, error) {
+	if result, err := m.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.MessageRecord), nil
+	}
+}
+
+func (m messageRecordDo) Take() (*model.MessageRecord, error) {
+	if result, err := m.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.MessageRecord), nil
+	}
+}
+
+func (m messageRecordDo) Last() (*model.MessageRecord, error) {
+	if result, err := m.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.MessageRecord), nil
+	}
+}
+
+func (m messageRecordDo) Find() ([]*model.MessageRecord, error) {
+	result, err := m.DO.Find()
+	return result.([]*model.MessageRecord), err
+}
+
+func (m messageRecordDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.MessageRecord, err error) {
+	buf := make([]*model.MessageRecord, 0, batchSize)
+	err = m.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (m messageRecordDo) FindInBatches(result *[]*model.MessageRecord, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return m.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (m messageRecordDo) Attrs(attrs ...field.AssignExpr) IMessageRecordDo {
+	return m.withDO(m.DO.Attrs(attrs...))
+}
+
+func (m messageRecordDo) Assign(attrs ...field.AssignExpr) IMessageRecordDo {
+	return m.withDO(m.DO.Assign(attrs...))
+}
+
+func (m messageRecordDo) Joins(fields ...field.RelationField) IMessageRecordDo {
+	for _, _f := range fields {
+		m = *m.withDO(m.DO.Joins(_f))
+	}
+	return &m
+}
+
+func (m messageRecordDo) Preload(fields ...field.RelationField) IMessageRecordDo {
+	for _, _f := range fields {
+		m = *m.withDO(m.DO.Preload(_f))
+	}
+	return &m
+}
+
+func (m messageRecordDo) FirstOrInit() (*model.MessageRecord, error) {
+	if result, err := m.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.MessageRecord), nil
+	}
+}
+
+func (m messageRecordDo) FirstOrCreate() (*model.MessageRecord, error) {
+	if result, err := m.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.MessageRecord), nil
+	}
+}
+
+func (m messageRecordDo) FindByPage(offset int, limit int) (result []*model.MessageRecord, count int64, err error) {
+	result, err = m.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = m.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (m messageRecordDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = m.Count()
+	if err != nil {
+		return
+	}
+
+	err = m.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (m messageRecordDo) Scan(result interface{}) (err error) {
+	return m.DO.Scan(result)
+}
+
+func (m messageRecordDo) Delete(models ...*model.MessageRecord) (result gen.ResultInfo, err error) {
+	return m.DO.Delete(models)
+}
+
+func (m *messageRecordDo) withDO(do gen.Dao) *messageRecordDo {
+	m.DO = *do.(*gen.DO)
+	return m
+}

+ 448 - 0
database/dao/wechat/query/mismatch_records.gen.go

@@ -0,0 +1,448 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newMismatchRecord(db *gorm.DB, opts ...gen.DOOption) mismatchRecord {
+	_mismatchRecord := mismatchRecord{}
+
+	_mismatchRecord.mismatchRecordDo.UseDB(db, opts...)
+	_mismatchRecord.mismatchRecordDo.UseModel(&model.MismatchRecord{})
+
+	tableName := _mismatchRecord.mismatchRecordDo.TableName()
+	_mismatchRecord.ALL = field.NewAsterisk(tableName)
+	_mismatchRecord.ID = field.NewString(tableName, "id")
+	_mismatchRecord.ExternalID = field.NewString(tableName, "external_id")
+	_mismatchRecord.IndustryType = field.NewInt64(tableName, "industry_type")
+	_mismatchRecord.ChatHistory = field.NewString(tableName, "chat_history")
+	_mismatchRecord.Missed = field.NewString(tableName, "missed")
+	_mismatchRecord.Ignore = field.NewInt64(tableName, "ignore")
+	_mismatchRecord.LlmIgnore = field.NewInt64(tableName, "llm_ignore")
+	_mismatchRecord.OrgID = field.NewInt64(tableName, "org_id")
+	_mismatchRecord.Status = field.NewInt64(tableName, "status")
+	_mismatchRecord.IgnoreResponseData = field.NewString(tableName, "ignore_response_data")
+	_mismatchRecord.RequestData = field.NewString(tableName, "request_data")
+	_mismatchRecord.ResponseData = field.NewString(tableName, "response_data")
+	_mismatchRecord.CreatedAt = field.NewTime(tableName, "created_at")
+	_mismatchRecord.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_mismatchRecord.UserIntent = field.NewString(tableName, "user_intent")
+	_mismatchRecord.SimilarReply = field.NewString(tableName, "similar_reply")
+	_mismatchRecord.Keywords = field.NewString(tableName, "keywords")
+	_mismatchRecord.Regular = field.NewString(tableName, "regular")
+
+	_mismatchRecord.fillFieldMap()
+
+	return _mismatchRecord
+}
+
+type mismatchRecord struct {
+	mismatchRecordDo
+
+	ALL                field.Asterisk
+	ID                 field.String // 主键id
+	ExternalID         field.String // 外部id
+	IndustryType       field.Int64  // 评分规则代码 0 通用 1 教育
+	ChatHistory        field.String // 通话记录
+	Missed             field.String // 未匹配内容
+	Ignore             field.Int64  // 0 自动过滤(默认) 1 手动标记忽略 2 不忽略强制分析
+	LlmIgnore          field.Int64  // 0 未过滤 1被忽略 2未被忽略
+	OrgID              field.Int64  // 机构 ID
+	Status             field.Int64  // 状态 1 入库 2 已判断 3 已回调
+	IgnoreResponseData field.String
+	RequestData        field.String
+	ResponseData       field.String
+	CreatedAt          field.Time   // Create Time | 创建日期
+	UpdatedAt          field.Time   // Update Time | 修改日期
+	UserIntent         field.String // 针对未匹配内容,推理用户的真实目的
+	SimilarReply       field.String // 针对未匹配内容,生成类似的回复
+	Keywords           field.String // 生成辅助关键词
+	Regular            field.String // 生成辅助正则表达式
+
+	fieldMap map[string]field.Expr
+}
+
+func (m mismatchRecord) Table(newTableName string) *mismatchRecord {
+	m.mismatchRecordDo.UseTable(newTableName)
+	return m.updateTableName(newTableName)
+}
+
+func (m mismatchRecord) As(alias string) *mismatchRecord {
+	m.mismatchRecordDo.DO = *(m.mismatchRecordDo.As(alias).(*gen.DO))
+	return m.updateTableName(alias)
+}
+
+func (m *mismatchRecord) updateTableName(table string) *mismatchRecord {
+	m.ALL = field.NewAsterisk(table)
+	m.ID = field.NewString(table, "id")
+	m.ExternalID = field.NewString(table, "external_id")
+	m.IndustryType = field.NewInt64(table, "industry_type")
+	m.ChatHistory = field.NewString(table, "chat_history")
+	m.Missed = field.NewString(table, "missed")
+	m.Ignore = field.NewInt64(table, "ignore")
+	m.LlmIgnore = field.NewInt64(table, "llm_ignore")
+	m.OrgID = field.NewInt64(table, "org_id")
+	m.Status = field.NewInt64(table, "status")
+	m.IgnoreResponseData = field.NewString(table, "ignore_response_data")
+	m.RequestData = field.NewString(table, "request_data")
+	m.ResponseData = field.NewString(table, "response_data")
+	m.CreatedAt = field.NewTime(table, "created_at")
+	m.UpdatedAt = field.NewTime(table, "updated_at")
+	m.UserIntent = field.NewString(table, "user_intent")
+	m.SimilarReply = field.NewString(table, "similar_reply")
+	m.Keywords = field.NewString(table, "keywords")
+	m.Regular = field.NewString(table, "regular")
+
+	m.fillFieldMap()
+
+	return m
+}
+
+func (m *mismatchRecord) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := m.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (m *mismatchRecord) fillFieldMap() {
+	m.fieldMap = make(map[string]field.Expr, 18)
+	m.fieldMap["id"] = m.ID
+	m.fieldMap["external_id"] = m.ExternalID
+	m.fieldMap["industry_type"] = m.IndustryType
+	m.fieldMap["chat_history"] = m.ChatHistory
+	m.fieldMap["missed"] = m.Missed
+	m.fieldMap["ignore"] = m.Ignore
+	m.fieldMap["llm_ignore"] = m.LlmIgnore
+	m.fieldMap["org_id"] = m.OrgID
+	m.fieldMap["status"] = m.Status
+	m.fieldMap["ignore_response_data"] = m.IgnoreResponseData
+	m.fieldMap["request_data"] = m.RequestData
+	m.fieldMap["response_data"] = m.ResponseData
+	m.fieldMap["created_at"] = m.CreatedAt
+	m.fieldMap["updated_at"] = m.UpdatedAt
+	m.fieldMap["user_intent"] = m.UserIntent
+	m.fieldMap["similar_reply"] = m.SimilarReply
+	m.fieldMap["keywords"] = m.Keywords
+	m.fieldMap["regular"] = m.Regular
+}
+
+func (m mismatchRecord) clone(db *gorm.DB) mismatchRecord {
+	m.mismatchRecordDo.ReplaceConnPool(db.Statement.ConnPool)
+	return m
+}
+
+func (m mismatchRecord) replaceDB(db *gorm.DB) mismatchRecord {
+	m.mismatchRecordDo.ReplaceDB(db)
+	return m
+}
+
+type mismatchRecordDo struct{ gen.DO }
+
+type IMismatchRecordDo interface {
+	gen.SubQuery
+	Debug() IMismatchRecordDo
+	WithContext(ctx context.Context) IMismatchRecordDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IMismatchRecordDo
+	WriteDB() IMismatchRecordDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IMismatchRecordDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IMismatchRecordDo
+	Not(conds ...gen.Condition) IMismatchRecordDo
+	Or(conds ...gen.Condition) IMismatchRecordDo
+	Select(conds ...field.Expr) IMismatchRecordDo
+	Where(conds ...gen.Condition) IMismatchRecordDo
+	Order(conds ...field.Expr) IMismatchRecordDo
+	Distinct(cols ...field.Expr) IMismatchRecordDo
+	Omit(cols ...field.Expr) IMismatchRecordDo
+	Join(table schema.Tabler, on ...field.Expr) IMismatchRecordDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IMismatchRecordDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IMismatchRecordDo
+	Group(cols ...field.Expr) IMismatchRecordDo
+	Having(conds ...gen.Condition) IMismatchRecordDo
+	Limit(limit int) IMismatchRecordDo
+	Offset(offset int) IMismatchRecordDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IMismatchRecordDo
+	Unscoped() IMismatchRecordDo
+	Create(values ...*model.MismatchRecord) error
+	CreateInBatches(values []*model.MismatchRecord, batchSize int) error
+	Save(values ...*model.MismatchRecord) error
+	First() (*model.MismatchRecord, error)
+	Take() (*model.MismatchRecord, error)
+	Last() (*model.MismatchRecord, error)
+	Find() ([]*model.MismatchRecord, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.MismatchRecord, err error)
+	FindInBatches(result *[]*model.MismatchRecord, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.MismatchRecord) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IMismatchRecordDo
+	Assign(attrs ...field.AssignExpr) IMismatchRecordDo
+	Joins(fields ...field.RelationField) IMismatchRecordDo
+	Preload(fields ...field.RelationField) IMismatchRecordDo
+	FirstOrInit() (*model.MismatchRecord, error)
+	FirstOrCreate() (*model.MismatchRecord, error)
+	FindByPage(offset int, limit int) (result []*model.MismatchRecord, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IMismatchRecordDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (m mismatchRecordDo) Debug() IMismatchRecordDo {
+	return m.withDO(m.DO.Debug())
+}
+
+func (m mismatchRecordDo) WithContext(ctx context.Context) IMismatchRecordDo {
+	return m.withDO(m.DO.WithContext(ctx))
+}
+
+func (m mismatchRecordDo) ReadDB() IMismatchRecordDo {
+	return m.Clauses(dbresolver.Read)
+}
+
+func (m mismatchRecordDo) WriteDB() IMismatchRecordDo {
+	return m.Clauses(dbresolver.Write)
+}
+
+func (m mismatchRecordDo) Session(config *gorm.Session) IMismatchRecordDo {
+	return m.withDO(m.DO.Session(config))
+}
+
+func (m mismatchRecordDo) Clauses(conds ...clause.Expression) IMismatchRecordDo {
+	return m.withDO(m.DO.Clauses(conds...))
+}
+
+func (m mismatchRecordDo) Returning(value interface{}, columns ...string) IMismatchRecordDo {
+	return m.withDO(m.DO.Returning(value, columns...))
+}
+
+func (m mismatchRecordDo) Not(conds ...gen.Condition) IMismatchRecordDo {
+	return m.withDO(m.DO.Not(conds...))
+}
+
+func (m mismatchRecordDo) Or(conds ...gen.Condition) IMismatchRecordDo {
+	return m.withDO(m.DO.Or(conds...))
+}
+
+func (m mismatchRecordDo) Select(conds ...field.Expr) IMismatchRecordDo {
+	return m.withDO(m.DO.Select(conds...))
+}
+
+func (m mismatchRecordDo) Where(conds ...gen.Condition) IMismatchRecordDo {
+	return m.withDO(m.DO.Where(conds...))
+}
+
+func (m mismatchRecordDo) Order(conds ...field.Expr) IMismatchRecordDo {
+	return m.withDO(m.DO.Order(conds...))
+}
+
+func (m mismatchRecordDo) Distinct(cols ...field.Expr) IMismatchRecordDo {
+	return m.withDO(m.DO.Distinct(cols...))
+}
+
+func (m mismatchRecordDo) Omit(cols ...field.Expr) IMismatchRecordDo {
+	return m.withDO(m.DO.Omit(cols...))
+}
+
+func (m mismatchRecordDo) Join(table schema.Tabler, on ...field.Expr) IMismatchRecordDo {
+	return m.withDO(m.DO.Join(table, on...))
+}
+
+func (m mismatchRecordDo) LeftJoin(table schema.Tabler, on ...field.Expr) IMismatchRecordDo {
+	return m.withDO(m.DO.LeftJoin(table, on...))
+}
+
+func (m mismatchRecordDo) RightJoin(table schema.Tabler, on ...field.Expr) IMismatchRecordDo {
+	return m.withDO(m.DO.RightJoin(table, on...))
+}
+
+func (m mismatchRecordDo) Group(cols ...field.Expr) IMismatchRecordDo {
+	return m.withDO(m.DO.Group(cols...))
+}
+
+func (m mismatchRecordDo) Having(conds ...gen.Condition) IMismatchRecordDo {
+	return m.withDO(m.DO.Having(conds...))
+}
+
+func (m mismatchRecordDo) Limit(limit int) IMismatchRecordDo {
+	return m.withDO(m.DO.Limit(limit))
+}
+
+func (m mismatchRecordDo) Offset(offset int) IMismatchRecordDo {
+	return m.withDO(m.DO.Offset(offset))
+}
+
+func (m mismatchRecordDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IMismatchRecordDo {
+	return m.withDO(m.DO.Scopes(funcs...))
+}
+
+func (m mismatchRecordDo) Unscoped() IMismatchRecordDo {
+	return m.withDO(m.DO.Unscoped())
+}
+
+func (m mismatchRecordDo) Create(values ...*model.MismatchRecord) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return m.DO.Create(values)
+}
+
+func (m mismatchRecordDo) CreateInBatches(values []*model.MismatchRecord, batchSize int) error {
+	return m.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (m mismatchRecordDo) Save(values ...*model.MismatchRecord) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return m.DO.Save(values)
+}
+
+func (m mismatchRecordDo) First() (*model.MismatchRecord, error) {
+	if result, err := m.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.MismatchRecord), nil
+	}
+}
+
+func (m mismatchRecordDo) Take() (*model.MismatchRecord, error) {
+	if result, err := m.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.MismatchRecord), nil
+	}
+}
+
+func (m mismatchRecordDo) Last() (*model.MismatchRecord, error) {
+	if result, err := m.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.MismatchRecord), nil
+	}
+}
+
+func (m mismatchRecordDo) Find() ([]*model.MismatchRecord, error) {
+	result, err := m.DO.Find()
+	return result.([]*model.MismatchRecord), err
+}
+
+func (m mismatchRecordDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.MismatchRecord, err error) {
+	buf := make([]*model.MismatchRecord, 0, batchSize)
+	err = m.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (m mismatchRecordDo) FindInBatches(result *[]*model.MismatchRecord, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return m.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (m mismatchRecordDo) Attrs(attrs ...field.AssignExpr) IMismatchRecordDo {
+	return m.withDO(m.DO.Attrs(attrs...))
+}
+
+func (m mismatchRecordDo) Assign(attrs ...field.AssignExpr) IMismatchRecordDo {
+	return m.withDO(m.DO.Assign(attrs...))
+}
+
+func (m mismatchRecordDo) Joins(fields ...field.RelationField) IMismatchRecordDo {
+	for _, _f := range fields {
+		m = *m.withDO(m.DO.Joins(_f))
+	}
+	return &m
+}
+
+func (m mismatchRecordDo) Preload(fields ...field.RelationField) IMismatchRecordDo {
+	for _, _f := range fields {
+		m = *m.withDO(m.DO.Preload(_f))
+	}
+	return &m
+}
+
+func (m mismatchRecordDo) FirstOrInit() (*model.MismatchRecord, error) {
+	if result, err := m.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.MismatchRecord), nil
+	}
+}
+
+func (m mismatchRecordDo) FirstOrCreate() (*model.MismatchRecord, error) {
+	if result, err := m.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.MismatchRecord), nil
+	}
+}
+
+func (m mismatchRecordDo) FindByPage(offset int, limit int) (result []*model.MismatchRecord, count int64, err error) {
+	result, err = m.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = m.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (m mismatchRecordDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = m.Count()
+	if err != nil {
+		return
+	}
+
+	err = m.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (m mismatchRecordDo) Scan(result interface{}) (err error) {
+	return m.DO.Scan(result)
+}
+
+func (m mismatchRecordDo) Delete(models ...*model.MismatchRecord) (result gen.ResultInfo, err error) {
+	return m.DO.Delete(models)
+}
+
+func (m *mismatchRecordDo) withDO(do gen.Dao) *mismatchRecordDo {
+	m.DO = *do.(*gen.DO)
+	return m
+}

+ 425 - 0
database/dao/wechat/query/msg.gen.go

@@ -0,0 +1,425 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newMsg(db *gorm.DB, opts ...gen.DOOption) msg {
+	_msg := msg{}
+
+	_msg.msgDo.UseDB(db, opts...)
+	_msg.msgDo.UseModel(&model.Msg{})
+
+	tableName := _msg.msgDo.TableName()
+	_msg.ALL = field.NewAsterisk(tableName)
+	_msg.ID = field.NewInt64(tableName, "id")
+	_msg.CreatedAt = field.NewTime(tableName, "created_at")
+	_msg.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_msg.DeletedAt = field.NewField(tableName, "deleted_at")
+	_msg.Status = field.NewInt64(tableName, "status")
+	_msg.Fromwxid = field.NewString(tableName, "fromwxid")
+	_msg.Toid = field.NewString(tableName, "toid")
+	_msg.Msgtype = field.NewInt64(tableName, "msgtype")
+	_msg.Msg = field.NewString(tableName, "msg")
+	_msg.BatchNo = field.NewString(tableName, "batch_no")
+	_msg.Cc = field.NewString(tableName, "cc")
+	_msg.Phone = field.NewString(tableName, "phone")
+
+	_msg.fillFieldMap()
+
+	return _msg
+}
+
+// msg 消息表
+type msg struct {
+	msgDo
+
+	ALL       field.Asterisk
+	ID        field.Int64
+	CreatedAt field.Time   // Create Time | 创建日期
+	UpdatedAt field.Time   // Update Time | 修改日期
+	DeletedAt field.Field  // Delete Time | 删除日期
+	Status    field.Int64  // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	Fromwxid  field.String // 发送方微信ID
+	Toid      field.String // 接收人微信ID/群ID
+	Msgtype   field.Int64  // 消息类型
+	Msg       field.String // 消息
+	BatchNo   field.String // 批次号
+	Cc        field.String // 国家区号
+	Phone     field.String // 手机号
+
+	fieldMap map[string]field.Expr
+}
+
+func (m msg) Table(newTableName string) *msg {
+	m.msgDo.UseTable(newTableName)
+	return m.updateTableName(newTableName)
+}
+
+func (m msg) As(alias string) *msg {
+	m.msgDo.DO = *(m.msgDo.As(alias).(*gen.DO))
+	return m.updateTableName(alias)
+}
+
+func (m *msg) updateTableName(table string) *msg {
+	m.ALL = field.NewAsterisk(table)
+	m.ID = field.NewInt64(table, "id")
+	m.CreatedAt = field.NewTime(table, "created_at")
+	m.UpdatedAt = field.NewTime(table, "updated_at")
+	m.DeletedAt = field.NewField(table, "deleted_at")
+	m.Status = field.NewInt64(table, "status")
+	m.Fromwxid = field.NewString(table, "fromwxid")
+	m.Toid = field.NewString(table, "toid")
+	m.Msgtype = field.NewInt64(table, "msgtype")
+	m.Msg = field.NewString(table, "msg")
+	m.BatchNo = field.NewString(table, "batch_no")
+	m.Cc = field.NewString(table, "cc")
+	m.Phone = field.NewString(table, "phone")
+
+	m.fillFieldMap()
+
+	return m
+}
+
+func (m *msg) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := m.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (m *msg) fillFieldMap() {
+	m.fieldMap = make(map[string]field.Expr, 12)
+	m.fieldMap["id"] = m.ID
+	m.fieldMap["created_at"] = m.CreatedAt
+	m.fieldMap["updated_at"] = m.UpdatedAt
+	m.fieldMap["deleted_at"] = m.DeletedAt
+	m.fieldMap["status"] = m.Status
+	m.fieldMap["fromwxid"] = m.Fromwxid
+	m.fieldMap["toid"] = m.Toid
+	m.fieldMap["msgtype"] = m.Msgtype
+	m.fieldMap["msg"] = m.Msg
+	m.fieldMap["batch_no"] = m.BatchNo
+	m.fieldMap["cc"] = m.Cc
+	m.fieldMap["phone"] = m.Phone
+}
+
+func (m msg) clone(db *gorm.DB) msg {
+	m.msgDo.ReplaceConnPool(db.Statement.ConnPool)
+	return m
+}
+
+func (m msg) replaceDB(db *gorm.DB) msg {
+	m.msgDo.ReplaceDB(db)
+	return m
+}
+
+type msgDo struct{ gen.DO }
+
+type IMsgDo interface {
+	gen.SubQuery
+	Debug() IMsgDo
+	WithContext(ctx context.Context) IMsgDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IMsgDo
+	WriteDB() IMsgDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IMsgDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IMsgDo
+	Not(conds ...gen.Condition) IMsgDo
+	Or(conds ...gen.Condition) IMsgDo
+	Select(conds ...field.Expr) IMsgDo
+	Where(conds ...gen.Condition) IMsgDo
+	Order(conds ...field.Expr) IMsgDo
+	Distinct(cols ...field.Expr) IMsgDo
+	Omit(cols ...field.Expr) IMsgDo
+	Join(table schema.Tabler, on ...field.Expr) IMsgDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IMsgDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IMsgDo
+	Group(cols ...field.Expr) IMsgDo
+	Having(conds ...gen.Condition) IMsgDo
+	Limit(limit int) IMsgDo
+	Offset(offset int) IMsgDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IMsgDo
+	Unscoped() IMsgDo
+	Create(values ...*model.Msg) error
+	CreateInBatches(values []*model.Msg, batchSize int) error
+	Save(values ...*model.Msg) error
+	First() (*model.Msg, error)
+	Take() (*model.Msg, error)
+	Last() (*model.Msg, error)
+	Find() ([]*model.Msg, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Msg, err error)
+	FindInBatches(result *[]*model.Msg, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.Msg) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IMsgDo
+	Assign(attrs ...field.AssignExpr) IMsgDo
+	Joins(fields ...field.RelationField) IMsgDo
+	Preload(fields ...field.RelationField) IMsgDo
+	FirstOrInit() (*model.Msg, error)
+	FirstOrCreate() (*model.Msg, error)
+	FindByPage(offset int, limit int) (result []*model.Msg, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IMsgDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (m msgDo) Debug() IMsgDo {
+	return m.withDO(m.DO.Debug())
+}
+
+func (m msgDo) WithContext(ctx context.Context) IMsgDo {
+	return m.withDO(m.DO.WithContext(ctx))
+}
+
+func (m msgDo) ReadDB() IMsgDo {
+	return m.Clauses(dbresolver.Read)
+}
+
+func (m msgDo) WriteDB() IMsgDo {
+	return m.Clauses(dbresolver.Write)
+}
+
+func (m msgDo) Session(config *gorm.Session) IMsgDo {
+	return m.withDO(m.DO.Session(config))
+}
+
+func (m msgDo) Clauses(conds ...clause.Expression) IMsgDo {
+	return m.withDO(m.DO.Clauses(conds...))
+}
+
+func (m msgDo) Returning(value interface{}, columns ...string) IMsgDo {
+	return m.withDO(m.DO.Returning(value, columns...))
+}
+
+func (m msgDo) Not(conds ...gen.Condition) IMsgDo {
+	return m.withDO(m.DO.Not(conds...))
+}
+
+func (m msgDo) Or(conds ...gen.Condition) IMsgDo {
+	return m.withDO(m.DO.Or(conds...))
+}
+
+func (m msgDo) Select(conds ...field.Expr) IMsgDo {
+	return m.withDO(m.DO.Select(conds...))
+}
+
+func (m msgDo) Where(conds ...gen.Condition) IMsgDo {
+	return m.withDO(m.DO.Where(conds...))
+}
+
+func (m msgDo) Order(conds ...field.Expr) IMsgDo {
+	return m.withDO(m.DO.Order(conds...))
+}
+
+func (m msgDo) Distinct(cols ...field.Expr) IMsgDo {
+	return m.withDO(m.DO.Distinct(cols...))
+}
+
+func (m msgDo) Omit(cols ...field.Expr) IMsgDo {
+	return m.withDO(m.DO.Omit(cols...))
+}
+
+func (m msgDo) Join(table schema.Tabler, on ...field.Expr) IMsgDo {
+	return m.withDO(m.DO.Join(table, on...))
+}
+
+func (m msgDo) LeftJoin(table schema.Tabler, on ...field.Expr) IMsgDo {
+	return m.withDO(m.DO.LeftJoin(table, on...))
+}
+
+func (m msgDo) RightJoin(table schema.Tabler, on ...field.Expr) IMsgDo {
+	return m.withDO(m.DO.RightJoin(table, on...))
+}
+
+func (m msgDo) Group(cols ...field.Expr) IMsgDo {
+	return m.withDO(m.DO.Group(cols...))
+}
+
+func (m msgDo) Having(conds ...gen.Condition) IMsgDo {
+	return m.withDO(m.DO.Having(conds...))
+}
+
+func (m msgDo) Limit(limit int) IMsgDo {
+	return m.withDO(m.DO.Limit(limit))
+}
+
+func (m msgDo) Offset(offset int) IMsgDo {
+	return m.withDO(m.DO.Offset(offset))
+}
+
+func (m msgDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IMsgDo {
+	return m.withDO(m.DO.Scopes(funcs...))
+}
+
+func (m msgDo) Unscoped() IMsgDo {
+	return m.withDO(m.DO.Unscoped())
+}
+
+func (m msgDo) Create(values ...*model.Msg) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return m.DO.Create(values)
+}
+
+func (m msgDo) CreateInBatches(values []*model.Msg, batchSize int) error {
+	return m.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (m msgDo) Save(values ...*model.Msg) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return m.DO.Save(values)
+}
+
+func (m msgDo) First() (*model.Msg, error) {
+	if result, err := m.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Msg), nil
+	}
+}
+
+func (m msgDo) Take() (*model.Msg, error) {
+	if result, err := m.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Msg), nil
+	}
+}
+
+func (m msgDo) Last() (*model.Msg, error) {
+	if result, err := m.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Msg), nil
+	}
+}
+
+func (m msgDo) Find() ([]*model.Msg, error) {
+	result, err := m.DO.Find()
+	return result.([]*model.Msg), err
+}
+
+func (m msgDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Msg, err error) {
+	buf := make([]*model.Msg, 0, batchSize)
+	err = m.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (m msgDo) FindInBatches(result *[]*model.Msg, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return m.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (m msgDo) Attrs(attrs ...field.AssignExpr) IMsgDo {
+	return m.withDO(m.DO.Attrs(attrs...))
+}
+
+func (m msgDo) Assign(attrs ...field.AssignExpr) IMsgDo {
+	return m.withDO(m.DO.Assign(attrs...))
+}
+
+func (m msgDo) Joins(fields ...field.RelationField) IMsgDo {
+	for _, _f := range fields {
+		m = *m.withDO(m.DO.Joins(_f))
+	}
+	return &m
+}
+
+func (m msgDo) Preload(fields ...field.RelationField) IMsgDo {
+	for _, _f := range fields {
+		m = *m.withDO(m.DO.Preload(_f))
+	}
+	return &m
+}
+
+func (m msgDo) FirstOrInit() (*model.Msg, error) {
+	if result, err := m.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Msg), nil
+	}
+}
+
+func (m msgDo) FirstOrCreate() (*model.Msg, error) {
+	if result, err := m.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Msg), nil
+	}
+}
+
+func (m msgDo) FindByPage(offset int, limit int) (result []*model.Msg, count int64, err error) {
+	result, err = m.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = m.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (m msgDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = m.Count()
+	if err != nil {
+		return
+	}
+
+	err = m.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (m msgDo) Scan(result interface{}) (err error) {
+	return m.DO.Scan(result)
+}
+
+func (m msgDo) Delete(models ...*model.Msg) (result gen.ResultInfo, err error) {
+	return m.DO.Delete(models)
+}
+
+func (m *msgDo) withDO(do gen.Dao) *msgDo {
+	m.DO = *do.(*gen.DO)
+	return m
+}

+ 417 - 0
database/dao/wechat/query/pay_recharge.gen.go

@@ -0,0 +1,417 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newPayRecharge(db *gorm.DB, opts ...gen.DOOption) payRecharge {
+	_payRecharge := payRecharge{}
+
+	_payRecharge.payRechargeDo.UseDB(db, opts...)
+	_payRecharge.payRechargeDo.UseModel(&model.PayRecharge{})
+
+	tableName := _payRecharge.payRechargeDo.TableName()
+	_payRecharge.ALL = field.NewAsterisk(tableName)
+	_payRecharge.ID = field.NewInt64(tableName, "id")
+	_payRecharge.CreatedAt = field.NewTime(tableName, "created_at")
+	_payRecharge.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_payRecharge.Status = field.NewInt64(tableName, "status")
+	_payRecharge.DeletedAt = field.NewField(tableName, "deleted_at")
+	_payRecharge.UserID = field.NewString(tableName, "user_id")
+	_payRecharge.Number = field.NewField(tableName, "number")
+	_payRecharge.Money = field.NewField(tableName, "money")
+	_payRecharge.OutTradeNo = field.NewString(tableName, "out_trade_no")
+	_payRecharge.OrganizationID = field.NewInt64(tableName, "organization_id")
+
+	_payRecharge.fillFieldMap()
+
+	return _payRecharge
+}
+
+// payRecharge 充值表
+type payRecharge struct {
+	payRechargeDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	Status         field.Int64  // 状态 1 正常 2 禁用
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	UserID         field.String // 用户ID
+	Number         field.Field  // 变化积分数
+	Money          field.Field  // 充值钱数
+	OutTradeNo     field.String // 外部订单号
+	OrganizationID field.Int64  // 机构 ID
+
+	fieldMap map[string]field.Expr
+}
+
+func (p payRecharge) Table(newTableName string) *payRecharge {
+	p.payRechargeDo.UseTable(newTableName)
+	return p.updateTableName(newTableName)
+}
+
+func (p payRecharge) As(alias string) *payRecharge {
+	p.payRechargeDo.DO = *(p.payRechargeDo.As(alias).(*gen.DO))
+	return p.updateTableName(alias)
+}
+
+func (p *payRecharge) updateTableName(table string) *payRecharge {
+	p.ALL = field.NewAsterisk(table)
+	p.ID = field.NewInt64(table, "id")
+	p.CreatedAt = field.NewTime(table, "created_at")
+	p.UpdatedAt = field.NewTime(table, "updated_at")
+	p.Status = field.NewInt64(table, "status")
+	p.DeletedAt = field.NewField(table, "deleted_at")
+	p.UserID = field.NewString(table, "user_id")
+	p.Number = field.NewField(table, "number")
+	p.Money = field.NewField(table, "money")
+	p.OutTradeNo = field.NewString(table, "out_trade_no")
+	p.OrganizationID = field.NewInt64(table, "organization_id")
+
+	p.fillFieldMap()
+
+	return p
+}
+
+func (p *payRecharge) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := p.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (p *payRecharge) fillFieldMap() {
+	p.fieldMap = make(map[string]field.Expr, 10)
+	p.fieldMap["id"] = p.ID
+	p.fieldMap["created_at"] = p.CreatedAt
+	p.fieldMap["updated_at"] = p.UpdatedAt
+	p.fieldMap["status"] = p.Status
+	p.fieldMap["deleted_at"] = p.DeletedAt
+	p.fieldMap["user_id"] = p.UserID
+	p.fieldMap["number"] = p.Number
+	p.fieldMap["money"] = p.Money
+	p.fieldMap["out_trade_no"] = p.OutTradeNo
+	p.fieldMap["organization_id"] = p.OrganizationID
+}
+
+func (p payRecharge) clone(db *gorm.DB) payRecharge {
+	p.payRechargeDo.ReplaceConnPool(db.Statement.ConnPool)
+	return p
+}
+
+func (p payRecharge) replaceDB(db *gorm.DB) payRecharge {
+	p.payRechargeDo.ReplaceDB(db)
+	return p
+}
+
+type payRechargeDo struct{ gen.DO }
+
+type IPayRechargeDo interface {
+	gen.SubQuery
+	Debug() IPayRechargeDo
+	WithContext(ctx context.Context) IPayRechargeDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IPayRechargeDo
+	WriteDB() IPayRechargeDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IPayRechargeDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IPayRechargeDo
+	Not(conds ...gen.Condition) IPayRechargeDo
+	Or(conds ...gen.Condition) IPayRechargeDo
+	Select(conds ...field.Expr) IPayRechargeDo
+	Where(conds ...gen.Condition) IPayRechargeDo
+	Order(conds ...field.Expr) IPayRechargeDo
+	Distinct(cols ...field.Expr) IPayRechargeDo
+	Omit(cols ...field.Expr) IPayRechargeDo
+	Join(table schema.Tabler, on ...field.Expr) IPayRechargeDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IPayRechargeDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IPayRechargeDo
+	Group(cols ...field.Expr) IPayRechargeDo
+	Having(conds ...gen.Condition) IPayRechargeDo
+	Limit(limit int) IPayRechargeDo
+	Offset(offset int) IPayRechargeDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IPayRechargeDo
+	Unscoped() IPayRechargeDo
+	Create(values ...*model.PayRecharge) error
+	CreateInBatches(values []*model.PayRecharge, batchSize int) error
+	Save(values ...*model.PayRecharge) error
+	First() (*model.PayRecharge, error)
+	Take() (*model.PayRecharge, error)
+	Last() (*model.PayRecharge, error)
+	Find() ([]*model.PayRecharge, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.PayRecharge, err error)
+	FindInBatches(result *[]*model.PayRecharge, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.PayRecharge) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IPayRechargeDo
+	Assign(attrs ...field.AssignExpr) IPayRechargeDo
+	Joins(fields ...field.RelationField) IPayRechargeDo
+	Preload(fields ...field.RelationField) IPayRechargeDo
+	FirstOrInit() (*model.PayRecharge, error)
+	FirstOrCreate() (*model.PayRecharge, error)
+	FindByPage(offset int, limit int) (result []*model.PayRecharge, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IPayRechargeDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (p payRechargeDo) Debug() IPayRechargeDo {
+	return p.withDO(p.DO.Debug())
+}
+
+func (p payRechargeDo) WithContext(ctx context.Context) IPayRechargeDo {
+	return p.withDO(p.DO.WithContext(ctx))
+}
+
+func (p payRechargeDo) ReadDB() IPayRechargeDo {
+	return p.Clauses(dbresolver.Read)
+}
+
+func (p payRechargeDo) WriteDB() IPayRechargeDo {
+	return p.Clauses(dbresolver.Write)
+}
+
+func (p payRechargeDo) Session(config *gorm.Session) IPayRechargeDo {
+	return p.withDO(p.DO.Session(config))
+}
+
+func (p payRechargeDo) Clauses(conds ...clause.Expression) IPayRechargeDo {
+	return p.withDO(p.DO.Clauses(conds...))
+}
+
+func (p payRechargeDo) Returning(value interface{}, columns ...string) IPayRechargeDo {
+	return p.withDO(p.DO.Returning(value, columns...))
+}
+
+func (p payRechargeDo) Not(conds ...gen.Condition) IPayRechargeDo {
+	return p.withDO(p.DO.Not(conds...))
+}
+
+func (p payRechargeDo) Or(conds ...gen.Condition) IPayRechargeDo {
+	return p.withDO(p.DO.Or(conds...))
+}
+
+func (p payRechargeDo) Select(conds ...field.Expr) IPayRechargeDo {
+	return p.withDO(p.DO.Select(conds...))
+}
+
+func (p payRechargeDo) Where(conds ...gen.Condition) IPayRechargeDo {
+	return p.withDO(p.DO.Where(conds...))
+}
+
+func (p payRechargeDo) Order(conds ...field.Expr) IPayRechargeDo {
+	return p.withDO(p.DO.Order(conds...))
+}
+
+func (p payRechargeDo) Distinct(cols ...field.Expr) IPayRechargeDo {
+	return p.withDO(p.DO.Distinct(cols...))
+}
+
+func (p payRechargeDo) Omit(cols ...field.Expr) IPayRechargeDo {
+	return p.withDO(p.DO.Omit(cols...))
+}
+
+func (p payRechargeDo) Join(table schema.Tabler, on ...field.Expr) IPayRechargeDo {
+	return p.withDO(p.DO.Join(table, on...))
+}
+
+func (p payRechargeDo) LeftJoin(table schema.Tabler, on ...field.Expr) IPayRechargeDo {
+	return p.withDO(p.DO.LeftJoin(table, on...))
+}
+
+func (p payRechargeDo) RightJoin(table schema.Tabler, on ...field.Expr) IPayRechargeDo {
+	return p.withDO(p.DO.RightJoin(table, on...))
+}
+
+func (p payRechargeDo) Group(cols ...field.Expr) IPayRechargeDo {
+	return p.withDO(p.DO.Group(cols...))
+}
+
+func (p payRechargeDo) Having(conds ...gen.Condition) IPayRechargeDo {
+	return p.withDO(p.DO.Having(conds...))
+}
+
+func (p payRechargeDo) Limit(limit int) IPayRechargeDo {
+	return p.withDO(p.DO.Limit(limit))
+}
+
+func (p payRechargeDo) Offset(offset int) IPayRechargeDo {
+	return p.withDO(p.DO.Offset(offset))
+}
+
+func (p payRechargeDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IPayRechargeDo {
+	return p.withDO(p.DO.Scopes(funcs...))
+}
+
+func (p payRechargeDo) Unscoped() IPayRechargeDo {
+	return p.withDO(p.DO.Unscoped())
+}
+
+func (p payRechargeDo) Create(values ...*model.PayRecharge) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return p.DO.Create(values)
+}
+
+func (p payRechargeDo) CreateInBatches(values []*model.PayRecharge, batchSize int) error {
+	return p.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (p payRechargeDo) Save(values ...*model.PayRecharge) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return p.DO.Save(values)
+}
+
+func (p payRechargeDo) First() (*model.PayRecharge, error) {
+	if result, err := p.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.PayRecharge), nil
+	}
+}
+
+func (p payRechargeDo) Take() (*model.PayRecharge, error) {
+	if result, err := p.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.PayRecharge), nil
+	}
+}
+
+func (p payRechargeDo) Last() (*model.PayRecharge, error) {
+	if result, err := p.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.PayRecharge), nil
+	}
+}
+
+func (p payRechargeDo) Find() ([]*model.PayRecharge, error) {
+	result, err := p.DO.Find()
+	return result.([]*model.PayRecharge), err
+}
+
+func (p payRechargeDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.PayRecharge, err error) {
+	buf := make([]*model.PayRecharge, 0, batchSize)
+	err = p.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (p payRechargeDo) FindInBatches(result *[]*model.PayRecharge, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return p.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (p payRechargeDo) Attrs(attrs ...field.AssignExpr) IPayRechargeDo {
+	return p.withDO(p.DO.Attrs(attrs...))
+}
+
+func (p payRechargeDo) Assign(attrs ...field.AssignExpr) IPayRechargeDo {
+	return p.withDO(p.DO.Assign(attrs...))
+}
+
+func (p payRechargeDo) Joins(fields ...field.RelationField) IPayRechargeDo {
+	for _, _f := range fields {
+		p = *p.withDO(p.DO.Joins(_f))
+	}
+	return &p
+}
+
+func (p payRechargeDo) Preload(fields ...field.RelationField) IPayRechargeDo {
+	for _, _f := range fields {
+		p = *p.withDO(p.DO.Preload(_f))
+	}
+	return &p
+}
+
+func (p payRechargeDo) FirstOrInit() (*model.PayRecharge, error) {
+	if result, err := p.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.PayRecharge), nil
+	}
+}
+
+func (p payRechargeDo) FirstOrCreate() (*model.PayRecharge, error) {
+	if result, err := p.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.PayRecharge), nil
+	}
+}
+
+func (p payRechargeDo) FindByPage(offset int, limit int) (result []*model.PayRecharge, count int64, err error) {
+	result, err = p.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = p.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (p payRechargeDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = p.Count()
+	if err != nil {
+		return
+	}
+
+	err = p.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (p payRechargeDo) Scan(result interface{}) (err error) {
+	return p.DO.Scan(result)
+}
+
+func (p payRechargeDo) Delete(models ...*model.PayRecharge) (result gen.ResultInfo, err error) {
+	return p.DO.Delete(models)
+}
+
+func (p *payRechargeDo) withDO(do gen.Dao) *payRechargeDo {
+	p.DO = *do.(*gen.DO)
+	return p
+}

+ 436 - 0
database/dao/wechat/query/records.gen.go

@@ -0,0 +1,436 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newRecord(db *gorm.DB, opts ...gen.DOOption) record {
+	_record := record{}
+
+	_record.recordDo.UseDB(db, opts...)
+	_record.recordDo.UseModel(&model.Record{})
+
+	tableName := _record.recordDo.TableName()
+	_record.ALL = field.NewAsterisk(tableName)
+	_record.ID = field.NewInt64(tableName, "id")
+	_record.CreatedAt = field.NewTime(tableName, "created_at")
+	_record.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_record.Body = field.NewString(tableName, "body")
+	_record.StaffNo = field.NewString(tableName, "staff_no")
+	_record.Caller = field.NewString(tableName, "caller")
+	_record.Callee = field.NewString(tableName, "callee")
+	_record.RecordFile = field.NewString(tableName, "record_file")
+	_record.Session = field.NewString(tableName, "session")
+	_record.AliTrans = field.NewString(tableName, "ali_trans")
+	_record.AliTaskID = field.NewString(tableName, "ali_task_id")
+	_record.Chats = field.NewString(tableName, "chats")
+	_record.UserIntent = field.NewString(tableName, "user_intent")
+	_record.Basis = field.NewString(tableName, "basis")
+	_record.Accept = field.NewInt64(tableName, "accept")
+
+	_record.fillFieldMap()
+
+	return _record
+}
+
+type record struct {
+	recordDo
+
+	ALL        field.Asterisk
+	ID         field.Int64
+	CreatedAt  field.Time   // Create Time | 创建日期
+	UpdatedAt  field.Time   // Update Time | 修改日期
+	Body       field.String // 获取原始数据
+	StaffNo    field.String // 坐席工号
+	Caller     field.String // 主叫号码
+	Callee     field.String // 被叫号码
+	RecordFile field.String // 录音文件
+	Session    field.String // 通话标识
+	AliTrans   field.String // 阿里语音识别原始结果
+	AliTaskID  field.String // 阿里语音识别任务ID
+	Chats      field.String // 提取的对话记录
+	UserIntent field.String // 判断的用户意图
+	Basis      field.String // 用户意图命中的原始文本
+	Accept     field.Int64  // 用户是否接受邀请 0 未判断  1 接受 2 不接受
+
+	fieldMap map[string]field.Expr
+}
+
+func (r record) Table(newTableName string) *record {
+	r.recordDo.UseTable(newTableName)
+	return r.updateTableName(newTableName)
+}
+
+func (r record) As(alias string) *record {
+	r.recordDo.DO = *(r.recordDo.As(alias).(*gen.DO))
+	return r.updateTableName(alias)
+}
+
+func (r *record) updateTableName(table string) *record {
+	r.ALL = field.NewAsterisk(table)
+	r.ID = field.NewInt64(table, "id")
+	r.CreatedAt = field.NewTime(table, "created_at")
+	r.UpdatedAt = field.NewTime(table, "updated_at")
+	r.Body = field.NewString(table, "body")
+	r.StaffNo = field.NewString(table, "staff_no")
+	r.Caller = field.NewString(table, "caller")
+	r.Callee = field.NewString(table, "callee")
+	r.RecordFile = field.NewString(table, "record_file")
+	r.Session = field.NewString(table, "session")
+	r.AliTrans = field.NewString(table, "ali_trans")
+	r.AliTaskID = field.NewString(table, "ali_task_id")
+	r.Chats = field.NewString(table, "chats")
+	r.UserIntent = field.NewString(table, "user_intent")
+	r.Basis = field.NewString(table, "basis")
+	r.Accept = field.NewInt64(table, "accept")
+
+	r.fillFieldMap()
+
+	return r
+}
+
+func (r *record) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := r.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (r *record) fillFieldMap() {
+	r.fieldMap = make(map[string]field.Expr, 15)
+	r.fieldMap["id"] = r.ID
+	r.fieldMap["created_at"] = r.CreatedAt
+	r.fieldMap["updated_at"] = r.UpdatedAt
+	r.fieldMap["body"] = r.Body
+	r.fieldMap["staff_no"] = r.StaffNo
+	r.fieldMap["caller"] = r.Caller
+	r.fieldMap["callee"] = r.Callee
+	r.fieldMap["record_file"] = r.RecordFile
+	r.fieldMap["session"] = r.Session
+	r.fieldMap["ali_trans"] = r.AliTrans
+	r.fieldMap["ali_task_id"] = r.AliTaskID
+	r.fieldMap["chats"] = r.Chats
+	r.fieldMap["user_intent"] = r.UserIntent
+	r.fieldMap["basis"] = r.Basis
+	r.fieldMap["accept"] = r.Accept
+}
+
+func (r record) clone(db *gorm.DB) record {
+	r.recordDo.ReplaceConnPool(db.Statement.ConnPool)
+	return r
+}
+
+func (r record) replaceDB(db *gorm.DB) record {
+	r.recordDo.ReplaceDB(db)
+	return r
+}
+
+type recordDo struct{ gen.DO }
+
+type IRecordDo interface {
+	gen.SubQuery
+	Debug() IRecordDo
+	WithContext(ctx context.Context) IRecordDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IRecordDo
+	WriteDB() IRecordDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IRecordDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IRecordDo
+	Not(conds ...gen.Condition) IRecordDo
+	Or(conds ...gen.Condition) IRecordDo
+	Select(conds ...field.Expr) IRecordDo
+	Where(conds ...gen.Condition) IRecordDo
+	Order(conds ...field.Expr) IRecordDo
+	Distinct(cols ...field.Expr) IRecordDo
+	Omit(cols ...field.Expr) IRecordDo
+	Join(table schema.Tabler, on ...field.Expr) IRecordDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IRecordDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IRecordDo
+	Group(cols ...field.Expr) IRecordDo
+	Having(conds ...gen.Condition) IRecordDo
+	Limit(limit int) IRecordDo
+	Offset(offset int) IRecordDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IRecordDo
+	Unscoped() IRecordDo
+	Create(values ...*model.Record) error
+	CreateInBatches(values []*model.Record, batchSize int) error
+	Save(values ...*model.Record) error
+	First() (*model.Record, error)
+	Take() (*model.Record, error)
+	Last() (*model.Record, error)
+	Find() ([]*model.Record, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Record, err error)
+	FindInBatches(result *[]*model.Record, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.Record) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IRecordDo
+	Assign(attrs ...field.AssignExpr) IRecordDo
+	Joins(fields ...field.RelationField) IRecordDo
+	Preload(fields ...field.RelationField) IRecordDo
+	FirstOrInit() (*model.Record, error)
+	FirstOrCreate() (*model.Record, error)
+	FindByPage(offset int, limit int) (result []*model.Record, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IRecordDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (r recordDo) Debug() IRecordDo {
+	return r.withDO(r.DO.Debug())
+}
+
+func (r recordDo) WithContext(ctx context.Context) IRecordDo {
+	return r.withDO(r.DO.WithContext(ctx))
+}
+
+func (r recordDo) ReadDB() IRecordDo {
+	return r.Clauses(dbresolver.Read)
+}
+
+func (r recordDo) WriteDB() IRecordDo {
+	return r.Clauses(dbresolver.Write)
+}
+
+func (r recordDo) Session(config *gorm.Session) IRecordDo {
+	return r.withDO(r.DO.Session(config))
+}
+
+func (r recordDo) Clauses(conds ...clause.Expression) IRecordDo {
+	return r.withDO(r.DO.Clauses(conds...))
+}
+
+func (r recordDo) Returning(value interface{}, columns ...string) IRecordDo {
+	return r.withDO(r.DO.Returning(value, columns...))
+}
+
+func (r recordDo) Not(conds ...gen.Condition) IRecordDo {
+	return r.withDO(r.DO.Not(conds...))
+}
+
+func (r recordDo) Or(conds ...gen.Condition) IRecordDo {
+	return r.withDO(r.DO.Or(conds...))
+}
+
+func (r recordDo) Select(conds ...field.Expr) IRecordDo {
+	return r.withDO(r.DO.Select(conds...))
+}
+
+func (r recordDo) Where(conds ...gen.Condition) IRecordDo {
+	return r.withDO(r.DO.Where(conds...))
+}
+
+func (r recordDo) Order(conds ...field.Expr) IRecordDo {
+	return r.withDO(r.DO.Order(conds...))
+}
+
+func (r recordDo) Distinct(cols ...field.Expr) IRecordDo {
+	return r.withDO(r.DO.Distinct(cols...))
+}
+
+func (r recordDo) Omit(cols ...field.Expr) IRecordDo {
+	return r.withDO(r.DO.Omit(cols...))
+}
+
+func (r recordDo) Join(table schema.Tabler, on ...field.Expr) IRecordDo {
+	return r.withDO(r.DO.Join(table, on...))
+}
+
+func (r recordDo) LeftJoin(table schema.Tabler, on ...field.Expr) IRecordDo {
+	return r.withDO(r.DO.LeftJoin(table, on...))
+}
+
+func (r recordDo) RightJoin(table schema.Tabler, on ...field.Expr) IRecordDo {
+	return r.withDO(r.DO.RightJoin(table, on...))
+}
+
+func (r recordDo) Group(cols ...field.Expr) IRecordDo {
+	return r.withDO(r.DO.Group(cols...))
+}
+
+func (r recordDo) Having(conds ...gen.Condition) IRecordDo {
+	return r.withDO(r.DO.Having(conds...))
+}
+
+func (r recordDo) Limit(limit int) IRecordDo {
+	return r.withDO(r.DO.Limit(limit))
+}
+
+func (r recordDo) Offset(offset int) IRecordDo {
+	return r.withDO(r.DO.Offset(offset))
+}
+
+func (r recordDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IRecordDo {
+	return r.withDO(r.DO.Scopes(funcs...))
+}
+
+func (r recordDo) Unscoped() IRecordDo {
+	return r.withDO(r.DO.Unscoped())
+}
+
+func (r recordDo) Create(values ...*model.Record) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return r.DO.Create(values)
+}
+
+func (r recordDo) CreateInBatches(values []*model.Record, batchSize int) error {
+	return r.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (r recordDo) Save(values ...*model.Record) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return r.DO.Save(values)
+}
+
+func (r recordDo) First() (*model.Record, error) {
+	if result, err := r.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Record), nil
+	}
+}
+
+func (r recordDo) Take() (*model.Record, error) {
+	if result, err := r.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Record), nil
+	}
+}
+
+func (r recordDo) Last() (*model.Record, error) {
+	if result, err := r.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Record), nil
+	}
+}
+
+func (r recordDo) Find() ([]*model.Record, error) {
+	result, err := r.DO.Find()
+	return result.([]*model.Record), err
+}
+
+func (r recordDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Record, err error) {
+	buf := make([]*model.Record, 0, batchSize)
+	err = r.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (r recordDo) FindInBatches(result *[]*model.Record, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return r.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (r recordDo) Attrs(attrs ...field.AssignExpr) IRecordDo {
+	return r.withDO(r.DO.Attrs(attrs...))
+}
+
+func (r recordDo) Assign(attrs ...field.AssignExpr) IRecordDo {
+	return r.withDO(r.DO.Assign(attrs...))
+}
+
+func (r recordDo) Joins(fields ...field.RelationField) IRecordDo {
+	for _, _f := range fields {
+		r = *r.withDO(r.DO.Joins(_f))
+	}
+	return &r
+}
+
+func (r recordDo) Preload(fields ...field.RelationField) IRecordDo {
+	for _, _f := range fields {
+		r = *r.withDO(r.DO.Preload(_f))
+	}
+	return &r
+}
+
+func (r recordDo) FirstOrInit() (*model.Record, error) {
+	if result, err := r.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Record), nil
+	}
+}
+
+func (r recordDo) FirstOrCreate() (*model.Record, error) {
+	if result, err := r.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Record), nil
+	}
+}
+
+func (r recordDo) FindByPage(offset int, limit int) (result []*model.Record, count int64, err error) {
+	result, err = r.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = r.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (r recordDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = r.Count()
+	if err != nil {
+		return
+	}
+
+	err = r.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (r recordDo) Scan(result interface{}) (err error) {
+	return r.DO.Scan(result)
+}
+
+func (r recordDo) Delete(models ...*model.Record) (result gen.ResultInfo, err error) {
+	return r.DO.Delete(models)
+}
+
+func (r *recordDo) withDO(do gen.Dao) *recordDo {
+	r.DO = *do.(*gen.DO)
+	return r
+}

+ 412 - 0
database/dao/wechat/query/server.gen.go

@@ -0,0 +1,412 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newServer(db *gorm.DB, opts ...gen.DOOption) server {
+	_server := server{}
+
+	_server.serverDo.UseDB(db, opts...)
+	_server.serverDo.UseModel(&model.Server{})
+
+	tableName := _server.serverDo.TableName()
+	_server.ALL = field.NewAsterisk(tableName)
+	_server.ID = field.NewInt64(tableName, "id")
+	_server.CreatedAt = field.NewTime(tableName, "created_at")
+	_server.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_server.Status = field.NewInt64(tableName, "status")
+	_server.DeletedAt = field.NewField(tableName, "deleted_at")
+	_server.Name = field.NewString(tableName, "name")
+	_server.PublicIP = field.NewString(tableName, "public_ip")
+	_server.PrivateIP = field.NewString(tableName, "private_ip")
+	_server.AdminPort = field.NewString(tableName, "admin_port")
+
+	_server.fillFieldMap()
+
+	return _server
+}
+
+type server struct {
+	serverDo
+
+	ALL       field.Asterisk
+	ID        field.Int64
+	CreatedAt field.Time   // Create Time | 创建日期
+	UpdatedAt field.Time   // Update Time | 修改日期
+	Status    field.Int64  // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt field.Field  // Delete Time | 删除日期
+	Name      field.String // 名称
+	PublicIP  field.String // 公网ip
+	PrivateIP field.String // 内网ip
+	AdminPort field.String // 管理端口
+
+	fieldMap map[string]field.Expr
+}
+
+func (s server) Table(newTableName string) *server {
+	s.serverDo.UseTable(newTableName)
+	return s.updateTableName(newTableName)
+}
+
+func (s server) As(alias string) *server {
+	s.serverDo.DO = *(s.serverDo.As(alias).(*gen.DO))
+	return s.updateTableName(alias)
+}
+
+func (s *server) updateTableName(table string) *server {
+	s.ALL = field.NewAsterisk(table)
+	s.ID = field.NewInt64(table, "id")
+	s.CreatedAt = field.NewTime(table, "created_at")
+	s.UpdatedAt = field.NewTime(table, "updated_at")
+	s.Status = field.NewInt64(table, "status")
+	s.DeletedAt = field.NewField(table, "deleted_at")
+	s.Name = field.NewString(table, "name")
+	s.PublicIP = field.NewString(table, "public_ip")
+	s.PrivateIP = field.NewString(table, "private_ip")
+	s.AdminPort = field.NewString(table, "admin_port")
+
+	s.fillFieldMap()
+
+	return s
+}
+
+func (s *server) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := s.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (s *server) fillFieldMap() {
+	s.fieldMap = make(map[string]field.Expr, 9)
+	s.fieldMap["id"] = s.ID
+	s.fieldMap["created_at"] = s.CreatedAt
+	s.fieldMap["updated_at"] = s.UpdatedAt
+	s.fieldMap["status"] = s.Status
+	s.fieldMap["deleted_at"] = s.DeletedAt
+	s.fieldMap["name"] = s.Name
+	s.fieldMap["public_ip"] = s.PublicIP
+	s.fieldMap["private_ip"] = s.PrivateIP
+	s.fieldMap["admin_port"] = s.AdminPort
+}
+
+func (s server) clone(db *gorm.DB) server {
+	s.serverDo.ReplaceConnPool(db.Statement.ConnPool)
+	return s
+}
+
+func (s server) replaceDB(db *gorm.DB) server {
+	s.serverDo.ReplaceDB(db)
+	return s
+}
+
+type serverDo struct{ gen.DO }
+
+type IServerDo interface {
+	gen.SubQuery
+	Debug() IServerDo
+	WithContext(ctx context.Context) IServerDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IServerDo
+	WriteDB() IServerDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IServerDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IServerDo
+	Not(conds ...gen.Condition) IServerDo
+	Or(conds ...gen.Condition) IServerDo
+	Select(conds ...field.Expr) IServerDo
+	Where(conds ...gen.Condition) IServerDo
+	Order(conds ...field.Expr) IServerDo
+	Distinct(cols ...field.Expr) IServerDo
+	Omit(cols ...field.Expr) IServerDo
+	Join(table schema.Tabler, on ...field.Expr) IServerDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IServerDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IServerDo
+	Group(cols ...field.Expr) IServerDo
+	Having(conds ...gen.Condition) IServerDo
+	Limit(limit int) IServerDo
+	Offset(offset int) IServerDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IServerDo
+	Unscoped() IServerDo
+	Create(values ...*model.Server) error
+	CreateInBatches(values []*model.Server, batchSize int) error
+	Save(values ...*model.Server) error
+	First() (*model.Server, error)
+	Take() (*model.Server, error)
+	Last() (*model.Server, error)
+	Find() ([]*model.Server, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Server, err error)
+	FindInBatches(result *[]*model.Server, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.Server) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IServerDo
+	Assign(attrs ...field.AssignExpr) IServerDo
+	Joins(fields ...field.RelationField) IServerDo
+	Preload(fields ...field.RelationField) IServerDo
+	FirstOrInit() (*model.Server, error)
+	FirstOrCreate() (*model.Server, error)
+	FindByPage(offset int, limit int) (result []*model.Server, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IServerDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (s serverDo) Debug() IServerDo {
+	return s.withDO(s.DO.Debug())
+}
+
+func (s serverDo) WithContext(ctx context.Context) IServerDo {
+	return s.withDO(s.DO.WithContext(ctx))
+}
+
+func (s serverDo) ReadDB() IServerDo {
+	return s.Clauses(dbresolver.Read)
+}
+
+func (s serverDo) WriteDB() IServerDo {
+	return s.Clauses(dbresolver.Write)
+}
+
+func (s serverDo) Session(config *gorm.Session) IServerDo {
+	return s.withDO(s.DO.Session(config))
+}
+
+func (s serverDo) Clauses(conds ...clause.Expression) IServerDo {
+	return s.withDO(s.DO.Clauses(conds...))
+}
+
+func (s serverDo) Returning(value interface{}, columns ...string) IServerDo {
+	return s.withDO(s.DO.Returning(value, columns...))
+}
+
+func (s serverDo) Not(conds ...gen.Condition) IServerDo {
+	return s.withDO(s.DO.Not(conds...))
+}
+
+func (s serverDo) Or(conds ...gen.Condition) IServerDo {
+	return s.withDO(s.DO.Or(conds...))
+}
+
+func (s serverDo) Select(conds ...field.Expr) IServerDo {
+	return s.withDO(s.DO.Select(conds...))
+}
+
+func (s serverDo) Where(conds ...gen.Condition) IServerDo {
+	return s.withDO(s.DO.Where(conds...))
+}
+
+func (s serverDo) Order(conds ...field.Expr) IServerDo {
+	return s.withDO(s.DO.Order(conds...))
+}
+
+func (s serverDo) Distinct(cols ...field.Expr) IServerDo {
+	return s.withDO(s.DO.Distinct(cols...))
+}
+
+func (s serverDo) Omit(cols ...field.Expr) IServerDo {
+	return s.withDO(s.DO.Omit(cols...))
+}
+
+func (s serverDo) Join(table schema.Tabler, on ...field.Expr) IServerDo {
+	return s.withDO(s.DO.Join(table, on...))
+}
+
+func (s serverDo) LeftJoin(table schema.Tabler, on ...field.Expr) IServerDo {
+	return s.withDO(s.DO.LeftJoin(table, on...))
+}
+
+func (s serverDo) RightJoin(table schema.Tabler, on ...field.Expr) IServerDo {
+	return s.withDO(s.DO.RightJoin(table, on...))
+}
+
+func (s serverDo) Group(cols ...field.Expr) IServerDo {
+	return s.withDO(s.DO.Group(cols...))
+}
+
+func (s serverDo) Having(conds ...gen.Condition) IServerDo {
+	return s.withDO(s.DO.Having(conds...))
+}
+
+func (s serverDo) Limit(limit int) IServerDo {
+	return s.withDO(s.DO.Limit(limit))
+}
+
+func (s serverDo) Offset(offset int) IServerDo {
+	return s.withDO(s.DO.Offset(offset))
+}
+
+func (s serverDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IServerDo {
+	return s.withDO(s.DO.Scopes(funcs...))
+}
+
+func (s serverDo) Unscoped() IServerDo {
+	return s.withDO(s.DO.Unscoped())
+}
+
+func (s serverDo) Create(values ...*model.Server) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return s.DO.Create(values)
+}
+
+func (s serverDo) CreateInBatches(values []*model.Server, batchSize int) error {
+	return s.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (s serverDo) Save(values ...*model.Server) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return s.DO.Save(values)
+}
+
+func (s serverDo) First() (*model.Server, error) {
+	if result, err := s.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Server), nil
+	}
+}
+
+func (s serverDo) Take() (*model.Server, error) {
+	if result, err := s.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Server), nil
+	}
+}
+
+func (s serverDo) Last() (*model.Server, error) {
+	if result, err := s.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Server), nil
+	}
+}
+
+func (s serverDo) Find() ([]*model.Server, error) {
+	result, err := s.DO.Find()
+	return result.([]*model.Server), err
+}
+
+func (s serverDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Server, err error) {
+	buf := make([]*model.Server, 0, batchSize)
+	err = s.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (s serverDo) FindInBatches(result *[]*model.Server, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return s.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (s serverDo) Attrs(attrs ...field.AssignExpr) IServerDo {
+	return s.withDO(s.DO.Attrs(attrs...))
+}
+
+func (s serverDo) Assign(attrs ...field.AssignExpr) IServerDo {
+	return s.withDO(s.DO.Assign(attrs...))
+}
+
+func (s serverDo) Joins(fields ...field.RelationField) IServerDo {
+	for _, _f := range fields {
+		s = *s.withDO(s.DO.Joins(_f))
+	}
+	return &s
+}
+
+func (s serverDo) Preload(fields ...field.RelationField) IServerDo {
+	for _, _f := range fields {
+		s = *s.withDO(s.DO.Preload(_f))
+	}
+	return &s
+}
+
+func (s serverDo) FirstOrInit() (*model.Server, error) {
+	if result, err := s.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Server), nil
+	}
+}
+
+func (s serverDo) FirstOrCreate() (*model.Server, error) {
+	if result, err := s.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Server), nil
+	}
+}
+
+func (s serverDo) FindByPage(offset int, limit int) (result []*model.Server, count int64, err error) {
+	result, err = s.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = s.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (s serverDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = s.Count()
+	if err != nil {
+		return
+	}
+
+	err = s.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (s serverDo) Scan(result interface{}) (err error) {
+	return s.DO.Scan(result)
+}
+
+func (s serverDo) Delete(models ...*model.Server) (result gen.ResultInfo, err error) {
+	return s.DO.Delete(models)
+}
+
+func (s *serverDo) withDO(do gen.Dao) *serverDo {
+	s.DO = *do.(*gen.DO)
+	return s
+}

+ 440 - 0
database/dao/wechat/query/sop_node.gen.go

@@ -0,0 +1,440 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newSopNode(db *gorm.DB, opts ...gen.DOOption) sopNode {
+	_sopNode := sopNode{}
+
+	_sopNode.sopNodeDo.UseDB(db, opts...)
+	_sopNode.sopNodeDo.UseModel(&model.SopNode{})
+
+	tableName := _sopNode.sopNodeDo.TableName()
+	_sopNode.ALL = field.NewAsterisk(tableName)
+	_sopNode.ID = field.NewInt64(tableName, "id")
+	_sopNode.CreatedAt = field.NewTime(tableName, "created_at")
+	_sopNode.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_sopNode.Status = field.NewInt64(tableName, "status")
+	_sopNode.DeletedAt = field.NewField(tableName, "deleted_at")
+	_sopNode.StageID = field.NewInt64(tableName, "stage_id")
+	_sopNode.ParentID = field.NewInt64(tableName, "parent_id")
+	_sopNode.Name = field.NewString(tableName, "name")
+	_sopNode.ConditionType = field.NewInt64(tableName, "condition_type")
+	_sopNode.ConditionList = field.NewString(tableName, "condition_list")
+	_sopNode.NoReplyCondition = field.NewInt64(tableName, "no_reply_condition")
+	_sopNode.ActionMessage = field.NewString(tableName, "action_message")
+	_sopNode.ActionLabelAdd = field.NewString(tableName, "action_label_add")
+	_sopNode.ActionForward = field.NewString(tableName, "action_forward")
+	_sopNode.NoReplyUnit = field.NewString(tableName, "no_reply_unit")
+	_sopNode.ActionLabelDel = field.NewString(tableName, "action_label_del")
+
+	_sopNode.fillFieldMap()
+
+	return _sopNode
+}
+
+type sopNode struct {
+	sopNodeDo
+
+	ALL              field.Asterisk
+	ID               field.Int64
+	CreatedAt        field.Time   // Create Time | 创建日期
+	UpdatedAt        field.Time   // Update Time | 修改日期
+	Status           field.Int64  // 状态 1 正常 2 禁用
+	DeletedAt        field.Field  // Delete Time | 删除日期
+	StageID          field.Int64  // 阶段 ID
+	ParentID         field.Int64  // 父节点 ID
+	Name             field.String // 节点名称
+	ConditionType    field.Int64  // 触发条件类型 1 客户回复后触发 2 超时后触发
+	ConditionList    field.String // 触发语义列表 当为空时则代表用户回复任意内容后触发
+	NoReplyCondition field.Int64  // 超时触发时间(分钟)
+	ActionMessage    field.String // 命中后发送的消息内容
+	ActionLabelAdd   field.String // 命中后需要打的标签
+	ActionForward    field.String // 命中后转发的消息
+	NoReplyUnit      field.String // 超时触发时间单位
+	ActionLabelDel   field.String // 命中后需要打的标签
+
+	fieldMap map[string]field.Expr
+}
+
+func (s sopNode) Table(newTableName string) *sopNode {
+	s.sopNodeDo.UseTable(newTableName)
+	return s.updateTableName(newTableName)
+}
+
+func (s sopNode) As(alias string) *sopNode {
+	s.sopNodeDo.DO = *(s.sopNodeDo.As(alias).(*gen.DO))
+	return s.updateTableName(alias)
+}
+
+func (s *sopNode) updateTableName(table string) *sopNode {
+	s.ALL = field.NewAsterisk(table)
+	s.ID = field.NewInt64(table, "id")
+	s.CreatedAt = field.NewTime(table, "created_at")
+	s.UpdatedAt = field.NewTime(table, "updated_at")
+	s.Status = field.NewInt64(table, "status")
+	s.DeletedAt = field.NewField(table, "deleted_at")
+	s.StageID = field.NewInt64(table, "stage_id")
+	s.ParentID = field.NewInt64(table, "parent_id")
+	s.Name = field.NewString(table, "name")
+	s.ConditionType = field.NewInt64(table, "condition_type")
+	s.ConditionList = field.NewString(table, "condition_list")
+	s.NoReplyCondition = field.NewInt64(table, "no_reply_condition")
+	s.ActionMessage = field.NewString(table, "action_message")
+	s.ActionLabelAdd = field.NewString(table, "action_label_add")
+	s.ActionForward = field.NewString(table, "action_forward")
+	s.NoReplyUnit = field.NewString(table, "no_reply_unit")
+	s.ActionLabelDel = field.NewString(table, "action_label_del")
+
+	s.fillFieldMap()
+
+	return s
+}
+
+func (s *sopNode) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := s.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (s *sopNode) fillFieldMap() {
+	s.fieldMap = make(map[string]field.Expr, 16)
+	s.fieldMap["id"] = s.ID
+	s.fieldMap["created_at"] = s.CreatedAt
+	s.fieldMap["updated_at"] = s.UpdatedAt
+	s.fieldMap["status"] = s.Status
+	s.fieldMap["deleted_at"] = s.DeletedAt
+	s.fieldMap["stage_id"] = s.StageID
+	s.fieldMap["parent_id"] = s.ParentID
+	s.fieldMap["name"] = s.Name
+	s.fieldMap["condition_type"] = s.ConditionType
+	s.fieldMap["condition_list"] = s.ConditionList
+	s.fieldMap["no_reply_condition"] = s.NoReplyCondition
+	s.fieldMap["action_message"] = s.ActionMessage
+	s.fieldMap["action_label_add"] = s.ActionLabelAdd
+	s.fieldMap["action_forward"] = s.ActionForward
+	s.fieldMap["no_reply_unit"] = s.NoReplyUnit
+	s.fieldMap["action_label_del"] = s.ActionLabelDel
+}
+
+func (s sopNode) clone(db *gorm.DB) sopNode {
+	s.sopNodeDo.ReplaceConnPool(db.Statement.ConnPool)
+	return s
+}
+
+func (s sopNode) replaceDB(db *gorm.DB) sopNode {
+	s.sopNodeDo.ReplaceDB(db)
+	return s
+}
+
+type sopNodeDo struct{ gen.DO }
+
+type ISopNodeDo interface {
+	gen.SubQuery
+	Debug() ISopNodeDo
+	WithContext(ctx context.Context) ISopNodeDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() ISopNodeDo
+	WriteDB() ISopNodeDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) ISopNodeDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) ISopNodeDo
+	Not(conds ...gen.Condition) ISopNodeDo
+	Or(conds ...gen.Condition) ISopNodeDo
+	Select(conds ...field.Expr) ISopNodeDo
+	Where(conds ...gen.Condition) ISopNodeDo
+	Order(conds ...field.Expr) ISopNodeDo
+	Distinct(cols ...field.Expr) ISopNodeDo
+	Omit(cols ...field.Expr) ISopNodeDo
+	Join(table schema.Tabler, on ...field.Expr) ISopNodeDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) ISopNodeDo
+	RightJoin(table schema.Tabler, on ...field.Expr) ISopNodeDo
+	Group(cols ...field.Expr) ISopNodeDo
+	Having(conds ...gen.Condition) ISopNodeDo
+	Limit(limit int) ISopNodeDo
+	Offset(offset int) ISopNodeDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) ISopNodeDo
+	Unscoped() ISopNodeDo
+	Create(values ...*model.SopNode) error
+	CreateInBatches(values []*model.SopNode, batchSize int) error
+	Save(values ...*model.SopNode) error
+	First() (*model.SopNode, error)
+	Take() (*model.SopNode, error)
+	Last() (*model.SopNode, error)
+	Find() ([]*model.SopNode, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.SopNode, err error)
+	FindInBatches(result *[]*model.SopNode, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.SopNode) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) ISopNodeDo
+	Assign(attrs ...field.AssignExpr) ISopNodeDo
+	Joins(fields ...field.RelationField) ISopNodeDo
+	Preload(fields ...field.RelationField) ISopNodeDo
+	FirstOrInit() (*model.SopNode, error)
+	FirstOrCreate() (*model.SopNode, error)
+	FindByPage(offset int, limit int) (result []*model.SopNode, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) ISopNodeDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (s sopNodeDo) Debug() ISopNodeDo {
+	return s.withDO(s.DO.Debug())
+}
+
+func (s sopNodeDo) WithContext(ctx context.Context) ISopNodeDo {
+	return s.withDO(s.DO.WithContext(ctx))
+}
+
+func (s sopNodeDo) ReadDB() ISopNodeDo {
+	return s.Clauses(dbresolver.Read)
+}
+
+func (s sopNodeDo) WriteDB() ISopNodeDo {
+	return s.Clauses(dbresolver.Write)
+}
+
+func (s sopNodeDo) Session(config *gorm.Session) ISopNodeDo {
+	return s.withDO(s.DO.Session(config))
+}
+
+func (s sopNodeDo) Clauses(conds ...clause.Expression) ISopNodeDo {
+	return s.withDO(s.DO.Clauses(conds...))
+}
+
+func (s sopNodeDo) Returning(value interface{}, columns ...string) ISopNodeDo {
+	return s.withDO(s.DO.Returning(value, columns...))
+}
+
+func (s sopNodeDo) Not(conds ...gen.Condition) ISopNodeDo {
+	return s.withDO(s.DO.Not(conds...))
+}
+
+func (s sopNodeDo) Or(conds ...gen.Condition) ISopNodeDo {
+	return s.withDO(s.DO.Or(conds...))
+}
+
+func (s sopNodeDo) Select(conds ...field.Expr) ISopNodeDo {
+	return s.withDO(s.DO.Select(conds...))
+}
+
+func (s sopNodeDo) Where(conds ...gen.Condition) ISopNodeDo {
+	return s.withDO(s.DO.Where(conds...))
+}
+
+func (s sopNodeDo) Order(conds ...field.Expr) ISopNodeDo {
+	return s.withDO(s.DO.Order(conds...))
+}
+
+func (s sopNodeDo) Distinct(cols ...field.Expr) ISopNodeDo {
+	return s.withDO(s.DO.Distinct(cols...))
+}
+
+func (s sopNodeDo) Omit(cols ...field.Expr) ISopNodeDo {
+	return s.withDO(s.DO.Omit(cols...))
+}
+
+func (s sopNodeDo) Join(table schema.Tabler, on ...field.Expr) ISopNodeDo {
+	return s.withDO(s.DO.Join(table, on...))
+}
+
+func (s sopNodeDo) LeftJoin(table schema.Tabler, on ...field.Expr) ISopNodeDo {
+	return s.withDO(s.DO.LeftJoin(table, on...))
+}
+
+func (s sopNodeDo) RightJoin(table schema.Tabler, on ...field.Expr) ISopNodeDo {
+	return s.withDO(s.DO.RightJoin(table, on...))
+}
+
+func (s sopNodeDo) Group(cols ...field.Expr) ISopNodeDo {
+	return s.withDO(s.DO.Group(cols...))
+}
+
+func (s sopNodeDo) Having(conds ...gen.Condition) ISopNodeDo {
+	return s.withDO(s.DO.Having(conds...))
+}
+
+func (s sopNodeDo) Limit(limit int) ISopNodeDo {
+	return s.withDO(s.DO.Limit(limit))
+}
+
+func (s sopNodeDo) Offset(offset int) ISopNodeDo {
+	return s.withDO(s.DO.Offset(offset))
+}
+
+func (s sopNodeDo) Scopes(funcs ...func(gen.Dao) gen.Dao) ISopNodeDo {
+	return s.withDO(s.DO.Scopes(funcs...))
+}
+
+func (s sopNodeDo) Unscoped() ISopNodeDo {
+	return s.withDO(s.DO.Unscoped())
+}
+
+func (s sopNodeDo) Create(values ...*model.SopNode) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return s.DO.Create(values)
+}
+
+func (s sopNodeDo) CreateInBatches(values []*model.SopNode, batchSize int) error {
+	return s.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (s sopNodeDo) Save(values ...*model.SopNode) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return s.DO.Save(values)
+}
+
+func (s sopNodeDo) First() (*model.SopNode, error) {
+	if result, err := s.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.SopNode), nil
+	}
+}
+
+func (s sopNodeDo) Take() (*model.SopNode, error) {
+	if result, err := s.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.SopNode), nil
+	}
+}
+
+func (s sopNodeDo) Last() (*model.SopNode, error) {
+	if result, err := s.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.SopNode), nil
+	}
+}
+
+func (s sopNodeDo) Find() ([]*model.SopNode, error) {
+	result, err := s.DO.Find()
+	return result.([]*model.SopNode), err
+}
+
+func (s sopNodeDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.SopNode, err error) {
+	buf := make([]*model.SopNode, 0, batchSize)
+	err = s.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (s sopNodeDo) FindInBatches(result *[]*model.SopNode, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return s.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (s sopNodeDo) Attrs(attrs ...field.AssignExpr) ISopNodeDo {
+	return s.withDO(s.DO.Attrs(attrs...))
+}
+
+func (s sopNodeDo) Assign(attrs ...field.AssignExpr) ISopNodeDo {
+	return s.withDO(s.DO.Assign(attrs...))
+}
+
+func (s sopNodeDo) Joins(fields ...field.RelationField) ISopNodeDo {
+	for _, _f := range fields {
+		s = *s.withDO(s.DO.Joins(_f))
+	}
+	return &s
+}
+
+func (s sopNodeDo) Preload(fields ...field.RelationField) ISopNodeDo {
+	for _, _f := range fields {
+		s = *s.withDO(s.DO.Preload(_f))
+	}
+	return &s
+}
+
+func (s sopNodeDo) FirstOrInit() (*model.SopNode, error) {
+	if result, err := s.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.SopNode), nil
+	}
+}
+
+func (s sopNodeDo) FirstOrCreate() (*model.SopNode, error) {
+	if result, err := s.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.SopNode), nil
+	}
+}
+
+func (s sopNodeDo) FindByPage(offset int, limit int) (result []*model.SopNode, count int64, err error) {
+	result, err = s.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = s.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (s sopNodeDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = s.Count()
+	if err != nil {
+		return
+	}
+
+	err = s.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (s sopNodeDo) Scan(result interface{}) (err error) {
+	return s.DO.Scan(result)
+}
+
+func (s sopNodeDo) Delete(models ...*model.SopNode) (result gen.ResultInfo, err error) {
+	return s.DO.Delete(models)
+}
+
+func (s *sopNodeDo) withDO(do gen.Dao) *sopNodeDo {
+	s.DO = *do.(*gen.DO)
+	return s
+}

+ 436 - 0
database/dao/wechat/query/sop_stage.gen.go

@@ -0,0 +1,436 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newSopStage(db *gorm.DB, opts ...gen.DOOption) sopStage {
+	_sopStage := sopStage{}
+
+	_sopStage.sopStageDo.UseDB(db, opts...)
+	_sopStage.sopStageDo.UseModel(&model.SopStage{})
+
+	tableName := _sopStage.sopStageDo.TableName()
+	_sopStage.ALL = field.NewAsterisk(tableName)
+	_sopStage.ID = field.NewInt64(tableName, "id")
+	_sopStage.CreatedAt = field.NewTime(tableName, "created_at")
+	_sopStage.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_sopStage.Status = field.NewInt64(tableName, "status")
+	_sopStage.DeletedAt = field.NewField(tableName, "deleted_at")
+	_sopStage.TaskID = field.NewInt64(tableName, "task_id")
+	_sopStage.Name = field.NewString(tableName, "name")
+	_sopStage.ConditionType = field.NewInt64(tableName, "condition_type")
+	_sopStage.ConditionOperator = field.NewInt64(tableName, "condition_operator")
+	_sopStage.ConditionList = field.NewString(tableName, "condition_list")
+	_sopStage.ActionMessage = field.NewString(tableName, "action_message")
+	_sopStage.ActionLabelAdd = field.NewString(tableName, "action_label_add")
+	_sopStage.ActionForward = field.NewString(tableName, "action_forward")
+	_sopStage.IndexSort = field.NewInt64(tableName, "index_sort")
+	_sopStage.ActionLabelDel = field.NewString(tableName, "action_label_del")
+
+	_sopStage.fillFieldMap()
+
+	return _sopStage
+}
+
+type sopStage struct {
+	sopStageDo
+
+	ALL               field.Asterisk
+	ID                field.Int64
+	CreatedAt         field.Time   // Create Time | 创建日期
+	UpdatedAt         field.Time   // Update Time | 修改日期
+	Status            field.Int64  // 状态 1 正常 2 禁用
+	DeletedAt         field.Field  // Delete Time | 删除日期
+	TaskID            field.Int64  // SOP 任务 ID
+	Name              field.String // 阶段名称
+	ConditionType     field.Int64  // 客群筛选条件类型  1 按标签筛选 2 按客户基本信息筛选
+	ConditionOperator field.Int64  // 筛选条件关系  1 满足所有条件(and) 2 满足任意条件(or)
+	ConditionList     field.String // 筛选条件列表
+	ActionMessage     field.String // 命中后发送的消息内容
+	ActionLabelAdd    field.String // 命中后需要打的标签
+	ActionForward     field.String // 命中后转发的消息
+	IndexSort         field.Int64  // 阶段顺序
+	ActionLabelDel    field.String // 命中后需要打的标签
+
+	fieldMap map[string]field.Expr
+}
+
+func (s sopStage) Table(newTableName string) *sopStage {
+	s.sopStageDo.UseTable(newTableName)
+	return s.updateTableName(newTableName)
+}
+
+func (s sopStage) As(alias string) *sopStage {
+	s.sopStageDo.DO = *(s.sopStageDo.As(alias).(*gen.DO))
+	return s.updateTableName(alias)
+}
+
+func (s *sopStage) updateTableName(table string) *sopStage {
+	s.ALL = field.NewAsterisk(table)
+	s.ID = field.NewInt64(table, "id")
+	s.CreatedAt = field.NewTime(table, "created_at")
+	s.UpdatedAt = field.NewTime(table, "updated_at")
+	s.Status = field.NewInt64(table, "status")
+	s.DeletedAt = field.NewField(table, "deleted_at")
+	s.TaskID = field.NewInt64(table, "task_id")
+	s.Name = field.NewString(table, "name")
+	s.ConditionType = field.NewInt64(table, "condition_type")
+	s.ConditionOperator = field.NewInt64(table, "condition_operator")
+	s.ConditionList = field.NewString(table, "condition_list")
+	s.ActionMessage = field.NewString(table, "action_message")
+	s.ActionLabelAdd = field.NewString(table, "action_label_add")
+	s.ActionForward = field.NewString(table, "action_forward")
+	s.IndexSort = field.NewInt64(table, "index_sort")
+	s.ActionLabelDel = field.NewString(table, "action_label_del")
+
+	s.fillFieldMap()
+
+	return s
+}
+
+func (s *sopStage) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := s.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (s *sopStage) fillFieldMap() {
+	s.fieldMap = make(map[string]field.Expr, 15)
+	s.fieldMap["id"] = s.ID
+	s.fieldMap["created_at"] = s.CreatedAt
+	s.fieldMap["updated_at"] = s.UpdatedAt
+	s.fieldMap["status"] = s.Status
+	s.fieldMap["deleted_at"] = s.DeletedAt
+	s.fieldMap["task_id"] = s.TaskID
+	s.fieldMap["name"] = s.Name
+	s.fieldMap["condition_type"] = s.ConditionType
+	s.fieldMap["condition_operator"] = s.ConditionOperator
+	s.fieldMap["condition_list"] = s.ConditionList
+	s.fieldMap["action_message"] = s.ActionMessage
+	s.fieldMap["action_label_add"] = s.ActionLabelAdd
+	s.fieldMap["action_forward"] = s.ActionForward
+	s.fieldMap["index_sort"] = s.IndexSort
+	s.fieldMap["action_label_del"] = s.ActionLabelDel
+}
+
+func (s sopStage) clone(db *gorm.DB) sopStage {
+	s.sopStageDo.ReplaceConnPool(db.Statement.ConnPool)
+	return s
+}
+
+func (s sopStage) replaceDB(db *gorm.DB) sopStage {
+	s.sopStageDo.ReplaceDB(db)
+	return s
+}
+
+type sopStageDo struct{ gen.DO }
+
+type ISopStageDo interface {
+	gen.SubQuery
+	Debug() ISopStageDo
+	WithContext(ctx context.Context) ISopStageDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() ISopStageDo
+	WriteDB() ISopStageDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) ISopStageDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) ISopStageDo
+	Not(conds ...gen.Condition) ISopStageDo
+	Or(conds ...gen.Condition) ISopStageDo
+	Select(conds ...field.Expr) ISopStageDo
+	Where(conds ...gen.Condition) ISopStageDo
+	Order(conds ...field.Expr) ISopStageDo
+	Distinct(cols ...field.Expr) ISopStageDo
+	Omit(cols ...field.Expr) ISopStageDo
+	Join(table schema.Tabler, on ...field.Expr) ISopStageDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) ISopStageDo
+	RightJoin(table schema.Tabler, on ...field.Expr) ISopStageDo
+	Group(cols ...field.Expr) ISopStageDo
+	Having(conds ...gen.Condition) ISopStageDo
+	Limit(limit int) ISopStageDo
+	Offset(offset int) ISopStageDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) ISopStageDo
+	Unscoped() ISopStageDo
+	Create(values ...*model.SopStage) error
+	CreateInBatches(values []*model.SopStage, batchSize int) error
+	Save(values ...*model.SopStage) error
+	First() (*model.SopStage, error)
+	Take() (*model.SopStage, error)
+	Last() (*model.SopStage, error)
+	Find() ([]*model.SopStage, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.SopStage, err error)
+	FindInBatches(result *[]*model.SopStage, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.SopStage) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) ISopStageDo
+	Assign(attrs ...field.AssignExpr) ISopStageDo
+	Joins(fields ...field.RelationField) ISopStageDo
+	Preload(fields ...field.RelationField) ISopStageDo
+	FirstOrInit() (*model.SopStage, error)
+	FirstOrCreate() (*model.SopStage, error)
+	FindByPage(offset int, limit int) (result []*model.SopStage, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) ISopStageDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (s sopStageDo) Debug() ISopStageDo {
+	return s.withDO(s.DO.Debug())
+}
+
+func (s sopStageDo) WithContext(ctx context.Context) ISopStageDo {
+	return s.withDO(s.DO.WithContext(ctx))
+}
+
+func (s sopStageDo) ReadDB() ISopStageDo {
+	return s.Clauses(dbresolver.Read)
+}
+
+func (s sopStageDo) WriteDB() ISopStageDo {
+	return s.Clauses(dbresolver.Write)
+}
+
+func (s sopStageDo) Session(config *gorm.Session) ISopStageDo {
+	return s.withDO(s.DO.Session(config))
+}
+
+func (s sopStageDo) Clauses(conds ...clause.Expression) ISopStageDo {
+	return s.withDO(s.DO.Clauses(conds...))
+}
+
+func (s sopStageDo) Returning(value interface{}, columns ...string) ISopStageDo {
+	return s.withDO(s.DO.Returning(value, columns...))
+}
+
+func (s sopStageDo) Not(conds ...gen.Condition) ISopStageDo {
+	return s.withDO(s.DO.Not(conds...))
+}
+
+func (s sopStageDo) Or(conds ...gen.Condition) ISopStageDo {
+	return s.withDO(s.DO.Or(conds...))
+}
+
+func (s sopStageDo) Select(conds ...field.Expr) ISopStageDo {
+	return s.withDO(s.DO.Select(conds...))
+}
+
+func (s sopStageDo) Where(conds ...gen.Condition) ISopStageDo {
+	return s.withDO(s.DO.Where(conds...))
+}
+
+func (s sopStageDo) Order(conds ...field.Expr) ISopStageDo {
+	return s.withDO(s.DO.Order(conds...))
+}
+
+func (s sopStageDo) Distinct(cols ...field.Expr) ISopStageDo {
+	return s.withDO(s.DO.Distinct(cols...))
+}
+
+func (s sopStageDo) Omit(cols ...field.Expr) ISopStageDo {
+	return s.withDO(s.DO.Omit(cols...))
+}
+
+func (s sopStageDo) Join(table schema.Tabler, on ...field.Expr) ISopStageDo {
+	return s.withDO(s.DO.Join(table, on...))
+}
+
+func (s sopStageDo) LeftJoin(table schema.Tabler, on ...field.Expr) ISopStageDo {
+	return s.withDO(s.DO.LeftJoin(table, on...))
+}
+
+func (s sopStageDo) RightJoin(table schema.Tabler, on ...field.Expr) ISopStageDo {
+	return s.withDO(s.DO.RightJoin(table, on...))
+}
+
+func (s sopStageDo) Group(cols ...field.Expr) ISopStageDo {
+	return s.withDO(s.DO.Group(cols...))
+}
+
+func (s sopStageDo) Having(conds ...gen.Condition) ISopStageDo {
+	return s.withDO(s.DO.Having(conds...))
+}
+
+func (s sopStageDo) Limit(limit int) ISopStageDo {
+	return s.withDO(s.DO.Limit(limit))
+}
+
+func (s sopStageDo) Offset(offset int) ISopStageDo {
+	return s.withDO(s.DO.Offset(offset))
+}
+
+func (s sopStageDo) Scopes(funcs ...func(gen.Dao) gen.Dao) ISopStageDo {
+	return s.withDO(s.DO.Scopes(funcs...))
+}
+
+func (s sopStageDo) Unscoped() ISopStageDo {
+	return s.withDO(s.DO.Unscoped())
+}
+
+func (s sopStageDo) Create(values ...*model.SopStage) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return s.DO.Create(values)
+}
+
+func (s sopStageDo) CreateInBatches(values []*model.SopStage, batchSize int) error {
+	return s.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (s sopStageDo) Save(values ...*model.SopStage) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return s.DO.Save(values)
+}
+
+func (s sopStageDo) First() (*model.SopStage, error) {
+	if result, err := s.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.SopStage), nil
+	}
+}
+
+func (s sopStageDo) Take() (*model.SopStage, error) {
+	if result, err := s.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.SopStage), nil
+	}
+}
+
+func (s sopStageDo) Last() (*model.SopStage, error) {
+	if result, err := s.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.SopStage), nil
+	}
+}
+
+func (s sopStageDo) Find() ([]*model.SopStage, error) {
+	result, err := s.DO.Find()
+	return result.([]*model.SopStage), err
+}
+
+func (s sopStageDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.SopStage, err error) {
+	buf := make([]*model.SopStage, 0, batchSize)
+	err = s.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (s sopStageDo) FindInBatches(result *[]*model.SopStage, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return s.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (s sopStageDo) Attrs(attrs ...field.AssignExpr) ISopStageDo {
+	return s.withDO(s.DO.Attrs(attrs...))
+}
+
+func (s sopStageDo) Assign(attrs ...field.AssignExpr) ISopStageDo {
+	return s.withDO(s.DO.Assign(attrs...))
+}
+
+func (s sopStageDo) Joins(fields ...field.RelationField) ISopStageDo {
+	for _, _f := range fields {
+		s = *s.withDO(s.DO.Joins(_f))
+	}
+	return &s
+}
+
+func (s sopStageDo) Preload(fields ...field.RelationField) ISopStageDo {
+	for _, _f := range fields {
+		s = *s.withDO(s.DO.Preload(_f))
+	}
+	return &s
+}
+
+func (s sopStageDo) FirstOrInit() (*model.SopStage, error) {
+	if result, err := s.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.SopStage), nil
+	}
+}
+
+func (s sopStageDo) FirstOrCreate() (*model.SopStage, error) {
+	if result, err := s.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.SopStage), nil
+	}
+}
+
+func (s sopStageDo) FindByPage(offset int, limit int) (result []*model.SopStage, count int64, err error) {
+	result, err = s.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = s.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (s sopStageDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = s.Count()
+	if err != nil {
+		return
+	}
+
+	err = s.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (s sopStageDo) Scan(result interface{}) (err error) {
+	return s.DO.Scan(result)
+}
+
+func (s sopStageDo) Delete(models ...*model.SopStage) (result gen.ResultInfo, err error) {
+	return s.DO.Delete(models)
+}
+
+func (s *sopStageDo) withDO(do gen.Dao) *sopStageDo {
+	s.DO = *do.(*gen.DO)
+	return s
+}

+ 428 - 0
database/dao/wechat/query/sop_task.gen.go

@@ -0,0 +1,428 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newSopTask(db *gorm.DB, opts ...gen.DOOption) sopTask {
+	_sopTask := sopTask{}
+
+	_sopTask.sopTaskDo.UseDB(db, opts...)
+	_sopTask.sopTaskDo.UseModel(&model.SopTask{})
+
+	tableName := _sopTask.sopTaskDo.TableName()
+	_sopTask.ALL = field.NewAsterisk(tableName)
+	_sopTask.ID = field.NewInt64(tableName, "id")
+	_sopTask.CreatedAt = field.NewTime(tableName, "created_at")
+	_sopTask.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_sopTask.Status = field.NewInt64(tableName, "status")
+	_sopTask.DeletedAt = field.NewField(tableName, "deleted_at")
+	_sopTask.Name = field.NewString(tableName, "name")
+	_sopTask.BotWxidList = field.NewString(tableName, "bot_wxid_list")
+	_sopTask.Type = field.NewInt64(tableName, "type")
+	_sopTask.PlanStartTime = field.NewTime(tableName, "plan_start_time")
+	_sopTask.PlanEndTime = field.NewTime(tableName, "plan_end_time")
+	_sopTask.CreatorID = field.NewString(tableName, "creator_id")
+	_sopTask.OrganizationID = field.NewInt64(tableName, "organization_id")
+	_sopTask.Token = field.NewString(tableName, "token")
+
+	_sopTask.fillFieldMap()
+
+	return _sopTask
+}
+
+type sopTask struct {
+	sopTaskDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	Status         field.Int64  // 状态 1 草稿 2 未开始 3 已开始 4 已结束 5 禁用
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	Name           field.String // SOP 任务名称
+	BotWxidList    field.String // 机器人微信 id 列表
+	Type           field.Int64  // 标签类型:1好友,2群组,3企业微信联系人
+	PlanStartTime  field.Time   // 任务计划开始时间
+	PlanEndTime    field.Time   // 任务计划结束时间
+	CreatorID      field.String // 创建者 id
+	OrganizationID field.Int64  // 机构 ID
+	Token          field.String
+
+	fieldMap map[string]field.Expr
+}
+
+func (s sopTask) Table(newTableName string) *sopTask {
+	s.sopTaskDo.UseTable(newTableName)
+	return s.updateTableName(newTableName)
+}
+
+func (s sopTask) As(alias string) *sopTask {
+	s.sopTaskDo.DO = *(s.sopTaskDo.As(alias).(*gen.DO))
+	return s.updateTableName(alias)
+}
+
+func (s *sopTask) updateTableName(table string) *sopTask {
+	s.ALL = field.NewAsterisk(table)
+	s.ID = field.NewInt64(table, "id")
+	s.CreatedAt = field.NewTime(table, "created_at")
+	s.UpdatedAt = field.NewTime(table, "updated_at")
+	s.Status = field.NewInt64(table, "status")
+	s.DeletedAt = field.NewField(table, "deleted_at")
+	s.Name = field.NewString(table, "name")
+	s.BotWxidList = field.NewString(table, "bot_wxid_list")
+	s.Type = field.NewInt64(table, "type")
+	s.PlanStartTime = field.NewTime(table, "plan_start_time")
+	s.PlanEndTime = field.NewTime(table, "plan_end_time")
+	s.CreatorID = field.NewString(table, "creator_id")
+	s.OrganizationID = field.NewInt64(table, "organization_id")
+	s.Token = field.NewString(table, "token")
+
+	s.fillFieldMap()
+
+	return s
+}
+
+func (s *sopTask) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := s.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (s *sopTask) fillFieldMap() {
+	s.fieldMap = make(map[string]field.Expr, 13)
+	s.fieldMap["id"] = s.ID
+	s.fieldMap["created_at"] = s.CreatedAt
+	s.fieldMap["updated_at"] = s.UpdatedAt
+	s.fieldMap["status"] = s.Status
+	s.fieldMap["deleted_at"] = s.DeletedAt
+	s.fieldMap["name"] = s.Name
+	s.fieldMap["bot_wxid_list"] = s.BotWxidList
+	s.fieldMap["type"] = s.Type
+	s.fieldMap["plan_start_time"] = s.PlanStartTime
+	s.fieldMap["plan_end_time"] = s.PlanEndTime
+	s.fieldMap["creator_id"] = s.CreatorID
+	s.fieldMap["organization_id"] = s.OrganizationID
+	s.fieldMap["token"] = s.Token
+}
+
+func (s sopTask) clone(db *gorm.DB) sopTask {
+	s.sopTaskDo.ReplaceConnPool(db.Statement.ConnPool)
+	return s
+}
+
+func (s sopTask) replaceDB(db *gorm.DB) sopTask {
+	s.sopTaskDo.ReplaceDB(db)
+	return s
+}
+
+type sopTaskDo struct{ gen.DO }
+
+type ISopTaskDo interface {
+	gen.SubQuery
+	Debug() ISopTaskDo
+	WithContext(ctx context.Context) ISopTaskDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() ISopTaskDo
+	WriteDB() ISopTaskDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) ISopTaskDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) ISopTaskDo
+	Not(conds ...gen.Condition) ISopTaskDo
+	Or(conds ...gen.Condition) ISopTaskDo
+	Select(conds ...field.Expr) ISopTaskDo
+	Where(conds ...gen.Condition) ISopTaskDo
+	Order(conds ...field.Expr) ISopTaskDo
+	Distinct(cols ...field.Expr) ISopTaskDo
+	Omit(cols ...field.Expr) ISopTaskDo
+	Join(table schema.Tabler, on ...field.Expr) ISopTaskDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) ISopTaskDo
+	RightJoin(table schema.Tabler, on ...field.Expr) ISopTaskDo
+	Group(cols ...field.Expr) ISopTaskDo
+	Having(conds ...gen.Condition) ISopTaskDo
+	Limit(limit int) ISopTaskDo
+	Offset(offset int) ISopTaskDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) ISopTaskDo
+	Unscoped() ISopTaskDo
+	Create(values ...*model.SopTask) error
+	CreateInBatches(values []*model.SopTask, batchSize int) error
+	Save(values ...*model.SopTask) error
+	First() (*model.SopTask, error)
+	Take() (*model.SopTask, error)
+	Last() (*model.SopTask, error)
+	Find() ([]*model.SopTask, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.SopTask, err error)
+	FindInBatches(result *[]*model.SopTask, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.SopTask) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) ISopTaskDo
+	Assign(attrs ...field.AssignExpr) ISopTaskDo
+	Joins(fields ...field.RelationField) ISopTaskDo
+	Preload(fields ...field.RelationField) ISopTaskDo
+	FirstOrInit() (*model.SopTask, error)
+	FirstOrCreate() (*model.SopTask, error)
+	FindByPage(offset int, limit int) (result []*model.SopTask, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) ISopTaskDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (s sopTaskDo) Debug() ISopTaskDo {
+	return s.withDO(s.DO.Debug())
+}
+
+func (s sopTaskDo) WithContext(ctx context.Context) ISopTaskDo {
+	return s.withDO(s.DO.WithContext(ctx))
+}
+
+func (s sopTaskDo) ReadDB() ISopTaskDo {
+	return s.Clauses(dbresolver.Read)
+}
+
+func (s sopTaskDo) WriteDB() ISopTaskDo {
+	return s.Clauses(dbresolver.Write)
+}
+
+func (s sopTaskDo) Session(config *gorm.Session) ISopTaskDo {
+	return s.withDO(s.DO.Session(config))
+}
+
+func (s sopTaskDo) Clauses(conds ...clause.Expression) ISopTaskDo {
+	return s.withDO(s.DO.Clauses(conds...))
+}
+
+func (s sopTaskDo) Returning(value interface{}, columns ...string) ISopTaskDo {
+	return s.withDO(s.DO.Returning(value, columns...))
+}
+
+func (s sopTaskDo) Not(conds ...gen.Condition) ISopTaskDo {
+	return s.withDO(s.DO.Not(conds...))
+}
+
+func (s sopTaskDo) Or(conds ...gen.Condition) ISopTaskDo {
+	return s.withDO(s.DO.Or(conds...))
+}
+
+func (s sopTaskDo) Select(conds ...field.Expr) ISopTaskDo {
+	return s.withDO(s.DO.Select(conds...))
+}
+
+func (s sopTaskDo) Where(conds ...gen.Condition) ISopTaskDo {
+	return s.withDO(s.DO.Where(conds...))
+}
+
+func (s sopTaskDo) Order(conds ...field.Expr) ISopTaskDo {
+	return s.withDO(s.DO.Order(conds...))
+}
+
+func (s sopTaskDo) Distinct(cols ...field.Expr) ISopTaskDo {
+	return s.withDO(s.DO.Distinct(cols...))
+}
+
+func (s sopTaskDo) Omit(cols ...field.Expr) ISopTaskDo {
+	return s.withDO(s.DO.Omit(cols...))
+}
+
+func (s sopTaskDo) Join(table schema.Tabler, on ...field.Expr) ISopTaskDo {
+	return s.withDO(s.DO.Join(table, on...))
+}
+
+func (s sopTaskDo) LeftJoin(table schema.Tabler, on ...field.Expr) ISopTaskDo {
+	return s.withDO(s.DO.LeftJoin(table, on...))
+}
+
+func (s sopTaskDo) RightJoin(table schema.Tabler, on ...field.Expr) ISopTaskDo {
+	return s.withDO(s.DO.RightJoin(table, on...))
+}
+
+func (s sopTaskDo) Group(cols ...field.Expr) ISopTaskDo {
+	return s.withDO(s.DO.Group(cols...))
+}
+
+func (s sopTaskDo) Having(conds ...gen.Condition) ISopTaskDo {
+	return s.withDO(s.DO.Having(conds...))
+}
+
+func (s sopTaskDo) Limit(limit int) ISopTaskDo {
+	return s.withDO(s.DO.Limit(limit))
+}
+
+func (s sopTaskDo) Offset(offset int) ISopTaskDo {
+	return s.withDO(s.DO.Offset(offset))
+}
+
+func (s sopTaskDo) Scopes(funcs ...func(gen.Dao) gen.Dao) ISopTaskDo {
+	return s.withDO(s.DO.Scopes(funcs...))
+}
+
+func (s sopTaskDo) Unscoped() ISopTaskDo {
+	return s.withDO(s.DO.Unscoped())
+}
+
+func (s sopTaskDo) Create(values ...*model.SopTask) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return s.DO.Create(values)
+}
+
+func (s sopTaskDo) CreateInBatches(values []*model.SopTask, batchSize int) error {
+	return s.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (s sopTaskDo) Save(values ...*model.SopTask) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return s.DO.Save(values)
+}
+
+func (s sopTaskDo) First() (*model.SopTask, error) {
+	if result, err := s.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.SopTask), nil
+	}
+}
+
+func (s sopTaskDo) Take() (*model.SopTask, error) {
+	if result, err := s.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.SopTask), nil
+	}
+}
+
+func (s sopTaskDo) Last() (*model.SopTask, error) {
+	if result, err := s.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.SopTask), nil
+	}
+}
+
+func (s sopTaskDo) Find() ([]*model.SopTask, error) {
+	result, err := s.DO.Find()
+	return result.([]*model.SopTask), err
+}
+
+func (s sopTaskDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.SopTask, err error) {
+	buf := make([]*model.SopTask, 0, batchSize)
+	err = s.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (s sopTaskDo) FindInBatches(result *[]*model.SopTask, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return s.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (s sopTaskDo) Attrs(attrs ...field.AssignExpr) ISopTaskDo {
+	return s.withDO(s.DO.Attrs(attrs...))
+}
+
+func (s sopTaskDo) Assign(attrs ...field.AssignExpr) ISopTaskDo {
+	return s.withDO(s.DO.Assign(attrs...))
+}
+
+func (s sopTaskDo) Joins(fields ...field.RelationField) ISopTaskDo {
+	for _, _f := range fields {
+		s = *s.withDO(s.DO.Joins(_f))
+	}
+	return &s
+}
+
+func (s sopTaskDo) Preload(fields ...field.RelationField) ISopTaskDo {
+	for _, _f := range fields {
+		s = *s.withDO(s.DO.Preload(_f))
+	}
+	return &s
+}
+
+func (s sopTaskDo) FirstOrInit() (*model.SopTask, error) {
+	if result, err := s.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.SopTask), nil
+	}
+}
+
+func (s sopTaskDo) FirstOrCreate() (*model.SopTask, error) {
+	if result, err := s.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.SopTask), nil
+	}
+}
+
+func (s sopTaskDo) FindByPage(offset int, limit int) (result []*model.SopTask, count int64, err error) {
+	result, err = s.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = s.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (s sopTaskDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = s.Count()
+	if err != nil {
+		return
+	}
+
+	err = s.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (s sopTaskDo) Scan(result interface{}) (err error) {
+	return s.DO.Scan(result)
+}
+
+func (s sopTaskDo) Delete(models ...*model.SopTask) (result gen.ResultInfo, err error) {
+	return s.DO.Delete(models)
+}
+
+func (s *sopTaskDo) withDO(do gen.Dao) *sopTaskDo {
+	s.DO = *do.(*gen.DO)
+	return s
+}

+ 433 - 0
database/dao/wechat/query/token.gen.go

@@ -0,0 +1,433 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newToken(db *gorm.DB, opts ...gen.DOOption) token {
+	_token := token{}
+
+	_token.tokenDo.UseDB(db, opts...)
+	_token.tokenDo.UseModel(&model.Token{})
+
+	tableName := _token.tokenDo.TableName()
+	_token.ALL = field.NewAsterisk(tableName)
+	_token.ID = field.NewInt64(tableName, "id")
+	_token.CreatedAt = field.NewTime(tableName, "created_at")
+	_token.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_token.DeletedAt = field.NewField(tableName, "deleted_at")
+	_token.ExpireAt = field.NewTime(tableName, "expire_at")
+	_token.Token = field.NewString(tableName, "token")
+	_token.Mac = field.NewString(tableName, "mac")
+	_token.Remark = field.NewString(tableName, "remark")
+	_token.OrganizationID = field.NewInt64(tableName, "organization_id")
+	_token.AgentID = field.NewInt64(tableName, "agent_id")
+	_token.CustomAgentBase = field.NewString(tableName, "custom_agent_base")
+	_token.CustomAgentKey = field.NewString(tableName, "custom_agent_key")
+	_token.OpenaiBase = field.NewString(tableName, "openai_base")
+	_token.OpenaiKey = field.NewString(tableName, "openai_key")
+
+	_token.fillFieldMap()
+
+	return _token
+}
+
+// token Token表
+type token struct {
+	tokenDo
+
+	ALL             field.Asterisk
+	ID              field.Int64
+	CreatedAt       field.Time   // Create Time | 创建日期
+	UpdatedAt       field.Time   // Update Time | 修改日期
+	DeletedAt       field.Field  // Delete Time | 删除时间
+	ExpireAt        field.Time   // 过期时间
+	Token           field.String // Token
+	Mac             field.String // Mac地址
+	Remark          field.String // 备注
+	OrganizationID  field.Int64  // 租户ID
+	AgentID         field.Int64  // 0 定制
+	CustomAgentBase field.String // 定制agent服务地址
+	CustomAgentKey  field.String // 定制agent服务密钥
+	OpenaiBase      field.String // 大模型服务地址
+	OpenaiKey       field.String // 大模型服务密钥
+
+	fieldMap map[string]field.Expr
+}
+
+func (t token) Table(newTableName string) *token {
+	t.tokenDo.UseTable(newTableName)
+	return t.updateTableName(newTableName)
+}
+
+func (t token) As(alias string) *token {
+	t.tokenDo.DO = *(t.tokenDo.As(alias).(*gen.DO))
+	return t.updateTableName(alias)
+}
+
+func (t *token) updateTableName(table string) *token {
+	t.ALL = field.NewAsterisk(table)
+	t.ID = field.NewInt64(table, "id")
+	t.CreatedAt = field.NewTime(table, "created_at")
+	t.UpdatedAt = field.NewTime(table, "updated_at")
+	t.DeletedAt = field.NewField(table, "deleted_at")
+	t.ExpireAt = field.NewTime(table, "expire_at")
+	t.Token = field.NewString(table, "token")
+	t.Mac = field.NewString(table, "mac")
+	t.Remark = field.NewString(table, "remark")
+	t.OrganizationID = field.NewInt64(table, "organization_id")
+	t.AgentID = field.NewInt64(table, "agent_id")
+	t.CustomAgentBase = field.NewString(table, "custom_agent_base")
+	t.CustomAgentKey = field.NewString(table, "custom_agent_key")
+	t.OpenaiBase = field.NewString(table, "openai_base")
+	t.OpenaiKey = field.NewString(table, "openai_key")
+
+	t.fillFieldMap()
+
+	return t
+}
+
+func (t *token) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := t.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (t *token) fillFieldMap() {
+	t.fieldMap = make(map[string]field.Expr, 14)
+	t.fieldMap["id"] = t.ID
+	t.fieldMap["created_at"] = t.CreatedAt
+	t.fieldMap["updated_at"] = t.UpdatedAt
+	t.fieldMap["deleted_at"] = t.DeletedAt
+	t.fieldMap["expire_at"] = t.ExpireAt
+	t.fieldMap["token"] = t.Token
+	t.fieldMap["mac"] = t.Mac
+	t.fieldMap["remark"] = t.Remark
+	t.fieldMap["organization_id"] = t.OrganizationID
+	t.fieldMap["agent_id"] = t.AgentID
+	t.fieldMap["custom_agent_base"] = t.CustomAgentBase
+	t.fieldMap["custom_agent_key"] = t.CustomAgentKey
+	t.fieldMap["openai_base"] = t.OpenaiBase
+	t.fieldMap["openai_key"] = t.OpenaiKey
+}
+
+func (t token) clone(db *gorm.DB) token {
+	t.tokenDo.ReplaceConnPool(db.Statement.ConnPool)
+	return t
+}
+
+func (t token) replaceDB(db *gorm.DB) token {
+	t.tokenDo.ReplaceDB(db)
+	return t
+}
+
+type tokenDo struct{ gen.DO }
+
+type ITokenDo interface {
+	gen.SubQuery
+	Debug() ITokenDo
+	WithContext(ctx context.Context) ITokenDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() ITokenDo
+	WriteDB() ITokenDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) ITokenDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) ITokenDo
+	Not(conds ...gen.Condition) ITokenDo
+	Or(conds ...gen.Condition) ITokenDo
+	Select(conds ...field.Expr) ITokenDo
+	Where(conds ...gen.Condition) ITokenDo
+	Order(conds ...field.Expr) ITokenDo
+	Distinct(cols ...field.Expr) ITokenDo
+	Omit(cols ...field.Expr) ITokenDo
+	Join(table schema.Tabler, on ...field.Expr) ITokenDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) ITokenDo
+	RightJoin(table schema.Tabler, on ...field.Expr) ITokenDo
+	Group(cols ...field.Expr) ITokenDo
+	Having(conds ...gen.Condition) ITokenDo
+	Limit(limit int) ITokenDo
+	Offset(offset int) ITokenDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) ITokenDo
+	Unscoped() ITokenDo
+	Create(values ...*model.Token) error
+	CreateInBatches(values []*model.Token, batchSize int) error
+	Save(values ...*model.Token) error
+	First() (*model.Token, error)
+	Take() (*model.Token, error)
+	Last() (*model.Token, error)
+	Find() ([]*model.Token, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Token, err error)
+	FindInBatches(result *[]*model.Token, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.Token) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) ITokenDo
+	Assign(attrs ...field.AssignExpr) ITokenDo
+	Joins(fields ...field.RelationField) ITokenDo
+	Preload(fields ...field.RelationField) ITokenDo
+	FirstOrInit() (*model.Token, error)
+	FirstOrCreate() (*model.Token, error)
+	FindByPage(offset int, limit int) (result []*model.Token, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) ITokenDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (t tokenDo) Debug() ITokenDo {
+	return t.withDO(t.DO.Debug())
+}
+
+func (t tokenDo) WithContext(ctx context.Context) ITokenDo {
+	return t.withDO(t.DO.WithContext(ctx))
+}
+
+func (t tokenDo) ReadDB() ITokenDo {
+	return t.Clauses(dbresolver.Read)
+}
+
+func (t tokenDo) WriteDB() ITokenDo {
+	return t.Clauses(dbresolver.Write)
+}
+
+func (t tokenDo) Session(config *gorm.Session) ITokenDo {
+	return t.withDO(t.DO.Session(config))
+}
+
+func (t tokenDo) Clauses(conds ...clause.Expression) ITokenDo {
+	return t.withDO(t.DO.Clauses(conds...))
+}
+
+func (t tokenDo) Returning(value interface{}, columns ...string) ITokenDo {
+	return t.withDO(t.DO.Returning(value, columns...))
+}
+
+func (t tokenDo) Not(conds ...gen.Condition) ITokenDo {
+	return t.withDO(t.DO.Not(conds...))
+}
+
+func (t tokenDo) Or(conds ...gen.Condition) ITokenDo {
+	return t.withDO(t.DO.Or(conds...))
+}
+
+func (t tokenDo) Select(conds ...field.Expr) ITokenDo {
+	return t.withDO(t.DO.Select(conds...))
+}
+
+func (t tokenDo) Where(conds ...gen.Condition) ITokenDo {
+	return t.withDO(t.DO.Where(conds...))
+}
+
+func (t tokenDo) Order(conds ...field.Expr) ITokenDo {
+	return t.withDO(t.DO.Order(conds...))
+}
+
+func (t tokenDo) Distinct(cols ...field.Expr) ITokenDo {
+	return t.withDO(t.DO.Distinct(cols...))
+}
+
+func (t tokenDo) Omit(cols ...field.Expr) ITokenDo {
+	return t.withDO(t.DO.Omit(cols...))
+}
+
+func (t tokenDo) Join(table schema.Tabler, on ...field.Expr) ITokenDo {
+	return t.withDO(t.DO.Join(table, on...))
+}
+
+func (t tokenDo) LeftJoin(table schema.Tabler, on ...field.Expr) ITokenDo {
+	return t.withDO(t.DO.LeftJoin(table, on...))
+}
+
+func (t tokenDo) RightJoin(table schema.Tabler, on ...field.Expr) ITokenDo {
+	return t.withDO(t.DO.RightJoin(table, on...))
+}
+
+func (t tokenDo) Group(cols ...field.Expr) ITokenDo {
+	return t.withDO(t.DO.Group(cols...))
+}
+
+func (t tokenDo) Having(conds ...gen.Condition) ITokenDo {
+	return t.withDO(t.DO.Having(conds...))
+}
+
+func (t tokenDo) Limit(limit int) ITokenDo {
+	return t.withDO(t.DO.Limit(limit))
+}
+
+func (t tokenDo) Offset(offset int) ITokenDo {
+	return t.withDO(t.DO.Offset(offset))
+}
+
+func (t tokenDo) Scopes(funcs ...func(gen.Dao) gen.Dao) ITokenDo {
+	return t.withDO(t.DO.Scopes(funcs...))
+}
+
+func (t tokenDo) Unscoped() ITokenDo {
+	return t.withDO(t.DO.Unscoped())
+}
+
+func (t tokenDo) Create(values ...*model.Token) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return t.DO.Create(values)
+}
+
+func (t tokenDo) CreateInBatches(values []*model.Token, batchSize int) error {
+	return t.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (t tokenDo) Save(values ...*model.Token) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return t.DO.Save(values)
+}
+
+func (t tokenDo) First() (*model.Token, error) {
+	if result, err := t.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Token), nil
+	}
+}
+
+func (t tokenDo) Take() (*model.Token, error) {
+	if result, err := t.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Token), nil
+	}
+}
+
+func (t tokenDo) Last() (*model.Token, error) {
+	if result, err := t.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Token), nil
+	}
+}
+
+func (t tokenDo) Find() ([]*model.Token, error) {
+	result, err := t.DO.Find()
+	return result.([]*model.Token), err
+}
+
+func (t tokenDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Token, err error) {
+	buf := make([]*model.Token, 0, batchSize)
+	err = t.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (t tokenDo) FindInBatches(result *[]*model.Token, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return t.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (t tokenDo) Attrs(attrs ...field.AssignExpr) ITokenDo {
+	return t.withDO(t.DO.Attrs(attrs...))
+}
+
+func (t tokenDo) Assign(attrs ...field.AssignExpr) ITokenDo {
+	return t.withDO(t.DO.Assign(attrs...))
+}
+
+func (t tokenDo) Joins(fields ...field.RelationField) ITokenDo {
+	for _, _f := range fields {
+		t = *t.withDO(t.DO.Joins(_f))
+	}
+	return &t
+}
+
+func (t tokenDo) Preload(fields ...field.RelationField) ITokenDo {
+	for _, _f := range fields {
+		t = *t.withDO(t.DO.Preload(_f))
+	}
+	return &t
+}
+
+func (t tokenDo) FirstOrInit() (*model.Token, error) {
+	if result, err := t.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Token), nil
+	}
+}
+
+func (t tokenDo) FirstOrCreate() (*model.Token, error) {
+	if result, err := t.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Token), nil
+	}
+}
+
+func (t tokenDo) FindByPage(offset int, limit int) (result []*model.Token, count int64, err error) {
+	result, err = t.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = t.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (t tokenDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = t.Count()
+	if err != nil {
+		return
+	}
+
+	err = t.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (t tokenDo) Scan(result interface{}) (err error) {
+	return t.DO.Scan(result)
+}
+
+func (t tokenDo) Delete(models ...*model.Token) (result gen.ResultInfo, err error) {
+	return t.DO.Delete(models)
+}
+
+func (t *tokenDo) withDO(do gen.Dao) *tokenDo {
+	t.DO = *do.(*gen.DO)
+	return t
+}

+ 413 - 0
database/dao/wechat/query/tutorial.gen.go

@@ -0,0 +1,413 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newTutorial(db *gorm.DB, opts ...gen.DOOption) tutorial {
+	_tutorial := tutorial{}
+
+	_tutorial.tutorialDo.UseDB(db, opts...)
+	_tutorial.tutorialDo.UseModel(&model.Tutorial{})
+
+	tableName := _tutorial.tutorialDo.TableName()
+	_tutorial.ALL = field.NewAsterisk(tableName)
+	_tutorial.ID = field.NewInt64(tableName, "id")
+	_tutorial.EmployeeID = field.NewInt64(tableName, "employee_id")
+	_tutorial.CreatedAt = field.NewTime(tableName, "created_at")
+	_tutorial.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_tutorial.DeletedAt = field.NewField(tableName, "deleted_at")
+	_tutorial.Index = field.NewInt64(tableName, "index")
+	_tutorial.Title = field.NewString(tableName, "title")
+	_tutorial.Content = field.NewString(tableName, "content")
+	_tutorial.OrganizationID = field.NewInt64(tableName, "organization_id")
+
+	_tutorial.fillFieldMap()
+
+	return _tutorial
+}
+
+// tutorial 数字员工使用教程表
+type tutorial struct {
+	tutorialDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	EmployeeID     field.Int64  // 员工ID
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	Index          field.Int64  // 序号
+	Title          field.String // 标题
+	Content        field.String // 内容
+	OrganizationID field.Int64  // 机构ID
+
+	fieldMap map[string]field.Expr
+}
+
+func (t tutorial) Table(newTableName string) *tutorial {
+	t.tutorialDo.UseTable(newTableName)
+	return t.updateTableName(newTableName)
+}
+
+func (t tutorial) As(alias string) *tutorial {
+	t.tutorialDo.DO = *(t.tutorialDo.As(alias).(*gen.DO))
+	return t.updateTableName(alias)
+}
+
+func (t *tutorial) updateTableName(table string) *tutorial {
+	t.ALL = field.NewAsterisk(table)
+	t.ID = field.NewInt64(table, "id")
+	t.EmployeeID = field.NewInt64(table, "employee_id")
+	t.CreatedAt = field.NewTime(table, "created_at")
+	t.UpdatedAt = field.NewTime(table, "updated_at")
+	t.DeletedAt = field.NewField(table, "deleted_at")
+	t.Index = field.NewInt64(table, "index")
+	t.Title = field.NewString(table, "title")
+	t.Content = field.NewString(table, "content")
+	t.OrganizationID = field.NewInt64(table, "organization_id")
+
+	t.fillFieldMap()
+
+	return t
+}
+
+func (t *tutorial) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := t.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (t *tutorial) fillFieldMap() {
+	t.fieldMap = make(map[string]field.Expr, 9)
+	t.fieldMap["id"] = t.ID
+	t.fieldMap["employee_id"] = t.EmployeeID
+	t.fieldMap["created_at"] = t.CreatedAt
+	t.fieldMap["updated_at"] = t.UpdatedAt
+	t.fieldMap["deleted_at"] = t.DeletedAt
+	t.fieldMap["index"] = t.Index
+	t.fieldMap["title"] = t.Title
+	t.fieldMap["content"] = t.Content
+	t.fieldMap["organization_id"] = t.OrganizationID
+}
+
+func (t tutorial) clone(db *gorm.DB) tutorial {
+	t.tutorialDo.ReplaceConnPool(db.Statement.ConnPool)
+	return t
+}
+
+func (t tutorial) replaceDB(db *gorm.DB) tutorial {
+	t.tutorialDo.ReplaceDB(db)
+	return t
+}
+
+type tutorialDo struct{ gen.DO }
+
+type ITutorialDo interface {
+	gen.SubQuery
+	Debug() ITutorialDo
+	WithContext(ctx context.Context) ITutorialDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() ITutorialDo
+	WriteDB() ITutorialDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) ITutorialDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) ITutorialDo
+	Not(conds ...gen.Condition) ITutorialDo
+	Or(conds ...gen.Condition) ITutorialDo
+	Select(conds ...field.Expr) ITutorialDo
+	Where(conds ...gen.Condition) ITutorialDo
+	Order(conds ...field.Expr) ITutorialDo
+	Distinct(cols ...field.Expr) ITutorialDo
+	Omit(cols ...field.Expr) ITutorialDo
+	Join(table schema.Tabler, on ...field.Expr) ITutorialDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) ITutorialDo
+	RightJoin(table schema.Tabler, on ...field.Expr) ITutorialDo
+	Group(cols ...field.Expr) ITutorialDo
+	Having(conds ...gen.Condition) ITutorialDo
+	Limit(limit int) ITutorialDo
+	Offset(offset int) ITutorialDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) ITutorialDo
+	Unscoped() ITutorialDo
+	Create(values ...*model.Tutorial) error
+	CreateInBatches(values []*model.Tutorial, batchSize int) error
+	Save(values ...*model.Tutorial) error
+	First() (*model.Tutorial, error)
+	Take() (*model.Tutorial, error)
+	Last() (*model.Tutorial, error)
+	Find() ([]*model.Tutorial, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Tutorial, err error)
+	FindInBatches(result *[]*model.Tutorial, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.Tutorial) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) ITutorialDo
+	Assign(attrs ...field.AssignExpr) ITutorialDo
+	Joins(fields ...field.RelationField) ITutorialDo
+	Preload(fields ...field.RelationField) ITutorialDo
+	FirstOrInit() (*model.Tutorial, error)
+	FirstOrCreate() (*model.Tutorial, error)
+	FindByPage(offset int, limit int) (result []*model.Tutorial, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) ITutorialDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (t tutorialDo) Debug() ITutorialDo {
+	return t.withDO(t.DO.Debug())
+}
+
+func (t tutorialDo) WithContext(ctx context.Context) ITutorialDo {
+	return t.withDO(t.DO.WithContext(ctx))
+}
+
+func (t tutorialDo) ReadDB() ITutorialDo {
+	return t.Clauses(dbresolver.Read)
+}
+
+func (t tutorialDo) WriteDB() ITutorialDo {
+	return t.Clauses(dbresolver.Write)
+}
+
+func (t tutorialDo) Session(config *gorm.Session) ITutorialDo {
+	return t.withDO(t.DO.Session(config))
+}
+
+func (t tutorialDo) Clauses(conds ...clause.Expression) ITutorialDo {
+	return t.withDO(t.DO.Clauses(conds...))
+}
+
+func (t tutorialDo) Returning(value interface{}, columns ...string) ITutorialDo {
+	return t.withDO(t.DO.Returning(value, columns...))
+}
+
+func (t tutorialDo) Not(conds ...gen.Condition) ITutorialDo {
+	return t.withDO(t.DO.Not(conds...))
+}
+
+func (t tutorialDo) Or(conds ...gen.Condition) ITutorialDo {
+	return t.withDO(t.DO.Or(conds...))
+}
+
+func (t tutorialDo) Select(conds ...field.Expr) ITutorialDo {
+	return t.withDO(t.DO.Select(conds...))
+}
+
+func (t tutorialDo) Where(conds ...gen.Condition) ITutorialDo {
+	return t.withDO(t.DO.Where(conds...))
+}
+
+func (t tutorialDo) Order(conds ...field.Expr) ITutorialDo {
+	return t.withDO(t.DO.Order(conds...))
+}
+
+func (t tutorialDo) Distinct(cols ...field.Expr) ITutorialDo {
+	return t.withDO(t.DO.Distinct(cols...))
+}
+
+func (t tutorialDo) Omit(cols ...field.Expr) ITutorialDo {
+	return t.withDO(t.DO.Omit(cols...))
+}
+
+func (t tutorialDo) Join(table schema.Tabler, on ...field.Expr) ITutorialDo {
+	return t.withDO(t.DO.Join(table, on...))
+}
+
+func (t tutorialDo) LeftJoin(table schema.Tabler, on ...field.Expr) ITutorialDo {
+	return t.withDO(t.DO.LeftJoin(table, on...))
+}
+
+func (t tutorialDo) RightJoin(table schema.Tabler, on ...field.Expr) ITutorialDo {
+	return t.withDO(t.DO.RightJoin(table, on...))
+}
+
+func (t tutorialDo) Group(cols ...field.Expr) ITutorialDo {
+	return t.withDO(t.DO.Group(cols...))
+}
+
+func (t tutorialDo) Having(conds ...gen.Condition) ITutorialDo {
+	return t.withDO(t.DO.Having(conds...))
+}
+
+func (t tutorialDo) Limit(limit int) ITutorialDo {
+	return t.withDO(t.DO.Limit(limit))
+}
+
+func (t tutorialDo) Offset(offset int) ITutorialDo {
+	return t.withDO(t.DO.Offset(offset))
+}
+
+func (t tutorialDo) Scopes(funcs ...func(gen.Dao) gen.Dao) ITutorialDo {
+	return t.withDO(t.DO.Scopes(funcs...))
+}
+
+func (t tutorialDo) Unscoped() ITutorialDo {
+	return t.withDO(t.DO.Unscoped())
+}
+
+func (t tutorialDo) Create(values ...*model.Tutorial) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return t.DO.Create(values)
+}
+
+func (t tutorialDo) CreateInBatches(values []*model.Tutorial, batchSize int) error {
+	return t.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (t tutorialDo) Save(values ...*model.Tutorial) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return t.DO.Save(values)
+}
+
+func (t tutorialDo) First() (*model.Tutorial, error) {
+	if result, err := t.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Tutorial), nil
+	}
+}
+
+func (t tutorialDo) Take() (*model.Tutorial, error) {
+	if result, err := t.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Tutorial), nil
+	}
+}
+
+func (t tutorialDo) Last() (*model.Tutorial, error) {
+	if result, err := t.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Tutorial), nil
+	}
+}
+
+func (t tutorialDo) Find() ([]*model.Tutorial, error) {
+	result, err := t.DO.Find()
+	return result.([]*model.Tutorial), err
+}
+
+func (t tutorialDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Tutorial, err error) {
+	buf := make([]*model.Tutorial, 0, batchSize)
+	err = t.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (t tutorialDo) FindInBatches(result *[]*model.Tutorial, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return t.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (t tutorialDo) Attrs(attrs ...field.AssignExpr) ITutorialDo {
+	return t.withDO(t.DO.Attrs(attrs...))
+}
+
+func (t tutorialDo) Assign(attrs ...field.AssignExpr) ITutorialDo {
+	return t.withDO(t.DO.Assign(attrs...))
+}
+
+func (t tutorialDo) Joins(fields ...field.RelationField) ITutorialDo {
+	for _, _f := range fields {
+		t = *t.withDO(t.DO.Joins(_f))
+	}
+	return &t
+}
+
+func (t tutorialDo) Preload(fields ...field.RelationField) ITutorialDo {
+	for _, _f := range fields {
+		t = *t.withDO(t.DO.Preload(_f))
+	}
+	return &t
+}
+
+func (t tutorialDo) FirstOrInit() (*model.Tutorial, error) {
+	if result, err := t.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Tutorial), nil
+	}
+}
+
+func (t tutorialDo) FirstOrCreate() (*model.Tutorial, error) {
+	if result, err := t.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Tutorial), nil
+	}
+}
+
+func (t tutorialDo) FindByPage(offset int, limit int) (result []*model.Tutorial, count int64, err error) {
+	result, err = t.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = t.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (t tutorialDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = t.Count()
+	if err != nil {
+		return
+	}
+
+	err = t.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (t tutorialDo) Scan(result interface{}) (err error) {
+	return t.DO.Scan(result)
+}
+
+func (t tutorialDo) Delete(models ...*model.Tutorial) (result gen.ResultInfo, err error) {
+	return t.DO.Delete(models)
+}
+
+func (t *tutorialDo) withDO(do gen.Dao) *tutorialDo {
+	t.DO = *do.(*gen.DO)
+	return t
+}

+ 444 - 0
database/dao/wechat/query/usage_detail.gen.go

@@ -0,0 +1,444 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newUsageDetail(db *gorm.DB, opts ...gen.DOOption) usageDetail {
+	_usageDetail := usageDetail{}
+
+	_usageDetail.usageDetailDo.UseDB(db, opts...)
+	_usageDetail.usageDetailDo.UseModel(&model.UsageDetail{})
+
+	tableName := _usageDetail.usageDetailDo.TableName()
+	_usageDetail.ALL = field.NewAsterisk(tableName)
+	_usageDetail.ID = field.NewInt64(tableName, "id")
+	_usageDetail.CreatedAt = field.NewTime(tableName, "created_at")
+	_usageDetail.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_usageDetail.Status = field.NewInt64(tableName, "status")
+	_usageDetail.DeletedAt = field.NewField(tableName, "deleted_at")
+	_usageDetail.Type = field.NewInt64(tableName, "type")
+	_usageDetail.BotID = field.NewString(tableName, "bot_id")
+	_usageDetail.ReceiverID = field.NewString(tableName, "receiver_id")
+	_usageDetail.App = field.NewInt64(tableName, "app")
+	_usageDetail.SessionID = field.NewInt64(tableName, "session_id")
+	_usageDetail.Request = field.NewString(tableName, "request")
+	_usageDetail.Response = field.NewString(tableName, "response")
+	_usageDetail.OriginalData = field.NewString(tableName, "original_data")
+	_usageDetail.TotalTokens = field.NewInt64(tableName, "total_tokens")
+	_usageDetail.PromptTokens = field.NewInt64(tableName, "prompt_tokens")
+	_usageDetail.CompletionTokens = field.NewInt64(tableName, "completion_tokens")
+	_usageDetail.OrganizationID = field.NewInt64(tableName, "organization_id")
+
+	_usageDetail.fillFieldMap()
+
+	return _usageDetail
+}
+
+type usageDetail struct {
+	usageDetailDo
+
+	ALL              field.Asterisk
+	ID               field.Int64
+	CreatedAt        field.Time   // Create Time | 创建日期
+	UpdatedAt        field.Time   // Update Time | 修改日期
+	Status           field.Int64  // 状态 1 正常 2 禁用
+	DeletedAt        field.Field  // Delete Time | 删除日期
+	Type             field.Int64  // 1 微信 2 名片
+	BotID            field.String // 微信或名片id
+	ReceiverID       field.String // 微信id或open_id
+	App              field.Int64  // 1 cow-basic 2 cow-agent-优化 3 cow-agent 4 cow-sop-阶段 5cow-sop-节点 6 mp-card 7 mp-employee
+	SessionID        field.Int64  // 名片会话id
+	Request          field.String // 请求内容
+	Response         field.String // 响应内容
+	OriginalData     field.String // 原始数据
+	TotalTokens      field.Int64  // 使用token总数
+	PromptTokens     field.Int64  // 请求token数
+	CompletionTokens field.Int64  // 响应token数
+	OrganizationID   field.Int64  // 机构 ID
+
+	fieldMap map[string]field.Expr
+}
+
+func (u usageDetail) Table(newTableName string) *usageDetail {
+	u.usageDetailDo.UseTable(newTableName)
+	return u.updateTableName(newTableName)
+}
+
+func (u usageDetail) As(alias string) *usageDetail {
+	u.usageDetailDo.DO = *(u.usageDetailDo.As(alias).(*gen.DO))
+	return u.updateTableName(alias)
+}
+
+func (u *usageDetail) updateTableName(table string) *usageDetail {
+	u.ALL = field.NewAsterisk(table)
+	u.ID = field.NewInt64(table, "id")
+	u.CreatedAt = field.NewTime(table, "created_at")
+	u.UpdatedAt = field.NewTime(table, "updated_at")
+	u.Status = field.NewInt64(table, "status")
+	u.DeletedAt = field.NewField(table, "deleted_at")
+	u.Type = field.NewInt64(table, "type")
+	u.BotID = field.NewString(table, "bot_id")
+	u.ReceiverID = field.NewString(table, "receiver_id")
+	u.App = field.NewInt64(table, "app")
+	u.SessionID = field.NewInt64(table, "session_id")
+	u.Request = field.NewString(table, "request")
+	u.Response = field.NewString(table, "response")
+	u.OriginalData = field.NewString(table, "original_data")
+	u.TotalTokens = field.NewInt64(table, "total_tokens")
+	u.PromptTokens = field.NewInt64(table, "prompt_tokens")
+	u.CompletionTokens = field.NewInt64(table, "completion_tokens")
+	u.OrganizationID = field.NewInt64(table, "organization_id")
+
+	u.fillFieldMap()
+
+	return u
+}
+
+func (u *usageDetail) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := u.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (u *usageDetail) fillFieldMap() {
+	u.fieldMap = make(map[string]field.Expr, 17)
+	u.fieldMap["id"] = u.ID
+	u.fieldMap["created_at"] = u.CreatedAt
+	u.fieldMap["updated_at"] = u.UpdatedAt
+	u.fieldMap["status"] = u.Status
+	u.fieldMap["deleted_at"] = u.DeletedAt
+	u.fieldMap["type"] = u.Type
+	u.fieldMap["bot_id"] = u.BotID
+	u.fieldMap["receiver_id"] = u.ReceiverID
+	u.fieldMap["app"] = u.App
+	u.fieldMap["session_id"] = u.SessionID
+	u.fieldMap["request"] = u.Request
+	u.fieldMap["response"] = u.Response
+	u.fieldMap["original_data"] = u.OriginalData
+	u.fieldMap["total_tokens"] = u.TotalTokens
+	u.fieldMap["prompt_tokens"] = u.PromptTokens
+	u.fieldMap["completion_tokens"] = u.CompletionTokens
+	u.fieldMap["organization_id"] = u.OrganizationID
+}
+
+func (u usageDetail) clone(db *gorm.DB) usageDetail {
+	u.usageDetailDo.ReplaceConnPool(db.Statement.ConnPool)
+	return u
+}
+
+func (u usageDetail) replaceDB(db *gorm.DB) usageDetail {
+	u.usageDetailDo.ReplaceDB(db)
+	return u
+}
+
+type usageDetailDo struct{ gen.DO }
+
+type IUsageDetailDo interface {
+	gen.SubQuery
+	Debug() IUsageDetailDo
+	WithContext(ctx context.Context) IUsageDetailDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IUsageDetailDo
+	WriteDB() IUsageDetailDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IUsageDetailDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IUsageDetailDo
+	Not(conds ...gen.Condition) IUsageDetailDo
+	Or(conds ...gen.Condition) IUsageDetailDo
+	Select(conds ...field.Expr) IUsageDetailDo
+	Where(conds ...gen.Condition) IUsageDetailDo
+	Order(conds ...field.Expr) IUsageDetailDo
+	Distinct(cols ...field.Expr) IUsageDetailDo
+	Omit(cols ...field.Expr) IUsageDetailDo
+	Join(table schema.Tabler, on ...field.Expr) IUsageDetailDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IUsageDetailDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IUsageDetailDo
+	Group(cols ...field.Expr) IUsageDetailDo
+	Having(conds ...gen.Condition) IUsageDetailDo
+	Limit(limit int) IUsageDetailDo
+	Offset(offset int) IUsageDetailDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IUsageDetailDo
+	Unscoped() IUsageDetailDo
+	Create(values ...*model.UsageDetail) error
+	CreateInBatches(values []*model.UsageDetail, batchSize int) error
+	Save(values ...*model.UsageDetail) error
+	First() (*model.UsageDetail, error)
+	Take() (*model.UsageDetail, error)
+	Last() (*model.UsageDetail, error)
+	Find() ([]*model.UsageDetail, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.UsageDetail, err error)
+	FindInBatches(result *[]*model.UsageDetail, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.UsageDetail) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IUsageDetailDo
+	Assign(attrs ...field.AssignExpr) IUsageDetailDo
+	Joins(fields ...field.RelationField) IUsageDetailDo
+	Preload(fields ...field.RelationField) IUsageDetailDo
+	FirstOrInit() (*model.UsageDetail, error)
+	FirstOrCreate() (*model.UsageDetail, error)
+	FindByPage(offset int, limit int) (result []*model.UsageDetail, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IUsageDetailDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (u usageDetailDo) Debug() IUsageDetailDo {
+	return u.withDO(u.DO.Debug())
+}
+
+func (u usageDetailDo) WithContext(ctx context.Context) IUsageDetailDo {
+	return u.withDO(u.DO.WithContext(ctx))
+}
+
+func (u usageDetailDo) ReadDB() IUsageDetailDo {
+	return u.Clauses(dbresolver.Read)
+}
+
+func (u usageDetailDo) WriteDB() IUsageDetailDo {
+	return u.Clauses(dbresolver.Write)
+}
+
+func (u usageDetailDo) Session(config *gorm.Session) IUsageDetailDo {
+	return u.withDO(u.DO.Session(config))
+}
+
+func (u usageDetailDo) Clauses(conds ...clause.Expression) IUsageDetailDo {
+	return u.withDO(u.DO.Clauses(conds...))
+}
+
+func (u usageDetailDo) Returning(value interface{}, columns ...string) IUsageDetailDo {
+	return u.withDO(u.DO.Returning(value, columns...))
+}
+
+func (u usageDetailDo) Not(conds ...gen.Condition) IUsageDetailDo {
+	return u.withDO(u.DO.Not(conds...))
+}
+
+func (u usageDetailDo) Or(conds ...gen.Condition) IUsageDetailDo {
+	return u.withDO(u.DO.Or(conds...))
+}
+
+func (u usageDetailDo) Select(conds ...field.Expr) IUsageDetailDo {
+	return u.withDO(u.DO.Select(conds...))
+}
+
+func (u usageDetailDo) Where(conds ...gen.Condition) IUsageDetailDo {
+	return u.withDO(u.DO.Where(conds...))
+}
+
+func (u usageDetailDo) Order(conds ...field.Expr) IUsageDetailDo {
+	return u.withDO(u.DO.Order(conds...))
+}
+
+func (u usageDetailDo) Distinct(cols ...field.Expr) IUsageDetailDo {
+	return u.withDO(u.DO.Distinct(cols...))
+}
+
+func (u usageDetailDo) Omit(cols ...field.Expr) IUsageDetailDo {
+	return u.withDO(u.DO.Omit(cols...))
+}
+
+func (u usageDetailDo) Join(table schema.Tabler, on ...field.Expr) IUsageDetailDo {
+	return u.withDO(u.DO.Join(table, on...))
+}
+
+func (u usageDetailDo) LeftJoin(table schema.Tabler, on ...field.Expr) IUsageDetailDo {
+	return u.withDO(u.DO.LeftJoin(table, on...))
+}
+
+func (u usageDetailDo) RightJoin(table schema.Tabler, on ...field.Expr) IUsageDetailDo {
+	return u.withDO(u.DO.RightJoin(table, on...))
+}
+
+func (u usageDetailDo) Group(cols ...field.Expr) IUsageDetailDo {
+	return u.withDO(u.DO.Group(cols...))
+}
+
+func (u usageDetailDo) Having(conds ...gen.Condition) IUsageDetailDo {
+	return u.withDO(u.DO.Having(conds...))
+}
+
+func (u usageDetailDo) Limit(limit int) IUsageDetailDo {
+	return u.withDO(u.DO.Limit(limit))
+}
+
+func (u usageDetailDo) Offset(offset int) IUsageDetailDo {
+	return u.withDO(u.DO.Offset(offset))
+}
+
+func (u usageDetailDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IUsageDetailDo {
+	return u.withDO(u.DO.Scopes(funcs...))
+}
+
+func (u usageDetailDo) Unscoped() IUsageDetailDo {
+	return u.withDO(u.DO.Unscoped())
+}
+
+func (u usageDetailDo) Create(values ...*model.UsageDetail) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return u.DO.Create(values)
+}
+
+func (u usageDetailDo) CreateInBatches(values []*model.UsageDetail, batchSize int) error {
+	return u.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (u usageDetailDo) Save(values ...*model.UsageDetail) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return u.DO.Save(values)
+}
+
+func (u usageDetailDo) First() (*model.UsageDetail, error) {
+	if result, err := u.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageDetail), nil
+	}
+}
+
+func (u usageDetailDo) Take() (*model.UsageDetail, error) {
+	if result, err := u.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageDetail), nil
+	}
+}
+
+func (u usageDetailDo) Last() (*model.UsageDetail, error) {
+	if result, err := u.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageDetail), nil
+	}
+}
+
+func (u usageDetailDo) Find() ([]*model.UsageDetail, error) {
+	result, err := u.DO.Find()
+	return result.([]*model.UsageDetail), err
+}
+
+func (u usageDetailDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.UsageDetail, err error) {
+	buf := make([]*model.UsageDetail, 0, batchSize)
+	err = u.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (u usageDetailDo) FindInBatches(result *[]*model.UsageDetail, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return u.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (u usageDetailDo) Attrs(attrs ...field.AssignExpr) IUsageDetailDo {
+	return u.withDO(u.DO.Attrs(attrs...))
+}
+
+func (u usageDetailDo) Assign(attrs ...field.AssignExpr) IUsageDetailDo {
+	return u.withDO(u.DO.Assign(attrs...))
+}
+
+func (u usageDetailDo) Joins(fields ...field.RelationField) IUsageDetailDo {
+	for _, _f := range fields {
+		u = *u.withDO(u.DO.Joins(_f))
+	}
+	return &u
+}
+
+func (u usageDetailDo) Preload(fields ...field.RelationField) IUsageDetailDo {
+	for _, _f := range fields {
+		u = *u.withDO(u.DO.Preload(_f))
+	}
+	return &u
+}
+
+func (u usageDetailDo) FirstOrInit() (*model.UsageDetail, error) {
+	if result, err := u.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageDetail), nil
+	}
+}
+
+func (u usageDetailDo) FirstOrCreate() (*model.UsageDetail, error) {
+	if result, err := u.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageDetail), nil
+	}
+}
+
+func (u usageDetailDo) FindByPage(offset int, limit int) (result []*model.UsageDetail, count int64, err error) {
+	result, err = u.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = u.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (u usageDetailDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = u.Count()
+	if err != nil {
+		return
+	}
+
+	err = u.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (u usageDetailDo) Scan(result interface{}) (err error) {
+	return u.DO.Scan(result)
+}
+
+func (u usageDetailDo) Delete(models ...*model.UsageDetail) (result gen.ResultInfo, err error) {
+	return u.DO.Delete(models)
+}
+
+func (u *usageDetailDo) withDO(do gen.Dao) *usageDetailDo {
+	u.DO = *do.(*gen.DO)
+	return u
+}

+ 448 - 0
database/dao/wechat/query/usage_statistic_day.gen.go

@@ -0,0 +1,448 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newUsageStatisticDay(db *gorm.DB, opts ...gen.DOOption) usageStatisticDay {
+	_usageStatisticDay := usageStatisticDay{}
+
+	_usageStatisticDay.usageStatisticDayDo.UseDB(db, opts...)
+	_usageStatisticDay.usageStatisticDayDo.UseModel(&model.UsageStatisticDay{})
+
+	tableName := _usageStatisticDay.usageStatisticDayDo.TableName()
+	_usageStatisticDay.ALL = field.NewAsterisk(tableName)
+	_usageStatisticDay.ID = field.NewInt64(tableName, "id")
+	_usageStatisticDay.CreatedAt = field.NewTime(tableName, "created_at")
+	_usageStatisticDay.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_usageStatisticDay.Status = field.NewInt64(tableName, "status")
+	_usageStatisticDay.DeletedAt = field.NewField(tableName, "deleted_at")
+	_usageStatisticDay.Addtime = field.NewInt64(tableName, "addtime")
+	_usageStatisticDay.Type = field.NewInt64(tableName, "type")
+	_usageStatisticDay.BotID = field.NewString(tableName, "bot_id")
+	_usageStatisticDay.OrganizationID = field.NewInt64(tableName, "organization_id")
+	_usageStatisticDay.AiResponse = field.NewInt64(tableName, "ai_response")
+	_usageStatisticDay.SopRun = field.NewInt64(tableName, "sop_run")
+	_usageStatisticDay.TotalFriend = field.NewInt64(tableName, "total_friend")
+	_usageStatisticDay.TotalGroup = field.NewInt64(tableName, "total_group")
+	_usageStatisticDay.AccountBalance = field.NewInt64(tableName, "account_balance")
+	_usageStatisticDay.ConsumeToken = field.NewInt64(tableName, "consume_token")
+	_usageStatisticDay.ActiveUser = field.NewInt64(tableName, "active_user")
+	_usageStatisticDay.NewUser = field.NewInt64(tableName, "new_user")
+	_usageStatisticDay.LabelDist = field.NewString(tableName, "label_dist")
+
+	_usageStatisticDay.fillFieldMap()
+
+	return _usageStatisticDay
+}
+
+type usageStatisticDay struct {
+	usageStatisticDayDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	Status         field.Int64  // 状态 1 正常 2 禁用
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	Addtime        field.Int64  // 写入年月日
+	Type           field.Int64  // 1-微信 2-名片
+	BotID          field.String // 微信或名片id
+	OrganizationID field.Int64  // 机构 ID
+	AiResponse     field.Int64  // AI回复次数
+	SopRun         field.Int64  // SOP运行次数
+	TotalFriend    field.Int64  // 好友总数
+	TotalGroup     field.Int64  // 群总数
+	AccountBalance field.Int64  // 账户余额(单位:分)
+	ConsumeToken   field.Int64  // 消耗token数
+	ActiveUser     field.Int64  // 活跃用户数
+	NewUser        field.Int64  // 新增用户数
+	LabelDist      field.String // 标签分布
+
+	fieldMap map[string]field.Expr
+}
+
+func (u usageStatisticDay) Table(newTableName string) *usageStatisticDay {
+	u.usageStatisticDayDo.UseTable(newTableName)
+	return u.updateTableName(newTableName)
+}
+
+func (u usageStatisticDay) As(alias string) *usageStatisticDay {
+	u.usageStatisticDayDo.DO = *(u.usageStatisticDayDo.As(alias).(*gen.DO))
+	return u.updateTableName(alias)
+}
+
+func (u *usageStatisticDay) updateTableName(table string) *usageStatisticDay {
+	u.ALL = field.NewAsterisk(table)
+	u.ID = field.NewInt64(table, "id")
+	u.CreatedAt = field.NewTime(table, "created_at")
+	u.UpdatedAt = field.NewTime(table, "updated_at")
+	u.Status = field.NewInt64(table, "status")
+	u.DeletedAt = field.NewField(table, "deleted_at")
+	u.Addtime = field.NewInt64(table, "addtime")
+	u.Type = field.NewInt64(table, "type")
+	u.BotID = field.NewString(table, "bot_id")
+	u.OrganizationID = field.NewInt64(table, "organization_id")
+	u.AiResponse = field.NewInt64(table, "ai_response")
+	u.SopRun = field.NewInt64(table, "sop_run")
+	u.TotalFriend = field.NewInt64(table, "total_friend")
+	u.TotalGroup = field.NewInt64(table, "total_group")
+	u.AccountBalance = field.NewInt64(table, "account_balance")
+	u.ConsumeToken = field.NewInt64(table, "consume_token")
+	u.ActiveUser = field.NewInt64(table, "active_user")
+	u.NewUser = field.NewInt64(table, "new_user")
+	u.LabelDist = field.NewString(table, "label_dist")
+
+	u.fillFieldMap()
+
+	return u
+}
+
+func (u *usageStatisticDay) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := u.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (u *usageStatisticDay) fillFieldMap() {
+	u.fieldMap = make(map[string]field.Expr, 18)
+	u.fieldMap["id"] = u.ID
+	u.fieldMap["created_at"] = u.CreatedAt
+	u.fieldMap["updated_at"] = u.UpdatedAt
+	u.fieldMap["status"] = u.Status
+	u.fieldMap["deleted_at"] = u.DeletedAt
+	u.fieldMap["addtime"] = u.Addtime
+	u.fieldMap["type"] = u.Type
+	u.fieldMap["bot_id"] = u.BotID
+	u.fieldMap["organization_id"] = u.OrganizationID
+	u.fieldMap["ai_response"] = u.AiResponse
+	u.fieldMap["sop_run"] = u.SopRun
+	u.fieldMap["total_friend"] = u.TotalFriend
+	u.fieldMap["total_group"] = u.TotalGroup
+	u.fieldMap["account_balance"] = u.AccountBalance
+	u.fieldMap["consume_token"] = u.ConsumeToken
+	u.fieldMap["active_user"] = u.ActiveUser
+	u.fieldMap["new_user"] = u.NewUser
+	u.fieldMap["label_dist"] = u.LabelDist
+}
+
+func (u usageStatisticDay) clone(db *gorm.DB) usageStatisticDay {
+	u.usageStatisticDayDo.ReplaceConnPool(db.Statement.ConnPool)
+	return u
+}
+
+func (u usageStatisticDay) replaceDB(db *gorm.DB) usageStatisticDay {
+	u.usageStatisticDayDo.ReplaceDB(db)
+	return u
+}
+
+type usageStatisticDayDo struct{ gen.DO }
+
+type IUsageStatisticDayDo interface {
+	gen.SubQuery
+	Debug() IUsageStatisticDayDo
+	WithContext(ctx context.Context) IUsageStatisticDayDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IUsageStatisticDayDo
+	WriteDB() IUsageStatisticDayDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IUsageStatisticDayDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IUsageStatisticDayDo
+	Not(conds ...gen.Condition) IUsageStatisticDayDo
+	Or(conds ...gen.Condition) IUsageStatisticDayDo
+	Select(conds ...field.Expr) IUsageStatisticDayDo
+	Where(conds ...gen.Condition) IUsageStatisticDayDo
+	Order(conds ...field.Expr) IUsageStatisticDayDo
+	Distinct(cols ...field.Expr) IUsageStatisticDayDo
+	Omit(cols ...field.Expr) IUsageStatisticDayDo
+	Join(table schema.Tabler, on ...field.Expr) IUsageStatisticDayDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IUsageStatisticDayDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IUsageStatisticDayDo
+	Group(cols ...field.Expr) IUsageStatisticDayDo
+	Having(conds ...gen.Condition) IUsageStatisticDayDo
+	Limit(limit int) IUsageStatisticDayDo
+	Offset(offset int) IUsageStatisticDayDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IUsageStatisticDayDo
+	Unscoped() IUsageStatisticDayDo
+	Create(values ...*model.UsageStatisticDay) error
+	CreateInBatches(values []*model.UsageStatisticDay, batchSize int) error
+	Save(values ...*model.UsageStatisticDay) error
+	First() (*model.UsageStatisticDay, error)
+	Take() (*model.UsageStatisticDay, error)
+	Last() (*model.UsageStatisticDay, error)
+	Find() ([]*model.UsageStatisticDay, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.UsageStatisticDay, err error)
+	FindInBatches(result *[]*model.UsageStatisticDay, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.UsageStatisticDay) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IUsageStatisticDayDo
+	Assign(attrs ...field.AssignExpr) IUsageStatisticDayDo
+	Joins(fields ...field.RelationField) IUsageStatisticDayDo
+	Preload(fields ...field.RelationField) IUsageStatisticDayDo
+	FirstOrInit() (*model.UsageStatisticDay, error)
+	FirstOrCreate() (*model.UsageStatisticDay, error)
+	FindByPage(offset int, limit int) (result []*model.UsageStatisticDay, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IUsageStatisticDayDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (u usageStatisticDayDo) Debug() IUsageStatisticDayDo {
+	return u.withDO(u.DO.Debug())
+}
+
+func (u usageStatisticDayDo) WithContext(ctx context.Context) IUsageStatisticDayDo {
+	return u.withDO(u.DO.WithContext(ctx))
+}
+
+func (u usageStatisticDayDo) ReadDB() IUsageStatisticDayDo {
+	return u.Clauses(dbresolver.Read)
+}
+
+func (u usageStatisticDayDo) WriteDB() IUsageStatisticDayDo {
+	return u.Clauses(dbresolver.Write)
+}
+
+func (u usageStatisticDayDo) Session(config *gorm.Session) IUsageStatisticDayDo {
+	return u.withDO(u.DO.Session(config))
+}
+
+func (u usageStatisticDayDo) Clauses(conds ...clause.Expression) IUsageStatisticDayDo {
+	return u.withDO(u.DO.Clauses(conds...))
+}
+
+func (u usageStatisticDayDo) Returning(value interface{}, columns ...string) IUsageStatisticDayDo {
+	return u.withDO(u.DO.Returning(value, columns...))
+}
+
+func (u usageStatisticDayDo) Not(conds ...gen.Condition) IUsageStatisticDayDo {
+	return u.withDO(u.DO.Not(conds...))
+}
+
+func (u usageStatisticDayDo) Or(conds ...gen.Condition) IUsageStatisticDayDo {
+	return u.withDO(u.DO.Or(conds...))
+}
+
+func (u usageStatisticDayDo) Select(conds ...field.Expr) IUsageStatisticDayDo {
+	return u.withDO(u.DO.Select(conds...))
+}
+
+func (u usageStatisticDayDo) Where(conds ...gen.Condition) IUsageStatisticDayDo {
+	return u.withDO(u.DO.Where(conds...))
+}
+
+func (u usageStatisticDayDo) Order(conds ...field.Expr) IUsageStatisticDayDo {
+	return u.withDO(u.DO.Order(conds...))
+}
+
+func (u usageStatisticDayDo) Distinct(cols ...field.Expr) IUsageStatisticDayDo {
+	return u.withDO(u.DO.Distinct(cols...))
+}
+
+func (u usageStatisticDayDo) Omit(cols ...field.Expr) IUsageStatisticDayDo {
+	return u.withDO(u.DO.Omit(cols...))
+}
+
+func (u usageStatisticDayDo) Join(table schema.Tabler, on ...field.Expr) IUsageStatisticDayDo {
+	return u.withDO(u.DO.Join(table, on...))
+}
+
+func (u usageStatisticDayDo) LeftJoin(table schema.Tabler, on ...field.Expr) IUsageStatisticDayDo {
+	return u.withDO(u.DO.LeftJoin(table, on...))
+}
+
+func (u usageStatisticDayDo) RightJoin(table schema.Tabler, on ...field.Expr) IUsageStatisticDayDo {
+	return u.withDO(u.DO.RightJoin(table, on...))
+}
+
+func (u usageStatisticDayDo) Group(cols ...field.Expr) IUsageStatisticDayDo {
+	return u.withDO(u.DO.Group(cols...))
+}
+
+func (u usageStatisticDayDo) Having(conds ...gen.Condition) IUsageStatisticDayDo {
+	return u.withDO(u.DO.Having(conds...))
+}
+
+func (u usageStatisticDayDo) Limit(limit int) IUsageStatisticDayDo {
+	return u.withDO(u.DO.Limit(limit))
+}
+
+func (u usageStatisticDayDo) Offset(offset int) IUsageStatisticDayDo {
+	return u.withDO(u.DO.Offset(offset))
+}
+
+func (u usageStatisticDayDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IUsageStatisticDayDo {
+	return u.withDO(u.DO.Scopes(funcs...))
+}
+
+func (u usageStatisticDayDo) Unscoped() IUsageStatisticDayDo {
+	return u.withDO(u.DO.Unscoped())
+}
+
+func (u usageStatisticDayDo) Create(values ...*model.UsageStatisticDay) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return u.DO.Create(values)
+}
+
+func (u usageStatisticDayDo) CreateInBatches(values []*model.UsageStatisticDay, batchSize int) error {
+	return u.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (u usageStatisticDayDo) Save(values ...*model.UsageStatisticDay) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return u.DO.Save(values)
+}
+
+func (u usageStatisticDayDo) First() (*model.UsageStatisticDay, error) {
+	if result, err := u.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageStatisticDay), nil
+	}
+}
+
+func (u usageStatisticDayDo) Take() (*model.UsageStatisticDay, error) {
+	if result, err := u.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageStatisticDay), nil
+	}
+}
+
+func (u usageStatisticDayDo) Last() (*model.UsageStatisticDay, error) {
+	if result, err := u.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageStatisticDay), nil
+	}
+}
+
+func (u usageStatisticDayDo) Find() ([]*model.UsageStatisticDay, error) {
+	result, err := u.DO.Find()
+	return result.([]*model.UsageStatisticDay), err
+}
+
+func (u usageStatisticDayDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.UsageStatisticDay, err error) {
+	buf := make([]*model.UsageStatisticDay, 0, batchSize)
+	err = u.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (u usageStatisticDayDo) FindInBatches(result *[]*model.UsageStatisticDay, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return u.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (u usageStatisticDayDo) Attrs(attrs ...field.AssignExpr) IUsageStatisticDayDo {
+	return u.withDO(u.DO.Attrs(attrs...))
+}
+
+func (u usageStatisticDayDo) Assign(attrs ...field.AssignExpr) IUsageStatisticDayDo {
+	return u.withDO(u.DO.Assign(attrs...))
+}
+
+func (u usageStatisticDayDo) Joins(fields ...field.RelationField) IUsageStatisticDayDo {
+	for _, _f := range fields {
+		u = *u.withDO(u.DO.Joins(_f))
+	}
+	return &u
+}
+
+func (u usageStatisticDayDo) Preload(fields ...field.RelationField) IUsageStatisticDayDo {
+	for _, _f := range fields {
+		u = *u.withDO(u.DO.Preload(_f))
+	}
+	return &u
+}
+
+func (u usageStatisticDayDo) FirstOrInit() (*model.UsageStatisticDay, error) {
+	if result, err := u.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageStatisticDay), nil
+	}
+}
+
+func (u usageStatisticDayDo) FirstOrCreate() (*model.UsageStatisticDay, error) {
+	if result, err := u.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageStatisticDay), nil
+	}
+}
+
+func (u usageStatisticDayDo) FindByPage(offset int, limit int) (result []*model.UsageStatisticDay, count int64, err error) {
+	result, err = u.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = u.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (u usageStatisticDayDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = u.Count()
+	if err != nil {
+		return
+	}
+
+	err = u.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (u usageStatisticDayDo) Scan(result interface{}) (err error) {
+	return u.DO.Scan(result)
+}
+
+func (u usageStatisticDayDo) Delete(models ...*model.UsageStatisticDay) (result gen.ResultInfo, err error) {
+	return u.DO.Delete(models)
+}
+
+func (u *usageStatisticDayDo) withDO(do gen.Dao) *usageStatisticDayDo {
+	u.DO = *do.(*gen.DO)
+	return u
+}

+ 448 - 0
database/dao/wechat/query/usage_statistic_hour.gen.go

@@ -0,0 +1,448 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newUsageStatisticHour(db *gorm.DB, opts ...gen.DOOption) usageStatisticHour {
+	_usageStatisticHour := usageStatisticHour{}
+
+	_usageStatisticHour.usageStatisticHourDo.UseDB(db, opts...)
+	_usageStatisticHour.usageStatisticHourDo.UseModel(&model.UsageStatisticHour{})
+
+	tableName := _usageStatisticHour.usageStatisticHourDo.TableName()
+	_usageStatisticHour.ALL = field.NewAsterisk(tableName)
+	_usageStatisticHour.ID = field.NewInt64(tableName, "id")
+	_usageStatisticHour.CreatedAt = field.NewTime(tableName, "created_at")
+	_usageStatisticHour.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_usageStatisticHour.Status = field.NewInt64(tableName, "status")
+	_usageStatisticHour.DeletedAt = field.NewField(tableName, "deleted_at")
+	_usageStatisticHour.Addtime = field.NewInt64(tableName, "addtime")
+	_usageStatisticHour.Type = field.NewInt64(tableName, "type")
+	_usageStatisticHour.BotID = field.NewString(tableName, "bot_id")
+	_usageStatisticHour.OrganizationID = field.NewInt64(tableName, "organization_id")
+	_usageStatisticHour.AiResponse = field.NewInt64(tableName, "ai_response")
+	_usageStatisticHour.SopRun = field.NewInt64(tableName, "sop_run")
+	_usageStatisticHour.TotalFriend = field.NewInt64(tableName, "total_friend")
+	_usageStatisticHour.TotalGroup = field.NewInt64(tableName, "total_group")
+	_usageStatisticHour.AccountBalance = field.NewInt64(tableName, "account_balance")
+	_usageStatisticHour.ConsumeToken = field.NewInt64(tableName, "consume_token")
+	_usageStatisticHour.ActiveUser = field.NewInt64(tableName, "active_user")
+	_usageStatisticHour.NewUser = field.NewInt64(tableName, "new_user")
+	_usageStatisticHour.LabelDist = field.NewString(tableName, "label_dist")
+
+	_usageStatisticHour.fillFieldMap()
+
+	return _usageStatisticHour
+}
+
+type usageStatisticHour struct {
+	usageStatisticHourDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	Status         field.Int64  // 状态 1 正常 2 禁用
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	Addtime        field.Int64  // 写入小时
+	Type           field.Int64  // 1-微信 2-名片
+	BotID          field.String // 微信或名片id
+	OrganizationID field.Int64  // 机构 ID
+	AiResponse     field.Int64  // AI回复次数
+	SopRun         field.Int64  // SOP运行次数
+	TotalFriend    field.Int64  // 好友总数
+	TotalGroup     field.Int64  // 群总数
+	AccountBalance field.Int64  // 账户余额(单位:分)
+	ConsumeToken   field.Int64  // 消耗token数
+	ActiveUser     field.Int64  // 活跃用户数
+	NewUser        field.Int64  // 新增用户数
+	LabelDist      field.String // 标签分布
+
+	fieldMap map[string]field.Expr
+}
+
+func (u usageStatisticHour) Table(newTableName string) *usageStatisticHour {
+	u.usageStatisticHourDo.UseTable(newTableName)
+	return u.updateTableName(newTableName)
+}
+
+func (u usageStatisticHour) As(alias string) *usageStatisticHour {
+	u.usageStatisticHourDo.DO = *(u.usageStatisticHourDo.As(alias).(*gen.DO))
+	return u.updateTableName(alias)
+}
+
+func (u *usageStatisticHour) updateTableName(table string) *usageStatisticHour {
+	u.ALL = field.NewAsterisk(table)
+	u.ID = field.NewInt64(table, "id")
+	u.CreatedAt = field.NewTime(table, "created_at")
+	u.UpdatedAt = field.NewTime(table, "updated_at")
+	u.Status = field.NewInt64(table, "status")
+	u.DeletedAt = field.NewField(table, "deleted_at")
+	u.Addtime = field.NewInt64(table, "addtime")
+	u.Type = field.NewInt64(table, "type")
+	u.BotID = field.NewString(table, "bot_id")
+	u.OrganizationID = field.NewInt64(table, "organization_id")
+	u.AiResponse = field.NewInt64(table, "ai_response")
+	u.SopRun = field.NewInt64(table, "sop_run")
+	u.TotalFriend = field.NewInt64(table, "total_friend")
+	u.TotalGroup = field.NewInt64(table, "total_group")
+	u.AccountBalance = field.NewInt64(table, "account_balance")
+	u.ConsumeToken = field.NewInt64(table, "consume_token")
+	u.ActiveUser = field.NewInt64(table, "active_user")
+	u.NewUser = field.NewInt64(table, "new_user")
+	u.LabelDist = field.NewString(table, "label_dist")
+
+	u.fillFieldMap()
+
+	return u
+}
+
+func (u *usageStatisticHour) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := u.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (u *usageStatisticHour) fillFieldMap() {
+	u.fieldMap = make(map[string]field.Expr, 18)
+	u.fieldMap["id"] = u.ID
+	u.fieldMap["created_at"] = u.CreatedAt
+	u.fieldMap["updated_at"] = u.UpdatedAt
+	u.fieldMap["status"] = u.Status
+	u.fieldMap["deleted_at"] = u.DeletedAt
+	u.fieldMap["addtime"] = u.Addtime
+	u.fieldMap["type"] = u.Type
+	u.fieldMap["bot_id"] = u.BotID
+	u.fieldMap["organization_id"] = u.OrganizationID
+	u.fieldMap["ai_response"] = u.AiResponse
+	u.fieldMap["sop_run"] = u.SopRun
+	u.fieldMap["total_friend"] = u.TotalFriend
+	u.fieldMap["total_group"] = u.TotalGroup
+	u.fieldMap["account_balance"] = u.AccountBalance
+	u.fieldMap["consume_token"] = u.ConsumeToken
+	u.fieldMap["active_user"] = u.ActiveUser
+	u.fieldMap["new_user"] = u.NewUser
+	u.fieldMap["label_dist"] = u.LabelDist
+}
+
+func (u usageStatisticHour) clone(db *gorm.DB) usageStatisticHour {
+	u.usageStatisticHourDo.ReplaceConnPool(db.Statement.ConnPool)
+	return u
+}
+
+func (u usageStatisticHour) replaceDB(db *gorm.DB) usageStatisticHour {
+	u.usageStatisticHourDo.ReplaceDB(db)
+	return u
+}
+
+type usageStatisticHourDo struct{ gen.DO }
+
+type IUsageStatisticHourDo interface {
+	gen.SubQuery
+	Debug() IUsageStatisticHourDo
+	WithContext(ctx context.Context) IUsageStatisticHourDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IUsageStatisticHourDo
+	WriteDB() IUsageStatisticHourDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IUsageStatisticHourDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IUsageStatisticHourDo
+	Not(conds ...gen.Condition) IUsageStatisticHourDo
+	Or(conds ...gen.Condition) IUsageStatisticHourDo
+	Select(conds ...field.Expr) IUsageStatisticHourDo
+	Where(conds ...gen.Condition) IUsageStatisticHourDo
+	Order(conds ...field.Expr) IUsageStatisticHourDo
+	Distinct(cols ...field.Expr) IUsageStatisticHourDo
+	Omit(cols ...field.Expr) IUsageStatisticHourDo
+	Join(table schema.Tabler, on ...field.Expr) IUsageStatisticHourDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IUsageStatisticHourDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IUsageStatisticHourDo
+	Group(cols ...field.Expr) IUsageStatisticHourDo
+	Having(conds ...gen.Condition) IUsageStatisticHourDo
+	Limit(limit int) IUsageStatisticHourDo
+	Offset(offset int) IUsageStatisticHourDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IUsageStatisticHourDo
+	Unscoped() IUsageStatisticHourDo
+	Create(values ...*model.UsageStatisticHour) error
+	CreateInBatches(values []*model.UsageStatisticHour, batchSize int) error
+	Save(values ...*model.UsageStatisticHour) error
+	First() (*model.UsageStatisticHour, error)
+	Take() (*model.UsageStatisticHour, error)
+	Last() (*model.UsageStatisticHour, error)
+	Find() ([]*model.UsageStatisticHour, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.UsageStatisticHour, err error)
+	FindInBatches(result *[]*model.UsageStatisticHour, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.UsageStatisticHour) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IUsageStatisticHourDo
+	Assign(attrs ...field.AssignExpr) IUsageStatisticHourDo
+	Joins(fields ...field.RelationField) IUsageStatisticHourDo
+	Preload(fields ...field.RelationField) IUsageStatisticHourDo
+	FirstOrInit() (*model.UsageStatisticHour, error)
+	FirstOrCreate() (*model.UsageStatisticHour, error)
+	FindByPage(offset int, limit int) (result []*model.UsageStatisticHour, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IUsageStatisticHourDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (u usageStatisticHourDo) Debug() IUsageStatisticHourDo {
+	return u.withDO(u.DO.Debug())
+}
+
+func (u usageStatisticHourDo) WithContext(ctx context.Context) IUsageStatisticHourDo {
+	return u.withDO(u.DO.WithContext(ctx))
+}
+
+func (u usageStatisticHourDo) ReadDB() IUsageStatisticHourDo {
+	return u.Clauses(dbresolver.Read)
+}
+
+func (u usageStatisticHourDo) WriteDB() IUsageStatisticHourDo {
+	return u.Clauses(dbresolver.Write)
+}
+
+func (u usageStatisticHourDo) Session(config *gorm.Session) IUsageStatisticHourDo {
+	return u.withDO(u.DO.Session(config))
+}
+
+func (u usageStatisticHourDo) Clauses(conds ...clause.Expression) IUsageStatisticHourDo {
+	return u.withDO(u.DO.Clauses(conds...))
+}
+
+func (u usageStatisticHourDo) Returning(value interface{}, columns ...string) IUsageStatisticHourDo {
+	return u.withDO(u.DO.Returning(value, columns...))
+}
+
+func (u usageStatisticHourDo) Not(conds ...gen.Condition) IUsageStatisticHourDo {
+	return u.withDO(u.DO.Not(conds...))
+}
+
+func (u usageStatisticHourDo) Or(conds ...gen.Condition) IUsageStatisticHourDo {
+	return u.withDO(u.DO.Or(conds...))
+}
+
+func (u usageStatisticHourDo) Select(conds ...field.Expr) IUsageStatisticHourDo {
+	return u.withDO(u.DO.Select(conds...))
+}
+
+func (u usageStatisticHourDo) Where(conds ...gen.Condition) IUsageStatisticHourDo {
+	return u.withDO(u.DO.Where(conds...))
+}
+
+func (u usageStatisticHourDo) Order(conds ...field.Expr) IUsageStatisticHourDo {
+	return u.withDO(u.DO.Order(conds...))
+}
+
+func (u usageStatisticHourDo) Distinct(cols ...field.Expr) IUsageStatisticHourDo {
+	return u.withDO(u.DO.Distinct(cols...))
+}
+
+func (u usageStatisticHourDo) Omit(cols ...field.Expr) IUsageStatisticHourDo {
+	return u.withDO(u.DO.Omit(cols...))
+}
+
+func (u usageStatisticHourDo) Join(table schema.Tabler, on ...field.Expr) IUsageStatisticHourDo {
+	return u.withDO(u.DO.Join(table, on...))
+}
+
+func (u usageStatisticHourDo) LeftJoin(table schema.Tabler, on ...field.Expr) IUsageStatisticHourDo {
+	return u.withDO(u.DO.LeftJoin(table, on...))
+}
+
+func (u usageStatisticHourDo) RightJoin(table schema.Tabler, on ...field.Expr) IUsageStatisticHourDo {
+	return u.withDO(u.DO.RightJoin(table, on...))
+}
+
+func (u usageStatisticHourDo) Group(cols ...field.Expr) IUsageStatisticHourDo {
+	return u.withDO(u.DO.Group(cols...))
+}
+
+func (u usageStatisticHourDo) Having(conds ...gen.Condition) IUsageStatisticHourDo {
+	return u.withDO(u.DO.Having(conds...))
+}
+
+func (u usageStatisticHourDo) Limit(limit int) IUsageStatisticHourDo {
+	return u.withDO(u.DO.Limit(limit))
+}
+
+func (u usageStatisticHourDo) Offset(offset int) IUsageStatisticHourDo {
+	return u.withDO(u.DO.Offset(offset))
+}
+
+func (u usageStatisticHourDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IUsageStatisticHourDo {
+	return u.withDO(u.DO.Scopes(funcs...))
+}
+
+func (u usageStatisticHourDo) Unscoped() IUsageStatisticHourDo {
+	return u.withDO(u.DO.Unscoped())
+}
+
+func (u usageStatisticHourDo) Create(values ...*model.UsageStatisticHour) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return u.DO.Create(values)
+}
+
+func (u usageStatisticHourDo) CreateInBatches(values []*model.UsageStatisticHour, batchSize int) error {
+	return u.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (u usageStatisticHourDo) Save(values ...*model.UsageStatisticHour) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return u.DO.Save(values)
+}
+
+func (u usageStatisticHourDo) First() (*model.UsageStatisticHour, error) {
+	if result, err := u.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageStatisticHour), nil
+	}
+}
+
+func (u usageStatisticHourDo) Take() (*model.UsageStatisticHour, error) {
+	if result, err := u.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageStatisticHour), nil
+	}
+}
+
+func (u usageStatisticHourDo) Last() (*model.UsageStatisticHour, error) {
+	if result, err := u.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageStatisticHour), nil
+	}
+}
+
+func (u usageStatisticHourDo) Find() ([]*model.UsageStatisticHour, error) {
+	result, err := u.DO.Find()
+	return result.([]*model.UsageStatisticHour), err
+}
+
+func (u usageStatisticHourDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.UsageStatisticHour, err error) {
+	buf := make([]*model.UsageStatisticHour, 0, batchSize)
+	err = u.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (u usageStatisticHourDo) FindInBatches(result *[]*model.UsageStatisticHour, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return u.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (u usageStatisticHourDo) Attrs(attrs ...field.AssignExpr) IUsageStatisticHourDo {
+	return u.withDO(u.DO.Attrs(attrs...))
+}
+
+func (u usageStatisticHourDo) Assign(attrs ...field.AssignExpr) IUsageStatisticHourDo {
+	return u.withDO(u.DO.Assign(attrs...))
+}
+
+func (u usageStatisticHourDo) Joins(fields ...field.RelationField) IUsageStatisticHourDo {
+	for _, _f := range fields {
+		u = *u.withDO(u.DO.Joins(_f))
+	}
+	return &u
+}
+
+func (u usageStatisticHourDo) Preload(fields ...field.RelationField) IUsageStatisticHourDo {
+	for _, _f := range fields {
+		u = *u.withDO(u.DO.Preload(_f))
+	}
+	return &u
+}
+
+func (u usageStatisticHourDo) FirstOrInit() (*model.UsageStatisticHour, error) {
+	if result, err := u.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageStatisticHour), nil
+	}
+}
+
+func (u usageStatisticHourDo) FirstOrCreate() (*model.UsageStatisticHour, error) {
+	if result, err := u.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageStatisticHour), nil
+	}
+}
+
+func (u usageStatisticHourDo) FindByPage(offset int, limit int) (result []*model.UsageStatisticHour, count int64, err error) {
+	result, err = u.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = u.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (u usageStatisticHourDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = u.Count()
+	if err != nil {
+		return
+	}
+
+	err = u.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (u usageStatisticHourDo) Scan(result interface{}) (err error) {
+	return u.DO.Scan(result)
+}
+
+func (u usageStatisticHourDo) Delete(models ...*model.UsageStatisticHour) (result gen.ResultInfo, err error) {
+	return u.DO.Delete(models)
+}
+
+func (u *usageStatisticHourDo) withDO(do gen.Dao) *usageStatisticHourDo {
+	u.DO = *do.(*gen.DO)
+	return u
+}

+ 448 - 0
database/dao/wechat/query/usage_statistic_month.gen.go

@@ -0,0 +1,448 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newUsageStatisticMonth(db *gorm.DB, opts ...gen.DOOption) usageStatisticMonth {
+	_usageStatisticMonth := usageStatisticMonth{}
+
+	_usageStatisticMonth.usageStatisticMonthDo.UseDB(db, opts...)
+	_usageStatisticMonth.usageStatisticMonthDo.UseModel(&model.UsageStatisticMonth{})
+
+	tableName := _usageStatisticMonth.usageStatisticMonthDo.TableName()
+	_usageStatisticMonth.ALL = field.NewAsterisk(tableName)
+	_usageStatisticMonth.ID = field.NewInt64(tableName, "id")
+	_usageStatisticMonth.CreatedAt = field.NewTime(tableName, "created_at")
+	_usageStatisticMonth.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_usageStatisticMonth.Status = field.NewInt64(tableName, "status")
+	_usageStatisticMonth.DeletedAt = field.NewField(tableName, "deleted_at")
+	_usageStatisticMonth.Addtime = field.NewInt64(tableName, "addtime")
+	_usageStatisticMonth.Type = field.NewInt64(tableName, "type")
+	_usageStatisticMonth.BotID = field.NewString(tableName, "bot_id")
+	_usageStatisticMonth.OrganizationID = field.NewInt64(tableName, "organization_id")
+	_usageStatisticMonth.AiResponse = field.NewInt64(tableName, "ai_response")
+	_usageStatisticMonth.SopRun = field.NewInt64(tableName, "sop_run")
+	_usageStatisticMonth.TotalFriend = field.NewInt64(tableName, "total_friend")
+	_usageStatisticMonth.TotalGroup = field.NewInt64(tableName, "total_group")
+	_usageStatisticMonth.AccountBalance = field.NewInt64(tableName, "account_balance")
+	_usageStatisticMonth.ConsumeToken = field.NewInt64(tableName, "consume_token")
+	_usageStatisticMonth.ActiveUser = field.NewInt64(tableName, "active_user")
+	_usageStatisticMonth.NewUser = field.NewInt64(tableName, "new_user")
+	_usageStatisticMonth.LabelDist = field.NewString(tableName, "label_dist")
+
+	_usageStatisticMonth.fillFieldMap()
+
+	return _usageStatisticMonth
+}
+
+type usageStatisticMonth struct {
+	usageStatisticMonthDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	Status         field.Int64  // 状态 1 正常 2 禁用
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	Addtime        field.Int64  // 写入年月
+	Type           field.Int64  // 1-微信 2-名片
+	BotID          field.String // 微信或名片id
+	OrganizationID field.Int64  // 机构 ID
+	AiResponse     field.Int64  // AI回复次数
+	SopRun         field.Int64  // SOP运行次数
+	TotalFriend    field.Int64  // 好友总数
+	TotalGroup     field.Int64  // 群总数
+	AccountBalance field.Int64  // 账户余额(单位:分)
+	ConsumeToken   field.Int64  // 消耗token数
+	ActiveUser     field.Int64  // 活跃用户数
+	NewUser        field.Int64  // 新增用户数
+	LabelDist      field.String // 标签分布
+
+	fieldMap map[string]field.Expr
+}
+
+func (u usageStatisticMonth) Table(newTableName string) *usageStatisticMonth {
+	u.usageStatisticMonthDo.UseTable(newTableName)
+	return u.updateTableName(newTableName)
+}
+
+func (u usageStatisticMonth) As(alias string) *usageStatisticMonth {
+	u.usageStatisticMonthDo.DO = *(u.usageStatisticMonthDo.As(alias).(*gen.DO))
+	return u.updateTableName(alias)
+}
+
+func (u *usageStatisticMonth) updateTableName(table string) *usageStatisticMonth {
+	u.ALL = field.NewAsterisk(table)
+	u.ID = field.NewInt64(table, "id")
+	u.CreatedAt = field.NewTime(table, "created_at")
+	u.UpdatedAt = field.NewTime(table, "updated_at")
+	u.Status = field.NewInt64(table, "status")
+	u.DeletedAt = field.NewField(table, "deleted_at")
+	u.Addtime = field.NewInt64(table, "addtime")
+	u.Type = field.NewInt64(table, "type")
+	u.BotID = field.NewString(table, "bot_id")
+	u.OrganizationID = field.NewInt64(table, "organization_id")
+	u.AiResponse = field.NewInt64(table, "ai_response")
+	u.SopRun = field.NewInt64(table, "sop_run")
+	u.TotalFriend = field.NewInt64(table, "total_friend")
+	u.TotalGroup = field.NewInt64(table, "total_group")
+	u.AccountBalance = field.NewInt64(table, "account_balance")
+	u.ConsumeToken = field.NewInt64(table, "consume_token")
+	u.ActiveUser = field.NewInt64(table, "active_user")
+	u.NewUser = field.NewInt64(table, "new_user")
+	u.LabelDist = field.NewString(table, "label_dist")
+
+	u.fillFieldMap()
+
+	return u
+}
+
+func (u *usageStatisticMonth) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := u.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (u *usageStatisticMonth) fillFieldMap() {
+	u.fieldMap = make(map[string]field.Expr, 18)
+	u.fieldMap["id"] = u.ID
+	u.fieldMap["created_at"] = u.CreatedAt
+	u.fieldMap["updated_at"] = u.UpdatedAt
+	u.fieldMap["status"] = u.Status
+	u.fieldMap["deleted_at"] = u.DeletedAt
+	u.fieldMap["addtime"] = u.Addtime
+	u.fieldMap["type"] = u.Type
+	u.fieldMap["bot_id"] = u.BotID
+	u.fieldMap["organization_id"] = u.OrganizationID
+	u.fieldMap["ai_response"] = u.AiResponse
+	u.fieldMap["sop_run"] = u.SopRun
+	u.fieldMap["total_friend"] = u.TotalFriend
+	u.fieldMap["total_group"] = u.TotalGroup
+	u.fieldMap["account_balance"] = u.AccountBalance
+	u.fieldMap["consume_token"] = u.ConsumeToken
+	u.fieldMap["active_user"] = u.ActiveUser
+	u.fieldMap["new_user"] = u.NewUser
+	u.fieldMap["label_dist"] = u.LabelDist
+}
+
+func (u usageStatisticMonth) clone(db *gorm.DB) usageStatisticMonth {
+	u.usageStatisticMonthDo.ReplaceConnPool(db.Statement.ConnPool)
+	return u
+}
+
+func (u usageStatisticMonth) replaceDB(db *gorm.DB) usageStatisticMonth {
+	u.usageStatisticMonthDo.ReplaceDB(db)
+	return u
+}
+
+type usageStatisticMonthDo struct{ gen.DO }
+
+type IUsageStatisticMonthDo interface {
+	gen.SubQuery
+	Debug() IUsageStatisticMonthDo
+	WithContext(ctx context.Context) IUsageStatisticMonthDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IUsageStatisticMonthDo
+	WriteDB() IUsageStatisticMonthDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IUsageStatisticMonthDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IUsageStatisticMonthDo
+	Not(conds ...gen.Condition) IUsageStatisticMonthDo
+	Or(conds ...gen.Condition) IUsageStatisticMonthDo
+	Select(conds ...field.Expr) IUsageStatisticMonthDo
+	Where(conds ...gen.Condition) IUsageStatisticMonthDo
+	Order(conds ...field.Expr) IUsageStatisticMonthDo
+	Distinct(cols ...field.Expr) IUsageStatisticMonthDo
+	Omit(cols ...field.Expr) IUsageStatisticMonthDo
+	Join(table schema.Tabler, on ...field.Expr) IUsageStatisticMonthDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IUsageStatisticMonthDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IUsageStatisticMonthDo
+	Group(cols ...field.Expr) IUsageStatisticMonthDo
+	Having(conds ...gen.Condition) IUsageStatisticMonthDo
+	Limit(limit int) IUsageStatisticMonthDo
+	Offset(offset int) IUsageStatisticMonthDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IUsageStatisticMonthDo
+	Unscoped() IUsageStatisticMonthDo
+	Create(values ...*model.UsageStatisticMonth) error
+	CreateInBatches(values []*model.UsageStatisticMonth, batchSize int) error
+	Save(values ...*model.UsageStatisticMonth) error
+	First() (*model.UsageStatisticMonth, error)
+	Take() (*model.UsageStatisticMonth, error)
+	Last() (*model.UsageStatisticMonth, error)
+	Find() ([]*model.UsageStatisticMonth, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.UsageStatisticMonth, err error)
+	FindInBatches(result *[]*model.UsageStatisticMonth, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.UsageStatisticMonth) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IUsageStatisticMonthDo
+	Assign(attrs ...field.AssignExpr) IUsageStatisticMonthDo
+	Joins(fields ...field.RelationField) IUsageStatisticMonthDo
+	Preload(fields ...field.RelationField) IUsageStatisticMonthDo
+	FirstOrInit() (*model.UsageStatisticMonth, error)
+	FirstOrCreate() (*model.UsageStatisticMonth, error)
+	FindByPage(offset int, limit int) (result []*model.UsageStatisticMonth, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IUsageStatisticMonthDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (u usageStatisticMonthDo) Debug() IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Debug())
+}
+
+func (u usageStatisticMonthDo) WithContext(ctx context.Context) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.WithContext(ctx))
+}
+
+func (u usageStatisticMonthDo) ReadDB() IUsageStatisticMonthDo {
+	return u.Clauses(dbresolver.Read)
+}
+
+func (u usageStatisticMonthDo) WriteDB() IUsageStatisticMonthDo {
+	return u.Clauses(dbresolver.Write)
+}
+
+func (u usageStatisticMonthDo) Session(config *gorm.Session) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Session(config))
+}
+
+func (u usageStatisticMonthDo) Clauses(conds ...clause.Expression) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Clauses(conds...))
+}
+
+func (u usageStatisticMonthDo) Returning(value interface{}, columns ...string) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Returning(value, columns...))
+}
+
+func (u usageStatisticMonthDo) Not(conds ...gen.Condition) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Not(conds...))
+}
+
+func (u usageStatisticMonthDo) Or(conds ...gen.Condition) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Or(conds...))
+}
+
+func (u usageStatisticMonthDo) Select(conds ...field.Expr) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Select(conds...))
+}
+
+func (u usageStatisticMonthDo) Where(conds ...gen.Condition) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Where(conds...))
+}
+
+func (u usageStatisticMonthDo) Order(conds ...field.Expr) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Order(conds...))
+}
+
+func (u usageStatisticMonthDo) Distinct(cols ...field.Expr) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Distinct(cols...))
+}
+
+func (u usageStatisticMonthDo) Omit(cols ...field.Expr) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Omit(cols...))
+}
+
+func (u usageStatisticMonthDo) Join(table schema.Tabler, on ...field.Expr) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Join(table, on...))
+}
+
+func (u usageStatisticMonthDo) LeftJoin(table schema.Tabler, on ...field.Expr) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.LeftJoin(table, on...))
+}
+
+func (u usageStatisticMonthDo) RightJoin(table schema.Tabler, on ...field.Expr) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.RightJoin(table, on...))
+}
+
+func (u usageStatisticMonthDo) Group(cols ...field.Expr) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Group(cols...))
+}
+
+func (u usageStatisticMonthDo) Having(conds ...gen.Condition) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Having(conds...))
+}
+
+func (u usageStatisticMonthDo) Limit(limit int) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Limit(limit))
+}
+
+func (u usageStatisticMonthDo) Offset(offset int) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Offset(offset))
+}
+
+func (u usageStatisticMonthDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Scopes(funcs...))
+}
+
+func (u usageStatisticMonthDo) Unscoped() IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Unscoped())
+}
+
+func (u usageStatisticMonthDo) Create(values ...*model.UsageStatisticMonth) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return u.DO.Create(values)
+}
+
+func (u usageStatisticMonthDo) CreateInBatches(values []*model.UsageStatisticMonth, batchSize int) error {
+	return u.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (u usageStatisticMonthDo) Save(values ...*model.UsageStatisticMonth) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return u.DO.Save(values)
+}
+
+func (u usageStatisticMonthDo) First() (*model.UsageStatisticMonth, error) {
+	if result, err := u.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageStatisticMonth), nil
+	}
+}
+
+func (u usageStatisticMonthDo) Take() (*model.UsageStatisticMonth, error) {
+	if result, err := u.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageStatisticMonth), nil
+	}
+}
+
+func (u usageStatisticMonthDo) Last() (*model.UsageStatisticMonth, error) {
+	if result, err := u.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageStatisticMonth), nil
+	}
+}
+
+func (u usageStatisticMonthDo) Find() ([]*model.UsageStatisticMonth, error) {
+	result, err := u.DO.Find()
+	return result.([]*model.UsageStatisticMonth), err
+}
+
+func (u usageStatisticMonthDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.UsageStatisticMonth, err error) {
+	buf := make([]*model.UsageStatisticMonth, 0, batchSize)
+	err = u.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (u usageStatisticMonthDo) FindInBatches(result *[]*model.UsageStatisticMonth, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return u.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (u usageStatisticMonthDo) Attrs(attrs ...field.AssignExpr) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Attrs(attrs...))
+}
+
+func (u usageStatisticMonthDo) Assign(attrs ...field.AssignExpr) IUsageStatisticMonthDo {
+	return u.withDO(u.DO.Assign(attrs...))
+}
+
+func (u usageStatisticMonthDo) Joins(fields ...field.RelationField) IUsageStatisticMonthDo {
+	for _, _f := range fields {
+		u = *u.withDO(u.DO.Joins(_f))
+	}
+	return &u
+}
+
+func (u usageStatisticMonthDo) Preload(fields ...field.RelationField) IUsageStatisticMonthDo {
+	for _, _f := range fields {
+		u = *u.withDO(u.DO.Preload(_f))
+	}
+	return &u
+}
+
+func (u usageStatisticMonthDo) FirstOrInit() (*model.UsageStatisticMonth, error) {
+	if result, err := u.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageStatisticMonth), nil
+	}
+}
+
+func (u usageStatisticMonthDo) FirstOrCreate() (*model.UsageStatisticMonth, error) {
+	if result, err := u.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageStatisticMonth), nil
+	}
+}
+
+func (u usageStatisticMonthDo) FindByPage(offset int, limit int) (result []*model.UsageStatisticMonth, count int64, err error) {
+	result, err = u.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = u.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (u usageStatisticMonthDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = u.Count()
+	if err != nil {
+		return
+	}
+
+	err = u.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (u usageStatisticMonthDo) Scan(result interface{}) (err error) {
+	return u.DO.Scan(result)
+}
+
+func (u usageStatisticMonthDo) Delete(models ...*model.UsageStatisticMonth) (result gen.ResultInfo, err error) {
+	return u.DO.Delete(models)
+}
+
+func (u *usageStatisticMonthDo) withDO(do gen.Dao) *usageStatisticMonthDo {
+	u.DO = *do.(*gen.DO)
+	return u
+}

+ 420 - 0
database/dao/wechat/query/usage_total.gen.go

@@ -0,0 +1,420 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newUsageTotal(db *gorm.DB, opts ...gen.DOOption) usageTotal {
+	_usageTotal := usageTotal{}
+
+	_usageTotal.usageTotalDo.UseDB(db, opts...)
+	_usageTotal.usageTotalDo.UseModel(&model.UsageTotal{})
+
+	tableName := _usageTotal.usageTotalDo.TableName()
+	_usageTotal.ALL = field.NewAsterisk(tableName)
+	_usageTotal.ID = field.NewInt64(tableName, "id")
+	_usageTotal.CreatedAt = field.NewTime(tableName, "created_at")
+	_usageTotal.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_usageTotal.Status = field.NewInt64(tableName, "status")
+	_usageTotal.DeletedAt = field.NewField(tableName, "deleted_at")
+	_usageTotal.Type = field.NewInt64(tableName, "type")
+	_usageTotal.BotID = field.NewString(tableName, "bot_id")
+	_usageTotal.TotalTokens = field.NewInt64(tableName, "total_tokens")
+	_usageTotal.StartIndex = field.NewInt64(tableName, "start_index")
+	_usageTotal.EndIndex = field.NewInt64(tableName, "end_index")
+	_usageTotal.OrganizationID = field.NewInt64(tableName, "organization_id")
+
+	_usageTotal.fillFieldMap()
+
+	return _usageTotal
+}
+
+type usageTotal struct {
+	usageTotalDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	Status         field.Int64  // 状态 1 正常 2 禁用
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	Type           field.Int64  // 1 微信 2 名片
+	BotID          field.String // 微信或名片id
+	TotalTokens    field.Int64  // 使用token总数
+	StartIndex     field.Int64  // 重制后的起始usage_detail 索引
+	EndIndex       field.Int64  // usage_detail 索引
+	OrganizationID field.Int64  // 机构 ID
+
+	fieldMap map[string]field.Expr
+}
+
+func (u usageTotal) Table(newTableName string) *usageTotal {
+	u.usageTotalDo.UseTable(newTableName)
+	return u.updateTableName(newTableName)
+}
+
+func (u usageTotal) As(alias string) *usageTotal {
+	u.usageTotalDo.DO = *(u.usageTotalDo.As(alias).(*gen.DO))
+	return u.updateTableName(alias)
+}
+
+func (u *usageTotal) updateTableName(table string) *usageTotal {
+	u.ALL = field.NewAsterisk(table)
+	u.ID = field.NewInt64(table, "id")
+	u.CreatedAt = field.NewTime(table, "created_at")
+	u.UpdatedAt = field.NewTime(table, "updated_at")
+	u.Status = field.NewInt64(table, "status")
+	u.DeletedAt = field.NewField(table, "deleted_at")
+	u.Type = field.NewInt64(table, "type")
+	u.BotID = field.NewString(table, "bot_id")
+	u.TotalTokens = field.NewInt64(table, "total_tokens")
+	u.StartIndex = field.NewInt64(table, "start_index")
+	u.EndIndex = field.NewInt64(table, "end_index")
+	u.OrganizationID = field.NewInt64(table, "organization_id")
+
+	u.fillFieldMap()
+
+	return u
+}
+
+func (u *usageTotal) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := u.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (u *usageTotal) fillFieldMap() {
+	u.fieldMap = make(map[string]field.Expr, 11)
+	u.fieldMap["id"] = u.ID
+	u.fieldMap["created_at"] = u.CreatedAt
+	u.fieldMap["updated_at"] = u.UpdatedAt
+	u.fieldMap["status"] = u.Status
+	u.fieldMap["deleted_at"] = u.DeletedAt
+	u.fieldMap["type"] = u.Type
+	u.fieldMap["bot_id"] = u.BotID
+	u.fieldMap["total_tokens"] = u.TotalTokens
+	u.fieldMap["start_index"] = u.StartIndex
+	u.fieldMap["end_index"] = u.EndIndex
+	u.fieldMap["organization_id"] = u.OrganizationID
+}
+
+func (u usageTotal) clone(db *gorm.DB) usageTotal {
+	u.usageTotalDo.ReplaceConnPool(db.Statement.ConnPool)
+	return u
+}
+
+func (u usageTotal) replaceDB(db *gorm.DB) usageTotal {
+	u.usageTotalDo.ReplaceDB(db)
+	return u
+}
+
+type usageTotalDo struct{ gen.DO }
+
+type IUsageTotalDo interface {
+	gen.SubQuery
+	Debug() IUsageTotalDo
+	WithContext(ctx context.Context) IUsageTotalDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IUsageTotalDo
+	WriteDB() IUsageTotalDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IUsageTotalDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IUsageTotalDo
+	Not(conds ...gen.Condition) IUsageTotalDo
+	Or(conds ...gen.Condition) IUsageTotalDo
+	Select(conds ...field.Expr) IUsageTotalDo
+	Where(conds ...gen.Condition) IUsageTotalDo
+	Order(conds ...field.Expr) IUsageTotalDo
+	Distinct(cols ...field.Expr) IUsageTotalDo
+	Omit(cols ...field.Expr) IUsageTotalDo
+	Join(table schema.Tabler, on ...field.Expr) IUsageTotalDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IUsageTotalDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IUsageTotalDo
+	Group(cols ...field.Expr) IUsageTotalDo
+	Having(conds ...gen.Condition) IUsageTotalDo
+	Limit(limit int) IUsageTotalDo
+	Offset(offset int) IUsageTotalDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IUsageTotalDo
+	Unscoped() IUsageTotalDo
+	Create(values ...*model.UsageTotal) error
+	CreateInBatches(values []*model.UsageTotal, batchSize int) error
+	Save(values ...*model.UsageTotal) error
+	First() (*model.UsageTotal, error)
+	Take() (*model.UsageTotal, error)
+	Last() (*model.UsageTotal, error)
+	Find() ([]*model.UsageTotal, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.UsageTotal, err error)
+	FindInBatches(result *[]*model.UsageTotal, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.UsageTotal) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IUsageTotalDo
+	Assign(attrs ...field.AssignExpr) IUsageTotalDo
+	Joins(fields ...field.RelationField) IUsageTotalDo
+	Preload(fields ...field.RelationField) IUsageTotalDo
+	FirstOrInit() (*model.UsageTotal, error)
+	FirstOrCreate() (*model.UsageTotal, error)
+	FindByPage(offset int, limit int) (result []*model.UsageTotal, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IUsageTotalDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (u usageTotalDo) Debug() IUsageTotalDo {
+	return u.withDO(u.DO.Debug())
+}
+
+func (u usageTotalDo) WithContext(ctx context.Context) IUsageTotalDo {
+	return u.withDO(u.DO.WithContext(ctx))
+}
+
+func (u usageTotalDo) ReadDB() IUsageTotalDo {
+	return u.Clauses(dbresolver.Read)
+}
+
+func (u usageTotalDo) WriteDB() IUsageTotalDo {
+	return u.Clauses(dbresolver.Write)
+}
+
+func (u usageTotalDo) Session(config *gorm.Session) IUsageTotalDo {
+	return u.withDO(u.DO.Session(config))
+}
+
+func (u usageTotalDo) Clauses(conds ...clause.Expression) IUsageTotalDo {
+	return u.withDO(u.DO.Clauses(conds...))
+}
+
+func (u usageTotalDo) Returning(value interface{}, columns ...string) IUsageTotalDo {
+	return u.withDO(u.DO.Returning(value, columns...))
+}
+
+func (u usageTotalDo) Not(conds ...gen.Condition) IUsageTotalDo {
+	return u.withDO(u.DO.Not(conds...))
+}
+
+func (u usageTotalDo) Or(conds ...gen.Condition) IUsageTotalDo {
+	return u.withDO(u.DO.Or(conds...))
+}
+
+func (u usageTotalDo) Select(conds ...field.Expr) IUsageTotalDo {
+	return u.withDO(u.DO.Select(conds...))
+}
+
+func (u usageTotalDo) Where(conds ...gen.Condition) IUsageTotalDo {
+	return u.withDO(u.DO.Where(conds...))
+}
+
+func (u usageTotalDo) Order(conds ...field.Expr) IUsageTotalDo {
+	return u.withDO(u.DO.Order(conds...))
+}
+
+func (u usageTotalDo) Distinct(cols ...field.Expr) IUsageTotalDo {
+	return u.withDO(u.DO.Distinct(cols...))
+}
+
+func (u usageTotalDo) Omit(cols ...field.Expr) IUsageTotalDo {
+	return u.withDO(u.DO.Omit(cols...))
+}
+
+func (u usageTotalDo) Join(table schema.Tabler, on ...field.Expr) IUsageTotalDo {
+	return u.withDO(u.DO.Join(table, on...))
+}
+
+func (u usageTotalDo) LeftJoin(table schema.Tabler, on ...field.Expr) IUsageTotalDo {
+	return u.withDO(u.DO.LeftJoin(table, on...))
+}
+
+func (u usageTotalDo) RightJoin(table schema.Tabler, on ...field.Expr) IUsageTotalDo {
+	return u.withDO(u.DO.RightJoin(table, on...))
+}
+
+func (u usageTotalDo) Group(cols ...field.Expr) IUsageTotalDo {
+	return u.withDO(u.DO.Group(cols...))
+}
+
+func (u usageTotalDo) Having(conds ...gen.Condition) IUsageTotalDo {
+	return u.withDO(u.DO.Having(conds...))
+}
+
+func (u usageTotalDo) Limit(limit int) IUsageTotalDo {
+	return u.withDO(u.DO.Limit(limit))
+}
+
+func (u usageTotalDo) Offset(offset int) IUsageTotalDo {
+	return u.withDO(u.DO.Offset(offset))
+}
+
+func (u usageTotalDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IUsageTotalDo {
+	return u.withDO(u.DO.Scopes(funcs...))
+}
+
+func (u usageTotalDo) Unscoped() IUsageTotalDo {
+	return u.withDO(u.DO.Unscoped())
+}
+
+func (u usageTotalDo) Create(values ...*model.UsageTotal) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return u.DO.Create(values)
+}
+
+func (u usageTotalDo) CreateInBatches(values []*model.UsageTotal, batchSize int) error {
+	return u.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (u usageTotalDo) Save(values ...*model.UsageTotal) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return u.DO.Save(values)
+}
+
+func (u usageTotalDo) First() (*model.UsageTotal, error) {
+	if result, err := u.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageTotal), nil
+	}
+}
+
+func (u usageTotalDo) Take() (*model.UsageTotal, error) {
+	if result, err := u.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageTotal), nil
+	}
+}
+
+func (u usageTotalDo) Last() (*model.UsageTotal, error) {
+	if result, err := u.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageTotal), nil
+	}
+}
+
+func (u usageTotalDo) Find() ([]*model.UsageTotal, error) {
+	result, err := u.DO.Find()
+	return result.([]*model.UsageTotal), err
+}
+
+func (u usageTotalDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.UsageTotal, err error) {
+	buf := make([]*model.UsageTotal, 0, batchSize)
+	err = u.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (u usageTotalDo) FindInBatches(result *[]*model.UsageTotal, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return u.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (u usageTotalDo) Attrs(attrs ...field.AssignExpr) IUsageTotalDo {
+	return u.withDO(u.DO.Attrs(attrs...))
+}
+
+func (u usageTotalDo) Assign(attrs ...field.AssignExpr) IUsageTotalDo {
+	return u.withDO(u.DO.Assign(attrs...))
+}
+
+func (u usageTotalDo) Joins(fields ...field.RelationField) IUsageTotalDo {
+	for _, _f := range fields {
+		u = *u.withDO(u.DO.Joins(_f))
+	}
+	return &u
+}
+
+func (u usageTotalDo) Preload(fields ...field.RelationField) IUsageTotalDo {
+	for _, _f := range fields {
+		u = *u.withDO(u.DO.Preload(_f))
+	}
+	return &u
+}
+
+func (u usageTotalDo) FirstOrInit() (*model.UsageTotal, error) {
+	if result, err := u.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageTotal), nil
+	}
+}
+
+func (u usageTotalDo) FirstOrCreate() (*model.UsageTotal, error) {
+	if result, err := u.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.UsageTotal), nil
+	}
+}
+
+func (u usageTotalDo) FindByPage(offset int, limit int) (result []*model.UsageTotal, count int64, err error) {
+	result, err = u.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = u.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (u usageTotalDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = u.Count()
+	if err != nil {
+		return
+	}
+
+	err = u.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (u usageTotalDo) Scan(result interface{}) (err error) {
+	return u.DO.Scan(result)
+}
+
+func (u usageTotalDo) Delete(models ...*model.UsageTotal) (result gen.ResultInfo, err error) {
+	return u.DO.Delete(models)
+}
+
+func (u *usageTotalDo) withDO(do gen.Dao) *usageTotalDo {
+	u.DO = *do.(*gen.DO)
+	return u
+}

+ 465 - 0
database/dao/wechat/query/whatsapp.gen.go

@@ -0,0 +1,465 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newWhatsapp(db *gorm.DB, opts ...gen.DOOption) whatsapp {
+	_whatsapp := whatsapp{}
+
+	_whatsapp.whatsappDo.UseDB(db, opts...)
+	_whatsapp.whatsappDo.UseModel(&model.Whatsapp{})
+
+	tableName := _whatsapp.whatsappDo.TableName()
+	_whatsapp.ALL = field.NewAsterisk(tableName)
+	_whatsapp.ID = field.NewInt64(tableName, "id")
+	_whatsapp.CreatedAt = field.NewTime(tableName, "created_at")
+	_whatsapp.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_whatsapp.Status = field.NewInt64(tableName, "status")
+	_whatsapp.DeletedAt = field.NewField(tableName, "deleted_at")
+	_whatsapp.WaID = field.NewString(tableName, "wa_id")
+	_whatsapp.WaName = field.NewString(tableName, "wa_name")
+	_whatsapp.Callback = field.NewString(tableName, "callback")
+	_whatsapp.AgentID = field.NewInt64(tableName, "agent_id")
+	_whatsapp.Account = field.NewString(tableName, "account")
+	_whatsapp.Cc = field.NewString(tableName, "cc")
+	_whatsapp.Phone = field.NewString(tableName, "phone")
+	_whatsapp.CcPhone = field.NewString(tableName, "cc_phone")
+	_whatsapp.PhoneName = field.NewString(tableName, "phone_name")
+	_whatsapp.PhoneStatus = field.NewInt64(tableName, "phone_status")
+	_whatsapp.APIBase = field.NewString(tableName, "api_base")
+	_whatsapp.APIKey = field.NewString(tableName, "api_key")
+	_whatsapp.AllowList = field.NewString(tableName, "allow_list")
+	_whatsapp.GroupAllowList = field.NewString(tableName, "group_allow_list")
+	_whatsapp.BlockList = field.NewString(tableName, "block_list")
+	_whatsapp.GroupBlockList = field.NewString(tableName, "group_block_list")
+	_whatsapp.OrganizationID = field.NewInt64(tableName, "organization_id")
+
+	_whatsapp.fillFieldMap()
+
+	return _whatsapp
+}
+
+// whatsapp whatsapp手机号表
+type whatsapp struct {
+	whatsappDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	Status         field.Int64  // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	WaID           field.String // wa通道ID
+	WaName         field.String // 通道名
+	Callback       field.String // 回调地址
+	AgentID        field.Int64  // AI角色ID
+	Account        field.String // 账户
+	Cc             field.String // 国家区号
+	Phone          field.String // 手机号
+	CcPhone        field.String // 国家区号 + 手机号
+	PhoneName      field.String // 号码名称
+	PhoneStatus    field.Int64  // 号码状态
+	APIBase        field.String
+	APIKey         field.String
+	AllowList      field.String // 白名单,以数组存储wxid。当包含 ALL 字符串时为全部允许
+	GroupAllowList field.String // 群白名单,以数组存储wxid。当包含 ALL 字符串时为全部允许
+	BlockList      field.String // 黑名单,以数组存储wxid。当包含 ALL 字符串时为全部拒绝
+	GroupBlockList field.String // 群黑名单,以数组存储wxid。当包含 ALL 字符串时为全部拒绝
+	OrganizationID field.Int64  // 机构ID
+
+	fieldMap map[string]field.Expr
+}
+
+func (w whatsapp) Table(newTableName string) *whatsapp {
+	w.whatsappDo.UseTable(newTableName)
+	return w.updateTableName(newTableName)
+}
+
+func (w whatsapp) As(alias string) *whatsapp {
+	w.whatsappDo.DO = *(w.whatsappDo.As(alias).(*gen.DO))
+	return w.updateTableName(alias)
+}
+
+func (w *whatsapp) updateTableName(table string) *whatsapp {
+	w.ALL = field.NewAsterisk(table)
+	w.ID = field.NewInt64(table, "id")
+	w.CreatedAt = field.NewTime(table, "created_at")
+	w.UpdatedAt = field.NewTime(table, "updated_at")
+	w.Status = field.NewInt64(table, "status")
+	w.DeletedAt = field.NewField(table, "deleted_at")
+	w.WaID = field.NewString(table, "wa_id")
+	w.WaName = field.NewString(table, "wa_name")
+	w.Callback = field.NewString(table, "callback")
+	w.AgentID = field.NewInt64(table, "agent_id")
+	w.Account = field.NewString(table, "account")
+	w.Cc = field.NewString(table, "cc")
+	w.Phone = field.NewString(table, "phone")
+	w.CcPhone = field.NewString(table, "cc_phone")
+	w.PhoneName = field.NewString(table, "phone_name")
+	w.PhoneStatus = field.NewInt64(table, "phone_status")
+	w.APIBase = field.NewString(table, "api_base")
+	w.APIKey = field.NewString(table, "api_key")
+	w.AllowList = field.NewString(table, "allow_list")
+	w.GroupAllowList = field.NewString(table, "group_allow_list")
+	w.BlockList = field.NewString(table, "block_list")
+	w.GroupBlockList = field.NewString(table, "group_block_list")
+	w.OrganizationID = field.NewInt64(table, "organization_id")
+
+	w.fillFieldMap()
+
+	return w
+}
+
+func (w *whatsapp) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := w.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (w *whatsapp) fillFieldMap() {
+	w.fieldMap = make(map[string]field.Expr, 22)
+	w.fieldMap["id"] = w.ID
+	w.fieldMap["created_at"] = w.CreatedAt
+	w.fieldMap["updated_at"] = w.UpdatedAt
+	w.fieldMap["status"] = w.Status
+	w.fieldMap["deleted_at"] = w.DeletedAt
+	w.fieldMap["wa_id"] = w.WaID
+	w.fieldMap["wa_name"] = w.WaName
+	w.fieldMap["callback"] = w.Callback
+	w.fieldMap["agent_id"] = w.AgentID
+	w.fieldMap["account"] = w.Account
+	w.fieldMap["cc"] = w.Cc
+	w.fieldMap["phone"] = w.Phone
+	w.fieldMap["cc_phone"] = w.CcPhone
+	w.fieldMap["phone_name"] = w.PhoneName
+	w.fieldMap["phone_status"] = w.PhoneStatus
+	w.fieldMap["api_base"] = w.APIBase
+	w.fieldMap["api_key"] = w.APIKey
+	w.fieldMap["allow_list"] = w.AllowList
+	w.fieldMap["group_allow_list"] = w.GroupAllowList
+	w.fieldMap["block_list"] = w.BlockList
+	w.fieldMap["group_block_list"] = w.GroupBlockList
+	w.fieldMap["organization_id"] = w.OrganizationID
+}
+
+func (w whatsapp) clone(db *gorm.DB) whatsapp {
+	w.whatsappDo.ReplaceConnPool(db.Statement.ConnPool)
+	return w
+}
+
+func (w whatsapp) replaceDB(db *gorm.DB) whatsapp {
+	w.whatsappDo.ReplaceDB(db)
+	return w
+}
+
+type whatsappDo struct{ gen.DO }
+
+type IWhatsappDo interface {
+	gen.SubQuery
+	Debug() IWhatsappDo
+	WithContext(ctx context.Context) IWhatsappDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IWhatsappDo
+	WriteDB() IWhatsappDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IWhatsappDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IWhatsappDo
+	Not(conds ...gen.Condition) IWhatsappDo
+	Or(conds ...gen.Condition) IWhatsappDo
+	Select(conds ...field.Expr) IWhatsappDo
+	Where(conds ...gen.Condition) IWhatsappDo
+	Order(conds ...field.Expr) IWhatsappDo
+	Distinct(cols ...field.Expr) IWhatsappDo
+	Omit(cols ...field.Expr) IWhatsappDo
+	Join(table schema.Tabler, on ...field.Expr) IWhatsappDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IWhatsappDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IWhatsappDo
+	Group(cols ...field.Expr) IWhatsappDo
+	Having(conds ...gen.Condition) IWhatsappDo
+	Limit(limit int) IWhatsappDo
+	Offset(offset int) IWhatsappDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IWhatsappDo
+	Unscoped() IWhatsappDo
+	Create(values ...*model.Whatsapp) error
+	CreateInBatches(values []*model.Whatsapp, batchSize int) error
+	Save(values ...*model.Whatsapp) error
+	First() (*model.Whatsapp, error)
+	Take() (*model.Whatsapp, error)
+	Last() (*model.Whatsapp, error)
+	Find() ([]*model.Whatsapp, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Whatsapp, err error)
+	FindInBatches(result *[]*model.Whatsapp, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.Whatsapp) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IWhatsappDo
+	Assign(attrs ...field.AssignExpr) IWhatsappDo
+	Joins(fields ...field.RelationField) IWhatsappDo
+	Preload(fields ...field.RelationField) IWhatsappDo
+	FirstOrInit() (*model.Whatsapp, error)
+	FirstOrCreate() (*model.Whatsapp, error)
+	FindByPage(offset int, limit int) (result []*model.Whatsapp, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IWhatsappDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (w whatsappDo) Debug() IWhatsappDo {
+	return w.withDO(w.DO.Debug())
+}
+
+func (w whatsappDo) WithContext(ctx context.Context) IWhatsappDo {
+	return w.withDO(w.DO.WithContext(ctx))
+}
+
+func (w whatsappDo) ReadDB() IWhatsappDo {
+	return w.Clauses(dbresolver.Read)
+}
+
+func (w whatsappDo) WriteDB() IWhatsappDo {
+	return w.Clauses(dbresolver.Write)
+}
+
+func (w whatsappDo) Session(config *gorm.Session) IWhatsappDo {
+	return w.withDO(w.DO.Session(config))
+}
+
+func (w whatsappDo) Clauses(conds ...clause.Expression) IWhatsappDo {
+	return w.withDO(w.DO.Clauses(conds...))
+}
+
+func (w whatsappDo) Returning(value interface{}, columns ...string) IWhatsappDo {
+	return w.withDO(w.DO.Returning(value, columns...))
+}
+
+func (w whatsappDo) Not(conds ...gen.Condition) IWhatsappDo {
+	return w.withDO(w.DO.Not(conds...))
+}
+
+func (w whatsappDo) Or(conds ...gen.Condition) IWhatsappDo {
+	return w.withDO(w.DO.Or(conds...))
+}
+
+func (w whatsappDo) Select(conds ...field.Expr) IWhatsappDo {
+	return w.withDO(w.DO.Select(conds...))
+}
+
+func (w whatsappDo) Where(conds ...gen.Condition) IWhatsappDo {
+	return w.withDO(w.DO.Where(conds...))
+}
+
+func (w whatsappDo) Order(conds ...field.Expr) IWhatsappDo {
+	return w.withDO(w.DO.Order(conds...))
+}
+
+func (w whatsappDo) Distinct(cols ...field.Expr) IWhatsappDo {
+	return w.withDO(w.DO.Distinct(cols...))
+}
+
+func (w whatsappDo) Omit(cols ...field.Expr) IWhatsappDo {
+	return w.withDO(w.DO.Omit(cols...))
+}
+
+func (w whatsappDo) Join(table schema.Tabler, on ...field.Expr) IWhatsappDo {
+	return w.withDO(w.DO.Join(table, on...))
+}
+
+func (w whatsappDo) LeftJoin(table schema.Tabler, on ...field.Expr) IWhatsappDo {
+	return w.withDO(w.DO.LeftJoin(table, on...))
+}
+
+func (w whatsappDo) RightJoin(table schema.Tabler, on ...field.Expr) IWhatsappDo {
+	return w.withDO(w.DO.RightJoin(table, on...))
+}
+
+func (w whatsappDo) Group(cols ...field.Expr) IWhatsappDo {
+	return w.withDO(w.DO.Group(cols...))
+}
+
+func (w whatsappDo) Having(conds ...gen.Condition) IWhatsappDo {
+	return w.withDO(w.DO.Having(conds...))
+}
+
+func (w whatsappDo) Limit(limit int) IWhatsappDo {
+	return w.withDO(w.DO.Limit(limit))
+}
+
+func (w whatsappDo) Offset(offset int) IWhatsappDo {
+	return w.withDO(w.DO.Offset(offset))
+}
+
+func (w whatsappDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IWhatsappDo {
+	return w.withDO(w.DO.Scopes(funcs...))
+}
+
+func (w whatsappDo) Unscoped() IWhatsappDo {
+	return w.withDO(w.DO.Unscoped())
+}
+
+func (w whatsappDo) Create(values ...*model.Whatsapp) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return w.DO.Create(values)
+}
+
+func (w whatsappDo) CreateInBatches(values []*model.Whatsapp, batchSize int) error {
+	return w.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (w whatsappDo) Save(values ...*model.Whatsapp) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return w.DO.Save(values)
+}
+
+func (w whatsappDo) First() (*model.Whatsapp, error) {
+	if result, err := w.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Whatsapp), nil
+	}
+}
+
+func (w whatsappDo) Take() (*model.Whatsapp, error) {
+	if result, err := w.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Whatsapp), nil
+	}
+}
+
+func (w whatsappDo) Last() (*model.Whatsapp, error) {
+	if result, err := w.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Whatsapp), nil
+	}
+}
+
+func (w whatsappDo) Find() ([]*model.Whatsapp, error) {
+	result, err := w.DO.Find()
+	return result.([]*model.Whatsapp), err
+}
+
+func (w whatsappDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Whatsapp, err error) {
+	buf := make([]*model.Whatsapp, 0, batchSize)
+	err = w.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (w whatsappDo) FindInBatches(result *[]*model.Whatsapp, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return w.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (w whatsappDo) Attrs(attrs ...field.AssignExpr) IWhatsappDo {
+	return w.withDO(w.DO.Attrs(attrs...))
+}
+
+func (w whatsappDo) Assign(attrs ...field.AssignExpr) IWhatsappDo {
+	return w.withDO(w.DO.Assign(attrs...))
+}
+
+func (w whatsappDo) Joins(fields ...field.RelationField) IWhatsappDo {
+	for _, _f := range fields {
+		w = *w.withDO(w.DO.Joins(_f))
+	}
+	return &w
+}
+
+func (w whatsappDo) Preload(fields ...field.RelationField) IWhatsappDo {
+	for _, _f := range fields {
+		w = *w.withDO(w.DO.Preload(_f))
+	}
+	return &w
+}
+
+func (w whatsappDo) FirstOrInit() (*model.Whatsapp, error) {
+	if result, err := w.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Whatsapp), nil
+	}
+}
+
+func (w whatsappDo) FirstOrCreate() (*model.Whatsapp, error) {
+	if result, err := w.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Whatsapp), nil
+	}
+}
+
+func (w whatsappDo) FindByPage(offset int, limit int) (result []*model.Whatsapp, count int64, err error) {
+	result, err = w.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = w.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (w whatsappDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = w.Count()
+	if err != nil {
+		return
+	}
+
+	err = w.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (w whatsappDo) Scan(result interface{}) (err error) {
+	return w.DO.Scan(result)
+}
+
+func (w whatsappDo) Delete(models ...*model.Whatsapp) (result gen.ResultInfo, err error) {
+	return w.DO.Delete(models)
+}
+
+func (w *whatsappDo) withDO(do gen.Dao) *whatsappDo {
+	w.DO = *do.(*gen.DO)
+	return w
+}

+ 429 - 0
database/dao/wechat/query/whatsapp_channel.gen.go

@@ -0,0 +1,429 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newWhatsappChannel(db *gorm.DB, opts ...gen.DOOption) whatsappChannel {
+	_whatsappChannel := whatsappChannel{}
+
+	_whatsappChannel.whatsappChannelDo.UseDB(db, opts...)
+	_whatsappChannel.whatsappChannelDo.UseModel(&model.WhatsappChannel{})
+
+	tableName := _whatsappChannel.whatsappChannelDo.TableName()
+	_whatsappChannel.ALL = field.NewAsterisk(tableName)
+	_whatsappChannel.ID = field.NewInt64(tableName, "id")
+	_whatsappChannel.CreatedAt = field.NewTime(tableName, "created_at")
+	_whatsappChannel.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_whatsappChannel.Status = field.NewInt64(tableName, "status")
+	_whatsappChannel.DeletedAt = field.NewField(tableName, "deleted_at")
+	_whatsappChannel.Ak = field.NewString(tableName, "ak")
+	_whatsappChannel.Sk = field.NewString(tableName, "sk")
+	_whatsappChannel.WaID = field.NewString(tableName, "wa_id")
+	_whatsappChannel.WaName = field.NewString(tableName, "wa_name")
+	_whatsappChannel.OrganizationID = field.NewInt64(tableName, "organization_id")
+	_whatsappChannel.WabaID = field.NewInt64(tableName, "waba_id")
+	_whatsappChannel.BusinessID = field.NewInt64(tableName, "business_id")
+	_whatsappChannel.VerifyAccount = field.NewString(tableName, "verify_account")
+
+	_whatsappChannel.fillFieldMap()
+
+	return _whatsappChannel
+}
+
+// whatsappChannel Whatsapp通道表
+type whatsappChannel struct {
+	whatsappChannelDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time  // Create Time | 创建日期
+	UpdatedAt      field.Time  // Update Time | 修改日期
+	Status         field.Int64 // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt      field.Field // Delete Time | 删除日期
+	Ak             field.String
+	Sk             field.String
+	WaID           field.String // 通道ID
+	WaName         field.String // 通道名
+	OrganizationID field.Int64  // 机构 ID
+	WabaID         field.Int64  // WABA ID
+	BusinessID     field.Int64  // 商品平台ID
+	VerifyAccount  field.String // 认证主体
+
+	fieldMap map[string]field.Expr
+}
+
+func (w whatsappChannel) Table(newTableName string) *whatsappChannel {
+	w.whatsappChannelDo.UseTable(newTableName)
+	return w.updateTableName(newTableName)
+}
+
+func (w whatsappChannel) As(alias string) *whatsappChannel {
+	w.whatsappChannelDo.DO = *(w.whatsappChannelDo.As(alias).(*gen.DO))
+	return w.updateTableName(alias)
+}
+
+func (w *whatsappChannel) updateTableName(table string) *whatsappChannel {
+	w.ALL = field.NewAsterisk(table)
+	w.ID = field.NewInt64(table, "id")
+	w.CreatedAt = field.NewTime(table, "created_at")
+	w.UpdatedAt = field.NewTime(table, "updated_at")
+	w.Status = field.NewInt64(table, "status")
+	w.DeletedAt = field.NewField(table, "deleted_at")
+	w.Ak = field.NewString(table, "ak")
+	w.Sk = field.NewString(table, "sk")
+	w.WaID = field.NewString(table, "wa_id")
+	w.WaName = field.NewString(table, "wa_name")
+	w.OrganizationID = field.NewInt64(table, "organization_id")
+	w.WabaID = field.NewInt64(table, "waba_id")
+	w.BusinessID = field.NewInt64(table, "business_id")
+	w.VerifyAccount = field.NewString(table, "verify_account")
+
+	w.fillFieldMap()
+
+	return w
+}
+
+func (w *whatsappChannel) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := w.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (w *whatsappChannel) fillFieldMap() {
+	w.fieldMap = make(map[string]field.Expr, 13)
+	w.fieldMap["id"] = w.ID
+	w.fieldMap["created_at"] = w.CreatedAt
+	w.fieldMap["updated_at"] = w.UpdatedAt
+	w.fieldMap["status"] = w.Status
+	w.fieldMap["deleted_at"] = w.DeletedAt
+	w.fieldMap["ak"] = w.Ak
+	w.fieldMap["sk"] = w.Sk
+	w.fieldMap["wa_id"] = w.WaID
+	w.fieldMap["wa_name"] = w.WaName
+	w.fieldMap["organization_id"] = w.OrganizationID
+	w.fieldMap["waba_id"] = w.WabaID
+	w.fieldMap["business_id"] = w.BusinessID
+	w.fieldMap["verify_account"] = w.VerifyAccount
+}
+
+func (w whatsappChannel) clone(db *gorm.DB) whatsappChannel {
+	w.whatsappChannelDo.ReplaceConnPool(db.Statement.ConnPool)
+	return w
+}
+
+func (w whatsappChannel) replaceDB(db *gorm.DB) whatsappChannel {
+	w.whatsappChannelDo.ReplaceDB(db)
+	return w
+}
+
+type whatsappChannelDo struct{ gen.DO }
+
+type IWhatsappChannelDo interface {
+	gen.SubQuery
+	Debug() IWhatsappChannelDo
+	WithContext(ctx context.Context) IWhatsappChannelDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IWhatsappChannelDo
+	WriteDB() IWhatsappChannelDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IWhatsappChannelDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IWhatsappChannelDo
+	Not(conds ...gen.Condition) IWhatsappChannelDo
+	Or(conds ...gen.Condition) IWhatsappChannelDo
+	Select(conds ...field.Expr) IWhatsappChannelDo
+	Where(conds ...gen.Condition) IWhatsappChannelDo
+	Order(conds ...field.Expr) IWhatsappChannelDo
+	Distinct(cols ...field.Expr) IWhatsappChannelDo
+	Omit(cols ...field.Expr) IWhatsappChannelDo
+	Join(table schema.Tabler, on ...field.Expr) IWhatsappChannelDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IWhatsappChannelDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IWhatsappChannelDo
+	Group(cols ...field.Expr) IWhatsappChannelDo
+	Having(conds ...gen.Condition) IWhatsappChannelDo
+	Limit(limit int) IWhatsappChannelDo
+	Offset(offset int) IWhatsappChannelDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IWhatsappChannelDo
+	Unscoped() IWhatsappChannelDo
+	Create(values ...*model.WhatsappChannel) error
+	CreateInBatches(values []*model.WhatsappChannel, batchSize int) error
+	Save(values ...*model.WhatsappChannel) error
+	First() (*model.WhatsappChannel, error)
+	Take() (*model.WhatsappChannel, error)
+	Last() (*model.WhatsappChannel, error)
+	Find() ([]*model.WhatsappChannel, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.WhatsappChannel, err error)
+	FindInBatches(result *[]*model.WhatsappChannel, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.WhatsappChannel) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IWhatsappChannelDo
+	Assign(attrs ...field.AssignExpr) IWhatsappChannelDo
+	Joins(fields ...field.RelationField) IWhatsappChannelDo
+	Preload(fields ...field.RelationField) IWhatsappChannelDo
+	FirstOrInit() (*model.WhatsappChannel, error)
+	FirstOrCreate() (*model.WhatsappChannel, error)
+	FindByPage(offset int, limit int) (result []*model.WhatsappChannel, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IWhatsappChannelDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (w whatsappChannelDo) Debug() IWhatsappChannelDo {
+	return w.withDO(w.DO.Debug())
+}
+
+func (w whatsappChannelDo) WithContext(ctx context.Context) IWhatsappChannelDo {
+	return w.withDO(w.DO.WithContext(ctx))
+}
+
+func (w whatsappChannelDo) ReadDB() IWhatsappChannelDo {
+	return w.Clauses(dbresolver.Read)
+}
+
+func (w whatsappChannelDo) WriteDB() IWhatsappChannelDo {
+	return w.Clauses(dbresolver.Write)
+}
+
+func (w whatsappChannelDo) Session(config *gorm.Session) IWhatsappChannelDo {
+	return w.withDO(w.DO.Session(config))
+}
+
+func (w whatsappChannelDo) Clauses(conds ...clause.Expression) IWhatsappChannelDo {
+	return w.withDO(w.DO.Clauses(conds...))
+}
+
+func (w whatsappChannelDo) Returning(value interface{}, columns ...string) IWhatsappChannelDo {
+	return w.withDO(w.DO.Returning(value, columns...))
+}
+
+func (w whatsappChannelDo) Not(conds ...gen.Condition) IWhatsappChannelDo {
+	return w.withDO(w.DO.Not(conds...))
+}
+
+func (w whatsappChannelDo) Or(conds ...gen.Condition) IWhatsappChannelDo {
+	return w.withDO(w.DO.Or(conds...))
+}
+
+func (w whatsappChannelDo) Select(conds ...field.Expr) IWhatsappChannelDo {
+	return w.withDO(w.DO.Select(conds...))
+}
+
+func (w whatsappChannelDo) Where(conds ...gen.Condition) IWhatsappChannelDo {
+	return w.withDO(w.DO.Where(conds...))
+}
+
+func (w whatsappChannelDo) Order(conds ...field.Expr) IWhatsappChannelDo {
+	return w.withDO(w.DO.Order(conds...))
+}
+
+func (w whatsappChannelDo) Distinct(cols ...field.Expr) IWhatsappChannelDo {
+	return w.withDO(w.DO.Distinct(cols...))
+}
+
+func (w whatsappChannelDo) Omit(cols ...field.Expr) IWhatsappChannelDo {
+	return w.withDO(w.DO.Omit(cols...))
+}
+
+func (w whatsappChannelDo) Join(table schema.Tabler, on ...field.Expr) IWhatsappChannelDo {
+	return w.withDO(w.DO.Join(table, on...))
+}
+
+func (w whatsappChannelDo) LeftJoin(table schema.Tabler, on ...field.Expr) IWhatsappChannelDo {
+	return w.withDO(w.DO.LeftJoin(table, on...))
+}
+
+func (w whatsappChannelDo) RightJoin(table schema.Tabler, on ...field.Expr) IWhatsappChannelDo {
+	return w.withDO(w.DO.RightJoin(table, on...))
+}
+
+func (w whatsappChannelDo) Group(cols ...field.Expr) IWhatsappChannelDo {
+	return w.withDO(w.DO.Group(cols...))
+}
+
+func (w whatsappChannelDo) Having(conds ...gen.Condition) IWhatsappChannelDo {
+	return w.withDO(w.DO.Having(conds...))
+}
+
+func (w whatsappChannelDo) Limit(limit int) IWhatsappChannelDo {
+	return w.withDO(w.DO.Limit(limit))
+}
+
+func (w whatsappChannelDo) Offset(offset int) IWhatsappChannelDo {
+	return w.withDO(w.DO.Offset(offset))
+}
+
+func (w whatsappChannelDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IWhatsappChannelDo {
+	return w.withDO(w.DO.Scopes(funcs...))
+}
+
+func (w whatsappChannelDo) Unscoped() IWhatsappChannelDo {
+	return w.withDO(w.DO.Unscoped())
+}
+
+func (w whatsappChannelDo) Create(values ...*model.WhatsappChannel) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return w.DO.Create(values)
+}
+
+func (w whatsappChannelDo) CreateInBatches(values []*model.WhatsappChannel, batchSize int) error {
+	return w.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (w whatsappChannelDo) Save(values ...*model.WhatsappChannel) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return w.DO.Save(values)
+}
+
+func (w whatsappChannelDo) First() (*model.WhatsappChannel, error) {
+	if result, err := w.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WhatsappChannel), nil
+	}
+}
+
+func (w whatsappChannelDo) Take() (*model.WhatsappChannel, error) {
+	if result, err := w.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WhatsappChannel), nil
+	}
+}
+
+func (w whatsappChannelDo) Last() (*model.WhatsappChannel, error) {
+	if result, err := w.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WhatsappChannel), nil
+	}
+}
+
+func (w whatsappChannelDo) Find() ([]*model.WhatsappChannel, error) {
+	result, err := w.DO.Find()
+	return result.([]*model.WhatsappChannel), err
+}
+
+func (w whatsappChannelDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.WhatsappChannel, err error) {
+	buf := make([]*model.WhatsappChannel, 0, batchSize)
+	err = w.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (w whatsappChannelDo) FindInBatches(result *[]*model.WhatsappChannel, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return w.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (w whatsappChannelDo) Attrs(attrs ...field.AssignExpr) IWhatsappChannelDo {
+	return w.withDO(w.DO.Attrs(attrs...))
+}
+
+func (w whatsappChannelDo) Assign(attrs ...field.AssignExpr) IWhatsappChannelDo {
+	return w.withDO(w.DO.Assign(attrs...))
+}
+
+func (w whatsappChannelDo) Joins(fields ...field.RelationField) IWhatsappChannelDo {
+	for _, _f := range fields {
+		w = *w.withDO(w.DO.Joins(_f))
+	}
+	return &w
+}
+
+func (w whatsappChannelDo) Preload(fields ...field.RelationField) IWhatsappChannelDo {
+	for _, _f := range fields {
+		w = *w.withDO(w.DO.Preload(_f))
+	}
+	return &w
+}
+
+func (w whatsappChannelDo) FirstOrInit() (*model.WhatsappChannel, error) {
+	if result, err := w.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WhatsappChannel), nil
+	}
+}
+
+func (w whatsappChannelDo) FirstOrCreate() (*model.WhatsappChannel, error) {
+	if result, err := w.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WhatsappChannel), nil
+	}
+}
+
+func (w whatsappChannelDo) FindByPage(offset int, limit int) (result []*model.WhatsappChannel, count int64, err error) {
+	result, err = w.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = w.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (w whatsappChannelDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = w.Count()
+	if err != nil {
+		return
+	}
+
+	err = w.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (w whatsappChannelDo) Scan(result interface{}) (err error) {
+	return w.DO.Scan(result)
+}
+
+func (w whatsappChannelDo) Delete(models ...*model.WhatsappChannel) (result gen.ResultInfo, err error) {
+	return w.DO.Delete(models)
+}
+
+func (w *whatsappChannelDo) withDO(do gen.Dao) *whatsappChannelDo {
+	w.DO = *do.(*gen.DO)
+	return w
+}

+ 417 - 0
database/dao/wechat/query/work_experience.gen.go

@@ -0,0 +1,417 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newWorkExperience(db *gorm.DB, opts ...gen.DOOption) workExperience {
+	_workExperience := workExperience{}
+
+	_workExperience.workExperienceDo.UseDB(db, opts...)
+	_workExperience.workExperienceDo.UseModel(&model.WorkExperience{})
+
+	tableName := _workExperience.workExperienceDo.TableName()
+	_workExperience.ALL = field.NewAsterisk(tableName)
+	_workExperience.ID = field.NewInt64(tableName, "id")
+	_workExperience.EmployeeID = field.NewInt64(tableName, "employee_id")
+	_workExperience.CreatedAt = field.NewTime(tableName, "created_at")
+	_workExperience.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_workExperience.DeletedAt = field.NewField(tableName, "deleted_at")
+	_workExperience.StartDate = field.NewTime(tableName, "start_date")
+	_workExperience.EndDate = field.NewTime(tableName, "end_date")
+	_workExperience.Company = field.NewString(tableName, "company")
+	_workExperience.Experience = field.NewString(tableName, "experience")
+	_workExperience.OrganizationID = field.NewInt64(tableName, "organization_id")
+
+	_workExperience.fillFieldMap()
+
+	return _workExperience
+}
+
+// workExperience 数字员工工作经验表
+type workExperience struct {
+	workExperienceDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	EmployeeID     field.Int64  // 员工ID
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	StartDate      field.Time   // 开始时间
+	EndDate        field.Time   // 结束时间
+	Company        field.String // 公司名
+	Experience     field.String // 工作内容
+	OrganizationID field.Int64  // 机构ID
+
+	fieldMap map[string]field.Expr
+}
+
+func (w workExperience) Table(newTableName string) *workExperience {
+	w.workExperienceDo.UseTable(newTableName)
+	return w.updateTableName(newTableName)
+}
+
+func (w workExperience) As(alias string) *workExperience {
+	w.workExperienceDo.DO = *(w.workExperienceDo.As(alias).(*gen.DO))
+	return w.updateTableName(alias)
+}
+
+func (w *workExperience) updateTableName(table string) *workExperience {
+	w.ALL = field.NewAsterisk(table)
+	w.ID = field.NewInt64(table, "id")
+	w.EmployeeID = field.NewInt64(table, "employee_id")
+	w.CreatedAt = field.NewTime(table, "created_at")
+	w.UpdatedAt = field.NewTime(table, "updated_at")
+	w.DeletedAt = field.NewField(table, "deleted_at")
+	w.StartDate = field.NewTime(table, "start_date")
+	w.EndDate = field.NewTime(table, "end_date")
+	w.Company = field.NewString(table, "company")
+	w.Experience = field.NewString(table, "experience")
+	w.OrganizationID = field.NewInt64(table, "organization_id")
+
+	w.fillFieldMap()
+
+	return w
+}
+
+func (w *workExperience) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := w.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (w *workExperience) fillFieldMap() {
+	w.fieldMap = make(map[string]field.Expr, 10)
+	w.fieldMap["id"] = w.ID
+	w.fieldMap["employee_id"] = w.EmployeeID
+	w.fieldMap["created_at"] = w.CreatedAt
+	w.fieldMap["updated_at"] = w.UpdatedAt
+	w.fieldMap["deleted_at"] = w.DeletedAt
+	w.fieldMap["start_date"] = w.StartDate
+	w.fieldMap["end_date"] = w.EndDate
+	w.fieldMap["company"] = w.Company
+	w.fieldMap["experience"] = w.Experience
+	w.fieldMap["organization_id"] = w.OrganizationID
+}
+
+func (w workExperience) clone(db *gorm.DB) workExperience {
+	w.workExperienceDo.ReplaceConnPool(db.Statement.ConnPool)
+	return w
+}
+
+func (w workExperience) replaceDB(db *gorm.DB) workExperience {
+	w.workExperienceDo.ReplaceDB(db)
+	return w
+}
+
+type workExperienceDo struct{ gen.DO }
+
+type IWorkExperienceDo interface {
+	gen.SubQuery
+	Debug() IWorkExperienceDo
+	WithContext(ctx context.Context) IWorkExperienceDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IWorkExperienceDo
+	WriteDB() IWorkExperienceDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IWorkExperienceDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IWorkExperienceDo
+	Not(conds ...gen.Condition) IWorkExperienceDo
+	Or(conds ...gen.Condition) IWorkExperienceDo
+	Select(conds ...field.Expr) IWorkExperienceDo
+	Where(conds ...gen.Condition) IWorkExperienceDo
+	Order(conds ...field.Expr) IWorkExperienceDo
+	Distinct(cols ...field.Expr) IWorkExperienceDo
+	Omit(cols ...field.Expr) IWorkExperienceDo
+	Join(table schema.Tabler, on ...field.Expr) IWorkExperienceDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IWorkExperienceDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IWorkExperienceDo
+	Group(cols ...field.Expr) IWorkExperienceDo
+	Having(conds ...gen.Condition) IWorkExperienceDo
+	Limit(limit int) IWorkExperienceDo
+	Offset(offset int) IWorkExperienceDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IWorkExperienceDo
+	Unscoped() IWorkExperienceDo
+	Create(values ...*model.WorkExperience) error
+	CreateInBatches(values []*model.WorkExperience, batchSize int) error
+	Save(values ...*model.WorkExperience) error
+	First() (*model.WorkExperience, error)
+	Take() (*model.WorkExperience, error)
+	Last() (*model.WorkExperience, error)
+	Find() ([]*model.WorkExperience, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.WorkExperience, err error)
+	FindInBatches(result *[]*model.WorkExperience, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.WorkExperience) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IWorkExperienceDo
+	Assign(attrs ...field.AssignExpr) IWorkExperienceDo
+	Joins(fields ...field.RelationField) IWorkExperienceDo
+	Preload(fields ...field.RelationField) IWorkExperienceDo
+	FirstOrInit() (*model.WorkExperience, error)
+	FirstOrCreate() (*model.WorkExperience, error)
+	FindByPage(offset int, limit int) (result []*model.WorkExperience, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IWorkExperienceDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (w workExperienceDo) Debug() IWorkExperienceDo {
+	return w.withDO(w.DO.Debug())
+}
+
+func (w workExperienceDo) WithContext(ctx context.Context) IWorkExperienceDo {
+	return w.withDO(w.DO.WithContext(ctx))
+}
+
+func (w workExperienceDo) ReadDB() IWorkExperienceDo {
+	return w.Clauses(dbresolver.Read)
+}
+
+func (w workExperienceDo) WriteDB() IWorkExperienceDo {
+	return w.Clauses(dbresolver.Write)
+}
+
+func (w workExperienceDo) Session(config *gorm.Session) IWorkExperienceDo {
+	return w.withDO(w.DO.Session(config))
+}
+
+func (w workExperienceDo) Clauses(conds ...clause.Expression) IWorkExperienceDo {
+	return w.withDO(w.DO.Clauses(conds...))
+}
+
+func (w workExperienceDo) Returning(value interface{}, columns ...string) IWorkExperienceDo {
+	return w.withDO(w.DO.Returning(value, columns...))
+}
+
+func (w workExperienceDo) Not(conds ...gen.Condition) IWorkExperienceDo {
+	return w.withDO(w.DO.Not(conds...))
+}
+
+func (w workExperienceDo) Or(conds ...gen.Condition) IWorkExperienceDo {
+	return w.withDO(w.DO.Or(conds...))
+}
+
+func (w workExperienceDo) Select(conds ...field.Expr) IWorkExperienceDo {
+	return w.withDO(w.DO.Select(conds...))
+}
+
+func (w workExperienceDo) Where(conds ...gen.Condition) IWorkExperienceDo {
+	return w.withDO(w.DO.Where(conds...))
+}
+
+func (w workExperienceDo) Order(conds ...field.Expr) IWorkExperienceDo {
+	return w.withDO(w.DO.Order(conds...))
+}
+
+func (w workExperienceDo) Distinct(cols ...field.Expr) IWorkExperienceDo {
+	return w.withDO(w.DO.Distinct(cols...))
+}
+
+func (w workExperienceDo) Omit(cols ...field.Expr) IWorkExperienceDo {
+	return w.withDO(w.DO.Omit(cols...))
+}
+
+func (w workExperienceDo) Join(table schema.Tabler, on ...field.Expr) IWorkExperienceDo {
+	return w.withDO(w.DO.Join(table, on...))
+}
+
+func (w workExperienceDo) LeftJoin(table schema.Tabler, on ...field.Expr) IWorkExperienceDo {
+	return w.withDO(w.DO.LeftJoin(table, on...))
+}
+
+func (w workExperienceDo) RightJoin(table schema.Tabler, on ...field.Expr) IWorkExperienceDo {
+	return w.withDO(w.DO.RightJoin(table, on...))
+}
+
+func (w workExperienceDo) Group(cols ...field.Expr) IWorkExperienceDo {
+	return w.withDO(w.DO.Group(cols...))
+}
+
+func (w workExperienceDo) Having(conds ...gen.Condition) IWorkExperienceDo {
+	return w.withDO(w.DO.Having(conds...))
+}
+
+func (w workExperienceDo) Limit(limit int) IWorkExperienceDo {
+	return w.withDO(w.DO.Limit(limit))
+}
+
+func (w workExperienceDo) Offset(offset int) IWorkExperienceDo {
+	return w.withDO(w.DO.Offset(offset))
+}
+
+func (w workExperienceDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IWorkExperienceDo {
+	return w.withDO(w.DO.Scopes(funcs...))
+}
+
+func (w workExperienceDo) Unscoped() IWorkExperienceDo {
+	return w.withDO(w.DO.Unscoped())
+}
+
+func (w workExperienceDo) Create(values ...*model.WorkExperience) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return w.DO.Create(values)
+}
+
+func (w workExperienceDo) CreateInBatches(values []*model.WorkExperience, batchSize int) error {
+	return w.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (w workExperienceDo) Save(values ...*model.WorkExperience) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return w.DO.Save(values)
+}
+
+func (w workExperienceDo) First() (*model.WorkExperience, error) {
+	if result, err := w.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WorkExperience), nil
+	}
+}
+
+func (w workExperienceDo) Take() (*model.WorkExperience, error) {
+	if result, err := w.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WorkExperience), nil
+	}
+}
+
+func (w workExperienceDo) Last() (*model.WorkExperience, error) {
+	if result, err := w.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WorkExperience), nil
+	}
+}
+
+func (w workExperienceDo) Find() ([]*model.WorkExperience, error) {
+	result, err := w.DO.Find()
+	return result.([]*model.WorkExperience), err
+}
+
+func (w workExperienceDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.WorkExperience, err error) {
+	buf := make([]*model.WorkExperience, 0, batchSize)
+	err = w.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (w workExperienceDo) FindInBatches(result *[]*model.WorkExperience, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return w.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (w workExperienceDo) Attrs(attrs ...field.AssignExpr) IWorkExperienceDo {
+	return w.withDO(w.DO.Attrs(attrs...))
+}
+
+func (w workExperienceDo) Assign(attrs ...field.AssignExpr) IWorkExperienceDo {
+	return w.withDO(w.DO.Assign(attrs...))
+}
+
+func (w workExperienceDo) Joins(fields ...field.RelationField) IWorkExperienceDo {
+	for _, _f := range fields {
+		w = *w.withDO(w.DO.Joins(_f))
+	}
+	return &w
+}
+
+func (w workExperienceDo) Preload(fields ...field.RelationField) IWorkExperienceDo {
+	for _, _f := range fields {
+		w = *w.withDO(w.DO.Preload(_f))
+	}
+	return &w
+}
+
+func (w workExperienceDo) FirstOrInit() (*model.WorkExperience, error) {
+	if result, err := w.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WorkExperience), nil
+	}
+}
+
+func (w workExperienceDo) FirstOrCreate() (*model.WorkExperience, error) {
+	if result, err := w.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WorkExperience), nil
+	}
+}
+
+func (w workExperienceDo) FindByPage(offset int, limit int) (result []*model.WorkExperience, count int64, err error) {
+	result, err = w.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = w.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (w workExperienceDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = w.Count()
+	if err != nil {
+		return
+	}
+
+	err = w.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (w workExperienceDo) Scan(result interface{}) (err error) {
+	return w.DO.Scan(result)
+}
+
+func (w workExperienceDo) Delete(models ...*model.WorkExperience) (result gen.ResultInfo, err error) {
+	return w.DO.Delete(models)
+}
+
+func (w *workExperienceDo) withDO(do gen.Dao) *workExperienceDo {
+	w.DO = *do.(*gen.DO)
+	return w
+}

+ 424 - 0
database/dao/wechat/query/wp_chatroom.gen.go

@@ -0,0 +1,424 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newWpChatroom(db *gorm.DB, opts ...gen.DOOption) wpChatroom {
+	_wpChatroom := wpChatroom{}
+
+	_wpChatroom.wpChatroomDo.UseDB(db, opts...)
+	_wpChatroom.wpChatroomDo.UseModel(&model.WpChatroom{})
+
+	tableName := _wpChatroom.wpChatroomDo.TableName()
+	_wpChatroom.ALL = field.NewAsterisk(tableName)
+	_wpChatroom.ID = field.NewInt64(tableName, "id")
+	_wpChatroom.CreatedAt = field.NewTime(tableName, "created_at")
+	_wpChatroom.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_wpChatroom.Status = field.NewInt64(tableName, "status")
+	_wpChatroom.DeletedAt = field.NewField(tableName, "deleted_at")
+	_wpChatroom.WxWxid = field.NewString(tableName, "wx_wxid")
+	_wpChatroom.ChatroomID = field.NewString(tableName, "chatroom_id")
+	_wpChatroom.Nickname = field.NewString(tableName, "nickname")
+	_wpChatroom.Owner = field.NewString(tableName, "owner")
+	_wpChatroom.Avatar = field.NewString(tableName, "avatar")
+	_wpChatroom.MemberList = field.NewString(tableName, "member_list")
+	_wpChatroom.ShowNameList = field.NewString(tableName, "show_name_list")
+
+	_wpChatroom.fillFieldMap()
+
+	return _wpChatroom
+}
+
+type wpChatroom struct {
+	wpChatroomDo
+
+	ALL          field.Asterisk
+	ID           field.Int64
+	CreatedAt    field.Time   // Create Time | 创建日期
+	UpdatedAt    field.Time   // Update Time | 修改日期
+	Status       field.Int64  // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt    field.Field  // Delete Time | 删除日期
+	WxWxid       field.String // 属主微信id
+	ChatroomID   field.String // 微信id 公众号微信ID
+	Nickname     field.String // 微信昵称 群备注名称
+	Owner        field.String // 群主微信id
+	Avatar       field.String // 头像
+	MemberList   field.String
+	ShowNameList field.String
+
+	fieldMap map[string]field.Expr
+}
+
+func (w wpChatroom) Table(newTableName string) *wpChatroom {
+	w.wpChatroomDo.UseTable(newTableName)
+	return w.updateTableName(newTableName)
+}
+
+func (w wpChatroom) As(alias string) *wpChatroom {
+	w.wpChatroomDo.DO = *(w.wpChatroomDo.As(alias).(*gen.DO))
+	return w.updateTableName(alias)
+}
+
+func (w *wpChatroom) updateTableName(table string) *wpChatroom {
+	w.ALL = field.NewAsterisk(table)
+	w.ID = field.NewInt64(table, "id")
+	w.CreatedAt = field.NewTime(table, "created_at")
+	w.UpdatedAt = field.NewTime(table, "updated_at")
+	w.Status = field.NewInt64(table, "status")
+	w.DeletedAt = field.NewField(table, "deleted_at")
+	w.WxWxid = field.NewString(table, "wx_wxid")
+	w.ChatroomID = field.NewString(table, "chatroom_id")
+	w.Nickname = field.NewString(table, "nickname")
+	w.Owner = field.NewString(table, "owner")
+	w.Avatar = field.NewString(table, "avatar")
+	w.MemberList = field.NewString(table, "member_list")
+	w.ShowNameList = field.NewString(table, "show_name_list")
+
+	w.fillFieldMap()
+
+	return w
+}
+
+func (w *wpChatroom) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := w.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (w *wpChatroom) fillFieldMap() {
+	w.fieldMap = make(map[string]field.Expr, 12)
+	w.fieldMap["id"] = w.ID
+	w.fieldMap["created_at"] = w.CreatedAt
+	w.fieldMap["updated_at"] = w.UpdatedAt
+	w.fieldMap["status"] = w.Status
+	w.fieldMap["deleted_at"] = w.DeletedAt
+	w.fieldMap["wx_wxid"] = w.WxWxid
+	w.fieldMap["chatroom_id"] = w.ChatroomID
+	w.fieldMap["nickname"] = w.Nickname
+	w.fieldMap["owner"] = w.Owner
+	w.fieldMap["avatar"] = w.Avatar
+	w.fieldMap["member_list"] = w.MemberList
+	w.fieldMap["show_name_list"] = w.ShowNameList
+}
+
+func (w wpChatroom) clone(db *gorm.DB) wpChatroom {
+	w.wpChatroomDo.ReplaceConnPool(db.Statement.ConnPool)
+	return w
+}
+
+func (w wpChatroom) replaceDB(db *gorm.DB) wpChatroom {
+	w.wpChatroomDo.ReplaceDB(db)
+	return w
+}
+
+type wpChatroomDo struct{ gen.DO }
+
+type IWpChatroomDo interface {
+	gen.SubQuery
+	Debug() IWpChatroomDo
+	WithContext(ctx context.Context) IWpChatroomDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IWpChatroomDo
+	WriteDB() IWpChatroomDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IWpChatroomDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IWpChatroomDo
+	Not(conds ...gen.Condition) IWpChatroomDo
+	Or(conds ...gen.Condition) IWpChatroomDo
+	Select(conds ...field.Expr) IWpChatroomDo
+	Where(conds ...gen.Condition) IWpChatroomDo
+	Order(conds ...field.Expr) IWpChatroomDo
+	Distinct(cols ...field.Expr) IWpChatroomDo
+	Omit(cols ...field.Expr) IWpChatroomDo
+	Join(table schema.Tabler, on ...field.Expr) IWpChatroomDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IWpChatroomDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IWpChatroomDo
+	Group(cols ...field.Expr) IWpChatroomDo
+	Having(conds ...gen.Condition) IWpChatroomDo
+	Limit(limit int) IWpChatroomDo
+	Offset(offset int) IWpChatroomDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IWpChatroomDo
+	Unscoped() IWpChatroomDo
+	Create(values ...*model.WpChatroom) error
+	CreateInBatches(values []*model.WpChatroom, batchSize int) error
+	Save(values ...*model.WpChatroom) error
+	First() (*model.WpChatroom, error)
+	Take() (*model.WpChatroom, error)
+	Last() (*model.WpChatroom, error)
+	Find() ([]*model.WpChatroom, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.WpChatroom, err error)
+	FindInBatches(result *[]*model.WpChatroom, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.WpChatroom) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IWpChatroomDo
+	Assign(attrs ...field.AssignExpr) IWpChatroomDo
+	Joins(fields ...field.RelationField) IWpChatroomDo
+	Preload(fields ...field.RelationField) IWpChatroomDo
+	FirstOrInit() (*model.WpChatroom, error)
+	FirstOrCreate() (*model.WpChatroom, error)
+	FindByPage(offset int, limit int) (result []*model.WpChatroom, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IWpChatroomDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (w wpChatroomDo) Debug() IWpChatroomDo {
+	return w.withDO(w.DO.Debug())
+}
+
+func (w wpChatroomDo) WithContext(ctx context.Context) IWpChatroomDo {
+	return w.withDO(w.DO.WithContext(ctx))
+}
+
+func (w wpChatroomDo) ReadDB() IWpChatroomDo {
+	return w.Clauses(dbresolver.Read)
+}
+
+func (w wpChatroomDo) WriteDB() IWpChatroomDo {
+	return w.Clauses(dbresolver.Write)
+}
+
+func (w wpChatroomDo) Session(config *gorm.Session) IWpChatroomDo {
+	return w.withDO(w.DO.Session(config))
+}
+
+func (w wpChatroomDo) Clauses(conds ...clause.Expression) IWpChatroomDo {
+	return w.withDO(w.DO.Clauses(conds...))
+}
+
+func (w wpChatroomDo) Returning(value interface{}, columns ...string) IWpChatroomDo {
+	return w.withDO(w.DO.Returning(value, columns...))
+}
+
+func (w wpChatroomDo) Not(conds ...gen.Condition) IWpChatroomDo {
+	return w.withDO(w.DO.Not(conds...))
+}
+
+func (w wpChatroomDo) Or(conds ...gen.Condition) IWpChatroomDo {
+	return w.withDO(w.DO.Or(conds...))
+}
+
+func (w wpChatroomDo) Select(conds ...field.Expr) IWpChatroomDo {
+	return w.withDO(w.DO.Select(conds...))
+}
+
+func (w wpChatroomDo) Where(conds ...gen.Condition) IWpChatroomDo {
+	return w.withDO(w.DO.Where(conds...))
+}
+
+func (w wpChatroomDo) Order(conds ...field.Expr) IWpChatroomDo {
+	return w.withDO(w.DO.Order(conds...))
+}
+
+func (w wpChatroomDo) Distinct(cols ...field.Expr) IWpChatroomDo {
+	return w.withDO(w.DO.Distinct(cols...))
+}
+
+func (w wpChatroomDo) Omit(cols ...field.Expr) IWpChatroomDo {
+	return w.withDO(w.DO.Omit(cols...))
+}
+
+func (w wpChatroomDo) Join(table schema.Tabler, on ...field.Expr) IWpChatroomDo {
+	return w.withDO(w.DO.Join(table, on...))
+}
+
+func (w wpChatroomDo) LeftJoin(table schema.Tabler, on ...field.Expr) IWpChatroomDo {
+	return w.withDO(w.DO.LeftJoin(table, on...))
+}
+
+func (w wpChatroomDo) RightJoin(table schema.Tabler, on ...field.Expr) IWpChatroomDo {
+	return w.withDO(w.DO.RightJoin(table, on...))
+}
+
+func (w wpChatroomDo) Group(cols ...field.Expr) IWpChatroomDo {
+	return w.withDO(w.DO.Group(cols...))
+}
+
+func (w wpChatroomDo) Having(conds ...gen.Condition) IWpChatroomDo {
+	return w.withDO(w.DO.Having(conds...))
+}
+
+func (w wpChatroomDo) Limit(limit int) IWpChatroomDo {
+	return w.withDO(w.DO.Limit(limit))
+}
+
+func (w wpChatroomDo) Offset(offset int) IWpChatroomDo {
+	return w.withDO(w.DO.Offset(offset))
+}
+
+func (w wpChatroomDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IWpChatroomDo {
+	return w.withDO(w.DO.Scopes(funcs...))
+}
+
+func (w wpChatroomDo) Unscoped() IWpChatroomDo {
+	return w.withDO(w.DO.Unscoped())
+}
+
+func (w wpChatroomDo) Create(values ...*model.WpChatroom) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return w.DO.Create(values)
+}
+
+func (w wpChatroomDo) CreateInBatches(values []*model.WpChatroom, batchSize int) error {
+	return w.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (w wpChatroomDo) Save(values ...*model.WpChatroom) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return w.DO.Save(values)
+}
+
+func (w wpChatroomDo) First() (*model.WpChatroom, error) {
+	if result, err := w.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WpChatroom), nil
+	}
+}
+
+func (w wpChatroomDo) Take() (*model.WpChatroom, error) {
+	if result, err := w.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WpChatroom), nil
+	}
+}
+
+func (w wpChatroomDo) Last() (*model.WpChatroom, error) {
+	if result, err := w.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WpChatroom), nil
+	}
+}
+
+func (w wpChatroomDo) Find() ([]*model.WpChatroom, error) {
+	result, err := w.DO.Find()
+	return result.([]*model.WpChatroom), err
+}
+
+func (w wpChatroomDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.WpChatroom, err error) {
+	buf := make([]*model.WpChatroom, 0, batchSize)
+	err = w.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (w wpChatroomDo) FindInBatches(result *[]*model.WpChatroom, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return w.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (w wpChatroomDo) Attrs(attrs ...field.AssignExpr) IWpChatroomDo {
+	return w.withDO(w.DO.Attrs(attrs...))
+}
+
+func (w wpChatroomDo) Assign(attrs ...field.AssignExpr) IWpChatroomDo {
+	return w.withDO(w.DO.Assign(attrs...))
+}
+
+func (w wpChatroomDo) Joins(fields ...field.RelationField) IWpChatroomDo {
+	for _, _f := range fields {
+		w = *w.withDO(w.DO.Joins(_f))
+	}
+	return &w
+}
+
+func (w wpChatroomDo) Preload(fields ...field.RelationField) IWpChatroomDo {
+	for _, _f := range fields {
+		w = *w.withDO(w.DO.Preload(_f))
+	}
+	return &w
+}
+
+func (w wpChatroomDo) FirstOrInit() (*model.WpChatroom, error) {
+	if result, err := w.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WpChatroom), nil
+	}
+}
+
+func (w wpChatroomDo) FirstOrCreate() (*model.WpChatroom, error) {
+	if result, err := w.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WpChatroom), nil
+	}
+}
+
+func (w wpChatroomDo) FindByPage(offset int, limit int) (result []*model.WpChatroom, count int64, err error) {
+	result, err = w.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = w.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (w wpChatroomDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = w.Count()
+	if err != nil {
+		return
+	}
+
+	err = w.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (w wpChatroomDo) Scan(result interface{}) (err error) {
+	return w.DO.Scan(result)
+}
+
+func (w wpChatroomDo) Delete(models ...*model.WpChatroom) (result gen.ResultInfo, err error) {
+	return w.DO.Delete(models)
+}
+
+func (w *wpChatroomDo) withDO(do gen.Dao) *wpChatroomDo {
+	w.DO = *do.(*gen.DO)
+	return w
+}

+ 412 - 0
database/dao/wechat/query/wp_chatroom_member.gen.go

@@ -0,0 +1,412 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newWpChatroomMember(db *gorm.DB, opts ...gen.DOOption) wpChatroomMember {
+	_wpChatroomMember := wpChatroomMember{}
+
+	_wpChatroomMember.wpChatroomMemberDo.UseDB(db, opts...)
+	_wpChatroomMember.wpChatroomMemberDo.UseModel(&model.WpChatroomMember{})
+
+	tableName := _wpChatroomMember.wpChatroomMemberDo.TableName()
+	_wpChatroomMember.ALL = field.NewAsterisk(tableName)
+	_wpChatroomMember.ID = field.NewInt64(tableName, "id")
+	_wpChatroomMember.CreatedAt = field.NewTime(tableName, "created_at")
+	_wpChatroomMember.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_wpChatroomMember.Status = field.NewInt64(tableName, "status")
+	_wpChatroomMember.DeletedAt = field.NewField(tableName, "deleted_at")
+	_wpChatroomMember.WxWxid = field.NewString(tableName, "wx_wxid")
+	_wpChatroomMember.Wxid = field.NewString(tableName, "wxid")
+	_wpChatroomMember.Nickname = field.NewString(tableName, "nickname")
+	_wpChatroomMember.Avatar = field.NewString(tableName, "avatar")
+
+	_wpChatroomMember.fillFieldMap()
+
+	return _wpChatroomMember
+}
+
+type wpChatroomMember struct {
+	wpChatroomMemberDo
+
+	ALL       field.Asterisk
+	ID        field.Int64
+	CreatedAt field.Time   // Create Time | 创建日期
+	UpdatedAt field.Time   // Update Time | 修改日期
+	Status    field.Int64  // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt field.Field  // Delete Time | 删除日期
+	WxWxid    field.String // 属主微信id
+	Wxid      field.String // 微信id
+	Nickname  field.String // 微信昵称 群备注名称
+	Avatar    field.String // 头像
+
+	fieldMap map[string]field.Expr
+}
+
+func (w wpChatroomMember) Table(newTableName string) *wpChatroomMember {
+	w.wpChatroomMemberDo.UseTable(newTableName)
+	return w.updateTableName(newTableName)
+}
+
+func (w wpChatroomMember) As(alias string) *wpChatroomMember {
+	w.wpChatroomMemberDo.DO = *(w.wpChatroomMemberDo.As(alias).(*gen.DO))
+	return w.updateTableName(alias)
+}
+
+func (w *wpChatroomMember) updateTableName(table string) *wpChatroomMember {
+	w.ALL = field.NewAsterisk(table)
+	w.ID = field.NewInt64(table, "id")
+	w.CreatedAt = field.NewTime(table, "created_at")
+	w.UpdatedAt = field.NewTime(table, "updated_at")
+	w.Status = field.NewInt64(table, "status")
+	w.DeletedAt = field.NewField(table, "deleted_at")
+	w.WxWxid = field.NewString(table, "wx_wxid")
+	w.Wxid = field.NewString(table, "wxid")
+	w.Nickname = field.NewString(table, "nickname")
+	w.Avatar = field.NewString(table, "avatar")
+
+	w.fillFieldMap()
+
+	return w
+}
+
+func (w *wpChatroomMember) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := w.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (w *wpChatroomMember) fillFieldMap() {
+	w.fieldMap = make(map[string]field.Expr, 9)
+	w.fieldMap["id"] = w.ID
+	w.fieldMap["created_at"] = w.CreatedAt
+	w.fieldMap["updated_at"] = w.UpdatedAt
+	w.fieldMap["status"] = w.Status
+	w.fieldMap["deleted_at"] = w.DeletedAt
+	w.fieldMap["wx_wxid"] = w.WxWxid
+	w.fieldMap["wxid"] = w.Wxid
+	w.fieldMap["nickname"] = w.Nickname
+	w.fieldMap["avatar"] = w.Avatar
+}
+
+func (w wpChatroomMember) clone(db *gorm.DB) wpChatroomMember {
+	w.wpChatroomMemberDo.ReplaceConnPool(db.Statement.ConnPool)
+	return w
+}
+
+func (w wpChatroomMember) replaceDB(db *gorm.DB) wpChatroomMember {
+	w.wpChatroomMemberDo.ReplaceDB(db)
+	return w
+}
+
+type wpChatroomMemberDo struct{ gen.DO }
+
+type IWpChatroomMemberDo interface {
+	gen.SubQuery
+	Debug() IWpChatroomMemberDo
+	WithContext(ctx context.Context) IWpChatroomMemberDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IWpChatroomMemberDo
+	WriteDB() IWpChatroomMemberDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IWpChatroomMemberDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IWpChatroomMemberDo
+	Not(conds ...gen.Condition) IWpChatroomMemberDo
+	Or(conds ...gen.Condition) IWpChatroomMemberDo
+	Select(conds ...field.Expr) IWpChatroomMemberDo
+	Where(conds ...gen.Condition) IWpChatroomMemberDo
+	Order(conds ...field.Expr) IWpChatroomMemberDo
+	Distinct(cols ...field.Expr) IWpChatroomMemberDo
+	Omit(cols ...field.Expr) IWpChatroomMemberDo
+	Join(table schema.Tabler, on ...field.Expr) IWpChatroomMemberDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IWpChatroomMemberDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IWpChatroomMemberDo
+	Group(cols ...field.Expr) IWpChatroomMemberDo
+	Having(conds ...gen.Condition) IWpChatroomMemberDo
+	Limit(limit int) IWpChatroomMemberDo
+	Offset(offset int) IWpChatroomMemberDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IWpChatroomMemberDo
+	Unscoped() IWpChatroomMemberDo
+	Create(values ...*model.WpChatroomMember) error
+	CreateInBatches(values []*model.WpChatroomMember, batchSize int) error
+	Save(values ...*model.WpChatroomMember) error
+	First() (*model.WpChatroomMember, error)
+	Take() (*model.WpChatroomMember, error)
+	Last() (*model.WpChatroomMember, error)
+	Find() ([]*model.WpChatroomMember, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.WpChatroomMember, err error)
+	FindInBatches(result *[]*model.WpChatroomMember, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.WpChatroomMember) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IWpChatroomMemberDo
+	Assign(attrs ...field.AssignExpr) IWpChatroomMemberDo
+	Joins(fields ...field.RelationField) IWpChatroomMemberDo
+	Preload(fields ...field.RelationField) IWpChatroomMemberDo
+	FirstOrInit() (*model.WpChatroomMember, error)
+	FirstOrCreate() (*model.WpChatroomMember, error)
+	FindByPage(offset int, limit int) (result []*model.WpChatroomMember, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IWpChatroomMemberDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (w wpChatroomMemberDo) Debug() IWpChatroomMemberDo {
+	return w.withDO(w.DO.Debug())
+}
+
+func (w wpChatroomMemberDo) WithContext(ctx context.Context) IWpChatroomMemberDo {
+	return w.withDO(w.DO.WithContext(ctx))
+}
+
+func (w wpChatroomMemberDo) ReadDB() IWpChatroomMemberDo {
+	return w.Clauses(dbresolver.Read)
+}
+
+func (w wpChatroomMemberDo) WriteDB() IWpChatroomMemberDo {
+	return w.Clauses(dbresolver.Write)
+}
+
+func (w wpChatroomMemberDo) Session(config *gorm.Session) IWpChatroomMemberDo {
+	return w.withDO(w.DO.Session(config))
+}
+
+func (w wpChatroomMemberDo) Clauses(conds ...clause.Expression) IWpChatroomMemberDo {
+	return w.withDO(w.DO.Clauses(conds...))
+}
+
+func (w wpChatroomMemberDo) Returning(value interface{}, columns ...string) IWpChatroomMemberDo {
+	return w.withDO(w.DO.Returning(value, columns...))
+}
+
+func (w wpChatroomMemberDo) Not(conds ...gen.Condition) IWpChatroomMemberDo {
+	return w.withDO(w.DO.Not(conds...))
+}
+
+func (w wpChatroomMemberDo) Or(conds ...gen.Condition) IWpChatroomMemberDo {
+	return w.withDO(w.DO.Or(conds...))
+}
+
+func (w wpChatroomMemberDo) Select(conds ...field.Expr) IWpChatroomMemberDo {
+	return w.withDO(w.DO.Select(conds...))
+}
+
+func (w wpChatroomMemberDo) Where(conds ...gen.Condition) IWpChatroomMemberDo {
+	return w.withDO(w.DO.Where(conds...))
+}
+
+func (w wpChatroomMemberDo) Order(conds ...field.Expr) IWpChatroomMemberDo {
+	return w.withDO(w.DO.Order(conds...))
+}
+
+func (w wpChatroomMemberDo) Distinct(cols ...field.Expr) IWpChatroomMemberDo {
+	return w.withDO(w.DO.Distinct(cols...))
+}
+
+func (w wpChatroomMemberDo) Omit(cols ...field.Expr) IWpChatroomMemberDo {
+	return w.withDO(w.DO.Omit(cols...))
+}
+
+func (w wpChatroomMemberDo) Join(table schema.Tabler, on ...field.Expr) IWpChatroomMemberDo {
+	return w.withDO(w.DO.Join(table, on...))
+}
+
+func (w wpChatroomMemberDo) LeftJoin(table schema.Tabler, on ...field.Expr) IWpChatroomMemberDo {
+	return w.withDO(w.DO.LeftJoin(table, on...))
+}
+
+func (w wpChatroomMemberDo) RightJoin(table schema.Tabler, on ...field.Expr) IWpChatroomMemberDo {
+	return w.withDO(w.DO.RightJoin(table, on...))
+}
+
+func (w wpChatroomMemberDo) Group(cols ...field.Expr) IWpChatroomMemberDo {
+	return w.withDO(w.DO.Group(cols...))
+}
+
+func (w wpChatroomMemberDo) Having(conds ...gen.Condition) IWpChatroomMemberDo {
+	return w.withDO(w.DO.Having(conds...))
+}
+
+func (w wpChatroomMemberDo) Limit(limit int) IWpChatroomMemberDo {
+	return w.withDO(w.DO.Limit(limit))
+}
+
+func (w wpChatroomMemberDo) Offset(offset int) IWpChatroomMemberDo {
+	return w.withDO(w.DO.Offset(offset))
+}
+
+func (w wpChatroomMemberDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IWpChatroomMemberDo {
+	return w.withDO(w.DO.Scopes(funcs...))
+}
+
+func (w wpChatroomMemberDo) Unscoped() IWpChatroomMemberDo {
+	return w.withDO(w.DO.Unscoped())
+}
+
+func (w wpChatroomMemberDo) Create(values ...*model.WpChatroomMember) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return w.DO.Create(values)
+}
+
+func (w wpChatroomMemberDo) CreateInBatches(values []*model.WpChatroomMember, batchSize int) error {
+	return w.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (w wpChatroomMemberDo) Save(values ...*model.WpChatroomMember) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return w.DO.Save(values)
+}
+
+func (w wpChatroomMemberDo) First() (*model.WpChatroomMember, error) {
+	if result, err := w.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WpChatroomMember), nil
+	}
+}
+
+func (w wpChatroomMemberDo) Take() (*model.WpChatroomMember, error) {
+	if result, err := w.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WpChatroomMember), nil
+	}
+}
+
+func (w wpChatroomMemberDo) Last() (*model.WpChatroomMember, error) {
+	if result, err := w.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WpChatroomMember), nil
+	}
+}
+
+func (w wpChatroomMemberDo) Find() ([]*model.WpChatroomMember, error) {
+	result, err := w.DO.Find()
+	return result.([]*model.WpChatroomMember), err
+}
+
+func (w wpChatroomMemberDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.WpChatroomMember, err error) {
+	buf := make([]*model.WpChatroomMember, 0, batchSize)
+	err = w.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (w wpChatroomMemberDo) FindInBatches(result *[]*model.WpChatroomMember, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return w.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (w wpChatroomMemberDo) Attrs(attrs ...field.AssignExpr) IWpChatroomMemberDo {
+	return w.withDO(w.DO.Attrs(attrs...))
+}
+
+func (w wpChatroomMemberDo) Assign(attrs ...field.AssignExpr) IWpChatroomMemberDo {
+	return w.withDO(w.DO.Assign(attrs...))
+}
+
+func (w wpChatroomMemberDo) Joins(fields ...field.RelationField) IWpChatroomMemberDo {
+	for _, _f := range fields {
+		w = *w.withDO(w.DO.Joins(_f))
+	}
+	return &w
+}
+
+func (w wpChatroomMemberDo) Preload(fields ...field.RelationField) IWpChatroomMemberDo {
+	for _, _f := range fields {
+		w = *w.withDO(w.DO.Preload(_f))
+	}
+	return &w
+}
+
+func (w wpChatroomMemberDo) FirstOrInit() (*model.WpChatroomMember, error) {
+	if result, err := w.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WpChatroomMember), nil
+	}
+}
+
+func (w wpChatroomMemberDo) FirstOrCreate() (*model.WpChatroomMember, error) {
+	if result, err := w.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WpChatroomMember), nil
+	}
+}
+
+func (w wpChatroomMemberDo) FindByPage(offset int, limit int) (result []*model.WpChatroomMember, count int64, err error) {
+	result, err = w.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = w.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (w wpChatroomMemberDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = w.Count()
+	if err != nil {
+		return
+	}
+
+	err = w.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (w wpChatroomMemberDo) Scan(result interface{}) (err error) {
+	return w.DO.Scan(result)
+}
+
+func (w wpChatroomMemberDo) Delete(models ...*model.WpChatroomMember) (result gen.ResultInfo, err error) {
+	return w.DO.Delete(models)
+}
+
+func (w *wpChatroomMemberDo) withDO(do gen.Dao) *wpChatroomMemberDo {
+	w.DO = *do.(*gen.DO)
+	return w
+}

+ 468 - 0
database/dao/wechat/query/wx.gen.go

@@ -0,0 +1,468 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newWx(db *gorm.DB, opts ...gen.DOOption) wx {
+	_wx := wx{}
+
+	_wx.wxDo.UseDB(db, opts...)
+	_wx.wxDo.UseModel(&model.Wx{})
+
+	tableName := _wx.wxDo.TableName()
+	_wx.ALL = field.NewAsterisk(tableName)
+	_wx.ID = field.NewInt64(tableName, "id")
+	_wx.CreatedAt = field.NewTime(tableName, "created_at")
+	_wx.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_wx.Status = field.NewInt64(tableName, "status")
+	_wx.DeletedAt = field.NewField(tableName, "deleted_at")
+	_wx.Port = field.NewString(tableName, "port")
+	_wx.ProcessID = field.NewString(tableName, "process_id")
+	_wx.Callback = field.NewString(tableName, "callback")
+	_wx.Wxid = field.NewString(tableName, "wxid")
+	_wx.Account = field.NewString(tableName, "account")
+	_wx.Nickname = field.NewString(tableName, "nickname")
+	_wx.Tel = field.NewString(tableName, "tel")
+	_wx.HeadBig = field.NewString(tableName, "head_big")
+	_wx.ServerID = field.NewInt64(tableName, "server_id")
+	_wx.OrganizationID = field.NewInt64(tableName, "organization_id")
+	_wx.AgentID = field.NewInt64(tableName, "agent_id")
+	_wx.APIBase = field.NewString(tableName, "api_base")
+	_wx.APIKey = field.NewString(tableName, "api_key")
+	_wx.AllowList = field.NewString(tableName, "allow_list")
+	_wx.GroupAllowList = field.NewString(tableName, "group_allow_list")
+	_wx.BlockList = field.NewString(tableName, "block_list")
+	_wx.GroupBlockList = field.NewString(tableName, "group_block_list")
+	_wx.Ctype = field.NewInt64(tableName, "ctype")
+
+	_wx.fillFieldMap()
+
+	return _wx
+}
+
+type wx struct {
+	wxDo
+
+	ALL            field.Asterisk
+	ID             field.Int64
+	CreatedAt      field.Time   // Create Time | 创建日期
+	UpdatedAt      field.Time   // Update Time | 修改日期
+	Status         field.Int64  // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt      field.Field  // Delete Time | 删除日期
+	Port           field.String // 端口号
+	ProcessID      field.String // 进程号
+	Callback       field.String // 回调地址
+	Wxid           field.String // 微信id
+	Account        field.String // 微信账号
+	Nickname       field.String // 微信昵称
+	Tel            field.String // 手机号
+	HeadBig        field.String // 微信头像
+	ServerID       field.Int64  // 服务器id
+	OrganizationID field.Int64  // 机构 ID
+	AgentID        field.Int64  // 0 fastgpt
+	APIBase        field.String
+	APIKey         field.String
+	AllowList      field.String // 白名单,以数组存储wxid。当包含 ALL 字符串时为全部允许
+	GroupAllowList field.String // 群白名单,以数组存储wxid。当包含 ALL 字符串时为全部允许
+	BlockList      field.String // 黑名单,以数组存储wxid。当包含 ALL 字符串时为全部拒绝
+	GroupBlockList field.String // 群黑名单,以数组存储wxid。当包含 ALL 字符串时为全部拒绝
+	Ctype          field.Int64  // 内容类型:1-个微 3-企微
+
+	fieldMap map[string]field.Expr
+}
+
+func (w wx) Table(newTableName string) *wx {
+	w.wxDo.UseTable(newTableName)
+	return w.updateTableName(newTableName)
+}
+
+func (w wx) As(alias string) *wx {
+	w.wxDo.DO = *(w.wxDo.As(alias).(*gen.DO))
+	return w.updateTableName(alias)
+}
+
+func (w *wx) updateTableName(table string) *wx {
+	w.ALL = field.NewAsterisk(table)
+	w.ID = field.NewInt64(table, "id")
+	w.CreatedAt = field.NewTime(table, "created_at")
+	w.UpdatedAt = field.NewTime(table, "updated_at")
+	w.Status = field.NewInt64(table, "status")
+	w.DeletedAt = field.NewField(table, "deleted_at")
+	w.Port = field.NewString(table, "port")
+	w.ProcessID = field.NewString(table, "process_id")
+	w.Callback = field.NewString(table, "callback")
+	w.Wxid = field.NewString(table, "wxid")
+	w.Account = field.NewString(table, "account")
+	w.Nickname = field.NewString(table, "nickname")
+	w.Tel = field.NewString(table, "tel")
+	w.HeadBig = field.NewString(table, "head_big")
+	w.ServerID = field.NewInt64(table, "server_id")
+	w.OrganizationID = field.NewInt64(table, "organization_id")
+	w.AgentID = field.NewInt64(table, "agent_id")
+	w.APIBase = field.NewString(table, "api_base")
+	w.APIKey = field.NewString(table, "api_key")
+	w.AllowList = field.NewString(table, "allow_list")
+	w.GroupAllowList = field.NewString(table, "group_allow_list")
+	w.BlockList = field.NewString(table, "block_list")
+	w.GroupBlockList = field.NewString(table, "group_block_list")
+	w.Ctype = field.NewInt64(table, "ctype")
+
+	w.fillFieldMap()
+
+	return w
+}
+
+func (w *wx) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := w.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (w *wx) fillFieldMap() {
+	w.fieldMap = make(map[string]field.Expr, 23)
+	w.fieldMap["id"] = w.ID
+	w.fieldMap["created_at"] = w.CreatedAt
+	w.fieldMap["updated_at"] = w.UpdatedAt
+	w.fieldMap["status"] = w.Status
+	w.fieldMap["deleted_at"] = w.DeletedAt
+	w.fieldMap["port"] = w.Port
+	w.fieldMap["process_id"] = w.ProcessID
+	w.fieldMap["callback"] = w.Callback
+	w.fieldMap["wxid"] = w.Wxid
+	w.fieldMap["account"] = w.Account
+	w.fieldMap["nickname"] = w.Nickname
+	w.fieldMap["tel"] = w.Tel
+	w.fieldMap["head_big"] = w.HeadBig
+	w.fieldMap["server_id"] = w.ServerID
+	w.fieldMap["organization_id"] = w.OrganizationID
+	w.fieldMap["agent_id"] = w.AgentID
+	w.fieldMap["api_base"] = w.APIBase
+	w.fieldMap["api_key"] = w.APIKey
+	w.fieldMap["allow_list"] = w.AllowList
+	w.fieldMap["group_allow_list"] = w.GroupAllowList
+	w.fieldMap["block_list"] = w.BlockList
+	w.fieldMap["group_block_list"] = w.GroupBlockList
+	w.fieldMap["ctype"] = w.Ctype
+}
+
+func (w wx) clone(db *gorm.DB) wx {
+	w.wxDo.ReplaceConnPool(db.Statement.ConnPool)
+	return w
+}
+
+func (w wx) replaceDB(db *gorm.DB) wx {
+	w.wxDo.ReplaceDB(db)
+	return w
+}
+
+type wxDo struct{ gen.DO }
+
+type IWxDo interface {
+	gen.SubQuery
+	Debug() IWxDo
+	WithContext(ctx context.Context) IWxDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IWxDo
+	WriteDB() IWxDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IWxDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IWxDo
+	Not(conds ...gen.Condition) IWxDo
+	Or(conds ...gen.Condition) IWxDo
+	Select(conds ...field.Expr) IWxDo
+	Where(conds ...gen.Condition) IWxDo
+	Order(conds ...field.Expr) IWxDo
+	Distinct(cols ...field.Expr) IWxDo
+	Omit(cols ...field.Expr) IWxDo
+	Join(table schema.Tabler, on ...field.Expr) IWxDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IWxDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IWxDo
+	Group(cols ...field.Expr) IWxDo
+	Having(conds ...gen.Condition) IWxDo
+	Limit(limit int) IWxDo
+	Offset(offset int) IWxDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IWxDo
+	Unscoped() IWxDo
+	Create(values ...*model.Wx) error
+	CreateInBatches(values []*model.Wx, batchSize int) error
+	Save(values ...*model.Wx) error
+	First() (*model.Wx, error)
+	Take() (*model.Wx, error)
+	Last() (*model.Wx, error)
+	Find() ([]*model.Wx, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Wx, err error)
+	FindInBatches(result *[]*model.Wx, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.Wx) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IWxDo
+	Assign(attrs ...field.AssignExpr) IWxDo
+	Joins(fields ...field.RelationField) IWxDo
+	Preload(fields ...field.RelationField) IWxDo
+	FirstOrInit() (*model.Wx, error)
+	FirstOrCreate() (*model.Wx, error)
+	FindByPage(offset int, limit int) (result []*model.Wx, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IWxDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (w wxDo) Debug() IWxDo {
+	return w.withDO(w.DO.Debug())
+}
+
+func (w wxDo) WithContext(ctx context.Context) IWxDo {
+	return w.withDO(w.DO.WithContext(ctx))
+}
+
+func (w wxDo) ReadDB() IWxDo {
+	return w.Clauses(dbresolver.Read)
+}
+
+func (w wxDo) WriteDB() IWxDo {
+	return w.Clauses(dbresolver.Write)
+}
+
+func (w wxDo) Session(config *gorm.Session) IWxDo {
+	return w.withDO(w.DO.Session(config))
+}
+
+func (w wxDo) Clauses(conds ...clause.Expression) IWxDo {
+	return w.withDO(w.DO.Clauses(conds...))
+}
+
+func (w wxDo) Returning(value interface{}, columns ...string) IWxDo {
+	return w.withDO(w.DO.Returning(value, columns...))
+}
+
+func (w wxDo) Not(conds ...gen.Condition) IWxDo {
+	return w.withDO(w.DO.Not(conds...))
+}
+
+func (w wxDo) Or(conds ...gen.Condition) IWxDo {
+	return w.withDO(w.DO.Or(conds...))
+}
+
+func (w wxDo) Select(conds ...field.Expr) IWxDo {
+	return w.withDO(w.DO.Select(conds...))
+}
+
+func (w wxDo) Where(conds ...gen.Condition) IWxDo {
+	return w.withDO(w.DO.Where(conds...))
+}
+
+func (w wxDo) Order(conds ...field.Expr) IWxDo {
+	return w.withDO(w.DO.Order(conds...))
+}
+
+func (w wxDo) Distinct(cols ...field.Expr) IWxDo {
+	return w.withDO(w.DO.Distinct(cols...))
+}
+
+func (w wxDo) Omit(cols ...field.Expr) IWxDo {
+	return w.withDO(w.DO.Omit(cols...))
+}
+
+func (w wxDo) Join(table schema.Tabler, on ...field.Expr) IWxDo {
+	return w.withDO(w.DO.Join(table, on...))
+}
+
+func (w wxDo) LeftJoin(table schema.Tabler, on ...field.Expr) IWxDo {
+	return w.withDO(w.DO.LeftJoin(table, on...))
+}
+
+func (w wxDo) RightJoin(table schema.Tabler, on ...field.Expr) IWxDo {
+	return w.withDO(w.DO.RightJoin(table, on...))
+}
+
+func (w wxDo) Group(cols ...field.Expr) IWxDo {
+	return w.withDO(w.DO.Group(cols...))
+}
+
+func (w wxDo) Having(conds ...gen.Condition) IWxDo {
+	return w.withDO(w.DO.Having(conds...))
+}
+
+func (w wxDo) Limit(limit int) IWxDo {
+	return w.withDO(w.DO.Limit(limit))
+}
+
+func (w wxDo) Offset(offset int) IWxDo {
+	return w.withDO(w.DO.Offset(offset))
+}
+
+func (w wxDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IWxDo {
+	return w.withDO(w.DO.Scopes(funcs...))
+}
+
+func (w wxDo) Unscoped() IWxDo {
+	return w.withDO(w.DO.Unscoped())
+}
+
+func (w wxDo) Create(values ...*model.Wx) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return w.DO.Create(values)
+}
+
+func (w wxDo) CreateInBatches(values []*model.Wx, batchSize int) error {
+	return w.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (w wxDo) Save(values ...*model.Wx) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return w.DO.Save(values)
+}
+
+func (w wxDo) First() (*model.Wx, error) {
+	if result, err := w.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Wx), nil
+	}
+}
+
+func (w wxDo) Take() (*model.Wx, error) {
+	if result, err := w.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Wx), nil
+	}
+}
+
+func (w wxDo) Last() (*model.Wx, error) {
+	if result, err := w.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Wx), nil
+	}
+}
+
+func (w wxDo) Find() ([]*model.Wx, error) {
+	result, err := w.DO.Find()
+	return result.([]*model.Wx), err
+}
+
+func (w wxDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Wx, err error) {
+	buf := make([]*model.Wx, 0, batchSize)
+	err = w.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (w wxDo) FindInBatches(result *[]*model.Wx, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return w.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (w wxDo) Attrs(attrs ...field.AssignExpr) IWxDo {
+	return w.withDO(w.DO.Attrs(attrs...))
+}
+
+func (w wxDo) Assign(attrs ...field.AssignExpr) IWxDo {
+	return w.withDO(w.DO.Assign(attrs...))
+}
+
+func (w wxDo) Joins(fields ...field.RelationField) IWxDo {
+	for _, _f := range fields {
+		w = *w.withDO(w.DO.Joins(_f))
+	}
+	return &w
+}
+
+func (w wxDo) Preload(fields ...field.RelationField) IWxDo {
+	for _, _f := range fields {
+		w = *w.withDO(w.DO.Preload(_f))
+	}
+	return &w
+}
+
+func (w wxDo) FirstOrInit() (*model.Wx, error) {
+	if result, err := w.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Wx), nil
+	}
+}
+
+func (w wxDo) FirstOrCreate() (*model.Wx, error) {
+	if result, err := w.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.Wx), nil
+	}
+}
+
+func (w wxDo) FindByPage(offset int, limit int) (result []*model.Wx, count int64, err error) {
+	result, err = w.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = w.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (w wxDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = w.Count()
+	if err != nil {
+		return
+	}
+
+	err = w.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (w wxDo) Scan(result interface{}) (err error) {
+	return w.DO.Scan(result)
+}
+
+func (w wxDo) Delete(models ...*model.Wx) (result gen.ResultInfo, err error) {
+	return w.DO.Delete(models)
+}
+
+func (w *wxDo) withDO(do gen.Dao) *wxDo {
+	w.DO = *do.(*gen.DO)
+	return w
+}

+ 453 - 0
database/dao/wechat/query/wx_card.gen.go

@@ -0,0 +1,453 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newWxCard(db *gorm.DB, opts ...gen.DOOption) wxCard {
+	_wxCard := wxCard{}
+
+	_wxCard.wxCardDo.UseDB(db, opts...)
+	_wxCard.wxCardDo.UseModel(&model.WxCard{})
+
+	tableName := _wxCard.wxCardDo.TableName()
+	_wxCard.ALL = field.NewAsterisk(tableName)
+	_wxCard.ID = field.NewInt64(tableName, "id")
+	_wxCard.CreatedAt = field.NewTime(tableName, "created_at")
+	_wxCard.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_wxCard.DeletedAt = field.NewField(tableName, "deleted_at")
+	_wxCard.UserID = field.NewInt64(tableName, "user_id")
+	_wxCard.WxUserID = field.NewInt64(tableName, "wx_user_id")
+	_wxCard.Avatar = field.NewString(tableName, "avatar")
+	_wxCard.Logo = field.NewString(tableName, "logo")
+	_wxCard.Name = field.NewString(tableName, "name")
+	_wxCard.Company = field.NewString(tableName, "company")
+	_wxCard.Address = field.NewString(tableName, "address")
+	_wxCard.Phone = field.NewString(tableName, "phone")
+	_wxCard.OfficialAccount = field.NewString(tableName, "official_account")
+	_wxCard.WechatAccount = field.NewString(tableName, "wechat_account")
+	_wxCard.Email = field.NewString(tableName, "email")
+	_wxCard.APIBase = field.NewString(tableName, "api_base")
+	_wxCard.APIKey = field.NewString(tableName, "api_key")
+	_wxCard.AiInfo = field.NewString(tableName, "ai_info")
+	_wxCard.Intro = field.NewString(tableName, "intro")
+
+	_wxCard.fillFieldMap()
+
+	return _wxCard
+}
+
+// wxCard 名片表
+type wxCard struct {
+	wxCardDo
+
+	ALL             field.Asterisk
+	ID              field.Int64
+	CreatedAt       field.Time   // Create Time | 创建日期
+	UpdatedAt       field.Time   // Update Time | 修改日期
+	DeletedAt       field.Field  // Delete Time | 删除日期
+	UserID          field.Int64  // use表ID
+	WxUserID        field.Int64  // wx表ID
+	Avatar          field.String // 头像
+	Logo            field.String // Logo
+	Name            field.String // 名称
+	Company         field.String // 公司
+	Address         field.String // 地址
+	Phone           field.String // 手机号
+	OfficialAccount field.String // 公众号
+	WechatAccount   field.String // 微信号
+	Email           field.String // 邮箱
+	APIBase         field.String // fastgpt-base
+	APIKey          field.String // fastgpt-key
+	AiInfo          field.String // AI信息
+	Intro           field.String // 简介
+
+	fieldMap map[string]field.Expr
+}
+
+func (w wxCard) Table(newTableName string) *wxCard {
+	w.wxCardDo.UseTable(newTableName)
+	return w.updateTableName(newTableName)
+}
+
+func (w wxCard) As(alias string) *wxCard {
+	w.wxCardDo.DO = *(w.wxCardDo.As(alias).(*gen.DO))
+	return w.updateTableName(alias)
+}
+
+func (w *wxCard) updateTableName(table string) *wxCard {
+	w.ALL = field.NewAsterisk(table)
+	w.ID = field.NewInt64(table, "id")
+	w.CreatedAt = field.NewTime(table, "created_at")
+	w.UpdatedAt = field.NewTime(table, "updated_at")
+	w.DeletedAt = field.NewField(table, "deleted_at")
+	w.UserID = field.NewInt64(table, "user_id")
+	w.WxUserID = field.NewInt64(table, "wx_user_id")
+	w.Avatar = field.NewString(table, "avatar")
+	w.Logo = field.NewString(table, "logo")
+	w.Name = field.NewString(table, "name")
+	w.Company = field.NewString(table, "company")
+	w.Address = field.NewString(table, "address")
+	w.Phone = field.NewString(table, "phone")
+	w.OfficialAccount = field.NewString(table, "official_account")
+	w.WechatAccount = field.NewString(table, "wechat_account")
+	w.Email = field.NewString(table, "email")
+	w.APIBase = field.NewString(table, "api_base")
+	w.APIKey = field.NewString(table, "api_key")
+	w.AiInfo = field.NewString(table, "ai_info")
+	w.Intro = field.NewString(table, "intro")
+
+	w.fillFieldMap()
+
+	return w
+}
+
+func (w *wxCard) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := w.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (w *wxCard) fillFieldMap() {
+	w.fieldMap = make(map[string]field.Expr, 19)
+	w.fieldMap["id"] = w.ID
+	w.fieldMap["created_at"] = w.CreatedAt
+	w.fieldMap["updated_at"] = w.UpdatedAt
+	w.fieldMap["deleted_at"] = w.DeletedAt
+	w.fieldMap["user_id"] = w.UserID
+	w.fieldMap["wx_user_id"] = w.WxUserID
+	w.fieldMap["avatar"] = w.Avatar
+	w.fieldMap["logo"] = w.Logo
+	w.fieldMap["name"] = w.Name
+	w.fieldMap["company"] = w.Company
+	w.fieldMap["address"] = w.Address
+	w.fieldMap["phone"] = w.Phone
+	w.fieldMap["official_account"] = w.OfficialAccount
+	w.fieldMap["wechat_account"] = w.WechatAccount
+	w.fieldMap["email"] = w.Email
+	w.fieldMap["api_base"] = w.APIBase
+	w.fieldMap["api_key"] = w.APIKey
+	w.fieldMap["ai_info"] = w.AiInfo
+	w.fieldMap["intro"] = w.Intro
+}
+
+func (w wxCard) clone(db *gorm.DB) wxCard {
+	w.wxCardDo.ReplaceConnPool(db.Statement.ConnPool)
+	return w
+}
+
+func (w wxCard) replaceDB(db *gorm.DB) wxCard {
+	w.wxCardDo.ReplaceDB(db)
+	return w
+}
+
+type wxCardDo struct{ gen.DO }
+
+type IWxCardDo interface {
+	gen.SubQuery
+	Debug() IWxCardDo
+	WithContext(ctx context.Context) IWxCardDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IWxCardDo
+	WriteDB() IWxCardDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IWxCardDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IWxCardDo
+	Not(conds ...gen.Condition) IWxCardDo
+	Or(conds ...gen.Condition) IWxCardDo
+	Select(conds ...field.Expr) IWxCardDo
+	Where(conds ...gen.Condition) IWxCardDo
+	Order(conds ...field.Expr) IWxCardDo
+	Distinct(cols ...field.Expr) IWxCardDo
+	Omit(cols ...field.Expr) IWxCardDo
+	Join(table schema.Tabler, on ...field.Expr) IWxCardDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IWxCardDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IWxCardDo
+	Group(cols ...field.Expr) IWxCardDo
+	Having(conds ...gen.Condition) IWxCardDo
+	Limit(limit int) IWxCardDo
+	Offset(offset int) IWxCardDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IWxCardDo
+	Unscoped() IWxCardDo
+	Create(values ...*model.WxCard) error
+	CreateInBatches(values []*model.WxCard, batchSize int) error
+	Save(values ...*model.WxCard) error
+	First() (*model.WxCard, error)
+	Take() (*model.WxCard, error)
+	Last() (*model.WxCard, error)
+	Find() ([]*model.WxCard, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.WxCard, err error)
+	FindInBatches(result *[]*model.WxCard, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.WxCard) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IWxCardDo
+	Assign(attrs ...field.AssignExpr) IWxCardDo
+	Joins(fields ...field.RelationField) IWxCardDo
+	Preload(fields ...field.RelationField) IWxCardDo
+	FirstOrInit() (*model.WxCard, error)
+	FirstOrCreate() (*model.WxCard, error)
+	FindByPage(offset int, limit int) (result []*model.WxCard, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IWxCardDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (w wxCardDo) Debug() IWxCardDo {
+	return w.withDO(w.DO.Debug())
+}
+
+func (w wxCardDo) WithContext(ctx context.Context) IWxCardDo {
+	return w.withDO(w.DO.WithContext(ctx))
+}
+
+func (w wxCardDo) ReadDB() IWxCardDo {
+	return w.Clauses(dbresolver.Read)
+}
+
+func (w wxCardDo) WriteDB() IWxCardDo {
+	return w.Clauses(dbresolver.Write)
+}
+
+func (w wxCardDo) Session(config *gorm.Session) IWxCardDo {
+	return w.withDO(w.DO.Session(config))
+}
+
+func (w wxCardDo) Clauses(conds ...clause.Expression) IWxCardDo {
+	return w.withDO(w.DO.Clauses(conds...))
+}
+
+func (w wxCardDo) Returning(value interface{}, columns ...string) IWxCardDo {
+	return w.withDO(w.DO.Returning(value, columns...))
+}
+
+func (w wxCardDo) Not(conds ...gen.Condition) IWxCardDo {
+	return w.withDO(w.DO.Not(conds...))
+}
+
+func (w wxCardDo) Or(conds ...gen.Condition) IWxCardDo {
+	return w.withDO(w.DO.Or(conds...))
+}
+
+func (w wxCardDo) Select(conds ...field.Expr) IWxCardDo {
+	return w.withDO(w.DO.Select(conds...))
+}
+
+func (w wxCardDo) Where(conds ...gen.Condition) IWxCardDo {
+	return w.withDO(w.DO.Where(conds...))
+}
+
+func (w wxCardDo) Order(conds ...field.Expr) IWxCardDo {
+	return w.withDO(w.DO.Order(conds...))
+}
+
+func (w wxCardDo) Distinct(cols ...field.Expr) IWxCardDo {
+	return w.withDO(w.DO.Distinct(cols...))
+}
+
+func (w wxCardDo) Omit(cols ...field.Expr) IWxCardDo {
+	return w.withDO(w.DO.Omit(cols...))
+}
+
+func (w wxCardDo) Join(table schema.Tabler, on ...field.Expr) IWxCardDo {
+	return w.withDO(w.DO.Join(table, on...))
+}
+
+func (w wxCardDo) LeftJoin(table schema.Tabler, on ...field.Expr) IWxCardDo {
+	return w.withDO(w.DO.LeftJoin(table, on...))
+}
+
+func (w wxCardDo) RightJoin(table schema.Tabler, on ...field.Expr) IWxCardDo {
+	return w.withDO(w.DO.RightJoin(table, on...))
+}
+
+func (w wxCardDo) Group(cols ...field.Expr) IWxCardDo {
+	return w.withDO(w.DO.Group(cols...))
+}
+
+func (w wxCardDo) Having(conds ...gen.Condition) IWxCardDo {
+	return w.withDO(w.DO.Having(conds...))
+}
+
+func (w wxCardDo) Limit(limit int) IWxCardDo {
+	return w.withDO(w.DO.Limit(limit))
+}
+
+func (w wxCardDo) Offset(offset int) IWxCardDo {
+	return w.withDO(w.DO.Offset(offset))
+}
+
+func (w wxCardDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IWxCardDo {
+	return w.withDO(w.DO.Scopes(funcs...))
+}
+
+func (w wxCardDo) Unscoped() IWxCardDo {
+	return w.withDO(w.DO.Unscoped())
+}
+
+func (w wxCardDo) Create(values ...*model.WxCard) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return w.DO.Create(values)
+}
+
+func (w wxCardDo) CreateInBatches(values []*model.WxCard, batchSize int) error {
+	return w.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (w wxCardDo) Save(values ...*model.WxCard) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return w.DO.Save(values)
+}
+
+func (w wxCardDo) First() (*model.WxCard, error) {
+	if result, err := w.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WxCard), nil
+	}
+}
+
+func (w wxCardDo) Take() (*model.WxCard, error) {
+	if result, err := w.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WxCard), nil
+	}
+}
+
+func (w wxCardDo) Last() (*model.WxCard, error) {
+	if result, err := w.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WxCard), nil
+	}
+}
+
+func (w wxCardDo) Find() ([]*model.WxCard, error) {
+	result, err := w.DO.Find()
+	return result.([]*model.WxCard), err
+}
+
+func (w wxCardDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.WxCard, err error) {
+	buf := make([]*model.WxCard, 0, batchSize)
+	err = w.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (w wxCardDo) FindInBatches(result *[]*model.WxCard, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return w.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (w wxCardDo) Attrs(attrs ...field.AssignExpr) IWxCardDo {
+	return w.withDO(w.DO.Attrs(attrs...))
+}
+
+func (w wxCardDo) Assign(attrs ...field.AssignExpr) IWxCardDo {
+	return w.withDO(w.DO.Assign(attrs...))
+}
+
+func (w wxCardDo) Joins(fields ...field.RelationField) IWxCardDo {
+	for _, _f := range fields {
+		w = *w.withDO(w.DO.Joins(_f))
+	}
+	return &w
+}
+
+func (w wxCardDo) Preload(fields ...field.RelationField) IWxCardDo {
+	for _, _f := range fields {
+		w = *w.withDO(w.DO.Preload(_f))
+	}
+	return &w
+}
+
+func (w wxCardDo) FirstOrInit() (*model.WxCard, error) {
+	if result, err := w.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WxCard), nil
+	}
+}
+
+func (w wxCardDo) FirstOrCreate() (*model.WxCard, error) {
+	if result, err := w.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WxCard), nil
+	}
+}
+
+func (w wxCardDo) FindByPage(offset int, limit int) (result []*model.WxCard, count int64, err error) {
+	result, err = w.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = w.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (w wxCardDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = w.Count()
+	if err != nil {
+		return
+	}
+
+	err = w.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (w wxCardDo) Scan(result interface{}) (err error) {
+	return w.DO.Scan(result)
+}
+
+func (w wxCardDo) Delete(models ...*model.WxCard) (result gen.ResultInfo, err error) {
+	return w.DO.Delete(models)
+}
+
+func (w *wxCardDo) withDO(do gen.Dao) *wxCardDo {
+	w.DO = *do.(*gen.DO)
+	return w
+}

+ 433 - 0
database/dao/wechat/query/wx_card_user.gen.go

@@ -0,0 +1,433 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newWxCardUser(db *gorm.DB, opts ...gen.DOOption) wxCardUser {
+	_wxCardUser := wxCardUser{}
+
+	_wxCardUser.wxCardUserDo.UseDB(db, opts...)
+	_wxCardUser.wxCardUserDo.UseModel(&model.WxCardUser{})
+
+	tableName := _wxCardUser.wxCardUserDo.TableName()
+	_wxCardUser.ALL = field.NewAsterisk(tableName)
+	_wxCardUser.ID = field.NewInt64(tableName, "id")
+	_wxCardUser.CreatedAt = field.NewTime(tableName, "created_at")
+	_wxCardUser.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_wxCardUser.DeletedAt = field.NewField(tableName, "deleted_at")
+	_wxCardUser.Wxid = field.NewString(tableName, "wxid")
+	_wxCardUser.Account = field.NewString(tableName, "account")
+	_wxCardUser.Nickname = field.NewString(tableName, "nickname")
+	_wxCardUser.Remark = field.NewString(tableName, "remark")
+	_wxCardUser.Avatar = field.NewString(tableName, "avatar")
+	_wxCardUser.Phone = field.NewString(tableName, "phone")
+	_wxCardUser.OpenID = field.NewString(tableName, "open_id")
+	_wxCardUser.UnionID = field.NewString(tableName, "union_id")
+	_wxCardUser.SessionKey = field.NewString(tableName, "session_key")
+	_wxCardUser.IsVip = field.NewInt64(tableName, "is_vip")
+
+	_wxCardUser.fillFieldMap()
+
+	return _wxCardUser
+}
+
+// wxCardUser 微信用户表
+type wxCardUser struct {
+	wxCardUserDo
+
+	ALL        field.Asterisk
+	ID         field.Int64
+	CreatedAt  field.Time   // Create Time | 创建日期
+	UpdatedAt  field.Time   // Update Time | 修改日期
+	DeletedAt  field.Field  // Delete Time | 删除日期
+	Wxid       field.String // 微信id
+	Account    field.String // 微信账号
+	Nickname   field.String // 微信昵称
+	Remark     field.String // 备注名
+	Avatar     field.String // 头像
+	Phone      field.String // 手机号
+	OpenID     field.String // OpenId
+	UnionID    field.String // UnionId
+	SessionKey field.String // SessionKey
+	IsVip      field.Int64  // 是否VIP:0-否 1-是
+
+	fieldMap map[string]field.Expr
+}
+
+func (w wxCardUser) Table(newTableName string) *wxCardUser {
+	w.wxCardUserDo.UseTable(newTableName)
+	return w.updateTableName(newTableName)
+}
+
+func (w wxCardUser) As(alias string) *wxCardUser {
+	w.wxCardUserDo.DO = *(w.wxCardUserDo.As(alias).(*gen.DO))
+	return w.updateTableName(alias)
+}
+
+func (w *wxCardUser) updateTableName(table string) *wxCardUser {
+	w.ALL = field.NewAsterisk(table)
+	w.ID = field.NewInt64(table, "id")
+	w.CreatedAt = field.NewTime(table, "created_at")
+	w.UpdatedAt = field.NewTime(table, "updated_at")
+	w.DeletedAt = field.NewField(table, "deleted_at")
+	w.Wxid = field.NewString(table, "wxid")
+	w.Account = field.NewString(table, "account")
+	w.Nickname = field.NewString(table, "nickname")
+	w.Remark = field.NewString(table, "remark")
+	w.Avatar = field.NewString(table, "avatar")
+	w.Phone = field.NewString(table, "phone")
+	w.OpenID = field.NewString(table, "open_id")
+	w.UnionID = field.NewString(table, "union_id")
+	w.SessionKey = field.NewString(table, "session_key")
+	w.IsVip = field.NewInt64(table, "is_vip")
+
+	w.fillFieldMap()
+
+	return w
+}
+
+func (w *wxCardUser) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := w.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (w *wxCardUser) fillFieldMap() {
+	w.fieldMap = make(map[string]field.Expr, 14)
+	w.fieldMap["id"] = w.ID
+	w.fieldMap["created_at"] = w.CreatedAt
+	w.fieldMap["updated_at"] = w.UpdatedAt
+	w.fieldMap["deleted_at"] = w.DeletedAt
+	w.fieldMap["wxid"] = w.Wxid
+	w.fieldMap["account"] = w.Account
+	w.fieldMap["nickname"] = w.Nickname
+	w.fieldMap["remark"] = w.Remark
+	w.fieldMap["avatar"] = w.Avatar
+	w.fieldMap["phone"] = w.Phone
+	w.fieldMap["open_id"] = w.OpenID
+	w.fieldMap["union_id"] = w.UnionID
+	w.fieldMap["session_key"] = w.SessionKey
+	w.fieldMap["is_vip"] = w.IsVip
+}
+
+func (w wxCardUser) clone(db *gorm.DB) wxCardUser {
+	w.wxCardUserDo.ReplaceConnPool(db.Statement.ConnPool)
+	return w
+}
+
+func (w wxCardUser) replaceDB(db *gorm.DB) wxCardUser {
+	w.wxCardUserDo.ReplaceDB(db)
+	return w
+}
+
+type wxCardUserDo struct{ gen.DO }
+
+type IWxCardUserDo interface {
+	gen.SubQuery
+	Debug() IWxCardUserDo
+	WithContext(ctx context.Context) IWxCardUserDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IWxCardUserDo
+	WriteDB() IWxCardUserDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IWxCardUserDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IWxCardUserDo
+	Not(conds ...gen.Condition) IWxCardUserDo
+	Or(conds ...gen.Condition) IWxCardUserDo
+	Select(conds ...field.Expr) IWxCardUserDo
+	Where(conds ...gen.Condition) IWxCardUserDo
+	Order(conds ...field.Expr) IWxCardUserDo
+	Distinct(cols ...field.Expr) IWxCardUserDo
+	Omit(cols ...field.Expr) IWxCardUserDo
+	Join(table schema.Tabler, on ...field.Expr) IWxCardUserDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IWxCardUserDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IWxCardUserDo
+	Group(cols ...field.Expr) IWxCardUserDo
+	Having(conds ...gen.Condition) IWxCardUserDo
+	Limit(limit int) IWxCardUserDo
+	Offset(offset int) IWxCardUserDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IWxCardUserDo
+	Unscoped() IWxCardUserDo
+	Create(values ...*model.WxCardUser) error
+	CreateInBatches(values []*model.WxCardUser, batchSize int) error
+	Save(values ...*model.WxCardUser) error
+	First() (*model.WxCardUser, error)
+	Take() (*model.WxCardUser, error)
+	Last() (*model.WxCardUser, error)
+	Find() ([]*model.WxCardUser, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.WxCardUser, err error)
+	FindInBatches(result *[]*model.WxCardUser, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.WxCardUser) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IWxCardUserDo
+	Assign(attrs ...field.AssignExpr) IWxCardUserDo
+	Joins(fields ...field.RelationField) IWxCardUserDo
+	Preload(fields ...field.RelationField) IWxCardUserDo
+	FirstOrInit() (*model.WxCardUser, error)
+	FirstOrCreate() (*model.WxCardUser, error)
+	FindByPage(offset int, limit int) (result []*model.WxCardUser, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IWxCardUserDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (w wxCardUserDo) Debug() IWxCardUserDo {
+	return w.withDO(w.DO.Debug())
+}
+
+func (w wxCardUserDo) WithContext(ctx context.Context) IWxCardUserDo {
+	return w.withDO(w.DO.WithContext(ctx))
+}
+
+func (w wxCardUserDo) ReadDB() IWxCardUserDo {
+	return w.Clauses(dbresolver.Read)
+}
+
+func (w wxCardUserDo) WriteDB() IWxCardUserDo {
+	return w.Clauses(dbresolver.Write)
+}
+
+func (w wxCardUserDo) Session(config *gorm.Session) IWxCardUserDo {
+	return w.withDO(w.DO.Session(config))
+}
+
+func (w wxCardUserDo) Clauses(conds ...clause.Expression) IWxCardUserDo {
+	return w.withDO(w.DO.Clauses(conds...))
+}
+
+func (w wxCardUserDo) Returning(value interface{}, columns ...string) IWxCardUserDo {
+	return w.withDO(w.DO.Returning(value, columns...))
+}
+
+func (w wxCardUserDo) Not(conds ...gen.Condition) IWxCardUserDo {
+	return w.withDO(w.DO.Not(conds...))
+}
+
+func (w wxCardUserDo) Or(conds ...gen.Condition) IWxCardUserDo {
+	return w.withDO(w.DO.Or(conds...))
+}
+
+func (w wxCardUserDo) Select(conds ...field.Expr) IWxCardUserDo {
+	return w.withDO(w.DO.Select(conds...))
+}
+
+func (w wxCardUserDo) Where(conds ...gen.Condition) IWxCardUserDo {
+	return w.withDO(w.DO.Where(conds...))
+}
+
+func (w wxCardUserDo) Order(conds ...field.Expr) IWxCardUserDo {
+	return w.withDO(w.DO.Order(conds...))
+}
+
+func (w wxCardUserDo) Distinct(cols ...field.Expr) IWxCardUserDo {
+	return w.withDO(w.DO.Distinct(cols...))
+}
+
+func (w wxCardUserDo) Omit(cols ...field.Expr) IWxCardUserDo {
+	return w.withDO(w.DO.Omit(cols...))
+}
+
+func (w wxCardUserDo) Join(table schema.Tabler, on ...field.Expr) IWxCardUserDo {
+	return w.withDO(w.DO.Join(table, on...))
+}
+
+func (w wxCardUserDo) LeftJoin(table schema.Tabler, on ...field.Expr) IWxCardUserDo {
+	return w.withDO(w.DO.LeftJoin(table, on...))
+}
+
+func (w wxCardUserDo) RightJoin(table schema.Tabler, on ...field.Expr) IWxCardUserDo {
+	return w.withDO(w.DO.RightJoin(table, on...))
+}
+
+func (w wxCardUserDo) Group(cols ...field.Expr) IWxCardUserDo {
+	return w.withDO(w.DO.Group(cols...))
+}
+
+func (w wxCardUserDo) Having(conds ...gen.Condition) IWxCardUserDo {
+	return w.withDO(w.DO.Having(conds...))
+}
+
+func (w wxCardUserDo) Limit(limit int) IWxCardUserDo {
+	return w.withDO(w.DO.Limit(limit))
+}
+
+func (w wxCardUserDo) Offset(offset int) IWxCardUserDo {
+	return w.withDO(w.DO.Offset(offset))
+}
+
+func (w wxCardUserDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IWxCardUserDo {
+	return w.withDO(w.DO.Scopes(funcs...))
+}
+
+func (w wxCardUserDo) Unscoped() IWxCardUserDo {
+	return w.withDO(w.DO.Unscoped())
+}
+
+func (w wxCardUserDo) Create(values ...*model.WxCardUser) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return w.DO.Create(values)
+}
+
+func (w wxCardUserDo) CreateInBatches(values []*model.WxCardUser, batchSize int) error {
+	return w.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (w wxCardUserDo) Save(values ...*model.WxCardUser) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return w.DO.Save(values)
+}
+
+func (w wxCardUserDo) First() (*model.WxCardUser, error) {
+	if result, err := w.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WxCardUser), nil
+	}
+}
+
+func (w wxCardUserDo) Take() (*model.WxCardUser, error) {
+	if result, err := w.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WxCardUser), nil
+	}
+}
+
+func (w wxCardUserDo) Last() (*model.WxCardUser, error) {
+	if result, err := w.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WxCardUser), nil
+	}
+}
+
+func (w wxCardUserDo) Find() ([]*model.WxCardUser, error) {
+	result, err := w.DO.Find()
+	return result.([]*model.WxCardUser), err
+}
+
+func (w wxCardUserDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.WxCardUser, err error) {
+	buf := make([]*model.WxCardUser, 0, batchSize)
+	err = w.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (w wxCardUserDo) FindInBatches(result *[]*model.WxCardUser, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return w.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (w wxCardUserDo) Attrs(attrs ...field.AssignExpr) IWxCardUserDo {
+	return w.withDO(w.DO.Attrs(attrs...))
+}
+
+func (w wxCardUserDo) Assign(attrs ...field.AssignExpr) IWxCardUserDo {
+	return w.withDO(w.DO.Assign(attrs...))
+}
+
+func (w wxCardUserDo) Joins(fields ...field.RelationField) IWxCardUserDo {
+	for _, _f := range fields {
+		w = *w.withDO(w.DO.Joins(_f))
+	}
+	return &w
+}
+
+func (w wxCardUserDo) Preload(fields ...field.RelationField) IWxCardUserDo {
+	for _, _f := range fields {
+		w = *w.withDO(w.DO.Preload(_f))
+	}
+	return &w
+}
+
+func (w wxCardUserDo) FirstOrInit() (*model.WxCardUser, error) {
+	if result, err := w.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WxCardUser), nil
+	}
+}
+
+func (w wxCardUserDo) FirstOrCreate() (*model.WxCardUser, error) {
+	if result, err := w.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WxCardUser), nil
+	}
+}
+
+func (w wxCardUserDo) FindByPage(offset int, limit int) (result []*model.WxCardUser, count int64, err error) {
+	result, err = w.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = w.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (w wxCardUserDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = w.Count()
+	if err != nil {
+		return
+	}
+
+	err = w.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (w wxCardUserDo) Scan(result interface{}) (err error) {
+	return w.DO.Scan(result)
+}
+
+func (w wxCardUserDo) Delete(models ...*model.WxCardUser) (result gen.ResultInfo, err error) {
+	return w.DO.Delete(models)
+}
+
+func (w *wxCardUserDo) withDO(do gen.Dao) *wxCardUserDo {
+	w.DO = *do.(*gen.DO)
+	return w
+}

+ 405 - 0
database/dao/wechat/query/wx_card_visit.gen.go

@@ -0,0 +1,405 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newWxCardVisit(db *gorm.DB, opts ...gen.DOOption) wxCardVisit {
+	_wxCardVisit := wxCardVisit{}
+
+	_wxCardVisit.wxCardVisitDo.UseDB(db, opts...)
+	_wxCardVisit.wxCardVisitDo.UseModel(&model.WxCardVisit{})
+
+	tableName := _wxCardVisit.wxCardVisitDo.TableName()
+	_wxCardVisit.ALL = field.NewAsterisk(tableName)
+	_wxCardVisit.ID = field.NewInt64(tableName, "id")
+	_wxCardVisit.CreatedAt = field.NewTime(tableName, "created_at")
+	_wxCardVisit.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_wxCardVisit.DeletedAt = field.NewField(tableName, "deleted_at")
+	_wxCardVisit.UserID = field.NewInt64(tableName, "user_id")
+	_wxCardVisit.BotID = field.NewInt64(tableName, "bot_id")
+	_wxCardVisit.BotType = field.NewInt64(tableName, "bot_type")
+
+	_wxCardVisit.fillFieldMap()
+
+	return _wxCardVisit
+}
+
+// wxCardVisit 名片访问记录表
+type wxCardVisit struct {
+	wxCardVisitDo
+
+	ALL       field.Asterisk
+	ID        field.Int64
+	CreatedAt field.Time  // Create Time | 创建日期
+	UpdatedAt field.Time  // Update Time | 修改日期
+	DeletedAt field.Field // Delete Time | 删除日期
+	UserID    field.Int64 // 访客 ID
+	BotID     field.Int64 // 被访ID
+	BotType   field.Int64 // 类型:1-微信 2-小程序 3-智能体
+
+	fieldMap map[string]field.Expr
+}
+
+func (w wxCardVisit) Table(newTableName string) *wxCardVisit {
+	w.wxCardVisitDo.UseTable(newTableName)
+	return w.updateTableName(newTableName)
+}
+
+func (w wxCardVisit) As(alias string) *wxCardVisit {
+	w.wxCardVisitDo.DO = *(w.wxCardVisitDo.As(alias).(*gen.DO))
+	return w.updateTableName(alias)
+}
+
+func (w *wxCardVisit) updateTableName(table string) *wxCardVisit {
+	w.ALL = field.NewAsterisk(table)
+	w.ID = field.NewInt64(table, "id")
+	w.CreatedAt = field.NewTime(table, "created_at")
+	w.UpdatedAt = field.NewTime(table, "updated_at")
+	w.DeletedAt = field.NewField(table, "deleted_at")
+	w.UserID = field.NewInt64(table, "user_id")
+	w.BotID = field.NewInt64(table, "bot_id")
+	w.BotType = field.NewInt64(table, "bot_type")
+
+	w.fillFieldMap()
+
+	return w
+}
+
+func (w *wxCardVisit) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := w.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (w *wxCardVisit) fillFieldMap() {
+	w.fieldMap = make(map[string]field.Expr, 7)
+	w.fieldMap["id"] = w.ID
+	w.fieldMap["created_at"] = w.CreatedAt
+	w.fieldMap["updated_at"] = w.UpdatedAt
+	w.fieldMap["deleted_at"] = w.DeletedAt
+	w.fieldMap["user_id"] = w.UserID
+	w.fieldMap["bot_id"] = w.BotID
+	w.fieldMap["bot_type"] = w.BotType
+}
+
+func (w wxCardVisit) clone(db *gorm.DB) wxCardVisit {
+	w.wxCardVisitDo.ReplaceConnPool(db.Statement.ConnPool)
+	return w
+}
+
+func (w wxCardVisit) replaceDB(db *gorm.DB) wxCardVisit {
+	w.wxCardVisitDo.ReplaceDB(db)
+	return w
+}
+
+type wxCardVisitDo struct{ gen.DO }
+
+type IWxCardVisitDo interface {
+	gen.SubQuery
+	Debug() IWxCardVisitDo
+	WithContext(ctx context.Context) IWxCardVisitDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IWxCardVisitDo
+	WriteDB() IWxCardVisitDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IWxCardVisitDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IWxCardVisitDo
+	Not(conds ...gen.Condition) IWxCardVisitDo
+	Or(conds ...gen.Condition) IWxCardVisitDo
+	Select(conds ...field.Expr) IWxCardVisitDo
+	Where(conds ...gen.Condition) IWxCardVisitDo
+	Order(conds ...field.Expr) IWxCardVisitDo
+	Distinct(cols ...field.Expr) IWxCardVisitDo
+	Omit(cols ...field.Expr) IWxCardVisitDo
+	Join(table schema.Tabler, on ...field.Expr) IWxCardVisitDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IWxCardVisitDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IWxCardVisitDo
+	Group(cols ...field.Expr) IWxCardVisitDo
+	Having(conds ...gen.Condition) IWxCardVisitDo
+	Limit(limit int) IWxCardVisitDo
+	Offset(offset int) IWxCardVisitDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IWxCardVisitDo
+	Unscoped() IWxCardVisitDo
+	Create(values ...*model.WxCardVisit) error
+	CreateInBatches(values []*model.WxCardVisit, batchSize int) error
+	Save(values ...*model.WxCardVisit) error
+	First() (*model.WxCardVisit, error)
+	Take() (*model.WxCardVisit, error)
+	Last() (*model.WxCardVisit, error)
+	Find() ([]*model.WxCardVisit, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.WxCardVisit, err error)
+	FindInBatches(result *[]*model.WxCardVisit, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.WxCardVisit) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IWxCardVisitDo
+	Assign(attrs ...field.AssignExpr) IWxCardVisitDo
+	Joins(fields ...field.RelationField) IWxCardVisitDo
+	Preload(fields ...field.RelationField) IWxCardVisitDo
+	FirstOrInit() (*model.WxCardVisit, error)
+	FirstOrCreate() (*model.WxCardVisit, error)
+	FindByPage(offset int, limit int) (result []*model.WxCardVisit, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IWxCardVisitDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (w wxCardVisitDo) Debug() IWxCardVisitDo {
+	return w.withDO(w.DO.Debug())
+}
+
+func (w wxCardVisitDo) WithContext(ctx context.Context) IWxCardVisitDo {
+	return w.withDO(w.DO.WithContext(ctx))
+}
+
+func (w wxCardVisitDo) ReadDB() IWxCardVisitDo {
+	return w.Clauses(dbresolver.Read)
+}
+
+func (w wxCardVisitDo) WriteDB() IWxCardVisitDo {
+	return w.Clauses(dbresolver.Write)
+}
+
+func (w wxCardVisitDo) Session(config *gorm.Session) IWxCardVisitDo {
+	return w.withDO(w.DO.Session(config))
+}
+
+func (w wxCardVisitDo) Clauses(conds ...clause.Expression) IWxCardVisitDo {
+	return w.withDO(w.DO.Clauses(conds...))
+}
+
+func (w wxCardVisitDo) Returning(value interface{}, columns ...string) IWxCardVisitDo {
+	return w.withDO(w.DO.Returning(value, columns...))
+}
+
+func (w wxCardVisitDo) Not(conds ...gen.Condition) IWxCardVisitDo {
+	return w.withDO(w.DO.Not(conds...))
+}
+
+func (w wxCardVisitDo) Or(conds ...gen.Condition) IWxCardVisitDo {
+	return w.withDO(w.DO.Or(conds...))
+}
+
+func (w wxCardVisitDo) Select(conds ...field.Expr) IWxCardVisitDo {
+	return w.withDO(w.DO.Select(conds...))
+}
+
+func (w wxCardVisitDo) Where(conds ...gen.Condition) IWxCardVisitDo {
+	return w.withDO(w.DO.Where(conds...))
+}
+
+func (w wxCardVisitDo) Order(conds ...field.Expr) IWxCardVisitDo {
+	return w.withDO(w.DO.Order(conds...))
+}
+
+func (w wxCardVisitDo) Distinct(cols ...field.Expr) IWxCardVisitDo {
+	return w.withDO(w.DO.Distinct(cols...))
+}
+
+func (w wxCardVisitDo) Omit(cols ...field.Expr) IWxCardVisitDo {
+	return w.withDO(w.DO.Omit(cols...))
+}
+
+func (w wxCardVisitDo) Join(table schema.Tabler, on ...field.Expr) IWxCardVisitDo {
+	return w.withDO(w.DO.Join(table, on...))
+}
+
+func (w wxCardVisitDo) LeftJoin(table schema.Tabler, on ...field.Expr) IWxCardVisitDo {
+	return w.withDO(w.DO.LeftJoin(table, on...))
+}
+
+func (w wxCardVisitDo) RightJoin(table schema.Tabler, on ...field.Expr) IWxCardVisitDo {
+	return w.withDO(w.DO.RightJoin(table, on...))
+}
+
+func (w wxCardVisitDo) Group(cols ...field.Expr) IWxCardVisitDo {
+	return w.withDO(w.DO.Group(cols...))
+}
+
+func (w wxCardVisitDo) Having(conds ...gen.Condition) IWxCardVisitDo {
+	return w.withDO(w.DO.Having(conds...))
+}
+
+func (w wxCardVisitDo) Limit(limit int) IWxCardVisitDo {
+	return w.withDO(w.DO.Limit(limit))
+}
+
+func (w wxCardVisitDo) Offset(offset int) IWxCardVisitDo {
+	return w.withDO(w.DO.Offset(offset))
+}
+
+func (w wxCardVisitDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IWxCardVisitDo {
+	return w.withDO(w.DO.Scopes(funcs...))
+}
+
+func (w wxCardVisitDo) Unscoped() IWxCardVisitDo {
+	return w.withDO(w.DO.Unscoped())
+}
+
+func (w wxCardVisitDo) Create(values ...*model.WxCardVisit) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return w.DO.Create(values)
+}
+
+func (w wxCardVisitDo) CreateInBatches(values []*model.WxCardVisit, batchSize int) error {
+	return w.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (w wxCardVisitDo) Save(values ...*model.WxCardVisit) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return w.DO.Save(values)
+}
+
+func (w wxCardVisitDo) First() (*model.WxCardVisit, error) {
+	if result, err := w.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WxCardVisit), nil
+	}
+}
+
+func (w wxCardVisitDo) Take() (*model.WxCardVisit, error) {
+	if result, err := w.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WxCardVisit), nil
+	}
+}
+
+func (w wxCardVisitDo) Last() (*model.WxCardVisit, error) {
+	if result, err := w.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WxCardVisit), nil
+	}
+}
+
+func (w wxCardVisitDo) Find() ([]*model.WxCardVisit, error) {
+	result, err := w.DO.Find()
+	return result.([]*model.WxCardVisit), err
+}
+
+func (w wxCardVisitDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.WxCardVisit, err error) {
+	buf := make([]*model.WxCardVisit, 0, batchSize)
+	err = w.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (w wxCardVisitDo) FindInBatches(result *[]*model.WxCardVisit, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return w.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (w wxCardVisitDo) Attrs(attrs ...field.AssignExpr) IWxCardVisitDo {
+	return w.withDO(w.DO.Attrs(attrs...))
+}
+
+func (w wxCardVisitDo) Assign(attrs ...field.AssignExpr) IWxCardVisitDo {
+	return w.withDO(w.DO.Assign(attrs...))
+}
+
+func (w wxCardVisitDo) Joins(fields ...field.RelationField) IWxCardVisitDo {
+	for _, _f := range fields {
+		w = *w.withDO(w.DO.Joins(_f))
+	}
+	return &w
+}
+
+func (w wxCardVisitDo) Preload(fields ...field.RelationField) IWxCardVisitDo {
+	for _, _f := range fields {
+		w = *w.withDO(w.DO.Preload(_f))
+	}
+	return &w
+}
+
+func (w wxCardVisitDo) FirstOrInit() (*model.WxCardVisit, error) {
+	if result, err := w.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WxCardVisit), nil
+	}
+}
+
+func (w wxCardVisitDo) FirstOrCreate() (*model.WxCardVisit, error) {
+	if result, err := w.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.WxCardVisit), nil
+	}
+}
+
+func (w wxCardVisitDo) FindByPage(offset int, limit int) (result []*model.WxCardVisit, count int64, err error) {
+	result, err = w.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = w.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (w wxCardVisitDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = w.Count()
+	if err != nil {
+		return
+	}
+
+	err = w.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (w wxCardVisitDo) Scan(result interface{}) (err error) {
+	return w.DO.Scan(result)
+}
+
+func (w wxCardVisitDo) Delete(models ...*model.WxCardVisit) (result gen.ResultInfo, err error) {
+	return w.DO.Delete(models)
+}
+
+func (w *wxCardVisitDo) withDO(do gen.Dao) *wxCardVisitDo {
+	w.DO = *do.(*gen.DO)
+	return w
+}

+ 412 - 0
database/dao/wechat/query/xunji_contact.gen.go

@@ -0,0 +1,412 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"wechat-api/database/dao/wechat/model"
+)
+
+func newXunjiContact(db *gorm.DB, opts ...gen.DOOption) xunjiContact {
+	_xunjiContact := xunjiContact{}
+
+	_xunjiContact.xunjiContactDo.UseDB(db, opts...)
+	_xunjiContact.xunjiContactDo.UseModel(&model.XunjiContact{})
+
+	tableName := _xunjiContact.xunjiContactDo.TableName()
+	_xunjiContact.ALL = field.NewAsterisk(tableName)
+	_xunjiContact.ID = field.NewInt64(tableName, "id")
+	_xunjiContact.CreatedAt = field.NewTime(tableName, "created_at")
+	_xunjiContact.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_xunjiContact.Status = field.NewInt64(tableName, "status")
+	_xunjiContact.DeletedAt = field.NewField(tableName, "deleted_at")
+	_xunjiContact.RobotID = field.NewString(tableName, "robot_id")
+	_xunjiContact.AccountID = field.NewString(tableName, "account_id")
+	_xunjiContact.Nickname = field.NewString(tableName, "nickname")
+	_xunjiContact.Avatar = field.NewString(tableName, "avatar")
+
+	_xunjiContact.fillFieldMap()
+
+	return _xunjiContact
+}
+
+type xunjiContact struct {
+	xunjiContactDo
+
+	ALL       field.Asterisk
+	ID        field.Int64
+	CreatedAt field.Time   // Create Time | 创建日期
+	UpdatedAt field.Time   // Update Time | 修改日期
+	Status    field.Int64  // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	DeletedAt field.Field  // Delete Time | 删除日期
+	RobotID   field.String // 机器人ID
+	AccountID field.String // 客户ID
+	Nickname  field.String // 昵称
+	Avatar    field.String // 头像
+
+	fieldMap map[string]field.Expr
+}
+
+func (x xunjiContact) Table(newTableName string) *xunjiContact {
+	x.xunjiContactDo.UseTable(newTableName)
+	return x.updateTableName(newTableName)
+}
+
+func (x xunjiContact) As(alias string) *xunjiContact {
+	x.xunjiContactDo.DO = *(x.xunjiContactDo.As(alias).(*gen.DO))
+	return x.updateTableName(alias)
+}
+
+func (x *xunjiContact) updateTableName(table string) *xunjiContact {
+	x.ALL = field.NewAsterisk(table)
+	x.ID = field.NewInt64(table, "id")
+	x.CreatedAt = field.NewTime(table, "created_at")
+	x.UpdatedAt = field.NewTime(table, "updated_at")
+	x.Status = field.NewInt64(table, "status")
+	x.DeletedAt = field.NewField(table, "deleted_at")
+	x.RobotID = field.NewString(table, "robot_id")
+	x.AccountID = field.NewString(table, "account_id")
+	x.Nickname = field.NewString(table, "nickname")
+	x.Avatar = field.NewString(table, "avatar")
+
+	x.fillFieldMap()
+
+	return x
+}
+
+func (x *xunjiContact) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := x.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (x *xunjiContact) fillFieldMap() {
+	x.fieldMap = make(map[string]field.Expr, 9)
+	x.fieldMap["id"] = x.ID
+	x.fieldMap["created_at"] = x.CreatedAt
+	x.fieldMap["updated_at"] = x.UpdatedAt
+	x.fieldMap["status"] = x.Status
+	x.fieldMap["deleted_at"] = x.DeletedAt
+	x.fieldMap["robot_id"] = x.RobotID
+	x.fieldMap["account_id"] = x.AccountID
+	x.fieldMap["nickname"] = x.Nickname
+	x.fieldMap["avatar"] = x.Avatar
+}
+
+func (x xunjiContact) clone(db *gorm.DB) xunjiContact {
+	x.xunjiContactDo.ReplaceConnPool(db.Statement.ConnPool)
+	return x
+}
+
+func (x xunjiContact) replaceDB(db *gorm.DB) xunjiContact {
+	x.xunjiContactDo.ReplaceDB(db)
+	return x
+}
+
+type xunjiContactDo struct{ gen.DO }
+
+type IXunjiContactDo interface {
+	gen.SubQuery
+	Debug() IXunjiContactDo
+	WithContext(ctx context.Context) IXunjiContactDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() IXunjiContactDo
+	WriteDB() IXunjiContactDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) IXunjiContactDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) IXunjiContactDo
+	Not(conds ...gen.Condition) IXunjiContactDo
+	Or(conds ...gen.Condition) IXunjiContactDo
+	Select(conds ...field.Expr) IXunjiContactDo
+	Where(conds ...gen.Condition) IXunjiContactDo
+	Order(conds ...field.Expr) IXunjiContactDo
+	Distinct(cols ...field.Expr) IXunjiContactDo
+	Omit(cols ...field.Expr) IXunjiContactDo
+	Join(table schema.Tabler, on ...field.Expr) IXunjiContactDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) IXunjiContactDo
+	RightJoin(table schema.Tabler, on ...field.Expr) IXunjiContactDo
+	Group(cols ...field.Expr) IXunjiContactDo
+	Having(conds ...gen.Condition) IXunjiContactDo
+	Limit(limit int) IXunjiContactDo
+	Offset(offset int) IXunjiContactDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) IXunjiContactDo
+	Unscoped() IXunjiContactDo
+	Create(values ...*model.XunjiContact) error
+	CreateInBatches(values []*model.XunjiContact, batchSize int) error
+	Save(values ...*model.XunjiContact) error
+	First() (*model.XunjiContact, error)
+	Take() (*model.XunjiContact, error)
+	Last() (*model.XunjiContact, error)
+	Find() ([]*model.XunjiContact, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.XunjiContact, err error)
+	FindInBatches(result *[]*model.XunjiContact, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model.XunjiContact) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) IXunjiContactDo
+	Assign(attrs ...field.AssignExpr) IXunjiContactDo
+	Joins(fields ...field.RelationField) IXunjiContactDo
+	Preload(fields ...field.RelationField) IXunjiContactDo
+	FirstOrInit() (*model.XunjiContact, error)
+	FirstOrCreate() (*model.XunjiContact, error)
+	FindByPage(offset int, limit int) (result []*model.XunjiContact, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) IXunjiContactDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+}
+
+func (x xunjiContactDo) Debug() IXunjiContactDo {
+	return x.withDO(x.DO.Debug())
+}
+
+func (x xunjiContactDo) WithContext(ctx context.Context) IXunjiContactDo {
+	return x.withDO(x.DO.WithContext(ctx))
+}
+
+func (x xunjiContactDo) ReadDB() IXunjiContactDo {
+	return x.Clauses(dbresolver.Read)
+}
+
+func (x xunjiContactDo) WriteDB() IXunjiContactDo {
+	return x.Clauses(dbresolver.Write)
+}
+
+func (x xunjiContactDo) Session(config *gorm.Session) IXunjiContactDo {
+	return x.withDO(x.DO.Session(config))
+}
+
+func (x xunjiContactDo) Clauses(conds ...clause.Expression) IXunjiContactDo {
+	return x.withDO(x.DO.Clauses(conds...))
+}
+
+func (x xunjiContactDo) Returning(value interface{}, columns ...string) IXunjiContactDo {
+	return x.withDO(x.DO.Returning(value, columns...))
+}
+
+func (x xunjiContactDo) Not(conds ...gen.Condition) IXunjiContactDo {
+	return x.withDO(x.DO.Not(conds...))
+}
+
+func (x xunjiContactDo) Or(conds ...gen.Condition) IXunjiContactDo {
+	return x.withDO(x.DO.Or(conds...))
+}
+
+func (x xunjiContactDo) Select(conds ...field.Expr) IXunjiContactDo {
+	return x.withDO(x.DO.Select(conds...))
+}
+
+func (x xunjiContactDo) Where(conds ...gen.Condition) IXunjiContactDo {
+	return x.withDO(x.DO.Where(conds...))
+}
+
+func (x xunjiContactDo) Order(conds ...field.Expr) IXunjiContactDo {
+	return x.withDO(x.DO.Order(conds...))
+}
+
+func (x xunjiContactDo) Distinct(cols ...field.Expr) IXunjiContactDo {
+	return x.withDO(x.DO.Distinct(cols...))
+}
+
+func (x xunjiContactDo) Omit(cols ...field.Expr) IXunjiContactDo {
+	return x.withDO(x.DO.Omit(cols...))
+}
+
+func (x xunjiContactDo) Join(table schema.Tabler, on ...field.Expr) IXunjiContactDo {
+	return x.withDO(x.DO.Join(table, on...))
+}
+
+func (x xunjiContactDo) LeftJoin(table schema.Tabler, on ...field.Expr) IXunjiContactDo {
+	return x.withDO(x.DO.LeftJoin(table, on...))
+}
+
+func (x xunjiContactDo) RightJoin(table schema.Tabler, on ...field.Expr) IXunjiContactDo {
+	return x.withDO(x.DO.RightJoin(table, on...))
+}
+
+func (x xunjiContactDo) Group(cols ...field.Expr) IXunjiContactDo {
+	return x.withDO(x.DO.Group(cols...))
+}
+
+func (x xunjiContactDo) Having(conds ...gen.Condition) IXunjiContactDo {
+	return x.withDO(x.DO.Having(conds...))
+}
+
+func (x xunjiContactDo) Limit(limit int) IXunjiContactDo {
+	return x.withDO(x.DO.Limit(limit))
+}
+
+func (x xunjiContactDo) Offset(offset int) IXunjiContactDo {
+	return x.withDO(x.DO.Offset(offset))
+}
+
+func (x xunjiContactDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IXunjiContactDo {
+	return x.withDO(x.DO.Scopes(funcs...))
+}
+
+func (x xunjiContactDo) Unscoped() IXunjiContactDo {
+	return x.withDO(x.DO.Unscoped())
+}
+
+func (x xunjiContactDo) Create(values ...*model.XunjiContact) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return x.DO.Create(values)
+}
+
+func (x xunjiContactDo) CreateInBatches(values []*model.XunjiContact, batchSize int) error {
+	return x.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (x xunjiContactDo) Save(values ...*model.XunjiContact) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return x.DO.Save(values)
+}
+
+func (x xunjiContactDo) First() (*model.XunjiContact, error) {
+	if result, err := x.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.XunjiContact), nil
+	}
+}
+
+func (x xunjiContactDo) Take() (*model.XunjiContact, error) {
+	if result, err := x.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.XunjiContact), nil
+	}
+}
+
+func (x xunjiContactDo) Last() (*model.XunjiContact, error) {
+	if result, err := x.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.XunjiContact), nil
+	}
+}
+
+func (x xunjiContactDo) Find() ([]*model.XunjiContact, error) {
+	result, err := x.DO.Find()
+	return result.([]*model.XunjiContact), err
+}
+
+func (x xunjiContactDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.XunjiContact, err error) {
+	buf := make([]*model.XunjiContact, 0, batchSize)
+	err = x.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (x xunjiContactDo) FindInBatches(result *[]*model.XunjiContact, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return x.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (x xunjiContactDo) Attrs(attrs ...field.AssignExpr) IXunjiContactDo {
+	return x.withDO(x.DO.Attrs(attrs...))
+}
+
+func (x xunjiContactDo) Assign(attrs ...field.AssignExpr) IXunjiContactDo {
+	return x.withDO(x.DO.Assign(attrs...))
+}
+
+func (x xunjiContactDo) Joins(fields ...field.RelationField) IXunjiContactDo {
+	for _, _f := range fields {
+		x = *x.withDO(x.DO.Joins(_f))
+	}
+	return &x
+}
+
+func (x xunjiContactDo) Preload(fields ...field.RelationField) IXunjiContactDo {
+	for _, _f := range fields {
+		x = *x.withDO(x.DO.Preload(_f))
+	}
+	return &x
+}
+
+func (x xunjiContactDo) FirstOrInit() (*model.XunjiContact, error) {
+	if result, err := x.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.XunjiContact), nil
+	}
+}
+
+func (x xunjiContactDo) FirstOrCreate() (*model.XunjiContact, error) {
+	if result, err := x.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.XunjiContact), nil
+	}
+}
+
+func (x xunjiContactDo) FindByPage(offset int, limit int) (result []*model.XunjiContact, count int64, err error) {
+	result, err = x.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = x.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (x xunjiContactDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = x.Count()
+	if err != nil {
+		return
+	}
+
+	err = x.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (x xunjiContactDo) Scan(result interface{}) (err error) {
+	return x.DO.Scan(result)
+}
+
+func (x xunjiContactDo) Delete(models ...*model.XunjiContact) (result gen.ResultInfo, err error) {
+	return x.DO.Delete(models)
+}
+
+func (x *xunjiContactDo) withDO(do gen.Dao) *xunjiContactDo {
+	x.DO = *do.(*gen.DO)
+	return x
+}

+ 61 - 0
database/gorm_gen.go

@@ -0,0 +1,61 @@
+package database
+
+import (
+	"gorm.io/driver/mysql"
+	"gorm.io/gen"
+	"gorm.io/gorm"
+	"os"
+)
+
+func generateGormDbModel(dsn string, daoPath string) {
+
+	currentPath, _ := os.Getwd()
+	db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
+
+	genConfig := gen.Config{
+		OutPath:      currentPath + "/dao" + daoPath + "/query",
+		ModelPkgPath: currentPath + "/dao" + daoPath + "/model",
+		Mode:         gen.WithoutContext | gen.WithDefaultQuery | gen.WithQueryInterface,
+
+		//// 表字段可为 null 值时, 对应结体字段使用指针类型
+		FieldNullable: false, // generate pointer when field is nullable
+		//
+		//// 表字段默认值与模型结构体字段零值不一致的字段, 在插入数据时需要赋值该字段值为零值的, 结构体字段须是指针类型才能成功, 即`FieldCoverable:true`配置下生成的结构体字段.
+		//// 因为在插入时遇到字段为零值的会被GORM赋予默认值. 如字段`age`表默认值为10, 即使你显式设置为0最后也会被GORM设为10提交.
+		//// 如果该字段没有上面提到的插入时赋零值的特殊需要, 则字段为非指针类型使用起来会比较方便.
+		//FieldCoverable: false, // generate pointer when field has default value, to fix problem zero value cannot be assign: https://gorm.io/docs/create.html#Default-Values
+		//
+		//// 模型结构体字段的数字类型的符号表示是否与表字段的一致, `false`指示都用有符号类型
+		//FieldSignable: false, // detect integer field's unsigned type, adjust generated data type
+		//// 生成 gorm 标签的字段索引属性
+		//FieldWithIndexTag: false, // generate with gorm index tag
+		//// 生成 gorm 标签的字段类型属性
+		//FieldWithTypeTag: true, // generate with gorm column type tag
+	}
+
+	g := gen.NewGenerator(genConfig)
+
+	g.WithImportPkgPath("github.com/shopspring/decimal")
+
+	g.UseDB(db)
+
+	// Add mapping for decimal(64,18) to decimal.Decimal
+	// 自定义类型映射
+	dataMap := map[string]func(detailType gorm.ColumnType) (dataType string){
+		"tinyint":   func(detailType gorm.ColumnType) (dataType string) { return "int64" },
+		"smallint":  func(detailType gorm.ColumnType) (dataType string) { return "int64" },
+		"mediumint": func(detailType gorm.ColumnType) (dataType string) { return "int64" },
+		"bigint":    func(detailType gorm.ColumnType) (dataType string) { return "int64" },
+		"int":       func(detailType gorm.ColumnType) (dataType string) { return "int64" },
+		"decimal":   func(detailType gorm.ColumnType) (dataType string) { return "decimal.Decimal" }, // 金额类型全部转换为第三方库,github.com/shopspring/decimal
+	}
+	g.WithDataTypeMap(dataMap)
+
+	// 修改字段名,和系统关键字冲突
+	g.WithOpts(gen.FieldRename("table", "MTable"))
+
+	g.GenerateAllTable()
+
+	g.ApplyBasic(g.GenerateAllTable()...)
+	g.Execute()
+}

+ 20 - 0
database/gorm_gen_test.go

@@ -0,0 +1,20 @@
+package database
+
+import (
+	"fmt"
+	"testing"
+)
+
+const dbHost = "wallet:wallet@tcp(localhost:3306)/%s?charset=utf8mb4&parseTime=True&loc=Local"
+const wechat_path = "/wechat"
+const tool_path = "/tool"
+
+func Test_generateWechatDbModel(t *testing.T) {
+	dsn := fmt.Sprintf(dbHost, "wechat")
+	generateGormDbModel(dsn, wechat_path)
+}
+
+func Test_generateToolDbModel(t *testing.T) {
+	dsn := fmt.Sprintf(dbHost, "tool")
+	generateGormDbModel(dsn, tool_path)
+}

+ 37 - 0
database/gorm_init.go

@@ -0,0 +1,37 @@
+package database
+
+import (
+	"github.com/suyuan32/simple-admin-common/config"
+	"github.com/zeromicro/go-zero/core/logx"
+	"gorm.io/driver/mysql"
+	"gorm.io/gorm"
+	"time"
+)
+
+func InitWechatDB(databaseConf config.DatabaseConf, mode string) (*gorm.DB, error) {
+	dsn := databaseConf.GetDSN()
+	wechatDb, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
+		Logger: NewGormLogger(mode),
+	})
+	if err != nil {
+		logx.Error(err)
+		return nil, err
+	}
+	if wechatDb != nil {
+		sqlDB, err := wechatDb.DB()
+		if err != nil {
+			logx.Error(err)
+			return nil, err
+		}
+		// 设置连接池
+		sqlDB.SetMaxIdleConns(10)
+
+		sqlDB.SetMaxOpenConns(100)
+
+		sqlDB.SetConnMaxLifetime(time.Hour)
+	}
+	//初始化DAO查询接口
+	//wechatQ := query.Use(wechatDb)
+
+	return wechatDb, nil
+}

+ 77 - 0
database/gorm_logger.go

@@ -0,0 +1,77 @@
+package database
+
+import (
+	"context"
+	"errors"
+	"github.com/zeromicro/go-zero/core/logx"
+	"github.com/zeromicro/go-zero/core/service"
+	"gorm.io/gorm"
+	"gorm.io/gorm/logger"
+	"strconv"
+	"time"
+)
+
+type GormLogger struct {
+	SlowThreshold time.Duration
+	Mode          string
+}
+
+func NewGormLogger(mode string) *GormLogger {
+	return &GormLogger{
+		SlowThreshold: 200 * time.Millisecond, // 一般超过200毫秒就算慢查所以不使用配置进行更改
+		Mode:          mode,
+	}
+}
+
+var _ logger.Interface = (*GormLogger)(nil)
+
+func (l *GormLogger) LogMode(lev logger.LogLevel) logger.Interface {
+	return &GormLogger{}
+}
+func (l *GormLogger) Info(ctx context.Context, msg string, data ...interface{}) {
+	logx.WithContext(ctx).Infof(msg, data)
+}
+func (l *GormLogger) Warn(ctx context.Context, msg string, data ...interface{}) {
+	logx.WithContext(ctx).Errorf(msg, data)
+}
+func (l *GormLogger) Error(ctx context.Context, msg string, data ...interface{}) {
+	logx.WithContext(ctx).Errorf(msg, data)
+}
+
+// MicrosecondsStr 将时间间隔转换为微秒并返回字符串
+func (l *GormLogger) MicrosecondsStr(d time.Duration) string {
+	microseconds := d.Microseconds()
+	return strconv.FormatInt(microseconds, 10)
+}
+
+func (l *GormLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) {
+	// 获取运行时间
+	elapsed := time.Since(begin)
+	// 获取 SQL 语句和返回条数
+	sql, rows := fc()
+	// 通用字段
+	logFields := []logx.LogField{
+		logx.Field("sql", sql),
+		logx.Field("time", l.MicrosecondsStr(elapsed)),
+		logx.Field("rows", rows),
+	}
+	// Gorm 错误
+	if err != nil {
+		// 记录未找到的错误使用 warning 等级
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			logx.WithContext(ctx).Infow("Database ErrRecordNotFound", logFields...)
+		} else {
+			// 其他错误使用 error 等级
+			logFields = append(logFields, logx.Field("catch error", err))
+			logx.WithContext(ctx).Errorw("Database Error", logFields...)
+		}
+	}
+	// 慢查询日志
+	if l.SlowThreshold != 0 && elapsed > l.SlowThreshold {
+		logx.WithContext(ctx).Sloww("Database Slow Log", logFields...)
+	}
+	// 非生产模式下,记录所有 SQL 请求
+	if l.Mode != service.ProMode {
+		logx.WithContext(ctx).Infow("Database Query", logFields...)
+	}
+}

+ 17 - 6
etc/wechat.yaml

@@ -28,8 +28,8 @@ DatabaseConf:
   Host: mysql-server
   Port: 3306
   DBName: wechat
-  Username: root
-  Password: simple-admin.
+  Username: wallet
+  Password: wallet
   MaxOpenConn: 100
   SSLMode: disable
   CacheTime: 5
@@ -47,9 +47,9 @@ CasbinDatabaseConf:
   Type: mysql
   Host: mysql-server
   Port: 3306
-  DBName: wechat_admin
-  Username: root
-  Password: simple-admin.
+  DBName: wechat-admin
+  Username: wallet
+  Password: wallet
   MaxOpenConn: 100
   SSLMode: disable
   CacheTime: 5
@@ -84,4 +84,15 @@ Fastgpt:
 
 Xiaoice:
   SubscriptionKey: ccaa5a6ff70f4393a934e69b9ace31bb
-  GptbotsAuthorization: app-hQL7oVq57McK5VBHlsMfhtUD
+  GptbotsAuthorization: app-hQL7oVq57McK5VBHlsMfhtUD
+
+OpenAI:
+  BaseUrl: https://api.openai.com/v1
+  ApiKey: sk-ZQRNypQOC8ID5WbpCdF263C58dF44271842e86D408Bb3848
+
+WebSocket:
+    -
+      Type: wechat
+      Name: default
+      Url: ws://chat.gkscrm.com:13088
+

+ 15 - 0
go.mod

@@ -11,17 +11,20 @@ require (
 	github.com/alibabacloud-go/sts-20150401/v2 v2.0.2
 	github.com/alibabacloud-go/tea v1.2.2
 	github.com/alibabacloud-go/tea-utils/v2 v2.0.7
+	github.com/bwmarrin/snowflake v0.3.0
 	github.com/casbin/casbin/v2 v2.85.0
 	github.com/go-resty/resty/v2 v2.14.0
 	github.com/gofrs/uuid/v5 v5.0.0
 	github.com/golang-jwt/jwt/v5 v5.2.1
 	github.com/gorilla/websocket v1.5.0
 	github.com/imroc/req/v3 v3.43.1
+	github.com/openai/openai-go v0.1.0-alpha.62
 	github.com/redis/go-redis/v9 v9.6.1
 	github.com/robfig/cron/v3 v3.0.1
 	github.com/russross/blackfriday v1.6.0
 	github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d
 	github.com/sashabaranov/go-openai v1.31.0
+	github.com/shopspring/decimal v1.4.0
 	github.com/speps/go-hashids/v2 v2.0.1
 	github.com/spf13/cast v1.6.0
 	github.com/suyuan32/simple-admin-common v1.3.11
@@ -30,6 +33,10 @@ require (
 	golang.org/x/crypto v0.27.0
 	golang.org/x/text v0.18.0
 	google.golang.org/protobuf v1.35.2
+	gorm.io/driver/mysql v1.5.5
+	gorm.io/gen v0.3.26
+	gorm.io/gorm v1.25.9
+	gorm.io/plugin/dbresolver v1.5.0
 )
 
 require (
@@ -93,6 +100,8 @@ require (
 	github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect
 	github.com/jackc/pgtype v1.14.2 // indirect
 	github.com/jackc/pgx/v4 v4.18.3 // indirect
+	github.com/jinzhu/inflection v1.0.0 // indirect
+	github.com/jinzhu/now v1.1.5 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/klauspost/compress v1.17.7 // indirect
@@ -120,6 +129,10 @@ require (
 	github.com/quic-go/quic-go v0.42.0 // indirect
 	github.com/refraction-networking/utls v1.6.3 // indirect
 	github.com/spaolacci/murmur3 v1.1.0 // indirect
+	github.com/tidwall/gjson v1.17.1 // indirect
+	github.com/tidwall/match v1.1.1 // indirect
+	github.com/tidwall/pretty v1.2.1 // indirect
+	github.com/tidwall/sjson v1.2.5 // indirect
 	github.com/tjfoc/gmsm v1.4.1 // indirect
 	github.com/zclconf/go-cty v1.14.3 // indirect
 	go.etcd.io/etcd/api/v3 v3.5.12 // indirect
@@ -156,6 +169,8 @@ require (
 	gopkg.in/ini.v1 v1.67.0 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
+	gorm.io/datatypes v1.1.1-0.20230130040222-c43177d3cf8c // indirect
+	gorm.io/hints v1.1.0 // indirect
 	k8s.io/api v0.29.3 // indirect
 	k8s.io/apimachinery v0.29.3 // indirect
 	k8s.io/client-go v0.29.3 // indirect

+ 61 - 5
go.sum

@@ -118,6 +118,8 @@ github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
 github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
 github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
 github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
+github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
+github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
 github.com/casbin/casbin/v2 v2.29.2/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
 github.com/casbin/casbin/v2 v2.85.0 h1:VajW9GR/T0fp3SND183gneZGIAdYtl9C7bDYBrqQiGg=
 github.com/casbin/casbin/v2 v2.85.0/go.mod h1:jX8uoN4veP85O/n2674r2qtfSXI6myvxW85f6TH50fw=
@@ -222,6 +224,8 @@ github.com/go-redis/redis/v8 v8.11.0/go.mod h1:DLomh7y2e3ggQXQLd1YgmvIfecPJoFl7W
 github.com/go-resty/resty/v2 v2.14.0 h1:/rhkzsAqGQkozwfKS5aFAbb6TyKd3zyFRWcdRXLPCAU=
 github.com/go-resty/resty/v2 v2.14.0/go.mod h1:IW6mekUOsElt9C7oWr0XRt9BNSD6D5rr9mhk6NjmNHg=
 github.com/go-sql-driver/mysql v1.5.1-0.20200311113236-681ffa848bae/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
 github.com/go-sql-driver/mysql v1.8.0 h1:UtktXaU2Nb64z/pLiGIxY4431SJ4/dR5cjMmlVHgnT4=
 github.com/go-sql-driver/mysql v1.8.0/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
@@ -240,6 +244,10 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
 github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
+github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
+github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
+github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
+github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -388,11 +396,22 @@ github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgS
 github.com/jackc/pgx/v4 v4.18.1/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE=
 github.com/jackc/pgx/v4 v4.18.3 h1:dE2/TrEsGX3RBprb3qryqSV9Y60iZN1C6i8IrmW9/BA=
 github.com/jackc/pgx/v4 v4.18.3/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw=
+github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
+github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
 github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
 github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
 github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
+github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0=
 github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
+github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
+github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
 github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
 github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
 github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
@@ -447,12 +466,14 @@ 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=
 github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
 github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE=
+github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ=
 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
 github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
 github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -481,7 +502,6 @@ 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=
@@ -494,6 +514,8 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
 github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48=
 github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
 github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
+github.com/openai/openai-go v0.1.0-alpha.62 h1:wf1Z+ZZAlqaUBlxhE5rhXxc9hQylcDRgMU2fg+jME+E=
+github.com/openai/openai-go v0.1.0-alpha.62/go.mod h1:3SdE6BffOX9HPEQv8IL/fi3LYZ5TUpRYaqGQZbyk11A=
 github.com/openzipkin/zipkin-go v0.4.2 h1:zjqfqHjUpPmB3c1GlCvvgsM1G4LkvqQbBDueDOCg/jA=
 github.com/openzipkin/zipkin-go v0.4.2/go.mod h1:ZeVkFjuuBiSy13y8vpSDCjMi9GoI3hPpCJSBx/EYFhY=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
@@ -560,8 +582,9 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg
 github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
 github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
 github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
-github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
 github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
+github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
+github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
@@ -580,8 +603,6 @@ 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=
@@ -611,6 +632,16 @@ github.com/suyuan32/simple-admin-core v1.3.11 h1:FeIHNvS9WnHm4CMWuxxhjTrt4nSyYz1
 github.com/suyuan32/simple-admin-core v1.3.11/go.mod h1:prymrTp+RjbqoH87HfXHOUrG5nu9lyFg6eNoy9hayLo=
 github.com/suyuan32/simple-admin-tools v1.6.9 h1:wEHV1YeEXdyKIh5MHT73NxQaNGKZo4eLzzK2bg7Zvho=
 github.com/suyuan32/simple-admin-tools v1.6.9/go.mod h1:RtX0cyNWNEd5mquIpl4azH5dUp790bYVmLIzxELS5Pw=
+github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
+github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
+github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
+github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
+github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
+github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
+github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
+github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
 github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
 github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
 github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
@@ -1005,6 +1036,31 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/datatypes v1.1.1-0.20230130040222-c43177d3cf8c h1:jWdr7cHgl8c/ua5vYbR2WhSp+NQmzhsj0xoY3foTzW8=
+gorm.io/datatypes v1.1.1-0.20230130040222-c43177d3cf8c/go.mod h1:SH2K9R+2RMjuX1CkCONrPwoe9JzVv2hkQvEu4bXGojE=
+gorm.io/driver/mysql v1.4.3/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c=
+gorm.io/driver/mysql v1.5.5 h1:WxklwX6FozMs1gk9yVadxGfjGiJjrBKPvIIvYZOMyws=
+gorm.io/driver/mysql v1.5.5/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
+gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM=
+gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA=
+gorm.io/driver/sqlite v1.1.6/go.mod h1:W8LmC/6UvVbHKah0+QOC7Ja66EaZXHwUTjgXY8YNWX8=
+gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU=
+gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI=
+gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0=
+gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig=
+gorm.io/gen v0.3.26 h1:sFf1j7vNStimPRRAtH4zz5NiHM+1dr6eA9aaRdplyhY=
+gorm.io/gen v0.3.26/go.mod h1:a5lq5y3w4g5LMxBcw0wnO6tYUCdNutWODq5LrIt75LE=
+gorm.io/gorm v1.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
+gorm.io/gorm v1.22.2/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
+gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
+gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
+gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
+gorm.io/gorm v1.25.9 h1:wct0gxZIELDk8+ZqF/MVnHLkA1rvYlBWUMv2EdsK1g8=
+gorm.io/gorm v1.25.9/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
+gorm.io/hints v1.1.0 h1:Lp4z3rxREufSdxn4qmkK3TLDltrM10FLTHiuqwDPvXw=
+gorm.io/hints v1.1.0/go.mod h1:lKQ0JjySsPBj3uslFzY3JhYDtqEwzm+G1hv8rWujB6Y=
+gorm.io/plugin/dbresolver v1.5.0 h1:XVHLxh775eP0CqVh3vcfJtYqja3uFl5Wr3cKlY8jgDY=
+gorm.io/plugin/dbresolver v1.5.0/go.mod h1:l4Cn87EHLEYuqUncpEeTC2tTJQkjngPSD+lo8hIvcT0=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

+ 2 - 0
internal/config/config.go

@@ -21,4 +21,6 @@ type Config struct {
 	Aliyun             types.Aliyun
 	CoreRpc            zrpc.RpcClientConf
 	Xiaoice            types.Xiaoice
+	WebSocket          []types.WebSocketConfig
+	OpenAI             types.OpenAI
 }

+ 129 - 0
internal/pkg/customer_of_im/channel/channel.go

@@ -0,0 +1,129 @@
+package channel
+
+import (
+	"context"
+	"encoding/json"
+	"github.com/openai/openai-go"
+	"github.com/zeromicro/go-zero/core/logx"
+	"math/rand"
+	"time"
+	"wechat-api/internal/pkg/customer_of_im/proto"
+	"wechat-api/internal/pkg/wechat_ws"
+	"wechat-api/internal/svc"
+)
+
+type IChannel interface {
+	OnMessage(msg *wechat_ws.MsgJsonObject) error                       // channel的入口,接收消息
+	FriendTalkHandle(msgStr string) error                               // 其他人发送过来的消息处理
+	TextToChatMessage(msgStr string) (*ChatMessage, error)              // 文本转ChatMessage
+	GenerateRelevantContext(msg *ChatMessage) (*RelevantContext, error) // 创建相关上下文
+	Send(message *ReplyMessage) error                                   // 发送消息
+}
+
+type Channel struct {
+	subChannel IChannel
+}
+
+func (c *Channel) InitChannel(subChannel IChannel) {
+	c.subChannel = subChannel
+}
+
+func (c *Channel) After(chatCtx *RelevantContext, message *ChatMessage, reply *ReplyMessage) bool {
+	return true
+}
+func (c *Channel) Before(chatCtx *RelevantContext, message *ChatMessage, reply *ReplyMessage) bool {
+	return true
+}
+
+func (c *Channel) randomPause() {
+	// 创建一个新的随机数源
+	source := rand.NewSource(time.Now().UnixNano())
+	// 创建一个新的随机数生成器
+	rng := rand.New(source)
+
+	// 生成 2 到 5 之间的随机整数
+	pauseDuration := 2 + rng.Intn(4) // 2 + (0, 1, 2, 3) => 2, 3, 4, 5
+
+	// 暂停程序执行相应的时间
+	time.Sleep(time.Duration(pauseDuration) * time.Second)
+}
+
+func (c *Channel) beforeSendReply(reply *ReplyMessage) error {
+	jsonReplay := make([]*ReplyJson, 0)
+	err := json.Unmarshal([]byte(reply.Content), &jsonReplay)
+	if err == nil && len(jsonReplay) > 0 {
+		for i, item := range jsonReplay {
+			if item.Content == "" {
+				continue
+			}
+			switch item.Type {
+			case "TEXT":
+				reply.Content = item.Content
+				_ = c.beforeSendReply(reply)
+			default:
+				logx.Error("未知类型", item.Type)
+			}
+			// 随机暂停
+			if i < len(jsonReplay)-1 {
+				c.randomPause()
+			}
+		}
+		return nil
+	}
+
+	err = c.subChannel.Send(reply)
+
+	return err
+}
+
+func (c *Channel) handle(chatCtx *RelevantContext, message *ChatMessage, reply *ReplyMessage) error {
+	chat := NewChatEngine(chatCtx.BaseURL, chatCtx.APIKey, chatCtx.IsFastGPT)
+
+	replyText, err := chat.ChatCompletions(context.Background(), openai.ChatModelGPT4, message.Content, message.UserId)
+	if err != nil {
+		logx.Error(err)
+		return err
+	}
+
+	reply.Content = replyText
+
+	err = c.beforeSendReply(reply)
+
+	return err
+}
+
+func (c *Channel) Produce(svcCtx *svc.ServiceContext, chatCtx *RelevantContext, message *ChatMessage) {
+	reply := &ReplyMessage{
+		ChatMessage: &ChatMessage{
+			UserId:           message.UserId,
+			MsgId:            svcCtx.NodeID.Generate().String(),
+			CreateTime:       time.Time{},
+			Type:             proto.EnumContentType_Text,
+			Content:          "",
+			FromUserId:       message.ToUserId,
+			FromUserNickname: message.ToUserNickname,
+			ToUserId:         message.FromUserId,
+			ToUserNickname:   message.FromUserNickname,
+			GroupId:          message.GroupId,
+			GroupName:        message.GroupName,
+			IsGroup:          message.IsGroup,
+			IsAt:             message.IsAt,
+		},
+	}
+
+	// 进行前置处理
+	ret := c.Before(chatCtx, message, reply)
+	if !ret {
+		return
+	}
+
+	// 可以使用 https://github.com/tmc/langchaingo 来进行会话记忆
+	err := c.handle(chatCtx, message, reply)
+	if err != nil {
+		logx.Error(err)
+		return
+	}
+
+	_ = c.After(chatCtx, message, reply)
+
+}

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov