jimmyyem 5 luni în urmă
părinte
comite
f2f418fb33
100 a modificat fișierele cu 24283 adăugiri și 754 ștergeri
  1. 6 1
      desc/all.api
  2. 33 0
      desc/wechat/avatar.api
  3. 12 0
      desc/wechat/category.api
  4. 109 0
      desc/wechat/chat_records.api
  5. 100 0
      desc/wechat/chat_session.api
  6. 33 1
      desc/wechat/employee.api
  7. 26 0
      desc/wechat/user.api
  8. 137 0
      desc/wechat/wx_card.api
  9. 109 0
      desc/wechat/wx_card_user.api
  10. 108 0
      desc/wechat/wx_card_visit.api
  11. 194 0
      ent/chatrecords.go
  12. 142 0
      ent/chatrecords/chatrecords.go
  13. 510 0
      ent/chatrecords/where.go
  14. 1111 0
      ent/chatrecords_create.go
  15. 88 0
      ent/chatrecords_delete.go
  16. 526 0
      ent/chatrecords_query.go
  17. 580 0
      ent/chatrecords_update.go
  18. 172 0
      ent/chatsession.go
  19. 122 0
      ent/chatsession/chatsession.go
  20. 420 0
      ent/chatsession/where.go
  21. 941 0
      ent/chatsession_create.go
  22. 88 0
      ent/chatsession_delete.go
  23. 526 0
      ent/chatsession_query.go
  24. 472 0
      ent/chatsession_update.go
  25. 733 14
      ent/client.go
  26. 23 1
      ent/employee.go
  27. 20 0
      ent/employee/employee.go
  28. 140 0
      ent/employee/where.go
  29. 130 0
      ent/employee_create.go
  30. 68 0
      ent/employee_update.go
  31. 10 0
      ent/ent.go
  32. 60 0
      ent/hook/hook.go
  33. 150 0
      ent/intercept/intercept.go
  34. 174 0
      ent/migrate/schema.go
  35. 927 676
      ent/mutation.go
  36. 410 0
      ent/pagination.go
  37. 15 0
      ent/predicate/predicate.go
  38. 244 0
      ent/runtime/runtime.go
  39. 51 0
      ent/schema/chat_records.go
  40. 48 0
      ent/schema/chat_session.go
  41. 2 0
      ent/schema/employee.go
  42. 61 0
      ent/schema/wx_card.go
  43. 54 0
      ent/schema/wx_card_user.go
  44. 49 0
      ent/schema/wx_card_visit.go
  45. 1176 0
      ent/set_not_nil.go
  46. 15 0
      ent/tx.go
  47. 293 0
      ent/wxcard.go
  48. 1285 0
      ent/wxcard/where.go
  49. 226 0
      ent/wxcard/wxcard.go
  50. 1743 0
      ent/wxcard_create.go
  51. 88 0
      ent/wxcard_delete.go
  52. 526 0
      ent/wxcard_query.go
  53. 952 0
      ent/wxcard_update.go
  54. 227 0
      ent/wxcarduser.go
  55. 845 0
      ent/wxcarduser/where.go
  56. 172 0
      ent/wxcarduser/wxcarduser.go
  57. 1206 0
      ent/wxcarduser_create.go
  58. 88 0
      ent/wxcarduser_delete.go
  59. 526 0
      ent/wxcarduser_query.go
  60. 582 0
      ent/wxcarduser_update.go
  61. 159 0
      ent/wxcardvisit.go
  62. 360 0
      ent/wxcardvisit/where.go
  63. 112 0
      ent/wxcardvisit/wxcardvisit.go
  64. 893 0
      ent/wxcardvisit_create.go
  65. 88 0
      ent/wxcardvisit_delete.go
  66. 526 0
      ent/wxcardvisit_query.go
  67. 456 0
      ent/wxcardvisit_update.go
  68. 37 18
      go.mod
  69. 172 40
      go.sum
  70. 123 0
      hook/aliyun/client.go
  71. 42 0
      hook/dify/chat.go
  72. 54 0
      hook/fastgpt/chat.go
  73. 16 0
      hook/fastgpt/resty.go
  74. 2 0
      internal/config/config.go
  75. 44 0
      internal/handler/User/do_api_user_login_handler.go
  76. 31 0
      internal/handler/category/get_api_category_list_handler.go
  77. 44 0
      internal/handler/chatrecords/create_chat_records_handler.go
  78. 44 0
      internal/handler/chatrecords/delete_chat_records_handler.go
  79. 44 0
      internal/handler/chatrecords/get_api_chat_list_handler.go
  80. 44 0
      internal/handler/chatrecords/get_chat_records_by_id_handler.go
  81. 44 0
      internal/handler/chatrecords/get_chat_records_list_handler.go
  82. 44 0
      internal/handler/chatrecords/save_api_chat_handler.go
  83. 44 0
      internal/handler/chatrecords/submit_api_chat_handler.go
  84. 44 0
      internal/handler/chatrecords/update_chat_records_handler.go
  85. 44 0
      internal/handler/chatsession/create_chat_session_handler.go
  86. 44 0
      internal/handler/chatsession/delete_api_session_handler.go
  87. 44 0
      internal/handler/chatsession/delete_chat_session_handler.go
  88. 44 0
      internal/handler/chatsession/get_api_session_list_handler.go
  89. 44 0
      internal/handler/chatsession/get_chat_session_by_id_handler.go
  90. 44 0
      internal/handler/chatsession/get_chat_session_list_handler.go
  91. 44 0
      internal/handler/chatsession/update_api_session_handler.go
  92. 44 0
      internal/handler/chatsession/update_chat_session_handler.go
  93. 44 0
      internal/handler/employee/get_api_employee_detail_handler.go
  94. 44 0
      internal/handler/employee/get_api_employee_list_handler.go
  95. 3 3
      internal/handler/employee/get_employee_search_test_handler.go
  96. 313 0
      internal/handler/routes.go
  97. 44 0
      internal/handler/wxcard/create_wx_card_handler.go
  98. 44 0
      internal/handler/wxcard/delete_wx_card_handler.go
  99. 44 0
      internal/handler/wxcard/get_api_wx_card_detail_handler.go
  100. 44 0
      internal/handler/wxcard/get_wx_card_by_id_handler.go

+ 6 - 1
desc/all.api

@@ -22,4 +22,9 @@ import "./wechat/tutorial.api"
 import "./wechat/token.api"
 import "./wechat/employee_config.api"
 import "./wechat/category.api"
-import "./wechat/agent_base.api"
+import "./wechat/agent_base.api"
+import "./wechat/chat_records.api"
+import "./wechat/chat_session.api"
+import "./wechat/wx_card.api"
+import "./wechat/wx_card_user.api"
+import "./wechat/wx_card_visit.api"

+ 33 - 0
desc/wechat/avatar.api

@@ -0,0 +1,33 @@
+import "../base.api"
+
+type (
+	AvatarInfo {
+
+	}
+
+	// start avatar request | 启动数字人
+    AvatarConfigReq {
+		// 名片 ID
+		CardId  *uint64 `json:"card_id,optional"`
+    }
+
+    // start avatar response | 启动数字人
+	AvatarConfigResp {
+        BaseDataInfo
+
+        // Agent information | Agent数据
+        Data AvatarInfo `json:"data"`
+    }
+)
+
+@server(
+    jwt: Auth
+    group: agent
+    middleware: Miniprogram
+)
+
+service Wechat {
+	// get avatar configuration | 获取数字人配置信息
+	@handler getApiAvatarConfig
+	post /api/avatar/config (AvatarConfigReq) returns (AvatarConfigResp)
+}

+ 12 - 0
desc/wechat/category.api

@@ -46,6 +46,18 @@ type (
 )
 
 @server(
+	jwt: Auth
+	group: category
+	middleware: Miniprogram
+)
+
+service Wechat {
+	// Get category list | 获取 category 列表
+	@handler getApiCategoryList
+	post /api/category/list () returns (CategoryListResp)
+}
+
+@server(
     group: category
 )
 

+ 109 - 0
desc/wechat/chat_records.api

@@ -0,0 +1,109 @@
+import "../base.api"
+
+type (
+    // The data of chat records information | ChatRecords信息
+    ChatRecordsInfo {
+        BaseIDInfo
+
+        // 内容 
+        Content  *string `json:"content,optional"`
+
+        // 内容类型:1-提问 2-回答 
+        ContentType  *uint8 `json:"contentType,optional"`
+
+        // 会话ID 
+        SessionId  *uint64 `json:"sessionId,optional"`
+
+        // 用户ID 
+        UserId  *uint64 `json:"userId,optional"`
+
+        // 聊天ID 
+        BotId  *uint64 `json:"botId,optional"`
+
+        // 类型:1-微信 2-小程序card 3-智能体 
+        BotType  *uint8 `json:"botType,optional,options=1|2|3"`
+
+		Finish bool `json:"finish,optional"`
+    }
+
+    // The response data of chat records list | ChatRecords列表数据
+    ChatRecordsListResp {
+        BaseDataInfo
+
+        // ChatRecords list data | ChatRecords列表数据
+        Data ChatRecordsListInfo `json:"data"`
+    }
+
+    // ChatRecords list data | ChatRecords列表数据
+    ChatRecordsListInfo {
+        BaseListInfo
+
+        // The API list data | ChatRecords列表数据
+        Data  []ChatRecordsInfo  `json:"data"`
+    }
+
+    // Get chat records list request params | ChatRecords列表请求参数
+    ChatRecordsListReq {
+        PageInfo
+
+        SessionId  *uint64 `json:"sessionId,optional"`
+		BotId *uint64 `json:"botId,optional"`
+		BotType *uint8  `json:"botType,optional"`
+    }
+
+    // ChatRecords information response | ChatRecords信息返回体
+    ChatRecordsInfoResp {
+        BaseDataInfo
+
+        // ChatRecords information | ChatRecords数据
+        Data ChatRecordsInfo `json:"data"`
+    }
+)
+
+@server(
+	jwt: Auth
+	group: chatrecords
+	middleware: Miniprogram
+)
+
+service Wechat {
+	// Create chat records information | 创建ChatRecords
+	@handler submitApiChat
+	post /api/chat/create (ChatRecordsInfo) returns ()
+
+	// Get chat records list | 获取ChatRecords列表
+	@handler getApiChatList
+	post /api/chat/list (ChatRecordsListReq) returns (ChatRecordsListResp)
+
+	// Get chat records list | 获取ChatRecords列表
+	@handler saveApiChat
+	post /api/chat/save (ChatRecordsInfo) returns (BaseMsgResp)
+}
+
+@server(
+    jwt: Auth
+    group: chatrecords
+    middleware: Authority
+)
+
+service Wechat {
+    // Create chat records information | 创建ChatRecords
+    @handler createChatRecords
+    post /chat_records/create (ChatRecordsInfo) returns (BaseMsgResp)
+
+    // Update chat records information | 更新ChatRecords
+    @handler updateChatRecords
+    post /chat_records/update (ChatRecordsInfo) returns (BaseMsgResp)
+
+    // Delete chat records information | 删除ChatRecords信息
+    @handler deleteChatRecords
+    post /chat_records/delete (IDsReq) returns (BaseMsgResp)
+
+    // Get chat records list | 获取ChatRecords列表
+    @handler getChatRecordsList
+    post /chat_records/list (ChatRecordsListReq) returns (ChatRecordsListResp)
+
+    // Get chat records by ID | 通过ID获取ChatRecords
+    @handler getChatRecordsById
+    post /chat_records (IDReq) returns (ChatRecordsInfoResp)
+}

+ 100 - 0
desc/wechat/chat_session.api

@@ -0,0 +1,100 @@
+import "../base.api"
+
+type (
+    // The data of chat session information | ChatSession信息
+    ChatSessionInfo {
+        BaseIDInfo
+
+        // 名称 
+        Name  *string `json:"name,optional"`
+
+        // 用户ID 
+        UserId  *uint64 `json:"userId,optional"`
+
+        // 聊天ID 
+        BotId  *uint64 `json:"botId,optional"`
+
+        // 类型:1-微信 2-小程序card 3-智能体 
+        BotType  *uint8 `json:"botType,optional"`
+    }
+
+    // The response data of chat session list | ChatSession列表数据
+    ChatSessionListResp {
+        BaseDataInfo
+
+        // ChatSession list data | ChatSession列表数据
+        Data ChatSessionListInfo `json:"data"`
+    }
+
+    // ChatSession list data | ChatSession列表数据
+    ChatSessionListInfo {
+        BaseListInfo
+
+        // The API list data | ChatSession列表数据
+        Data  []ChatSessionInfo  `json:"data"`
+    }
+
+    // Get chat session list request params | ChatSession列表请求参数
+    ChatSessionListReq {
+        PageInfo
+
+        BotType  *uint8 `json:"botType,optional"`
+    }
+
+    // ChatSession information response | ChatSession信息返回体
+    ChatSessionInfoResp {
+        BaseDataInfo
+
+        // ChatSession information | ChatSession数据
+        Data ChatSessionInfo `json:"data"`
+    }
+)
+
+@server(
+	jwt: Auth
+	group: chatsession
+	middleware: Miniprogram
+)
+
+service Wechat {
+	// Get chat session list | 获取ChatSession列表
+	@handler getApiSessionList
+	post /api/session/list (ChatSessionListReq) returns (ChatSessionListResp)
+
+	// Update chat session information | 更新ChatSession
+	@handler updateApiSession
+	post /api/session/update (ChatSessionInfo) returns (BaseMsgResp)
+
+	// Delete chat session information | 删除ChatSession信息
+	@handler deleteApiSession
+	post /api/session/delete (IDsReq) returns (BaseMsgResp)
+}
+
+
+@server(
+    jwt: Auth
+    group: chatsession
+    middleware: Authority
+)
+
+service Wechat {
+    // Create chat session information | 创建ChatSession
+    @handler createChatSession
+    post /chat_session/create (ChatSessionInfo) returns (BaseMsgResp)
+
+    // Update chat session information | 更新ChatSession
+    @handler updateChatSession
+    post /chat_session/update (ChatSessionInfo) returns (BaseMsgResp)
+
+    // Delete chat session information | 删除ChatSession信息
+    @handler deleteChatSession
+    post /chat_session/delete (IDsReq) returns (BaseMsgResp)
+
+    // Get chat session list | 获取ChatSession列表
+    @handler getChatSessionList
+    post /chat_session/list (ChatSessionListReq) returns (ChatSessionListResp)
+
+    // Get chat session by ID | 通过ID获取ChatSession
+    @handler getChatSessionById
+    post /chat_session (IDReq) returns (ChatSessionInfoResp)
+}

+ 33 - 1
desc/wechat/employee.api

@@ -56,6 +56,9 @@ type (
 
 		// work_experience | 工作经验
 		WorkExperience []WorkExperienceInfo `json:"workExperience,optional"`
+
+		ApiBase *string `json:"apiBase,optional"`
+		ApiKey *string `json:"apiKey,optional"`
     }
 
     // The response data of employee list | Employee列表数据
@@ -95,8 +98,37 @@ type (
         // Employee information | Employee数据
         Data EmployeeInfo `json:"data"`
     }
+
+	AuthReq {
+		Token *string `json:"token,optional"`
+		Data uint64 `json:"data,optional"`
+	}
+
+	AuthResp {
+		Token *string `json:"token,optional"`
+		Data *uint64 `json:"data,optional"`
+		Original interface{} `json:"original,optional"`
+		OK interface{} `json:"ok,optional"`
+		SecretKey string `json:"secretKey,optional"`
+	}
+)
+
+@server(
+	jwt: Auth
+	group: employee
+	middleware: Miniprogram
 )
 
+service Wechat {
+	// Get employee list | 获取Employee列表
+	@handler getApiEmployeeList
+	post /api/employee/list (EmployeeListReq) returns (EmployeeListResp)
+
+	// Get employee by ID | 通过ID获取Employee
+	@handler getApiEmployeeDetail
+	post /api/employee/detail (IDReq) returns (EmployeeInfoResp)
+}
+
 @server(
 	group: employee
 )
@@ -108,7 +140,7 @@ service Wechat {
 
 	// Get employee list | 获取Employee列表
 	@handler getEmployeeSearchTest
-	post /employee/search/test (EmployeeListReq) returns (EmployeeListResp)
+	post /employee/search/test (AuthReq) returns (AuthResp)
 
 	// Get employee by ID | 通过ID获取Employee
 	@handler getEmployeeDetail

+ 26 - 0
desc/wechat/user.api

@@ -87,8 +87,34 @@ type (
         // Department Name | 部门备注
         DepartmentRemark string `json:"departmentRemark,optional"`
     }
+
+	UserLoginReq {
+		JsCode *string `json:"js_code,optional"`
+	}
+
+	UserLoginResp {
+		BaseDataInfo
+		Data UserToken `json:"data,optional"`
+	}
+
+	UserToken {
+		Token *string `json:"token,optional"`
+		ID *uint64 `json:"id,optional"`
+		Avatar *string `json:"avatar,optional"`
+		Nickname *string `json:"nickname,optional"`
+	}
+)
+
+@server(
+	group: User
 )
 
+service Wechat {
+	// Get user basic information | 获取用户基本信息
+	@handler doApiUserLogin
+	get /api/user/login (UserLoginReq) returns (UserLoginResp)
+}
+
 @server(
     jwt: Auth
     group: User

+ 137 - 0
desc/wechat/wx_card.api

@@ -0,0 +1,137 @@
+import "../base.api"
+
+type (
+    // The data of wx card information | WxCard信息
+    WxCardInfo {
+        BaseIDInfo
+
+        // user表ID 
+        UserId  *uint64 `json:"userId,optional"`
+
+        // wx表ID 
+        WxUserId  *uint64 `json:"wxUserId,optional"`
+
+        // 头像 
+        Avatar  *string `json:"avatar,optional"`
+
+        // logo 
+        Logo  *string `json:"logo,optional"`
+
+        // 名称 
+        Name  *string `json:"name,optional"`
+
+        // 公司 
+        Company  *string `json:"company,optional"`
+
+        // 地址 
+        Address  *string `json:"address,optional"`
+
+        // 手机号 
+        Phone  *string `json:"phone,optional"`
+
+        // 公众号 
+        OfficialAccount  *string `json:"officialAccount,optional"`
+
+        // 微信号 
+        WechatAccount  *string `json:"wechatAccount,optional"`
+
+        // 邮箱 
+        Email  *string `json:"email,optional"`
+
+        // 聊天信息 
+        ApiBase  *string `json:"apiBase,optional"`
+		ApiKey  *string `json:"apiKey,optional"`
+
+        // AI信息 
+        AiInfo  *string `json:"aiInfo,optional"`
+
+        // 个人介绍 
+        Intro  *string `json:"intro,optional"`
+    }
+
+	WxCardSimpleInfo {
+		// 头像
+		Avatar  *string `json:"avatar,optional"`
+
+		// 名称
+		Name  *string `json:"name,optional"`
+	}
+
+    // The response data of wx card list | WxCard列表数据
+    WxCardListResp {
+        BaseDataInfo
+
+        // WxCard list data | WxCard列表数据
+        Data WxCardListInfo `json:"data"`
+    }
+
+    // WxCard list data | WxCard列表数据
+    WxCardListInfo {
+        BaseListInfo
+
+        // The API list data | WxCard列表数据
+        Data  []WxCardInfo  `json:"data"`
+    }
+
+    // Get wx card list request params | WxCard列表请求参数
+    WxCardListReq {
+        PageInfo
+
+        // 头像 
+        Avatar  *string `json:"avatar,optional"`
+
+        // logo 
+        Logo  *string `json:"logo,optional"`
+
+        // 名称 
+        Name  *string `json:"name,optional"`
+    }
+
+    // WxCard information response | WxCard信息返回体
+    WxCardInfoResp {
+        BaseDataInfo
+
+        // WxCard information | WxCard数据
+        Data WxCardInfo `json:"data"`
+    }
+)
+
+@server(
+	jwt: Auth
+	group: wxcard
+	middleware: Miniprogram
+)
+
+service Wechat {
+	// Get wx card by ID | 通过ID获取WxCard
+	@handler getApiWxCardDetail
+	post /api/card/detail (IDReq) returns (WxCardInfoResp)
+}
+
+@server(
+    jwt: Auth
+    group: wxcard
+    middleware: Authority
+)
+
+service Wechat {
+    // Create wx card information | 创建WxCard
+    @handler createWxCard
+    post /wx_card/create (WxCardInfo) returns (BaseMsgResp)
+
+    // Update wx card information | 更新WxCard
+    @handler updateWxCard
+    post /wx_card/update (WxCardInfo) returns (BaseMsgResp)
+
+    // Delete wx card information | 删除WxCard信息
+    @handler deleteWxCard
+    post /wx_card/delete (IDsReq) returns (BaseMsgResp)
+
+    // Get wx card list | 获取WxCard列表
+    @handler getWxCardList
+    post /wx_card/list (WxCardListReq) returns (WxCardListResp)
+
+    // Get wx card by ID | 通过ID获取WxCard
+    @handler getWxCardById
+    post /wx_card (IDReq) returns (WxCardInfoResp)
+}

+ 109 - 0
desc/wechat/wx_card_user.api

@@ -0,0 +1,109 @@
+import "../base.api"
+
+type (
+    // The data of wx card user information | WxCardUser信息
+    WxCardUserInfo {
+        BaseIDInfo
+
+        // 微信id 
+        Wxid  *string `json:"wxid,optional"`
+
+        // 微信号 
+        Account  *string `json:"account,optional"`
+
+        // 头像 
+        Avatar  *string `json:"avatar,optional"`
+
+        // 昵称 
+        Nickname  *string `json:"nickname,optional"`
+
+        // 备注名 
+        Remark  *string `json:"remark,optional"`
+
+        // 手机号 
+        Phone  *string `json:"phone,optional"`
+
+        // OpenID 
+        OpenId  *string `json:"openId,optional"`
+    }
+
+    // The response data of wx card user list | WxCardUser列表数据
+    WxCardUserListResp {
+        BaseDataInfo
+
+        // WxCardUser list data | WxCardUser列表数据
+        Data WxCardUserListInfo `json:"data"`
+    }
+
+    // WxCardUser list data | WxCardUser列表数据
+    WxCardUserListInfo {
+        BaseListInfo
+
+        // The API list data | WxCardUser列表数据
+        Data  []WxCardUserInfo  `json:"data"`
+    }
+
+    // Get wx card user list request params | WxCardUser列表请求参数
+    WxCardUserListReq {
+        PageInfo
+
+        // 微信id 
+        Wxid  *string `json:"wxid,optional"`
+
+        // 微信号 
+        Account  *string `json:"account,optional"`
+
+        // 头像 
+        Avatar  *string `json:"avatar,optional"`
+    }
+
+    // WxCardUser information response | WxCardUser信息返回体
+    WxCardUserInfoResp {
+        BaseDataInfo
+
+        // WxCardUser information | WxCardUser数据
+        Data WxCardUserInfo `json:"data"`
+    }
+)
+
+@server(
+	jwt: Auth
+	group: wxcarduser
+	middleware: Miniprogram
+)
+
+service Wechat {
+
+
+	// Update wx card user information | 更新WxCardUser
+	@handler updateApiWxCardUser
+	post /api/user/update (WxCardUserInfo) returns (BaseMsgResp)
+}
+
+@server(
+    jwt: Auth
+    group: wxcarduser
+    middleware: Authority
+)
+
+service Wechat {
+    // Create wx card user information | 创建WxCardUser
+    @handler createWxCardUser
+    post /wx_card_user/create (WxCardUserInfo) returns (BaseMsgResp)
+
+    // Update wx card user information | 更新WxCardUser
+    @handler updateWxCardUser
+    post /wx_card_user/update (WxCardUserInfo) returns (BaseMsgResp)
+
+    // Delete wx card user information | 删除WxCardUser信息
+    @handler deleteWxCardUser
+    post /wx_card_user/delete (IDsReq) returns (BaseMsgResp)
+
+    // Get wx card user list | 获取WxCardUser列表
+    @handler getWxCardUserList
+    post /wx_card_user/list (WxCardUserListReq) returns (WxCardUserListResp)
+
+    // Get wx card user by ID | 通过ID获取WxCardUser
+    @handler getWxCardUserById
+    post /wx_card_user (IDReq) returns (WxCardUserInfoResp)
+}

+ 108 - 0
desc/wechat/wx_card_visit.api

@@ -0,0 +1,108 @@
+import "../base.api"
+import "./wx_card.api"
+
+type (
+    // The data of wx card visit information | WxCardVisit信息
+    WxCardVisitInfo {
+        BaseIDInfo
+
+        // user表ID 
+        UserId  *uint64 `json:"userId,optional"`
+
+        // 被访ID 
+        BotId  *uint64 `json:"botId,optional"`
+
+        // 类型:1-微信 2-小程序 3-智能体 
+        BotType  *uint8 `json:"botType,optional"`
+
+		CardInfo WxCardSimpleInfo `json:"cardInfo,optional"`
+    }
+
+	WxCardVisitSingleInfo {
+		BaseIDInfo
+
+		// user表ID
+		UserId  *uint64 `json:"userId,optional"`
+
+		// 被访ID
+		BotId  *uint64 `json:"botId,optional"`
+
+		// 类型:1-微信 2-小程序 3-智能体
+		BotType  *uint8 `json:"botType,optional"`
+
+		CardInfo WxCardInfo `json:"cardInfo,optional"`
+	}
+
+    // The response data of wx card visit list | WxCardVisit列表数据
+    WxCardVisitListResp {
+        BaseDataInfo
+
+        // WxCardVisit list data | WxCardVisit列表数据
+        Data WxCardVisitListInfo `json:"data"`
+    }
+
+    // WxCardVisit list data | WxCardVisit列表数据
+    WxCardVisitListInfo {
+        BaseListInfo
+
+        // The API list data | WxCardVisit列表数据
+        Data  []WxCardVisitInfo  `json:"data"`
+    }
+
+    // Get wx card visit list request params | WxCardVisit列表请求参数
+    WxCardVisitListReq {
+        PageInfo
+    }
+
+    // WxCardVisit information response | WxCardVisit信息返回体
+    WxCardVisitInfoResp {
+        BaseDataInfo
+
+        // WxCardVisit information | WxCardVisit数据
+        Data WxCardVisitInfo `json:"data"`
+    }
+)
+
+@server(
+	jwt: Auth
+	group: wxcardvisit
+	middleware: Miniprogram
+)
+
+service Wechat {
+	// Create wx card visit information | 创建WxCardVisit
+	@handler submitApiWxCardVisit
+	post /api/card/visit (WxCardVisitInfo) returns (BaseMsgResp)
+
+	// Get wx card visit information | 获取WxCardVisit列表
+	@handler getApiWxCardVisitList
+	post /api/card/visit/history (WxCardVisitListReq) returns (WxCardVisitListResp)
+}
+
+@server(
+    jwt: Auth
+    group: wxcardvisit
+    middleware: Authority
+)
+
+service Wechat {
+    // Create wx card visit information | 创建WxCardVisit
+    @handler createWxCardVisit
+    post /wx_card_visit/create (WxCardVisitInfo) returns (BaseMsgResp)
+
+    // Update wx card visit information | 更新WxCardVisit
+    @handler updateWxCardVisit
+    post /wx_card_visit/update (WxCardVisitInfo) returns (BaseMsgResp)
+
+    // Delete wx card visit information | 删除WxCardVisit信息
+    @handler deleteWxCardVisit
+    post /wx_card_visit/delete (IDsReq) returns (BaseMsgResp)
+
+    // Get wx card visit list | 获取WxCardVisit列表
+    @handler getWxCardVisitList
+    post /wx_card_visit/list (WxCardVisitListReq) returns (WxCardVisitListResp)
+
+    // Get wx card visit by ID | 通过ID获取WxCardVisit
+    @handler getWxCardVisitById
+    post /wx_card_visit (IDReq) returns (WxCardVisitInfoResp)
+}

+ 194 - 0
ent/chatrecords.go

@@ -0,0 +1,194 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"fmt"
+	"strings"
+	"time"
+	"wechat-api/ent/chatrecords"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+)
+
+// ChatRecords is the model entity for the ChatRecords schema.
+type ChatRecords struct {
+	config `json:"-"`
+	// ID of the ent.
+	ID uint64 `json:"id,omitempty"`
+	// Create Time | 创建日期
+	CreatedAt time.Time `json:"created_at,omitempty"`
+	// Update Time | 修改日期
+	UpdatedAt time.Time `json:"updated_at,omitempty"`
+	// Delete Time | 删除日期
+	DeletedAt time.Time `json:"deleted_at,omitempty"`
+	// 内容
+	Content string `json:"content,omitempty"`
+	// 内容类型:1-提问 2-回答
+	ContentType uint8 `json:"content_type,omitempty"`
+	// 会话ID
+	SessionID uint64 `json:"session_id,omitempty"`
+	// 用户ID
+	UserID uint64 `json:"user_id,omitempty"`
+	// 聊天ID
+	BotID uint64 `json:"bot_id,omitempty"`
+	// 类型:1-微信 2-小程序card 3-智能体
+	BotType      uint8 `json:"bot_type,omitempty"`
+	selectValues sql.SelectValues
+}
+
+// scanValues returns the types for scanning values from sql.Rows.
+func (*ChatRecords) scanValues(columns []string) ([]any, error) {
+	values := make([]any, len(columns))
+	for i := range columns {
+		switch columns[i] {
+		case chatrecords.FieldID, chatrecords.FieldContentType, chatrecords.FieldSessionID, chatrecords.FieldUserID, chatrecords.FieldBotID, chatrecords.FieldBotType:
+			values[i] = new(sql.NullInt64)
+		case chatrecords.FieldContent:
+			values[i] = new(sql.NullString)
+		case chatrecords.FieldCreatedAt, chatrecords.FieldUpdatedAt, chatrecords.FieldDeletedAt:
+			values[i] = new(sql.NullTime)
+		default:
+			values[i] = new(sql.UnknownType)
+		}
+	}
+	return values, nil
+}
+
+// assignValues assigns the values that were returned from sql.Rows (after scanning)
+// to the ChatRecords fields.
+func (cr *ChatRecords) assignValues(columns []string, values []any) error {
+	if m, n := len(values), len(columns); m < n {
+		return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
+	}
+	for i := range columns {
+		switch columns[i] {
+		case chatrecords.FieldID:
+			value, ok := values[i].(*sql.NullInt64)
+			if !ok {
+				return fmt.Errorf("unexpected type %T for field id", value)
+			}
+			cr.ID = uint64(value.Int64)
+		case chatrecords.FieldCreatedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field created_at", values[i])
+			} else if value.Valid {
+				cr.CreatedAt = value.Time
+			}
+		case chatrecords.FieldUpdatedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field updated_at", values[i])
+			} else if value.Valid {
+				cr.UpdatedAt = value.Time
+			}
+		case chatrecords.FieldDeletedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field deleted_at", values[i])
+			} else if value.Valid {
+				cr.DeletedAt = value.Time
+			}
+		case chatrecords.FieldContent:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field content", values[i])
+			} else if value.Valid {
+				cr.Content = value.String
+			}
+		case chatrecords.FieldContentType:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field content_type", values[i])
+			} else if value.Valid {
+				cr.ContentType = uint8(value.Int64)
+			}
+		case chatrecords.FieldSessionID:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field session_id", values[i])
+			} else if value.Valid {
+				cr.SessionID = uint64(value.Int64)
+			}
+		case chatrecords.FieldUserID:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field user_id", values[i])
+			} else if value.Valid {
+				cr.UserID = uint64(value.Int64)
+			}
+		case chatrecords.FieldBotID:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field bot_id", values[i])
+			} else if value.Valid {
+				cr.BotID = uint64(value.Int64)
+			}
+		case chatrecords.FieldBotType:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field bot_type", values[i])
+			} else if value.Valid {
+				cr.BotType = uint8(value.Int64)
+			}
+		default:
+			cr.selectValues.Set(columns[i], values[i])
+		}
+	}
+	return nil
+}
+
+// Value returns the ent.Value that was dynamically selected and assigned to the ChatRecords.
+// This includes values selected through modifiers, order, etc.
+func (cr *ChatRecords) Value(name string) (ent.Value, error) {
+	return cr.selectValues.Get(name)
+}
+
+// Update returns a builder for updating this ChatRecords.
+// Note that you need to call ChatRecords.Unwrap() before calling this method if this ChatRecords
+// was returned from a transaction, and the transaction was committed or rolled back.
+func (cr *ChatRecords) Update() *ChatRecordsUpdateOne {
+	return NewChatRecordsClient(cr.config).UpdateOne(cr)
+}
+
+// Unwrap unwraps the ChatRecords entity that was returned from a transaction after it was closed,
+// so that all future queries will be executed through the driver which created the transaction.
+func (cr *ChatRecords) Unwrap() *ChatRecords {
+	_tx, ok := cr.config.driver.(*txDriver)
+	if !ok {
+		panic("ent: ChatRecords is not a transactional entity")
+	}
+	cr.config.driver = _tx.drv
+	return cr
+}
+
+// String implements the fmt.Stringer.
+func (cr *ChatRecords) String() string {
+	var builder strings.Builder
+	builder.WriteString("ChatRecords(")
+	builder.WriteString(fmt.Sprintf("id=%v, ", cr.ID))
+	builder.WriteString("created_at=")
+	builder.WriteString(cr.CreatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("updated_at=")
+	builder.WriteString(cr.UpdatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("deleted_at=")
+	builder.WriteString(cr.DeletedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("content=")
+	builder.WriteString(cr.Content)
+	builder.WriteString(", ")
+	builder.WriteString("content_type=")
+	builder.WriteString(fmt.Sprintf("%v", cr.ContentType))
+	builder.WriteString(", ")
+	builder.WriteString("session_id=")
+	builder.WriteString(fmt.Sprintf("%v", cr.SessionID))
+	builder.WriteString(", ")
+	builder.WriteString("user_id=")
+	builder.WriteString(fmt.Sprintf("%v", cr.UserID))
+	builder.WriteString(", ")
+	builder.WriteString("bot_id=")
+	builder.WriteString(fmt.Sprintf("%v", cr.BotID))
+	builder.WriteString(", ")
+	builder.WriteString("bot_type=")
+	builder.WriteString(fmt.Sprintf("%v", cr.BotType))
+	builder.WriteByte(')')
+	return builder.String()
+}
+
+// ChatRecordsSlice is a parsable slice of ChatRecords.
+type ChatRecordsSlice []*ChatRecords

+ 142 - 0
ent/chatrecords/chatrecords.go

@@ -0,0 +1,142 @@
+// Code generated by ent, DO NOT EDIT.
+
+package chatrecords
+
+import (
+	"time"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+)
+
+const (
+	// Label holds the string label denoting the chatrecords type in the database.
+	Label = "chat_records"
+	// FieldID holds the string denoting the id field in the database.
+	FieldID = "id"
+	// FieldCreatedAt holds the string denoting the created_at field in the database.
+	FieldCreatedAt = "created_at"
+	// FieldUpdatedAt holds the string denoting the updated_at field in the database.
+	FieldUpdatedAt = "updated_at"
+	// FieldDeletedAt holds the string denoting the deleted_at field in the database.
+	FieldDeletedAt = "deleted_at"
+	// FieldContent holds the string denoting the content field in the database.
+	FieldContent = "content"
+	// FieldContentType holds the string denoting the content_type field in the database.
+	FieldContentType = "content_type"
+	// FieldSessionID holds the string denoting the session_id field in the database.
+	FieldSessionID = "session_id"
+	// FieldUserID holds the string denoting the user_id field in the database.
+	FieldUserID = "user_id"
+	// FieldBotID holds the string denoting the bot_id field in the database.
+	FieldBotID = "bot_id"
+	// FieldBotType holds the string denoting the bot_type field in the database.
+	FieldBotType = "bot_type"
+	// Table holds the table name of the chatrecords in the database.
+	Table = "chat_records"
+)
+
+// Columns holds all SQL columns for chatrecords fields.
+var Columns = []string{
+	FieldID,
+	FieldCreatedAt,
+	FieldUpdatedAt,
+	FieldDeletedAt,
+	FieldContent,
+	FieldContentType,
+	FieldSessionID,
+	FieldUserID,
+	FieldBotID,
+	FieldBotType,
+}
+
+// ValidColumn reports if the column name is valid (part of the table columns).
+func ValidColumn(column string) bool {
+	for i := range Columns {
+		if column == Columns[i] {
+			return true
+		}
+	}
+	return false
+}
+
+// Note that the variables below are initialized by the runtime
+// package on the initialization of the application. Therefore,
+// it should be imported in the main as follows:
+//
+//	import _ "wechat-api/ent/runtime"
+var (
+	Hooks        [1]ent.Hook
+	Interceptors [1]ent.Interceptor
+	// DefaultCreatedAt holds the default value on creation for the "created_at" field.
+	DefaultCreatedAt func() time.Time
+	// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
+	DefaultUpdatedAt func() time.Time
+	// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
+	UpdateDefaultUpdatedAt func() time.Time
+	// DefaultContent holds the default value on creation for the "content" field.
+	DefaultContent string
+	// DefaultContentType holds the default value on creation for the "content_type" field.
+	DefaultContentType uint8
+	// DefaultSessionID holds the default value on creation for the "session_id" field.
+	DefaultSessionID uint64
+	// DefaultUserID holds the default value on creation for the "user_id" field.
+	DefaultUserID uint64
+	// DefaultBotID holds the default value on creation for the "bot_id" field.
+	DefaultBotID uint64
+	// DefaultBotType holds the default value on creation for the "bot_type" field.
+	DefaultBotType uint8
+)
+
+// OrderOption defines the ordering options for the ChatRecords queries.
+type OrderOption func(*sql.Selector)
+
+// ByID orders the results by the id field.
+func ByID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldID, opts...).ToFunc()
+}
+
+// ByCreatedAt orders the results by the created_at field.
+func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
+}
+
+// ByUpdatedAt orders the results by the updated_at field.
+func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
+}
+
+// ByDeletedAt orders the results by the deleted_at field.
+func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldDeletedAt, opts...).ToFunc()
+}
+
+// ByContent orders the results by the content field.
+func ByContent(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldContent, opts...).ToFunc()
+}
+
+// ByContentType orders the results by the content_type field.
+func ByContentType(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldContentType, opts...).ToFunc()
+}
+
+// BySessionID orders the results by the session_id field.
+func BySessionID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldSessionID, opts...).ToFunc()
+}
+
+// ByUserID orders the results by the user_id field.
+func ByUserID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldUserID, opts...).ToFunc()
+}
+
+// ByBotID orders the results by the bot_id field.
+func ByBotID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldBotID, opts...).ToFunc()
+}
+
+// ByBotType orders the results by the bot_type field.
+func ByBotType(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldBotType, opts...).ToFunc()
+}

+ 510 - 0
ent/chatrecords/where.go

@@ -0,0 +1,510 @@
+// Code generated by ent, DO NOT EDIT.
+
+package chatrecords
+
+import (
+	"time"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+)
+
+// ID filters vertices based on their ID field.
+func ID(id uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldID, id))
+}
+
+// IDEQ applies the EQ predicate on the ID field.
+func IDEQ(id uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldID, id))
+}
+
+// IDNEQ applies the NEQ predicate on the ID field.
+func IDNEQ(id uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNEQ(FieldID, id))
+}
+
+// IDIn applies the In predicate on the ID field.
+func IDIn(ids ...uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldIn(FieldID, ids...))
+}
+
+// IDNotIn applies the NotIn predicate on the ID field.
+func IDNotIn(ids ...uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNotIn(FieldID, ids...))
+}
+
+// IDGT applies the GT predicate on the ID field.
+func IDGT(id uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGT(FieldID, id))
+}
+
+// IDGTE applies the GTE predicate on the ID field.
+func IDGTE(id uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGTE(FieldID, id))
+}
+
+// IDLT applies the LT predicate on the ID field.
+func IDLT(id uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLT(FieldID, id))
+}
+
+// IDLTE applies the LTE predicate on the ID field.
+func IDLTE(id uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLTE(FieldID, id))
+}
+
+// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
+func CreatedAt(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
+func UpdatedAt(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ.
+func DeletedAt(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// Content applies equality check predicate on the "content" field. It's identical to ContentEQ.
+func Content(v string) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldContent, v))
+}
+
+// ContentType applies equality check predicate on the "content_type" field. It's identical to ContentTypeEQ.
+func ContentType(v uint8) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldContentType, v))
+}
+
+// SessionID applies equality check predicate on the "session_id" field. It's identical to SessionIDEQ.
+func SessionID(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldSessionID, v))
+}
+
+// UserID applies equality check predicate on the "user_id" field. It's identical to UserIDEQ.
+func UserID(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldUserID, v))
+}
+
+// BotID applies equality check predicate on the "bot_id" field. It's identical to BotIDEQ.
+func BotID(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldBotID, v))
+}
+
+// BotType applies equality check predicate on the "bot_type" field. It's identical to BotTypeEQ.
+func BotType(v uint8) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldBotType, v))
+}
+
+// CreatedAtEQ applies the EQ predicate on the "created_at" field.
+func CreatedAtEQ(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
+func CreatedAtNEQ(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtIn applies the In predicate on the "created_at" field.
+func CreatedAtIn(vs ...time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
+func CreatedAtNotIn(vs ...time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNotIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtGT applies the GT predicate on the "created_at" field.
+func CreatedAtGT(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGT(FieldCreatedAt, v))
+}
+
+// CreatedAtGTE applies the GTE predicate on the "created_at" field.
+func CreatedAtGTE(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGTE(FieldCreatedAt, v))
+}
+
+// CreatedAtLT applies the LT predicate on the "created_at" field.
+func CreatedAtLT(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLT(FieldCreatedAt, v))
+}
+
+// CreatedAtLTE applies the LTE predicate on the "created_at" field.
+func CreatedAtLTE(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLTE(FieldCreatedAt, v))
+}
+
+// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
+func UpdatedAtEQ(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
+func UpdatedAtNEQ(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtIn applies the In predicate on the "updated_at" field.
+func UpdatedAtIn(vs ...time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
+func UpdatedAtNotIn(vs ...time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNotIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtGT applies the GT predicate on the "updated_at" field.
+func UpdatedAtGT(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
+func UpdatedAtGTE(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGTE(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLT applies the LT predicate on the "updated_at" field.
+func UpdatedAtLT(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
+func UpdatedAtLTE(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLTE(FieldUpdatedAt, v))
+}
+
+// DeletedAtEQ applies the EQ predicate on the "deleted_at" field.
+func DeletedAtEQ(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field.
+func DeletedAtNEQ(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtIn applies the In predicate on the "deleted_at" field.
+func DeletedAtIn(vs ...time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field.
+func DeletedAtNotIn(vs ...time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNotIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtGT applies the GT predicate on the "deleted_at" field.
+func DeletedAtGT(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGT(FieldDeletedAt, v))
+}
+
+// DeletedAtGTE applies the GTE predicate on the "deleted_at" field.
+func DeletedAtGTE(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGTE(FieldDeletedAt, v))
+}
+
+// DeletedAtLT applies the LT predicate on the "deleted_at" field.
+func DeletedAtLT(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLT(FieldDeletedAt, v))
+}
+
+// DeletedAtLTE applies the LTE predicate on the "deleted_at" field.
+func DeletedAtLTE(v time.Time) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLTE(FieldDeletedAt, v))
+}
+
+// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field.
+func DeletedAtIsNil() predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldIsNull(FieldDeletedAt))
+}
+
+// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field.
+func DeletedAtNotNil() predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNotNull(FieldDeletedAt))
+}
+
+// ContentEQ applies the EQ predicate on the "content" field.
+func ContentEQ(v string) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldContent, v))
+}
+
+// ContentNEQ applies the NEQ predicate on the "content" field.
+func ContentNEQ(v string) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNEQ(FieldContent, v))
+}
+
+// ContentIn applies the In predicate on the "content" field.
+func ContentIn(vs ...string) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldIn(FieldContent, vs...))
+}
+
+// ContentNotIn applies the NotIn predicate on the "content" field.
+func ContentNotIn(vs ...string) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNotIn(FieldContent, vs...))
+}
+
+// ContentGT applies the GT predicate on the "content" field.
+func ContentGT(v string) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGT(FieldContent, v))
+}
+
+// ContentGTE applies the GTE predicate on the "content" field.
+func ContentGTE(v string) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGTE(FieldContent, v))
+}
+
+// ContentLT applies the LT predicate on the "content" field.
+func ContentLT(v string) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLT(FieldContent, v))
+}
+
+// ContentLTE applies the LTE predicate on the "content" field.
+func ContentLTE(v string) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLTE(FieldContent, v))
+}
+
+// ContentContains applies the Contains predicate on the "content" field.
+func ContentContains(v string) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldContains(FieldContent, v))
+}
+
+// ContentHasPrefix applies the HasPrefix predicate on the "content" field.
+func ContentHasPrefix(v string) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldHasPrefix(FieldContent, v))
+}
+
+// ContentHasSuffix applies the HasSuffix predicate on the "content" field.
+func ContentHasSuffix(v string) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldHasSuffix(FieldContent, v))
+}
+
+// ContentEqualFold applies the EqualFold predicate on the "content" field.
+func ContentEqualFold(v string) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEqualFold(FieldContent, v))
+}
+
+// ContentContainsFold applies the ContainsFold predicate on the "content" field.
+func ContentContainsFold(v string) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldContainsFold(FieldContent, v))
+}
+
+// ContentTypeEQ applies the EQ predicate on the "content_type" field.
+func ContentTypeEQ(v uint8) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldContentType, v))
+}
+
+// ContentTypeNEQ applies the NEQ predicate on the "content_type" field.
+func ContentTypeNEQ(v uint8) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNEQ(FieldContentType, v))
+}
+
+// ContentTypeIn applies the In predicate on the "content_type" field.
+func ContentTypeIn(vs ...uint8) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldIn(FieldContentType, vs...))
+}
+
+// ContentTypeNotIn applies the NotIn predicate on the "content_type" field.
+func ContentTypeNotIn(vs ...uint8) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNotIn(FieldContentType, vs...))
+}
+
+// ContentTypeGT applies the GT predicate on the "content_type" field.
+func ContentTypeGT(v uint8) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGT(FieldContentType, v))
+}
+
+// ContentTypeGTE applies the GTE predicate on the "content_type" field.
+func ContentTypeGTE(v uint8) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGTE(FieldContentType, v))
+}
+
+// ContentTypeLT applies the LT predicate on the "content_type" field.
+func ContentTypeLT(v uint8) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLT(FieldContentType, v))
+}
+
+// ContentTypeLTE applies the LTE predicate on the "content_type" field.
+func ContentTypeLTE(v uint8) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLTE(FieldContentType, v))
+}
+
+// SessionIDEQ applies the EQ predicate on the "session_id" field.
+func SessionIDEQ(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldSessionID, v))
+}
+
+// SessionIDNEQ applies the NEQ predicate on the "session_id" field.
+func SessionIDNEQ(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNEQ(FieldSessionID, v))
+}
+
+// SessionIDIn applies the In predicate on the "session_id" field.
+func SessionIDIn(vs ...uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldIn(FieldSessionID, vs...))
+}
+
+// SessionIDNotIn applies the NotIn predicate on the "session_id" field.
+func SessionIDNotIn(vs ...uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNotIn(FieldSessionID, vs...))
+}
+
+// SessionIDGT applies the GT predicate on the "session_id" field.
+func SessionIDGT(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGT(FieldSessionID, v))
+}
+
+// SessionIDGTE applies the GTE predicate on the "session_id" field.
+func SessionIDGTE(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGTE(FieldSessionID, v))
+}
+
+// SessionIDLT applies the LT predicate on the "session_id" field.
+func SessionIDLT(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLT(FieldSessionID, v))
+}
+
+// SessionIDLTE applies the LTE predicate on the "session_id" field.
+func SessionIDLTE(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLTE(FieldSessionID, v))
+}
+
+// UserIDEQ applies the EQ predicate on the "user_id" field.
+func UserIDEQ(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldUserID, v))
+}
+
+// UserIDNEQ applies the NEQ predicate on the "user_id" field.
+func UserIDNEQ(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNEQ(FieldUserID, v))
+}
+
+// UserIDIn applies the In predicate on the "user_id" field.
+func UserIDIn(vs ...uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldIn(FieldUserID, vs...))
+}
+
+// UserIDNotIn applies the NotIn predicate on the "user_id" field.
+func UserIDNotIn(vs ...uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNotIn(FieldUserID, vs...))
+}
+
+// UserIDGT applies the GT predicate on the "user_id" field.
+func UserIDGT(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGT(FieldUserID, v))
+}
+
+// UserIDGTE applies the GTE predicate on the "user_id" field.
+func UserIDGTE(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGTE(FieldUserID, v))
+}
+
+// UserIDLT applies the LT predicate on the "user_id" field.
+func UserIDLT(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLT(FieldUserID, v))
+}
+
+// UserIDLTE applies the LTE predicate on the "user_id" field.
+func UserIDLTE(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLTE(FieldUserID, v))
+}
+
+// BotIDEQ applies the EQ predicate on the "bot_id" field.
+func BotIDEQ(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldBotID, v))
+}
+
+// BotIDNEQ applies the NEQ predicate on the "bot_id" field.
+func BotIDNEQ(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNEQ(FieldBotID, v))
+}
+
+// BotIDIn applies the In predicate on the "bot_id" field.
+func BotIDIn(vs ...uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldIn(FieldBotID, vs...))
+}
+
+// BotIDNotIn applies the NotIn predicate on the "bot_id" field.
+func BotIDNotIn(vs ...uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNotIn(FieldBotID, vs...))
+}
+
+// BotIDGT applies the GT predicate on the "bot_id" field.
+func BotIDGT(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGT(FieldBotID, v))
+}
+
+// BotIDGTE applies the GTE predicate on the "bot_id" field.
+func BotIDGTE(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGTE(FieldBotID, v))
+}
+
+// BotIDLT applies the LT predicate on the "bot_id" field.
+func BotIDLT(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLT(FieldBotID, v))
+}
+
+// BotIDLTE applies the LTE predicate on the "bot_id" field.
+func BotIDLTE(v uint64) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLTE(FieldBotID, v))
+}
+
+// BotTypeEQ applies the EQ predicate on the "bot_type" field.
+func BotTypeEQ(v uint8) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldEQ(FieldBotType, v))
+}
+
+// BotTypeNEQ applies the NEQ predicate on the "bot_type" field.
+func BotTypeNEQ(v uint8) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNEQ(FieldBotType, v))
+}
+
+// BotTypeIn applies the In predicate on the "bot_type" field.
+func BotTypeIn(vs ...uint8) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldIn(FieldBotType, vs...))
+}
+
+// BotTypeNotIn applies the NotIn predicate on the "bot_type" field.
+func BotTypeNotIn(vs ...uint8) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldNotIn(FieldBotType, vs...))
+}
+
+// BotTypeGT applies the GT predicate on the "bot_type" field.
+func BotTypeGT(v uint8) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGT(FieldBotType, v))
+}
+
+// BotTypeGTE applies the GTE predicate on the "bot_type" field.
+func BotTypeGTE(v uint8) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldGTE(FieldBotType, v))
+}
+
+// BotTypeLT applies the LT predicate on the "bot_type" field.
+func BotTypeLT(v uint8) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLT(FieldBotType, v))
+}
+
+// BotTypeLTE applies the LTE predicate on the "bot_type" field.
+func BotTypeLTE(v uint8) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.FieldLTE(FieldBotType, v))
+}
+
+// And groups predicates with the AND operator between them.
+func And(predicates ...predicate.ChatRecords) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.AndPredicates(predicates...))
+}
+
+// Or groups predicates with the OR operator between them.
+func Or(predicates ...predicate.ChatRecords) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.OrPredicates(predicates...))
+}
+
+// Not applies the not operator on the given predicate.
+func Not(p predicate.ChatRecords) predicate.ChatRecords {
+	return predicate.ChatRecords(sql.NotPredicates(p))
+}

+ 1111 - 0
ent/chatrecords_create.go

@@ -0,0 +1,1111 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/chatrecords"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// ChatRecordsCreate is the builder for creating a ChatRecords entity.
+type ChatRecordsCreate struct {
+	config
+	mutation *ChatRecordsMutation
+	hooks    []Hook
+	conflict []sql.ConflictOption
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (crc *ChatRecordsCreate) SetCreatedAt(t time.Time) *ChatRecordsCreate {
+	crc.mutation.SetCreatedAt(t)
+	return crc
+}
+
+// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
+func (crc *ChatRecordsCreate) SetNillableCreatedAt(t *time.Time) *ChatRecordsCreate {
+	if t != nil {
+		crc.SetCreatedAt(*t)
+	}
+	return crc
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (crc *ChatRecordsCreate) SetUpdatedAt(t time.Time) *ChatRecordsCreate {
+	crc.mutation.SetUpdatedAt(t)
+	return crc
+}
+
+// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
+func (crc *ChatRecordsCreate) SetNillableUpdatedAt(t *time.Time) *ChatRecordsCreate {
+	if t != nil {
+		crc.SetUpdatedAt(*t)
+	}
+	return crc
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (crc *ChatRecordsCreate) SetDeletedAt(t time.Time) *ChatRecordsCreate {
+	crc.mutation.SetDeletedAt(t)
+	return crc
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (crc *ChatRecordsCreate) SetNillableDeletedAt(t *time.Time) *ChatRecordsCreate {
+	if t != nil {
+		crc.SetDeletedAt(*t)
+	}
+	return crc
+}
+
+// SetContent sets the "content" field.
+func (crc *ChatRecordsCreate) SetContent(s string) *ChatRecordsCreate {
+	crc.mutation.SetContent(s)
+	return crc
+}
+
+// SetNillableContent sets the "content" field if the given value is not nil.
+func (crc *ChatRecordsCreate) SetNillableContent(s *string) *ChatRecordsCreate {
+	if s != nil {
+		crc.SetContent(*s)
+	}
+	return crc
+}
+
+// SetContentType sets the "content_type" field.
+func (crc *ChatRecordsCreate) SetContentType(u uint8) *ChatRecordsCreate {
+	crc.mutation.SetContentType(u)
+	return crc
+}
+
+// SetNillableContentType sets the "content_type" field if the given value is not nil.
+func (crc *ChatRecordsCreate) SetNillableContentType(u *uint8) *ChatRecordsCreate {
+	if u != nil {
+		crc.SetContentType(*u)
+	}
+	return crc
+}
+
+// SetSessionID sets the "session_id" field.
+func (crc *ChatRecordsCreate) SetSessionID(u uint64) *ChatRecordsCreate {
+	crc.mutation.SetSessionID(u)
+	return crc
+}
+
+// SetNillableSessionID sets the "session_id" field if the given value is not nil.
+func (crc *ChatRecordsCreate) SetNillableSessionID(u *uint64) *ChatRecordsCreate {
+	if u != nil {
+		crc.SetSessionID(*u)
+	}
+	return crc
+}
+
+// SetUserID sets the "user_id" field.
+func (crc *ChatRecordsCreate) SetUserID(u uint64) *ChatRecordsCreate {
+	crc.mutation.SetUserID(u)
+	return crc
+}
+
+// SetNillableUserID sets the "user_id" field if the given value is not nil.
+func (crc *ChatRecordsCreate) SetNillableUserID(u *uint64) *ChatRecordsCreate {
+	if u != nil {
+		crc.SetUserID(*u)
+	}
+	return crc
+}
+
+// SetBotID sets the "bot_id" field.
+func (crc *ChatRecordsCreate) SetBotID(u uint64) *ChatRecordsCreate {
+	crc.mutation.SetBotID(u)
+	return crc
+}
+
+// SetNillableBotID sets the "bot_id" field if the given value is not nil.
+func (crc *ChatRecordsCreate) SetNillableBotID(u *uint64) *ChatRecordsCreate {
+	if u != nil {
+		crc.SetBotID(*u)
+	}
+	return crc
+}
+
+// SetBotType sets the "bot_type" field.
+func (crc *ChatRecordsCreate) SetBotType(u uint8) *ChatRecordsCreate {
+	crc.mutation.SetBotType(u)
+	return crc
+}
+
+// SetNillableBotType sets the "bot_type" field if the given value is not nil.
+func (crc *ChatRecordsCreate) SetNillableBotType(u *uint8) *ChatRecordsCreate {
+	if u != nil {
+		crc.SetBotType(*u)
+	}
+	return crc
+}
+
+// SetID sets the "id" field.
+func (crc *ChatRecordsCreate) SetID(u uint64) *ChatRecordsCreate {
+	crc.mutation.SetID(u)
+	return crc
+}
+
+// Mutation returns the ChatRecordsMutation object of the builder.
+func (crc *ChatRecordsCreate) Mutation() *ChatRecordsMutation {
+	return crc.mutation
+}
+
+// Save creates the ChatRecords in the database.
+func (crc *ChatRecordsCreate) Save(ctx context.Context) (*ChatRecords, error) {
+	if err := crc.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, crc.sqlSave, crc.mutation, crc.hooks)
+}
+
+// SaveX calls Save and panics if Save returns an error.
+func (crc *ChatRecordsCreate) SaveX(ctx context.Context) *ChatRecords {
+	v, err := crc.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (crc *ChatRecordsCreate) Exec(ctx context.Context) error {
+	_, err := crc.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (crc *ChatRecordsCreate) ExecX(ctx context.Context) {
+	if err := crc.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (crc *ChatRecordsCreate) defaults() error {
+	if _, ok := crc.mutation.CreatedAt(); !ok {
+		if chatrecords.DefaultCreatedAt == nil {
+			return fmt.Errorf("ent: uninitialized chatrecords.DefaultCreatedAt (forgotten import ent/runtime?)")
+		}
+		v := chatrecords.DefaultCreatedAt()
+		crc.mutation.SetCreatedAt(v)
+	}
+	if _, ok := crc.mutation.UpdatedAt(); !ok {
+		if chatrecords.DefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized chatrecords.DefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := chatrecords.DefaultUpdatedAt()
+		crc.mutation.SetUpdatedAt(v)
+	}
+	if _, ok := crc.mutation.Content(); !ok {
+		v := chatrecords.DefaultContent
+		crc.mutation.SetContent(v)
+	}
+	if _, ok := crc.mutation.ContentType(); !ok {
+		v := chatrecords.DefaultContentType
+		crc.mutation.SetContentType(v)
+	}
+	if _, ok := crc.mutation.SessionID(); !ok {
+		v := chatrecords.DefaultSessionID
+		crc.mutation.SetSessionID(v)
+	}
+	if _, ok := crc.mutation.UserID(); !ok {
+		v := chatrecords.DefaultUserID
+		crc.mutation.SetUserID(v)
+	}
+	if _, ok := crc.mutation.BotID(); !ok {
+		v := chatrecords.DefaultBotID
+		crc.mutation.SetBotID(v)
+	}
+	if _, ok := crc.mutation.BotType(); !ok {
+		v := chatrecords.DefaultBotType
+		crc.mutation.SetBotType(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (crc *ChatRecordsCreate) check() error {
+	if _, ok := crc.mutation.CreatedAt(); !ok {
+		return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "ChatRecords.created_at"`)}
+	}
+	if _, ok := crc.mutation.UpdatedAt(); !ok {
+		return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "ChatRecords.updated_at"`)}
+	}
+	if _, ok := crc.mutation.Content(); !ok {
+		return &ValidationError{Name: "content", err: errors.New(`ent: missing required field "ChatRecords.content"`)}
+	}
+	if _, ok := crc.mutation.ContentType(); !ok {
+		return &ValidationError{Name: "content_type", err: errors.New(`ent: missing required field "ChatRecords.content_type"`)}
+	}
+	if _, ok := crc.mutation.SessionID(); !ok {
+		return &ValidationError{Name: "session_id", err: errors.New(`ent: missing required field "ChatRecords.session_id"`)}
+	}
+	if _, ok := crc.mutation.UserID(); !ok {
+		return &ValidationError{Name: "user_id", err: errors.New(`ent: missing required field "ChatRecords.user_id"`)}
+	}
+	if _, ok := crc.mutation.BotID(); !ok {
+		return &ValidationError{Name: "bot_id", err: errors.New(`ent: missing required field "ChatRecords.bot_id"`)}
+	}
+	if _, ok := crc.mutation.BotType(); !ok {
+		return &ValidationError{Name: "bot_type", err: errors.New(`ent: missing required field "ChatRecords.bot_type"`)}
+	}
+	return nil
+}
+
+func (crc *ChatRecordsCreate) sqlSave(ctx context.Context) (*ChatRecords, error) {
+	if err := crc.check(); err != nil {
+		return nil, err
+	}
+	_node, _spec := crc.createSpec()
+	if err := sqlgraph.CreateNode(ctx, crc.driver, _spec); err != nil {
+		if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	if _spec.ID.Value != _node.ID {
+		id := _spec.ID.Value.(int64)
+		_node.ID = uint64(id)
+	}
+	crc.mutation.id = &_node.ID
+	crc.mutation.done = true
+	return _node, nil
+}
+
+func (crc *ChatRecordsCreate) createSpec() (*ChatRecords, *sqlgraph.CreateSpec) {
+	var (
+		_node = &ChatRecords{config: crc.config}
+		_spec = sqlgraph.NewCreateSpec(chatrecords.Table, sqlgraph.NewFieldSpec(chatrecords.FieldID, field.TypeUint64))
+	)
+	_spec.OnConflict = crc.conflict
+	if id, ok := crc.mutation.ID(); ok {
+		_node.ID = id
+		_spec.ID.Value = id
+	}
+	if value, ok := crc.mutation.CreatedAt(); ok {
+		_spec.SetField(chatrecords.FieldCreatedAt, field.TypeTime, value)
+		_node.CreatedAt = value
+	}
+	if value, ok := crc.mutation.UpdatedAt(); ok {
+		_spec.SetField(chatrecords.FieldUpdatedAt, field.TypeTime, value)
+		_node.UpdatedAt = value
+	}
+	if value, ok := crc.mutation.DeletedAt(); ok {
+		_spec.SetField(chatrecords.FieldDeletedAt, field.TypeTime, value)
+		_node.DeletedAt = value
+	}
+	if value, ok := crc.mutation.Content(); ok {
+		_spec.SetField(chatrecords.FieldContent, field.TypeString, value)
+		_node.Content = value
+	}
+	if value, ok := crc.mutation.ContentType(); ok {
+		_spec.SetField(chatrecords.FieldContentType, field.TypeUint8, value)
+		_node.ContentType = value
+	}
+	if value, ok := crc.mutation.SessionID(); ok {
+		_spec.SetField(chatrecords.FieldSessionID, field.TypeUint64, value)
+		_node.SessionID = value
+	}
+	if value, ok := crc.mutation.UserID(); ok {
+		_spec.SetField(chatrecords.FieldUserID, field.TypeUint64, value)
+		_node.UserID = value
+	}
+	if value, ok := crc.mutation.BotID(); ok {
+		_spec.SetField(chatrecords.FieldBotID, field.TypeUint64, value)
+		_node.BotID = value
+	}
+	if value, ok := crc.mutation.BotType(); ok {
+		_spec.SetField(chatrecords.FieldBotType, field.TypeUint8, value)
+		_node.BotType = value
+	}
+	return _node, _spec
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.ChatRecords.Create().
+//		SetCreatedAt(v).
+//		OnConflict(
+//			// Update the row with the new values
+//			// the was proposed for insertion.
+//			sql.ResolveWithNewValues(),
+//		).
+//		// Override some of the fields with custom
+//		// update values.
+//		Update(func(u *ent.ChatRecordsUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (crc *ChatRecordsCreate) OnConflict(opts ...sql.ConflictOption) *ChatRecordsUpsertOne {
+	crc.conflict = opts
+	return &ChatRecordsUpsertOne{
+		create: crc,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.ChatRecords.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (crc *ChatRecordsCreate) OnConflictColumns(columns ...string) *ChatRecordsUpsertOne {
+	crc.conflict = append(crc.conflict, sql.ConflictColumns(columns...))
+	return &ChatRecordsUpsertOne{
+		create: crc,
+	}
+}
+
+type (
+	// ChatRecordsUpsertOne is the builder for "upsert"-ing
+	//  one ChatRecords node.
+	ChatRecordsUpsertOne struct {
+		create *ChatRecordsCreate
+	}
+
+	// ChatRecordsUpsert is the "OnConflict" setter.
+	ChatRecordsUpsert struct {
+		*sql.UpdateSet
+	}
+)
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *ChatRecordsUpsert) SetUpdatedAt(v time.Time) *ChatRecordsUpsert {
+	u.Set(chatrecords.FieldUpdatedAt, v)
+	return u
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *ChatRecordsUpsert) UpdateUpdatedAt() *ChatRecordsUpsert {
+	u.SetExcluded(chatrecords.FieldUpdatedAt)
+	return u
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *ChatRecordsUpsert) SetDeletedAt(v time.Time) *ChatRecordsUpsert {
+	u.Set(chatrecords.FieldDeletedAt, v)
+	return u
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *ChatRecordsUpsert) UpdateDeletedAt() *ChatRecordsUpsert {
+	u.SetExcluded(chatrecords.FieldDeletedAt)
+	return u
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *ChatRecordsUpsert) ClearDeletedAt() *ChatRecordsUpsert {
+	u.SetNull(chatrecords.FieldDeletedAt)
+	return u
+}
+
+// SetContent sets the "content" field.
+func (u *ChatRecordsUpsert) SetContent(v string) *ChatRecordsUpsert {
+	u.Set(chatrecords.FieldContent, v)
+	return u
+}
+
+// UpdateContent sets the "content" field to the value that was provided on create.
+func (u *ChatRecordsUpsert) UpdateContent() *ChatRecordsUpsert {
+	u.SetExcluded(chatrecords.FieldContent)
+	return u
+}
+
+// SetContentType sets the "content_type" field.
+func (u *ChatRecordsUpsert) SetContentType(v uint8) *ChatRecordsUpsert {
+	u.Set(chatrecords.FieldContentType, v)
+	return u
+}
+
+// UpdateContentType sets the "content_type" field to the value that was provided on create.
+func (u *ChatRecordsUpsert) UpdateContentType() *ChatRecordsUpsert {
+	u.SetExcluded(chatrecords.FieldContentType)
+	return u
+}
+
+// AddContentType adds v to the "content_type" field.
+func (u *ChatRecordsUpsert) AddContentType(v uint8) *ChatRecordsUpsert {
+	u.Add(chatrecords.FieldContentType, v)
+	return u
+}
+
+// SetSessionID sets the "session_id" field.
+func (u *ChatRecordsUpsert) SetSessionID(v uint64) *ChatRecordsUpsert {
+	u.Set(chatrecords.FieldSessionID, v)
+	return u
+}
+
+// UpdateSessionID sets the "session_id" field to the value that was provided on create.
+func (u *ChatRecordsUpsert) UpdateSessionID() *ChatRecordsUpsert {
+	u.SetExcluded(chatrecords.FieldSessionID)
+	return u
+}
+
+// AddSessionID adds v to the "session_id" field.
+func (u *ChatRecordsUpsert) AddSessionID(v uint64) *ChatRecordsUpsert {
+	u.Add(chatrecords.FieldSessionID, v)
+	return u
+}
+
+// SetUserID sets the "user_id" field.
+func (u *ChatRecordsUpsert) SetUserID(v uint64) *ChatRecordsUpsert {
+	u.Set(chatrecords.FieldUserID, v)
+	return u
+}
+
+// UpdateUserID sets the "user_id" field to the value that was provided on create.
+func (u *ChatRecordsUpsert) UpdateUserID() *ChatRecordsUpsert {
+	u.SetExcluded(chatrecords.FieldUserID)
+	return u
+}
+
+// AddUserID adds v to the "user_id" field.
+func (u *ChatRecordsUpsert) AddUserID(v uint64) *ChatRecordsUpsert {
+	u.Add(chatrecords.FieldUserID, v)
+	return u
+}
+
+// SetBotID sets the "bot_id" field.
+func (u *ChatRecordsUpsert) SetBotID(v uint64) *ChatRecordsUpsert {
+	u.Set(chatrecords.FieldBotID, v)
+	return u
+}
+
+// UpdateBotID sets the "bot_id" field to the value that was provided on create.
+func (u *ChatRecordsUpsert) UpdateBotID() *ChatRecordsUpsert {
+	u.SetExcluded(chatrecords.FieldBotID)
+	return u
+}
+
+// AddBotID adds v to the "bot_id" field.
+func (u *ChatRecordsUpsert) AddBotID(v uint64) *ChatRecordsUpsert {
+	u.Add(chatrecords.FieldBotID, v)
+	return u
+}
+
+// SetBotType sets the "bot_type" field.
+func (u *ChatRecordsUpsert) SetBotType(v uint8) *ChatRecordsUpsert {
+	u.Set(chatrecords.FieldBotType, v)
+	return u
+}
+
+// UpdateBotType sets the "bot_type" field to the value that was provided on create.
+func (u *ChatRecordsUpsert) UpdateBotType() *ChatRecordsUpsert {
+	u.SetExcluded(chatrecords.FieldBotType)
+	return u
+}
+
+// AddBotType adds v to the "bot_type" field.
+func (u *ChatRecordsUpsert) AddBotType(v uint8) *ChatRecordsUpsert {
+	u.Add(chatrecords.FieldBotType, v)
+	return u
+}
+
+// UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field.
+// Using this option is equivalent to using:
+//
+//	client.ChatRecords.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(chatrecords.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *ChatRecordsUpsertOne) UpdateNewValues() *ChatRecordsUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
+		if _, exists := u.create.mutation.ID(); exists {
+			s.SetIgnore(chatrecords.FieldID)
+		}
+		if _, exists := u.create.mutation.CreatedAt(); exists {
+			s.SetIgnore(chatrecords.FieldCreatedAt)
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.ChatRecords.Create().
+//	    OnConflict(sql.ResolveWithIgnore()).
+//	    Exec(ctx)
+func (u *ChatRecordsUpsertOne) Ignore() *ChatRecordsUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
+	return u
+}
+
+// DoNothing configures the conflict_action to `DO NOTHING`.
+// Supported only by SQLite and PostgreSQL.
+func (u *ChatRecordsUpsertOne) DoNothing() *ChatRecordsUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the ChatRecordsCreate.OnConflict
+// documentation for more info.
+func (u *ChatRecordsUpsertOne) Update(set func(*ChatRecordsUpsert)) *ChatRecordsUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&ChatRecordsUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *ChatRecordsUpsertOne) SetUpdatedAt(v time.Time) *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *ChatRecordsUpsertOne) UpdateUpdatedAt() *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *ChatRecordsUpsertOne) SetDeletedAt(v time.Time) *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *ChatRecordsUpsertOne) UpdateDeletedAt() *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *ChatRecordsUpsertOne) ClearDeletedAt() *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetContent sets the "content" field.
+func (u *ChatRecordsUpsertOne) SetContent(v string) *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.SetContent(v)
+	})
+}
+
+// UpdateContent sets the "content" field to the value that was provided on create.
+func (u *ChatRecordsUpsertOne) UpdateContent() *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.UpdateContent()
+	})
+}
+
+// SetContentType sets the "content_type" field.
+func (u *ChatRecordsUpsertOne) SetContentType(v uint8) *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.SetContentType(v)
+	})
+}
+
+// AddContentType adds v to the "content_type" field.
+func (u *ChatRecordsUpsertOne) AddContentType(v uint8) *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.AddContentType(v)
+	})
+}
+
+// UpdateContentType sets the "content_type" field to the value that was provided on create.
+func (u *ChatRecordsUpsertOne) UpdateContentType() *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.UpdateContentType()
+	})
+}
+
+// SetSessionID sets the "session_id" field.
+func (u *ChatRecordsUpsertOne) SetSessionID(v uint64) *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.SetSessionID(v)
+	})
+}
+
+// AddSessionID adds v to the "session_id" field.
+func (u *ChatRecordsUpsertOne) AddSessionID(v uint64) *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.AddSessionID(v)
+	})
+}
+
+// UpdateSessionID sets the "session_id" field to the value that was provided on create.
+func (u *ChatRecordsUpsertOne) UpdateSessionID() *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.UpdateSessionID()
+	})
+}
+
+// SetUserID sets the "user_id" field.
+func (u *ChatRecordsUpsertOne) SetUserID(v uint64) *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.SetUserID(v)
+	})
+}
+
+// AddUserID adds v to the "user_id" field.
+func (u *ChatRecordsUpsertOne) AddUserID(v uint64) *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.AddUserID(v)
+	})
+}
+
+// UpdateUserID sets the "user_id" field to the value that was provided on create.
+func (u *ChatRecordsUpsertOne) UpdateUserID() *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.UpdateUserID()
+	})
+}
+
+// SetBotID sets the "bot_id" field.
+func (u *ChatRecordsUpsertOne) SetBotID(v uint64) *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.SetBotID(v)
+	})
+}
+
+// AddBotID adds v to the "bot_id" field.
+func (u *ChatRecordsUpsertOne) AddBotID(v uint64) *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.AddBotID(v)
+	})
+}
+
+// UpdateBotID sets the "bot_id" field to the value that was provided on create.
+func (u *ChatRecordsUpsertOne) UpdateBotID() *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.UpdateBotID()
+	})
+}
+
+// SetBotType sets the "bot_type" field.
+func (u *ChatRecordsUpsertOne) SetBotType(v uint8) *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.SetBotType(v)
+	})
+}
+
+// AddBotType adds v to the "bot_type" field.
+func (u *ChatRecordsUpsertOne) AddBotType(v uint8) *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.AddBotType(v)
+	})
+}
+
+// UpdateBotType sets the "bot_type" field to the value that was provided on create.
+func (u *ChatRecordsUpsertOne) UpdateBotType() *ChatRecordsUpsertOne {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.UpdateBotType()
+	})
+}
+
+// Exec executes the query.
+func (u *ChatRecordsUpsertOne) Exec(ctx context.Context) error {
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for ChatRecordsCreate.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *ChatRecordsUpsertOne) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// Exec executes the UPSERT query and returns the inserted/updated ID.
+func (u *ChatRecordsUpsertOne) ID(ctx context.Context) (id uint64, err error) {
+	node, err := u.create.Save(ctx)
+	if err != nil {
+		return id, err
+	}
+	return node.ID, nil
+}
+
+// IDX is like ID, but panics if an error occurs.
+func (u *ChatRecordsUpsertOne) IDX(ctx context.Context) uint64 {
+	id, err := u.ID(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+// ChatRecordsCreateBulk is the builder for creating many ChatRecords entities in bulk.
+type ChatRecordsCreateBulk struct {
+	config
+	err      error
+	builders []*ChatRecordsCreate
+	conflict []sql.ConflictOption
+}
+
+// Save creates the ChatRecords entities in the database.
+func (crcb *ChatRecordsCreateBulk) Save(ctx context.Context) ([]*ChatRecords, error) {
+	if crcb.err != nil {
+		return nil, crcb.err
+	}
+	specs := make([]*sqlgraph.CreateSpec, len(crcb.builders))
+	nodes := make([]*ChatRecords, len(crcb.builders))
+	mutators := make([]Mutator, len(crcb.builders))
+	for i := range crcb.builders {
+		func(i int, root context.Context) {
+			builder := crcb.builders[i]
+			builder.defaults()
+			var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
+				mutation, ok := m.(*ChatRecordsMutation)
+				if !ok {
+					return nil, fmt.Errorf("unexpected mutation type %T", m)
+				}
+				if err := builder.check(); err != nil {
+					return nil, err
+				}
+				builder.mutation = mutation
+				var err error
+				nodes[i], specs[i] = builder.createSpec()
+				if i < len(mutators)-1 {
+					_, err = mutators[i+1].Mutate(root, crcb.builders[i+1].mutation)
+				} else {
+					spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
+					spec.OnConflict = crcb.conflict
+					// Invoke the actual operation on the latest mutation in the chain.
+					if err = sqlgraph.BatchCreate(ctx, crcb.driver, spec); err != nil {
+						if sqlgraph.IsConstraintError(err) {
+							err = &ConstraintError{msg: err.Error(), wrap: err}
+						}
+					}
+				}
+				if err != nil {
+					return nil, err
+				}
+				mutation.id = &nodes[i].ID
+				if specs[i].ID.Value != nil && nodes[i].ID == 0 {
+					id := specs[i].ID.Value.(int64)
+					nodes[i].ID = uint64(id)
+				}
+				mutation.done = true
+				return nodes[i], nil
+			})
+			for i := len(builder.hooks) - 1; i >= 0; i-- {
+				mut = builder.hooks[i](mut)
+			}
+			mutators[i] = mut
+		}(i, ctx)
+	}
+	if len(mutators) > 0 {
+		if _, err := mutators[0].Mutate(ctx, crcb.builders[0].mutation); err != nil {
+			return nil, err
+		}
+	}
+	return nodes, nil
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (crcb *ChatRecordsCreateBulk) SaveX(ctx context.Context) []*ChatRecords {
+	v, err := crcb.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (crcb *ChatRecordsCreateBulk) Exec(ctx context.Context) error {
+	_, err := crcb.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (crcb *ChatRecordsCreateBulk) ExecX(ctx context.Context) {
+	if err := crcb.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.ChatRecords.CreateBulk(builders...).
+//		OnConflict(
+//			// Update the row with the new values
+//			// the was proposed for insertion.
+//			sql.ResolveWithNewValues(),
+//		).
+//		// Override some of the fields with custom
+//		// update values.
+//		Update(func(u *ent.ChatRecordsUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (crcb *ChatRecordsCreateBulk) OnConflict(opts ...sql.ConflictOption) *ChatRecordsUpsertBulk {
+	crcb.conflict = opts
+	return &ChatRecordsUpsertBulk{
+		create: crcb,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.ChatRecords.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (crcb *ChatRecordsCreateBulk) OnConflictColumns(columns ...string) *ChatRecordsUpsertBulk {
+	crcb.conflict = append(crcb.conflict, sql.ConflictColumns(columns...))
+	return &ChatRecordsUpsertBulk{
+		create: crcb,
+	}
+}
+
+// ChatRecordsUpsertBulk is the builder for "upsert"-ing
+// a bulk of ChatRecords nodes.
+type ChatRecordsUpsertBulk struct {
+	create *ChatRecordsCreateBulk
+}
+
+// UpdateNewValues updates the mutable fields using the new values that
+// were set on create. Using this option is equivalent to using:
+//
+//	client.ChatRecords.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(chatrecords.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *ChatRecordsUpsertBulk) UpdateNewValues() *ChatRecordsUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
+		for _, b := range u.create.builders {
+			if _, exists := b.mutation.ID(); exists {
+				s.SetIgnore(chatrecords.FieldID)
+			}
+			if _, exists := b.mutation.CreatedAt(); exists {
+				s.SetIgnore(chatrecords.FieldCreatedAt)
+			}
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.ChatRecords.Create().
+//		OnConflict(sql.ResolveWithIgnore()).
+//		Exec(ctx)
+func (u *ChatRecordsUpsertBulk) Ignore() *ChatRecordsUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
+	return u
+}
+
+// DoNothing configures the conflict_action to `DO NOTHING`.
+// Supported only by SQLite and PostgreSQL.
+func (u *ChatRecordsUpsertBulk) DoNothing() *ChatRecordsUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the ChatRecordsCreateBulk.OnConflict
+// documentation for more info.
+func (u *ChatRecordsUpsertBulk) Update(set func(*ChatRecordsUpsert)) *ChatRecordsUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&ChatRecordsUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *ChatRecordsUpsertBulk) SetUpdatedAt(v time.Time) *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *ChatRecordsUpsertBulk) UpdateUpdatedAt() *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *ChatRecordsUpsertBulk) SetDeletedAt(v time.Time) *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *ChatRecordsUpsertBulk) UpdateDeletedAt() *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *ChatRecordsUpsertBulk) ClearDeletedAt() *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetContent sets the "content" field.
+func (u *ChatRecordsUpsertBulk) SetContent(v string) *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.SetContent(v)
+	})
+}
+
+// UpdateContent sets the "content" field to the value that was provided on create.
+func (u *ChatRecordsUpsertBulk) UpdateContent() *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.UpdateContent()
+	})
+}
+
+// SetContentType sets the "content_type" field.
+func (u *ChatRecordsUpsertBulk) SetContentType(v uint8) *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.SetContentType(v)
+	})
+}
+
+// AddContentType adds v to the "content_type" field.
+func (u *ChatRecordsUpsertBulk) AddContentType(v uint8) *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.AddContentType(v)
+	})
+}
+
+// UpdateContentType sets the "content_type" field to the value that was provided on create.
+func (u *ChatRecordsUpsertBulk) UpdateContentType() *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.UpdateContentType()
+	})
+}
+
+// SetSessionID sets the "session_id" field.
+func (u *ChatRecordsUpsertBulk) SetSessionID(v uint64) *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.SetSessionID(v)
+	})
+}
+
+// AddSessionID adds v to the "session_id" field.
+func (u *ChatRecordsUpsertBulk) AddSessionID(v uint64) *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.AddSessionID(v)
+	})
+}
+
+// UpdateSessionID sets the "session_id" field to the value that was provided on create.
+func (u *ChatRecordsUpsertBulk) UpdateSessionID() *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.UpdateSessionID()
+	})
+}
+
+// SetUserID sets the "user_id" field.
+func (u *ChatRecordsUpsertBulk) SetUserID(v uint64) *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.SetUserID(v)
+	})
+}
+
+// AddUserID adds v to the "user_id" field.
+func (u *ChatRecordsUpsertBulk) AddUserID(v uint64) *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.AddUserID(v)
+	})
+}
+
+// UpdateUserID sets the "user_id" field to the value that was provided on create.
+func (u *ChatRecordsUpsertBulk) UpdateUserID() *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.UpdateUserID()
+	})
+}
+
+// SetBotID sets the "bot_id" field.
+func (u *ChatRecordsUpsertBulk) SetBotID(v uint64) *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.SetBotID(v)
+	})
+}
+
+// AddBotID adds v to the "bot_id" field.
+func (u *ChatRecordsUpsertBulk) AddBotID(v uint64) *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.AddBotID(v)
+	})
+}
+
+// UpdateBotID sets the "bot_id" field to the value that was provided on create.
+func (u *ChatRecordsUpsertBulk) UpdateBotID() *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.UpdateBotID()
+	})
+}
+
+// SetBotType sets the "bot_type" field.
+func (u *ChatRecordsUpsertBulk) SetBotType(v uint8) *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.SetBotType(v)
+	})
+}
+
+// AddBotType adds v to the "bot_type" field.
+func (u *ChatRecordsUpsertBulk) AddBotType(v uint8) *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.AddBotType(v)
+	})
+}
+
+// UpdateBotType sets the "bot_type" field to the value that was provided on create.
+func (u *ChatRecordsUpsertBulk) UpdateBotType() *ChatRecordsUpsertBulk {
+	return u.Update(func(s *ChatRecordsUpsert) {
+		s.UpdateBotType()
+	})
+}
+
+// Exec executes the query.
+func (u *ChatRecordsUpsertBulk) Exec(ctx context.Context) error {
+	if u.create.err != nil {
+		return u.create.err
+	}
+	for i, b := range u.create.builders {
+		if len(b.conflict) != 0 {
+			return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the ChatRecordsCreateBulk instead", i)
+		}
+	}
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for ChatRecordsCreateBulk.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *ChatRecordsUpsertBulk) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}

+ 88 - 0
ent/chatrecords_delete.go

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

+ 526 - 0
ent/chatrecords_query.go

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

+ 580 - 0
ent/chatrecords_update.go

@@ -0,0 +1,580 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/chatrecords"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// ChatRecordsUpdate is the builder for updating ChatRecords entities.
+type ChatRecordsUpdate struct {
+	config
+	hooks    []Hook
+	mutation *ChatRecordsMutation
+}
+
+// Where appends a list predicates to the ChatRecordsUpdate builder.
+func (cru *ChatRecordsUpdate) Where(ps ...predicate.ChatRecords) *ChatRecordsUpdate {
+	cru.mutation.Where(ps...)
+	return cru
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (cru *ChatRecordsUpdate) SetUpdatedAt(t time.Time) *ChatRecordsUpdate {
+	cru.mutation.SetUpdatedAt(t)
+	return cru
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (cru *ChatRecordsUpdate) SetDeletedAt(t time.Time) *ChatRecordsUpdate {
+	cru.mutation.SetDeletedAt(t)
+	return cru
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (cru *ChatRecordsUpdate) SetNillableDeletedAt(t *time.Time) *ChatRecordsUpdate {
+	if t != nil {
+		cru.SetDeletedAt(*t)
+	}
+	return cru
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (cru *ChatRecordsUpdate) ClearDeletedAt() *ChatRecordsUpdate {
+	cru.mutation.ClearDeletedAt()
+	return cru
+}
+
+// SetContent sets the "content" field.
+func (cru *ChatRecordsUpdate) SetContent(s string) *ChatRecordsUpdate {
+	cru.mutation.SetContent(s)
+	return cru
+}
+
+// SetNillableContent sets the "content" field if the given value is not nil.
+func (cru *ChatRecordsUpdate) SetNillableContent(s *string) *ChatRecordsUpdate {
+	if s != nil {
+		cru.SetContent(*s)
+	}
+	return cru
+}
+
+// SetContentType sets the "content_type" field.
+func (cru *ChatRecordsUpdate) SetContentType(u uint8) *ChatRecordsUpdate {
+	cru.mutation.ResetContentType()
+	cru.mutation.SetContentType(u)
+	return cru
+}
+
+// SetNillableContentType sets the "content_type" field if the given value is not nil.
+func (cru *ChatRecordsUpdate) SetNillableContentType(u *uint8) *ChatRecordsUpdate {
+	if u != nil {
+		cru.SetContentType(*u)
+	}
+	return cru
+}
+
+// AddContentType adds u to the "content_type" field.
+func (cru *ChatRecordsUpdate) AddContentType(u int8) *ChatRecordsUpdate {
+	cru.mutation.AddContentType(u)
+	return cru
+}
+
+// SetSessionID sets the "session_id" field.
+func (cru *ChatRecordsUpdate) SetSessionID(u uint64) *ChatRecordsUpdate {
+	cru.mutation.ResetSessionID()
+	cru.mutation.SetSessionID(u)
+	return cru
+}
+
+// SetNillableSessionID sets the "session_id" field if the given value is not nil.
+func (cru *ChatRecordsUpdate) SetNillableSessionID(u *uint64) *ChatRecordsUpdate {
+	if u != nil {
+		cru.SetSessionID(*u)
+	}
+	return cru
+}
+
+// AddSessionID adds u to the "session_id" field.
+func (cru *ChatRecordsUpdate) AddSessionID(u int64) *ChatRecordsUpdate {
+	cru.mutation.AddSessionID(u)
+	return cru
+}
+
+// SetUserID sets the "user_id" field.
+func (cru *ChatRecordsUpdate) SetUserID(u uint64) *ChatRecordsUpdate {
+	cru.mutation.ResetUserID()
+	cru.mutation.SetUserID(u)
+	return cru
+}
+
+// SetNillableUserID sets the "user_id" field if the given value is not nil.
+func (cru *ChatRecordsUpdate) SetNillableUserID(u *uint64) *ChatRecordsUpdate {
+	if u != nil {
+		cru.SetUserID(*u)
+	}
+	return cru
+}
+
+// AddUserID adds u to the "user_id" field.
+func (cru *ChatRecordsUpdate) AddUserID(u int64) *ChatRecordsUpdate {
+	cru.mutation.AddUserID(u)
+	return cru
+}
+
+// SetBotID sets the "bot_id" field.
+func (cru *ChatRecordsUpdate) SetBotID(u uint64) *ChatRecordsUpdate {
+	cru.mutation.ResetBotID()
+	cru.mutation.SetBotID(u)
+	return cru
+}
+
+// SetNillableBotID sets the "bot_id" field if the given value is not nil.
+func (cru *ChatRecordsUpdate) SetNillableBotID(u *uint64) *ChatRecordsUpdate {
+	if u != nil {
+		cru.SetBotID(*u)
+	}
+	return cru
+}
+
+// AddBotID adds u to the "bot_id" field.
+func (cru *ChatRecordsUpdate) AddBotID(u int64) *ChatRecordsUpdate {
+	cru.mutation.AddBotID(u)
+	return cru
+}
+
+// SetBotType sets the "bot_type" field.
+func (cru *ChatRecordsUpdate) SetBotType(u uint8) *ChatRecordsUpdate {
+	cru.mutation.ResetBotType()
+	cru.mutation.SetBotType(u)
+	return cru
+}
+
+// SetNillableBotType sets the "bot_type" field if the given value is not nil.
+func (cru *ChatRecordsUpdate) SetNillableBotType(u *uint8) *ChatRecordsUpdate {
+	if u != nil {
+		cru.SetBotType(*u)
+	}
+	return cru
+}
+
+// AddBotType adds u to the "bot_type" field.
+func (cru *ChatRecordsUpdate) AddBotType(u int8) *ChatRecordsUpdate {
+	cru.mutation.AddBotType(u)
+	return cru
+}
+
+// Mutation returns the ChatRecordsMutation object of the builder.
+func (cru *ChatRecordsUpdate) Mutation() *ChatRecordsMutation {
+	return cru.mutation
+}
+
+// Save executes the query and returns the number of nodes affected by the update operation.
+func (cru *ChatRecordsUpdate) Save(ctx context.Context) (int, error) {
+	if err := cru.defaults(); err != nil {
+		return 0, err
+	}
+	return withHooks(ctx, cru.sqlSave, cru.mutation, cru.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (cru *ChatRecordsUpdate) SaveX(ctx context.Context) int {
+	affected, err := cru.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return affected
+}
+
+// Exec executes the query.
+func (cru *ChatRecordsUpdate) Exec(ctx context.Context) error {
+	_, err := cru.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (cru *ChatRecordsUpdate) ExecX(ctx context.Context) {
+	if err := cru.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (cru *ChatRecordsUpdate) defaults() error {
+	if _, ok := cru.mutation.UpdatedAt(); !ok {
+		if chatrecords.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized chatrecords.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := chatrecords.UpdateDefaultUpdatedAt()
+		cru.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+func (cru *ChatRecordsUpdate) sqlSave(ctx context.Context) (n int, err error) {
+	_spec := sqlgraph.NewUpdateSpec(chatrecords.Table, chatrecords.Columns, sqlgraph.NewFieldSpec(chatrecords.FieldID, field.TypeUint64))
+	if ps := cru.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := cru.mutation.UpdatedAt(); ok {
+		_spec.SetField(chatrecords.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := cru.mutation.DeletedAt(); ok {
+		_spec.SetField(chatrecords.FieldDeletedAt, field.TypeTime, value)
+	}
+	if cru.mutation.DeletedAtCleared() {
+		_spec.ClearField(chatrecords.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := cru.mutation.Content(); ok {
+		_spec.SetField(chatrecords.FieldContent, field.TypeString, value)
+	}
+	if value, ok := cru.mutation.ContentType(); ok {
+		_spec.SetField(chatrecords.FieldContentType, field.TypeUint8, value)
+	}
+	if value, ok := cru.mutation.AddedContentType(); ok {
+		_spec.AddField(chatrecords.FieldContentType, field.TypeUint8, value)
+	}
+	if value, ok := cru.mutation.SessionID(); ok {
+		_spec.SetField(chatrecords.FieldSessionID, field.TypeUint64, value)
+	}
+	if value, ok := cru.mutation.AddedSessionID(); ok {
+		_spec.AddField(chatrecords.FieldSessionID, field.TypeUint64, value)
+	}
+	if value, ok := cru.mutation.UserID(); ok {
+		_spec.SetField(chatrecords.FieldUserID, field.TypeUint64, value)
+	}
+	if value, ok := cru.mutation.AddedUserID(); ok {
+		_spec.AddField(chatrecords.FieldUserID, field.TypeUint64, value)
+	}
+	if value, ok := cru.mutation.BotID(); ok {
+		_spec.SetField(chatrecords.FieldBotID, field.TypeUint64, value)
+	}
+	if value, ok := cru.mutation.AddedBotID(); ok {
+		_spec.AddField(chatrecords.FieldBotID, field.TypeUint64, value)
+	}
+	if value, ok := cru.mutation.BotType(); ok {
+		_spec.SetField(chatrecords.FieldBotType, field.TypeUint8, value)
+	}
+	if value, ok := cru.mutation.AddedBotType(); ok {
+		_spec.AddField(chatrecords.FieldBotType, field.TypeUint8, value)
+	}
+	if n, err = sqlgraph.UpdateNodes(ctx, cru.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{chatrecords.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return 0, err
+	}
+	cru.mutation.done = true
+	return n, nil
+}
+
+// ChatRecordsUpdateOne is the builder for updating a single ChatRecords entity.
+type ChatRecordsUpdateOne struct {
+	config
+	fields   []string
+	hooks    []Hook
+	mutation *ChatRecordsMutation
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (cruo *ChatRecordsUpdateOne) SetUpdatedAt(t time.Time) *ChatRecordsUpdateOne {
+	cruo.mutation.SetUpdatedAt(t)
+	return cruo
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (cruo *ChatRecordsUpdateOne) SetDeletedAt(t time.Time) *ChatRecordsUpdateOne {
+	cruo.mutation.SetDeletedAt(t)
+	return cruo
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (cruo *ChatRecordsUpdateOne) SetNillableDeletedAt(t *time.Time) *ChatRecordsUpdateOne {
+	if t != nil {
+		cruo.SetDeletedAt(*t)
+	}
+	return cruo
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (cruo *ChatRecordsUpdateOne) ClearDeletedAt() *ChatRecordsUpdateOne {
+	cruo.mutation.ClearDeletedAt()
+	return cruo
+}
+
+// SetContent sets the "content" field.
+func (cruo *ChatRecordsUpdateOne) SetContent(s string) *ChatRecordsUpdateOne {
+	cruo.mutation.SetContent(s)
+	return cruo
+}
+
+// SetNillableContent sets the "content" field if the given value is not nil.
+func (cruo *ChatRecordsUpdateOne) SetNillableContent(s *string) *ChatRecordsUpdateOne {
+	if s != nil {
+		cruo.SetContent(*s)
+	}
+	return cruo
+}
+
+// SetContentType sets the "content_type" field.
+func (cruo *ChatRecordsUpdateOne) SetContentType(u uint8) *ChatRecordsUpdateOne {
+	cruo.mutation.ResetContentType()
+	cruo.mutation.SetContentType(u)
+	return cruo
+}
+
+// SetNillableContentType sets the "content_type" field if the given value is not nil.
+func (cruo *ChatRecordsUpdateOne) SetNillableContentType(u *uint8) *ChatRecordsUpdateOne {
+	if u != nil {
+		cruo.SetContentType(*u)
+	}
+	return cruo
+}
+
+// AddContentType adds u to the "content_type" field.
+func (cruo *ChatRecordsUpdateOne) AddContentType(u int8) *ChatRecordsUpdateOne {
+	cruo.mutation.AddContentType(u)
+	return cruo
+}
+
+// SetSessionID sets the "session_id" field.
+func (cruo *ChatRecordsUpdateOne) SetSessionID(u uint64) *ChatRecordsUpdateOne {
+	cruo.mutation.ResetSessionID()
+	cruo.mutation.SetSessionID(u)
+	return cruo
+}
+
+// SetNillableSessionID sets the "session_id" field if the given value is not nil.
+func (cruo *ChatRecordsUpdateOne) SetNillableSessionID(u *uint64) *ChatRecordsUpdateOne {
+	if u != nil {
+		cruo.SetSessionID(*u)
+	}
+	return cruo
+}
+
+// AddSessionID adds u to the "session_id" field.
+func (cruo *ChatRecordsUpdateOne) AddSessionID(u int64) *ChatRecordsUpdateOne {
+	cruo.mutation.AddSessionID(u)
+	return cruo
+}
+
+// SetUserID sets the "user_id" field.
+func (cruo *ChatRecordsUpdateOne) SetUserID(u uint64) *ChatRecordsUpdateOne {
+	cruo.mutation.ResetUserID()
+	cruo.mutation.SetUserID(u)
+	return cruo
+}
+
+// SetNillableUserID sets the "user_id" field if the given value is not nil.
+func (cruo *ChatRecordsUpdateOne) SetNillableUserID(u *uint64) *ChatRecordsUpdateOne {
+	if u != nil {
+		cruo.SetUserID(*u)
+	}
+	return cruo
+}
+
+// AddUserID adds u to the "user_id" field.
+func (cruo *ChatRecordsUpdateOne) AddUserID(u int64) *ChatRecordsUpdateOne {
+	cruo.mutation.AddUserID(u)
+	return cruo
+}
+
+// SetBotID sets the "bot_id" field.
+func (cruo *ChatRecordsUpdateOne) SetBotID(u uint64) *ChatRecordsUpdateOne {
+	cruo.mutation.ResetBotID()
+	cruo.mutation.SetBotID(u)
+	return cruo
+}
+
+// SetNillableBotID sets the "bot_id" field if the given value is not nil.
+func (cruo *ChatRecordsUpdateOne) SetNillableBotID(u *uint64) *ChatRecordsUpdateOne {
+	if u != nil {
+		cruo.SetBotID(*u)
+	}
+	return cruo
+}
+
+// AddBotID adds u to the "bot_id" field.
+func (cruo *ChatRecordsUpdateOne) AddBotID(u int64) *ChatRecordsUpdateOne {
+	cruo.mutation.AddBotID(u)
+	return cruo
+}
+
+// SetBotType sets the "bot_type" field.
+func (cruo *ChatRecordsUpdateOne) SetBotType(u uint8) *ChatRecordsUpdateOne {
+	cruo.mutation.ResetBotType()
+	cruo.mutation.SetBotType(u)
+	return cruo
+}
+
+// SetNillableBotType sets the "bot_type" field if the given value is not nil.
+func (cruo *ChatRecordsUpdateOne) SetNillableBotType(u *uint8) *ChatRecordsUpdateOne {
+	if u != nil {
+		cruo.SetBotType(*u)
+	}
+	return cruo
+}
+
+// AddBotType adds u to the "bot_type" field.
+func (cruo *ChatRecordsUpdateOne) AddBotType(u int8) *ChatRecordsUpdateOne {
+	cruo.mutation.AddBotType(u)
+	return cruo
+}
+
+// Mutation returns the ChatRecordsMutation object of the builder.
+func (cruo *ChatRecordsUpdateOne) Mutation() *ChatRecordsMutation {
+	return cruo.mutation
+}
+
+// Where appends a list predicates to the ChatRecordsUpdate builder.
+func (cruo *ChatRecordsUpdateOne) Where(ps ...predicate.ChatRecords) *ChatRecordsUpdateOne {
+	cruo.mutation.Where(ps...)
+	return cruo
+}
+
+// Select allows selecting one or more fields (columns) of the returned entity.
+// The default is selecting all fields defined in the entity schema.
+func (cruo *ChatRecordsUpdateOne) Select(field string, fields ...string) *ChatRecordsUpdateOne {
+	cruo.fields = append([]string{field}, fields...)
+	return cruo
+}
+
+// Save executes the query and returns the updated ChatRecords entity.
+func (cruo *ChatRecordsUpdateOne) Save(ctx context.Context) (*ChatRecords, error) {
+	if err := cruo.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, cruo.sqlSave, cruo.mutation, cruo.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (cruo *ChatRecordsUpdateOne) SaveX(ctx context.Context) *ChatRecords {
+	node, err := cruo.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return node
+}
+
+// Exec executes the query on the entity.
+func (cruo *ChatRecordsUpdateOne) Exec(ctx context.Context) error {
+	_, err := cruo.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (cruo *ChatRecordsUpdateOne) ExecX(ctx context.Context) {
+	if err := cruo.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (cruo *ChatRecordsUpdateOne) defaults() error {
+	if _, ok := cruo.mutation.UpdatedAt(); !ok {
+		if chatrecords.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized chatrecords.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := chatrecords.UpdateDefaultUpdatedAt()
+		cruo.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+func (cruo *ChatRecordsUpdateOne) sqlSave(ctx context.Context) (_node *ChatRecords, err error) {
+	_spec := sqlgraph.NewUpdateSpec(chatrecords.Table, chatrecords.Columns, sqlgraph.NewFieldSpec(chatrecords.FieldID, field.TypeUint64))
+	id, ok := cruo.mutation.ID()
+	if !ok {
+		return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "ChatRecords.id" for update`)}
+	}
+	_spec.Node.ID.Value = id
+	if fields := cruo.fields; len(fields) > 0 {
+		_spec.Node.Columns = make([]string, 0, len(fields))
+		_spec.Node.Columns = append(_spec.Node.Columns, chatrecords.FieldID)
+		for _, f := range fields {
+			if !chatrecords.ValidColumn(f) {
+				return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+			}
+			if f != chatrecords.FieldID {
+				_spec.Node.Columns = append(_spec.Node.Columns, f)
+			}
+		}
+	}
+	if ps := cruo.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := cruo.mutation.UpdatedAt(); ok {
+		_spec.SetField(chatrecords.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := cruo.mutation.DeletedAt(); ok {
+		_spec.SetField(chatrecords.FieldDeletedAt, field.TypeTime, value)
+	}
+	if cruo.mutation.DeletedAtCleared() {
+		_spec.ClearField(chatrecords.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := cruo.mutation.Content(); ok {
+		_spec.SetField(chatrecords.FieldContent, field.TypeString, value)
+	}
+	if value, ok := cruo.mutation.ContentType(); ok {
+		_spec.SetField(chatrecords.FieldContentType, field.TypeUint8, value)
+	}
+	if value, ok := cruo.mutation.AddedContentType(); ok {
+		_spec.AddField(chatrecords.FieldContentType, field.TypeUint8, value)
+	}
+	if value, ok := cruo.mutation.SessionID(); ok {
+		_spec.SetField(chatrecords.FieldSessionID, field.TypeUint64, value)
+	}
+	if value, ok := cruo.mutation.AddedSessionID(); ok {
+		_spec.AddField(chatrecords.FieldSessionID, field.TypeUint64, value)
+	}
+	if value, ok := cruo.mutation.UserID(); ok {
+		_spec.SetField(chatrecords.FieldUserID, field.TypeUint64, value)
+	}
+	if value, ok := cruo.mutation.AddedUserID(); ok {
+		_spec.AddField(chatrecords.FieldUserID, field.TypeUint64, value)
+	}
+	if value, ok := cruo.mutation.BotID(); ok {
+		_spec.SetField(chatrecords.FieldBotID, field.TypeUint64, value)
+	}
+	if value, ok := cruo.mutation.AddedBotID(); ok {
+		_spec.AddField(chatrecords.FieldBotID, field.TypeUint64, value)
+	}
+	if value, ok := cruo.mutation.BotType(); ok {
+		_spec.SetField(chatrecords.FieldBotType, field.TypeUint8, value)
+	}
+	if value, ok := cruo.mutation.AddedBotType(); ok {
+		_spec.AddField(chatrecords.FieldBotType, field.TypeUint8, value)
+	}
+	_node = &ChatRecords{config: cruo.config}
+	_spec.Assign = _node.assignValues
+	_spec.ScanValues = _node.scanValues
+	if err = sqlgraph.UpdateNode(ctx, cruo.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{chatrecords.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	cruo.mutation.done = true
+	return _node, nil
+}

+ 172 - 0
ent/chatsession.go

@@ -0,0 +1,172 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"fmt"
+	"strings"
+	"time"
+	"wechat-api/ent/chatsession"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+)
+
+// ChatSession is the model entity for the ChatSession schema.
+type ChatSession struct {
+	config `json:"-"`
+	// ID of the ent.
+	ID uint64 `json:"id,omitempty"`
+	// Create Time | 创建日期
+	CreatedAt time.Time `json:"created_at,omitempty"`
+	// Update Time | 修改日期
+	UpdatedAt time.Time `json:"updated_at,omitempty"`
+	// Delete Time | 删除日期
+	DeletedAt time.Time `json:"deleted_at,omitempty"`
+	// 名称
+	Name string `json:"name,omitempty"`
+	// 用户ID
+	UserID uint64 `json:"user_id,omitempty"`
+	// 聊天ID
+	BotID uint64 `json:"bot_id,omitempty"`
+	// 类型:1-微信 2-小程序card 3-智能体
+	BotType      uint8 `json:"bot_type,omitempty"`
+	selectValues sql.SelectValues
+}
+
+// scanValues returns the types for scanning values from sql.Rows.
+func (*ChatSession) scanValues(columns []string) ([]any, error) {
+	values := make([]any, len(columns))
+	for i := range columns {
+		switch columns[i] {
+		case chatsession.FieldID, chatsession.FieldUserID, chatsession.FieldBotID, chatsession.FieldBotType:
+			values[i] = new(sql.NullInt64)
+		case chatsession.FieldName:
+			values[i] = new(sql.NullString)
+		case chatsession.FieldCreatedAt, chatsession.FieldUpdatedAt, chatsession.FieldDeletedAt:
+			values[i] = new(sql.NullTime)
+		default:
+			values[i] = new(sql.UnknownType)
+		}
+	}
+	return values, nil
+}
+
+// assignValues assigns the values that were returned from sql.Rows (after scanning)
+// to the ChatSession fields.
+func (cs *ChatSession) assignValues(columns []string, values []any) error {
+	if m, n := len(values), len(columns); m < n {
+		return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
+	}
+	for i := range columns {
+		switch columns[i] {
+		case chatsession.FieldID:
+			value, ok := values[i].(*sql.NullInt64)
+			if !ok {
+				return fmt.Errorf("unexpected type %T for field id", value)
+			}
+			cs.ID = uint64(value.Int64)
+		case chatsession.FieldCreatedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field created_at", values[i])
+			} else if value.Valid {
+				cs.CreatedAt = value.Time
+			}
+		case chatsession.FieldUpdatedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field updated_at", values[i])
+			} else if value.Valid {
+				cs.UpdatedAt = value.Time
+			}
+		case chatsession.FieldDeletedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field deleted_at", values[i])
+			} else if value.Valid {
+				cs.DeletedAt = value.Time
+			}
+		case chatsession.FieldName:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field name", values[i])
+			} else if value.Valid {
+				cs.Name = value.String
+			}
+		case chatsession.FieldUserID:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field user_id", values[i])
+			} else if value.Valid {
+				cs.UserID = uint64(value.Int64)
+			}
+		case chatsession.FieldBotID:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field bot_id", values[i])
+			} else if value.Valid {
+				cs.BotID = uint64(value.Int64)
+			}
+		case chatsession.FieldBotType:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field bot_type", values[i])
+			} else if value.Valid {
+				cs.BotType = uint8(value.Int64)
+			}
+		default:
+			cs.selectValues.Set(columns[i], values[i])
+		}
+	}
+	return nil
+}
+
+// Value returns the ent.Value that was dynamically selected and assigned to the ChatSession.
+// This includes values selected through modifiers, order, etc.
+func (cs *ChatSession) Value(name string) (ent.Value, error) {
+	return cs.selectValues.Get(name)
+}
+
+// Update returns a builder for updating this ChatSession.
+// Note that you need to call ChatSession.Unwrap() before calling this method if this ChatSession
+// was returned from a transaction, and the transaction was committed or rolled back.
+func (cs *ChatSession) Update() *ChatSessionUpdateOne {
+	return NewChatSessionClient(cs.config).UpdateOne(cs)
+}
+
+// Unwrap unwraps the ChatSession entity that was returned from a transaction after it was closed,
+// so that all future queries will be executed through the driver which created the transaction.
+func (cs *ChatSession) Unwrap() *ChatSession {
+	_tx, ok := cs.config.driver.(*txDriver)
+	if !ok {
+		panic("ent: ChatSession is not a transactional entity")
+	}
+	cs.config.driver = _tx.drv
+	return cs
+}
+
+// String implements the fmt.Stringer.
+func (cs *ChatSession) String() string {
+	var builder strings.Builder
+	builder.WriteString("ChatSession(")
+	builder.WriteString(fmt.Sprintf("id=%v, ", cs.ID))
+	builder.WriteString("created_at=")
+	builder.WriteString(cs.CreatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("updated_at=")
+	builder.WriteString(cs.UpdatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("deleted_at=")
+	builder.WriteString(cs.DeletedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("name=")
+	builder.WriteString(cs.Name)
+	builder.WriteString(", ")
+	builder.WriteString("user_id=")
+	builder.WriteString(fmt.Sprintf("%v", cs.UserID))
+	builder.WriteString(", ")
+	builder.WriteString("bot_id=")
+	builder.WriteString(fmt.Sprintf("%v", cs.BotID))
+	builder.WriteString(", ")
+	builder.WriteString("bot_type=")
+	builder.WriteString(fmt.Sprintf("%v", cs.BotType))
+	builder.WriteByte(')')
+	return builder.String()
+}
+
+// ChatSessions is a parsable slice of ChatSession.
+type ChatSessions []*ChatSession

+ 122 - 0
ent/chatsession/chatsession.go

@@ -0,0 +1,122 @@
+// Code generated by ent, DO NOT EDIT.
+
+package chatsession
+
+import (
+	"time"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+)
+
+const (
+	// Label holds the string label denoting the chatsession type in the database.
+	Label = "chat_session"
+	// FieldID holds the string denoting the id field in the database.
+	FieldID = "id"
+	// FieldCreatedAt holds the string denoting the created_at field in the database.
+	FieldCreatedAt = "created_at"
+	// FieldUpdatedAt holds the string denoting the updated_at field in the database.
+	FieldUpdatedAt = "updated_at"
+	// FieldDeletedAt holds the string denoting the deleted_at field in the database.
+	FieldDeletedAt = "deleted_at"
+	// FieldName holds the string denoting the name field in the database.
+	FieldName = "name"
+	// FieldUserID holds the string denoting the user_id field in the database.
+	FieldUserID = "user_id"
+	// FieldBotID holds the string denoting the bot_id field in the database.
+	FieldBotID = "bot_id"
+	// FieldBotType holds the string denoting the bot_type field in the database.
+	FieldBotType = "bot_type"
+	// Table holds the table name of the chatsession in the database.
+	Table = "chat_session"
+)
+
+// Columns holds all SQL columns for chatsession fields.
+var Columns = []string{
+	FieldID,
+	FieldCreatedAt,
+	FieldUpdatedAt,
+	FieldDeletedAt,
+	FieldName,
+	FieldUserID,
+	FieldBotID,
+	FieldBotType,
+}
+
+// ValidColumn reports if the column name is valid (part of the table columns).
+func ValidColumn(column string) bool {
+	for i := range Columns {
+		if column == Columns[i] {
+			return true
+		}
+	}
+	return false
+}
+
+// Note that the variables below are initialized by the runtime
+// package on the initialization of the application. Therefore,
+// it should be imported in the main as follows:
+//
+//	import _ "wechat-api/ent/runtime"
+var (
+	Hooks        [1]ent.Hook
+	Interceptors [1]ent.Interceptor
+	// DefaultCreatedAt holds the default value on creation for the "created_at" field.
+	DefaultCreatedAt func() time.Time
+	// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
+	DefaultUpdatedAt func() time.Time
+	// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
+	UpdateDefaultUpdatedAt func() time.Time
+	// DefaultName holds the default value on creation for the "name" field.
+	DefaultName string
+	// DefaultUserID holds the default value on creation for the "user_id" field.
+	DefaultUserID uint64
+	// DefaultBotID holds the default value on creation for the "bot_id" field.
+	DefaultBotID uint64
+	// DefaultBotType holds the default value on creation for the "bot_type" field.
+	DefaultBotType uint8
+)
+
+// OrderOption defines the ordering options for the ChatSession queries.
+type OrderOption func(*sql.Selector)
+
+// ByID orders the results by the id field.
+func ByID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldID, opts...).ToFunc()
+}
+
+// ByCreatedAt orders the results by the created_at field.
+func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
+}
+
+// ByUpdatedAt orders the results by the updated_at field.
+func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
+}
+
+// ByDeletedAt orders the results by the deleted_at field.
+func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldDeletedAt, opts...).ToFunc()
+}
+
+// ByName orders the results by the name field.
+func ByName(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldName, opts...).ToFunc()
+}
+
+// ByUserID orders the results by the user_id field.
+func ByUserID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldUserID, opts...).ToFunc()
+}
+
+// ByBotID orders the results by the bot_id field.
+func ByBotID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldBotID, opts...).ToFunc()
+}
+
+// ByBotType orders the results by the bot_type field.
+func ByBotType(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldBotType, opts...).ToFunc()
+}

+ 420 - 0
ent/chatsession/where.go

@@ -0,0 +1,420 @@
+// Code generated by ent, DO NOT EDIT.
+
+package chatsession
+
+import (
+	"time"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+)
+
+// ID filters vertices based on their ID field.
+func ID(id uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldEQ(FieldID, id))
+}
+
+// IDEQ applies the EQ predicate on the ID field.
+func IDEQ(id uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldEQ(FieldID, id))
+}
+
+// IDNEQ applies the NEQ predicate on the ID field.
+func IDNEQ(id uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldNEQ(FieldID, id))
+}
+
+// IDIn applies the In predicate on the ID field.
+func IDIn(ids ...uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldIn(FieldID, ids...))
+}
+
+// IDNotIn applies the NotIn predicate on the ID field.
+func IDNotIn(ids ...uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldNotIn(FieldID, ids...))
+}
+
+// IDGT applies the GT predicate on the ID field.
+func IDGT(id uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldGT(FieldID, id))
+}
+
+// IDGTE applies the GTE predicate on the ID field.
+func IDGTE(id uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldGTE(FieldID, id))
+}
+
+// IDLT applies the LT predicate on the ID field.
+func IDLT(id uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldLT(FieldID, id))
+}
+
+// IDLTE applies the LTE predicate on the ID field.
+func IDLTE(id uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldLTE(FieldID, id))
+}
+
+// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
+func CreatedAt(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
+func UpdatedAt(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ.
+func DeletedAt(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
+func Name(v string) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldEQ(FieldName, v))
+}
+
+// UserID applies equality check predicate on the "user_id" field. It's identical to UserIDEQ.
+func UserID(v uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldEQ(FieldUserID, v))
+}
+
+// BotID applies equality check predicate on the "bot_id" field. It's identical to BotIDEQ.
+func BotID(v uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldEQ(FieldBotID, v))
+}
+
+// BotType applies equality check predicate on the "bot_type" field. It's identical to BotTypeEQ.
+func BotType(v uint8) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldEQ(FieldBotType, v))
+}
+
+// CreatedAtEQ applies the EQ predicate on the "created_at" field.
+func CreatedAtEQ(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
+func CreatedAtNEQ(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldNEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtIn applies the In predicate on the "created_at" field.
+func CreatedAtIn(vs ...time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
+func CreatedAtNotIn(vs ...time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldNotIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtGT applies the GT predicate on the "created_at" field.
+func CreatedAtGT(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldGT(FieldCreatedAt, v))
+}
+
+// CreatedAtGTE applies the GTE predicate on the "created_at" field.
+func CreatedAtGTE(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldGTE(FieldCreatedAt, v))
+}
+
+// CreatedAtLT applies the LT predicate on the "created_at" field.
+func CreatedAtLT(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldLT(FieldCreatedAt, v))
+}
+
+// CreatedAtLTE applies the LTE predicate on the "created_at" field.
+func CreatedAtLTE(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldLTE(FieldCreatedAt, v))
+}
+
+// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
+func UpdatedAtEQ(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
+func UpdatedAtNEQ(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldNEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtIn applies the In predicate on the "updated_at" field.
+func UpdatedAtIn(vs ...time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
+func UpdatedAtNotIn(vs ...time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldNotIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtGT applies the GT predicate on the "updated_at" field.
+func UpdatedAtGT(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldGT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
+func UpdatedAtGTE(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldGTE(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLT applies the LT predicate on the "updated_at" field.
+func UpdatedAtLT(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldLT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
+func UpdatedAtLTE(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldLTE(FieldUpdatedAt, v))
+}
+
+// DeletedAtEQ applies the EQ predicate on the "deleted_at" field.
+func DeletedAtEQ(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field.
+func DeletedAtNEQ(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldNEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtIn applies the In predicate on the "deleted_at" field.
+func DeletedAtIn(vs ...time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field.
+func DeletedAtNotIn(vs ...time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldNotIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtGT applies the GT predicate on the "deleted_at" field.
+func DeletedAtGT(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldGT(FieldDeletedAt, v))
+}
+
+// DeletedAtGTE applies the GTE predicate on the "deleted_at" field.
+func DeletedAtGTE(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldGTE(FieldDeletedAt, v))
+}
+
+// DeletedAtLT applies the LT predicate on the "deleted_at" field.
+func DeletedAtLT(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldLT(FieldDeletedAt, v))
+}
+
+// DeletedAtLTE applies the LTE predicate on the "deleted_at" field.
+func DeletedAtLTE(v time.Time) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldLTE(FieldDeletedAt, v))
+}
+
+// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field.
+func DeletedAtIsNil() predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldIsNull(FieldDeletedAt))
+}
+
+// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field.
+func DeletedAtNotNil() predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldNotNull(FieldDeletedAt))
+}
+
+// NameEQ applies the EQ predicate on the "name" field.
+func NameEQ(v string) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldEQ(FieldName, v))
+}
+
+// NameNEQ applies the NEQ predicate on the "name" field.
+func NameNEQ(v string) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldNEQ(FieldName, v))
+}
+
+// NameIn applies the In predicate on the "name" field.
+func NameIn(vs ...string) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldIn(FieldName, vs...))
+}
+
+// NameNotIn applies the NotIn predicate on the "name" field.
+func NameNotIn(vs ...string) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldNotIn(FieldName, vs...))
+}
+
+// NameGT applies the GT predicate on the "name" field.
+func NameGT(v string) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldGT(FieldName, v))
+}
+
+// NameGTE applies the GTE predicate on the "name" field.
+func NameGTE(v string) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldGTE(FieldName, v))
+}
+
+// NameLT applies the LT predicate on the "name" field.
+func NameLT(v string) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldLT(FieldName, v))
+}
+
+// NameLTE applies the LTE predicate on the "name" field.
+func NameLTE(v string) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldLTE(FieldName, v))
+}
+
+// NameContains applies the Contains predicate on the "name" field.
+func NameContains(v string) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldContains(FieldName, v))
+}
+
+// NameHasPrefix applies the HasPrefix predicate on the "name" field.
+func NameHasPrefix(v string) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldHasPrefix(FieldName, v))
+}
+
+// NameHasSuffix applies the HasSuffix predicate on the "name" field.
+func NameHasSuffix(v string) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldHasSuffix(FieldName, v))
+}
+
+// NameEqualFold applies the EqualFold predicate on the "name" field.
+func NameEqualFold(v string) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldEqualFold(FieldName, v))
+}
+
+// NameContainsFold applies the ContainsFold predicate on the "name" field.
+func NameContainsFold(v string) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldContainsFold(FieldName, v))
+}
+
+// UserIDEQ applies the EQ predicate on the "user_id" field.
+func UserIDEQ(v uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldEQ(FieldUserID, v))
+}
+
+// UserIDNEQ applies the NEQ predicate on the "user_id" field.
+func UserIDNEQ(v uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldNEQ(FieldUserID, v))
+}
+
+// UserIDIn applies the In predicate on the "user_id" field.
+func UserIDIn(vs ...uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldIn(FieldUserID, vs...))
+}
+
+// UserIDNotIn applies the NotIn predicate on the "user_id" field.
+func UserIDNotIn(vs ...uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldNotIn(FieldUserID, vs...))
+}
+
+// UserIDGT applies the GT predicate on the "user_id" field.
+func UserIDGT(v uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldGT(FieldUserID, v))
+}
+
+// UserIDGTE applies the GTE predicate on the "user_id" field.
+func UserIDGTE(v uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldGTE(FieldUserID, v))
+}
+
+// UserIDLT applies the LT predicate on the "user_id" field.
+func UserIDLT(v uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldLT(FieldUserID, v))
+}
+
+// UserIDLTE applies the LTE predicate on the "user_id" field.
+func UserIDLTE(v uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldLTE(FieldUserID, v))
+}
+
+// BotIDEQ applies the EQ predicate on the "bot_id" field.
+func BotIDEQ(v uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldEQ(FieldBotID, v))
+}
+
+// BotIDNEQ applies the NEQ predicate on the "bot_id" field.
+func BotIDNEQ(v uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldNEQ(FieldBotID, v))
+}
+
+// BotIDIn applies the In predicate on the "bot_id" field.
+func BotIDIn(vs ...uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldIn(FieldBotID, vs...))
+}
+
+// BotIDNotIn applies the NotIn predicate on the "bot_id" field.
+func BotIDNotIn(vs ...uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldNotIn(FieldBotID, vs...))
+}
+
+// BotIDGT applies the GT predicate on the "bot_id" field.
+func BotIDGT(v uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldGT(FieldBotID, v))
+}
+
+// BotIDGTE applies the GTE predicate on the "bot_id" field.
+func BotIDGTE(v uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldGTE(FieldBotID, v))
+}
+
+// BotIDLT applies the LT predicate on the "bot_id" field.
+func BotIDLT(v uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldLT(FieldBotID, v))
+}
+
+// BotIDLTE applies the LTE predicate on the "bot_id" field.
+func BotIDLTE(v uint64) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldLTE(FieldBotID, v))
+}
+
+// BotTypeEQ applies the EQ predicate on the "bot_type" field.
+func BotTypeEQ(v uint8) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldEQ(FieldBotType, v))
+}
+
+// BotTypeNEQ applies the NEQ predicate on the "bot_type" field.
+func BotTypeNEQ(v uint8) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldNEQ(FieldBotType, v))
+}
+
+// BotTypeIn applies the In predicate on the "bot_type" field.
+func BotTypeIn(vs ...uint8) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldIn(FieldBotType, vs...))
+}
+
+// BotTypeNotIn applies the NotIn predicate on the "bot_type" field.
+func BotTypeNotIn(vs ...uint8) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldNotIn(FieldBotType, vs...))
+}
+
+// BotTypeGT applies the GT predicate on the "bot_type" field.
+func BotTypeGT(v uint8) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldGT(FieldBotType, v))
+}
+
+// BotTypeGTE applies the GTE predicate on the "bot_type" field.
+func BotTypeGTE(v uint8) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldGTE(FieldBotType, v))
+}
+
+// BotTypeLT applies the LT predicate on the "bot_type" field.
+func BotTypeLT(v uint8) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldLT(FieldBotType, v))
+}
+
+// BotTypeLTE applies the LTE predicate on the "bot_type" field.
+func BotTypeLTE(v uint8) predicate.ChatSession {
+	return predicate.ChatSession(sql.FieldLTE(FieldBotType, v))
+}
+
+// And groups predicates with the AND operator between them.
+func And(predicates ...predicate.ChatSession) predicate.ChatSession {
+	return predicate.ChatSession(sql.AndPredicates(predicates...))
+}
+
+// Or groups predicates with the OR operator between them.
+func Or(predicates ...predicate.ChatSession) predicate.ChatSession {
+	return predicate.ChatSession(sql.OrPredicates(predicates...))
+}
+
+// Not applies the not operator on the given predicate.
+func Not(p predicate.ChatSession) predicate.ChatSession {
+	return predicate.ChatSession(sql.NotPredicates(p))
+}

+ 941 - 0
ent/chatsession_create.go

@@ -0,0 +1,941 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/chatsession"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// ChatSessionCreate is the builder for creating a ChatSession entity.
+type ChatSessionCreate struct {
+	config
+	mutation *ChatSessionMutation
+	hooks    []Hook
+	conflict []sql.ConflictOption
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (csc *ChatSessionCreate) SetCreatedAt(t time.Time) *ChatSessionCreate {
+	csc.mutation.SetCreatedAt(t)
+	return csc
+}
+
+// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
+func (csc *ChatSessionCreate) SetNillableCreatedAt(t *time.Time) *ChatSessionCreate {
+	if t != nil {
+		csc.SetCreatedAt(*t)
+	}
+	return csc
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (csc *ChatSessionCreate) SetUpdatedAt(t time.Time) *ChatSessionCreate {
+	csc.mutation.SetUpdatedAt(t)
+	return csc
+}
+
+// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
+func (csc *ChatSessionCreate) SetNillableUpdatedAt(t *time.Time) *ChatSessionCreate {
+	if t != nil {
+		csc.SetUpdatedAt(*t)
+	}
+	return csc
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (csc *ChatSessionCreate) SetDeletedAt(t time.Time) *ChatSessionCreate {
+	csc.mutation.SetDeletedAt(t)
+	return csc
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (csc *ChatSessionCreate) SetNillableDeletedAt(t *time.Time) *ChatSessionCreate {
+	if t != nil {
+		csc.SetDeletedAt(*t)
+	}
+	return csc
+}
+
+// SetName sets the "name" field.
+func (csc *ChatSessionCreate) SetName(s string) *ChatSessionCreate {
+	csc.mutation.SetName(s)
+	return csc
+}
+
+// SetNillableName sets the "name" field if the given value is not nil.
+func (csc *ChatSessionCreate) SetNillableName(s *string) *ChatSessionCreate {
+	if s != nil {
+		csc.SetName(*s)
+	}
+	return csc
+}
+
+// SetUserID sets the "user_id" field.
+func (csc *ChatSessionCreate) SetUserID(u uint64) *ChatSessionCreate {
+	csc.mutation.SetUserID(u)
+	return csc
+}
+
+// SetNillableUserID sets the "user_id" field if the given value is not nil.
+func (csc *ChatSessionCreate) SetNillableUserID(u *uint64) *ChatSessionCreate {
+	if u != nil {
+		csc.SetUserID(*u)
+	}
+	return csc
+}
+
+// SetBotID sets the "bot_id" field.
+func (csc *ChatSessionCreate) SetBotID(u uint64) *ChatSessionCreate {
+	csc.mutation.SetBotID(u)
+	return csc
+}
+
+// SetNillableBotID sets the "bot_id" field if the given value is not nil.
+func (csc *ChatSessionCreate) SetNillableBotID(u *uint64) *ChatSessionCreate {
+	if u != nil {
+		csc.SetBotID(*u)
+	}
+	return csc
+}
+
+// SetBotType sets the "bot_type" field.
+func (csc *ChatSessionCreate) SetBotType(u uint8) *ChatSessionCreate {
+	csc.mutation.SetBotType(u)
+	return csc
+}
+
+// SetNillableBotType sets the "bot_type" field if the given value is not nil.
+func (csc *ChatSessionCreate) SetNillableBotType(u *uint8) *ChatSessionCreate {
+	if u != nil {
+		csc.SetBotType(*u)
+	}
+	return csc
+}
+
+// SetID sets the "id" field.
+func (csc *ChatSessionCreate) SetID(u uint64) *ChatSessionCreate {
+	csc.mutation.SetID(u)
+	return csc
+}
+
+// Mutation returns the ChatSessionMutation object of the builder.
+func (csc *ChatSessionCreate) Mutation() *ChatSessionMutation {
+	return csc.mutation
+}
+
+// Save creates the ChatSession in the database.
+func (csc *ChatSessionCreate) Save(ctx context.Context) (*ChatSession, error) {
+	if err := csc.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, csc.sqlSave, csc.mutation, csc.hooks)
+}
+
+// SaveX calls Save and panics if Save returns an error.
+func (csc *ChatSessionCreate) SaveX(ctx context.Context) *ChatSession {
+	v, err := csc.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (csc *ChatSessionCreate) Exec(ctx context.Context) error {
+	_, err := csc.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (csc *ChatSessionCreate) ExecX(ctx context.Context) {
+	if err := csc.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (csc *ChatSessionCreate) defaults() error {
+	if _, ok := csc.mutation.CreatedAt(); !ok {
+		if chatsession.DefaultCreatedAt == nil {
+			return fmt.Errorf("ent: uninitialized chatsession.DefaultCreatedAt (forgotten import ent/runtime?)")
+		}
+		v := chatsession.DefaultCreatedAt()
+		csc.mutation.SetCreatedAt(v)
+	}
+	if _, ok := csc.mutation.UpdatedAt(); !ok {
+		if chatsession.DefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized chatsession.DefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := chatsession.DefaultUpdatedAt()
+		csc.mutation.SetUpdatedAt(v)
+	}
+	if _, ok := csc.mutation.Name(); !ok {
+		v := chatsession.DefaultName
+		csc.mutation.SetName(v)
+	}
+	if _, ok := csc.mutation.UserID(); !ok {
+		v := chatsession.DefaultUserID
+		csc.mutation.SetUserID(v)
+	}
+	if _, ok := csc.mutation.BotID(); !ok {
+		v := chatsession.DefaultBotID
+		csc.mutation.SetBotID(v)
+	}
+	if _, ok := csc.mutation.BotType(); !ok {
+		v := chatsession.DefaultBotType
+		csc.mutation.SetBotType(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (csc *ChatSessionCreate) check() error {
+	if _, ok := csc.mutation.CreatedAt(); !ok {
+		return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "ChatSession.created_at"`)}
+	}
+	if _, ok := csc.mutation.UpdatedAt(); !ok {
+		return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "ChatSession.updated_at"`)}
+	}
+	if _, ok := csc.mutation.Name(); !ok {
+		return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "ChatSession.name"`)}
+	}
+	if _, ok := csc.mutation.UserID(); !ok {
+		return &ValidationError{Name: "user_id", err: errors.New(`ent: missing required field "ChatSession.user_id"`)}
+	}
+	if _, ok := csc.mutation.BotID(); !ok {
+		return &ValidationError{Name: "bot_id", err: errors.New(`ent: missing required field "ChatSession.bot_id"`)}
+	}
+	if _, ok := csc.mutation.BotType(); !ok {
+		return &ValidationError{Name: "bot_type", err: errors.New(`ent: missing required field "ChatSession.bot_type"`)}
+	}
+	return nil
+}
+
+func (csc *ChatSessionCreate) sqlSave(ctx context.Context) (*ChatSession, error) {
+	if err := csc.check(); err != nil {
+		return nil, err
+	}
+	_node, _spec := csc.createSpec()
+	if err := sqlgraph.CreateNode(ctx, csc.driver, _spec); err != nil {
+		if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	if _spec.ID.Value != _node.ID {
+		id := _spec.ID.Value.(int64)
+		_node.ID = uint64(id)
+	}
+	csc.mutation.id = &_node.ID
+	csc.mutation.done = true
+	return _node, nil
+}
+
+func (csc *ChatSessionCreate) createSpec() (*ChatSession, *sqlgraph.CreateSpec) {
+	var (
+		_node = &ChatSession{config: csc.config}
+		_spec = sqlgraph.NewCreateSpec(chatsession.Table, sqlgraph.NewFieldSpec(chatsession.FieldID, field.TypeUint64))
+	)
+	_spec.OnConflict = csc.conflict
+	if id, ok := csc.mutation.ID(); ok {
+		_node.ID = id
+		_spec.ID.Value = id
+	}
+	if value, ok := csc.mutation.CreatedAt(); ok {
+		_spec.SetField(chatsession.FieldCreatedAt, field.TypeTime, value)
+		_node.CreatedAt = value
+	}
+	if value, ok := csc.mutation.UpdatedAt(); ok {
+		_spec.SetField(chatsession.FieldUpdatedAt, field.TypeTime, value)
+		_node.UpdatedAt = value
+	}
+	if value, ok := csc.mutation.DeletedAt(); ok {
+		_spec.SetField(chatsession.FieldDeletedAt, field.TypeTime, value)
+		_node.DeletedAt = value
+	}
+	if value, ok := csc.mutation.Name(); ok {
+		_spec.SetField(chatsession.FieldName, field.TypeString, value)
+		_node.Name = value
+	}
+	if value, ok := csc.mutation.UserID(); ok {
+		_spec.SetField(chatsession.FieldUserID, field.TypeUint64, value)
+		_node.UserID = value
+	}
+	if value, ok := csc.mutation.BotID(); ok {
+		_spec.SetField(chatsession.FieldBotID, field.TypeUint64, value)
+		_node.BotID = value
+	}
+	if value, ok := csc.mutation.BotType(); ok {
+		_spec.SetField(chatsession.FieldBotType, field.TypeUint8, value)
+		_node.BotType = value
+	}
+	return _node, _spec
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.ChatSession.Create().
+//		SetCreatedAt(v).
+//		OnConflict(
+//			// Update the row with the new values
+//			// the was proposed for insertion.
+//			sql.ResolveWithNewValues(),
+//		).
+//		// Override some of the fields with custom
+//		// update values.
+//		Update(func(u *ent.ChatSessionUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (csc *ChatSessionCreate) OnConflict(opts ...sql.ConflictOption) *ChatSessionUpsertOne {
+	csc.conflict = opts
+	return &ChatSessionUpsertOne{
+		create: csc,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.ChatSession.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (csc *ChatSessionCreate) OnConflictColumns(columns ...string) *ChatSessionUpsertOne {
+	csc.conflict = append(csc.conflict, sql.ConflictColumns(columns...))
+	return &ChatSessionUpsertOne{
+		create: csc,
+	}
+}
+
+type (
+	// ChatSessionUpsertOne is the builder for "upsert"-ing
+	//  one ChatSession node.
+	ChatSessionUpsertOne struct {
+		create *ChatSessionCreate
+	}
+
+	// ChatSessionUpsert is the "OnConflict" setter.
+	ChatSessionUpsert struct {
+		*sql.UpdateSet
+	}
+)
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *ChatSessionUpsert) SetUpdatedAt(v time.Time) *ChatSessionUpsert {
+	u.Set(chatsession.FieldUpdatedAt, v)
+	return u
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *ChatSessionUpsert) UpdateUpdatedAt() *ChatSessionUpsert {
+	u.SetExcluded(chatsession.FieldUpdatedAt)
+	return u
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *ChatSessionUpsert) SetDeletedAt(v time.Time) *ChatSessionUpsert {
+	u.Set(chatsession.FieldDeletedAt, v)
+	return u
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *ChatSessionUpsert) UpdateDeletedAt() *ChatSessionUpsert {
+	u.SetExcluded(chatsession.FieldDeletedAt)
+	return u
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *ChatSessionUpsert) ClearDeletedAt() *ChatSessionUpsert {
+	u.SetNull(chatsession.FieldDeletedAt)
+	return u
+}
+
+// SetName sets the "name" field.
+func (u *ChatSessionUpsert) SetName(v string) *ChatSessionUpsert {
+	u.Set(chatsession.FieldName, v)
+	return u
+}
+
+// UpdateName sets the "name" field to the value that was provided on create.
+func (u *ChatSessionUpsert) UpdateName() *ChatSessionUpsert {
+	u.SetExcluded(chatsession.FieldName)
+	return u
+}
+
+// SetUserID sets the "user_id" field.
+func (u *ChatSessionUpsert) SetUserID(v uint64) *ChatSessionUpsert {
+	u.Set(chatsession.FieldUserID, v)
+	return u
+}
+
+// UpdateUserID sets the "user_id" field to the value that was provided on create.
+func (u *ChatSessionUpsert) UpdateUserID() *ChatSessionUpsert {
+	u.SetExcluded(chatsession.FieldUserID)
+	return u
+}
+
+// AddUserID adds v to the "user_id" field.
+func (u *ChatSessionUpsert) AddUserID(v uint64) *ChatSessionUpsert {
+	u.Add(chatsession.FieldUserID, v)
+	return u
+}
+
+// SetBotID sets the "bot_id" field.
+func (u *ChatSessionUpsert) SetBotID(v uint64) *ChatSessionUpsert {
+	u.Set(chatsession.FieldBotID, v)
+	return u
+}
+
+// UpdateBotID sets the "bot_id" field to the value that was provided on create.
+func (u *ChatSessionUpsert) UpdateBotID() *ChatSessionUpsert {
+	u.SetExcluded(chatsession.FieldBotID)
+	return u
+}
+
+// AddBotID adds v to the "bot_id" field.
+func (u *ChatSessionUpsert) AddBotID(v uint64) *ChatSessionUpsert {
+	u.Add(chatsession.FieldBotID, v)
+	return u
+}
+
+// SetBotType sets the "bot_type" field.
+func (u *ChatSessionUpsert) SetBotType(v uint8) *ChatSessionUpsert {
+	u.Set(chatsession.FieldBotType, v)
+	return u
+}
+
+// UpdateBotType sets the "bot_type" field to the value that was provided on create.
+func (u *ChatSessionUpsert) UpdateBotType() *ChatSessionUpsert {
+	u.SetExcluded(chatsession.FieldBotType)
+	return u
+}
+
+// AddBotType adds v to the "bot_type" field.
+func (u *ChatSessionUpsert) AddBotType(v uint8) *ChatSessionUpsert {
+	u.Add(chatsession.FieldBotType, v)
+	return u
+}
+
+// UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field.
+// Using this option is equivalent to using:
+//
+//	client.ChatSession.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(chatsession.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *ChatSessionUpsertOne) UpdateNewValues() *ChatSessionUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
+		if _, exists := u.create.mutation.ID(); exists {
+			s.SetIgnore(chatsession.FieldID)
+		}
+		if _, exists := u.create.mutation.CreatedAt(); exists {
+			s.SetIgnore(chatsession.FieldCreatedAt)
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.ChatSession.Create().
+//	    OnConflict(sql.ResolveWithIgnore()).
+//	    Exec(ctx)
+func (u *ChatSessionUpsertOne) Ignore() *ChatSessionUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
+	return u
+}
+
+// DoNothing configures the conflict_action to `DO NOTHING`.
+// Supported only by SQLite and PostgreSQL.
+func (u *ChatSessionUpsertOne) DoNothing() *ChatSessionUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the ChatSessionCreate.OnConflict
+// documentation for more info.
+func (u *ChatSessionUpsertOne) Update(set func(*ChatSessionUpsert)) *ChatSessionUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&ChatSessionUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *ChatSessionUpsertOne) SetUpdatedAt(v time.Time) *ChatSessionUpsertOne {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *ChatSessionUpsertOne) UpdateUpdatedAt() *ChatSessionUpsertOne {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *ChatSessionUpsertOne) SetDeletedAt(v time.Time) *ChatSessionUpsertOne {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *ChatSessionUpsertOne) UpdateDeletedAt() *ChatSessionUpsertOne {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *ChatSessionUpsertOne) ClearDeletedAt() *ChatSessionUpsertOne {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetName sets the "name" field.
+func (u *ChatSessionUpsertOne) SetName(v string) *ChatSessionUpsertOne {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.SetName(v)
+	})
+}
+
+// UpdateName sets the "name" field to the value that was provided on create.
+func (u *ChatSessionUpsertOne) UpdateName() *ChatSessionUpsertOne {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.UpdateName()
+	})
+}
+
+// SetUserID sets the "user_id" field.
+func (u *ChatSessionUpsertOne) SetUserID(v uint64) *ChatSessionUpsertOne {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.SetUserID(v)
+	})
+}
+
+// AddUserID adds v to the "user_id" field.
+func (u *ChatSessionUpsertOne) AddUserID(v uint64) *ChatSessionUpsertOne {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.AddUserID(v)
+	})
+}
+
+// UpdateUserID sets the "user_id" field to the value that was provided on create.
+func (u *ChatSessionUpsertOne) UpdateUserID() *ChatSessionUpsertOne {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.UpdateUserID()
+	})
+}
+
+// SetBotID sets the "bot_id" field.
+func (u *ChatSessionUpsertOne) SetBotID(v uint64) *ChatSessionUpsertOne {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.SetBotID(v)
+	})
+}
+
+// AddBotID adds v to the "bot_id" field.
+func (u *ChatSessionUpsertOne) AddBotID(v uint64) *ChatSessionUpsertOne {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.AddBotID(v)
+	})
+}
+
+// UpdateBotID sets the "bot_id" field to the value that was provided on create.
+func (u *ChatSessionUpsertOne) UpdateBotID() *ChatSessionUpsertOne {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.UpdateBotID()
+	})
+}
+
+// SetBotType sets the "bot_type" field.
+func (u *ChatSessionUpsertOne) SetBotType(v uint8) *ChatSessionUpsertOne {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.SetBotType(v)
+	})
+}
+
+// AddBotType adds v to the "bot_type" field.
+func (u *ChatSessionUpsertOne) AddBotType(v uint8) *ChatSessionUpsertOne {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.AddBotType(v)
+	})
+}
+
+// UpdateBotType sets the "bot_type" field to the value that was provided on create.
+func (u *ChatSessionUpsertOne) UpdateBotType() *ChatSessionUpsertOne {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.UpdateBotType()
+	})
+}
+
+// Exec executes the query.
+func (u *ChatSessionUpsertOne) Exec(ctx context.Context) error {
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for ChatSessionCreate.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *ChatSessionUpsertOne) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// Exec executes the UPSERT query and returns the inserted/updated ID.
+func (u *ChatSessionUpsertOne) ID(ctx context.Context) (id uint64, err error) {
+	node, err := u.create.Save(ctx)
+	if err != nil {
+		return id, err
+	}
+	return node.ID, nil
+}
+
+// IDX is like ID, but panics if an error occurs.
+func (u *ChatSessionUpsertOne) IDX(ctx context.Context) uint64 {
+	id, err := u.ID(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+// ChatSessionCreateBulk is the builder for creating many ChatSession entities in bulk.
+type ChatSessionCreateBulk struct {
+	config
+	err      error
+	builders []*ChatSessionCreate
+	conflict []sql.ConflictOption
+}
+
+// Save creates the ChatSession entities in the database.
+func (cscb *ChatSessionCreateBulk) Save(ctx context.Context) ([]*ChatSession, error) {
+	if cscb.err != nil {
+		return nil, cscb.err
+	}
+	specs := make([]*sqlgraph.CreateSpec, len(cscb.builders))
+	nodes := make([]*ChatSession, len(cscb.builders))
+	mutators := make([]Mutator, len(cscb.builders))
+	for i := range cscb.builders {
+		func(i int, root context.Context) {
+			builder := cscb.builders[i]
+			builder.defaults()
+			var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
+				mutation, ok := m.(*ChatSessionMutation)
+				if !ok {
+					return nil, fmt.Errorf("unexpected mutation type %T", m)
+				}
+				if err := builder.check(); err != nil {
+					return nil, err
+				}
+				builder.mutation = mutation
+				var err error
+				nodes[i], specs[i] = builder.createSpec()
+				if i < len(mutators)-1 {
+					_, err = mutators[i+1].Mutate(root, cscb.builders[i+1].mutation)
+				} else {
+					spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
+					spec.OnConflict = cscb.conflict
+					// Invoke the actual operation on the latest mutation in the chain.
+					if err = sqlgraph.BatchCreate(ctx, cscb.driver, spec); err != nil {
+						if sqlgraph.IsConstraintError(err) {
+							err = &ConstraintError{msg: err.Error(), wrap: err}
+						}
+					}
+				}
+				if err != nil {
+					return nil, err
+				}
+				mutation.id = &nodes[i].ID
+				if specs[i].ID.Value != nil && nodes[i].ID == 0 {
+					id := specs[i].ID.Value.(int64)
+					nodes[i].ID = uint64(id)
+				}
+				mutation.done = true
+				return nodes[i], nil
+			})
+			for i := len(builder.hooks) - 1; i >= 0; i-- {
+				mut = builder.hooks[i](mut)
+			}
+			mutators[i] = mut
+		}(i, ctx)
+	}
+	if len(mutators) > 0 {
+		if _, err := mutators[0].Mutate(ctx, cscb.builders[0].mutation); err != nil {
+			return nil, err
+		}
+	}
+	return nodes, nil
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (cscb *ChatSessionCreateBulk) SaveX(ctx context.Context) []*ChatSession {
+	v, err := cscb.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (cscb *ChatSessionCreateBulk) Exec(ctx context.Context) error {
+	_, err := cscb.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (cscb *ChatSessionCreateBulk) ExecX(ctx context.Context) {
+	if err := cscb.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.ChatSession.CreateBulk(builders...).
+//		OnConflict(
+//			// Update the row with the new values
+//			// the was proposed for insertion.
+//			sql.ResolveWithNewValues(),
+//		).
+//		// Override some of the fields with custom
+//		// update values.
+//		Update(func(u *ent.ChatSessionUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (cscb *ChatSessionCreateBulk) OnConflict(opts ...sql.ConflictOption) *ChatSessionUpsertBulk {
+	cscb.conflict = opts
+	return &ChatSessionUpsertBulk{
+		create: cscb,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.ChatSession.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (cscb *ChatSessionCreateBulk) OnConflictColumns(columns ...string) *ChatSessionUpsertBulk {
+	cscb.conflict = append(cscb.conflict, sql.ConflictColumns(columns...))
+	return &ChatSessionUpsertBulk{
+		create: cscb,
+	}
+}
+
+// ChatSessionUpsertBulk is the builder for "upsert"-ing
+// a bulk of ChatSession nodes.
+type ChatSessionUpsertBulk struct {
+	create *ChatSessionCreateBulk
+}
+
+// UpdateNewValues updates the mutable fields using the new values that
+// were set on create. Using this option is equivalent to using:
+//
+//	client.ChatSession.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(chatsession.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *ChatSessionUpsertBulk) UpdateNewValues() *ChatSessionUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
+		for _, b := range u.create.builders {
+			if _, exists := b.mutation.ID(); exists {
+				s.SetIgnore(chatsession.FieldID)
+			}
+			if _, exists := b.mutation.CreatedAt(); exists {
+				s.SetIgnore(chatsession.FieldCreatedAt)
+			}
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.ChatSession.Create().
+//		OnConflict(sql.ResolveWithIgnore()).
+//		Exec(ctx)
+func (u *ChatSessionUpsertBulk) Ignore() *ChatSessionUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
+	return u
+}
+
+// DoNothing configures the conflict_action to `DO NOTHING`.
+// Supported only by SQLite and PostgreSQL.
+func (u *ChatSessionUpsertBulk) DoNothing() *ChatSessionUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the ChatSessionCreateBulk.OnConflict
+// documentation for more info.
+func (u *ChatSessionUpsertBulk) Update(set func(*ChatSessionUpsert)) *ChatSessionUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&ChatSessionUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *ChatSessionUpsertBulk) SetUpdatedAt(v time.Time) *ChatSessionUpsertBulk {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *ChatSessionUpsertBulk) UpdateUpdatedAt() *ChatSessionUpsertBulk {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *ChatSessionUpsertBulk) SetDeletedAt(v time.Time) *ChatSessionUpsertBulk {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *ChatSessionUpsertBulk) UpdateDeletedAt() *ChatSessionUpsertBulk {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *ChatSessionUpsertBulk) ClearDeletedAt() *ChatSessionUpsertBulk {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetName sets the "name" field.
+func (u *ChatSessionUpsertBulk) SetName(v string) *ChatSessionUpsertBulk {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.SetName(v)
+	})
+}
+
+// UpdateName sets the "name" field to the value that was provided on create.
+func (u *ChatSessionUpsertBulk) UpdateName() *ChatSessionUpsertBulk {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.UpdateName()
+	})
+}
+
+// SetUserID sets the "user_id" field.
+func (u *ChatSessionUpsertBulk) SetUserID(v uint64) *ChatSessionUpsertBulk {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.SetUserID(v)
+	})
+}
+
+// AddUserID adds v to the "user_id" field.
+func (u *ChatSessionUpsertBulk) AddUserID(v uint64) *ChatSessionUpsertBulk {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.AddUserID(v)
+	})
+}
+
+// UpdateUserID sets the "user_id" field to the value that was provided on create.
+func (u *ChatSessionUpsertBulk) UpdateUserID() *ChatSessionUpsertBulk {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.UpdateUserID()
+	})
+}
+
+// SetBotID sets the "bot_id" field.
+func (u *ChatSessionUpsertBulk) SetBotID(v uint64) *ChatSessionUpsertBulk {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.SetBotID(v)
+	})
+}
+
+// AddBotID adds v to the "bot_id" field.
+func (u *ChatSessionUpsertBulk) AddBotID(v uint64) *ChatSessionUpsertBulk {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.AddBotID(v)
+	})
+}
+
+// UpdateBotID sets the "bot_id" field to the value that was provided on create.
+func (u *ChatSessionUpsertBulk) UpdateBotID() *ChatSessionUpsertBulk {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.UpdateBotID()
+	})
+}
+
+// SetBotType sets the "bot_type" field.
+func (u *ChatSessionUpsertBulk) SetBotType(v uint8) *ChatSessionUpsertBulk {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.SetBotType(v)
+	})
+}
+
+// AddBotType adds v to the "bot_type" field.
+func (u *ChatSessionUpsertBulk) AddBotType(v uint8) *ChatSessionUpsertBulk {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.AddBotType(v)
+	})
+}
+
+// UpdateBotType sets the "bot_type" field to the value that was provided on create.
+func (u *ChatSessionUpsertBulk) UpdateBotType() *ChatSessionUpsertBulk {
+	return u.Update(func(s *ChatSessionUpsert) {
+		s.UpdateBotType()
+	})
+}
+
+// Exec executes the query.
+func (u *ChatSessionUpsertBulk) Exec(ctx context.Context) error {
+	if u.create.err != nil {
+		return u.create.err
+	}
+	for i, b := range u.create.builders {
+		if len(b.conflict) != 0 {
+			return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the ChatSessionCreateBulk instead", i)
+		}
+	}
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for ChatSessionCreateBulk.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *ChatSessionUpsertBulk) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}

+ 88 - 0
ent/chatsession_delete.go

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

+ 526 - 0
ent/chatsession_query.go

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

+ 472 - 0
ent/chatsession_update.go

@@ -0,0 +1,472 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/chatsession"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// ChatSessionUpdate is the builder for updating ChatSession entities.
+type ChatSessionUpdate struct {
+	config
+	hooks    []Hook
+	mutation *ChatSessionMutation
+}
+
+// Where appends a list predicates to the ChatSessionUpdate builder.
+func (csu *ChatSessionUpdate) Where(ps ...predicate.ChatSession) *ChatSessionUpdate {
+	csu.mutation.Where(ps...)
+	return csu
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (csu *ChatSessionUpdate) SetUpdatedAt(t time.Time) *ChatSessionUpdate {
+	csu.mutation.SetUpdatedAt(t)
+	return csu
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (csu *ChatSessionUpdate) SetDeletedAt(t time.Time) *ChatSessionUpdate {
+	csu.mutation.SetDeletedAt(t)
+	return csu
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (csu *ChatSessionUpdate) SetNillableDeletedAt(t *time.Time) *ChatSessionUpdate {
+	if t != nil {
+		csu.SetDeletedAt(*t)
+	}
+	return csu
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (csu *ChatSessionUpdate) ClearDeletedAt() *ChatSessionUpdate {
+	csu.mutation.ClearDeletedAt()
+	return csu
+}
+
+// SetName sets the "name" field.
+func (csu *ChatSessionUpdate) SetName(s string) *ChatSessionUpdate {
+	csu.mutation.SetName(s)
+	return csu
+}
+
+// SetNillableName sets the "name" field if the given value is not nil.
+func (csu *ChatSessionUpdate) SetNillableName(s *string) *ChatSessionUpdate {
+	if s != nil {
+		csu.SetName(*s)
+	}
+	return csu
+}
+
+// SetUserID sets the "user_id" field.
+func (csu *ChatSessionUpdate) SetUserID(u uint64) *ChatSessionUpdate {
+	csu.mutation.ResetUserID()
+	csu.mutation.SetUserID(u)
+	return csu
+}
+
+// SetNillableUserID sets the "user_id" field if the given value is not nil.
+func (csu *ChatSessionUpdate) SetNillableUserID(u *uint64) *ChatSessionUpdate {
+	if u != nil {
+		csu.SetUserID(*u)
+	}
+	return csu
+}
+
+// AddUserID adds u to the "user_id" field.
+func (csu *ChatSessionUpdate) AddUserID(u int64) *ChatSessionUpdate {
+	csu.mutation.AddUserID(u)
+	return csu
+}
+
+// SetBotID sets the "bot_id" field.
+func (csu *ChatSessionUpdate) SetBotID(u uint64) *ChatSessionUpdate {
+	csu.mutation.ResetBotID()
+	csu.mutation.SetBotID(u)
+	return csu
+}
+
+// SetNillableBotID sets the "bot_id" field if the given value is not nil.
+func (csu *ChatSessionUpdate) SetNillableBotID(u *uint64) *ChatSessionUpdate {
+	if u != nil {
+		csu.SetBotID(*u)
+	}
+	return csu
+}
+
+// AddBotID adds u to the "bot_id" field.
+func (csu *ChatSessionUpdate) AddBotID(u int64) *ChatSessionUpdate {
+	csu.mutation.AddBotID(u)
+	return csu
+}
+
+// SetBotType sets the "bot_type" field.
+func (csu *ChatSessionUpdate) SetBotType(u uint8) *ChatSessionUpdate {
+	csu.mutation.ResetBotType()
+	csu.mutation.SetBotType(u)
+	return csu
+}
+
+// SetNillableBotType sets the "bot_type" field if the given value is not nil.
+func (csu *ChatSessionUpdate) SetNillableBotType(u *uint8) *ChatSessionUpdate {
+	if u != nil {
+		csu.SetBotType(*u)
+	}
+	return csu
+}
+
+// AddBotType adds u to the "bot_type" field.
+func (csu *ChatSessionUpdate) AddBotType(u int8) *ChatSessionUpdate {
+	csu.mutation.AddBotType(u)
+	return csu
+}
+
+// Mutation returns the ChatSessionMutation object of the builder.
+func (csu *ChatSessionUpdate) Mutation() *ChatSessionMutation {
+	return csu.mutation
+}
+
+// Save executes the query and returns the number of nodes affected by the update operation.
+func (csu *ChatSessionUpdate) Save(ctx context.Context) (int, error) {
+	if err := csu.defaults(); err != nil {
+		return 0, err
+	}
+	return withHooks(ctx, csu.sqlSave, csu.mutation, csu.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (csu *ChatSessionUpdate) SaveX(ctx context.Context) int {
+	affected, err := csu.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return affected
+}
+
+// Exec executes the query.
+func (csu *ChatSessionUpdate) Exec(ctx context.Context) error {
+	_, err := csu.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (csu *ChatSessionUpdate) ExecX(ctx context.Context) {
+	if err := csu.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (csu *ChatSessionUpdate) defaults() error {
+	if _, ok := csu.mutation.UpdatedAt(); !ok {
+		if chatsession.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized chatsession.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := chatsession.UpdateDefaultUpdatedAt()
+		csu.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+func (csu *ChatSessionUpdate) sqlSave(ctx context.Context) (n int, err error) {
+	_spec := sqlgraph.NewUpdateSpec(chatsession.Table, chatsession.Columns, sqlgraph.NewFieldSpec(chatsession.FieldID, field.TypeUint64))
+	if ps := csu.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := csu.mutation.UpdatedAt(); ok {
+		_spec.SetField(chatsession.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := csu.mutation.DeletedAt(); ok {
+		_spec.SetField(chatsession.FieldDeletedAt, field.TypeTime, value)
+	}
+	if csu.mutation.DeletedAtCleared() {
+		_spec.ClearField(chatsession.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := csu.mutation.Name(); ok {
+		_spec.SetField(chatsession.FieldName, field.TypeString, value)
+	}
+	if value, ok := csu.mutation.UserID(); ok {
+		_spec.SetField(chatsession.FieldUserID, field.TypeUint64, value)
+	}
+	if value, ok := csu.mutation.AddedUserID(); ok {
+		_spec.AddField(chatsession.FieldUserID, field.TypeUint64, value)
+	}
+	if value, ok := csu.mutation.BotID(); ok {
+		_spec.SetField(chatsession.FieldBotID, field.TypeUint64, value)
+	}
+	if value, ok := csu.mutation.AddedBotID(); ok {
+		_spec.AddField(chatsession.FieldBotID, field.TypeUint64, value)
+	}
+	if value, ok := csu.mutation.BotType(); ok {
+		_spec.SetField(chatsession.FieldBotType, field.TypeUint8, value)
+	}
+	if value, ok := csu.mutation.AddedBotType(); ok {
+		_spec.AddField(chatsession.FieldBotType, field.TypeUint8, value)
+	}
+	if n, err = sqlgraph.UpdateNodes(ctx, csu.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{chatsession.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return 0, err
+	}
+	csu.mutation.done = true
+	return n, nil
+}
+
+// ChatSessionUpdateOne is the builder for updating a single ChatSession entity.
+type ChatSessionUpdateOne struct {
+	config
+	fields   []string
+	hooks    []Hook
+	mutation *ChatSessionMutation
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (csuo *ChatSessionUpdateOne) SetUpdatedAt(t time.Time) *ChatSessionUpdateOne {
+	csuo.mutation.SetUpdatedAt(t)
+	return csuo
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (csuo *ChatSessionUpdateOne) SetDeletedAt(t time.Time) *ChatSessionUpdateOne {
+	csuo.mutation.SetDeletedAt(t)
+	return csuo
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (csuo *ChatSessionUpdateOne) SetNillableDeletedAt(t *time.Time) *ChatSessionUpdateOne {
+	if t != nil {
+		csuo.SetDeletedAt(*t)
+	}
+	return csuo
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (csuo *ChatSessionUpdateOne) ClearDeletedAt() *ChatSessionUpdateOne {
+	csuo.mutation.ClearDeletedAt()
+	return csuo
+}
+
+// SetName sets the "name" field.
+func (csuo *ChatSessionUpdateOne) SetName(s string) *ChatSessionUpdateOne {
+	csuo.mutation.SetName(s)
+	return csuo
+}
+
+// SetNillableName sets the "name" field if the given value is not nil.
+func (csuo *ChatSessionUpdateOne) SetNillableName(s *string) *ChatSessionUpdateOne {
+	if s != nil {
+		csuo.SetName(*s)
+	}
+	return csuo
+}
+
+// SetUserID sets the "user_id" field.
+func (csuo *ChatSessionUpdateOne) SetUserID(u uint64) *ChatSessionUpdateOne {
+	csuo.mutation.ResetUserID()
+	csuo.mutation.SetUserID(u)
+	return csuo
+}
+
+// SetNillableUserID sets the "user_id" field if the given value is not nil.
+func (csuo *ChatSessionUpdateOne) SetNillableUserID(u *uint64) *ChatSessionUpdateOne {
+	if u != nil {
+		csuo.SetUserID(*u)
+	}
+	return csuo
+}
+
+// AddUserID adds u to the "user_id" field.
+func (csuo *ChatSessionUpdateOne) AddUserID(u int64) *ChatSessionUpdateOne {
+	csuo.mutation.AddUserID(u)
+	return csuo
+}
+
+// SetBotID sets the "bot_id" field.
+func (csuo *ChatSessionUpdateOne) SetBotID(u uint64) *ChatSessionUpdateOne {
+	csuo.mutation.ResetBotID()
+	csuo.mutation.SetBotID(u)
+	return csuo
+}
+
+// SetNillableBotID sets the "bot_id" field if the given value is not nil.
+func (csuo *ChatSessionUpdateOne) SetNillableBotID(u *uint64) *ChatSessionUpdateOne {
+	if u != nil {
+		csuo.SetBotID(*u)
+	}
+	return csuo
+}
+
+// AddBotID adds u to the "bot_id" field.
+func (csuo *ChatSessionUpdateOne) AddBotID(u int64) *ChatSessionUpdateOne {
+	csuo.mutation.AddBotID(u)
+	return csuo
+}
+
+// SetBotType sets the "bot_type" field.
+func (csuo *ChatSessionUpdateOne) SetBotType(u uint8) *ChatSessionUpdateOne {
+	csuo.mutation.ResetBotType()
+	csuo.mutation.SetBotType(u)
+	return csuo
+}
+
+// SetNillableBotType sets the "bot_type" field if the given value is not nil.
+func (csuo *ChatSessionUpdateOne) SetNillableBotType(u *uint8) *ChatSessionUpdateOne {
+	if u != nil {
+		csuo.SetBotType(*u)
+	}
+	return csuo
+}
+
+// AddBotType adds u to the "bot_type" field.
+func (csuo *ChatSessionUpdateOne) AddBotType(u int8) *ChatSessionUpdateOne {
+	csuo.mutation.AddBotType(u)
+	return csuo
+}
+
+// Mutation returns the ChatSessionMutation object of the builder.
+func (csuo *ChatSessionUpdateOne) Mutation() *ChatSessionMutation {
+	return csuo.mutation
+}
+
+// Where appends a list predicates to the ChatSessionUpdate builder.
+func (csuo *ChatSessionUpdateOne) Where(ps ...predicate.ChatSession) *ChatSessionUpdateOne {
+	csuo.mutation.Where(ps...)
+	return csuo
+}
+
+// Select allows selecting one or more fields (columns) of the returned entity.
+// The default is selecting all fields defined in the entity schema.
+func (csuo *ChatSessionUpdateOne) Select(field string, fields ...string) *ChatSessionUpdateOne {
+	csuo.fields = append([]string{field}, fields...)
+	return csuo
+}
+
+// Save executes the query and returns the updated ChatSession entity.
+func (csuo *ChatSessionUpdateOne) Save(ctx context.Context) (*ChatSession, error) {
+	if err := csuo.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, csuo.sqlSave, csuo.mutation, csuo.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (csuo *ChatSessionUpdateOne) SaveX(ctx context.Context) *ChatSession {
+	node, err := csuo.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return node
+}
+
+// Exec executes the query on the entity.
+func (csuo *ChatSessionUpdateOne) Exec(ctx context.Context) error {
+	_, err := csuo.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (csuo *ChatSessionUpdateOne) ExecX(ctx context.Context) {
+	if err := csuo.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (csuo *ChatSessionUpdateOne) defaults() error {
+	if _, ok := csuo.mutation.UpdatedAt(); !ok {
+		if chatsession.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized chatsession.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := chatsession.UpdateDefaultUpdatedAt()
+		csuo.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+func (csuo *ChatSessionUpdateOne) sqlSave(ctx context.Context) (_node *ChatSession, err error) {
+	_spec := sqlgraph.NewUpdateSpec(chatsession.Table, chatsession.Columns, sqlgraph.NewFieldSpec(chatsession.FieldID, field.TypeUint64))
+	id, ok := csuo.mutation.ID()
+	if !ok {
+		return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "ChatSession.id" for update`)}
+	}
+	_spec.Node.ID.Value = id
+	if fields := csuo.fields; len(fields) > 0 {
+		_spec.Node.Columns = make([]string, 0, len(fields))
+		_spec.Node.Columns = append(_spec.Node.Columns, chatsession.FieldID)
+		for _, f := range fields {
+			if !chatsession.ValidColumn(f) {
+				return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+			}
+			if f != chatsession.FieldID {
+				_spec.Node.Columns = append(_spec.Node.Columns, f)
+			}
+		}
+	}
+	if ps := csuo.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := csuo.mutation.UpdatedAt(); ok {
+		_spec.SetField(chatsession.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := csuo.mutation.DeletedAt(); ok {
+		_spec.SetField(chatsession.FieldDeletedAt, field.TypeTime, value)
+	}
+	if csuo.mutation.DeletedAtCleared() {
+		_spec.ClearField(chatsession.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := csuo.mutation.Name(); ok {
+		_spec.SetField(chatsession.FieldName, field.TypeString, value)
+	}
+	if value, ok := csuo.mutation.UserID(); ok {
+		_spec.SetField(chatsession.FieldUserID, field.TypeUint64, value)
+	}
+	if value, ok := csuo.mutation.AddedUserID(); ok {
+		_spec.AddField(chatsession.FieldUserID, field.TypeUint64, value)
+	}
+	if value, ok := csuo.mutation.BotID(); ok {
+		_spec.SetField(chatsession.FieldBotID, field.TypeUint64, value)
+	}
+	if value, ok := csuo.mutation.AddedBotID(); ok {
+		_spec.AddField(chatsession.FieldBotID, field.TypeUint64, value)
+	}
+	if value, ok := csuo.mutation.BotType(); ok {
+		_spec.SetField(chatsession.FieldBotType, field.TypeUint8, value)
+	}
+	if value, ok := csuo.mutation.AddedBotType(); ok {
+		_spec.AddField(chatsession.FieldBotType, field.TypeUint8, value)
+	}
+	_node = &ChatSession{config: csuo.config}
+	_spec.Assign = _node.assignValues
+	_spec.ScanValues = _node.scanValues
+	if err = sqlgraph.UpdateNode(ctx, csuo.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{chatsession.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	csuo.mutation.done = true
+	return _node, nil
+}

+ 733 - 14
ent/client.go

@@ -15,6 +15,8 @@ import (
 	"wechat-api/ent/agentbase"
 	"wechat-api/ent/batchmsg"
 	"wechat-api/ent/category"
+	"wechat-api/ent/chatrecords"
+	"wechat-api/ent/chatsession"
 	"wechat-api/ent/contact"
 	"wechat-api/ent/employee"
 	"wechat-api/ent/employeeconfig"
@@ -31,6 +33,9 @@ import (
 	"wechat-api/ent/tutorial"
 	"wechat-api/ent/workexperience"
 	"wechat-api/ent/wx"
+	"wechat-api/ent/wxcard"
+	"wechat-api/ent/wxcarduser"
+	"wechat-api/ent/wxcardvisit"
 
 	"entgo.io/ent"
 	"entgo.io/ent/dialect"
@@ -53,6 +58,10 @@ type Client struct {
 	BatchMsg *BatchMsgClient
 	// Category is the client for interacting with the Category builders.
 	Category *CategoryClient
+	// ChatRecords is the client for interacting with the ChatRecords builders.
+	ChatRecords *ChatRecordsClient
+	// ChatSession is the client for interacting with the ChatSession builders.
+	ChatSession *ChatSessionClient
 	// Contact is the client for interacting with the Contact builders.
 	Contact *ContactClient
 	// Employee is the client for interacting with the Employee builders.
@@ -85,6 +94,12 @@ type Client struct {
 	WorkExperience *WorkExperienceClient
 	// Wx is the client for interacting with the Wx builders.
 	Wx *WxClient
+	// WxCard is the client for interacting with the WxCard builders.
+	WxCard *WxCardClient
+	// WxCardUser is the client for interacting with the WxCardUser builders.
+	WxCardUser *WxCardUserClient
+	// WxCardVisit is the client for interacting with the WxCardVisit builders.
+	WxCardVisit *WxCardVisitClient
 }
 
 // NewClient creates a new client configured with the given options.
@@ -100,6 +115,8 @@ func (c *Client) init() {
 	c.AgentBase = NewAgentBaseClient(c.config)
 	c.BatchMsg = NewBatchMsgClient(c.config)
 	c.Category = NewCategoryClient(c.config)
+	c.ChatRecords = NewChatRecordsClient(c.config)
+	c.ChatSession = NewChatSessionClient(c.config)
 	c.Contact = NewContactClient(c.config)
 	c.Employee = NewEmployeeClient(c.config)
 	c.EmployeeConfig = NewEmployeeConfigClient(c.config)
@@ -116,6 +133,9 @@ func (c *Client) init() {
 	c.Tutorial = NewTutorialClient(c.config)
 	c.WorkExperience = NewWorkExperienceClient(c.config)
 	c.Wx = NewWxClient(c.config)
+	c.WxCard = NewWxCardClient(c.config)
+	c.WxCardUser = NewWxCardUserClient(c.config)
+	c.WxCardVisit = NewWxCardVisitClient(c.config)
 }
 
 type (
@@ -212,6 +232,8 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
 		AgentBase:         NewAgentBaseClient(cfg),
 		BatchMsg:          NewBatchMsgClient(cfg),
 		Category:          NewCategoryClient(cfg),
+		ChatRecords:       NewChatRecordsClient(cfg),
+		ChatSession:       NewChatSessionClient(cfg),
 		Contact:           NewContactClient(cfg),
 		Employee:          NewEmployeeClient(cfg),
 		EmployeeConfig:    NewEmployeeConfigClient(cfg),
@@ -228,6 +250,9 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
 		Tutorial:          NewTutorialClient(cfg),
 		WorkExperience:    NewWorkExperienceClient(cfg),
 		Wx:                NewWxClient(cfg),
+		WxCard:            NewWxCardClient(cfg),
+		WxCardUser:        NewWxCardUserClient(cfg),
+		WxCardVisit:       NewWxCardVisitClient(cfg),
 	}, nil
 }
 
@@ -251,6 +276,8 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
 		AgentBase:         NewAgentBaseClient(cfg),
 		BatchMsg:          NewBatchMsgClient(cfg),
 		Category:          NewCategoryClient(cfg),
+		ChatRecords:       NewChatRecordsClient(cfg),
+		ChatSession:       NewChatSessionClient(cfg),
 		Contact:           NewContactClient(cfg),
 		Employee:          NewEmployeeClient(cfg),
 		EmployeeConfig:    NewEmployeeConfigClient(cfg),
@@ -267,6 +294,9 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
 		Tutorial:          NewTutorialClient(cfg),
 		WorkExperience:    NewWorkExperienceClient(cfg),
 		Wx:                NewWxClient(cfg),
+		WxCard:            NewWxCardClient(cfg),
+		WxCardUser:        NewWxCardUserClient(cfg),
+		WxCardVisit:       NewWxCardVisitClient(cfg),
 	}, nil
 }
 
@@ -296,10 +326,11 @@ func (c *Client) Close() error {
 // In order to add hooks to a specific client, call: `client.Node.Use(...)`.
 func (c *Client) Use(hooks ...Hook) {
 	for _, n := range []interface{ Use(...Hook) }{
-		c.Agent, c.AgentBase, c.BatchMsg, c.Category, c.Contact, c.Employee,
-		c.EmployeeConfig, c.Label, c.LabelRelationship, c.Message, c.MessageRecords,
-		c.Msg, c.Server, c.SopNode, c.SopStage, c.SopTask, c.Token, c.Tutorial,
-		c.WorkExperience, c.Wx,
+		c.Agent, c.AgentBase, c.BatchMsg, c.Category, c.ChatRecords, c.ChatSession,
+		c.Contact, c.Employee, c.EmployeeConfig, c.Label, c.LabelRelationship,
+		c.Message, c.MessageRecords, c.Msg, c.Server, c.SopNode, c.SopStage, c.SopTask,
+		c.Token, c.Tutorial, c.WorkExperience, c.Wx, c.WxCard, c.WxCardUser,
+		c.WxCardVisit,
 	} {
 		n.Use(hooks...)
 	}
@@ -309,10 +340,11 @@ func (c *Client) Use(hooks ...Hook) {
 // In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`.
 func (c *Client) Intercept(interceptors ...Interceptor) {
 	for _, n := range []interface{ Intercept(...Interceptor) }{
-		c.Agent, c.AgentBase, c.BatchMsg, c.Category, c.Contact, c.Employee,
-		c.EmployeeConfig, c.Label, c.LabelRelationship, c.Message, c.MessageRecords,
-		c.Msg, c.Server, c.SopNode, c.SopStage, c.SopTask, c.Token, c.Tutorial,
-		c.WorkExperience, c.Wx,
+		c.Agent, c.AgentBase, c.BatchMsg, c.Category, c.ChatRecords, c.ChatSession,
+		c.Contact, c.Employee, c.EmployeeConfig, c.Label, c.LabelRelationship,
+		c.Message, c.MessageRecords, c.Msg, c.Server, c.SopNode, c.SopStage, c.SopTask,
+		c.Token, c.Tutorial, c.WorkExperience, c.Wx, c.WxCard, c.WxCardUser,
+		c.WxCardVisit,
 	} {
 		n.Intercept(interceptors...)
 	}
@@ -329,6 +361,10 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
 		return c.BatchMsg.mutate(ctx, m)
 	case *CategoryMutation:
 		return c.Category.mutate(ctx, m)
+	case *ChatRecordsMutation:
+		return c.ChatRecords.mutate(ctx, m)
+	case *ChatSessionMutation:
+		return c.ChatSession.mutate(ctx, m)
 	case *ContactMutation:
 		return c.Contact.mutate(ctx, m)
 	case *EmployeeMutation:
@@ -361,6 +397,12 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
 		return c.WorkExperience.mutate(ctx, m)
 	case *WxMutation:
 		return c.Wx.mutate(ctx, m)
+	case *WxCardMutation:
+		return c.WxCard.mutate(ctx, m)
+	case *WxCardUserMutation:
+		return c.WxCardUser.mutate(ctx, m)
+	case *WxCardVisitMutation:
+		return c.WxCardVisit.mutate(ctx, m)
 	default:
 		return nil, fmt.Errorf("ent: unknown mutation type %T", m)
 	}
@@ -936,6 +978,276 @@ func (c *CategoryClient) mutate(ctx context.Context, m *CategoryMutation) (Value
 	}
 }
 
+// ChatRecordsClient is a client for the ChatRecords schema.
+type ChatRecordsClient struct {
+	config
+}
+
+// NewChatRecordsClient returns a client for the ChatRecords from the given config.
+func NewChatRecordsClient(c config) *ChatRecordsClient {
+	return &ChatRecordsClient{config: c}
+}
+
+// Use adds a list of mutation hooks to the hooks stack.
+// A call to `Use(f, g, h)` equals to `chatrecords.Hooks(f(g(h())))`.
+func (c *ChatRecordsClient) Use(hooks ...Hook) {
+	c.hooks.ChatRecords = append(c.hooks.ChatRecords, hooks...)
+}
+
+// Intercept adds a list of query interceptors to the interceptors stack.
+// A call to `Intercept(f, g, h)` equals to `chatrecords.Intercept(f(g(h())))`.
+func (c *ChatRecordsClient) Intercept(interceptors ...Interceptor) {
+	c.inters.ChatRecords = append(c.inters.ChatRecords, interceptors...)
+}
+
+// Create returns a builder for creating a ChatRecords entity.
+func (c *ChatRecordsClient) Create() *ChatRecordsCreate {
+	mutation := newChatRecordsMutation(c.config, OpCreate)
+	return &ChatRecordsCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// CreateBulk returns a builder for creating a bulk of ChatRecords entities.
+func (c *ChatRecordsClient) CreateBulk(builders ...*ChatRecordsCreate) *ChatRecordsCreateBulk {
+	return &ChatRecordsCreateBulk{config: c.config, builders: builders}
+}
+
+// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
+// a builder and applies setFunc on it.
+func (c *ChatRecordsClient) MapCreateBulk(slice any, setFunc func(*ChatRecordsCreate, int)) *ChatRecordsCreateBulk {
+	rv := reflect.ValueOf(slice)
+	if rv.Kind() != reflect.Slice {
+		return &ChatRecordsCreateBulk{err: fmt.Errorf("calling to ChatRecordsClient.MapCreateBulk with wrong type %T, need slice", slice)}
+	}
+	builders := make([]*ChatRecordsCreate, rv.Len())
+	for i := 0; i < rv.Len(); i++ {
+		builders[i] = c.Create()
+		setFunc(builders[i], i)
+	}
+	return &ChatRecordsCreateBulk{config: c.config, builders: builders}
+}
+
+// Update returns an update builder for ChatRecords.
+func (c *ChatRecordsClient) Update() *ChatRecordsUpdate {
+	mutation := newChatRecordsMutation(c.config, OpUpdate)
+	return &ChatRecordsUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOne returns an update builder for the given entity.
+func (c *ChatRecordsClient) UpdateOne(cr *ChatRecords) *ChatRecordsUpdateOne {
+	mutation := newChatRecordsMutation(c.config, OpUpdateOne, withChatRecords(cr))
+	return &ChatRecordsUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOneID returns an update builder for the given id.
+func (c *ChatRecordsClient) UpdateOneID(id uint64) *ChatRecordsUpdateOne {
+	mutation := newChatRecordsMutation(c.config, OpUpdateOne, withChatRecordsID(id))
+	return &ChatRecordsUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// Delete returns a delete builder for ChatRecords.
+func (c *ChatRecordsClient) Delete() *ChatRecordsDelete {
+	mutation := newChatRecordsMutation(c.config, OpDelete)
+	return &ChatRecordsDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// DeleteOne returns a builder for deleting the given entity.
+func (c *ChatRecordsClient) DeleteOne(cr *ChatRecords) *ChatRecordsDeleteOne {
+	return c.DeleteOneID(cr.ID)
+}
+
+// DeleteOneID returns a builder for deleting the given entity by its id.
+func (c *ChatRecordsClient) DeleteOneID(id uint64) *ChatRecordsDeleteOne {
+	builder := c.Delete().Where(chatrecords.ID(id))
+	builder.mutation.id = &id
+	builder.mutation.op = OpDeleteOne
+	return &ChatRecordsDeleteOne{builder}
+}
+
+// Query returns a query builder for ChatRecords.
+func (c *ChatRecordsClient) Query() *ChatRecordsQuery {
+	return &ChatRecordsQuery{
+		config: c.config,
+		ctx:    &QueryContext{Type: TypeChatRecords},
+		inters: c.Interceptors(),
+	}
+}
+
+// Get returns a ChatRecords entity by its id.
+func (c *ChatRecordsClient) Get(ctx context.Context, id uint64) (*ChatRecords, error) {
+	return c.Query().Where(chatrecords.ID(id)).Only(ctx)
+}
+
+// GetX is like Get, but panics if an error occurs.
+func (c *ChatRecordsClient) GetX(ctx context.Context, id uint64) *ChatRecords {
+	obj, err := c.Get(ctx, id)
+	if err != nil {
+		panic(err)
+	}
+	return obj
+}
+
+// Hooks returns the client hooks.
+func (c *ChatRecordsClient) Hooks() []Hook {
+	hooks := c.hooks.ChatRecords
+	return append(hooks[:len(hooks):len(hooks)], chatrecords.Hooks[:]...)
+}
+
+// Interceptors returns the client interceptors.
+func (c *ChatRecordsClient) Interceptors() []Interceptor {
+	inters := c.inters.ChatRecords
+	return append(inters[:len(inters):len(inters)], chatrecords.Interceptors[:]...)
+}
+
+func (c *ChatRecordsClient) mutate(ctx context.Context, m *ChatRecordsMutation) (Value, error) {
+	switch m.Op() {
+	case OpCreate:
+		return (&ChatRecordsCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdate:
+		return (&ChatRecordsUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdateOne:
+		return (&ChatRecordsUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpDelete, OpDeleteOne:
+		return (&ChatRecordsDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
+	default:
+		return nil, fmt.Errorf("ent: unknown ChatRecords mutation op: %q", m.Op())
+	}
+}
+
+// ChatSessionClient is a client for the ChatSession schema.
+type ChatSessionClient struct {
+	config
+}
+
+// NewChatSessionClient returns a client for the ChatSession from the given config.
+func NewChatSessionClient(c config) *ChatSessionClient {
+	return &ChatSessionClient{config: c}
+}
+
+// Use adds a list of mutation hooks to the hooks stack.
+// A call to `Use(f, g, h)` equals to `chatsession.Hooks(f(g(h())))`.
+func (c *ChatSessionClient) Use(hooks ...Hook) {
+	c.hooks.ChatSession = append(c.hooks.ChatSession, hooks...)
+}
+
+// Intercept adds a list of query interceptors to the interceptors stack.
+// A call to `Intercept(f, g, h)` equals to `chatsession.Intercept(f(g(h())))`.
+func (c *ChatSessionClient) Intercept(interceptors ...Interceptor) {
+	c.inters.ChatSession = append(c.inters.ChatSession, interceptors...)
+}
+
+// Create returns a builder for creating a ChatSession entity.
+func (c *ChatSessionClient) Create() *ChatSessionCreate {
+	mutation := newChatSessionMutation(c.config, OpCreate)
+	return &ChatSessionCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// CreateBulk returns a builder for creating a bulk of ChatSession entities.
+func (c *ChatSessionClient) CreateBulk(builders ...*ChatSessionCreate) *ChatSessionCreateBulk {
+	return &ChatSessionCreateBulk{config: c.config, builders: builders}
+}
+
+// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
+// a builder and applies setFunc on it.
+func (c *ChatSessionClient) MapCreateBulk(slice any, setFunc func(*ChatSessionCreate, int)) *ChatSessionCreateBulk {
+	rv := reflect.ValueOf(slice)
+	if rv.Kind() != reflect.Slice {
+		return &ChatSessionCreateBulk{err: fmt.Errorf("calling to ChatSessionClient.MapCreateBulk with wrong type %T, need slice", slice)}
+	}
+	builders := make([]*ChatSessionCreate, rv.Len())
+	for i := 0; i < rv.Len(); i++ {
+		builders[i] = c.Create()
+		setFunc(builders[i], i)
+	}
+	return &ChatSessionCreateBulk{config: c.config, builders: builders}
+}
+
+// Update returns an update builder for ChatSession.
+func (c *ChatSessionClient) Update() *ChatSessionUpdate {
+	mutation := newChatSessionMutation(c.config, OpUpdate)
+	return &ChatSessionUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOne returns an update builder for the given entity.
+func (c *ChatSessionClient) UpdateOne(cs *ChatSession) *ChatSessionUpdateOne {
+	mutation := newChatSessionMutation(c.config, OpUpdateOne, withChatSession(cs))
+	return &ChatSessionUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOneID returns an update builder for the given id.
+func (c *ChatSessionClient) UpdateOneID(id uint64) *ChatSessionUpdateOne {
+	mutation := newChatSessionMutation(c.config, OpUpdateOne, withChatSessionID(id))
+	return &ChatSessionUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// Delete returns a delete builder for ChatSession.
+func (c *ChatSessionClient) Delete() *ChatSessionDelete {
+	mutation := newChatSessionMutation(c.config, OpDelete)
+	return &ChatSessionDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// DeleteOne returns a builder for deleting the given entity.
+func (c *ChatSessionClient) DeleteOne(cs *ChatSession) *ChatSessionDeleteOne {
+	return c.DeleteOneID(cs.ID)
+}
+
+// DeleteOneID returns a builder for deleting the given entity by its id.
+func (c *ChatSessionClient) DeleteOneID(id uint64) *ChatSessionDeleteOne {
+	builder := c.Delete().Where(chatsession.ID(id))
+	builder.mutation.id = &id
+	builder.mutation.op = OpDeleteOne
+	return &ChatSessionDeleteOne{builder}
+}
+
+// Query returns a query builder for ChatSession.
+func (c *ChatSessionClient) Query() *ChatSessionQuery {
+	return &ChatSessionQuery{
+		config: c.config,
+		ctx:    &QueryContext{Type: TypeChatSession},
+		inters: c.Interceptors(),
+	}
+}
+
+// Get returns a ChatSession entity by its id.
+func (c *ChatSessionClient) Get(ctx context.Context, id uint64) (*ChatSession, error) {
+	return c.Query().Where(chatsession.ID(id)).Only(ctx)
+}
+
+// GetX is like Get, but panics if an error occurs.
+func (c *ChatSessionClient) GetX(ctx context.Context, id uint64) *ChatSession {
+	obj, err := c.Get(ctx, id)
+	if err != nil {
+		panic(err)
+	}
+	return obj
+}
+
+// Hooks returns the client hooks.
+func (c *ChatSessionClient) Hooks() []Hook {
+	hooks := c.hooks.ChatSession
+	return append(hooks[:len(hooks):len(hooks)], chatsession.Hooks[:]...)
+}
+
+// Interceptors returns the client interceptors.
+func (c *ChatSessionClient) Interceptors() []Interceptor {
+	inters := c.inters.ChatSession
+	return append(inters[:len(inters):len(inters)], chatsession.Interceptors[:]...)
+}
+
+func (c *ChatSessionClient) mutate(ctx context.Context, m *ChatSessionMutation) (Value, error) {
+	switch m.Op() {
+	case OpCreate:
+		return (&ChatSessionCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdate:
+		return (&ChatSessionUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdateOne:
+		return (&ChatSessionUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpDelete, OpDeleteOne:
+		return (&ChatSessionDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
+	default:
+		return nil, fmt.Errorf("ent: unknown ChatSession mutation op: %q", m.Op())
+	}
+}
+
 // ContactClient is a client for the Contact schema.
 type ContactClient struct {
 	config
@@ -3426,17 +3738,424 @@ func (c *WxClient) mutate(ctx context.Context, m *WxMutation) (Value, error) {
 	}
 }
 
+// WxCardClient is a client for the WxCard schema.
+type WxCardClient struct {
+	config
+}
+
+// NewWxCardClient returns a client for the WxCard from the given config.
+func NewWxCardClient(c config) *WxCardClient {
+	return &WxCardClient{config: c}
+}
+
+// Use adds a list of mutation hooks to the hooks stack.
+// A call to `Use(f, g, h)` equals to `wxcard.Hooks(f(g(h())))`.
+func (c *WxCardClient) Use(hooks ...Hook) {
+	c.hooks.WxCard = append(c.hooks.WxCard, hooks...)
+}
+
+// Intercept adds a list of query interceptors to the interceptors stack.
+// A call to `Intercept(f, g, h)` equals to `wxcard.Intercept(f(g(h())))`.
+func (c *WxCardClient) Intercept(interceptors ...Interceptor) {
+	c.inters.WxCard = append(c.inters.WxCard, interceptors...)
+}
+
+// Create returns a builder for creating a WxCard entity.
+func (c *WxCardClient) Create() *WxCardCreate {
+	mutation := newWxCardMutation(c.config, OpCreate)
+	return &WxCardCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// CreateBulk returns a builder for creating a bulk of WxCard entities.
+func (c *WxCardClient) CreateBulk(builders ...*WxCardCreate) *WxCardCreateBulk {
+	return &WxCardCreateBulk{config: c.config, builders: builders}
+}
+
+// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
+// a builder and applies setFunc on it.
+func (c *WxCardClient) MapCreateBulk(slice any, setFunc func(*WxCardCreate, int)) *WxCardCreateBulk {
+	rv := reflect.ValueOf(slice)
+	if rv.Kind() != reflect.Slice {
+		return &WxCardCreateBulk{err: fmt.Errorf("calling to WxCardClient.MapCreateBulk with wrong type %T, need slice", slice)}
+	}
+	builders := make([]*WxCardCreate, rv.Len())
+	for i := 0; i < rv.Len(); i++ {
+		builders[i] = c.Create()
+		setFunc(builders[i], i)
+	}
+	return &WxCardCreateBulk{config: c.config, builders: builders}
+}
+
+// Update returns an update builder for WxCard.
+func (c *WxCardClient) Update() *WxCardUpdate {
+	mutation := newWxCardMutation(c.config, OpUpdate)
+	return &WxCardUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOne returns an update builder for the given entity.
+func (c *WxCardClient) UpdateOne(wc *WxCard) *WxCardUpdateOne {
+	mutation := newWxCardMutation(c.config, OpUpdateOne, withWxCard(wc))
+	return &WxCardUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOneID returns an update builder for the given id.
+func (c *WxCardClient) UpdateOneID(id uint64) *WxCardUpdateOne {
+	mutation := newWxCardMutation(c.config, OpUpdateOne, withWxCardID(id))
+	return &WxCardUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// Delete returns a delete builder for WxCard.
+func (c *WxCardClient) Delete() *WxCardDelete {
+	mutation := newWxCardMutation(c.config, OpDelete)
+	return &WxCardDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// DeleteOne returns a builder for deleting the given entity.
+func (c *WxCardClient) DeleteOne(wc *WxCard) *WxCardDeleteOne {
+	return c.DeleteOneID(wc.ID)
+}
+
+// DeleteOneID returns a builder for deleting the given entity by its id.
+func (c *WxCardClient) DeleteOneID(id uint64) *WxCardDeleteOne {
+	builder := c.Delete().Where(wxcard.ID(id))
+	builder.mutation.id = &id
+	builder.mutation.op = OpDeleteOne
+	return &WxCardDeleteOne{builder}
+}
+
+// Query returns a query builder for WxCard.
+func (c *WxCardClient) Query() *WxCardQuery {
+	return &WxCardQuery{
+		config: c.config,
+		ctx:    &QueryContext{Type: TypeWxCard},
+		inters: c.Interceptors(),
+	}
+}
+
+// Get returns a WxCard entity by its id.
+func (c *WxCardClient) Get(ctx context.Context, id uint64) (*WxCard, error) {
+	return c.Query().Where(wxcard.ID(id)).Only(ctx)
+}
+
+// GetX is like Get, but panics if an error occurs.
+func (c *WxCardClient) GetX(ctx context.Context, id uint64) *WxCard {
+	obj, err := c.Get(ctx, id)
+	if err != nil {
+		panic(err)
+	}
+	return obj
+}
+
+// Hooks returns the client hooks.
+func (c *WxCardClient) Hooks() []Hook {
+	hooks := c.hooks.WxCard
+	return append(hooks[:len(hooks):len(hooks)], wxcard.Hooks[:]...)
+}
+
+// Interceptors returns the client interceptors.
+func (c *WxCardClient) Interceptors() []Interceptor {
+	inters := c.inters.WxCard
+	return append(inters[:len(inters):len(inters)], wxcard.Interceptors[:]...)
+}
+
+func (c *WxCardClient) mutate(ctx context.Context, m *WxCardMutation) (Value, error) {
+	switch m.Op() {
+	case OpCreate:
+		return (&WxCardCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdate:
+		return (&WxCardUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdateOne:
+		return (&WxCardUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpDelete, OpDeleteOne:
+		return (&WxCardDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
+	default:
+		return nil, fmt.Errorf("ent: unknown WxCard mutation op: %q", m.Op())
+	}
+}
+
+// WxCardUserClient is a client for the WxCardUser schema.
+type WxCardUserClient struct {
+	config
+}
+
+// NewWxCardUserClient returns a client for the WxCardUser from the given config.
+func NewWxCardUserClient(c config) *WxCardUserClient {
+	return &WxCardUserClient{config: c}
+}
+
+// Use adds a list of mutation hooks to the hooks stack.
+// A call to `Use(f, g, h)` equals to `wxcarduser.Hooks(f(g(h())))`.
+func (c *WxCardUserClient) Use(hooks ...Hook) {
+	c.hooks.WxCardUser = append(c.hooks.WxCardUser, hooks...)
+}
+
+// Intercept adds a list of query interceptors to the interceptors stack.
+// A call to `Intercept(f, g, h)` equals to `wxcarduser.Intercept(f(g(h())))`.
+func (c *WxCardUserClient) Intercept(interceptors ...Interceptor) {
+	c.inters.WxCardUser = append(c.inters.WxCardUser, interceptors...)
+}
+
+// Create returns a builder for creating a WxCardUser entity.
+func (c *WxCardUserClient) Create() *WxCardUserCreate {
+	mutation := newWxCardUserMutation(c.config, OpCreate)
+	return &WxCardUserCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// CreateBulk returns a builder for creating a bulk of WxCardUser entities.
+func (c *WxCardUserClient) CreateBulk(builders ...*WxCardUserCreate) *WxCardUserCreateBulk {
+	return &WxCardUserCreateBulk{config: c.config, builders: builders}
+}
+
+// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
+// a builder and applies setFunc on it.
+func (c *WxCardUserClient) MapCreateBulk(slice any, setFunc func(*WxCardUserCreate, int)) *WxCardUserCreateBulk {
+	rv := reflect.ValueOf(slice)
+	if rv.Kind() != reflect.Slice {
+		return &WxCardUserCreateBulk{err: fmt.Errorf("calling to WxCardUserClient.MapCreateBulk with wrong type %T, need slice", slice)}
+	}
+	builders := make([]*WxCardUserCreate, rv.Len())
+	for i := 0; i < rv.Len(); i++ {
+		builders[i] = c.Create()
+		setFunc(builders[i], i)
+	}
+	return &WxCardUserCreateBulk{config: c.config, builders: builders}
+}
+
+// Update returns an update builder for WxCardUser.
+func (c *WxCardUserClient) Update() *WxCardUserUpdate {
+	mutation := newWxCardUserMutation(c.config, OpUpdate)
+	return &WxCardUserUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOne returns an update builder for the given entity.
+func (c *WxCardUserClient) UpdateOne(wcu *WxCardUser) *WxCardUserUpdateOne {
+	mutation := newWxCardUserMutation(c.config, OpUpdateOne, withWxCardUser(wcu))
+	return &WxCardUserUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOneID returns an update builder for the given id.
+func (c *WxCardUserClient) UpdateOneID(id uint64) *WxCardUserUpdateOne {
+	mutation := newWxCardUserMutation(c.config, OpUpdateOne, withWxCardUserID(id))
+	return &WxCardUserUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// Delete returns a delete builder for WxCardUser.
+func (c *WxCardUserClient) Delete() *WxCardUserDelete {
+	mutation := newWxCardUserMutation(c.config, OpDelete)
+	return &WxCardUserDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// DeleteOne returns a builder for deleting the given entity.
+func (c *WxCardUserClient) DeleteOne(wcu *WxCardUser) *WxCardUserDeleteOne {
+	return c.DeleteOneID(wcu.ID)
+}
+
+// DeleteOneID returns a builder for deleting the given entity by its id.
+func (c *WxCardUserClient) DeleteOneID(id uint64) *WxCardUserDeleteOne {
+	builder := c.Delete().Where(wxcarduser.ID(id))
+	builder.mutation.id = &id
+	builder.mutation.op = OpDeleteOne
+	return &WxCardUserDeleteOne{builder}
+}
+
+// Query returns a query builder for WxCardUser.
+func (c *WxCardUserClient) Query() *WxCardUserQuery {
+	return &WxCardUserQuery{
+		config: c.config,
+		ctx:    &QueryContext{Type: TypeWxCardUser},
+		inters: c.Interceptors(),
+	}
+}
+
+// Get returns a WxCardUser entity by its id.
+func (c *WxCardUserClient) Get(ctx context.Context, id uint64) (*WxCardUser, error) {
+	return c.Query().Where(wxcarduser.ID(id)).Only(ctx)
+}
+
+// GetX is like Get, but panics if an error occurs.
+func (c *WxCardUserClient) GetX(ctx context.Context, id uint64) *WxCardUser {
+	obj, err := c.Get(ctx, id)
+	if err != nil {
+		panic(err)
+	}
+	return obj
+}
+
+// Hooks returns the client hooks.
+func (c *WxCardUserClient) Hooks() []Hook {
+	hooks := c.hooks.WxCardUser
+	return append(hooks[:len(hooks):len(hooks)], wxcarduser.Hooks[:]...)
+}
+
+// Interceptors returns the client interceptors.
+func (c *WxCardUserClient) Interceptors() []Interceptor {
+	inters := c.inters.WxCardUser
+	return append(inters[:len(inters):len(inters)], wxcarduser.Interceptors[:]...)
+}
+
+func (c *WxCardUserClient) mutate(ctx context.Context, m *WxCardUserMutation) (Value, error) {
+	switch m.Op() {
+	case OpCreate:
+		return (&WxCardUserCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdate:
+		return (&WxCardUserUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdateOne:
+		return (&WxCardUserUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpDelete, OpDeleteOne:
+		return (&WxCardUserDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
+	default:
+		return nil, fmt.Errorf("ent: unknown WxCardUser mutation op: %q", m.Op())
+	}
+}
+
+// WxCardVisitClient is a client for the WxCardVisit schema.
+type WxCardVisitClient struct {
+	config
+}
+
+// NewWxCardVisitClient returns a client for the WxCardVisit from the given config.
+func NewWxCardVisitClient(c config) *WxCardVisitClient {
+	return &WxCardVisitClient{config: c}
+}
+
+// Use adds a list of mutation hooks to the hooks stack.
+// A call to `Use(f, g, h)` equals to `wxcardvisit.Hooks(f(g(h())))`.
+func (c *WxCardVisitClient) Use(hooks ...Hook) {
+	c.hooks.WxCardVisit = append(c.hooks.WxCardVisit, hooks...)
+}
+
+// Intercept adds a list of query interceptors to the interceptors stack.
+// A call to `Intercept(f, g, h)` equals to `wxcardvisit.Intercept(f(g(h())))`.
+func (c *WxCardVisitClient) Intercept(interceptors ...Interceptor) {
+	c.inters.WxCardVisit = append(c.inters.WxCardVisit, interceptors...)
+}
+
+// Create returns a builder for creating a WxCardVisit entity.
+func (c *WxCardVisitClient) Create() *WxCardVisitCreate {
+	mutation := newWxCardVisitMutation(c.config, OpCreate)
+	return &WxCardVisitCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// CreateBulk returns a builder for creating a bulk of WxCardVisit entities.
+func (c *WxCardVisitClient) CreateBulk(builders ...*WxCardVisitCreate) *WxCardVisitCreateBulk {
+	return &WxCardVisitCreateBulk{config: c.config, builders: builders}
+}
+
+// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
+// a builder and applies setFunc on it.
+func (c *WxCardVisitClient) MapCreateBulk(slice any, setFunc func(*WxCardVisitCreate, int)) *WxCardVisitCreateBulk {
+	rv := reflect.ValueOf(slice)
+	if rv.Kind() != reflect.Slice {
+		return &WxCardVisitCreateBulk{err: fmt.Errorf("calling to WxCardVisitClient.MapCreateBulk with wrong type %T, need slice", slice)}
+	}
+	builders := make([]*WxCardVisitCreate, rv.Len())
+	for i := 0; i < rv.Len(); i++ {
+		builders[i] = c.Create()
+		setFunc(builders[i], i)
+	}
+	return &WxCardVisitCreateBulk{config: c.config, builders: builders}
+}
+
+// Update returns an update builder for WxCardVisit.
+func (c *WxCardVisitClient) Update() *WxCardVisitUpdate {
+	mutation := newWxCardVisitMutation(c.config, OpUpdate)
+	return &WxCardVisitUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOne returns an update builder for the given entity.
+func (c *WxCardVisitClient) UpdateOne(wcv *WxCardVisit) *WxCardVisitUpdateOne {
+	mutation := newWxCardVisitMutation(c.config, OpUpdateOne, withWxCardVisit(wcv))
+	return &WxCardVisitUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOneID returns an update builder for the given id.
+func (c *WxCardVisitClient) UpdateOneID(id uint64) *WxCardVisitUpdateOne {
+	mutation := newWxCardVisitMutation(c.config, OpUpdateOne, withWxCardVisitID(id))
+	return &WxCardVisitUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// Delete returns a delete builder for WxCardVisit.
+func (c *WxCardVisitClient) Delete() *WxCardVisitDelete {
+	mutation := newWxCardVisitMutation(c.config, OpDelete)
+	return &WxCardVisitDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// DeleteOne returns a builder for deleting the given entity.
+func (c *WxCardVisitClient) DeleteOne(wcv *WxCardVisit) *WxCardVisitDeleteOne {
+	return c.DeleteOneID(wcv.ID)
+}
+
+// DeleteOneID returns a builder for deleting the given entity by its id.
+func (c *WxCardVisitClient) DeleteOneID(id uint64) *WxCardVisitDeleteOne {
+	builder := c.Delete().Where(wxcardvisit.ID(id))
+	builder.mutation.id = &id
+	builder.mutation.op = OpDeleteOne
+	return &WxCardVisitDeleteOne{builder}
+}
+
+// Query returns a query builder for WxCardVisit.
+func (c *WxCardVisitClient) Query() *WxCardVisitQuery {
+	return &WxCardVisitQuery{
+		config: c.config,
+		ctx:    &QueryContext{Type: TypeWxCardVisit},
+		inters: c.Interceptors(),
+	}
+}
+
+// Get returns a WxCardVisit entity by its id.
+func (c *WxCardVisitClient) Get(ctx context.Context, id uint64) (*WxCardVisit, error) {
+	return c.Query().Where(wxcardvisit.ID(id)).Only(ctx)
+}
+
+// GetX is like Get, but panics if an error occurs.
+func (c *WxCardVisitClient) GetX(ctx context.Context, id uint64) *WxCardVisit {
+	obj, err := c.Get(ctx, id)
+	if err != nil {
+		panic(err)
+	}
+	return obj
+}
+
+// Hooks returns the client hooks.
+func (c *WxCardVisitClient) Hooks() []Hook {
+	hooks := c.hooks.WxCardVisit
+	return append(hooks[:len(hooks):len(hooks)], wxcardvisit.Hooks[:]...)
+}
+
+// Interceptors returns the client interceptors.
+func (c *WxCardVisitClient) Interceptors() []Interceptor {
+	inters := c.inters.WxCardVisit
+	return append(inters[:len(inters):len(inters)], wxcardvisit.Interceptors[:]...)
+}
+
+func (c *WxCardVisitClient) mutate(ctx context.Context, m *WxCardVisitMutation) (Value, error) {
+	switch m.Op() {
+	case OpCreate:
+		return (&WxCardVisitCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdate:
+		return (&WxCardVisitUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdateOne:
+		return (&WxCardVisitUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpDelete, OpDeleteOne:
+		return (&WxCardVisitDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
+	default:
+		return nil, fmt.Errorf("ent: unknown WxCardVisit mutation op: %q", m.Op())
+	}
+}
+
 // hooks and interceptors per client, for fast access.
 type (
 	hooks struct {
-		Agent, AgentBase, BatchMsg, Category, Contact, Employee, EmployeeConfig, Label,
-		LabelRelationship, Message, MessageRecords, Msg, Server, SopNode, SopStage,
-		SopTask, Token, Tutorial, WorkExperience, Wx []ent.Hook
+		Agent, AgentBase, BatchMsg, Category, ChatRecords, ChatSession, Contact,
+		Employee, EmployeeConfig, Label, LabelRelationship, Message, MessageRecords,
+		Msg, Server, SopNode, SopStage, SopTask, Token, Tutorial, WorkExperience, Wx,
+		WxCard, WxCardUser, WxCardVisit []ent.Hook
 	}
 	inters struct {
-		Agent, AgentBase, BatchMsg, Category, Contact, Employee, EmployeeConfig, Label,
-		LabelRelationship, Message, MessageRecords, Msg, Server, SopNode, SopStage,
-		SopTask, Token, Tutorial, WorkExperience, Wx []ent.Interceptor
+		Agent, AgentBase, BatchMsg, Category, ChatRecords, ChatSession, Contact,
+		Employee, EmployeeConfig, Label, LabelRelationship, Message, MessageRecords,
+		Msg, Server, SopNode, SopStage, SopTask, Token, Tutorial, WorkExperience, Wx,
+		WxCard, WxCardUser, WxCardVisit []ent.Interceptor
 	}
 )
 

+ 23 - 1
ent/employee.go

@@ -53,6 +53,10 @@ type Employee struct {
 	OrganizationID uint64 `json:"organization_id,omitempty"`
 	// category_id | 分类ID
 	CategoryID uint64 `json:"category_id,omitempty"`
+	// api_base
+	APIBase string `json:"api_base,omitempty"`
+	// api_key
+	APIKey string `json:"api_key,omitempty"`
 	// Edges holds the relations/edges for other nodes in the graph.
 	// The values are being populated by the EmployeeQuery when eager-loading is set.
 	Edges        EmployeeEdges `json:"edges"`
@@ -95,7 +99,7 @@ func (*Employee) scanValues(columns []string) ([]any, error) {
 		switch columns[i] {
 		case employee.FieldID, employee.FieldHireCount, employee.FieldServiceCount, employee.FieldAchievementCount, employee.FieldOrganizationID, employee.FieldCategoryID:
 			values[i] = new(sql.NullInt64)
-		case employee.FieldTitle, employee.FieldAvatar, employee.FieldTags, employee.FieldIntro, employee.FieldEstimate, employee.FieldSkill, employee.FieldAbilityType, employee.FieldScene, employee.FieldSwitchIn, employee.FieldVideoURL:
+		case employee.FieldTitle, employee.FieldAvatar, employee.FieldTags, employee.FieldIntro, employee.FieldEstimate, employee.FieldSkill, employee.FieldAbilityType, employee.FieldScene, employee.FieldSwitchIn, employee.FieldVideoURL, employee.FieldAPIBase, employee.FieldAPIKey:
 			values[i] = new(sql.NullString)
 		case employee.FieldCreatedAt, employee.FieldUpdatedAt, employee.FieldDeletedAt:
 			values[i] = new(sql.NullTime)
@@ -228,6 +232,18 @@ func (e *Employee) assignValues(columns []string, values []any) error {
 			} else if value.Valid {
 				e.CategoryID = uint64(value.Int64)
 			}
+		case employee.FieldAPIBase:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field api_base", values[i])
+			} else if value.Valid {
+				e.APIBase = value.String
+			}
+		case employee.FieldAPIKey:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field api_key", values[i])
+			} else if value.Valid {
+				e.APIKey = value.String
+			}
 		default:
 			e.selectValues.Set(columns[i], values[i])
 		}
@@ -327,6 +343,12 @@ func (e *Employee) String() string {
 	builder.WriteString(", ")
 	builder.WriteString("category_id=")
 	builder.WriteString(fmt.Sprintf("%v", e.CategoryID))
+	builder.WriteString(", ")
+	builder.WriteString("api_base=")
+	builder.WriteString(e.APIBase)
+	builder.WriteString(", ")
+	builder.WriteString("api_key=")
+	builder.WriteString(e.APIKey)
 	builder.WriteByte(')')
 	return builder.String()
 }

+ 20 - 0
ent/employee/employee.go

@@ -51,6 +51,10 @@ const (
 	FieldOrganizationID = "organization_id"
 	// FieldCategoryID holds the string denoting the category_id field in the database.
 	FieldCategoryID = "category_id"
+	// FieldAPIBase holds the string denoting the api_base field in the database.
+	FieldAPIBase = "api_base"
+	// FieldAPIKey holds the string denoting the api_key field in the database.
+	FieldAPIKey = "api_key"
 	// EdgeEmWorkExperiences holds the string denoting the em_work_experiences edge name in mutations.
 	EdgeEmWorkExperiences = "em_work_experiences"
 	// EdgeEmTutorial holds the string denoting the em_tutorial edge name in mutations.
@@ -94,6 +98,8 @@ var Columns = []string{
 	FieldVideoURL,
 	FieldOrganizationID,
 	FieldCategoryID,
+	FieldAPIBase,
+	FieldAPIKey,
 }
 
 // ValidColumn reports if the column name is valid (part of the table columns).
@@ -164,6 +170,10 @@ var (
 	OrganizationIDValidator func(uint64) error
 	// CategoryIDValidator is a validator for the "category_id" field. It is called by the builders before save.
 	CategoryIDValidator func(uint64) error
+	// DefaultAPIBase holds the default value on creation for the "api_base" field.
+	DefaultAPIBase string
+	// DefaultAPIKey holds the default value on creation for the "api_key" field.
+	DefaultAPIKey string
 )
 
 // OrderOption defines the ordering options for the Employee queries.
@@ -264,6 +274,16 @@ func ByCategoryID(opts ...sql.OrderTermOption) OrderOption {
 	return sql.OrderByField(FieldCategoryID, opts...).ToFunc()
 }
 
+// ByAPIBase orders the results by the api_base field.
+func ByAPIBase(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldAPIBase, opts...).ToFunc()
+}
+
+// ByAPIKey orders the results by the api_key field.
+func ByAPIKey(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldAPIKey, opts...).ToFunc()
+}
+
 // ByEmWorkExperiencesCount orders the results by em_work_experiences count.
 func ByEmWorkExperiencesCount(opts ...sql.OrderTermOption) OrderOption {
 	return func(s *sql.Selector) {

+ 140 - 0
ent/employee/where.go

@@ -145,6 +145,16 @@ func CategoryID(v uint64) predicate.Employee {
 	return predicate.Employee(sql.FieldEQ(FieldCategoryID, v))
 }
 
+// APIBase applies equality check predicate on the "api_base" field. It's identical to APIBaseEQ.
+func APIBase(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldAPIBase, v))
+}
+
+// APIKey applies equality check predicate on the "api_key" field. It's identical to APIKeyEQ.
+func APIKey(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldAPIKey, v))
+}
+
 // CreatedAtEQ applies the EQ predicate on the "created_at" field.
 func CreatedAtEQ(v time.Time) predicate.Employee {
 	return predicate.Employee(sql.FieldEQ(FieldCreatedAt, v))
@@ -1125,6 +1135,136 @@ func CategoryIDLTE(v uint64) predicate.Employee {
 	return predicate.Employee(sql.FieldLTE(FieldCategoryID, v))
 }
 
+// APIBaseEQ applies the EQ predicate on the "api_base" field.
+func APIBaseEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldAPIBase, v))
+}
+
+// APIBaseNEQ applies the NEQ predicate on the "api_base" field.
+func APIBaseNEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldAPIBase, v))
+}
+
+// APIBaseIn applies the In predicate on the "api_base" field.
+func APIBaseIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldAPIBase, vs...))
+}
+
+// APIBaseNotIn applies the NotIn predicate on the "api_base" field.
+func APIBaseNotIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldAPIBase, vs...))
+}
+
+// APIBaseGT applies the GT predicate on the "api_base" field.
+func APIBaseGT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldAPIBase, v))
+}
+
+// APIBaseGTE applies the GTE predicate on the "api_base" field.
+func APIBaseGTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldAPIBase, v))
+}
+
+// APIBaseLT applies the LT predicate on the "api_base" field.
+func APIBaseLT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldAPIBase, v))
+}
+
+// APIBaseLTE applies the LTE predicate on the "api_base" field.
+func APIBaseLTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldAPIBase, v))
+}
+
+// APIBaseContains applies the Contains predicate on the "api_base" field.
+func APIBaseContains(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContains(FieldAPIBase, v))
+}
+
+// APIBaseHasPrefix applies the HasPrefix predicate on the "api_base" field.
+func APIBaseHasPrefix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasPrefix(FieldAPIBase, v))
+}
+
+// APIBaseHasSuffix applies the HasSuffix predicate on the "api_base" field.
+func APIBaseHasSuffix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasSuffix(FieldAPIBase, v))
+}
+
+// APIBaseEqualFold applies the EqualFold predicate on the "api_base" field.
+func APIBaseEqualFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEqualFold(FieldAPIBase, v))
+}
+
+// APIBaseContainsFold applies the ContainsFold predicate on the "api_base" field.
+func APIBaseContainsFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContainsFold(FieldAPIBase, v))
+}
+
+// APIKeyEQ applies the EQ predicate on the "api_key" field.
+func APIKeyEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldAPIKey, v))
+}
+
+// APIKeyNEQ applies the NEQ predicate on the "api_key" field.
+func APIKeyNEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldAPIKey, v))
+}
+
+// APIKeyIn applies the In predicate on the "api_key" field.
+func APIKeyIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldAPIKey, vs...))
+}
+
+// APIKeyNotIn applies the NotIn predicate on the "api_key" field.
+func APIKeyNotIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldAPIKey, vs...))
+}
+
+// APIKeyGT applies the GT predicate on the "api_key" field.
+func APIKeyGT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldAPIKey, v))
+}
+
+// APIKeyGTE applies the GTE predicate on the "api_key" field.
+func APIKeyGTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldAPIKey, v))
+}
+
+// APIKeyLT applies the LT predicate on the "api_key" field.
+func APIKeyLT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldAPIKey, v))
+}
+
+// APIKeyLTE applies the LTE predicate on the "api_key" field.
+func APIKeyLTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldAPIKey, v))
+}
+
+// APIKeyContains applies the Contains predicate on the "api_key" field.
+func APIKeyContains(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContains(FieldAPIKey, v))
+}
+
+// APIKeyHasPrefix applies the HasPrefix predicate on the "api_key" field.
+func APIKeyHasPrefix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasPrefix(FieldAPIKey, v))
+}
+
+// APIKeyHasSuffix applies the HasSuffix predicate on the "api_key" field.
+func APIKeyHasSuffix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasSuffix(FieldAPIKey, v))
+}
+
+// APIKeyEqualFold applies the EqualFold predicate on the "api_key" field.
+func APIKeyEqualFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEqualFold(FieldAPIKey, v))
+}
+
+// APIKeyContainsFold applies the ContainsFold predicate on the "api_key" field.
+func APIKeyContainsFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContainsFold(FieldAPIKey, v))
+}
+
 // HasEmWorkExperiences applies the HasEdge predicate on the "em_work_experiences" edge.
 func HasEmWorkExperiences() predicate.Employee {
 	return predicate.Employee(func(s *sql.Selector) {

+ 130 - 0
ent/employee_create.go

@@ -236,6 +236,34 @@ func (ec *EmployeeCreate) SetCategoryID(u uint64) *EmployeeCreate {
 	return ec
 }
 
+// SetAPIBase sets the "api_base" field.
+func (ec *EmployeeCreate) SetAPIBase(s string) *EmployeeCreate {
+	ec.mutation.SetAPIBase(s)
+	return ec
+}
+
+// SetNillableAPIBase sets the "api_base" field if the given value is not nil.
+func (ec *EmployeeCreate) SetNillableAPIBase(s *string) *EmployeeCreate {
+	if s != nil {
+		ec.SetAPIBase(*s)
+	}
+	return ec
+}
+
+// SetAPIKey sets the "api_key" field.
+func (ec *EmployeeCreate) SetAPIKey(s string) *EmployeeCreate {
+	ec.mutation.SetAPIKey(s)
+	return ec
+}
+
+// SetNillableAPIKey sets the "api_key" field if the given value is not nil.
+func (ec *EmployeeCreate) SetNillableAPIKey(s *string) *EmployeeCreate {
+	if s != nil {
+		ec.SetAPIKey(*s)
+	}
+	return ec
+}
+
 // SetID sets the "id" field.
 func (ec *EmployeeCreate) SetID(u uint64) *EmployeeCreate {
 	ec.mutation.SetID(u)
@@ -363,6 +391,14 @@ func (ec *EmployeeCreate) defaults() error {
 		v := employee.DefaultVideoURL
 		ec.mutation.SetVideoURL(v)
 	}
+	if _, ok := ec.mutation.APIBase(); !ok {
+		v := employee.DefaultAPIBase
+		ec.mutation.SetAPIBase(v)
+	}
+	if _, ok := ec.mutation.APIKey(); !ok {
+		v := employee.DefaultAPIKey
+		ec.mutation.SetAPIKey(v)
+	}
 	return nil
 }
 
@@ -479,6 +515,12 @@ func (ec *EmployeeCreate) check() error {
 			return &ValidationError{Name: "category_id", err: fmt.Errorf(`ent: validator failed for field "Employee.category_id": %w`, err)}
 		}
 	}
+	if _, ok := ec.mutation.APIBase(); !ok {
+		return &ValidationError{Name: "api_base", err: errors.New(`ent: missing required field "Employee.api_base"`)}
+	}
+	if _, ok := ec.mutation.APIKey(); !ok {
+		return &ValidationError{Name: "api_key", err: errors.New(`ent: missing required field "Employee.api_key"`)}
+	}
 	return nil
 }
 
@@ -584,6 +626,14 @@ func (ec *EmployeeCreate) createSpec() (*Employee, *sqlgraph.CreateSpec) {
 		_spec.SetField(employee.FieldCategoryID, field.TypeUint64, value)
 		_node.CategoryID = value
 	}
+	if value, ok := ec.mutation.APIBase(); ok {
+		_spec.SetField(employee.FieldAPIBase, field.TypeString, value)
+		_node.APIBase = value
+	}
+	if value, ok := ec.mutation.APIKey(); ok {
+		_spec.SetField(employee.FieldAPIKey, field.TypeString, value)
+		_node.APIKey = value
+	}
 	if nodes := ec.mutation.EmWorkExperiencesIDs(); len(nodes) > 0 {
 		edge := &sqlgraph.EdgeSpec{
 			Rel:     sqlgraph.O2M,
@@ -908,6 +958,30 @@ func (u *EmployeeUpsert) AddCategoryID(v uint64) *EmployeeUpsert {
 	return u
 }
 
+// SetAPIBase sets the "api_base" field.
+func (u *EmployeeUpsert) SetAPIBase(v string) *EmployeeUpsert {
+	u.Set(employee.FieldAPIBase, v)
+	return u
+}
+
+// UpdateAPIBase sets the "api_base" field to the value that was provided on create.
+func (u *EmployeeUpsert) UpdateAPIBase() *EmployeeUpsert {
+	u.SetExcluded(employee.FieldAPIBase)
+	return u
+}
+
+// SetAPIKey sets the "api_key" field.
+func (u *EmployeeUpsert) SetAPIKey(v string) *EmployeeUpsert {
+	u.Set(employee.FieldAPIKey, v)
+	return u
+}
+
+// UpdateAPIKey sets the "api_key" field to the value that was provided on create.
+func (u *EmployeeUpsert) UpdateAPIKey() *EmployeeUpsert {
+	u.SetExcluded(employee.FieldAPIKey)
+	return u
+}
+
 // UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field.
 // Using this option is equivalent to using:
 //
@@ -1239,6 +1313,34 @@ func (u *EmployeeUpsertOne) UpdateCategoryID() *EmployeeUpsertOne {
 	})
 }
 
+// SetAPIBase sets the "api_base" field.
+func (u *EmployeeUpsertOne) SetAPIBase(v string) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetAPIBase(v)
+	})
+}
+
+// UpdateAPIBase sets the "api_base" field to the value that was provided on create.
+func (u *EmployeeUpsertOne) UpdateAPIBase() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateAPIBase()
+	})
+}
+
+// SetAPIKey sets the "api_key" field.
+func (u *EmployeeUpsertOne) SetAPIKey(v string) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetAPIKey(v)
+	})
+}
+
+// UpdateAPIKey sets the "api_key" field to the value that was provided on create.
+func (u *EmployeeUpsertOne) UpdateAPIKey() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateAPIKey()
+	})
+}
+
 // Exec executes the query.
 func (u *EmployeeUpsertOne) Exec(ctx context.Context) error {
 	if len(u.create.conflict) == 0 {
@@ -1736,6 +1838,34 @@ func (u *EmployeeUpsertBulk) UpdateCategoryID() *EmployeeUpsertBulk {
 	})
 }
 
+// SetAPIBase sets the "api_base" field.
+func (u *EmployeeUpsertBulk) SetAPIBase(v string) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetAPIBase(v)
+	})
+}
+
+// UpdateAPIBase sets the "api_base" field to the value that was provided on create.
+func (u *EmployeeUpsertBulk) UpdateAPIBase() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateAPIBase()
+	})
+}
+
+// SetAPIKey sets the "api_key" field.
+func (u *EmployeeUpsertBulk) SetAPIKey(v string) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetAPIKey(v)
+	})
+}
+
+// UpdateAPIKey sets the "api_key" field to the value that was provided on create.
+func (u *EmployeeUpsertBulk) UpdateAPIKey() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateAPIKey()
+	})
+}
+
 // Exec executes the query.
 func (u *EmployeeUpsertBulk) Exec(ctx context.Context) error {
 	if u.create.err != nil {

+ 68 - 0
ent/employee_update.go

@@ -301,6 +301,34 @@ func (eu *EmployeeUpdate) AddCategoryID(u int64) *EmployeeUpdate {
 	return eu
 }
 
+// SetAPIBase sets the "api_base" field.
+func (eu *EmployeeUpdate) SetAPIBase(s string) *EmployeeUpdate {
+	eu.mutation.SetAPIBase(s)
+	return eu
+}
+
+// SetNillableAPIBase sets the "api_base" field if the given value is not nil.
+func (eu *EmployeeUpdate) SetNillableAPIBase(s *string) *EmployeeUpdate {
+	if s != nil {
+		eu.SetAPIBase(*s)
+	}
+	return eu
+}
+
+// SetAPIKey sets the "api_key" field.
+func (eu *EmployeeUpdate) SetAPIKey(s string) *EmployeeUpdate {
+	eu.mutation.SetAPIKey(s)
+	return eu
+}
+
+// SetNillableAPIKey sets the "api_key" field if the given value is not nil.
+func (eu *EmployeeUpdate) SetNillableAPIKey(s *string) *EmployeeUpdate {
+	if s != nil {
+		eu.SetAPIKey(*s)
+	}
+	return eu
+}
+
 // AddEmWorkExperienceIDs adds the "em_work_experiences" edge to the WorkExperience entity by IDs.
 func (eu *EmployeeUpdate) AddEmWorkExperienceIDs(ids ...uint64) *EmployeeUpdate {
 	eu.mutation.AddEmWorkExperienceIDs(ids...)
@@ -566,6 +594,12 @@ func (eu *EmployeeUpdate) sqlSave(ctx context.Context) (n int, err error) {
 	if value, ok := eu.mutation.AddedCategoryID(); ok {
 		_spec.AddField(employee.FieldCategoryID, field.TypeUint64, value)
 	}
+	if value, ok := eu.mutation.APIBase(); ok {
+		_spec.SetField(employee.FieldAPIBase, field.TypeString, value)
+	}
+	if value, ok := eu.mutation.APIKey(); ok {
+		_spec.SetField(employee.FieldAPIKey, field.TypeString, value)
+	}
 	if eu.mutation.EmWorkExperiencesCleared() {
 		edge := &sqlgraph.EdgeSpec{
 			Rel:     sqlgraph.O2M,
@@ -947,6 +981,34 @@ func (euo *EmployeeUpdateOne) AddCategoryID(u int64) *EmployeeUpdateOne {
 	return euo
 }
 
+// SetAPIBase sets the "api_base" field.
+func (euo *EmployeeUpdateOne) SetAPIBase(s string) *EmployeeUpdateOne {
+	euo.mutation.SetAPIBase(s)
+	return euo
+}
+
+// SetNillableAPIBase sets the "api_base" field if the given value is not nil.
+func (euo *EmployeeUpdateOne) SetNillableAPIBase(s *string) *EmployeeUpdateOne {
+	if s != nil {
+		euo.SetAPIBase(*s)
+	}
+	return euo
+}
+
+// SetAPIKey sets the "api_key" field.
+func (euo *EmployeeUpdateOne) SetAPIKey(s string) *EmployeeUpdateOne {
+	euo.mutation.SetAPIKey(s)
+	return euo
+}
+
+// SetNillableAPIKey sets the "api_key" field if the given value is not nil.
+func (euo *EmployeeUpdateOne) SetNillableAPIKey(s *string) *EmployeeUpdateOne {
+	if s != nil {
+		euo.SetAPIKey(*s)
+	}
+	return euo
+}
+
 // AddEmWorkExperienceIDs adds the "em_work_experiences" edge to the WorkExperience entity by IDs.
 func (euo *EmployeeUpdateOne) AddEmWorkExperienceIDs(ids ...uint64) *EmployeeUpdateOne {
 	euo.mutation.AddEmWorkExperienceIDs(ids...)
@@ -1242,6 +1304,12 @@ func (euo *EmployeeUpdateOne) sqlSave(ctx context.Context) (_node *Employee, err
 	if value, ok := euo.mutation.AddedCategoryID(); ok {
 		_spec.AddField(employee.FieldCategoryID, field.TypeUint64, value)
 	}
+	if value, ok := euo.mutation.APIBase(); ok {
+		_spec.SetField(employee.FieldAPIBase, field.TypeString, value)
+	}
+	if value, ok := euo.mutation.APIKey(); ok {
+		_spec.SetField(employee.FieldAPIKey, field.TypeString, value)
+	}
 	if euo.mutation.EmWorkExperiencesCleared() {
 		edge := &sqlgraph.EdgeSpec{
 			Rel:     sqlgraph.O2M,

+ 10 - 0
ent/ent.go

@@ -12,6 +12,8 @@ import (
 	"wechat-api/ent/agentbase"
 	"wechat-api/ent/batchmsg"
 	"wechat-api/ent/category"
+	"wechat-api/ent/chatrecords"
+	"wechat-api/ent/chatsession"
 	"wechat-api/ent/contact"
 	"wechat-api/ent/employee"
 	"wechat-api/ent/employeeconfig"
@@ -28,6 +30,9 @@ import (
 	"wechat-api/ent/tutorial"
 	"wechat-api/ent/workexperience"
 	"wechat-api/ent/wx"
+	"wechat-api/ent/wxcard"
+	"wechat-api/ent/wxcarduser"
+	"wechat-api/ent/wxcardvisit"
 
 	"entgo.io/ent"
 	"entgo.io/ent/dialect/sql"
@@ -96,6 +101,8 @@ func checkColumn(table, column string) error {
 			agentbase.Table:         agentbase.ValidColumn,
 			batchmsg.Table:          batchmsg.ValidColumn,
 			category.Table:          category.ValidColumn,
+			chatrecords.Table:       chatrecords.ValidColumn,
+			chatsession.Table:       chatsession.ValidColumn,
 			contact.Table:           contact.ValidColumn,
 			employee.Table:          employee.ValidColumn,
 			employeeconfig.Table:    employeeconfig.ValidColumn,
@@ -112,6 +119,9 @@ func checkColumn(table, column string) error {
 			tutorial.Table:          tutorial.ValidColumn,
 			workexperience.Table:    workexperience.ValidColumn,
 			wx.Table:                wx.ValidColumn,
+			wxcard.Table:            wxcard.ValidColumn,
+			wxcarduser.Table:        wxcarduser.ValidColumn,
+			wxcardvisit.Table:       wxcardvisit.ValidColumn,
 		})
 	})
 	return columnCheck(table, column)

+ 60 - 0
ent/hook/hook.go

@@ -56,6 +56,30 @@ func (f CategoryFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, er
 	return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.CategoryMutation", m)
 }
 
+// The ChatRecordsFunc type is an adapter to allow the use of ordinary
+// function as ChatRecords mutator.
+type ChatRecordsFunc func(context.Context, *ent.ChatRecordsMutation) (ent.Value, error)
+
+// Mutate calls f(ctx, m).
+func (f ChatRecordsFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
+	if mv, ok := m.(*ent.ChatRecordsMutation); ok {
+		return f(ctx, mv)
+	}
+	return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ChatRecordsMutation", m)
+}
+
+// The ChatSessionFunc type is an adapter to allow the use of ordinary
+// function as ChatSession mutator.
+type ChatSessionFunc func(context.Context, *ent.ChatSessionMutation) (ent.Value, error)
+
+// Mutate calls f(ctx, m).
+func (f ChatSessionFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
+	if mv, ok := m.(*ent.ChatSessionMutation); ok {
+		return f(ctx, mv)
+	}
+	return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ChatSessionMutation", m)
+}
+
 // The ContactFunc type is an adapter to allow the use of ordinary
 // function as Contact mutator.
 type ContactFunc func(context.Context, *ent.ContactMutation) (ent.Value, error)
@@ -248,6 +272,42 @@ func (f WxFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
 	return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.WxMutation", m)
 }
 
+// The WxCardFunc type is an adapter to allow the use of ordinary
+// function as WxCard mutator.
+type WxCardFunc func(context.Context, *ent.WxCardMutation) (ent.Value, error)
+
+// Mutate calls f(ctx, m).
+func (f WxCardFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
+	if mv, ok := m.(*ent.WxCardMutation); ok {
+		return f(ctx, mv)
+	}
+	return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.WxCardMutation", m)
+}
+
+// The WxCardUserFunc type is an adapter to allow the use of ordinary
+// function as WxCardUser mutator.
+type WxCardUserFunc func(context.Context, *ent.WxCardUserMutation) (ent.Value, error)
+
+// Mutate calls f(ctx, m).
+func (f WxCardUserFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
+	if mv, ok := m.(*ent.WxCardUserMutation); ok {
+		return f(ctx, mv)
+	}
+	return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.WxCardUserMutation", m)
+}
+
+// The WxCardVisitFunc type is an adapter to allow the use of ordinary
+// function as WxCardVisit mutator.
+type WxCardVisitFunc func(context.Context, *ent.WxCardVisitMutation) (ent.Value, error)
+
+// Mutate calls f(ctx, m).
+func (f WxCardVisitFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
+	if mv, ok := m.(*ent.WxCardVisitMutation); ok {
+		return f(ctx, mv)
+	}
+	return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.WxCardVisitMutation", m)
+}
+
 // Condition is a hook condition function.
 type Condition func(context.Context, ent.Mutation) bool
 

+ 150 - 0
ent/intercept/intercept.go

@@ -10,6 +10,8 @@ import (
 	"wechat-api/ent/agentbase"
 	"wechat-api/ent/batchmsg"
 	"wechat-api/ent/category"
+	"wechat-api/ent/chatrecords"
+	"wechat-api/ent/chatsession"
 	"wechat-api/ent/contact"
 	"wechat-api/ent/employee"
 	"wechat-api/ent/employeeconfig"
@@ -27,6 +29,9 @@ import (
 	"wechat-api/ent/tutorial"
 	"wechat-api/ent/workexperience"
 	"wechat-api/ent/wx"
+	"wechat-api/ent/wxcard"
+	"wechat-api/ent/wxcarduser"
+	"wechat-api/ent/wxcardvisit"
 
 	"entgo.io/ent/dialect/sql"
 )
@@ -195,6 +200,60 @@ func (f TraverseCategory) Traverse(ctx context.Context, q ent.Query) error {
 	return fmt.Errorf("unexpected query type %T. expect *ent.CategoryQuery", q)
 }
 
+// The ChatRecordsFunc type is an adapter to allow the use of ordinary function as a Querier.
+type ChatRecordsFunc func(context.Context, *ent.ChatRecordsQuery) (ent.Value, error)
+
+// Query calls f(ctx, q).
+func (f ChatRecordsFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
+	if q, ok := q.(*ent.ChatRecordsQuery); ok {
+		return f(ctx, q)
+	}
+	return nil, fmt.Errorf("unexpected query type %T. expect *ent.ChatRecordsQuery", q)
+}
+
+// The TraverseChatRecords type is an adapter to allow the use of ordinary function as Traverser.
+type TraverseChatRecords func(context.Context, *ent.ChatRecordsQuery) error
+
+// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
+func (f TraverseChatRecords) Intercept(next ent.Querier) ent.Querier {
+	return next
+}
+
+// Traverse calls f(ctx, q).
+func (f TraverseChatRecords) Traverse(ctx context.Context, q ent.Query) error {
+	if q, ok := q.(*ent.ChatRecordsQuery); ok {
+		return f(ctx, q)
+	}
+	return fmt.Errorf("unexpected query type %T. expect *ent.ChatRecordsQuery", q)
+}
+
+// The ChatSessionFunc type is an adapter to allow the use of ordinary function as a Querier.
+type ChatSessionFunc func(context.Context, *ent.ChatSessionQuery) (ent.Value, error)
+
+// Query calls f(ctx, q).
+func (f ChatSessionFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
+	if q, ok := q.(*ent.ChatSessionQuery); ok {
+		return f(ctx, q)
+	}
+	return nil, fmt.Errorf("unexpected query type %T. expect *ent.ChatSessionQuery", q)
+}
+
+// The TraverseChatSession type is an adapter to allow the use of ordinary function as Traverser.
+type TraverseChatSession func(context.Context, *ent.ChatSessionQuery) error
+
+// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
+func (f TraverseChatSession) Intercept(next ent.Querier) ent.Querier {
+	return next
+}
+
+// Traverse calls f(ctx, q).
+func (f TraverseChatSession) Traverse(ctx context.Context, q ent.Query) error {
+	if q, ok := q.(*ent.ChatSessionQuery); ok {
+		return f(ctx, q)
+	}
+	return fmt.Errorf("unexpected query type %T. expect *ent.ChatSessionQuery", q)
+}
+
 // The ContactFunc type is an adapter to allow the use of ordinary function as a Querier.
 type ContactFunc func(context.Context, *ent.ContactQuery) (ent.Value, error)
 
@@ -627,6 +686,87 @@ func (f TraverseWx) Traverse(ctx context.Context, q ent.Query) error {
 	return fmt.Errorf("unexpected query type %T. expect *ent.WxQuery", q)
 }
 
+// The WxCardFunc type is an adapter to allow the use of ordinary function as a Querier.
+type WxCardFunc func(context.Context, *ent.WxCardQuery) (ent.Value, error)
+
+// Query calls f(ctx, q).
+func (f WxCardFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
+	if q, ok := q.(*ent.WxCardQuery); ok {
+		return f(ctx, q)
+	}
+	return nil, fmt.Errorf("unexpected query type %T. expect *ent.WxCardQuery", q)
+}
+
+// The TraverseWxCard type is an adapter to allow the use of ordinary function as Traverser.
+type TraverseWxCard func(context.Context, *ent.WxCardQuery) error
+
+// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
+func (f TraverseWxCard) Intercept(next ent.Querier) ent.Querier {
+	return next
+}
+
+// Traverse calls f(ctx, q).
+func (f TraverseWxCard) Traverse(ctx context.Context, q ent.Query) error {
+	if q, ok := q.(*ent.WxCardQuery); ok {
+		return f(ctx, q)
+	}
+	return fmt.Errorf("unexpected query type %T. expect *ent.WxCardQuery", q)
+}
+
+// The WxCardUserFunc type is an adapter to allow the use of ordinary function as a Querier.
+type WxCardUserFunc func(context.Context, *ent.WxCardUserQuery) (ent.Value, error)
+
+// Query calls f(ctx, q).
+func (f WxCardUserFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
+	if q, ok := q.(*ent.WxCardUserQuery); ok {
+		return f(ctx, q)
+	}
+	return nil, fmt.Errorf("unexpected query type %T. expect *ent.WxCardUserQuery", q)
+}
+
+// The TraverseWxCardUser type is an adapter to allow the use of ordinary function as Traverser.
+type TraverseWxCardUser func(context.Context, *ent.WxCardUserQuery) error
+
+// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
+func (f TraverseWxCardUser) Intercept(next ent.Querier) ent.Querier {
+	return next
+}
+
+// Traverse calls f(ctx, q).
+func (f TraverseWxCardUser) Traverse(ctx context.Context, q ent.Query) error {
+	if q, ok := q.(*ent.WxCardUserQuery); ok {
+		return f(ctx, q)
+	}
+	return fmt.Errorf("unexpected query type %T. expect *ent.WxCardUserQuery", q)
+}
+
+// The WxCardVisitFunc type is an adapter to allow the use of ordinary function as a Querier.
+type WxCardVisitFunc func(context.Context, *ent.WxCardVisitQuery) (ent.Value, error)
+
+// Query calls f(ctx, q).
+func (f WxCardVisitFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
+	if q, ok := q.(*ent.WxCardVisitQuery); ok {
+		return f(ctx, q)
+	}
+	return nil, fmt.Errorf("unexpected query type %T. expect *ent.WxCardVisitQuery", q)
+}
+
+// The TraverseWxCardVisit type is an adapter to allow the use of ordinary function as Traverser.
+type TraverseWxCardVisit func(context.Context, *ent.WxCardVisitQuery) error
+
+// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
+func (f TraverseWxCardVisit) Intercept(next ent.Querier) ent.Querier {
+	return next
+}
+
+// Traverse calls f(ctx, q).
+func (f TraverseWxCardVisit) Traverse(ctx context.Context, q ent.Query) error {
+	if q, ok := q.(*ent.WxCardVisitQuery); ok {
+		return f(ctx, q)
+	}
+	return fmt.Errorf("unexpected query type %T. expect *ent.WxCardVisitQuery", q)
+}
+
 // NewQuery returns the generic Query interface for the given typed query.
 func NewQuery(q ent.Query) (Query, error) {
 	switch q := q.(type) {
@@ -638,6 +778,10 @@ func NewQuery(q ent.Query) (Query, error) {
 		return &query[*ent.BatchMsgQuery, predicate.BatchMsg, batchmsg.OrderOption]{typ: ent.TypeBatchMsg, tq: q}, nil
 	case *ent.CategoryQuery:
 		return &query[*ent.CategoryQuery, predicate.Category, category.OrderOption]{typ: ent.TypeCategory, tq: q}, nil
+	case *ent.ChatRecordsQuery:
+		return &query[*ent.ChatRecordsQuery, predicate.ChatRecords, chatrecords.OrderOption]{typ: ent.TypeChatRecords, tq: q}, nil
+	case *ent.ChatSessionQuery:
+		return &query[*ent.ChatSessionQuery, predicate.ChatSession, chatsession.OrderOption]{typ: ent.TypeChatSession, tq: q}, nil
 	case *ent.ContactQuery:
 		return &query[*ent.ContactQuery, predicate.Contact, contact.OrderOption]{typ: ent.TypeContact, tq: q}, nil
 	case *ent.EmployeeQuery:
@@ -670,6 +814,12 @@ func NewQuery(q ent.Query) (Query, error) {
 		return &query[*ent.WorkExperienceQuery, predicate.WorkExperience, workexperience.OrderOption]{typ: ent.TypeWorkExperience, tq: q}, nil
 	case *ent.WxQuery:
 		return &query[*ent.WxQuery, predicate.Wx, wx.OrderOption]{typ: ent.TypeWx, tq: q}, nil
+	case *ent.WxCardQuery:
+		return &query[*ent.WxCardQuery, predicate.WxCard, wxcard.OrderOption]{typ: ent.TypeWxCard, tq: q}, nil
+	case *ent.WxCardUserQuery:
+		return &query[*ent.WxCardUserQuery, predicate.WxCardUser, wxcarduser.OrderOption]{typ: ent.TypeWxCardUser, tq: q}, nil
+	case *ent.WxCardVisitQuery:
+		return &query[*ent.WxCardVisitQuery, predicate.WxCardVisit, wxcardvisit.OrderOption]{typ: ent.TypeWxCardVisit, tq: q}, nil
 	default:
 		return nil, fmt.Errorf("unknown query type %T", q)
 	}

+ 174 - 0
ent/migrate/schema.go

@@ -118,6 +118,61 @@ var (
 			},
 		},
 	}
+	// ChatRecordsColumns holds the columns for the "chat_records" table.
+	ChatRecordsColumns = []*schema.Column{
+		{Name: "id", Type: field.TypeUint64, Increment: true},
+		{Name: "created_at", Type: field.TypeTime, Comment: "Create Time | 创建日期"},
+		{Name: "updated_at", Type: field.TypeTime, Comment: "Update Time | 修改日期"},
+		{Name: "deleted_at", Type: field.TypeTime, Nullable: true, Comment: "Delete Time | 删除日期"},
+		{Name: "content", Type: field.TypeString, Comment: "内容", Default: ""},
+		{Name: "content_type", Type: field.TypeUint8, Comment: "内容类型:1-提问 2-回答", Default: 1},
+		{Name: "session_id", Type: field.TypeUint64, Comment: "会话ID", Default: 0},
+		{Name: "user_id", Type: field.TypeUint64, Comment: "用户ID", Default: 0},
+		{Name: "bot_id", Type: field.TypeUint64, Comment: "聊天ID", Default: 0},
+		{Name: "bot_type", Type: field.TypeUint8, Comment: "类型:1-微信 2-小程序card 3-智能体", Default: 2},
+	}
+	// ChatRecordsTable holds the schema information for the "chat_records" table.
+	ChatRecordsTable = &schema.Table{
+		Name:       "chat_records",
+		Columns:    ChatRecordsColumns,
+		PrimaryKey: []*schema.Column{ChatRecordsColumns[0]},
+		Indexes: []*schema.Index{
+			{
+				Name:    "chatrecords_user_id_bot_id_bot_type",
+				Unique:  false,
+				Columns: []*schema.Column{ChatRecordsColumns[7], ChatRecordsColumns[8], ChatRecordsColumns[9]},
+			},
+			{
+				Name:    "chatrecords_session_id",
+				Unique:  false,
+				Columns: []*schema.Column{ChatRecordsColumns[6]},
+			},
+		},
+	}
+	// ChatSessionColumns holds the columns for the "chat_session" table.
+	ChatSessionColumns = []*schema.Column{
+		{Name: "id", Type: field.TypeUint64, Increment: true},
+		{Name: "created_at", Type: field.TypeTime, Comment: "Create Time | 创建日期"},
+		{Name: "updated_at", Type: field.TypeTime, Comment: "Update Time | 修改日期"},
+		{Name: "deleted_at", Type: field.TypeTime, Nullable: true, Comment: "Delete Time | 删除日期"},
+		{Name: "name", Type: field.TypeString, Comment: "名称", Default: ""},
+		{Name: "user_id", Type: field.TypeUint64, Comment: "用户ID", Default: 0},
+		{Name: "bot_id", Type: field.TypeUint64, Comment: "聊天ID", Default: 0},
+		{Name: "bot_type", Type: field.TypeUint8, Comment: "类型:1-微信 2-小程序card 3-智能体", Default: 2},
+	}
+	// ChatSessionTable holds the schema information for the "chat_session" table.
+	ChatSessionTable = &schema.Table{
+		Name:       "chat_session",
+		Columns:    ChatSessionColumns,
+		PrimaryKey: []*schema.Column{ChatSessionColumns[0]},
+		Indexes: []*schema.Index{
+			{
+				Name:    "chatsession_user_id_bot_id_bot_type",
+				Unique:  false,
+				Columns: []*schema.Column{ChatSessionColumns[5], ChatSessionColumns[6], ChatSessionColumns[7]},
+			},
+		},
+	}
 	// ContactColumns holds the columns for the "contact" table.
 	ContactColumns = []*schema.Column{
 		{Name: "id", Type: field.TypeUint64, Increment: true},
@@ -191,6 +246,8 @@ var (
 		{Name: "video_url", Type: field.TypeString, Size: 1000, Comment: "video_url | 视频地址", Default: ""},
 		{Name: "organization_id", Type: field.TypeUint64, Comment: "organization_id | 租户ID"},
 		{Name: "category_id", Type: field.TypeUint64, Comment: "category_id | 分类ID"},
+		{Name: "api_base", Type: field.TypeString, Comment: "api_base", Default: ""},
+		{Name: "api_key", Type: field.TypeString, Comment: "api_key", Default: ""},
 	}
 	// EmployeeTable holds the schema information for the "employee" table.
 	EmployeeTable = &schema.Table{
@@ -706,12 +763,111 @@ var (
 			},
 		},
 	}
+	// WxCardColumns holds the columns for the "wx_card" table.
+	WxCardColumns = []*schema.Column{
+		{Name: "id", Type: field.TypeUint64, Increment: true},
+		{Name: "created_at", Type: field.TypeTime, Comment: "Create Time | 创建日期"},
+		{Name: "updated_at", Type: field.TypeTime, Comment: "Update Time | 修改日期"},
+		{Name: "deleted_at", Type: field.TypeTime, Nullable: true, Comment: "Delete Time | 删除日期"},
+		{Name: "user_id", Type: field.TypeUint64, Nullable: true, Comment: "user表ID", Default: 0},
+		{Name: "wx_user_id", Type: field.TypeUint64, Nullable: true, Comment: "wx表ID", Default: 0},
+		{Name: "avatar", Type: field.TypeString, Comment: "头像", Default: ""},
+		{Name: "logo", Type: field.TypeString, Comment: "logo", Default: ""},
+		{Name: "name", Type: field.TypeString, Comment: "名称", Default: ""},
+		{Name: "company", Type: field.TypeString, Comment: "公司", Default: ""},
+		{Name: "address", Type: field.TypeString, Comment: "地址", Default: ""},
+		{Name: "phone", Type: field.TypeString, Comment: "手机号", Default: ""},
+		{Name: "official_account", Type: field.TypeString, Comment: "公众号", Default: ""},
+		{Name: "wechat_account", Type: field.TypeString, Comment: "微信号", Default: ""},
+		{Name: "email", Type: field.TypeString, Nullable: true, Comment: "邮箱", Default: ""},
+		{Name: "api_base", Type: field.TypeString, Nullable: true, Comment: "fastgpt-base"},
+		{Name: "api_key", Type: field.TypeString, Nullable: true, Comment: "fastgpt-key"},
+		{Name: "ai_info", Type: field.TypeString, Nullable: true, Comment: "AI信息"},
+		{Name: "intro", Type: field.TypeString, Nullable: true, Comment: "个人介绍", Default: ""},
+	}
+	// WxCardTable holds the schema information for the "wx_card" table.
+	WxCardTable = &schema.Table{
+		Name:       "wx_card",
+		Columns:    WxCardColumns,
+		PrimaryKey: []*schema.Column{WxCardColumns[0]},
+		Indexes: []*schema.Index{
+			{
+				Name:    "wxcard_user_id",
+				Unique:  false,
+				Columns: []*schema.Column{WxCardColumns[4]},
+			},
+			{
+				Name:    "wxcard_wx_user_id",
+				Unique:  false,
+				Columns: []*schema.Column{WxCardColumns[5]},
+			},
+		},
+	}
+	// WxCardUserColumns holds the columns for the "wx_card_user" table.
+	WxCardUserColumns = []*schema.Column{
+		{Name: "id", Type: field.TypeUint64, Increment: true},
+		{Name: "created_at", Type: field.TypeTime, Comment: "Create Time | 创建日期"},
+		{Name: "updated_at", Type: field.TypeTime, Comment: "Update Time | 修改日期"},
+		{Name: "deleted_at", Type: field.TypeTime, Nullable: true, Comment: "Delete Time | 删除日期"},
+		{Name: "wxid", Type: field.TypeString, Comment: "微信id", Default: ""},
+		{Name: "account", Type: field.TypeString, Comment: "微信号", Default: ""},
+		{Name: "avatar", Type: field.TypeString, Comment: "头像", Default: ""},
+		{Name: "nickname", Type: field.TypeString, Comment: "昵称", Default: ""},
+		{Name: "remark", Type: field.TypeString, Comment: "备注名", Default: ""},
+		{Name: "phone", Type: field.TypeString, Comment: "手机号", Default: ""},
+		{Name: "open_id", Type: field.TypeString, Comment: "OpenID", Default: ""},
+		{Name: "union_id", Type: field.TypeString, Comment: "UnionID", Default: ""},
+		{Name: "session_key", Type: field.TypeString, Comment: "SessionKey", Default: ""},
+	}
+	// WxCardUserTable holds the schema information for the "wx_card_user" table.
+	WxCardUserTable = &schema.Table{
+		Name:       "wx_card_user",
+		Columns:    WxCardUserColumns,
+		PrimaryKey: []*schema.Column{WxCardUserColumns[0]},
+		Indexes: []*schema.Index{
+			{
+				Name:    "wxcarduser_wxid_open_id",
+				Unique:  false,
+				Columns: []*schema.Column{WxCardUserColumns[4], WxCardUserColumns[10]},
+			},
+		},
+	}
+	// WxCardVisitColumns holds the columns for the "wx_card_visit" table.
+	WxCardVisitColumns = []*schema.Column{
+		{Name: "id", Type: field.TypeUint64, Increment: true},
+		{Name: "created_at", Type: field.TypeTime, Comment: "Create Time | 创建日期"},
+		{Name: "updated_at", Type: field.TypeTime, Comment: "Update Time | 修改日期"},
+		{Name: "deleted_at", Type: field.TypeTime, Nullable: true, Comment: "Delete Time | 删除日期"},
+		{Name: "user_id", Type: field.TypeUint64, Nullable: true, Comment: "user表ID", Default: 0},
+		{Name: "bot_id", Type: field.TypeUint64, Comment: "被访ID", Default: 0},
+		{Name: "bot_type", Type: field.TypeUint8, Comment: "类型:1-微信 2-小程序 3-智能体", Default: 0},
+	}
+	// WxCardVisitTable holds the schema information for the "wx_card_visit" table.
+	WxCardVisitTable = &schema.Table{
+		Name:       "wx_card_visit",
+		Columns:    WxCardVisitColumns,
+		PrimaryKey: []*schema.Column{WxCardVisitColumns[0]},
+		Indexes: []*schema.Index{
+			{
+				Name:    "wxcardvisit_user_id",
+				Unique:  false,
+				Columns: []*schema.Column{WxCardVisitColumns[4]},
+			},
+			{
+				Name:    "wxcardvisit_bot_id_bot_type",
+				Unique:  false,
+				Columns: []*schema.Column{WxCardVisitColumns[5], WxCardVisitColumns[6]},
+			},
+		},
+	}
 	// Tables holds all the tables in the schema.
 	Tables = []*schema.Table{
 		AgentTable,
 		AgentBaseTable,
 		BatchMsgTable,
 		CategoryTable,
+		ChatRecordsTable,
+		ChatSessionTable,
 		ContactTable,
 		EmployeeTable,
 		EmployeeConfigTable,
@@ -728,6 +884,9 @@ var (
 		TutorialTable,
 		WorkExperienceTable,
 		WxTable,
+		WxCardTable,
+		WxCardUserTable,
+		WxCardVisitTable,
 	}
 )
 
@@ -744,6 +903,12 @@ func init() {
 	CategoryTable.Annotation = &entsql.Annotation{
 		Table: "category",
 	}
+	ChatRecordsTable.Annotation = &entsql.Annotation{
+		Table: "chat_records",
+	}
+	ChatSessionTable.Annotation = &entsql.Annotation{
+		Table: "chat_session",
+	}
 	ContactTable.Annotation = &entsql.Annotation{
 		Table: "contact",
 	}
@@ -804,4 +969,13 @@ func init() {
 	WxTable.Annotation = &entsql.Annotation{
 		Table: "wx",
 	}
+	WxCardTable.Annotation = &entsql.Annotation{
+		Table: "wx_card",
+	}
+	WxCardUserTable.Annotation = &entsql.Annotation{
+		Table: "wx_card_user",
+	}
+	WxCardVisitTable.Annotation = &entsql.Annotation{
+		Table: "wx_card_visit",
+	}
 }

Fișier diff suprimat deoarece este prea mare
+ 927 - 676
ent/mutation.go


+ 410 - 0
ent/pagination.go

@@ -9,6 +9,8 @@ import (
 	"wechat-api/ent/agentbase"
 	"wechat-api/ent/batchmsg"
 	"wechat-api/ent/category"
+	"wechat-api/ent/chatrecords"
+	"wechat-api/ent/chatsession"
 	"wechat-api/ent/contact"
 	"wechat-api/ent/employee"
 	"wechat-api/ent/employeeconfig"
@@ -25,6 +27,9 @@ import (
 	"wechat-api/ent/tutorial"
 	"wechat-api/ent/workexperience"
 	"wechat-api/ent/wx"
+	"wechat-api/ent/wxcard"
+	"wechat-api/ent/wxcarduser"
+	"wechat-api/ent/wxcardvisit"
 )
 
 const errInvalidPage = "INVALID_PAGE"
@@ -397,6 +402,168 @@ func (c *CategoryQuery) Page(
 	return ret, nil
 }
 
+type ChatRecordsPager struct {
+	Order  chatrecords.OrderOption
+	Filter func(*ChatRecordsQuery) (*ChatRecordsQuery, error)
+}
+
+// ChatRecordsPaginateOption enables pagination customization.
+type ChatRecordsPaginateOption func(*ChatRecordsPager)
+
+// DefaultChatRecordsOrder is the default ordering of ChatRecords.
+var DefaultChatRecordsOrder = Desc(chatrecords.FieldID)
+
+func newChatRecordsPager(opts []ChatRecordsPaginateOption) (*ChatRecordsPager, error) {
+	pager := &ChatRecordsPager{}
+	for _, opt := range opts {
+		opt(pager)
+	}
+	if pager.Order == nil {
+		pager.Order = DefaultChatRecordsOrder
+	}
+	return pager, nil
+}
+
+func (p *ChatRecordsPager) ApplyFilter(query *ChatRecordsQuery) (*ChatRecordsQuery, error) {
+	if p.Filter != nil {
+		return p.Filter(query)
+	}
+	return query, nil
+}
+
+// ChatRecordsPageList is ChatRecords PageList result.
+type ChatRecordsPageList struct {
+	List        []*ChatRecords `json:"list"`
+	PageDetails *PageDetails   `json:"pageDetails"`
+}
+
+func (cr *ChatRecordsQuery) Page(
+	ctx context.Context, pageNum uint64, pageSize uint64, opts ...ChatRecordsPaginateOption,
+) (*ChatRecordsPageList, error) {
+
+	pager, err := newChatRecordsPager(opts)
+	if err != nil {
+		return nil, err
+	}
+
+	if cr, err = pager.ApplyFilter(cr); err != nil {
+		return nil, err
+	}
+
+	ret := &ChatRecordsPageList{}
+
+	ret.PageDetails = &PageDetails{
+		Page: pageNum,
+		Size: pageSize,
+	}
+
+	query := cr.Clone()
+	query.ctx.Fields = nil
+	count, err := query.Count(ctx)
+
+	if err != nil {
+		return nil, err
+	}
+
+	ret.PageDetails.Total = uint64(count)
+
+	if pager.Order != nil {
+		cr = cr.Order(pager.Order)
+	} else {
+		cr = cr.Order(DefaultChatRecordsOrder)
+	}
+
+	cr = cr.Offset(int((pageNum - 1) * pageSize)).Limit(int(pageSize))
+	list, err := cr.All(ctx)
+	if err != nil {
+		return nil, err
+	}
+	ret.List = list
+
+	return ret, nil
+}
+
+type ChatSessionPager struct {
+	Order  chatsession.OrderOption
+	Filter func(*ChatSessionQuery) (*ChatSessionQuery, error)
+}
+
+// ChatSessionPaginateOption enables pagination customization.
+type ChatSessionPaginateOption func(*ChatSessionPager)
+
+// DefaultChatSessionOrder is the default ordering of ChatSession.
+var DefaultChatSessionOrder = Desc(chatsession.FieldID)
+
+func newChatSessionPager(opts []ChatSessionPaginateOption) (*ChatSessionPager, error) {
+	pager := &ChatSessionPager{}
+	for _, opt := range opts {
+		opt(pager)
+	}
+	if pager.Order == nil {
+		pager.Order = DefaultChatSessionOrder
+	}
+	return pager, nil
+}
+
+func (p *ChatSessionPager) ApplyFilter(query *ChatSessionQuery) (*ChatSessionQuery, error) {
+	if p.Filter != nil {
+		return p.Filter(query)
+	}
+	return query, nil
+}
+
+// ChatSessionPageList is ChatSession PageList result.
+type ChatSessionPageList struct {
+	List        []*ChatSession `json:"list"`
+	PageDetails *PageDetails   `json:"pageDetails"`
+}
+
+func (cs *ChatSessionQuery) Page(
+	ctx context.Context, pageNum uint64, pageSize uint64, opts ...ChatSessionPaginateOption,
+) (*ChatSessionPageList, error) {
+
+	pager, err := newChatSessionPager(opts)
+	if err != nil {
+		return nil, err
+	}
+
+	if cs, err = pager.ApplyFilter(cs); err != nil {
+		return nil, err
+	}
+
+	ret := &ChatSessionPageList{}
+
+	ret.PageDetails = &PageDetails{
+		Page: pageNum,
+		Size: pageSize,
+	}
+
+	query := cs.Clone()
+	query.ctx.Fields = nil
+	count, err := query.Count(ctx)
+
+	if err != nil {
+		return nil, err
+	}
+
+	ret.PageDetails.Total = uint64(count)
+
+	if pager.Order != nil {
+		cs = cs.Order(pager.Order)
+	} else {
+		cs = cs.Order(DefaultChatSessionOrder)
+	}
+
+	cs = cs.Offset(int((pageNum - 1) * pageSize)).Limit(int(pageSize))
+	list, err := cs.All(ctx)
+	if err != nil {
+		return nil, err
+	}
+	ret.List = list
+
+	return ret, nil
+}
+
 type ContactPager struct {
 	Order  contact.OrderOption
 	Filter func(*ContactQuery) (*ContactQuery, error)
@@ -1692,3 +1859,246 @@ func (w *WxQuery) Page(
 
 	return ret, nil
 }
+
+type WxCardPager struct {
+	Order  wxcard.OrderOption
+	Filter func(*WxCardQuery) (*WxCardQuery, error)
+}
+
+// WxCardPaginateOption enables pagination customization.
+type WxCardPaginateOption func(*WxCardPager)
+
+// DefaultWxCardOrder is the default ordering of WxCard.
+var DefaultWxCardOrder = Desc(wxcard.FieldID)
+
+func newWxCardPager(opts []WxCardPaginateOption) (*WxCardPager, error) {
+	pager := &WxCardPager{}
+	for _, opt := range opts {
+		opt(pager)
+	}
+	if pager.Order == nil {
+		pager.Order = DefaultWxCardOrder
+	}
+	return pager, nil
+}
+
+func (p *WxCardPager) ApplyFilter(query *WxCardQuery) (*WxCardQuery, error) {
+	if p.Filter != nil {
+		return p.Filter(query)
+	}
+	return query, nil
+}
+
+// WxCardPageList is WxCard PageList result.
+type WxCardPageList struct {
+	List        []*WxCard    `json:"list"`
+	PageDetails *PageDetails `json:"pageDetails"`
+}
+
+func (wc *WxCardQuery) Page(
+	ctx context.Context, pageNum uint64, pageSize uint64, opts ...WxCardPaginateOption,
+) (*WxCardPageList, error) {
+
+	pager, err := newWxCardPager(opts)
+	if err != nil {
+		return nil, err
+	}
+
+	if wc, err = pager.ApplyFilter(wc); err != nil {
+		return nil, err
+	}
+
+	ret := &WxCardPageList{}
+
+	ret.PageDetails = &PageDetails{
+		Page: pageNum,
+		Size: pageSize,
+	}
+
+	query := wc.Clone()
+	query.ctx.Fields = nil
+	count, err := query.Count(ctx)
+
+	if err != nil {
+		return nil, err
+	}
+
+	ret.PageDetails.Total = uint64(count)
+
+	if pager.Order != nil {
+		wc = wc.Order(pager.Order)
+	} else {
+		wc = wc.Order(DefaultWxCardOrder)
+	}
+
+	wc = wc.Offset(int((pageNum - 1) * pageSize)).Limit(int(pageSize))
+	list, err := wc.All(ctx)
+	if err != nil {
+		return nil, err
+	}
+	ret.List = list
+
+	return ret, nil
+}
+
+type WxCardUserPager struct {
+	Order  wxcarduser.OrderOption
+	Filter func(*WxCardUserQuery) (*WxCardUserQuery, error)
+}
+
+// WxCardUserPaginateOption enables pagination customization.
+type WxCardUserPaginateOption func(*WxCardUserPager)
+
+// DefaultWxCardUserOrder is the default ordering of WxCardUser.
+var DefaultWxCardUserOrder = Desc(wxcarduser.FieldID)
+
+func newWxCardUserPager(opts []WxCardUserPaginateOption) (*WxCardUserPager, error) {
+	pager := &WxCardUserPager{}
+	for _, opt := range opts {
+		opt(pager)
+	}
+	if pager.Order == nil {
+		pager.Order = DefaultWxCardUserOrder
+	}
+	return pager, nil
+}
+
+func (p *WxCardUserPager) ApplyFilter(query *WxCardUserQuery) (*WxCardUserQuery, error) {
+	if p.Filter != nil {
+		return p.Filter(query)
+	}
+	return query, nil
+}
+
+// WxCardUserPageList is WxCardUser PageList result.
+type WxCardUserPageList struct {
+	List        []*WxCardUser `json:"list"`
+	PageDetails *PageDetails  `json:"pageDetails"`
+}
+
+func (wcu *WxCardUserQuery) Page(
+	ctx context.Context, pageNum uint64, pageSize uint64, opts ...WxCardUserPaginateOption,
+) (*WxCardUserPageList, error) {
+
+	pager, err := newWxCardUserPager(opts)
+	if err != nil {
+		return nil, err
+	}
+
+	if wcu, err = pager.ApplyFilter(wcu); err != nil {
+		return nil, err
+	}
+
+	ret := &WxCardUserPageList{}
+
+	ret.PageDetails = &PageDetails{
+		Page: pageNum,
+		Size: pageSize,
+	}
+
+	query := wcu.Clone()
+	query.ctx.Fields = nil
+	count, err := query.Count(ctx)
+
+	if err != nil {
+		return nil, err
+	}
+
+	ret.PageDetails.Total = uint64(count)
+
+	if pager.Order != nil {
+		wcu = wcu.Order(pager.Order)
+	} else {
+		wcu = wcu.Order(DefaultWxCardUserOrder)
+	}
+
+	wcu = wcu.Offset(int((pageNum - 1) * pageSize)).Limit(int(pageSize))
+	list, err := wcu.All(ctx)
+	if err != nil {
+		return nil, err
+	}
+	ret.List = list
+
+	return ret, nil
+}
+
+type WxCardVisitPager struct {
+	Order  wxcardvisit.OrderOption
+	Filter func(*WxCardVisitQuery) (*WxCardVisitQuery, error)
+}
+
+// WxCardVisitPaginateOption enables pagination customization.
+type WxCardVisitPaginateOption func(*WxCardVisitPager)
+
+// DefaultWxCardVisitOrder is the default ordering of WxCardVisit.
+var DefaultWxCardVisitOrder = Desc(wxcardvisit.FieldID)
+
+func newWxCardVisitPager(opts []WxCardVisitPaginateOption) (*WxCardVisitPager, error) {
+	pager := &WxCardVisitPager{}
+	for _, opt := range opts {
+		opt(pager)
+	}
+	if pager.Order == nil {
+		pager.Order = DefaultWxCardVisitOrder
+	}
+	return pager, nil
+}
+
+func (p *WxCardVisitPager) ApplyFilter(query *WxCardVisitQuery) (*WxCardVisitQuery, error) {
+	if p.Filter != nil {
+		return p.Filter(query)
+	}
+	return query, nil
+}
+
+// WxCardVisitPageList is WxCardVisit PageList result.
+type WxCardVisitPageList struct {
+	List        []*WxCardVisit `json:"list"`
+	PageDetails *PageDetails   `json:"pageDetails"`
+}
+
+func (wcv *WxCardVisitQuery) Page(
+	ctx context.Context, pageNum uint64, pageSize uint64, opts ...WxCardVisitPaginateOption,
+) (*WxCardVisitPageList, error) {
+
+	pager, err := newWxCardVisitPager(opts)
+	if err != nil {
+		return nil, err
+	}
+
+	if wcv, err = pager.ApplyFilter(wcv); err != nil {
+		return nil, err
+	}
+
+	ret := &WxCardVisitPageList{}
+
+	ret.PageDetails = &PageDetails{
+		Page: pageNum,
+		Size: pageSize,
+	}
+
+	query := wcv.Clone()
+	query.ctx.Fields = nil
+	count, err := query.Count(ctx)
+
+	if err != nil {
+		return nil, err
+	}
+
+	ret.PageDetails.Total = uint64(count)
+
+	if pager.Order != nil {
+		wcv = wcv.Order(pager.Order)
+	} else {
+		wcv = wcv.Order(DefaultWxCardVisitOrder)
+	}
+
+	wcv = wcv.Offset(int((pageNum - 1) * pageSize)).Limit(int(pageSize))
+	list, err := wcv.All(ctx)
+	if err != nil {
+		return nil, err
+	}
+	ret.List = list
+
+	return ret, nil
+}

+ 15 - 0
ent/predicate/predicate.go

@@ -18,6 +18,12 @@ type BatchMsg func(*sql.Selector)
 // Category is the predicate function for category builders.
 type Category func(*sql.Selector)
 
+// ChatRecords is the predicate function for chatrecords builders.
+type ChatRecords func(*sql.Selector)
+
+// ChatSession is the predicate function for chatsession builders.
+type ChatSession func(*sql.Selector)
+
 // Contact is the predicate function for contact builders.
 type Contact func(*sql.Selector)
 
@@ -65,3 +71,12 @@ type WorkExperience func(*sql.Selector)
 
 // Wx is the predicate function for wx builders.
 type Wx func(*sql.Selector)
+
+// WxCard is the predicate function for wxcard builders.
+type WxCard func(*sql.Selector)
+
+// WxCardUser is the predicate function for wxcarduser builders.
+type WxCardUser func(*sql.Selector)
+
+// WxCardVisit is the predicate function for wxcardvisit builders.
+type WxCardVisit func(*sql.Selector)

+ 244 - 0
ent/runtime/runtime.go

@@ -8,6 +8,8 @@ import (
 	"wechat-api/ent/agentbase"
 	"wechat-api/ent/batchmsg"
 	"wechat-api/ent/category"
+	"wechat-api/ent/chatrecords"
+	"wechat-api/ent/chatsession"
 	"wechat-api/ent/contact"
 	"wechat-api/ent/employee"
 	"wechat-api/ent/employeeconfig"
@@ -25,6 +27,9 @@ import (
 	"wechat-api/ent/tutorial"
 	"wechat-api/ent/workexperience"
 	"wechat-api/ent/wx"
+	"wechat-api/ent/wxcard"
+	"wechat-api/ent/wxcarduser"
+	"wechat-api/ent/wxcardvisit"
 )
 
 // The init function reads all schema descriptors with runtime code
@@ -172,6 +177,84 @@ func init() {
 	categoryDescOrganizationID := categoryFields[1].Descriptor()
 	// category.OrganizationIDValidator is a validator for the "organization_id" field. It is called by the builders before save.
 	category.OrganizationIDValidator = categoryDescOrganizationID.Validators[0].(func(uint64) error)
+	chatrecordsMixin := schema.ChatRecords{}.Mixin()
+	chatrecordsMixinHooks1 := chatrecordsMixin[1].Hooks()
+	chatrecords.Hooks[0] = chatrecordsMixinHooks1[0]
+	chatrecordsMixinInters1 := chatrecordsMixin[1].Interceptors()
+	chatrecords.Interceptors[0] = chatrecordsMixinInters1[0]
+	chatrecordsMixinFields0 := chatrecordsMixin[0].Fields()
+	_ = chatrecordsMixinFields0
+	chatrecordsFields := schema.ChatRecords{}.Fields()
+	_ = chatrecordsFields
+	// chatrecordsDescCreatedAt is the schema descriptor for created_at field.
+	chatrecordsDescCreatedAt := chatrecordsMixinFields0[1].Descriptor()
+	// chatrecords.DefaultCreatedAt holds the default value on creation for the created_at field.
+	chatrecords.DefaultCreatedAt = chatrecordsDescCreatedAt.Default.(func() time.Time)
+	// chatrecordsDescUpdatedAt is the schema descriptor for updated_at field.
+	chatrecordsDescUpdatedAt := chatrecordsMixinFields0[2].Descriptor()
+	// chatrecords.DefaultUpdatedAt holds the default value on creation for the updated_at field.
+	chatrecords.DefaultUpdatedAt = chatrecordsDescUpdatedAt.Default.(func() time.Time)
+	// chatrecords.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
+	chatrecords.UpdateDefaultUpdatedAt = chatrecordsDescUpdatedAt.UpdateDefault.(func() time.Time)
+	// chatrecordsDescContent is the schema descriptor for content field.
+	chatrecordsDescContent := chatrecordsFields[0].Descriptor()
+	// chatrecords.DefaultContent holds the default value on creation for the content field.
+	chatrecords.DefaultContent = chatrecordsDescContent.Default.(string)
+	// chatrecordsDescContentType is the schema descriptor for content_type field.
+	chatrecordsDescContentType := chatrecordsFields[1].Descriptor()
+	// chatrecords.DefaultContentType holds the default value on creation for the content_type field.
+	chatrecords.DefaultContentType = chatrecordsDescContentType.Default.(uint8)
+	// chatrecordsDescSessionID is the schema descriptor for session_id field.
+	chatrecordsDescSessionID := chatrecordsFields[2].Descriptor()
+	// chatrecords.DefaultSessionID holds the default value on creation for the session_id field.
+	chatrecords.DefaultSessionID = chatrecordsDescSessionID.Default.(uint64)
+	// chatrecordsDescUserID is the schema descriptor for user_id field.
+	chatrecordsDescUserID := chatrecordsFields[3].Descriptor()
+	// chatrecords.DefaultUserID holds the default value on creation for the user_id field.
+	chatrecords.DefaultUserID = chatrecordsDescUserID.Default.(uint64)
+	// chatrecordsDescBotID is the schema descriptor for bot_id field.
+	chatrecordsDescBotID := chatrecordsFields[4].Descriptor()
+	// chatrecords.DefaultBotID holds the default value on creation for the bot_id field.
+	chatrecords.DefaultBotID = chatrecordsDescBotID.Default.(uint64)
+	// chatrecordsDescBotType is the schema descriptor for bot_type field.
+	chatrecordsDescBotType := chatrecordsFields[5].Descriptor()
+	// chatrecords.DefaultBotType holds the default value on creation for the bot_type field.
+	chatrecords.DefaultBotType = chatrecordsDescBotType.Default.(uint8)
+	chatsessionMixin := schema.ChatSession{}.Mixin()
+	chatsessionMixinHooks1 := chatsessionMixin[1].Hooks()
+	chatsession.Hooks[0] = chatsessionMixinHooks1[0]
+	chatsessionMixinInters1 := chatsessionMixin[1].Interceptors()
+	chatsession.Interceptors[0] = chatsessionMixinInters1[0]
+	chatsessionMixinFields0 := chatsessionMixin[0].Fields()
+	_ = chatsessionMixinFields0
+	chatsessionFields := schema.ChatSession{}.Fields()
+	_ = chatsessionFields
+	// chatsessionDescCreatedAt is the schema descriptor for created_at field.
+	chatsessionDescCreatedAt := chatsessionMixinFields0[1].Descriptor()
+	// chatsession.DefaultCreatedAt holds the default value on creation for the created_at field.
+	chatsession.DefaultCreatedAt = chatsessionDescCreatedAt.Default.(func() time.Time)
+	// chatsessionDescUpdatedAt is the schema descriptor for updated_at field.
+	chatsessionDescUpdatedAt := chatsessionMixinFields0[2].Descriptor()
+	// chatsession.DefaultUpdatedAt holds the default value on creation for the updated_at field.
+	chatsession.DefaultUpdatedAt = chatsessionDescUpdatedAt.Default.(func() time.Time)
+	// chatsession.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
+	chatsession.UpdateDefaultUpdatedAt = chatsessionDescUpdatedAt.UpdateDefault.(func() time.Time)
+	// chatsessionDescName is the schema descriptor for name field.
+	chatsessionDescName := chatsessionFields[0].Descriptor()
+	// chatsession.DefaultName holds the default value on creation for the name field.
+	chatsession.DefaultName = chatsessionDescName.Default.(string)
+	// chatsessionDescUserID is the schema descriptor for user_id field.
+	chatsessionDescUserID := chatsessionFields[1].Descriptor()
+	// chatsession.DefaultUserID holds the default value on creation for the user_id field.
+	chatsession.DefaultUserID = chatsessionDescUserID.Default.(uint64)
+	// chatsessionDescBotID is the schema descriptor for bot_id field.
+	chatsessionDescBotID := chatsessionFields[2].Descriptor()
+	// chatsession.DefaultBotID holds the default value on creation for the bot_id field.
+	chatsession.DefaultBotID = chatsessionDescBotID.Default.(uint64)
+	// chatsessionDescBotType is the schema descriptor for bot_type field.
+	chatsessionDescBotType := chatsessionFields[3].Descriptor()
+	// chatsession.DefaultBotType holds the default value on creation for the bot_type field.
+	chatsession.DefaultBotType = chatsessionDescBotType.Default.(uint8)
 	contactMixin := schema.Contact{}.Mixin()
 	contactMixinHooks2 := contactMixin[2].Hooks()
 	contact.Hooks[0] = contactMixinHooks2[0]
@@ -354,6 +437,14 @@ func init() {
 	employeeDescCategoryID := employeeFields[14].Descriptor()
 	// employee.CategoryIDValidator is a validator for the "category_id" field. It is called by the builders before save.
 	employee.CategoryIDValidator = employeeDescCategoryID.Validators[0].(func(uint64) error)
+	// employeeDescAPIBase is the schema descriptor for api_base field.
+	employeeDescAPIBase := employeeFields[15].Descriptor()
+	// employee.DefaultAPIBase holds the default value on creation for the api_base field.
+	employee.DefaultAPIBase = employeeDescAPIBase.Default.(string)
+	// employeeDescAPIKey is the schema descriptor for api_key field.
+	employeeDescAPIKey := employeeFields[16].Descriptor()
+	// employee.DefaultAPIKey holds the default value on creation for the api_key field.
+	employee.DefaultAPIKey = employeeDescAPIKey.Default.(string)
 	employeeconfigMixin := schema.EmployeeConfig{}.Mixin()
 	employeeconfigMixinHooks1 := employeeconfigMixin[1].Hooks()
 	employeeconfig.Hooks[0] = employeeconfigMixinHooks1[0]
@@ -851,6 +942,159 @@ func init() {
 	wxDescAPIKey := wxFields[12].Descriptor()
 	// wx.DefaultAPIKey holds the default value on creation for the api_key field.
 	wx.DefaultAPIKey = wxDescAPIKey.Default.(string)
+	wxcardMixin := schema.WxCard{}.Mixin()
+	wxcardMixinHooks1 := wxcardMixin[1].Hooks()
+	wxcard.Hooks[0] = wxcardMixinHooks1[0]
+	wxcardMixinInters1 := wxcardMixin[1].Interceptors()
+	wxcard.Interceptors[0] = wxcardMixinInters1[0]
+	wxcardMixinFields0 := wxcardMixin[0].Fields()
+	_ = wxcardMixinFields0
+	wxcardFields := schema.WxCard{}.Fields()
+	_ = wxcardFields
+	// wxcardDescCreatedAt is the schema descriptor for created_at field.
+	wxcardDescCreatedAt := wxcardMixinFields0[1].Descriptor()
+	// wxcard.DefaultCreatedAt holds the default value on creation for the created_at field.
+	wxcard.DefaultCreatedAt = wxcardDescCreatedAt.Default.(func() time.Time)
+	// wxcardDescUpdatedAt is the schema descriptor for updated_at field.
+	wxcardDescUpdatedAt := wxcardMixinFields0[2].Descriptor()
+	// wxcard.DefaultUpdatedAt holds the default value on creation for the updated_at field.
+	wxcard.DefaultUpdatedAt = wxcardDescUpdatedAt.Default.(func() time.Time)
+	// wxcard.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
+	wxcard.UpdateDefaultUpdatedAt = wxcardDescUpdatedAt.UpdateDefault.(func() time.Time)
+	// wxcardDescUserID is the schema descriptor for user_id field.
+	wxcardDescUserID := wxcardFields[0].Descriptor()
+	// wxcard.DefaultUserID holds the default value on creation for the user_id field.
+	wxcard.DefaultUserID = wxcardDescUserID.Default.(uint64)
+	// wxcardDescWxUserID is the schema descriptor for wx_user_id field.
+	wxcardDescWxUserID := wxcardFields[1].Descriptor()
+	// wxcard.DefaultWxUserID holds the default value on creation for the wx_user_id field.
+	wxcard.DefaultWxUserID = wxcardDescWxUserID.Default.(uint64)
+	// wxcardDescAvatar is the schema descriptor for avatar field.
+	wxcardDescAvatar := wxcardFields[2].Descriptor()
+	// wxcard.DefaultAvatar holds the default value on creation for the avatar field.
+	wxcard.DefaultAvatar = wxcardDescAvatar.Default.(string)
+	// wxcardDescLogo is the schema descriptor for logo field.
+	wxcardDescLogo := wxcardFields[3].Descriptor()
+	// wxcard.DefaultLogo holds the default value on creation for the logo field.
+	wxcard.DefaultLogo = wxcardDescLogo.Default.(string)
+	// wxcardDescName is the schema descriptor for name field.
+	wxcardDescName := wxcardFields[4].Descriptor()
+	// wxcard.DefaultName holds the default value on creation for the name field.
+	wxcard.DefaultName = wxcardDescName.Default.(string)
+	// wxcardDescCompany is the schema descriptor for company field.
+	wxcardDescCompany := wxcardFields[5].Descriptor()
+	// wxcard.DefaultCompany holds the default value on creation for the company field.
+	wxcard.DefaultCompany = wxcardDescCompany.Default.(string)
+	// wxcardDescAddress is the schema descriptor for address field.
+	wxcardDescAddress := wxcardFields[6].Descriptor()
+	// wxcard.DefaultAddress holds the default value on creation for the address field.
+	wxcard.DefaultAddress = wxcardDescAddress.Default.(string)
+	// wxcardDescPhone is the schema descriptor for phone field.
+	wxcardDescPhone := wxcardFields[7].Descriptor()
+	// wxcard.DefaultPhone holds the default value on creation for the phone field.
+	wxcard.DefaultPhone = wxcardDescPhone.Default.(string)
+	// wxcardDescOfficialAccount is the schema descriptor for official_account field.
+	wxcardDescOfficialAccount := wxcardFields[8].Descriptor()
+	// wxcard.DefaultOfficialAccount holds the default value on creation for the official_account field.
+	wxcard.DefaultOfficialAccount = wxcardDescOfficialAccount.Default.(string)
+	// wxcardDescWechatAccount is the schema descriptor for wechat_account field.
+	wxcardDescWechatAccount := wxcardFields[9].Descriptor()
+	// wxcard.DefaultWechatAccount holds the default value on creation for the wechat_account field.
+	wxcard.DefaultWechatAccount = wxcardDescWechatAccount.Default.(string)
+	// wxcardDescEmail is the schema descriptor for email field.
+	wxcardDescEmail := wxcardFields[10].Descriptor()
+	// wxcard.DefaultEmail holds the default value on creation for the email field.
+	wxcard.DefaultEmail = wxcardDescEmail.Default.(string)
+	// wxcardDescIntro is the schema descriptor for intro field.
+	wxcardDescIntro := wxcardFields[14].Descriptor()
+	// wxcard.DefaultIntro holds the default value on creation for the intro field.
+	wxcard.DefaultIntro = wxcardDescIntro.Default.(string)
+	wxcarduserMixin := schema.WxCardUser{}.Mixin()
+	wxcarduserMixinHooks1 := wxcarduserMixin[1].Hooks()
+	wxcarduser.Hooks[0] = wxcarduserMixinHooks1[0]
+	wxcarduserMixinInters1 := wxcarduserMixin[1].Interceptors()
+	wxcarduser.Interceptors[0] = wxcarduserMixinInters1[0]
+	wxcarduserMixinFields0 := wxcarduserMixin[0].Fields()
+	_ = wxcarduserMixinFields0
+	wxcarduserFields := schema.WxCardUser{}.Fields()
+	_ = wxcarduserFields
+	// wxcarduserDescCreatedAt is the schema descriptor for created_at field.
+	wxcarduserDescCreatedAt := wxcarduserMixinFields0[1].Descriptor()
+	// wxcarduser.DefaultCreatedAt holds the default value on creation for the created_at field.
+	wxcarduser.DefaultCreatedAt = wxcarduserDescCreatedAt.Default.(func() time.Time)
+	// wxcarduserDescUpdatedAt is the schema descriptor for updated_at field.
+	wxcarduserDescUpdatedAt := wxcarduserMixinFields0[2].Descriptor()
+	// wxcarduser.DefaultUpdatedAt holds the default value on creation for the updated_at field.
+	wxcarduser.DefaultUpdatedAt = wxcarduserDescUpdatedAt.Default.(func() time.Time)
+	// wxcarduser.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
+	wxcarduser.UpdateDefaultUpdatedAt = wxcarduserDescUpdatedAt.UpdateDefault.(func() time.Time)
+	// wxcarduserDescWxid is the schema descriptor for wxid field.
+	wxcarduserDescWxid := wxcarduserFields[0].Descriptor()
+	// wxcarduser.DefaultWxid holds the default value on creation for the wxid field.
+	wxcarduser.DefaultWxid = wxcarduserDescWxid.Default.(string)
+	// wxcarduserDescAccount is the schema descriptor for account field.
+	wxcarduserDescAccount := wxcarduserFields[1].Descriptor()
+	// wxcarduser.DefaultAccount holds the default value on creation for the account field.
+	wxcarduser.DefaultAccount = wxcarduserDescAccount.Default.(string)
+	// wxcarduserDescAvatar is the schema descriptor for avatar field.
+	wxcarduserDescAvatar := wxcarduserFields[2].Descriptor()
+	// wxcarduser.DefaultAvatar holds the default value on creation for the avatar field.
+	wxcarduser.DefaultAvatar = wxcarduserDescAvatar.Default.(string)
+	// wxcarduserDescNickname is the schema descriptor for nickname field.
+	wxcarduserDescNickname := wxcarduserFields[3].Descriptor()
+	// wxcarduser.DefaultNickname holds the default value on creation for the nickname field.
+	wxcarduser.DefaultNickname = wxcarduserDescNickname.Default.(string)
+	// wxcarduserDescRemark is the schema descriptor for remark field.
+	wxcarduserDescRemark := wxcarduserFields[4].Descriptor()
+	// wxcarduser.DefaultRemark holds the default value on creation for the remark field.
+	wxcarduser.DefaultRemark = wxcarduserDescRemark.Default.(string)
+	// wxcarduserDescPhone is the schema descriptor for phone field.
+	wxcarduserDescPhone := wxcarduserFields[5].Descriptor()
+	// wxcarduser.DefaultPhone holds the default value on creation for the phone field.
+	wxcarduser.DefaultPhone = wxcarduserDescPhone.Default.(string)
+	// wxcarduserDescOpenID is the schema descriptor for open_id field.
+	wxcarduserDescOpenID := wxcarduserFields[6].Descriptor()
+	// wxcarduser.DefaultOpenID holds the default value on creation for the open_id field.
+	wxcarduser.DefaultOpenID = wxcarduserDescOpenID.Default.(string)
+	// wxcarduserDescUnionID is the schema descriptor for union_id field.
+	wxcarduserDescUnionID := wxcarduserFields[7].Descriptor()
+	// wxcarduser.DefaultUnionID holds the default value on creation for the union_id field.
+	wxcarduser.DefaultUnionID = wxcarduserDescUnionID.Default.(string)
+	// wxcarduserDescSessionKey is the schema descriptor for session_key field.
+	wxcarduserDescSessionKey := wxcarduserFields[8].Descriptor()
+	// wxcarduser.DefaultSessionKey holds the default value on creation for the session_key field.
+	wxcarduser.DefaultSessionKey = wxcarduserDescSessionKey.Default.(string)
+	wxcardvisitMixin := schema.WxCardVisit{}.Mixin()
+	wxcardvisitMixinHooks1 := wxcardvisitMixin[1].Hooks()
+	wxcardvisit.Hooks[0] = wxcardvisitMixinHooks1[0]
+	wxcardvisitMixinInters1 := wxcardvisitMixin[1].Interceptors()
+	wxcardvisit.Interceptors[0] = wxcardvisitMixinInters1[0]
+	wxcardvisitMixinFields0 := wxcardvisitMixin[0].Fields()
+	_ = wxcardvisitMixinFields0
+	wxcardvisitFields := schema.WxCardVisit{}.Fields()
+	_ = wxcardvisitFields
+	// wxcardvisitDescCreatedAt is the schema descriptor for created_at field.
+	wxcardvisitDescCreatedAt := wxcardvisitMixinFields0[1].Descriptor()
+	// wxcardvisit.DefaultCreatedAt holds the default value on creation for the created_at field.
+	wxcardvisit.DefaultCreatedAt = wxcardvisitDescCreatedAt.Default.(func() time.Time)
+	// wxcardvisitDescUpdatedAt is the schema descriptor for updated_at field.
+	wxcardvisitDescUpdatedAt := wxcardvisitMixinFields0[2].Descriptor()
+	// wxcardvisit.DefaultUpdatedAt holds the default value on creation for the updated_at field.
+	wxcardvisit.DefaultUpdatedAt = wxcardvisitDescUpdatedAt.Default.(func() time.Time)
+	// wxcardvisit.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
+	wxcardvisit.UpdateDefaultUpdatedAt = wxcardvisitDescUpdatedAt.UpdateDefault.(func() time.Time)
+	// wxcardvisitDescUserID is the schema descriptor for user_id field.
+	wxcardvisitDescUserID := wxcardvisitFields[0].Descriptor()
+	// wxcardvisit.DefaultUserID holds the default value on creation for the user_id field.
+	wxcardvisit.DefaultUserID = wxcardvisitDescUserID.Default.(uint64)
+	// wxcardvisitDescBotID is the schema descriptor for bot_id field.
+	wxcardvisitDescBotID := wxcardvisitFields[1].Descriptor()
+	// wxcardvisit.DefaultBotID holds the default value on creation for the bot_id field.
+	wxcardvisit.DefaultBotID = wxcardvisitDescBotID.Default.(uint64)
+	// wxcardvisitDescBotType is the schema descriptor for bot_type field.
+	wxcardvisitDescBotType := wxcardvisitFields[2].Descriptor()
+	// wxcardvisit.DefaultBotType holds the default value on creation for the bot_type field.
+	wxcardvisit.DefaultBotType = wxcardvisitDescBotType.Default.(uint8)
 }
 
 const (

+ 51 - 0
ent/schema/chat_records.go

@@ -0,0 +1,51 @@
+package schema
+
+import (
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/entsql"
+	"entgo.io/ent/schema"
+	"entgo.io/ent/schema/field"
+	"entgo.io/ent/schema/index"
+	"github.com/suyuan32/simple-admin-common/orm/ent/mixins"
+	"wechat-api/ent/schema/localmixin"
+)
+
+type ChatRecords struct {
+	ent.Schema
+}
+
+func (ChatRecords) Fields() []ent.Field {
+	return []ent.Field{
+		field.String("content").Default("").Comment("内容"),
+		field.Uint8("content_type").Default(1).Comment("内容类型:1-提问 2-回答"),
+		field.Uint64("session_id").Default(0).Comment("会话ID"),
+		field.Uint64("user_id").Default(0).Comment("用户ID"),
+		field.Uint64("bot_id").Default(0).Comment("聊天ID"),
+		field.Uint8("bot_type").Default(2).Comment("类型:1-微信 2-小程序card 3-智能体"),
+	}
+}
+
+func (ChatRecords) Mixin() []ent.Mixin {
+	return []ent.Mixin{
+		mixins.IDMixin{},
+		localmixin.SoftDeleteMixin{},
+	}
+}
+
+func (ChatRecords) Indexes() []ent.Index {
+	return []ent.Index{
+		index.Fields("user_id", "bot_id", "bot_type"),
+		index.Fields("session_id"),
+	}
+}
+
+func (ChatRecords) Edges() []ent.Edge {
+	return nil
+}
+
+func (ChatRecords) Annotations() []schema.Annotation {
+	return []schema.Annotation{
+		entsql.WithComments(true),
+		entsql.Annotation{Table: "chat_records"},
+	}
+}

+ 48 - 0
ent/schema/chat_session.go

@@ -0,0 +1,48 @@
+package schema
+
+import (
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/entsql"
+	"entgo.io/ent/schema"
+	"entgo.io/ent/schema/field"
+	"entgo.io/ent/schema/index"
+	"github.com/suyuan32/simple-admin-common/orm/ent/mixins"
+	"wechat-api/ent/schema/localmixin"
+)
+
+type ChatSession struct {
+	ent.Schema
+}
+
+func (ChatSession) Fields() []ent.Field {
+	return []ent.Field{
+		field.String("name").Default("").Comment("名称"),
+		field.Uint64("user_id").Default(0).Comment("用户ID"),
+		field.Uint64("bot_id").Default(0).Comment("聊天ID"),
+		field.Uint8("bot_type").Default(2).Comment("类型:1-微信 2-小程序card 3-智能体"),
+	}
+}
+
+func (ChatSession) Mixin() []ent.Mixin {
+	return []ent.Mixin{
+		mixins.IDMixin{},
+		localmixin.SoftDeleteMixin{},
+	}
+}
+
+func (ChatSession) Indexes() []ent.Index {
+	return []ent.Index{
+		index.Fields("user_id", "bot_id", "bot_type"),
+	}
+}
+
+func (ChatSession) Edges() []ent.Edge {
+	return nil
+}
+
+func (ChatSession) Annotations() []schema.Annotation {
+	return []schema.Annotation{
+		entsql.WithComments(true),
+		entsql.Annotation{Table: "chat_session"},
+	}
+}

+ 2 - 0
ent/schema/employee.go

@@ -33,6 +33,8 @@ func (Employee) Fields() []ent.Field {
 		field.String("video_url").MaxLen(1000).Default("").Comment("video_url | 视频地址"),
 		field.Uint64("organization_id").Positive().Comment("organization_id | 租户ID"),
 		field.Uint64("category_id").Positive().Comment("category_id | 分类ID"),
+		field.String("api_base").Default("").Comment("api_base"),
+		field.String("api_key").Default("").Comment("api_key"),
 	}
 }
 

+ 61 - 0
ent/schema/wx_card.go

@@ -0,0 +1,61 @@
+package schema
+
+import (
+	"wechat-api/ent/schema/localmixin"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/entsql"
+	"entgo.io/ent/schema"
+	"entgo.io/ent/schema/field"
+	"entgo.io/ent/schema/index"
+	"github.com/suyuan32/simple-admin-common/orm/ent/mixins"
+)
+
+type WxCard struct {
+	ent.Schema
+}
+
+func (WxCard) Fields() []ent.Field {
+	return []ent.Field{
+		field.Uint64("user_id").Optional().Default(0).Comment("user表ID"),
+		field.Uint64("wx_user_id").Optional().Default(0).Comment("wx表ID"),
+		field.String("avatar").Default("").Comment("头像"),
+		field.String("logo").Default("").Comment("logo"),
+		field.String("name").Default("").Comment("名称"),
+		field.String("company").Default("").Comment("公司"),
+		field.String("address").Default("").Comment("地址"),
+		field.String("phone").Default("").Comment("手机号"),
+		field.String("official_account").Default("").Comment("公众号"),
+		field.String("wechat_account").Default("").Comment("微信号"),
+		field.String("email").Optional().Default("").Comment("邮箱"),
+		field.String("api_base").Optional().Comment("fastgpt-base"),
+		field.String("api_key").Optional().Comment("fastgpt-key"),
+		field.String("ai_info").Optional().Comment("AI信息"),
+		field.String("intro").Optional().Default("").Comment("个人介绍"),
+	}
+}
+
+func (WxCard) Mixin() []ent.Mixin {
+	return []ent.Mixin{
+		mixins.IDMixin{},
+		localmixin.SoftDeleteMixin{},
+	}
+}
+
+func (WxCard) Indexes() []ent.Index {
+	return []ent.Index{
+		index.Fields("user_id"),
+		index.Fields("wx_user_id"),
+	}
+}
+
+func (WxCard) Edges() []ent.Edge {
+	return nil
+}
+
+func (WxCard) Annotations() []schema.Annotation {
+	return []schema.Annotation{
+		entsql.WithComments(true),
+		entsql.Annotation{Table: "wx_card"},
+	}
+}

+ 54 - 0
ent/schema/wx_card_user.go

@@ -0,0 +1,54 @@
+package schema
+
+import (
+	"wechat-api/ent/schema/localmixin"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/entsql"
+	"entgo.io/ent/schema"
+	"entgo.io/ent/schema/field"
+	"entgo.io/ent/schema/index"
+	"github.com/suyuan32/simple-admin-common/orm/ent/mixins"
+)
+
+type WxCardUser struct {
+	ent.Schema
+}
+
+func (WxCardUser) Fields() []ent.Field {
+	return []ent.Field{
+		field.String("wxid").Default("").Default("").Comment("微信id"),
+		field.String("account").Default("").Comment("微信号"),
+		field.String("avatar").Default("").Comment("头像"),
+		field.String("nickname").Default("").Comment("昵称"),
+		field.String("remark").Default("").Comment("备注名"),
+		field.String("phone").Default("").Comment("手机号"),
+		field.String("open_id").Default("").Comment("OpenID"),
+		field.String("union_id").Default("").Comment("UnionID"),
+		field.String("session_key").Default("").Comment("SessionKey"),
+	}
+}
+
+func (WxCardUser) Mixin() []ent.Mixin {
+	return []ent.Mixin{
+		mixins.IDMixin{},
+		localmixin.SoftDeleteMixin{},
+	}
+}
+
+func (WxCardUser) Indexes() []ent.Index {
+	return []ent.Index{
+		index.Fields("wxid", "open_id"),
+	}
+}
+
+func (WxCardUser) Edges() []ent.Edge {
+	return nil
+}
+
+func (WxCardUser) Annotations() []schema.Annotation {
+	return []schema.Annotation{
+		entsql.WithComments(true),
+		entsql.Annotation{Table: "wx_card_user"},
+	}
+}

+ 49 - 0
ent/schema/wx_card_visit.go

@@ -0,0 +1,49 @@
+package schema
+
+import (
+	"wechat-api/ent/schema/localmixin"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/entsql"
+	"entgo.io/ent/schema"
+	"entgo.io/ent/schema/field"
+	"entgo.io/ent/schema/index"
+	"github.com/suyuan32/simple-admin-common/orm/ent/mixins"
+)
+
+type WxCardVisit struct {
+	ent.Schema
+}
+
+func (WxCardVisit) Fields() []ent.Field {
+	return []ent.Field{
+		field.Uint64("user_id").Optional().Default(0).Comment("user表ID"),
+		field.Uint64("bot_id").Default(0).Comment("被访ID"),
+		field.Uint8("bot_type").Default(0).Comment("类型:1-微信 2-小程序 3-智能体"),
+	}
+}
+
+func (WxCardVisit) Mixin() []ent.Mixin {
+	return []ent.Mixin{
+		mixins.IDMixin{},
+		localmixin.SoftDeleteMixin{},
+	}
+}
+
+func (WxCardVisit) Indexes() []ent.Index {
+	return []ent.Index{
+		index.Fields("user_id"),
+		index.Fields("bot_id", "bot_type"),
+	}
+}
+
+func (WxCardVisit) Edges() []ent.Edge {
+	return nil
+}
+
+func (WxCardVisit) Annotations() []schema.Annotation {
+	return []schema.Annotation{
+		entsql.WithComments(true),
+		entsql.Annotation{Table: "wx_card_visit"},
+	}
+}

+ 1176 - 0
ent/set_not_nil.go

@@ -968,6 +968,342 @@ func (c *CategoryCreate) SetNotNilOrganizationID(value *uint64) *CategoryCreate
 }
 
 // set field if value's pointer is not nil.
+func (cr *ChatRecordsUpdate) SetNotNilUpdatedAt(value *time.Time) *ChatRecordsUpdate {
+	if value != nil {
+		return cr.SetUpdatedAt(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsUpdateOne) SetNotNilUpdatedAt(value *time.Time) *ChatRecordsUpdateOne {
+	if value != nil {
+		return cr.SetUpdatedAt(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsCreate) SetNotNilUpdatedAt(value *time.Time) *ChatRecordsCreate {
+	if value != nil {
+		return cr.SetUpdatedAt(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsUpdate) SetNotNilDeletedAt(value *time.Time) *ChatRecordsUpdate {
+	if value != nil {
+		return cr.SetDeletedAt(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsUpdateOne) SetNotNilDeletedAt(value *time.Time) *ChatRecordsUpdateOne {
+	if value != nil {
+		return cr.SetDeletedAt(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsCreate) SetNotNilDeletedAt(value *time.Time) *ChatRecordsCreate {
+	if value != nil {
+		return cr.SetDeletedAt(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsUpdate) SetNotNilContent(value *string) *ChatRecordsUpdate {
+	if value != nil {
+		return cr.SetContent(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsUpdateOne) SetNotNilContent(value *string) *ChatRecordsUpdateOne {
+	if value != nil {
+		return cr.SetContent(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsCreate) SetNotNilContent(value *string) *ChatRecordsCreate {
+	if value != nil {
+		return cr.SetContent(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsUpdate) SetNotNilContentType(value *uint8) *ChatRecordsUpdate {
+	if value != nil {
+		return cr.SetContentType(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsUpdateOne) SetNotNilContentType(value *uint8) *ChatRecordsUpdateOne {
+	if value != nil {
+		return cr.SetContentType(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsCreate) SetNotNilContentType(value *uint8) *ChatRecordsCreate {
+	if value != nil {
+		return cr.SetContentType(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsUpdate) SetNotNilSessionID(value *uint64) *ChatRecordsUpdate {
+	if value != nil {
+		return cr.SetSessionID(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsUpdateOne) SetNotNilSessionID(value *uint64) *ChatRecordsUpdateOne {
+	if value != nil {
+		return cr.SetSessionID(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsCreate) SetNotNilSessionID(value *uint64) *ChatRecordsCreate {
+	if value != nil {
+		return cr.SetSessionID(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsUpdate) SetNotNilUserID(value *uint64) *ChatRecordsUpdate {
+	if value != nil {
+		return cr.SetUserID(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsUpdateOne) SetNotNilUserID(value *uint64) *ChatRecordsUpdateOne {
+	if value != nil {
+		return cr.SetUserID(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsCreate) SetNotNilUserID(value *uint64) *ChatRecordsCreate {
+	if value != nil {
+		return cr.SetUserID(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsUpdate) SetNotNilBotID(value *uint64) *ChatRecordsUpdate {
+	if value != nil {
+		return cr.SetBotID(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsUpdateOne) SetNotNilBotID(value *uint64) *ChatRecordsUpdateOne {
+	if value != nil {
+		return cr.SetBotID(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsCreate) SetNotNilBotID(value *uint64) *ChatRecordsCreate {
+	if value != nil {
+		return cr.SetBotID(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsUpdate) SetNotNilBotType(value *uint8) *ChatRecordsUpdate {
+	if value != nil {
+		return cr.SetBotType(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsUpdateOne) SetNotNilBotType(value *uint8) *ChatRecordsUpdateOne {
+	if value != nil {
+		return cr.SetBotType(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cr *ChatRecordsCreate) SetNotNilBotType(value *uint8) *ChatRecordsCreate {
+	if value != nil {
+		return cr.SetBotType(*value)
+	}
+	return cr
+}
+
+// set field if value's pointer is not nil.
+func (cs *ChatSessionUpdate) SetNotNilUpdatedAt(value *time.Time) *ChatSessionUpdate {
+	if value != nil {
+		return cs.SetUpdatedAt(*value)
+	}
+	return cs
+}
+
+// set field if value's pointer is not nil.
+func (cs *ChatSessionUpdateOne) SetNotNilUpdatedAt(value *time.Time) *ChatSessionUpdateOne {
+	if value != nil {
+		return cs.SetUpdatedAt(*value)
+	}
+	return cs
+}
+
+// set field if value's pointer is not nil.
+func (cs *ChatSessionCreate) SetNotNilUpdatedAt(value *time.Time) *ChatSessionCreate {
+	if value != nil {
+		return cs.SetUpdatedAt(*value)
+	}
+	return cs
+}
+
+// set field if value's pointer is not nil.
+func (cs *ChatSessionUpdate) SetNotNilDeletedAt(value *time.Time) *ChatSessionUpdate {
+	if value != nil {
+		return cs.SetDeletedAt(*value)
+	}
+	return cs
+}
+
+// set field if value's pointer is not nil.
+func (cs *ChatSessionUpdateOne) SetNotNilDeletedAt(value *time.Time) *ChatSessionUpdateOne {
+	if value != nil {
+		return cs.SetDeletedAt(*value)
+	}
+	return cs
+}
+
+// set field if value's pointer is not nil.
+func (cs *ChatSessionCreate) SetNotNilDeletedAt(value *time.Time) *ChatSessionCreate {
+	if value != nil {
+		return cs.SetDeletedAt(*value)
+	}
+	return cs
+}
+
+// set field if value's pointer is not nil.
+func (cs *ChatSessionUpdate) SetNotNilName(value *string) *ChatSessionUpdate {
+	if value != nil {
+		return cs.SetName(*value)
+	}
+	return cs
+}
+
+// set field if value's pointer is not nil.
+func (cs *ChatSessionUpdateOne) SetNotNilName(value *string) *ChatSessionUpdateOne {
+	if value != nil {
+		return cs.SetName(*value)
+	}
+	return cs
+}
+
+// set field if value's pointer is not nil.
+func (cs *ChatSessionCreate) SetNotNilName(value *string) *ChatSessionCreate {
+	if value != nil {
+		return cs.SetName(*value)
+	}
+	return cs
+}
+
+// set field if value's pointer is not nil.
+func (cs *ChatSessionUpdate) SetNotNilUserID(value *uint64) *ChatSessionUpdate {
+	if value != nil {
+		return cs.SetUserID(*value)
+	}
+	return cs
+}
+
+// set field if value's pointer is not nil.
+func (cs *ChatSessionUpdateOne) SetNotNilUserID(value *uint64) *ChatSessionUpdateOne {
+	if value != nil {
+		return cs.SetUserID(*value)
+	}
+	return cs
+}
+
+// set field if value's pointer is not nil.
+func (cs *ChatSessionCreate) SetNotNilUserID(value *uint64) *ChatSessionCreate {
+	if value != nil {
+		return cs.SetUserID(*value)
+	}
+	return cs
+}
+
+// set field if value's pointer is not nil.
+func (cs *ChatSessionUpdate) SetNotNilBotID(value *uint64) *ChatSessionUpdate {
+	if value != nil {
+		return cs.SetBotID(*value)
+	}
+	return cs
+}
+
+// set field if value's pointer is not nil.
+func (cs *ChatSessionUpdateOne) SetNotNilBotID(value *uint64) *ChatSessionUpdateOne {
+	if value != nil {
+		return cs.SetBotID(*value)
+	}
+	return cs
+}
+
+// set field if value's pointer is not nil.
+func (cs *ChatSessionCreate) SetNotNilBotID(value *uint64) *ChatSessionCreate {
+	if value != nil {
+		return cs.SetBotID(*value)
+	}
+	return cs
+}
+
+// set field if value's pointer is not nil.
+func (cs *ChatSessionUpdate) SetNotNilBotType(value *uint8) *ChatSessionUpdate {
+	if value != nil {
+		return cs.SetBotType(*value)
+	}
+	return cs
+}
+
+// set field if value's pointer is not nil.
+func (cs *ChatSessionUpdateOne) SetNotNilBotType(value *uint8) *ChatSessionUpdateOne {
+	if value != nil {
+		return cs.SetBotType(*value)
+	}
+	return cs
+}
+
+// set field if value's pointer is not nil.
+func (cs *ChatSessionCreate) SetNotNilBotType(value *uint8) *ChatSessionCreate {
+	if value != nil {
+		return cs.SetBotType(*value)
+	}
+	return cs
+}
+
+// set field if value's pointer is not nil.
 func (c *ContactUpdate) SetNotNilUpdatedAt(value *time.Time) *ContactUpdate {
 	if value != nil {
 		return c.SetUpdatedAt(*value)
@@ -1832,6 +2168,54 @@ func (e *EmployeeCreate) SetNotNilCategoryID(value *uint64) *EmployeeCreate {
 }
 
 // set field if value's pointer is not nil.
+func (e *EmployeeUpdate) SetNotNilAPIBase(value *string) *EmployeeUpdate {
+	if value != nil {
+		return e.SetAPIBase(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdateOne) SetNotNilAPIBase(value *string) *EmployeeUpdateOne {
+	if value != nil {
+		return e.SetAPIBase(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeCreate) SetNotNilAPIBase(value *string) *EmployeeCreate {
+	if value != nil {
+		return e.SetAPIBase(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdate) SetNotNilAPIKey(value *string) *EmployeeUpdate {
+	if value != nil {
+		return e.SetAPIKey(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdateOne) SetNotNilAPIKey(value *string) *EmployeeUpdateOne {
+	if value != nil {
+		return e.SetAPIKey(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeCreate) SetNotNilAPIKey(value *string) *EmployeeCreate {
+	if value != nil {
+		return e.SetAPIKey(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
 func (ec *EmployeeConfigUpdate) SetNotNilUpdatedAt(value *time.Time) *EmployeeConfigUpdate {
 	if value != nil {
 		return ec.SetUpdatedAt(*value)
@@ -4830,3 +5214,795 @@ func (w *WxCreate) SetNotNilGroupBlockList(value []string) *WxCreate {
 	}
 	return w
 }
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdate) SetNotNilUpdatedAt(value *time.Time) *WxCardUpdate {
+	if value != nil {
+		return wc.SetUpdatedAt(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdateOne) SetNotNilUpdatedAt(value *time.Time) *WxCardUpdateOne {
+	if value != nil {
+		return wc.SetUpdatedAt(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardCreate) SetNotNilUpdatedAt(value *time.Time) *WxCardCreate {
+	if value != nil {
+		return wc.SetUpdatedAt(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdate) SetNotNilDeletedAt(value *time.Time) *WxCardUpdate {
+	if value != nil {
+		return wc.SetDeletedAt(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdateOne) SetNotNilDeletedAt(value *time.Time) *WxCardUpdateOne {
+	if value != nil {
+		return wc.SetDeletedAt(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardCreate) SetNotNilDeletedAt(value *time.Time) *WxCardCreate {
+	if value != nil {
+		return wc.SetDeletedAt(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdate) SetNotNilUserID(value *uint64) *WxCardUpdate {
+	if value != nil {
+		return wc.SetUserID(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdateOne) SetNotNilUserID(value *uint64) *WxCardUpdateOne {
+	if value != nil {
+		return wc.SetUserID(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardCreate) SetNotNilUserID(value *uint64) *WxCardCreate {
+	if value != nil {
+		return wc.SetUserID(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdate) SetNotNilWxUserID(value *uint64) *WxCardUpdate {
+	if value != nil {
+		return wc.SetWxUserID(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdateOne) SetNotNilWxUserID(value *uint64) *WxCardUpdateOne {
+	if value != nil {
+		return wc.SetWxUserID(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardCreate) SetNotNilWxUserID(value *uint64) *WxCardCreate {
+	if value != nil {
+		return wc.SetWxUserID(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdate) SetNotNilAvatar(value *string) *WxCardUpdate {
+	if value != nil {
+		return wc.SetAvatar(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdateOne) SetNotNilAvatar(value *string) *WxCardUpdateOne {
+	if value != nil {
+		return wc.SetAvatar(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardCreate) SetNotNilAvatar(value *string) *WxCardCreate {
+	if value != nil {
+		return wc.SetAvatar(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdate) SetNotNilLogo(value *string) *WxCardUpdate {
+	if value != nil {
+		return wc.SetLogo(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdateOne) SetNotNilLogo(value *string) *WxCardUpdateOne {
+	if value != nil {
+		return wc.SetLogo(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardCreate) SetNotNilLogo(value *string) *WxCardCreate {
+	if value != nil {
+		return wc.SetLogo(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdate) SetNotNilName(value *string) *WxCardUpdate {
+	if value != nil {
+		return wc.SetName(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdateOne) SetNotNilName(value *string) *WxCardUpdateOne {
+	if value != nil {
+		return wc.SetName(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardCreate) SetNotNilName(value *string) *WxCardCreate {
+	if value != nil {
+		return wc.SetName(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdate) SetNotNilCompany(value *string) *WxCardUpdate {
+	if value != nil {
+		return wc.SetCompany(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdateOne) SetNotNilCompany(value *string) *WxCardUpdateOne {
+	if value != nil {
+		return wc.SetCompany(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardCreate) SetNotNilCompany(value *string) *WxCardCreate {
+	if value != nil {
+		return wc.SetCompany(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdate) SetNotNilAddress(value *string) *WxCardUpdate {
+	if value != nil {
+		return wc.SetAddress(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdateOne) SetNotNilAddress(value *string) *WxCardUpdateOne {
+	if value != nil {
+		return wc.SetAddress(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardCreate) SetNotNilAddress(value *string) *WxCardCreate {
+	if value != nil {
+		return wc.SetAddress(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdate) SetNotNilPhone(value *string) *WxCardUpdate {
+	if value != nil {
+		return wc.SetPhone(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdateOne) SetNotNilPhone(value *string) *WxCardUpdateOne {
+	if value != nil {
+		return wc.SetPhone(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardCreate) SetNotNilPhone(value *string) *WxCardCreate {
+	if value != nil {
+		return wc.SetPhone(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdate) SetNotNilOfficialAccount(value *string) *WxCardUpdate {
+	if value != nil {
+		return wc.SetOfficialAccount(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdateOne) SetNotNilOfficialAccount(value *string) *WxCardUpdateOne {
+	if value != nil {
+		return wc.SetOfficialAccount(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardCreate) SetNotNilOfficialAccount(value *string) *WxCardCreate {
+	if value != nil {
+		return wc.SetOfficialAccount(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdate) SetNotNilWechatAccount(value *string) *WxCardUpdate {
+	if value != nil {
+		return wc.SetWechatAccount(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdateOne) SetNotNilWechatAccount(value *string) *WxCardUpdateOne {
+	if value != nil {
+		return wc.SetWechatAccount(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardCreate) SetNotNilWechatAccount(value *string) *WxCardCreate {
+	if value != nil {
+		return wc.SetWechatAccount(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdate) SetNotNilEmail(value *string) *WxCardUpdate {
+	if value != nil {
+		return wc.SetEmail(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdateOne) SetNotNilEmail(value *string) *WxCardUpdateOne {
+	if value != nil {
+		return wc.SetEmail(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardCreate) SetNotNilEmail(value *string) *WxCardCreate {
+	if value != nil {
+		return wc.SetEmail(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdate) SetNotNilAPIBase(value *string) *WxCardUpdate {
+	if value != nil {
+		return wc.SetAPIBase(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdateOne) SetNotNilAPIBase(value *string) *WxCardUpdateOne {
+	if value != nil {
+		return wc.SetAPIBase(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardCreate) SetNotNilAPIBase(value *string) *WxCardCreate {
+	if value != nil {
+		return wc.SetAPIBase(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdate) SetNotNilAPIKey(value *string) *WxCardUpdate {
+	if value != nil {
+		return wc.SetAPIKey(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdateOne) SetNotNilAPIKey(value *string) *WxCardUpdateOne {
+	if value != nil {
+		return wc.SetAPIKey(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardCreate) SetNotNilAPIKey(value *string) *WxCardCreate {
+	if value != nil {
+		return wc.SetAPIKey(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdate) SetNotNilAiInfo(value *string) *WxCardUpdate {
+	if value != nil {
+		return wc.SetAiInfo(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdateOne) SetNotNilAiInfo(value *string) *WxCardUpdateOne {
+	if value != nil {
+		return wc.SetAiInfo(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardCreate) SetNotNilAiInfo(value *string) *WxCardCreate {
+	if value != nil {
+		return wc.SetAiInfo(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdate) SetNotNilIntro(value *string) *WxCardUpdate {
+	if value != nil {
+		return wc.SetIntro(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardUpdateOne) SetNotNilIntro(value *string) *WxCardUpdateOne {
+	if value != nil {
+		return wc.SetIntro(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wc *WxCardCreate) SetNotNilIntro(value *string) *WxCardCreate {
+	if value != nil {
+		return wc.SetIntro(*value)
+	}
+	return wc
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdate) SetNotNilUpdatedAt(value *time.Time) *WxCardUserUpdate {
+	if value != nil {
+		return wcu.SetUpdatedAt(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdateOne) SetNotNilUpdatedAt(value *time.Time) *WxCardUserUpdateOne {
+	if value != nil {
+		return wcu.SetUpdatedAt(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserCreate) SetNotNilUpdatedAt(value *time.Time) *WxCardUserCreate {
+	if value != nil {
+		return wcu.SetUpdatedAt(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdate) SetNotNilDeletedAt(value *time.Time) *WxCardUserUpdate {
+	if value != nil {
+		return wcu.SetDeletedAt(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdateOne) SetNotNilDeletedAt(value *time.Time) *WxCardUserUpdateOne {
+	if value != nil {
+		return wcu.SetDeletedAt(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserCreate) SetNotNilDeletedAt(value *time.Time) *WxCardUserCreate {
+	if value != nil {
+		return wcu.SetDeletedAt(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdate) SetNotNilWxid(value *string) *WxCardUserUpdate {
+	if value != nil {
+		return wcu.SetWxid(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdateOne) SetNotNilWxid(value *string) *WxCardUserUpdateOne {
+	if value != nil {
+		return wcu.SetWxid(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserCreate) SetNotNilWxid(value *string) *WxCardUserCreate {
+	if value != nil {
+		return wcu.SetWxid(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdate) SetNotNilAccount(value *string) *WxCardUserUpdate {
+	if value != nil {
+		return wcu.SetAccount(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdateOne) SetNotNilAccount(value *string) *WxCardUserUpdateOne {
+	if value != nil {
+		return wcu.SetAccount(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserCreate) SetNotNilAccount(value *string) *WxCardUserCreate {
+	if value != nil {
+		return wcu.SetAccount(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdate) SetNotNilAvatar(value *string) *WxCardUserUpdate {
+	if value != nil {
+		return wcu.SetAvatar(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdateOne) SetNotNilAvatar(value *string) *WxCardUserUpdateOne {
+	if value != nil {
+		return wcu.SetAvatar(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserCreate) SetNotNilAvatar(value *string) *WxCardUserCreate {
+	if value != nil {
+		return wcu.SetAvatar(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdate) SetNotNilNickname(value *string) *WxCardUserUpdate {
+	if value != nil {
+		return wcu.SetNickname(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdateOne) SetNotNilNickname(value *string) *WxCardUserUpdateOne {
+	if value != nil {
+		return wcu.SetNickname(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserCreate) SetNotNilNickname(value *string) *WxCardUserCreate {
+	if value != nil {
+		return wcu.SetNickname(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdate) SetNotNilRemark(value *string) *WxCardUserUpdate {
+	if value != nil {
+		return wcu.SetRemark(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdateOne) SetNotNilRemark(value *string) *WxCardUserUpdateOne {
+	if value != nil {
+		return wcu.SetRemark(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserCreate) SetNotNilRemark(value *string) *WxCardUserCreate {
+	if value != nil {
+		return wcu.SetRemark(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdate) SetNotNilPhone(value *string) *WxCardUserUpdate {
+	if value != nil {
+		return wcu.SetPhone(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdateOne) SetNotNilPhone(value *string) *WxCardUserUpdateOne {
+	if value != nil {
+		return wcu.SetPhone(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserCreate) SetNotNilPhone(value *string) *WxCardUserCreate {
+	if value != nil {
+		return wcu.SetPhone(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdate) SetNotNilOpenID(value *string) *WxCardUserUpdate {
+	if value != nil {
+		return wcu.SetOpenID(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdateOne) SetNotNilOpenID(value *string) *WxCardUserUpdateOne {
+	if value != nil {
+		return wcu.SetOpenID(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserCreate) SetNotNilOpenID(value *string) *WxCardUserCreate {
+	if value != nil {
+		return wcu.SetOpenID(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdate) SetNotNilUnionID(value *string) *WxCardUserUpdate {
+	if value != nil {
+		return wcu.SetUnionID(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdateOne) SetNotNilUnionID(value *string) *WxCardUserUpdateOne {
+	if value != nil {
+		return wcu.SetUnionID(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserCreate) SetNotNilUnionID(value *string) *WxCardUserCreate {
+	if value != nil {
+		return wcu.SetUnionID(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdate) SetNotNilSessionKey(value *string) *WxCardUserUpdate {
+	if value != nil {
+		return wcu.SetSessionKey(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserUpdateOne) SetNotNilSessionKey(value *string) *WxCardUserUpdateOne {
+	if value != nil {
+		return wcu.SetSessionKey(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcu *WxCardUserCreate) SetNotNilSessionKey(value *string) *WxCardUserCreate {
+	if value != nil {
+		return wcu.SetSessionKey(*value)
+	}
+	return wcu
+}
+
+// set field if value's pointer is not nil.
+func (wcv *WxCardVisitUpdate) SetNotNilUpdatedAt(value *time.Time) *WxCardVisitUpdate {
+	if value != nil {
+		return wcv.SetUpdatedAt(*value)
+	}
+	return wcv
+}
+
+// set field if value's pointer is not nil.
+func (wcv *WxCardVisitUpdateOne) SetNotNilUpdatedAt(value *time.Time) *WxCardVisitUpdateOne {
+	if value != nil {
+		return wcv.SetUpdatedAt(*value)
+	}
+	return wcv
+}
+
+// set field if value's pointer is not nil.
+func (wcv *WxCardVisitCreate) SetNotNilUpdatedAt(value *time.Time) *WxCardVisitCreate {
+	if value != nil {
+		return wcv.SetUpdatedAt(*value)
+	}
+	return wcv
+}
+
+// set field if value's pointer is not nil.
+func (wcv *WxCardVisitUpdate) SetNotNilDeletedAt(value *time.Time) *WxCardVisitUpdate {
+	if value != nil {
+		return wcv.SetDeletedAt(*value)
+	}
+	return wcv
+}
+
+// set field if value's pointer is not nil.
+func (wcv *WxCardVisitUpdateOne) SetNotNilDeletedAt(value *time.Time) *WxCardVisitUpdateOne {
+	if value != nil {
+		return wcv.SetDeletedAt(*value)
+	}
+	return wcv
+}
+
+// set field if value's pointer is not nil.
+func (wcv *WxCardVisitCreate) SetNotNilDeletedAt(value *time.Time) *WxCardVisitCreate {
+	if value != nil {
+		return wcv.SetDeletedAt(*value)
+	}
+	return wcv
+}
+
+// set field if value's pointer is not nil.
+func (wcv *WxCardVisitUpdate) SetNotNilUserID(value *uint64) *WxCardVisitUpdate {
+	if value != nil {
+		return wcv.SetUserID(*value)
+	}
+	return wcv
+}
+
+// set field if value's pointer is not nil.
+func (wcv *WxCardVisitUpdateOne) SetNotNilUserID(value *uint64) *WxCardVisitUpdateOne {
+	if value != nil {
+		return wcv.SetUserID(*value)
+	}
+	return wcv
+}
+
+// set field if value's pointer is not nil.
+func (wcv *WxCardVisitCreate) SetNotNilUserID(value *uint64) *WxCardVisitCreate {
+	if value != nil {
+		return wcv.SetUserID(*value)
+	}
+	return wcv
+}
+
+// set field if value's pointer is not nil.
+func (wcv *WxCardVisitUpdate) SetNotNilBotID(value *uint64) *WxCardVisitUpdate {
+	if value != nil {
+		return wcv.SetBotID(*value)
+	}
+	return wcv
+}
+
+// set field if value's pointer is not nil.
+func (wcv *WxCardVisitUpdateOne) SetNotNilBotID(value *uint64) *WxCardVisitUpdateOne {
+	if value != nil {
+		return wcv.SetBotID(*value)
+	}
+	return wcv
+}
+
+// set field if value's pointer is not nil.
+func (wcv *WxCardVisitCreate) SetNotNilBotID(value *uint64) *WxCardVisitCreate {
+	if value != nil {
+		return wcv.SetBotID(*value)
+	}
+	return wcv
+}
+
+// set field if value's pointer is not nil.
+func (wcv *WxCardVisitUpdate) SetNotNilBotType(value *uint8) *WxCardVisitUpdate {
+	if value != nil {
+		return wcv.SetBotType(*value)
+	}
+	return wcv
+}
+
+// set field if value's pointer is not nil.
+func (wcv *WxCardVisitUpdateOne) SetNotNilBotType(value *uint8) *WxCardVisitUpdateOne {
+	if value != nil {
+		return wcv.SetBotType(*value)
+	}
+	return wcv
+}
+
+// set field if value's pointer is not nil.
+func (wcv *WxCardVisitCreate) SetNotNilBotType(value *uint8) *WxCardVisitCreate {
+	if value != nil {
+		return wcv.SetBotType(*value)
+	}
+	return wcv
+}

+ 15 - 0
ent/tx.go

@@ -22,6 +22,10 @@ type Tx struct {
 	BatchMsg *BatchMsgClient
 	// Category is the client for interacting with the Category builders.
 	Category *CategoryClient
+	// ChatRecords is the client for interacting with the ChatRecords builders.
+	ChatRecords *ChatRecordsClient
+	// ChatSession is the client for interacting with the ChatSession builders.
+	ChatSession *ChatSessionClient
 	// Contact is the client for interacting with the Contact builders.
 	Contact *ContactClient
 	// Employee is the client for interacting with the Employee builders.
@@ -54,6 +58,12 @@ type Tx struct {
 	WorkExperience *WorkExperienceClient
 	// Wx is the client for interacting with the Wx builders.
 	Wx *WxClient
+	// WxCard is the client for interacting with the WxCard builders.
+	WxCard *WxCardClient
+	// WxCardUser is the client for interacting with the WxCardUser builders.
+	WxCardUser *WxCardUserClient
+	// WxCardVisit is the client for interacting with the WxCardVisit builders.
+	WxCardVisit *WxCardVisitClient
 
 	// lazily loaded.
 	client     *Client
@@ -189,6 +199,8 @@ func (tx *Tx) init() {
 	tx.AgentBase = NewAgentBaseClient(tx.config)
 	tx.BatchMsg = NewBatchMsgClient(tx.config)
 	tx.Category = NewCategoryClient(tx.config)
+	tx.ChatRecords = NewChatRecordsClient(tx.config)
+	tx.ChatSession = NewChatSessionClient(tx.config)
 	tx.Contact = NewContactClient(tx.config)
 	tx.Employee = NewEmployeeClient(tx.config)
 	tx.EmployeeConfig = NewEmployeeConfigClient(tx.config)
@@ -205,6 +217,9 @@ func (tx *Tx) init() {
 	tx.Tutorial = NewTutorialClient(tx.config)
 	tx.WorkExperience = NewWorkExperienceClient(tx.config)
 	tx.Wx = NewWxClient(tx.config)
+	tx.WxCard = NewWxCardClient(tx.config)
+	tx.WxCardUser = NewWxCardUserClient(tx.config)
+	tx.WxCardVisit = NewWxCardVisitClient(tx.config)
 }
 
 // txDriver wraps the given dialect.Tx with a nop dialect.Driver implementation.

+ 293 - 0
ent/wxcard.go

@@ -0,0 +1,293 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"fmt"
+	"strings"
+	"time"
+	"wechat-api/ent/wxcard"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+)
+
+// WxCard is the model entity for the WxCard schema.
+type WxCard struct {
+	config `json:"-"`
+	// ID of the ent.
+	ID uint64 `json:"id,omitempty"`
+	// Create Time | 创建日期
+	CreatedAt time.Time `json:"created_at,omitempty"`
+	// Update Time | 修改日期
+	UpdatedAt time.Time `json:"updated_at,omitempty"`
+	// Delete Time | 删除日期
+	DeletedAt time.Time `json:"deleted_at,omitempty"`
+	// user表ID
+	UserID uint64 `json:"user_id,omitempty"`
+	// wx表ID
+	WxUserID uint64 `json:"wx_user_id,omitempty"`
+	// 头像
+	Avatar string `json:"avatar,omitempty"`
+	// logo
+	Logo string `json:"logo,omitempty"`
+	// 名称
+	Name string `json:"name,omitempty"`
+	// 公司
+	Company string `json:"company,omitempty"`
+	// 地址
+	Address string `json:"address,omitempty"`
+	// 手机号
+	Phone string `json:"phone,omitempty"`
+	// 公众号
+	OfficialAccount string `json:"official_account,omitempty"`
+	// 微信号
+	WechatAccount string `json:"wechat_account,omitempty"`
+	// 邮箱
+	Email string `json:"email,omitempty"`
+	// fastgpt-base
+	APIBase string `json:"api_base,omitempty"`
+	// fastgpt-key
+	APIKey string `json:"api_key,omitempty"`
+	// AI信息
+	AiInfo string `json:"ai_info,omitempty"`
+	// 个人介绍
+	Intro        string `json:"intro,omitempty"`
+	selectValues sql.SelectValues
+}
+
+// scanValues returns the types for scanning values from sql.Rows.
+func (*WxCard) scanValues(columns []string) ([]any, error) {
+	values := make([]any, len(columns))
+	for i := range columns {
+		switch columns[i] {
+		case wxcard.FieldID, wxcard.FieldUserID, wxcard.FieldWxUserID:
+			values[i] = new(sql.NullInt64)
+		case wxcard.FieldAvatar, wxcard.FieldLogo, wxcard.FieldName, wxcard.FieldCompany, wxcard.FieldAddress, wxcard.FieldPhone, wxcard.FieldOfficialAccount, wxcard.FieldWechatAccount, wxcard.FieldEmail, wxcard.FieldAPIBase, wxcard.FieldAPIKey, wxcard.FieldAiInfo, wxcard.FieldIntro:
+			values[i] = new(sql.NullString)
+		case wxcard.FieldCreatedAt, wxcard.FieldUpdatedAt, wxcard.FieldDeletedAt:
+			values[i] = new(sql.NullTime)
+		default:
+			values[i] = new(sql.UnknownType)
+		}
+	}
+	return values, nil
+}
+
+// assignValues assigns the values that were returned from sql.Rows (after scanning)
+// to the WxCard fields.
+func (wc *WxCard) assignValues(columns []string, values []any) error {
+	if m, n := len(values), len(columns); m < n {
+		return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
+	}
+	for i := range columns {
+		switch columns[i] {
+		case wxcard.FieldID:
+			value, ok := values[i].(*sql.NullInt64)
+			if !ok {
+				return fmt.Errorf("unexpected type %T for field id", value)
+			}
+			wc.ID = uint64(value.Int64)
+		case wxcard.FieldCreatedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field created_at", values[i])
+			} else if value.Valid {
+				wc.CreatedAt = value.Time
+			}
+		case wxcard.FieldUpdatedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field updated_at", values[i])
+			} else if value.Valid {
+				wc.UpdatedAt = value.Time
+			}
+		case wxcard.FieldDeletedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field deleted_at", values[i])
+			} else if value.Valid {
+				wc.DeletedAt = value.Time
+			}
+		case wxcard.FieldUserID:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field user_id", values[i])
+			} else if value.Valid {
+				wc.UserID = uint64(value.Int64)
+			}
+		case wxcard.FieldWxUserID:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field wx_user_id", values[i])
+			} else if value.Valid {
+				wc.WxUserID = uint64(value.Int64)
+			}
+		case wxcard.FieldAvatar:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field avatar", values[i])
+			} else if value.Valid {
+				wc.Avatar = value.String
+			}
+		case wxcard.FieldLogo:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field logo", values[i])
+			} else if value.Valid {
+				wc.Logo = value.String
+			}
+		case wxcard.FieldName:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field name", values[i])
+			} else if value.Valid {
+				wc.Name = value.String
+			}
+		case wxcard.FieldCompany:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field company", values[i])
+			} else if value.Valid {
+				wc.Company = value.String
+			}
+		case wxcard.FieldAddress:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field address", values[i])
+			} else if value.Valid {
+				wc.Address = value.String
+			}
+		case wxcard.FieldPhone:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field phone", values[i])
+			} else if value.Valid {
+				wc.Phone = value.String
+			}
+		case wxcard.FieldOfficialAccount:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field official_account", values[i])
+			} else if value.Valid {
+				wc.OfficialAccount = value.String
+			}
+		case wxcard.FieldWechatAccount:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field wechat_account", values[i])
+			} else if value.Valid {
+				wc.WechatAccount = value.String
+			}
+		case wxcard.FieldEmail:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field email", values[i])
+			} else if value.Valid {
+				wc.Email = value.String
+			}
+		case wxcard.FieldAPIBase:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field api_base", values[i])
+			} else if value.Valid {
+				wc.APIBase = value.String
+			}
+		case wxcard.FieldAPIKey:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field api_key", values[i])
+			} else if value.Valid {
+				wc.APIKey = value.String
+			}
+		case wxcard.FieldAiInfo:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field ai_info", values[i])
+			} else if value.Valid {
+				wc.AiInfo = value.String
+			}
+		case wxcard.FieldIntro:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field intro", values[i])
+			} else if value.Valid {
+				wc.Intro = value.String
+			}
+		default:
+			wc.selectValues.Set(columns[i], values[i])
+		}
+	}
+	return nil
+}
+
+// Value returns the ent.Value that was dynamically selected and assigned to the WxCard.
+// This includes values selected through modifiers, order, etc.
+func (wc *WxCard) Value(name string) (ent.Value, error) {
+	return wc.selectValues.Get(name)
+}
+
+// Update returns a builder for updating this WxCard.
+// Note that you need to call WxCard.Unwrap() before calling this method if this WxCard
+// was returned from a transaction, and the transaction was committed or rolled back.
+func (wc *WxCard) Update() *WxCardUpdateOne {
+	return NewWxCardClient(wc.config).UpdateOne(wc)
+}
+
+// Unwrap unwraps the WxCard entity that was returned from a transaction after it was closed,
+// so that all future queries will be executed through the driver which created the transaction.
+func (wc *WxCard) Unwrap() *WxCard {
+	_tx, ok := wc.config.driver.(*txDriver)
+	if !ok {
+		panic("ent: WxCard is not a transactional entity")
+	}
+	wc.config.driver = _tx.drv
+	return wc
+}
+
+// String implements the fmt.Stringer.
+func (wc *WxCard) String() string {
+	var builder strings.Builder
+	builder.WriteString("WxCard(")
+	builder.WriteString(fmt.Sprintf("id=%v, ", wc.ID))
+	builder.WriteString("created_at=")
+	builder.WriteString(wc.CreatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("updated_at=")
+	builder.WriteString(wc.UpdatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("deleted_at=")
+	builder.WriteString(wc.DeletedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("user_id=")
+	builder.WriteString(fmt.Sprintf("%v", wc.UserID))
+	builder.WriteString(", ")
+	builder.WriteString("wx_user_id=")
+	builder.WriteString(fmt.Sprintf("%v", wc.WxUserID))
+	builder.WriteString(", ")
+	builder.WriteString("avatar=")
+	builder.WriteString(wc.Avatar)
+	builder.WriteString(", ")
+	builder.WriteString("logo=")
+	builder.WriteString(wc.Logo)
+	builder.WriteString(", ")
+	builder.WriteString("name=")
+	builder.WriteString(wc.Name)
+	builder.WriteString(", ")
+	builder.WriteString("company=")
+	builder.WriteString(wc.Company)
+	builder.WriteString(", ")
+	builder.WriteString("address=")
+	builder.WriteString(wc.Address)
+	builder.WriteString(", ")
+	builder.WriteString("phone=")
+	builder.WriteString(wc.Phone)
+	builder.WriteString(", ")
+	builder.WriteString("official_account=")
+	builder.WriteString(wc.OfficialAccount)
+	builder.WriteString(", ")
+	builder.WriteString("wechat_account=")
+	builder.WriteString(wc.WechatAccount)
+	builder.WriteString(", ")
+	builder.WriteString("email=")
+	builder.WriteString(wc.Email)
+	builder.WriteString(", ")
+	builder.WriteString("api_base=")
+	builder.WriteString(wc.APIBase)
+	builder.WriteString(", ")
+	builder.WriteString("api_key=")
+	builder.WriteString(wc.APIKey)
+	builder.WriteString(", ")
+	builder.WriteString("ai_info=")
+	builder.WriteString(wc.AiInfo)
+	builder.WriteString(", ")
+	builder.WriteString("intro=")
+	builder.WriteString(wc.Intro)
+	builder.WriteByte(')')
+	return builder.String()
+}
+
+// WxCards is a parsable slice of WxCard.
+type WxCards []*WxCard

+ 1285 - 0
ent/wxcard/where.go

@@ -0,0 +1,1285 @@
+// Code generated by ent, DO NOT EDIT.
+
+package wxcard
+
+import (
+	"time"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+)
+
+// ID filters vertices based on their ID field.
+func ID(id uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldID, id))
+}
+
+// IDEQ applies the EQ predicate on the ID field.
+func IDEQ(id uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldID, id))
+}
+
+// IDNEQ applies the NEQ predicate on the ID field.
+func IDNEQ(id uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldID, id))
+}
+
+// IDIn applies the In predicate on the ID field.
+func IDIn(ids ...uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldID, ids...))
+}
+
+// IDNotIn applies the NotIn predicate on the ID field.
+func IDNotIn(ids ...uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldID, ids...))
+}
+
+// IDGT applies the GT predicate on the ID field.
+func IDGT(id uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldID, id))
+}
+
+// IDGTE applies the GTE predicate on the ID field.
+func IDGTE(id uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldID, id))
+}
+
+// IDLT applies the LT predicate on the ID field.
+func IDLT(id uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldID, id))
+}
+
+// IDLTE applies the LTE predicate on the ID field.
+func IDLTE(id uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldID, id))
+}
+
+// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
+func CreatedAt(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
+func UpdatedAt(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ.
+func DeletedAt(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// UserID applies equality check predicate on the "user_id" field. It's identical to UserIDEQ.
+func UserID(v uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldUserID, v))
+}
+
+// WxUserID applies equality check predicate on the "wx_user_id" field. It's identical to WxUserIDEQ.
+func WxUserID(v uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldWxUserID, v))
+}
+
+// Avatar applies equality check predicate on the "avatar" field. It's identical to AvatarEQ.
+func Avatar(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldAvatar, v))
+}
+
+// Logo applies equality check predicate on the "logo" field. It's identical to LogoEQ.
+func Logo(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldLogo, v))
+}
+
+// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
+func Name(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldName, v))
+}
+
+// Company applies equality check predicate on the "company" field. It's identical to CompanyEQ.
+func Company(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldCompany, v))
+}
+
+// Address applies equality check predicate on the "address" field. It's identical to AddressEQ.
+func Address(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldAddress, v))
+}
+
+// Phone applies equality check predicate on the "phone" field. It's identical to PhoneEQ.
+func Phone(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldPhone, v))
+}
+
+// OfficialAccount applies equality check predicate on the "official_account" field. It's identical to OfficialAccountEQ.
+func OfficialAccount(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldOfficialAccount, v))
+}
+
+// WechatAccount applies equality check predicate on the "wechat_account" field. It's identical to WechatAccountEQ.
+func WechatAccount(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldWechatAccount, v))
+}
+
+// Email applies equality check predicate on the "email" field. It's identical to EmailEQ.
+func Email(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldEmail, v))
+}
+
+// APIBase applies equality check predicate on the "api_base" field. It's identical to APIBaseEQ.
+func APIBase(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldAPIBase, v))
+}
+
+// APIKey applies equality check predicate on the "api_key" field. It's identical to APIKeyEQ.
+func APIKey(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldAPIKey, v))
+}
+
+// AiInfo applies equality check predicate on the "ai_info" field. It's identical to AiInfoEQ.
+func AiInfo(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldAiInfo, v))
+}
+
+// Intro applies equality check predicate on the "intro" field. It's identical to IntroEQ.
+func Intro(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldIntro, v))
+}
+
+// CreatedAtEQ applies the EQ predicate on the "created_at" field.
+func CreatedAtEQ(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
+func CreatedAtNEQ(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtIn applies the In predicate on the "created_at" field.
+func CreatedAtIn(vs ...time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
+func CreatedAtNotIn(vs ...time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtGT applies the GT predicate on the "created_at" field.
+func CreatedAtGT(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldCreatedAt, v))
+}
+
+// CreatedAtGTE applies the GTE predicate on the "created_at" field.
+func CreatedAtGTE(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldCreatedAt, v))
+}
+
+// CreatedAtLT applies the LT predicate on the "created_at" field.
+func CreatedAtLT(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldCreatedAt, v))
+}
+
+// CreatedAtLTE applies the LTE predicate on the "created_at" field.
+func CreatedAtLTE(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldCreatedAt, v))
+}
+
+// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
+func UpdatedAtEQ(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
+func UpdatedAtNEQ(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtIn applies the In predicate on the "updated_at" field.
+func UpdatedAtIn(vs ...time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
+func UpdatedAtNotIn(vs ...time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtGT applies the GT predicate on the "updated_at" field.
+func UpdatedAtGT(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
+func UpdatedAtGTE(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLT applies the LT predicate on the "updated_at" field.
+func UpdatedAtLT(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
+func UpdatedAtLTE(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldUpdatedAt, v))
+}
+
+// DeletedAtEQ applies the EQ predicate on the "deleted_at" field.
+func DeletedAtEQ(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field.
+func DeletedAtNEQ(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtIn applies the In predicate on the "deleted_at" field.
+func DeletedAtIn(vs ...time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field.
+func DeletedAtNotIn(vs ...time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtGT applies the GT predicate on the "deleted_at" field.
+func DeletedAtGT(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldDeletedAt, v))
+}
+
+// DeletedAtGTE applies the GTE predicate on the "deleted_at" field.
+func DeletedAtGTE(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldDeletedAt, v))
+}
+
+// DeletedAtLT applies the LT predicate on the "deleted_at" field.
+func DeletedAtLT(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldDeletedAt, v))
+}
+
+// DeletedAtLTE applies the LTE predicate on the "deleted_at" field.
+func DeletedAtLTE(v time.Time) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldDeletedAt, v))
+}
+
+// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field.
+func DeletedAtIsNil() predicate.WxCard {
+	return predicate.WxCard(sql.FieldIsNull(FieldDeletedAt))
+}
+
+// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field.
+func DeletedAtNotNil() predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotNull(FieldDeletedAt))
+}
+
+// UserIDEQ applies the EQ predicate on the "user_id" field.
+func UserIDEQ(v uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldUserID, v))
+}
+
+// UserIDNEQ applies the NEQ predicate on the "user_id" field.
+func UserIDNEQ(v uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldUserID, v))
+}
+
+// UserIDIn applies the In predicate on the "user_id" field.
+func UserIDIn(vs ...uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldUserID, vs...))
+}
+
+// UserIDNotIn applies the NotIn predicate on the "user_id" field.
+func UserIDNotIn(vs ...uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldUserID, vs...))
+}
+
+// UserIDGT applies the GT predicate on the "user_id" field.
+func UserIDGT(v uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldUserID, v))
+}
+
+// UserIDGTE applies the GTE predicate on the "user_id" field.
+func UserIDGTE(v uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldUserID, v))
+}
+
+// UserIDLT applies the LT predicate on the "user_id" field.
+func UserIDLT(v uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldUserID, v))
+}
+
+// UserIDLTE applies the LTE predicate on the "user_id" field.
+func UserIDLTE(v uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldUserID, v))
+}
+
+// UserIDIsNil applies the IsNil predicate on the "user_id" field.
+func UserIDIsNil() predicate.WxCard {
+	return predicate.WxCard(sql.FieldIsNull(FieldUserID))
+}
+
+// UserIDNotNil applies the NotNil predicate on the "user_id" field.
+func UserIDNotNil() predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotNull(FieldUserID))
+}
+
+// WxUserIDEQ applies the EQ predicate on the "wx_user_id" field.
+func WxUserIDEQ(v uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldWxUserID, v))
+}
+
+// WxUserIDNEQ applies the NEQ predicate on the "wx_user_id" field.
+func WxUserIDNEQ(v uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldWxUserID, v))
+}
+
+// WxUserIDIn applies the In predicate on the "wx_user_id" field.
+func WxUserIDIn(vs ...uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldWxUserID, vs...))
+}
+
+// WxUserIDNotIn applies the NotIn predicate on the "wx_user_id" field.
+func WxUserIDNotIn(vs ...uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldWxUserID, vs...))
+}
+
+// WxUserIDGT applies the GT predicate on the "wx_user_id" field.
+func WxUserIDGT(v uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldWxUserID, v))
+}
+
+// WxUserIDGTE applies the GTE predicate on the "wx_user_id" field.
+func WxUserIDGTE(v uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldWxUserID, v))
+}
+
+// WxUserIDLT applies the LT predicate on the "wx_user_id" field.
+func WxUserIDLT(v uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldWxUserID, v))
+}
+
+// WxUserIDLTE applies the LTE predicate on the "wx_user_id" field.
+func WxUserIDLTE(v uint64) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldWxUserID, v))
+}
+
+// WxUserIDIsNil applies the IsNil predicate on the "wx_user_id" field.
+func WxUserIDIsNil() predicate.WxCard {
+	return predicate.WxCard(sql.FieldIsNull(FieldWxUserID))
+}
+
+// WxUserIDNotNil applies the NotNil predicate on the "wx_user_id" field.
+func WxUserIDNotNil() predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotNull(FieldWxUserID))
+}
+
+// AvatarEQ applies the EQ predicate on the "avatar" field.
+func AvatarEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldAvatar, v))
+}
+
+// AvatarNEQ applies the NEQ predicate on the "avatar" field.
+func AvatarNEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldAvatar, v))
+}
+
+// AvatarIn applies the In predicate on the "avatar" field.
+func AvatarIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldAvatar, vs...))
+}
+
+// AvatarNotIn applies the NotIn predicate on the "avatar" field.
+func AvatarNotIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldAvatar, vs...))
+}
+
+// AvatarGT applies the GT predicate on the "avatar" field.
+func AvatarGT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldAvatar, v))
+}
+
+// AvatarGTE applies the GTE predicate on the "avatar" field.
+func AvatarGTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldAvatar, v))
+}
+
+// AvatarLT applies the LT predicate on the "avatar" field.
+func AvatarLT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldAvatar, v))
+}
+
+// AvatarLTE applies the LTE predicate on the "avatar" field.
+func AvatarLTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldAvatar, v))
+}
+
+// AvatarContains applies the Contains predicate on the "avatar" field.
+func AvatarContains(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContains(FieldAvatar, v))
+}
+
+// AvatarHasPrefix applies the HasPrefix predicate on the "avatar" field.
+func AvatarHasPrefix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasPrefix(FieldAvatar, v))
+}
+
+// AvatarHasSuffix applies the HasSuffix predicate on the "avatar" field.
+func AvatarHasSuffix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasSuffix(FieldAvatar, v))
+}
+
+// AvatarEqualFold applies the EqualFold predicate on the "avatar" field.
+func AvatarEqualFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEqualFold(FieldAvatar, v))
+}
+
+// AvatarContainsFold applies the ContainsFold predicate on the "avatar" field.
+func AvatarContainsFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContainsFold(FieldAvatar, v))
+}
+
+// LogoEQ applies the EQ predicate on the "logo" field.
+func LogoEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldLogo, v))
+}
+
+// LogoNEQ applies the NEQ predicate on the "logo" field.
+func LogoNEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldLogo, v))
+}
+
+// LogoIn applies the In predicate on the "logo" field.
+func LogoIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldLogo, vs...))
+}
+
+// LogoNotIn applies the NotIn predicate on the "logo" field.
+func LogoNotIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldLogo, vs...))
+}
+
+// LogoGT applies the GT predicate on the "logo" field.
+func LogoGT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldLogo, v))
+}
+
+// LogoGTE applies the GTE predicate on the "logo" field.
+func LogoGTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldLogo, v))
+}
+
+// LogoLT applies the LT predicate on the "logo" field.
+func LogoLT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldLogo, v))
+}
+
+// LogoLTE applies the LTE predicate on the "logo" field.
+func LogoLTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldLogo, v))
+}
+
+// LogoContains applies the Contains predicate on the "logo" field.
+func LogoContains(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContains(FieldLogo, v))
+}
+
+// LogoHasPrefix applies the HasPrefix predicate on the "logo" field.
+func LogoHasPrefix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasPrefix(FieldLogo, v))
+}
+
+// LogoHasSuffix applies the HasSuffix predicate on the "logo" field.
+func LogoHasSuffix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasSuffix(FieldLogo, v))
+}
+
+// LogoEqualFold applies the EqualFold predicate on the "logo" field.
+func LogoEqualFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEqualFold(FieldLogo, v))
+}
+
+// LogoContainsFold applies the ContainsFold predicate on the "logo" field.
+func LogoContainsFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContainsFold(FieldLogo, v))
+}
+
+// NameEQ applies the EQ predicate on the "name" field.
+func NameEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldName, v))
+}
+
+// NameNEQ applies the NEQ predicate on the "name" field.
+func NameNEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldName, v))
+}
+
+// NameIn applies the In predicate on the "name" field.
+func NameIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldName, vs...))
+}
+
+// NameNotIn applies the NotIn predicate on the "name" field.
+func NameNotIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldName, vs...))
+}
+
+// NameGT applies the GT predicate on the "name" field.
+func NameGT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldName, v))
+}
+
+// NameGTE applies the GTE predicate on the "name" field.
+func NameGTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldName, v))
+}
+
+// NameLT applies the LT predicate on the "name" field.
+func NameLT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldName, v))
+}
+
+// NameLTE applies the LTE predicate on the "name" field.
+func NameLTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldName, v))
+}
+
+// NameContains applies the Contains predicate on the "name" field.
+func NameContains(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContains(FieldName, v))
+}
+
+// NameHasPrefix applies the HasPrefix predicate on the "name" field.
+func NameHasPrefix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasPrefix(FieldName, v))
+}
+
+// NameHasSuffix applies the HasSuffix predicate on the "name" field.
+func NameHasSuffix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasSuffix(FieldName, v))
+}
+
+// NameEqualFold applies the EqualFold predicate on the "name" field.
+func NameEqualFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEqualFold(FieldName, v))
+}
+
+// NameContainsFold applies the ContainsFold predicate on the "name" field.
+func NameContainsFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContainsFold(FieldName, v))
+}
+
+// CompanyEQ applies the EQ predicate on the "company" field.
+func CompanyEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldCompany, v))
+}
+
+// CompanyNEQ applies the NEQ predicate on the "company" field.
+func CompanyNEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldCompany, v))
+}
+
+// CompanyIn applies the In predicate on the "company" field.
+func CompanyIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldCompany, vs...))
+}
+
+// CompanyNotIn applies the NotIn predicate on the "company" field.
+func CompanyNotIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldCompany, vs...))
+}
+
+// CompanyGT applies the GT predicate on the "company" field.
+func CompanyGT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldCompany, v))
+}
+
+// CompanyGTE applies the GTE predicate on the "company" field.
+func CompanyGTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldCompany, v))
+}
+
+// CompanyLT applies the LT predicate on the "company" field.
+func CompanyLT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldCompany, v))
+}
+
+// CompanyLTE applies the LTE predicate on the "company" field.
+func CompanyLTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldCompany, v))
+}
+
+// CompanyContains applies the Contains predicate on the "company" field.
+func CompanyContains(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContains(FieldCompany, v))
+}
+
+// CompanyHasPrefix applies the HasPrefix predicate on the "company" field.
+func CompanyHasPrefix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasPrefix(FieldCompany, v))
+}
+
+// CompanyHasSuffix applies the HasSuffix predicate on the "company" field.
+func CompanyHasSuffix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasSuffix(FieldCompany, v))
+}
+
+// CompanyEqualFold applies the EqualFold predicate on the "company" field.
+func CompanyEqualFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEqualFold(FieldCompany, v))
+}
+
+// CompanyContainsFold applies the ContainsFold predicate on the "company" field.
+func CompanyContainsFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContainsFold(FieldCompany, v))
+}
+
+// AddressEQ applies the EQ predicate on the "address" field.
+func AddressEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldAddress, v))
+}
+
+// AddressNEQ applies the NEQ predicate on the "address" field.
+func AddressNEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldAddress, v))
+}
+
+// AddressIn applies the In predicate on the "address" field.
+func AddressIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldAddress, vs...))
+}
+
+// AddressNotIn applies the NotIn predicate on the "address" field.
+func AddressNotIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldAddress, vs...))
+}
+
+// AddressGT applies the GT predicate on the "address" field.
+func AddressGT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldAddress, v))
+}
+
+// AddressGTE applies the GTE predicate on the "address" field.
+func AddressGTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldAddress, v))
+}
+
+// AddressLT applies the LT predicate on the "address" field.
+func AddressLT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldAddress, v))
+}
+
+// AddressLTE applies the LTE predicate on the "address" field.
+func AddressLTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldAddress, v))
+}
+
+// AddressContains applies the Contains predicate on the "address" field.
+func AddressContains(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContains(FieldAddress, v))
+}
+
+// AddressHasPrefix applies the HasPrefix predicate on the "address" field.
+func AddressHasPrefix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasPrefix(FieldAddress, v))
+}
+
+// AddressHasSuffix applies the HasSuffix predicate on the "address" field.
+func AddressHasSuffix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasSuffix(FieldAddress, v))
+}
+
+// AddressEqualFold applies the EqualFold predicate on the "address" field.
+func AddressEqualFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEqualFold(FieldAddress, v))
+}
+
+// AddressContainsFold applies the ContainsFold predicate on the "address" field.
+func AddressContainsFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContainsFold(FieldAddress, v))
+}
+
+// PhoneEQ applies the EQ predicate on the "phone" field.
+func PhoneEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldPhone, v))
+}
+
+// PhoneNEQ applies the NEQ predicate on the "phone" field.
+func PhoneNEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldPhone, v))
+}
+
+// PhoneIn applies the In predicate on the "phone" field.
+func PhoneIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldPhone, vs...))
+}
+
+// PhoneNotIn applies the NotIn predicate on the "phone" field.
+func PhoneNotIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldPhone, vs...))
+}
+
+// PhoneGT applies the GT predicate on the "phone" field.
+func PhoneGT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldPhone, v))
+}
+
+// PhoneGTE applies the GTE predicate on the "phone" field.
+func PhoneGTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldPhone, v))
+}
+
+// PhoneLT applies the LT predicate on the "phone" field.
+func PhoneLT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldPhone, v))
+}
+
+// PhoneLTE applies the LTE predicate on the "phone" field.
+func PhoneLTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldPhone, v))
+}
+
+// PhoneContains applies the Contains predicate on the "phone" field.
+func PhoneContains(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContains(FieldPhone, v))
+}
+
+// PhoneHasPrefix applies the HasPrefix predicate on the "phone" field.
+func PhoneHasPrefix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasPrefix(FieldPhone, v))
+}
+
+// PhoneHasSuffix applies the HasSuffix predicate on the "phone" field.
+func PhoneHasSuffix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasSuffix(FieldPhone, v))
+}
+
+// PhoneEqualFold applies the EqualFold predicate on the "phone" field.
+func PhoneEqualFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEqualFold(FieldPhone, v))
+}
+
+// PhoneContainsFold applies the ContainsFold predicate on the "phone" field.
+func PhoneContainsFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContainsFold(FieldPhone, v))
+}
+
+// OfficialAccountEQ applies the EQ predicate on the "official_account" field.
+func OfficialAccountEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldOfficialAccount, v))
+}
+
+// OfficialAccountNEQ applies the NEQ predicate on the "official_account" field.
+func OfficialAccountNEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldOfficialAccount, v))
+}
+
+// OfficialAccountIn applies the In predicate on the "official_account" field.
+func OfficialAccountIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldOfficialAccount, vs...))
+}
+
+// OfficialAccountNotIn applies the NotIn predicate on the "official_account" field.
+func OfficialAccountNotIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldOfficialAccount, vs...))
+}
+
+// OfficialAccountGT applies the GT predicate on the "official_account" field.
+func OfficialAccountGT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldOfficialAccount, v))
+}
+
+// OfficialAccountGTE applies the GTE predicate on the "official_account" field.
+func OfficialAccountGTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldOfficialAccount, v))
+}
+
+// OfficialAccountLT applies the LT predicate on the "official_account" field.
+func OfficialAccountLT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldOfficialAccount, v))
+}
+
+// OfficialAccountLTE applies the LTE predicate on the "official_account" field.
+func OfficialAccountLTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldOfficialAccount, v))
+}
+
+// OfficialAccountContains applies the Contains predicate on the "official_account" field.
+func OfficialAccountContains(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContains(FieldOfficialAccount, v))
+}
+
+// OfficialAccountHasPrefix applies the HasPrefix predicate on the "official_account" field.
+func OfficialAccountHasPrefix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasPrefix(FieldOfficialAccount, v))
+}
+
+// OfficialAccountHasSuffix applies the HasSuffix predicate on the "official_account" field.
+func OfficialAccountHasSuffix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasSuffix(FieldOfficialAccount, v))
+}
+
+// OfficialAccountEqualFold applies the EqualFold predicate on the "official_account" field.
+func OfficialAccountEqualFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEqualFold(FieldOfficialAccount, v))
+}
+
+// OfficialAccountContainsFold applies the ContainsFold predicate on the "official_account" field.
+func OfficialAccountContainsFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContainsFold(FieldOfficialAccount, v))
+}
+
+// WechatAccountEQ applies the EQ predicate on the "wechat_account" field.
+func WechatAccountEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldWechatAccount, v))
+}
+
+// WechatAccountNEQ applies the NEQ predicate on the "wechat_account" field.
+func WechatAccountNEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldWechatAccount, v))
+}
+
+// WechatAccountIn applies the In predicate on the "wechat_account" field.
+func WechatAccountIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldWechatAccount, vs...))
+}
+
+// WechatAccountNotIn applies the NotIn predicate on the "wechat_account" field.
+func WechatAccountNotIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldWechatAccount, vs...))
+}
+
+// WechatAccountGT applies the GT predicate on the "wechat_account" field.
+func WechatAccountGT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldWechatAccount, v))
+}
+
+// WechatAccountGTE applies the GTE predicate on the "wechat_account" field.
+func WechatAccountGTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldWechatAccount, v))
+}
+
+// WechatAccountLT applies the LT predicate on the "wechat_account" field.
+func WechatAccountLT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldWechatAccount, v))
+}
+
+// WechatAccountLTE applies the LTE predicate on the "wechat_account" field.
+func WechatAccountLTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldWechatAccount, v))
+}
+
+// WechatAccountContains applies the Contains predicate on the "wechat_account" field.
+func WechatAccountContains(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContains(FieldWechatAccount, v))
+}
+
+// WechatAccountHasPrefix applies the HasPrefix predicate on the "wechat_account" field.
+func WechatAccountHasPrefix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasPrefix(FieldWechatAccount, v))
+}
+
+// WechatAccountHasSuffix applies the HasSuffix predicate on the "wechat_account" field.
+func WechatAccountHasSuffix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasSuffix(FieldWechatAccount, v))
+}
+
+// WechatAccountEqualFold applies the EqualFold predicate on the "wechat_account" field.
+func WechatAccountEqualFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEqualFold(FieldWechatAccount, v))
+}
+
+// WechatAccountContainsFold applies the ContainsFold predicate on the "wechat_account" field.
+func WechatAccountContainsFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContainsFold(FieldWechatAccount, v))
+}
+
+// EmailEQ applies the EQ predicate on the "email" field.
+func EmailEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldEmail, v))
+}
+
+// EmailNEQ applies the NEQ predicate on the "email" field.
+func EmailNEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldEmail, v))
+}
+
+// EmailIn applies the In predicate on the "email" field.
+func EmailIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldEmail, vs...))
+}
+
+// EmailNotIn applies the NotIn predicate on the "email" field.
+func EmailNotIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldEmail, vs...))
+}
+
+// EmailGT applies the GT predicate on the "email" field.
+func EmailGT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldEmail, v))
+}
+
+// EmailGTE applies the GTE predicate on the "email" field.
+func EmailGTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldEmail, v))
+}
+
+// EmailLT applies the LT predicate on the "email" field.
+func EmailLT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldEmail, v))
+}
+
+// EmailLTE applies the LTE predicate on the "email" field.
+func EmailLTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldEmail, v))
+}
+
+// EmailContains applies the Contains predicate on the "email" field.
+func EmailContains(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContains(FieldEmail, v))
+}
+
+// EmailHasPrefix applies the HasPrefix predicate on the "email" field.
+func EmailHasPrefix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasPrefix(FieldEmail, v))
+}
+
+// EmailHasSuffix applies the HasSuffix predicate on the "email" field.
+func EmailHasSuffix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasSuffix(FieldEmail, v))
+}
+
+// EmailIsNil applies the IsNil predicate on the "email" field.
+func EmailIsNil() predicate.WxCard {
+	return predicate.WxCard(sql.FieldIsNull(FieldEmail))
+}
+
+// EmailNotNil applies the NotNil predicate on the "email" field.
+func EmailNotNil() predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotNull(FieldEmail))
+}
+
+// EmailEqualFold applies the EqualFold predicate on the "email" field.
+func EmailEqualFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEqualFold(FieldEmail, v))
+}
+
+// EmailContainsFold applies the ContainsFold predicate on the "email" field.
+func EmailContainsFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContainsFold(FieldEmail, v))
+}
+
+// APIBaseEQ applies the EQ predicate on the "api_base" field.
+func APIBaseEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldAPIBase, v))
+}
+
+// APIBaseNEQ applies the NEQ predicate on the "api_base" field.
+func APIBaseNEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldAPIBase, v))
+}
+
+// APIBaseIn applies the In predicate on the "api_base" field.
+func APIBaseIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldAPIBase, vs...))
+}
+
+// APIBaseNotIn applies the NotIn predicate on the "api_base" field.
+func APIBaseNotIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldAPIBase, vs...))
+}
+
+// APIBaseGT applies the GT predicate on the "api_base" field.
+func APIBaseGT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldAPIBase, v))
+}
+
+// APIBaseGTE applies the GTE predicate on the "api_base" field.
+func APIBaseGTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldAPIBase, v))
+}
+
+// APIBaseLT applies the LT predicate on the "api_base" field.
+func APIBaseLT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldAPIBase, v))
+}
+
+// APIBaseLTE applies the LTE predicate on the "api_base" field.
+func APIBaseLTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldAPIBase, v))
+}
+
+// APIBaseContains applies the Contains predicate on the "api_base" field.
+func APIBaseContains(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContains(FieldAPIBase, v))
+}
+
+// APIBaseHasPrefix applies the HasPrefix predicate on the "api_base" field.
+func APIBaseHasPrefix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasPrefix(FieldAPIBase, v))
+}
+
+// APIBaseHasSuffix applies the HasSuffix predicate on the "api_base" field.
+func APIBaseHasSuffix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasSuffix(FieldAPIBase, v))
+}
+
+// APIBaseIsNil applies the IsNil predicate on the "api_base" field.
+func APIBaseIsNil() predicate.WxCard {
+	return predicate.WxCard(sql.FieldIsNull(FieldAPIBase))
+}
+
+// APIBaseNotNil applies the NotNil predicate on the "api_base" field.
+func APIBaseNotNil() predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotNull(FieldAPIBase))
+}
+
+// APIBaseEqualFold applies the EqualFold predicate on the "api_base" field.
+func APIBaseEqualFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEqualFold(FieldAPIBase, v))
+}
+
+// APIBaseContainsFold applies the ContainsFold predicate on the "api_base" field.
+func APIBaseContainsFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContainsFold(FieldAPIBase, v))
+}
+
+// APIKeyEQ applies the EQ predicate on the "api_key" field.
+func APIKeyEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldAPIKey, v))
+}
+
+// APIKeyNEQ applies the NEQ predicate on the "api_key" field.
+func APIKeyNEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldAPIKey, v))
+}
+
+// APIKeyIn applies the In predicate on the "api_key" field.
+func APIKeyIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldAPIKey, vs...))
+}
+
+// APIKeyNotIn applies the NotIn predicate on the "api_key" field.
+func APIKeyNotIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldAPIKey, vs...))
+}
+
+// APIKeyGT applies the GT predicate on the "api_key" field.
+func APIKeyGT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldAPIKey, v))
+}
+
+// APIKeyGTE applies the GTE predicate on the "api_key" field.
+func APIKeyGTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldAPIKey, v))
+}
+
+// APIKeyLT applies the LT predicate on the "api_key" field.
+func APIKeyLT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldAPIKey, v))
+}
+
+// APIKeyLTE applies the LTE predicate on the "api_key" field.
+func APIKeyLTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldAPIKey, v))
+}
+
+// APIKeyContains applies the Contains predicate on the "api_key" field.
+func APIKeyContains(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContains(FieldAPIKey, v))
+}
+
+// APIKeyHasPrefix applies the HasPrefix predicate on the "api_key" field.
+func APIKeyHasPrefix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasPrefix(FieldAPIKey, v))
+}
+
+// APIKeyHasSuffix applies the HasSuffix predicate on the "api_key" field.
+func APIKeyHasSuffix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasSuffix(FieldAPIKey, v))
+}
+
+// APIKeyIsNil applies the IsNil predicate on the "api_key" field.
+func APIKeyIsNil() predicate.WxCard {
+	return predicate.WxCard(sql.FieldIsNull(FieldAPIKey))
+}
+
+// APIKeyNotNil applies the NotNil predicate on the "api_key" field.
+func APIKeyNotNil() predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotNull(FieldAPIKey))
+}
+
+// APIKeyEqualFold applies the EqualFold predicate on the "api_key" field.
+func APIKeyEqualFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEqualFold(FieldAPIKey, v))
+}
+
+// APIKeyContainsFold applies the ContainsFold predicate on the "api_key" field.
+func APIKeyContainsFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContainsFold(FieldAPIKey, v))
+}
+
+// AiInfoEQ applies the EQ predicate on the "ai_info" field.
+func AiInfoEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldAiInfo, v))
+}
+
+// AiInfoNEQ applies the NEQ predicate on the "ai_info" field.
+func AiInfoNEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldAiInfo, v))
+}
+
+// AiInfoIn applies the In predicate on the "ai_info" field.
+func AiInfoIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldAiInfo, vs...))
+}
+
+// AiInfoNotIn applies the NotIn predicate on the "ai_info" field.
+func AiInfoNotIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldAiInfo, vs...))
+}
+
+// AiInfoGT applies the GT predicate on the "ai_info" field.
+func AiInfoGT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldAiInfo, v))
+}
+
+// AiInfoGTE applies the GTE predicate on the "ai_info" field.
+func AiInfoGTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldAiInfo, v))
+}
+
+// AiInfoLT applies the LT predicate on the "ai_info" field.
+func AiInfoLT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldAiInfo, v))
+}
+
+// AiInfoLTE applies the LTE predicate on the "ai_info" field.
+func AiInfoLTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldAiInfo, v))
+}
+
+// AiInfoContains applies the Contains predicate on the "ai_info" field.
+func AiInfoContains(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContains(FieldAiInfo, v))
+}
+
+// AiInfoHasPrefix applies the HasPrefix predicate on the "ai_info" field.
+func AiInfoHasPrefix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasPrefix(FieldAiInfo, v))
+}
+
+// AiInfoHasSuffix applies the HasSuffix predicate on the "ai_info" field.
+func AiInfoHasSuffix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasSuffix(FieldAiInfo, v))
+}
+
+// AiInfoIsNil applies the IsNil predicate on the "ai_info" field.
+func AiInfoIsNil() predicate.WxCard {
+	return predicate.WxCard(sql.FieldIsNull(FieldAiInfo))
+}
+
+// AiInfoNotNil applies the NotNil predicate on the "ai_info" field.
+func AiInfoNotNil() predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotNull(FieldAiInfo))
+}
+
+// AiInfoEqualFold applies the EqualFold predicate on the "ai_info" field.
+func AiInfoEqualFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEqualFold(FieldAiInfo, v))
+}
+
+// AiInfoContainsFold applies the ContainsFold predicate on the "ai_info" field.
+func AiInfoContainsFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContainsFold(FieldAiInfo, v))
+}
+
+// IntroEQ applies the EQ predicate on the "intro" field.
+func IntroEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEQ(FieldIntro, v))
+}
+
+// IntroNEQ applies the NEQ predicate on the "intro" field.
+func IntroNEQ(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNEQ(FieldIntro, v))
+}
+
+// IntroIn applies the In predicate on the "intro" field.
+func IntroIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldIn(FieldIntro, vs...))
+}
+
+// IntroNotIn applies the NotIn predicate on the "intro" field.
+func IntroNotIn(vs ...string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotIn(FieldIntro, vs...))
+}
+
+// IntroGT applies the GT predicate on the "intro" field.
+func IntroGT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGT(FieldIntro, v))
+}
+
+// IntroGTE applies the GTE predicate on the "intro" field.
+func IntroGTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldGTE(FieldIntro, v))
+}
+
+// IntroLT applies the LT predicate on the "intro" field.
+func IntroLT(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLT(FieldIntro, v))
+}
+
+// IntroLTE applies the LTE predicate on the "intro" field.
+func IntroLTE(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldLTE(FieldIntro, v))
+}
+
+// IntroContains applies the Contains predicate on the "intro" field.
+func IntroContains(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContains(FieldIntro, v))
+}
+
+// IntroHasPrefix applies the HasPrefix predicate on the "intro" field.
+func IntroHasPrefix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasPrefix(FieldIntro, v))
+}
+
+// IntroHasSuffix applies the HasSuffix predicate on the "intro" field.
+func IntroHasSuffix(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldHasSuffix(FieldIntro, v))
+}
+
+// IntroIsNil applies the IsNil predicate on the "intro" field.
+func IntroIsNil() predicate.WxCard {
+	return predicate.WxCard(sql.FieldIsNull(FieldIntro))
+}
+
+// IntroNotNil applies the NotNil predicate on the "intro" field.
+func IntroNotNil() predicate.WxCard {
+	return predicate.WxCard(sql.FieldNotNull(FieldIntro))
+}
+
+// IntroEqualFold applies the EqualFold predicate on the "intro" field.
+func IntroEqualFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldEqualFold(FieldIntro, v))
+}
+
+// IntroContainsFold applies the ContainsFold predicate on the "intro" field.
+func IntroContainsFold(v string) predicate.WxCard {
+	return predicate.WxCard(sql.FieldContainsFold(FieldIntro, v))
+}
+
+// And groups predicates with the AND operator between them.
+func And(predicates ...predicate.WxCard) predicate.WxCard {
+	return predicate.WxCard(sql.AndPredicates(predicates...))
+}
+
+// Or groups predicates with the OR operator between them.
+func Or(predicates ...predicate.WxCard) predicate.WxCard {
+	return predicate.WxCard(sql.OrPredicates(predicates...))
+}
+
+// Not applies the not operator on the given predicate.
+func Not(p predicate.WxCard) predicate.WxCard {
+	return predicate.WxCard(sql.NotPredicates(p))
+}

+ 226 - 0
ent/wxcard/wxcard.go

@@ -0,0 +1,226 @@
+// Code generated by ent, DO NOT EDIT.
+
+package wxcard
+
+import (
+	"time"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+)
+
+const (
+	// Label holds the string label denoting the wxcard type in the database.
+	Label = "wx_card"
+	// FieldID holds the string denoting the id field in the database.
+	FieldID = "id"
+	// FieldCreatedAt holds the string denoting the created_at field in the database.
+	FieldCreatedAt = "created_at"
+	// FieldUpdatedAt holds the string denoting the updated_at field in the database.
+	FieldUpdatedAt = "updated_at"
+	// FieldDeletedAt holds the string denoting the deleted_at field in the database.
+	FieldDeletedAt = "deleted_at"
+	// FieldUserID holds the string denoting the user_id field in the database.
+	FieldUserID = "user_id"
+	// FieldWxUserID holds the string denoting the wx_user_id field in the database.
+	FieldWxUserID = "wx_user_id"
+	// FieldAvatar holds the string denoting the avatar field in the database.
+	FieldAvatar = "avatar"
+	// FieldLogo holds the string denoting the logo field in the database.
+	FieldLogo = "logo"
+	// FieldName holds the string denoting the name field in the database.
+	FieldName = "name"
+	// FieldCompany holds the string denoting the company field in the database.
+	FieldCompany = "company"
+	// FieldAddress holds the string denoting the address field in the database.
+	FieldAddress = "address"
+	// FieldPhone holds the string denoting the phone field in the database.
+	FieldPhone = "phone"
+	// FieldOfficialAccount holds the string denoting the official_account field in the database.
+	FieldOfficialAccount = "official_account"
+	// FieldWechatAccount holds the string denoting the wechat_account field in the database.
+	FieldWechatAccount = "wechat_account"
+	// FieldEmail holds the string denoting the email field in the database.
+	FieldEmail = "email"
+	// FieldAPIBase holds the string denoting the api_base field in the database.
+	FieldAPIBase = "api_base"
+	// FieldAPIKey holds the string denoting the api_key field in the database.
+	FieldAPIKey = "api_key"
+	// FieldAiInfo holds the string denoting the ai_info field in the database.
+	FieldAiInfo = "ai_info"
+	// FieldIntro holds the string denoting the intro field in the database.
+	FieldIntro = "intro"
+	// Table holds the table name of the wxcard in the database.
+	Table = "wx_card"
+)
+
+// Columns holds all SQL columns for wxcard fields.
+var Columns = []string{
+	FieldID,
+	FieldCreatedAt,
+	FieldUpdatedAt,
+	FieldDeletedAt,
+	FieldUserID,
+	FieldWxUserID,
+	FieldAvatar,
+	FieldLogo,
+	FieldName,
+	FieldCompany,
+	FieldAddress,
+	FieldPhone,
+	FieldOfficialAccount,
+	FieldWechatAccount,
+	FieldEmail,
+	FieldAPIBase,
+	FieldAPIKey,
+	FieldAiInfo,
+	FieldIntro,
+}
+
+// ValidColumn reports if the column name is valid (part of the table columns).
+func ValidColumn(column string) bool {
+	for i := range Columns {
+		if column == Columns[i] {
+			return true
+		}
+	}
+	return false
+}
+
+// Note that the variables below are initialized by the runtime
+// package on the initialization of the application. Therefore,
+// it should be imported in the main as follows:
+//
+//	import _ "wechat-api/ent/runtime"
+var (
+	Hooks        [1]ent.Hook
+	Interceptors [1]ent.Interceptor
+	// DefaultCreatedAt holds the default value on creation for the "created_at" field.
+	DefaultCreatedAt func() time.Time
+	// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
+	DefaultUpdatedAt func() time.Time
+	// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
+	UpdateDefaultUpdatedAt func() time.Time
+	// DefaultUserID holds the default value on creation for the "user_id" field.
+	DefaultUserID uint64
+	// DefaultWxUserID holds the default value on creation for the "wx_user_id" field.
+	DefaultWxUserID uint64
+	// DefaultAvatar holds the default value on creation for the "avatar" field.
+	DefaultAvatar string
+	// DefaultLogo holds the default value on creation for the "logo" field.
+	DefaultLogo string
+	// DefaultName holds the default value on creation for the "name" field.
+	DefaultName string
+	// DefaultCompany holds the default value on creation for the "company" field.
+	DefaultCompany string
+	// DefaultAddress holds the default value on creation for the "address" field.
+	DefaultAddress string
+	// DefaultPhone holds the default value on creation for the "phone" field.
+	DefaultPhone string
+	// DefaultOfficialAccount holds the default value on creation for the "official_account" field.
+	DefaultOfficialAccount string
+	// DefaultWechatAccount holds the default value on creation for the "wechat_account" field.
+	DefaultWechatAccount string
+	// DefaultEmail holds the default value on creation for the "email" field.
+	DefaultEmail string
+	// DefaultIntro holds the default value on creation for the "intro" field.
+	DefaultIntro string
+)
+
+// OrderOption defines the ordering options for the WxCard queries.
+type OrderOption func(*sql.Selector)
+
+// ByID orders the results by the id field.
+func ByID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldID, opts...).ToFunc()
+}
+
+// ByCreatedAt orders the results by the created_at field.
+func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
+}
+
+// ByUpdatedAt orders the results by the updated_at field.
+func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
+}
+
+// ByDeletedAt orders the results by the deleted_at field.
+func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldDeletedAt, opts...).ToFunc()
+}
+
+// ByUserID orders the results by the user_id field.
+func ByUserID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldUserID, opts...).ToFunc()
+}
+
+// ByWxUserID orders the results by the wx_user_id field.
+func ByWxUserID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldWxUserID, opts...).ToFunc()
+}
+
+// ByAvatar orders the results by the avatar field.
+func ByAvatar(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldAvatar, opts...).ToFunc()
+}
+
+// ByLogo orders the results by the logo field.
+func ByLogo(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldLogo, opts...).ToFunc()
+}
+
+// ByName orders the results by the name field.
+func ByName(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldName, opts...).ToFunc()
+}
+
+// ByCompany orders the results by the company field.
+func ByCompany(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldCompany, opts...).ToFunc()
+}
+
+// ByAddress orders the results by the address field.
+func ByAddress(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldAddress, opts...).ToFunc()
+}
+
+// ByPhone orders the results by the phone field.
+func ByPhone(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldPhone, opts...).ToFunc()
+}
+
+// ByOfficialAccount orders the results by the official_account field.
+func ByOfficialAccount(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldOfficialAccount, opts...).ToFunc()
+}
+
+// ByWechatAccount orders the results by the wechat_account field.
+func ByWechatAccount(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldWechatAccount, opts...).ToFunc()
+}
+
+// ByEmail orders the results by the email field.
+func ByEmail(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldEmail, opts...).ToFunc()
+}
+
+// ByAPIBase orders the results by the api_base field.
+func ByAPIBase(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldAPIBase, opts...).ToFunc()
+}
+
+// ByAPIKey orders the results by the api_key field.
+func ByAPIKey(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldAPIKey, opts...).ToFunc()
+}
+
+// ByAiInfo orders the results by the ai_info field.
+func ByAiInfo(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldAiInfo, opts...).ToFunc()
+}
+
+// ByIntro orders the results by the intro field.
+func ByIntro(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldIntro, opts...).ToFunc()
+}

+ 1743 - 0
ent/wxcard_create.go

@@ -0,0 +1,1743 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/wxcard"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// WxCardCreate is the builder for creating a WxCard entity.
+type WxCardCreate struct {
+	config
+	mutation *WxCardMutation
+	hooks    []Hook
+	conflict []sql.ConflictOption
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (wcc *WxCardCreate) SetCreatedAt(t time.Time) *WxCardCreate {
+	wcc.mutation.SetCreatedAt(t)
+	return wcc
+}
+
+// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
+func (wcc *WxCardCreate) SetNillableCreatedAt(t *time.Time) *WxCardCreate {
+	if t != nil {
+		wcc.SetCreatedAt(*t)
+	}
+	return wcc
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (wcc *WxCardCreate) SetUpdatedAt(t time.Time) *WxCardCreate {
+	wcc.mutation.SetUpdatedAt(t)
+	return wcc
+}
+
+// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
+func (wcc *WxCardCreate) SetNillableUpdatedAt(t *time.Time) *WxCardCreate {
+	if t != nil {
+		wcc.SetUpdatedAt(*t)
+	}
+	return wcc
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (wcc *WxCardCreate) SetDeletedAt(t time.Time) *WxCardCreate {
+	wcc.mutation.SetDeletedAt(t)
+	return wcc
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (wcc *WxCardCreate) SetNillableDeletedAt(t *time.Time) *WxCardCreate {
+	if t != nil {
+		wcc.SetDeletedAt(*t)
+	}
+	return wcc
+}
+
+// SetUserID sets the "user_id" field.
+func (wcc *WxCardCreate) SetUserID(u uint64) *WxCardCreate {
+	wcc.mutation.SetUserID(u)
+	return wcc
+}
+
+// SetNillableUserID sets the "user_id" field if the given value is not nil.
+func (wcc *WxCardCreate) SetNillableUserID(u *uint64) *WxCardCreate {
+	if u != nil {
+		wcc.SetUserID(*u)
+	}
+	return wcc
+}
+
+// SetWxUserID sets the "wx_user_id" field.
+func (wcc *WxCardCreate) SetWxUserID(u uint64) *WxCardCreate {
+	wcc.mutation.SetWxUserID(u)
+	return wcc
+}
+
+// SetNillableWxUserID sets the "wx_user_id" field if the given value is not nil.
+func (wcc *WxCardCreate) SetNillableWxUserID(u *uint64) *WxCardCreate {
+	if u != nil {
+		wcc.SetWxUserID(*u)
+	}
+	return wcc
+}
+
+// SetAvatar sets the "avatar" field.
+func (wcc *WxCardCreate) SetAvatar(s string) *WxCardCreate {
+	wcc.mutation.SetAvatar(s)
+	return wcc
+}
+
+// SetNillableAvatar sets the "avatar" field if the given value is not nil.
+func (wcc *WxCardCreate) SetNillableAvatar(s *string) *WxCardCreate {
+	if s != nil {
+		wcc.SetAvatar(*s)
+	}
+	return wcc
+}
+
+// SetLogo sets the "logo" field.
+func (wcc *WxCardCreate) SetLogo(s string) *WxCardCreate {
+	wcc.mutation.SetLogo(s)
+	return wcc
+}
+
+// SetNillableLogo sets the "logo" field if the given value is not nil.
+func (wcc *WxCardCreate) SetNillableLogo(s *string) *WxCardCreate {
+	if s != nil {
+		wcc.SetLogo(*s)
+	}
+	return wcc
+}
+
+// SetName sets the "name" field.
+func (wcc *WxCardCreate) SetName(s string) *WxCardCreate {
+	wcc.mutation.SetName(s)
+	return wcc
+}
+
+// SetNillableName sets the "name" field if the given value is not nil.
+func (wcc *WxCardCreate) SetNillableName(s *string) *WxCardCreate {
+	if s != nil {
+		wcc.SetName(*s)
+	}
+	return wcc
+}
+
+// SetCompany sets the "company" field.
+func (wcc *WxCardCreate) SetCompany(s string) *WxCardCreate {
+	wcc.mutation.SetCompany(s)
+	return wcc
+}
+
+// SetNillableCompany sets the "company" field if the given value is not nil.
+func (wcc *WxCardCreate) SetNillableCompany(s *string) *WxCardCreate {
+	if s != nil {
+		wcc.SetCompany(*s)
+	}
+	return wcc
+}
+
+// SetAddress sets the "address" field.
+func (wcc *WxCardCreate) SetAddress(s string) *WxCardCreate {
+	wcc.mutation.SetAddress(s)
+	return wcc
+}
+
+// SetNillableAddress sets the "address" field if the given value is not nil.
+func (wcc *WxCardCreate) SetNillableAddress(s *string) *WxCardCreate {
+	if s != nil {
+		wcc.SetAddress(*s)
+	}
+	return wcc
+}
+
+// SetPhone sets the "phone" field.
+func (wcc *WxCardCreate) SetPhone(s string) *WxCardCreate {
+	wcc.mutation.SetPhone(s)
+	return wcc
+}
+
+// SetNillablePhone sets the "phone" field if the given value is not nil.
+func (wcc *WxCardCreate) SetNillablePhone(s *string) *WxCardCreate {
+	if s != nil {
+		wcc.SetPhone(*s)
+	}
+	return wcc
+}
+
+// SetOfficialAccount sets the "official_account" field.
+func (wcc *WxCardCreate) SetOfficialAccount(s string) *WxCardCreate {
+	wcc.mutation.SetOfficialAccount(s)
+	return wcc
+}
+
+// SetNillableOfficialAccount sets the "official_account" field if the given value is not nil.
+func (wcc *WxCardCreate) SetNillableOfficialAccount(s *string) *WxCardCreate {
+	if s != nil {
+		wcc.SetOfficialAccount(*s)
+	}
+	return wcc
+}
+
+// SetWechatAccount sets the "wechat_account" field.
+func (wcc *WxCardCreate) SetWechatAccount(s string) *WxCardCreate {
+	wcc.mutation.SetWechatAccount(s)
+	return wcc
+}
+
+// SetNillableWechatAccount sets the "wechat_account" field if the given value is not nil.
+func (wcc *WxCardCreate) SetNillableWechatAccount(s *string) *WxCardCreate {
+	if s != nil {
+		wcc.SetWechatAccount(*s)
+	}
+	return wcc
+}
+
+// SetEmail sets the "email" field.
+func (wcc *WxCardCreate) SetEmail(s string) *WxCardCreate {
+	wcc.mutation.SetEmail(s)
+	return wcc
+}
+
+// SetNillableEmail sets the "email" field if the given value is not nil.
+func (wcc *WxCardCreate) SetNillableEmail(s *string) *WxCardCreate {
+	if s != nil {
+		wcc.SetEmail(*s)
+	}
+	return wcc
+}
+
+// SetAPIBase sets the "api_base" field.
+func (wcc *WxCardCreate) SetAPIBase(s string) *WxCardCreate {
+	wcc.mutation.SetAPIBase(s)
+	return wcc
+}
+
+// SetNillableAPIBase sets the "api_base" field if the given value is not nil.
+func (wcc *WxCardCreate) SetNillableAPIBase(s *string) *WxCardCreate {
+	if s != nil {
+		wcc.SetAPIBase(*s)
+	}
+	return wcc
+}
+
+// SetAPIKey sets the "api_key" field.
+func (wcc *WxCardCreate) SetAPIKey(s string) *WxCardCreate {
+	wcc.mutation.SetAPIKey(s)
+	return wcc
+}
+
+// SetNillableAPIKey sets the "api_key" field if the given value is not nil.
+func (wcc *WxCardCreate) SetNillableAPIKey(s *string) *WxCardCreate {
+	if s != nil {
+		wcc.SetAPIKey(*s)
+	}
+	return wcc
+}
+
+// SetAiInfo sets the "ai_info" field.
+func (wcc *WxCardCreate) SetAiInfo(s string) *WxCardCreate {
+	wcc.mutation.SetAiInfo(s)
+	return wcc
+}
+
+// SetNillableAiInfo sets the "ai_info" field if the given value is not nil.
+func (wcc *WxCardCreate) SetNillableAiInfo(s *string) *WxCardCreate {
+	if s != nil {
+		wcc.SetAiInfo(*s)
+	}
+	return wcc
+}
+
+// SetIntro sets the "intro" field.
+func (wcc *WxCardCreate) SetIntro(s string) *WxCardCreate {
+	wcc.mutation.SetIntro(s)
+	return wcc
+}
+
+// SetNillableIntro sets the "intro" field if the given value is not nil.
+func (wcc *WxCardCreate) SetNillableIntro(s *string) *WxCardCreate {
+	if s != nil {
+		wcc.SetIntro(*s)
+	}
+	return wcc
+}
+
+// SetID sets the "id" field.
+func (wcc *WxCardCreate) SetID(u uint64) *WxCardCreate {
+	wcc.mutation.SetID(u)
+	return wcc
+}
+
+// Mutation returns the WxCardMutation object of the builder.
+func (wcc *WxCardCreate) Mutation() *WxCardMutation {
+	return wcc.mutation
+}
+
+// Save creates the WxCard in the database.
+func (wcc *WxCardCreate) Save(ctx context.Context) (*WxCard, error) {
+	if err := wcc.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, wcc.sqlSave, wcc.mutation, wcc.hooks)
+}
+
+// SaveX calls Save and panics if Save returns an error.
+func (wcc *WxCardCreate) SaveX(ctx context.Context) *WxCard {
+	v, err := wcc.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (wcc *WxCardCreate) Exec(ctx context.Context) error {
+	_, err := wcc.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (wcc *WxCardCreate) ExecX(ctx context.Context) {
+	if err := wcc.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (wcc *WxCardCreate) defaults() error {
+	if _, ok := wcc.mutation.CreatedAt(); !ok {
+		if wxcard.DefaultCreatedAt == nil {
+			return fmt.Errorf("ent: uninitialized wxcard.DefaultCreatedAt (forgotten import ent/runtime?)")
+		}
+		v := wxcard.DefaultCreatedAt()
+		wcc.mutation.SetCreatedAt(v)
+	}
+	if _, ok := wcc.mutation.UpdatedAt(); !ok {
+		if wxcard.DefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized wxcard.DefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := wxcard.DefaultUpdatedAt()
+		wcc.mutation.SetUpdatedAt(v)
+	}
+	if _, ok := wcc.mutation.UserID(); !ok {
+		v := wxcard.DefaultUserID
+		wcc.mutation.SetUserID(v)
+	}
+	if _, ok := wcc.mutation.WxUserID(); !ok {
+		v := wxcard.DefaultWxUserID
+		wcc.mutation.SetWxUserID(v)
+	}
+	if _, ok := wcc.mutation.Avatar(); !ok {
+		v := wxcard.DefaultAvatar
+		wcc.mutation.SetAvatar(v)
+	}
+	if _, ok := wcc.mutation.Logo(); !ok {
+		v := wxcard.DefaultLogo
+		wcc.mutation.SetLogo(v)
+	}
+	if _, ok := wcc.mutation.Name(); !ok {
+		v := wxcard.DefaultName
+		wcc.mutation.SetName(v)
+	}
+	if _, ok := wcc.mutation.Company(); !ok {
+		v := wxcard.DefaultCompany
+		wcc.mutation.SetCompany(v)
+	}
+	if _, ok := wcc.mutation.Address(); !ok {
+		v := wxcard.DefaultAddress
+		wcc.mutation.SetAddress(v)
+	}
+	if _, ok := wcc.mutation.Phone(); !ok {
+		v := wxcard.DefaultPhone
+		wcc.mutation.SetPhone(v)
+	}
+	if _, ok := wcc.mutation.OfficialAccount(); !ok {
+		v := wxcard.DefaultOfficialAccount
+		wcc.mutation.SetOfficialAccount(v)
+	}
+	if _, ok := wcc.mutation.WechatAccount(); !ok {
+		v := wxcard.DefaultWechatAccount
+		wcc.mutation.SetWechatAccount(v)
+	}
+	if _, ok := wcc.mutation.Email(); !ok {
+		v := wxcard.DefaultEmail
+		wcc.mutation.SetEmail(v)
+	}
+	if _, ok := wcc.mutation.Intro(); !ok {
+		v := wxcard.DefaultIntro
+		wcc.mutation.SetIntro(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (wcc *WxCardCreate) check() error {
+	if _, ok := wcc.mutation.CreatedAt(); !ok {
+		return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "WxCard.created_at"`)}
+	}
+	if _, ok := wcc.mutation.UpdatedAt(); !ok {
+		return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "WxCard.updated_at"`)}
+	}
+	if _, ok := wcc.mutation.Avatar(); !ok {
+		return &ValidationError{Name: "avatar", err: errors.New(`ent: missing required field "WxCard.avatar"`)}
+	}
+	if _, ok := wcc.mutation.Logo(); !ok {
+		return &ValidationError{Name: "logo", err: errors.New(`ent: missing required field "WxCard.logo"`)}
+	}
+	if _, ok := wcc.mutation.Name(); !ok {
+		return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "WxCard.name"`)}
+	}
+	if _, ok := wcc.mutation.Company(); !ok {
+		return &ValidationError{Name: "company", err: errors.New(`ent: missing required field "WxCard.company"`)}
+	}
+	if _, ok := wcc.mutation.Address(); !ok {
+		return &ValidationError{Name: "address", err: errors.New(`ent: missing required field "WxCard.address"`)}
+	}
+	if _, ok := wcc.mutation.Phone(); !ok {
+		return &ValidationError{Name: "phone", err: errors.New(`ent: missing required field "WxCard.phone"`)}
+	}
+	if _, ok := wcc.mutation.OfficialAccount(); !ok {
+		return &ValidationError{Name: "official_account", err: errors.New(`ent: missing required field "WxCard.official_account"`)}
+	}
+	if _, ok := wcc.mutation.WechatAccount(); !ok {
+		return &ValidationError{Name: "wechat_account", err: errors.New(`ent: missing required field "WxCard.wechat_account"`)}
+	}
+	return nil
+}
+
+func (wcc *WxCardCreate) sqlSave(ctx context.Context) (*WxCard, error) {
+	if err := wcc.check(); err != nil {
+		return nil, err
+	}
+	_node, _spec := wcc.createSpec()
+	if err := sqlgraph.CreateNode(ctx, wcc.driver, _spec); err != nil {
+		if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	if _spec.ID.Value != _node.ID {
+		id := _spec.ID.Value.(int64)
+		_node.ID = uint64(id)
+	}
+	wcc.mutation.id = &_node.ID
+	wcc.mutation.done = true
+	return _node, nil
+}
+
+func (wcc *WxCardCreate) createSpec() (*WxCard, *sqlgraph.CreateSpec) {
+	var (
+		_node = &WxCard{config: wcc.config}
+		_spec = sqlgraph.NewCreateSpec(wxcard.Table, sqlgraph.NewFieldSpec(wxcard.FieldID, field.TypeUint64))
+	)
+	_spec.OnConflict = wcc.conflict
+	if id, ok := wcc.mutation.ID(); ok {
+		_node.ID = id
+		_spec.ID.Value = id
+	}
+	if value, ok := wcc.mutation.CreatedAt(); ok {
+		_spec.SetField(wxcard.FieldCreatedAt, field.TypeTime, value)
+		_node.CreatedAt = value
+	}
+	if value, ok := wcc.mutation.UpdatedAt(); ok {
+		_spec.SetField(wxcard.FieldUpdatedAt, field.TypeTime, value)
+		_node.UpdatedAt = value
+	}
+	if value, ok := wcc.mutation.DeletedAt(); ok {
+		_spec.SetField(wxcard.FieldDeletedAt, field.TypeTime, value)
+		_node.DeletedAt = value
+	}
+	if value, ok := wcc.mutation.UserID(); ok {
+		_spec.SetField(wxcard.FieldUserID, field.TypeUint64, value)
+		_node.UserID = value
+	}
+	if value, ok := wcc.mutation.WxUserID(); ok {
+		_spec.SetField(wxcard.FieldWxUserID, field.TypeUint64, value)
+		_node.WxUserID = value
+	}
+	if value, ok := wcc.mutation.Avatar(); ok {
+		_spec.SetField(wxcard.FieldAvatar, field.TypeString, value)
+		_node.Avatar = value
+	}
+	if value, ok := wcc.mutation.Logo(); ok {
+		_spec.SetField(wxcard.FieldLogo, field.TypeString, value)
+		_node.Logo = value
+	}
+	if value, ok := wcc.mutation.Name(); ok {
+		_spec.SetField(wxcard.FieldName, field.TypeString, value)
+		_node.Name = value
+	}
+	if value, ok := wcc.mutation.Company(); ok {
+		_spec.SetField(wxcard.FieldCompany, field.TypeString, value)
+		_node.Company = value
+	}
+	if value, ok := wcc.mutation.Address(); ok {
+		_spec.SetField(wxcard.FieldAddress, field.TypeString, value)
+		_node.Address = value
+	}
+	if value, ok := wcc.mutation.Phone(); ok {
+		_spec.SetField(wxcard.FieldPhone, field.TypeString, value)
+		_node.Phone = value
+	}
+	if value, ok := wcc.mutation.OfficialAccount(); ok {
+		_spec.SetField(wxcard.FieldOfficialAccount, field.TypeString, value)
+		_node.OfficialAccount = value
+	}
+	if value, ok := wcc.mutation.WechatAccount(); ok {
+		_spec.SetField(wxcard.FieldWechatAccount, field.TypeString, value)
+		_node.WechatAccount = value
+	}
+	if value, ok := wcc.mutation.Email(); ok {
+		_spec.SetField(wxcard.FieldEmail, field.TypeString, value)
+		_node.Email = value
+	}
+	if value, ok := wcc.mutation.APIBase(); ok {
+		_spec.SetField(wxcard.FieldAPIBase, field.TypeString, value)
+		_node.APIBase = value
+	}
+	if value, ok := wcc.mutation.APIKey(); ok {
+		_spec.SetField(wxcard.FieldAPIKey, field.TypeString, value)
+		_node.APIKey = value
+	}
+	if value, ok := wcc.mutation.AiInfo(); ok {
+		_spec.SetField(wxcard.FieldAiInfo, field.TypeString, value)
+		_node.AiInfo = value
+	}
+	if value, ok := wcc.mutation.Intro(); ok {
+		_spec.SetField(wxcard.FieldIntro, field.TypeString, value)
+		_node.Intro = value
+	}
+	return _node, _spec
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.WxCard.Create().
+//		SetCreatedAt(v).
+//		OnConflict(
+//			// Update the row with the new values
+//			// the was proposed for insertion.
+//			sql.ResolveWithNewValues(),
+//		).
+//		// Override some of the fields with custom
+//		// update values.
+//		Update(func(u *ent.WxCardUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (wcc *WxCardCreate) OnConflict(opts ...sql.ConflictOption) *WxCardUpsertOne {
+	wcc.conflict = opts
+	return &WxCardUpsertOne{
+		create: wcc,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.WxCard.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (wcc *WxCardCreate) OnConflictColumns(columns ...string) *WxCardUpsertOne {
+	wcc.conflict = append(wcc.conflict, sql.ConflictColumns(columns...))
+	return &WxCardUpsertOne{
+		create: wcc,
+	}
+}
+
+type (
+	// WxCardUpsertOne is the builder for "upsert"-ing
+	//  one WxCard node.
+	WxCardUpsertOne struct {
+		create *WxCardCreate
+	}
+
+	// WxCardUpsert is the "OnConflict" setter.
+	WxCardUpsert struct {
+		*sql.UpdateSet
+	}
+)
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *WxCardUpsert) SetUpdatedAt(v time.Time) *WxCardUpsert {
+	u.Set(wxcard.FieldUpdatedAt, v)
+	return u
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *WxCardUpsert) UpdateUpdatedAt() *WxCardUpsert {
+	u.SetExcluded(wxcard.FieldUpdatedAt)
+	return u
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *WxCardUpsert) SetDeletedAt(v time.Time) *WxCardUpsert {
+	u.Set(wxcard.FieldDeletedAt, v)
+	return u
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *WxCardUpsert) UpdateDeletedAt() *WxCardUpsert {
+	u.SetExcluded(wxcard.FieldDeletedAt)
+	return u
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *WxCardUpsert) ClearDeletedAt() *WxCardUpsert {
+	u.SetNull(wxcard.FieldDeletedAt)
+	return u
+}
+
+// SetUserID sets the "user_id" field.
+func (u *WxCardUpsert) SetUserID(v uint64) *WxCardUpsert {
+	u.Set(wxcard.FieldUserID, v)
+	return u
+}
+
+// UpdateUserID sets the "user_id" field to the value that was provided on create.
+func (u *WxCardUpsert) UpdateUserID() *WxCardUpsert {
+	u.SetExcluded(wxcard.FieldUserID)
+	return u
+}
+
+// AddUserID adds v to the "user_id" field.
+func (u *WxCardUpsert) AddUserID(v uint64) *WxCardUpsert {
+	u.Add(wxcard.FieldUserID, v)
+	return u
+}
+
+// ClearUserID clears the value of the "user_id" field.
+func (u *WxCardUpsert) ClearUserID() *WxCardUpsert {
+	u.SetNull(wxcard.FieldUserID)
+	return u
+}
+
+// SetWxUserID sets the "wx_user_id" field.
+func (u *WxCardUpsert) SetWxUserID(v uint64) *WxCardUpsert {
+	u.Set(wxcard.FieldWxUserID, v)
+	return u
+}
+
+// UpdateWxUserID sets the "wx_user_id" field to the value that was provided on create.
+func (u *WxCardUpsert) UpdateWxUserID() *WxCardUpsert {
+	u.SetExcluded(wxcard.FieldWxUserID)
+	return u
+}
+
+// AddWxUserID adds v to the "wx_user_id" field.
+func (u *WxCardUpsert) AddWxUserID(v uint64) *WxCardUpsert {
+	u.Add(wxcard.FieldWxUserID, v)
+	return u
+}
+
+// ClearWxUserID clears the value of the "wx_user_id" field.
+func (u *WxCardUpsert) ClearWxUserID() *WxCardUpsert {
+	u.SetNull(wxcard.FieldWxUserID)
+	return u
+}
+
+// SetAvatar sets the "avatar" field.
+func (u *WxCardUpsert) SetAvatar(v string) *WxCardUpsert {
+	u.Set(wxcard.FieldAvatar, v)
+	return u
+}
+
+// UpdateAvatar sets the "avatar" field to the value that was provided on create.
+func (u *WxCardUpsert) UpdateAvatar() *WxCardUpsert {
+	u.SetExcluded(wxcard.FieldAvatar)
+	return u
+}
+
+// SetLogo sets the "logo" field.
+func (u *WxCardUpsert) SetLogo(v string) *WxCardUpsert {
+	u.Set(wxcard.FieldLogo, v)
+	return u
+}
+
+// UpdateLogo sets the "logo" field to the value that was provided on create.
+func (u *WxCardUpsert) UpdateLogo() *WxCardUpsert {
+	u.SetExcluded(wxcard.FieldLogo)
+	return u
+}
+
+// SetName sets the "name" field.
+func (u *WxCardUpsert) SetName(v string) *WxCardUpsert {
+	u.Set(wxcard.FieldName, v)
+	return u
+}
+
+// UpdateName sets the "name" field to the value that was provided on create.
+func (u *WxCardUpsert) UpdateName() *WxCardUpsert {
+	u.SetExcluded(wxcard.FieldName)
+	return u
+}
+
+// SetCompany sets the "company" field.
+func (u *WxCardUpsert) SetCompany(v string) *WxCardUpsert {
+	u.Set(wxcard.FieldCompany, v)
+	return u
+}
+
+// UpdateCompany sets the "company" field to the value that was provided on create.
+func (u *WxCardUpsert) UpdateCompany() *WxCardUpsert {
+	u.SetExcluded(wxcard.FieldCompany)
+	return u
+}
+
+// SetAddress sets the "address" field.
+func (u *WxCardUpsert) SetAddress(v string) *WxCardUpsert {
+	u.Set(wxcard.FieldAddress, v)
+	return u
+}
+
+// UpdateAddress sets the "address" field to the value that was provided on create.
+func (u *WxCardUpsert) UpdateAddress() *WxCardUpsert {
+	u.SetExcluded(wxcard.FieldAddress)
+	return u
+}
+
+// SetPhone sets the "phone" field.
+func (u *WxCardUpsert) SetPhone(v string) *WxCardUpsert {
+	u.Set(wxcard.FieldPhone, v)
+	return u
+}
+
+// UpdatePhone sets the "phone" field to the value that was provided on create.
+func (u *WxCardUpsert) UpdatePhone() *WxCardUpsert {
+	u.SetExcluded(wxcard.FieldPhone)
+	return u
+}
+
+// SetOfficialAccount sets the "official_account" field.
+func (u *WxCardUpsert) SetOfficialAccount(v string) *WxCardUpsert {
+	u.Set(wxcard.FieldOfficialAccount, v)
+	return u
+}
+
+// UpdateOfficialAccount sets the "official_account" field to the value that was provided on create.
+func (u *WxCardUpsert) UpdateOfficialAccount() *WxCardUpsert {
+	u.SetExcluded(wxcard.FieldOfficialAccount)
+	return u
+}
+
+// SetWechatAccount sets the "wechat_account" field.
+func (u *WxCardUpsert) SetWechatAccount(v string) *WxCardUpsert {
+	u.Set(wxcard.FieldWechatAccount, v)
+	return u
+}
+
+// UpdateWechatAccount sets the "wechat_account" field to the value that was provided on create.
+func (u *WxCardUpsert) UpdateWechatAccount() *WxCardUpsert {
+	u.SetExcluded(wxcard.FieldWechatAccount)
+	return u
+}
+
+// SetEmail sets the "email" field.
+func (u *WxCardUpsert) SetEmail(v string) *WxCardUpsert {
+	u.Set(wxcard.FieldEmail, v)
+	return u
+}
+
+// UpdateEmail sets the "email" field to the value that was provided on create.
+func (u *WxCardUpsert) UpdateEmail() *WxCardUpsert {
+	u.SetExcluded(wxcard.FieldEmail)
+	return u
+}
+
+// ClearEmail clears the value of the "email" field.
+func (u *WxCardUpsert) ClearEmail() *WxCardUpsert {
+	u.SetNull(wxcard.FieldEmail)
+	return u
+}
+
+// SetAPIBase sets the "api_base" field.
+func (u *WxCardUpsert) SetAPIBase(v string) *WxCardUpsert {
+	u.Set(wxcard.FieldAPIBase, v)
+	return u
+}
+
+// UpdateAPIBase sets the "api_base" field to the value that was provided on create.
+func (u *WxCardUpsert) UpdateAPIBase() *WxCardUpsert {
+	u.SetExcluded(wxcard.FieldAPIBase)
+	return u
+}
+
+// ClearAPIBase clears the value of the "api_base" field.
+func (u *WxCardUpsert) ClearAPIBase() *WxCardUpsert {
+	u.SetNull(wxcard.FieldAPIBase)
+	return u
+}
+
+// SetAPIKey sets the "api_key" field.
+func (u *WxCardUpsert) SetAPIKey(v string) *WxCardUpsert {
+	u.Set(wxcard.FieldAPIKey, v)
+	return u
+}
+
+// UpdateAPIKey sets the "api_key" field to the value that was provided on create.
+func (u *WxCardUpsert) UpdateAPIKey() *WxCardUpsert {
+	u.SetExcluded(wxcard.FieldAPIKey)
+	return u
+}
+
+// ClearAPIKey clears the value of the "api_key" field.
+func (u *WxCardUpsert) ClearAPIKey() *WxCardUpsert {
+	u.SetNull(wxcard.FieldAPIKey)
+	return u
+}
+
+// SetAiInfo sets the "ai_info" field.
+func (u *WxCardUpsert) SetAiInfo(v string) *WxCardUpsert {
+	u.Set(wxcard.FieldAiInfo, v)
+	return u
+}
+
+// UpdateAiInfo sets the "ai_info" field to the value that was provided on create.
+func (u *WxCardUpsert) UpdateAiInfo() *WxCardUpsert {
+	u.SetExcluded(wxcard.FieldAiInfo)
+	return u
+}
+
+// ClearAiInfo clears the value of the "ai_info" field.
+func (u *WxCardUpsert) ClearAiInfo() *WxCardUpsert {
+	u.SetNull(wxcard.FieldAiInfo)
+	return u
+}
+
+// SetIntro sets the "intro" field.
+func (u *WxCardUpsert) SetIntro(v string) *WxCardUpsert {
+	u.Set(wxcard.FieldIntro, v)
+	return u
+}
+
+// UpdateIntro sets the "intro" field to the value that was provided on create.
+func (u *WxCardUpsert) UpdateIntro() *WxCardUpsert {
+	u.SetExcluded(wxcard.FieldIntro)
+	return u
+}
+
+// ClearIntro clears the value of the "intro" field.
+func (u *WxCardUpsert) ClearIntro() *WxCardUpsert {
+	u.SetNull(wxcard.FieldIntro)
+	return u
+}
+
+// UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field.
+// Using this option is equivalent to using:
+//
+//	client.WxCard.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(wxcard.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *WxCardUpsertOne) UpdateNewValues() *WxCardUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
+		if _, exists := u.create.mutation.ID(); exists {
+			s.SetIgnore(wxcard.FieldID)
+		}
+		if _, exists := u.create.mutation.CreatedAt(); exists {
+			s.SetIgnore(wxcard.FieldCreatedAt)
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.WxCard.Create().
+//	    OnConflict(sql.ResolveWithIgnore()).
+//	    Exec(ctx)
+func (u *WxCardUpsertOne) Ignore() *WxCardUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
+	return u
+}
+
+// DoNothing configures the conflict_action to `DO NOTHING`.
+// Supported only by SQLite and PostgreSQL.
+func (u *WxCardUpsertOne) DoNothing() *WxCardUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the WxCardCreate.OnConflict
+// documentation for more info.
+func (u *WxCardUpsertOne) Update(set func(*WxCardUpsert)) *WxCardUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&WxCardUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *WxCardUpsertOne) SetUpdatedAt(v time.Time) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *WxCardUpsertOne) UpdateUpdatedAt() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *WxCardUpsertOne) SetDeletedAt(v time.Time) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *WxCardUpsertOne) UpdateDeletedAt() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *WxCardUpsertOne) ClearDeletedAt() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetUserID sets the "user_id" field.
+func (u *WxCardUpsertOne) SetUserID(v uint64) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetUserID(v)
+	})
+}
+
+// AddUserID adds v to the "user_id" field.
+func (u *WxCardUpsertOne) AddUserID(v uint64) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.AddUserID(v)
+	})
+}
+
+// UpdateUserID sets the "user_id" field to the value that was provided on create.
+func (u *WxCardUpsertOne) UpdateUserID() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateUserID()
+	})
+}
+
+// ClearUserID clears the value of the "user_id" field.
+func (u *WxCardUpsertOne) ClearUserID() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.ClearUserID()
+	})
+}
+
+// SetWxUserID sets the "wx_user_id" field.
+func (u *WxCardUpsertOne) SetWxUserID(v uint64) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetWxUserID(v)
+	})
+}
+
+// AddWxUserID adds v to the "wx_user_id" field.
+func (u *WxCardUpsertOne) AddWxUserID(v uint64) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.AddWxUserID(v)
+	})
+}
+
+// UpdateWxUserID sets the "wx_user_id" field to the value that was provided on create.
+func (u *WxCardUpsertOne) UpdateWxUserID() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateWxUserID()
+	})
+}
+
+// ClearWxUserID clears the value of the "wx_user_id" field.
+func (u *WxCardUpsertOne) ClearWxUserID() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.ClearWxUserID()
+	})
+}
+
+// SetAvatar sets the "avatar" field.
+func (u *WxCardUpsertOne) SetAvatar(v string) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetAvatar(v)
+	})
+}
+
+// UpdateAvatar sets the "avatar" field to the value that was provided on create.
+func (u *WxCardUpsertOne) UpdateAvatar() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateAvatar()
+	})
+}
+
+// SetLogo sets the "logo" field.
+func (u *WxCardUpsertOne) SetLogo(v string) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetLogo(v)
+	})
+}
+
+// UpdateLogo sets the "logo" field to the value that was provided on create.
+func (u *WxCardUpsertOne) UpdateLogo() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateLogo()
+	})
+}
+
+// SetName sets the "name" field.
+func (u *WxCardUpsertOne) SetName(v string) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetName(v)
+	})
+}
+
+// UpdateName sets the "name" field to the value that was provided on create.
+func (u *WxCardUpsertOne) UpdateName() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateName()
+	})
+}
+
+// SetCompany sets the "company" field.
+func (u *WxCardUpsertOne) SetCompany(v string) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetCompany(v)
+	})
+}
+
+// UpdateCompany sets the "company" field to the value that was provided on create.
+func (u *WxCardUpsertOne) UpdateCompany() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateCompany()
+	})
+}
+
+// SetAddress sets the "address" field.
+func (u *WxCardUpsertOne) SetAddress(v string) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetAddress(v)
+	})
+}
+
+// UpdateAddress sets the "address" field to the value that was provided on create.
+func (u *WxCardUpsertOne) UpdateAddress() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateAddress()
+	})
+}
+
+// SetPhone sets the "phone" field.
+func (u *WxCardUpsertOne) SetPhone(v string) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetPhone(v)
+	})
+}
+
+// UpdatePhone sets the "phone" field to the value that was provided on create.
+func (u *WxCardUpsertOne) UpdatePhone() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdatePhone()
+	})
+}
+
+// SetOfficialAccount sets the "official_account" field.
+func (u *WxCardUpsertOne) SetOfficialAccount(v string) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetOfficialAccount(v)
+	})
+}
+
+// UpdateOfficialAccount sets the "official_account" field to the value that was provided on create.
+func (u *WxCardUpsertOne) UpdateOfficialAccount() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateOfficialAccount()
+	})
+}
+
+// SetWechatAccount sets the "wechat_account" field.
+func (u *WxCardUpsertOne) SetWechatAccount(v string) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetWechatAccount(v)
+	})
+}
+
+// UpdateWechatAccount sets the "wechat_account" field to the value that was provided on create.
+func (u *WxCardUpsertOne) UpdateWechatAccount() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateWechatAccount()
+	})
+}
+
+// SetEmail sets the "email" field.
+func (u *WxCardUpsertOne) SetEmail(v string) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetEmail(v)
+	})
+}
+
+// UpdateEmail sets the "email" field to the value that was provided on create.
+func (u *WxCardUpsertOne) UpdateEmail() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateEmail()
+	})
+}
+
+// ClearEmail clears the value of the "email" field.
+func (u *WxCardUpsertOne) ClearEmail() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.ClearEmail()
+	})
+}
+
+// SetAPIBase sets the "api_base" field.
+func (u *WxCardUpsertOne) SetAPIBase(v string) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetAPIBase(v)
+	})
+}
+
+// UpdateAPIBase sets the "api_base" field to the value that was provided on create.
+func (u *WxCardUpsertOne) UpdateAPIBase() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateAPIBase()
+	})
+}
+
+// ClearAPIBase clears the value of the "api_base" field.
+func (u *WxCardUpsertOne) ClearAPIBase() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.ClearAPIBase()
+	})
+}
+
+// SetAPIKey sets the "api_key" field.
+func (u *WxCardUpsertOne) SetAPIKey(v string) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetAPIKey(v)
+	})
+}
+
+// UpdateAPIKey sets the "api_key" field to the value that was provided on create.
+func (u *WxCardUpsertOne) UpdateAPIKey() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateAPIKey()
+	})
+}
+
+// ClearAPIKey clears the value of the "api_key" field.
+func (u *WxCardUpsertOne) ClearAPIKey() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.ClearAPIKey()
+	})
+}
+
+// SetAiInfo sets the "ai_info" field.
+func (u *WxCardUpsertOne) SetAiInfo(v string) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetAiInfo(v)
+	})
+}
+
+// UpdateAiInfo sets the "ai_info" field to the value that was provided on create.
+func (u *WxCardUpsertOne) UpdateAiInfo() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateAiInfo()
+	})
+}
+
+// ClearAiInfo clears the value of the "ai_info" field.
+func (u *WxCardUpsertOne) ClearAiInfo() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.ClearAiInfo()
+	})
+}
+
+// SetIntro sets the "intro" field.
+func (u *WxCardUpsertOne) SetIntro(v string) *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetIntro(v)
+	})
+}
+
+// UpdateIntro sets the "intro" field to the value that was provided on create.
+func (u *WxCardUpsertOne) UpdateIntro() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateIntro()
+	})
+}
+
+// ClearIntro clears the value of the "intro" field.
+func (u *WxCardUpsertOne) ClearIntro() *WxCardUpsertOne {
+	return u.Update(func(s *WxCardUpsert) {
+		s.ClearIntro()
+	})
+}
+
+// Exec executes the query.
+func (u *WxCardUpsertOne) Exec(ctx context.Context) error {
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for WxCardCreate.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *WxCardUpsertOne) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// Exec executes the UPSERT query and returns the inserted/updated ID.
+func (u *WxCardUpsertOne) ID(ctx context.Context) (id uint64, err error) {
+	node, err := u.create.Save(ctx)
+	if err != nil {
+		return id, err
+	}
+	return node.ID, nil
+}
+
+// IDX is like ID, but panics if an error occurs.
+func (u *WxCardUpsertOne) IDX(ctx context.Context) uint64 {
+	id, err := u.ID(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+// WxCardCreateBulk is the builder for creating many WxCard entities in bulk.
+type WxCardCreateBulk struct {
+	config
+	err      error
+	builders []*WxCardCreate
+	conflict []sql.ConflictOption
+}
+
+// Save creates the WxCard entities in the database.
+func (wccb *WxCardCreateBulk) Save(ctx context.Context) ([]*WxCard, error) {
+	if wccb.err != nil {
+		return nil, wccb.err
+	}
+	specs := make([]*sqlgraph.CreateSpec, len(wccb.builders))
+	nodes := make([]*WxCard, len(wccb.builders))
+	mutators := make([]Mutator, len(wccb.builders))
+	for i := range wccb.builders {
+		func(i int, root context.Context) {
+			builder := wccb.builders[i]
+			builder.defaults()
+			var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
+				mutation, ok := m.(*WxCardMutation)
+				if !ok {
+					return nil, fmt.Errorf("unexpected mutation type %T", m)
+				}
+				if err := builder.check(); err != nil {
+					return nil, err
+				}
+				builder.mutation = mutation
+				var err error
+				nodes[i], specs[i] = builder.createSpec()
+				if i < len(mutators)-1 {
+					_, err = mutators[i+1].Mutate(root, wccb.builders[i+1].mutation)
+				} else {
+					spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
+					spec.OnConflict = wccb.conflict
+					// Invoke the actual operation on the latest mutation in the chain.
+					if err = sqlgraph.BatchCreate(ctx, wccb.driver, spec); err != nil {
+						if sqlgraph.IsConstraintError(err) {
+							err = &ConstraintError{msg: err.Error(), wrap: err}
+						}
+					}
+				}
+				if err != nil {
+					return nil, err
+				}
+				mutation.id = &nodes[i].ID
+				if specs[i].ID.Value != nil && nodes[i].ID == 0 {
+					id := specs[i].ID.Value.(int64)
+					nodes[i].ID = uint64(id)
+				}
+				mutation.done = true
+				return nodes[i], nil
+			})
+			for i := len(builder.hooks) - 1; i >= 0; i-- {
+				mut = builder.hooks[i](mut)
+			}
+			mutators[i] = mut
+		}(i, ctx)
+	}
+	if len(mutators) > 0 {
+		if _, err := mutators[0].Mutate(ctx, wccb.builders[0].mutation); err != nil {
+			return nil, err
+		}
+	}
+	return nodes, nil
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (wccb *WxCardCreateBulk) SaveX(ctx context.Context) []*WxCard {
+	v, err := wccb.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (wccb *WxCardCreateBulk) Exec(ctx context.Context) error {
+	_, err := wccb.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (wccb *WxCardCreateBulk) ExecX(ctx context.Context) {
+	if err := wccb.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.WxCard.CreateBulk(builders...).
+//		OnConflict(
+//			// Update the row with the new values
+//			// the was proposed for insertion.
+//			sql.ResolveWithNewValues(),
+//		).
+//		// Override some of the fields with custom
+//		// update values.
+//		Update(func(u *ent.WxCardUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (wccb *WxCardCreateBulk) OnConflict(opts ...sql.ConflictOption) *WxCardUpsertBulk {
+	wccb.conflict = opts
+	return &WxCardUpsertBulk{
+		create: wccb,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.WxCard.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (wccb *WxCardCreateBulk) OnConflictColumns(columns ...string) *WxCardUpsertBulk {
+	wccb.conflict = append(wccb.conflict, sql.ConflictColumns(columns...))
+	return &WxCardUpsertBulk{
+		create: wccb,
+	}
+}
+
+// WxCardUpsertBulk is the builder for "upsert"-ing
+// a bulk of WxCard nodes.
+type WxCardUpsertBulk struct {
+	create *WxCardCreateBulk
+}
+
+// UpdateNewValues updates the mutable fields using the new values that
+// were set on create. Using this option is equivalent to using:
+//
+//	client.WxCard.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(wxcard.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *WxCardUpsertBulk) UpdateNewValues() *WxCardUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
+		for _, b := range u.create.builders {
+			if _, exists := b.mutation.ID(); exists {
+				s.SetIgnore(wxcard.FieldID)
+			}
+			if _, exists := b.mutation.CreatedAt(); exists {
+				s.SetIgnore(wxcard.FieldCreatedAt)
+			}
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.WxCard.Create().
+//		OnConflict(sql.ResolveWithIgnore()).
+//		Exec(ctx)
+func (u *WxCardUpsertBulk) Ignore() *WxCardUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
+	return u
+}
+
+// DoNothing configures the conflict_action to `DO NOTHING`.
+// Supported only by SQLite and PostgreSQL.
+func (u *WxCardUpsertBulk) DoNothing() *WxCardUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the WxCardCreateBulk.OnConflict
+// documentation for more info.
+func (u *WxCardUpsertBulk) Update(set func(*WxCardUpsert)) *WxCardUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&WxCardUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *WxCardUpsertBulk) SetUpdatedAt(v time.Time) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *WxCardUpsertBulk) UpdateUpdatedAt() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *WxCardUpsertBulk) SetDeletedAt(v time.Time) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *WxCardUpsertBulk) UpdateDeletedAt() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *WxCardUpsertBulk) ClearDeletedAt() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetUserID sets the "user_id" field.
+func (u *WxCardUpsertBulk) SetUserID(v uint64) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetUserID(v)
+	})
+}
+
+// AddUserID adds v to the "user_id" field.
+func (u *WxCardUpsertBulk) AddUserID(v uint64) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.AddUserID(v)
+	})
+}
+
+// UpdateUserID sets the "user_id" field to the value that was provided on create.
+func (u *WxCardUpsertBulk) UpdateUserID() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateUserID()
+	})
+}
+
+// ClearUserID clears the value of the "user_id" field.
+func (u *WxCardUpsertBulk) ClearUserID() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.ClearUserID()
+	})
+}
+
+// SetWxUserID sets the "wx_user_id" field.
+func (u *WxCardUpsertBulk) SetWxUserID(v uint64) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetWxUserID(v)
+	})
+}
+
+// AddWxUserID adds v to the "wx_user_id" field.
+func (u *WxCardUpsertBulk) AddWxUserID(v uint64) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.AddWxUserID(v)
+	})
+}
+
+// UpdateWxUserID sets the "wx_user_id" field to the value that was provided on create.
+func (u *WxCardUpsertBulk) UpdateWxUserID() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateWxUserID()
+	})
+}
+
+// ClearWxUserID clears the value of the "wx_user_id" field.
+func (u *WxCardUpsertBulk) ClearWxUserID() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.ClearWxUserID()
+	})
+}
+
+// SetAvatar sets the "avatar" field.
+func (u *WxCardUpsertBulk) SetAvatar(v string) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetAvatar(v)
+	})
+}
+
+// UpdateAvatar sets the "avatar" field to the value that was provided on create.
+func (u *WxCardUpsertBulk) UpdateAvatar() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateAvatar()
+	})
+}
+
+// SetLogo sets the "logo" field.
+func (u *WxCardUpsertBulk) SetLogo(v string) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetLogo(v)
+	})
+}
+
+// UpdateLogo sets the "logo" field to the value that was provided on create.
+func (u *WxCardUpsertBulk) UpdateLogo() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateLogo()
+	})
+}
+
+// SetName sets the "name" field.
+func (u *WxCardUpsertBulk) SetName(v string) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetName(v)
+	})
+}
+
+// UpdateName sets the "name" field to the value that was provided on create.
+func (u *WxCardUpsertBulk) UpdateName() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateName()
+	})
+}
+
+// SetCompany sets the "company" field.
+func (u *WxCardUpsertBulk) SetCompany(v string) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetCompany(v)
+	})
+}
+
+// UpdateCompany sets the "company" field to the value that was provided on create.
+func (u *WxCardUpsertBulk) UpdateCompany() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateCompany()
+	})
+}
+
+// SetAddress sets the "address" field.
+func (u *WxCardUpsertBulk) SetAddress(v string) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetAddress(v)
+	})
+}
+
+// UpdateAddress sets the "address" field to the value that was provided on create.
+func (u *WxCardUpsertBulk) UpdateAddress() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateAddress()
+	})
+}
+
+// SetPhone sets the "phone" field.
+func (u *WxCardUpsertBulk) SetPhone(v string) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetPhone(v)
+	})
+}
+
+// UpdatePhone sets the "phone" field to the value that was provided on create.
+func (u *WxCardUpsertBulk) UpdatePhone() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdatePhone()
+	})
+}
+
+// SetOfficialAccount sets the "official_account" field.
+func (u *WxCardUpsertBulk) SetOfficialAccount(v string) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetOfficialAccount(v)
+	})
+}
+
+// UpdateOfficialAccount sets the "official_account" field to the value that was provided on create.
+func (u *WxCardUpsertBulk) UpdateOfficialAccount() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateOfficialAccount()
+	})
+}
+
+// SetWechatAccount sets the "wechat_account" field.
+func (u *WxCardUpsertBulk) SetWechatAccount(v string) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetWechatAccount(v)
+	})
+}
+
+// UpdateWechatAccount sets the "wechat_account" field to the value that was provided on create.
+func (u *WxCardUpsertBulk) UpdateWechatAccount() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateWechatAccount()
+	})
+}
+
+// SetEmail sets the "email" field.
+func (u *WxCardUpsertBulk) SetEmail(v string) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetEmail(v)
+	})
+}
+
+// UpdateEmail sets the "email" field to the value that was provided on create.
+func (u *WxCardUpsertBulk) UpdateEmail() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateEmail()
+	})
+}
+
+// ClearEmail clears the value of the "email" field.
+func (u *WxCardUpsertBulk) ClearEmail() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.ClearEmail()
+	})
+}
+
+// SetAPIBase sets the "api_base" field.
+func (u *WxCardUpsertBulk) SetAPIBase(v string) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetAPIBase(v)
+	})
+}
+
+// UpdateAPIBase sets the "api_base" field to the value that was provided on create.
+func (u *WxCardUpsertBulk) UpdateAPIBase() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateAPIBase()
+	})
+}
+
+// ClearAPIBase clears the value of the "api_base" field.
+func (u *WxCardUpsertBulk) ClearAPIBase() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.ClearAPIBase()
+	})
+}
+
+// SetAPIKey sets the "api_key" field.
+func (u *WxCardUpsertBulk) SetAPIKey(v string) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetAPIKey(v)
+	})
+}
+
+// UpdateAPIKey sets the "api_key" field to the value that was provided on create.
+func (u *WxCardUpsertBulk) UpdateAPIKey() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateAPIKey()
+	})
+}
+
+// ClearAPIKey clears the value of the "api_key" field.
+func (u *WxCardUpsertBulk) ClearAPIKey() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.ClearAPIKey()
+	})
+}
+
+// SetAiInfo sets the "ai_info" field.
+func (u *WxCardUpsertBulk) SetAiInfo(v string) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetAiInfo(v)
+	})
+}
+
+// UpdateAiInfo sets the "ai_info" field to the value that was provided on create.
+func (u *WxCardUpsertBulk) UpdateAiInfo() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateAiInfo()
+	})
+}
+
+// ClearAiInfo clears the value of the "ai_info" field.
+func (u *WxCardUpsertBulk) ClearAiInfo() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.ClearAiInfo()
+	})
+}
+
+// SetIntro sets the "intro" field.
+func (u *WxCardUpsertBulk) SetIntro(v string) *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.SetIntro(v)
+	})
+}
+
+// UpdateIntro sets the "intro" field to the value that was provided on create.
+func (u *WxCardUpsertBulk) UpdateIntro() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.UpdateIntro()
+	})
+}
+
+// ClearIntro clears the value of the "intro" field.
+func (u *WxCardUpsertBulk) ClearIntro() *WxCardUpsertBulk {
+	return u.Update(func(s *WxCardUpsert) {
+		s.ClearIntro()
+	})
+}
+
+// Exec executes the query.
+func (u *WxCardUpsertBulk) Exec(ctx context.Context) error {
+	if u.create.err != nil {
+		return u.create.err
+	}
+	for i, b := range u.create.builders {
+		if len(b.conflict) != 0 {
+			return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the WxCardCreateBulk instead", i)
+		}
+	}
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for WxCardCreateBulk.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *WxCardUpsertBulk) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}

+ 88 - 0
ent/wxcard_delete.go

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

+ 526 - 0
ent/wxcard_query.go

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

+ 952 - 0
ent/wxcard_update.go

@@ -0,0 +1,952 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/predicate"
+	"wechat-api/ent/wxcard"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// WxCardUpdate is the builder for updating WxCard entities.
+type WxCardUpdate struct {
+	config
+	hooks    []Hook
+	mutation *WxCardMutation
+}
+
+// Where appends a list predicates to the WxCardUpdate builder.
+func (wcu *WxCardUpdate) Where(ps ...predicate.WxCard) *WxCardUpdate {
+	wcu.mutation.Where(ps...)
+	return wcu
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (wcu *WxCardUpdate) SetUpdatedAt(t time.Time) *WxCardUpdate {
+	wcu.mutation.SetUpdatedAt(t)
+	return wcu
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (wcu *WxCardUpdate) SetDeletedAt(t time.Time) *WxCardUpdate {
+	wcu.mutation.SetDeletedAt(t)
+	return wcu
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (wcu *WxCardUpdate) SetNillableDeletedAt(t *time.Time) *WxCardUpdate {
+	if t != nil {
+		wcu.SetDeletedAt(*t)
+	}
+	return wcu
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (wcu *WxCardUpdate) ClearDeletedAt() *WxCardUpdate {
+	wcu.mutation.ClearDeletedAt()
+	return wcu
+}
+
+// SetUserID sets the "user_id" field.
+func (wcu *WxCardUpdate) SetUserID(u uint64) *WxCardUpdate {
+	wcu.mutation.ResetUserID()
+	wcu.mutation.SetUserID(u)
+	return wcu
+}
+
+// SetNillableUserID sets the "user_id" field if the given value is not nil.
+func (wcu *WxCardUpdate) SetNillableUserID(u *uint64) *WxCardUpdate {
+	if u != nil {
+		wcu.SetUserID(*u)
+	}
+	return wcu
+}
+
+// AddUserID adds u to the "user_id" field.
+func (wcu *WxCardUpdate) AddUserID(u int64) *WxCardUpdate {
+	wcu.mutation.AddUserID(u)
+	return wcu
+}
+
+// ClearUserID clears the value of the "user_id" field.
+func (wcu *WxCardUpdate) ClearUserID() *WxCardUpdate {
+	wcu.mutation.ClearUserID()
+	return wcu
+}
+
+// SetWxUserID sets the "wx_user_id" field.
+func (wcu *WxCardUpdate) SetWxUserID(u uint64) *WxCardUpdate {
+	wcu.mutation.ResetWxUserID()
+	wcu.mutation.SetWxUserID(u)
+	return wcu
+}
+
+// SetNillableWxUserID sets the "wx_user_id" field if the given value is not nil.
+func (wcu *WxCardUpdate) SetNillableWxUserID(u *uint64) *WxCardUpdate {
+	if u != nil {
+		wcu.SetWxUserID(*u)
+	}
+	return wcu
+}
+
+// AddWxUserID adds u to the "wx_user_id" field.
+func (wcu *WxCardUpdate) AddWxUserID(u int64) *WxCardUpdate {
+	wcu.mutation.AddWxUserID(u)
+	return wcu
+}
+
+// ClearWxUserID clears the value of the "wx_user_id" field.
+func (wcu *WxCardUpdate) ClearWxUserID() *WxCardUpdate {
+	wcu.mutation.ClearWxUserID()
+	return wcu
+}
+
+// SetAvatar sets the "avatar" field.
+func (wcu *WxCardUpdate) SetAvatar(s string) *WxCardUpdate {
+	wcu.mutation.SetAvatar(s)
+	return wcu
+}
+
+// SetNillableAvatar sets the "avatar" field if the given value is not nil.
+func (wcu *WxCardUpdate) SetNillableAvatar(s *string) *WxCardUpdate {
+	if s != nil {
+		wcu.SetAvatar(*s)
+	}
+	return wcu
+}
+
+// SetLogo sets the "logo" field.
+func (wcu *WxCardUpdate) SetLogo(s string) *WxCardUpdate {
+	wcu.mutation.SetLogo(s)
+	return wcu
+}
+
+// SetNillableLogo sets the "logo" field if the given value is not nil.
+func (wcu *WxCardUpdate) SetNillableLogo(s *string) *WxCardUpdate {
+	if s != nil {
+		wcu.SetLogo(*s)
+	}
+	return wcu
+}
+
+// SetName sets the "name" field.
+func (wcu *WxCardUpdate) SetName(s string) *WxCardUpdate {
+	wcu.mutation.SetName(s)
+	return wcu
+}
+
+// SetNillableName sets the "name" field if the given value is not nil.
+func (wcu *WxCardUpdate) SetNillableName(s *string) *WxCardUpdate {
+	if s != nil {
+		wcu.SetName(*s)
+	}
+	return wcu
+}
+
+// SetCompany sets the "company" field.
+func (wcu *WxCardUpdate) SetCompany(s string) *WxCardUpdate {
+	wcu.mutation.SetCompany(s)
+	return wcu
+}
+
+// SetNillableCompany sets the "company" field if the given value is not nil.
+func (wcu *WxCardUpdate) SetNillableCompany(s *string) *WxCardUpdate {
+	if s != nil {
+		wcu.SetCompany(*s)
+	}
+	return wcu
+}
+
+// SetAddress sets the "address" field.
+func (wcu *WxCardUpdate) SetAddress(s string) *WxCardUpdate {
+	wcu.mutation.SetAddress(s)
+	return wcu
+}
+
+// SetNillableAddress sets the "address" field if the given value is not nil.
+func (wcu *WxCardUpdate) SetNillableAddress(s *string) *WxCardUpdate {
+	if s != nil {
+		wcu.SetAddress(*s)
+	}
+	return wcu
+}
+
+// SetPhone sets the "phone" field.
+func (wcu *WxCardUpdate) SetPhone(s string) *WxCardUpdate {
+	wcu.mutation.SetPhone(s)
+	return wcu
+}
+
+// SetNillablePhone sets the "phone" field if the given value is not nil.
+func (wcu *WxCardUpdate) SetNillablePhone(s *string) *WxCardUpdate {
+	if s != nil {
+		wcu.SetPhone(*s)
+	}
+	return wcu
+}
+
+// SetOfficialAccount sets the "official_account" field.
+func (wcu *WxCardUpdate) SetOfficialAccount(s string) *WxCardUpdate {
+	wcu.mutation.SetOfficialAccount(s)
+	return wcu
+}
+
+// SetNillableOfficialAccount sets the "official_account" field if the given value is not nil.
+func (wcu *WxCardUpdate) SetNillableOfficialAccount(s *string) *WxCardUpdate {
+	if s != nil {
+		wcu.SetOfficialAccount(*s)
+	}
+	return wcu
+}
+
+// SetWechatAccount sets the "wechat_account" field.
+func (wcu *WxCardUpdate) SetWechatAccount(s string) *WxCardUpdate {
+	wcu.mutation.SetWechatAccount(s)
+	return wcu
+}
+
+// SetNillableWechatAccount sets the "wechat_account" field if the given value is not nil.
+func (wcu *WxCardUpdate) SetNillableWechatAccount(s *string) *WxCardUpdate {
+	if s != nil {
+		wcu.SetWechatAccount(*s)
+	}
+	return wcu
+}
+
+// SetEmail sets the "email" field.
+func (wcu *WxCardUpdate) SetEmail(s string) *WxCardUpdate {
+	wcu.mutation.SetEmail(s)
+	return wcu
+}
+
+// SetNillableEmail sets the "email" field if the given value is not nil.
+func (wcu *WxCardUpdate) SetNillableEmail(s *string) *WxCardUpdate {
+	if s != nil {
+		wcu.SetEmail(*s)
+	}
+	return wcu
+}
+
+// ClearEmail clears the value of the "email" field.
+func (wcu *WxCardUpdate) ClearEmail() *WxCardUpdate {
+	wcu.mutation.ClearEmail()
+	return wcu
+}
+
+// SetAPIBase sets the "api_base" field.
+func (wcu *WxCardUpdate) SetAPIBase(s string) *WxCardUpdate {
+	wcu.mutation.SetAPIBase(s)
+	return wcu
+}
+
+// SetNillableAPIBase sets the "api_base" field if the given value is not nil.
+func (wcu *WxCardUpdate) SetNillableAPIBase(s *string) *WxCardUpdate {
+	if s != nil {
+		wcu.SetAPIBase(*s)
+	}
+	return wcu
+}
+
+// ClearAPIBase clears the value of the "api_base" field.
+func (wcu *WxCardUpdate) ClearAPIBase() *WxCardUpdate {
+	wcu.mutation.ClearAPIBase()
+	return wcu
+}
+
+// SetAPIKey sets the "api_key" field.
+func (wcu *WxCardUpdate) SetAPIKey(s string) *WxCardUpdate {
+	wcu.mutation.SetAPIKey(s)
+	return wcu
+}
+
+// SetNillableAPIKey sets the "api_key" field if the given value is not nil.
+func (wcu *WxCardUpdate) SetNillableAPIKey(s *string) *WxCardUpdate {
+	if s != nil {
+		wcu.SetAPIKey(*s)
+	}
+	return wcu
+}
+
+// ClearAPIKey clears the value of the "api_key" field.
+func (wcu *WxCardUpdate) ClearAPIKey() *WxCardUpdate {
+	wcu.mutation.ClearAPIKey()
+	return wcu
+}
+
+// SetAiInfo sets the "ai_info" field.
+func (wcu *WxCardUpdate) SetAiInfo(s string) *WxCardUpdate {
+	wcu.mutation.SetAiInfo(s)
+	return wcu
+}
+
+// SetNillableAiInfo sets the "ai_info" field if the given value is not nil.
+func (wcu *WxCardUpdate) SetNillableAiInfo(s *string) *WxCardUpdate {
+	if s != nil {
+		wcu.SetAiInfo(*s)
+	}
+	return wcu
+}
+
+// ClearAiInfo clears the value of the "ai_info" field.
+func (wcu *WxCardUpdate) ClearAiInfo() *WxCardUpdate {
+	wcu.mutation.ClearAiInfo()
+	return wcu
+}
+
+// SetIntro sets the "intro" field.
+func (wcu *WxCardUpdate) SetIntro(s string) *WxCardUpdate {
+	wcu.mutation.SetIntro(s)
+	return wcu
+}
+
+// SetNillableIntro sets the "intro" field if the given value is not nil.
+func (wcu *WxCardUpdate) SetNillableIntro(s *string) *WxCardUpdate {
+	if s != nil {
+		wcu.SetIntro(*s)
+	}
+	return wcu
+}
+
+// ClearIntro clears the value of the "intro" field.
+func (wcu *WxCardUpdate) ClearIntro() *WxCardUpdate {
+	wcu.mutation.ClearIntro()
+	return wcu
+}
+
+// Mutation returns the WxCardMutation object of the builder.
+func (wcu *WxCardUpdate) Mutation() *WxCardMutation {
+	return wcu.mutation
+}
+
+// Save executes the query and returns the number of nodes affected by the update operation.
+func (wcu *WxCardUpdate) Save(ctx context.Context) (int, error) {
+	if err := wcu.defaults(); err != nil {
+		return 0, err
+	}
+	return withHooks(ctx, wcu.sqlSave, wcu.mutation, wcu.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (wcu *WxCardUpdate) SaveX(ctx context.Context) int {
+	affected, err := wcu.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return affected
+}
+
+// Exec executes the query.
+func (wcu *WxCardUpdate) Exec(ctx context.Context) error {
+	_, err := wcu.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (wcu *WxCardUpdate) ExecX(ctx context.Context) {
+	if err := wcu.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (wcu *WxCardUpdate) defaults() error {
+	if _, ok := wcu.mutation.UpdatedAt(); !ok {
+		if wxcard.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized wxcard.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := wxcard.UpdateDefaultUpdatedAt()
+		wcu.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+func (wcu *WxCardUpdate) sqlSave(ctx context.Context) (n int, err error) {
+	_spec := sqlgraph.NewUpdateSpec(wxcard.Table, wxcard.Columns, sqlgraph.NewFieldSpec(wxcard.FieldID, field.TypeUint64))
+	if ps := wcu.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := wcu.mutation.UpdatedAt(); ok {
+		_spec.SetField(wxcard.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := wcu.mutation.DeletedAt(); ok {
+		_spec.SetField(wxcard.FieldDeletedAt, field.TypeTime, value)
+	}
+	if wcu.mutation.DeletedAtCleared() {
+		_spec.ClearField(wxcard.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := wcu.mutation.UserID(); ok {
+		_spec.SetField(wxcard.FieldUserID, field.TypeUint64, value)
+	}
+	if value, ok := wcu.mutation.AddedUserID(); ok {
+		_spec.AddField(wxcard.FieldUserID, field.TypeUint64, value)
+	}
+	if wcu.mutation.UserIDCleared() {
+		_spec.ClearField(wxcard.FieldUserID, field.TypeUint64)
+	}
+	if value, ok := wcu.mutation.WxUserID(); ok {
+		_spec.SetField(wxcard.FieldWxUserID, field.TypeUint64, value)
+	}
+	if value, ok := wcu.mutation.AddedWxUserID(); ok {
+		_spec.AddField(wxcard.FieldWxUserID, field.TypeUint64, value)
+	}
+	if wcu.mutation.WxUserIDCleared() {
+		_spec.ClearField(wxcard.FieldWxUserID, field.TypeUint64)
+	}
+	if value, ok := wcu.mutation.Avatar(); ok {
+		_spec.SetField(wxcard.FieldAvatar, field.TypeString, value)
+	}
+	if value, ok := wcu.mutation.Logo(); ok {
+		_spec.SetField(wxcard.FieldLogo, field.TypeString, value)
+	}
+	if value, ok := wcu.mutation.Name(); ok {
+		_spec.SetField(wxcard.FieldName, field.TypeString, value)
+	}
+	if value, ok := wcu.mutation.Company(); ok {
+		_spec.SetField(wxcard.FieldCompany, field.TypeString, value)
+	}
+	if value, ok := wcu.mutation.Address(); ok {
+		_spec.SetField(wxcard.FieldAddress, field.TypeString, value)
+	}
+	if value, ok := wcu.mutation.Phone(); ok {
+		_spec.SetField(wxcard.FieldPhone, field.TypeString, value)
+	}
+	if value, ok := wcu.mutation.OfficialAccount(); ok {
+		_spec.SetField(wxcard.FieldOfficialAccount, field.TypeString, value)
+	}
+	if value, ok := wcu.mutation.WechatAccount(); ok {
+		_spec.SetField(wxcard.FieldWechatAccount, field.TypeString, value)
+	}
+	if value, ok := wcu.mutation.Email(); ok {
+		_spec.SetField(wxcard.FieldEmail, field.TypeString, value)
+	}
+	if wcu.mutation.EmailCleared() {
+		_spec.ClearField(wxcard.FieldEmail, field.TypeString)
+	}
+	if value, ok := wcu.mutation.APIBase(); ok {
+		_spec.SetField(wxcard.FieldAPIBase, field.TypeString, value)
+	}
+	if wcu.mutation.APIBaseCleared() {
+		_spec.ClearField(wxcard.FieldAPIBase, field.TypeString)
+	}
+	if value, ok := wcu.mutation.APIKey(); ok {
+		_spec.SetField(wxcard.FieldAPIKey, field.TypeString, value)
+	}
+	if wcu.mutation.APIKeyCleared() {
+		_spec.ClearField(wxcard.FieldAPIKey, field.TypeString)
+	}
+	if value, ok := wcu.mutation.AiInfo(); ok {
+		_spec.SetField(wxcard.FieldAiInfo, field.TypeString, value)
+	}
+	if wcu.mutation.AiInfoCleared() {
+		_spec.ClearField(wxcard.FieldAiInfo, field.TypeString)
+	}
+	if value, ok := wcu.mutation.Intro(); ok {
+		_spec.SetField(wxcard.FieldIntro, field.TypeString, value)
+	}
+	if wcu.mutation.IntroCleared() {
+		_spec.ClearField(wxcard.FieldIntro, field.TypeString)
+	}
+	if n, err = sqlgraph.UpdateNodes(ctx, wcu.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{wxcard.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return 0, err
+	}
+	wcu.mutation.done = true
+	return n, nil
+}
+
+// WxCardUpdateOne is the builder for updating a single WxCard entity.
+type WxCardUpdateOne struct {
+	config
+	fields   []string
+	hooks    []Hook
+	mutation *WxCardMutation
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (wcuo *WxCardUpdateOne) SetUpdatedAt(t time.Time) *WxCardUpdateOne {
+	wcuo.mutation.SetUpdatedAt(t)
+	return wcuo
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (wcuo *WxCardUpdateOne) SetDeletedAt(t time.Time) *WxCardUpdateOne {
+	wcuo.mutation.SetDeletedAt(t)
+	return wcuo
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (wcuo *WxCardUpdateOne) SetNillableDeletedAt(t *time.Time) *WxCardUpdateOne {
+	if t != nil {
+		wcuo.SetDeletedAt(*t)
+	}
+	return wcuo
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (wcuo *WxCardUpdateOne) ClearDeletedAt() *WxCardUpdateOne {
+	wcuo.mutation.ClearDeletedAt()
+	return wcuo
+}
+
+// SetUserID sets the "user_id" field.
+func (wcuo *WxCardUpdateOne) SetUserID(u uint64) *WxCardUpdateOne {
+	wcuo.mutation.ResetUserID()
+	wcuo.mutation.SetUserID(u)
+	return wcuo
+}
+
+// SetNillableUserID sets the "user_id" field if the given value is not nil.
+func (wcuo *WxCardUpdateOne) SetNillableUserID(u *uint64) *WxCardUpdateOne {
+	if u != nil {
+		wcuo.SetUserID(*u)
+	}
+	return wcuo
+}
+
+// AddUserID adds u to the "user_id" field.
+func (wcuo *WxCardUpdateOne) AddUserID(u int64) *WxCardUpdateOne {
+	wcuo.mutation.AddUserID(u)
+	return wcuo
+}
+
+// ClearUserID clears the value of the "user_id" field.
+func (wcuo *WxCardUpdateOne) ClearUserID() *WxCardUpdateOne {
+	wcuo.mutation.ClearUserID()
+	return wcuo
+}
+
+// SetWxUserID sets the "wx_user_id" field.
+func (wcuo *WxCardUpdateOne) SetWxUserID(u uint64) *WxCardUpdateOne {
+	wcuo.mutation.ResetWxUserID()
+	wcuo.mutation.SetWxUserID(u)
+	return wcuo
+}
+
+// SetNillableWxUserID sets the "wx_user_id" field if the given value is not nil.
+func (wcuo *WxCardUpdateOne) SetNillableWxUserID(u *uint64) *WxCardUpdateOne {
+	if u != nil {
+		wcuo.SetWxUserID(*u)
+	}
+	return wcuo
+}
+
+// AddWxUserID adds u to the "wx_user_id" field.
+func (wcuo *WxCardUpdateOne) AddWxUserID(u int64) *WxCardUpdateOne {
+	wcuo.mutation.AddWxUserID(u)
+	return wcuo
+}
+
+// ClearWxUserID clears the value of the "wx_user_id" field.
+func (wcuo *WxCardUpdateOne) ClearWxUserID() *WxCardUpdateOne {
+	wcuo.mutation.ClearWxUserID()
+	return wcuo
+}
+
+// SetAvatar sets the "avatar" field.
+func (wcuo *WxCardUpdateOne) SetAvatar(s string) *WxCardUpdateOne {
+	wcuo.mutation.SetAvatar(s)
+	return wcuo
+}
+
+// SetNillableAvatar sets the "avatar" field if the given value is not nil.
+func (wcuo *WxCardUpdateOne) SetNillableAvatar(s *string) *WxCardUpdateOne {
+	if s != nil {
+		wcuo.SetAvatar(*s)
+	}
+	return wcuo
+}
+
+// SetLogo sets the "logo" field.
+func (wcuo *WxCardUpdateOne) SetLogo(s string) *WxCardUpdateOne {
+	wcuo.mutation.SetLogo(s)
+	return wcuo
+}
+
+// SetNillableLogo sets the "logo" field if the given value is not nil.
+func (wcuo *WxCardUpdateOne) SetNillableLogo(s *string) *WxCardUpdateOne {
+	if s != nil {
+		wcuo.SetLogo(*s)
+	}
+	return wcuo
+}
+
+// SetName sets the "name" field.
+func (wcuo *WxCardUpdateOne) SetName(s string) *WxCardUpdateOne {
+	wcuo.mutation.SetName(s)
+	return wcuo
+}
+
+// SetNillableName sets the "name" field if the given value is not nil.
+func (wcuo *WxCardUpdateOne) SetNillableName(s *string) *WxCardUpdateOne {
+	if s != nil {
+		wcuo.SetName(*s)
+	}
+	return wcuo
+}
+
+// SetCompany sets the "company" field.
+func (wcuo *WxCardUpdateOne) SetCompany(s string) *WxCardUpdateOne {
+	wcuo.mutation.SetCompany(s)
+	return wcuo
+}
+
+// SetNillableCompany sets the "company" field if the given value is not nil.
+func (wcuo *WxCardUpdateOne) SetNillableCompany(s *string) *WxCardUpdateOne {
+	if s != nil {
+		wcuo.SetCompany(*s)
+	}
+	return wcuo
+}
+
+// SetAddress sets the "address" field.
+func (wcuo *WxCardUpdateOne) SetAddress(s string) *WxCardUpdateOne {
+	wcuo.mutation.SetAddress(s)
+	return wcuo
+}
+
+// SetNillableAddress sets the "address" field if the given value is not nil.
+func (wcuo *WxCardUpdateOne) SetNillableAddress(s *string) *WxCardUpdateOne {
+	if s != nil {
+		wcuo.SetAddress(*s)
+	}
+	return wcuo
+}
+
+// SetPhone sets the "phone" field.
+func (wcuo *WxCardUpdateOne) SetPhone(s string) *WxCardUpdateOne {
+	wcuo.mutation.SetPhone(s)
+	return wcuo
+}
+
+// SetNillablePhone sets the "phone" field if the given value is not nil.
+func (wcuo *WxCardUpdateOne) SetNillablePhone(s *string) *WxCardUpdateOne {
+	if s != nil {
+		wcuo.SetPhone(*s)
+	}
+	return wcuo
+}
+
+// SetOfficialAccount sets the "official_account" field.
+func (wcuo *WxCardUpdateOne) SetOfficialAccount(s string) *WxCardUpdateOne {
+	wcuo.mutation.SetOfficialAccount(s)
+	return wcuo
+}
+
+// SetNillableOfficialAccount sets the "official_account" field if the given value is not nil.
+func (wcuo *WxCardUpdateOne) SetNillableOfficialAccount(s *string) *WxCardUpdateOne {
+	if s != nil {
+		wcuo.SetOfficialAccount(*s)
+	}
+	return wcuo
+}
+
+// SetWechatAccount sets the "wechat_account" field.
+func (wcuo *WxCardUpdateOne) SetWechatAccount(s string) *WxCardUpdateOne {
+	wcuo.mutation.SetWechatAccount(s)
+	return wcuo
+}
+
+// SetNillableWechatAccount sets the "wechat_account" field if the given value is not nil.
+func (wcuo *WxCardUpdateOne) SetNillableWechatAccount(s *string) *WxCardUpdateOne {
+	if s != nil {
+		wcuo.SetWechatAccount(*s)
+	}
+	return wcuo
+}
+
+// SetEmail sets the "email" field.
+func (wcuo *WxCardUpdateOne) SetEmail(s string) *WxCardUpdateOne {
+	wcuo.mutation.SetEmail(s)
+	return wcuo
+}
+
+// SetNillableEmail sets the "email" field if the given value is not nil.
+func (wcuo *WxCardUpdateOne) SetNillableEmail(s *string) *WxCardUpdateOne {
+	if s != nil {
+		wcuo.SetEmail(*s)
+	}
+	return wcuo
+}
+
+// ClearEmail clears the value of the "email" field.
+func (wcuo *WxCardUpdateOne) ClearEmail() *WxCardUpdateOne {
+	wcuo.mutation.ClearEmail()
+	return wcuo
+}
+
+// SetAPIBase sets the "api_base" field.
+func (wcuo *WxCardUpdateOne) SetAPIBase(s string) *WxCardUpdateOne {
+	wcuo.mutation.SetAPIBase(s)
+	return wcuo
+}
+
+// SetNillableAPIBase sets the "api_base" field if the given value is not nil.
+func (wcuo *WxCardUpdateOne) SetNillableAPIBase(s *string) *WxCardUpdateOne {
+	if s != nil {
+		wcuo.SetAPIBase(*s)
+	}
+	return wcuo
+}
+
+// ClearAPIBase clears the value of the "api_base" field.
+func (wcuo *WxCardUpdateOne) ClearAPIBase() *WxCardUpdateOne {
+	wcuo.mutation.ClearAPIBase()
+	return wcuo
+}
+
+// SetAPIKey sets the "api_key" field.
+func (wcuo *WxCardUpdateOne) SetAPIKey(s string) *WxCardUpdateOne {
+	wcuo.mutation.SetAPIKey(s)
+	return wcuo
+}
+
+// SetNillableAPIKey sets the "api_key" field if the given value is not nil.
+func (wcuo *WxCardUpdateOne) SetNillableAPIKey(s *string) *WxCardUpdateOne {
+	if s != nil {
+		wcuo.SetAPIKey(*s)
+	}
+	return wcuo
+}
+
+// ClearAPIKey clears the value of the "api_key" field.
+func (wcuo *WxCardUpdateOne) ClearAPIKey() *WxCardUpdateOne {
+	wcuo.mutation.ClearAPIKey()
+	return wcuo
+}
+
+// SetAiInfo sets the "ai_info" field.
+func (wcuo *WxCardUpdateOne) SetAiInfo(s string) *WxCardUpdateOne {
+	wcuo.mutation.SetAiInfo(s)
+	return wcuo
+}
+
+// SetNillableAiInfo sets the "ai_info" field if the given value is not nil.
+func (wcuo *WxCardUpdateOne) SetNillableAiInfo(s *string) *WxCardUpdateOne {
+	if s != nil {
+		wcuo.SetAiInfo(*s)
+	}
+	return wcuo
+}
+
+// ClearAiInfo clears the value of the "ai_info" field.
+func (wcuo *WxCardUpdateOne) ClearAiInfo() *WxCardUpdateOne {
+	wcuo.mutation.ClearAiInfo()
+	return wcuo
+}
+
+// SetIntro sets the "intro" field.
+func (wcuo *WxCardUpdateOne) SetIntro(s string) *WxCardUpdateOne {
+	wcuo.mutation.SetIntro(s)
+	return wcuo
+}
+
+// SetNillableIntro sets the "intro" field if the given value is not nil.
+func (wcuo *WxCardUpdateOne) SetNillableIntro(s *string) *WxCardUpdateOne {
+	if s != nil {
+		wcuo.SetIntro(*s)
+	}
+	return wcuo
+}
+
+// ClearIntro clears the value of the "intro" field.
+func (wcuo *WxCardUpdateOne) ClearIntro() *WxCardUpdateOne {
+	wcuo.mutation.ClearIntro()
+	return wcuo
+}
+
+// Mutation returns the WxCardMutation object of the builder.
+func (wcuo *WxCardUpdateOne) Mutation() *WxCardMutation {
+	return wcuo.mutation
+}
+
+// Where appends a list predicates to the WxCardUpdate builder.
+func (wcuo *WxCardUpdateOne) Where(ps ...predicate.WxCard) *WxCardUpdateOne {
+	wcuo.mutation.Where(ps...)
+	return wcuo
+}
+
+// Select allows selecting one or more fields (columns) of the returned entity.
+// The default is selecting all fields defined in the entity schema.
+func (wcuo *WxCardUpdateOne) Select(field string, fields ...string) *WxCardUpdateOne {
+	wcuo.fields = append([]string{field}, fields...)
+	return wcuo
+}
+
+// Save executes the query and returns the updated WxCard entity.
+func (wcuo *WxCardUpdateOne) Save(ctx context.Context) (*WxCard, error) {
+	if err := wcuo.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, wcuo.sqlSave, wcuo.mutation, wcuo.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (wcuo *WxCardUpdateOne) SaveX(ctx context.Context) *WxCard {
+	node, err := wcuo.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return node
+}
+
+// Exec executes the query on the entity.
+func (wcuo *WxCardUpdateOne) Exec(ctx context.Context) error {
+	_, err := wcuo.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (wcuo *WxCardUpdateOne) ExecX(ctx context.Context) {
+	if err := wcuo.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (wcuo *WxCardUpdateOne) defaults() error {
+	if _, ok := wcuo.mutation.UpdatedAt(); !ok {
+		if wxcard.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized wxcard.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := wxcard.UpdateDefaultUpdatedAt()
+		wcuo.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+func (wcuo *WxCardUpdateOne) sqlSave(ctx context.Context) (_node *WxCard, err error) {
+	_spec := sqlgraph.NewUpdateSpec(wxcard.Table, wxcard.Columns, sqlgraph.NewFieldSpec(wxcard.FieldID, field.TypeUint64))
+	id, ok := wcuo.mutation.ID()
+	if !ok {
+		return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "WxCard.id" for update`)}
+	}
+	_spec.Node.ID.Value = id
+	if fields := wcuo.fields; len(fields) > 0 {
+		_spec.Node.Columns = make([]string, 0, len(fields))
+		_spec.Node.Columns = append(_spec.Node.Columns, wxcard.FieldID)
+		for _, f := range fields {
+			if !wxcard.ValidColumn(f) {
+				return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+			}
+			if f != wxcard.FieldID {
+				_spec.Node.Columns = append(_spec.Node.Columns, f)
+			}
+		}
+	}
+	if ps := wcuo.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := wcuo.mutation.UpdatedAt(); ok {
+		_spec.SetField(wxcard.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := wcuo.mutation.DeletedAt(); ok {
+		_spec.SetField(wxcard.FieldDeletedAt, field.TypeTime, value)
+	}
+	if wcuo.mutation.DeletedAtCleared() {
+		_spec.ClearField(wxcard.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := wcuo.mutation.UserID(); ok {
+		_spec.SetField(wxcard.FieldUserID, field.TypeUint64, value)
+	}
+	if value, ok := wcuo.mutation.AddedUserID(); ok {
+		_spec.AddField(wxcard.FieldUserID, field.TypeUint64, value)
+	}
+	if wcuo.mutation.UserIDCleared() {
+		_spec.ClearField(wxcard.FieldUserID, field.TypeUint64)
+	}
+	if value, ok := wcuo.mutation.WxUserID(); ok {
+		_spec.SetField(wxcard.FieldWxUserID, field.TypeUint64, value)
+	}
+	if value, ok := wcuo.mutation.AddedWxUserID(); ok {
+		_spec.AddField(wxcard.FieldWxUserID, field.TypeUint64, value)
+	}
+	if wcuo.mutation.WxUserIDCleared() {
+		_spec.ClearField(wxcard.FieldWxUserID, field.TypeUint64)
+	}
+	if value, ok := wcuo.mutation.Avatar(); ok {
+		_spec.SetField(wxcard.FieldAvatar, field.TypeString, value)
+	}
+	if value, ok := wcuo.mutation.Logo(); ok {
+		_spec.SetField(wxcard.FieldLogo, field.TypeString, value)
+	}
+	if value, ok := wcuo.mutation.Name(); ok {
+		_spec.SetField(wxcard.FieldName, field.TypeString, value)
+	}
+	if value, ok := wcuo.mutation.Company(); ok {
+		_spec.SetField(wxcard.FieldCompany, field.TypeString, value)
+	}
+	if value, ok := wcuo.mutation.Address(); ok {
+		_spec.SetField(wxcard.FieldAddress, field.TypeString, value)
+	}
+	if value, ok := wcuo.mutation.Phone(); ok {
+		_spec.SetField(wxcard.FieldPhone, field.TypeString, value)
+	}
+	if value, ok := wcuo.mutation.OfficialAccount(); ok {
+		_spec.SetField(wxcard.FieldOfficialAccount, field.TypeString, value)
+	}
+	if value, ok := wcuo.mutation.WechatAccount(); ok {
+		_spec.SetField(wxcard.FieldWechatAccount, field.TypeString, value)
+	}
+	if value, ok := wcuo.mutation.Email(); ok {
+		_spec.SetField(wxcard.FieldEmail, field.TypeString, value)
+	}
+	if wcuo.mutation.EmailCleared() {
+		_spec.ClearField(wxcard.FieldEmail, field.TypeString)
+	}
+	if value, ok := wcuo.mutation.APIBase(); ok {
+		_spec.SetField(wxcard.FieldAPIBase, field.TypeString, value)
+	}
+	if wcuo.mutation.APIBaseCleared() {
+		_spec.ClearField(wxcard.FieldAPIBase, field.TypeString)
+	}
+	if value, ok := wcuo.mutation.APIKey(); ok {
+		_spec.SetField(wxcard.FieldAPIKey, field.TypeString, value)
+	}
+	if wcuo.mutation.APIKeyCleared() {
+		_spec.ClearField(wxcard.FieldAPIKey, field.TypeString)
+	}
+	if value, ok := wcuo.mutation.AiInfo(); ok {
+		_spec.SetField(wxcard.FieldAiInfo, field.TypeString, value)
+	}
+	if wcuo.mutation.AiInfoCleared() {
+		_spec.ClearField(wxcard.FieldAiInfo, field.TypeString)
+	}
+	if value, ok := wcuo.mutation.Intro(); ok {
+		_spec.SetField(wxcard.FieldIntro, field.TypeString, value)
+	}
+	if wcuo.mutation.IntroCleared() {
+		_spec.ClearField(wxcard.FieldIntro, field.TypeString)
+	}
+	_node = &WxCard{config: wcuo.config}
+	_spec.Assign = _node.assignValues
+	_spec.ScanValues = _node.scanValues
+	if err = sqlgraph.UpdateNode(ctx, wcuo.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{wxcard.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	wcuo.mutation.done = true
+	return _node, nil
+}

+ 227 - 0
ent/wxcarduser.go

@@ -0,0 +1,227 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"fmt"
+	"strings"
+	"time"
+	"wechat-api/ent/wxcarduser"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+)
+
+// WxCardUser is the model entity for the WxCardUser schema.
+type WxCardUser struct {
+	config `json:"-"`
+	// ID of the ent.
+	ID uint64 `json:"id,omitempty"`
+	// Create Time | 创建日期
+	CreatedAt time.Time `json:"created_at,omitempty"`
+	// Update Time | 修改日期
+	UpdatedAt time.Time `json:"updated_at,omitempty"`
+	// Delete Time | 删除日期
+	DeletedAt time.Time `json:"deleted_at,omitempty"`
+	// 微信id
+	Wxid string `json:"wxid,omitempty"`
+	// 微信号
+	Account string `json:"account,omitempty"`
+	// 头像
+	Avatar string `json:"avatar,omitempty"`
+	// 昵称
+	Nickname string `json:"nickname,omitempty"`
+	// 备注名
+	Remark string `json:"remark,omitempty"`
+	// 手机号
+	Phone string `json:"phone,omitempty"`
+	// OpenID
+	OpenID string `json:"open_id,omitempty"`
+	// UnionID
+	UnionID string `json:"union_id,omitempty"`
+	// SessionKey
+	SessionKey   string `json:"session_key,omitempty"`
+	selectValues sql.SelectValues
+}
+
+// scanValues returns the types for scanning values from sql.Rows.
+func (*WxCardUser) scanValues(columns []string) ([]any, error) {
+	values := make([]any, len(columns))
+	for i := range columns {
+		switch columns[i] {
+		case wxcarduser.FieldID:
+			values[i] = new(sql.NullInt64)
+		case wxcarduser.FieldWxid, wxcarduser.FieldAccount, wxcarduser.FieldAvatar, wxcarduser.FieldNickname, wxcarduser.FieldRemark, wxcarduser.FieldPhone, wxcarduser.FieldOpenID, wxcarduser.FieldUnionID, wxcarduser.FieldSessionKey:
+			values[i] = new(sql.NullString)
+		case wxcarduser.FieldCreatedAt, wxcarduser.FieldUpdatedAt, wxcarduser.FieldDeletedAt:
+			values[i] = new(sql.NullTime)
+		default:
+			values[i] = new(sql.UnknownType)
+		}
+	}
+	return values, nil
+}
+
+// assignValues assigns the values that were returned from sql.Rows (after scanning)
+// to the WxCardUser fields.
+func (wcu *WxCardUser) assignValues(columns []string, values []any) error {
+	if m, n := len(values), len(columns); m < n {
+		return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
+	}
+	for i := range columns {
+		switch columns[i] {
+		case wxcarduser.FieldID:
+			value, ok := values[i].(*sql.NullInt64)
+			if !ok {
+				return fmt.Errorf("unexpected type %T for field id", value)
+			}
+			wcu.ID = uint64(value.Int64)
+		case wxcarduser.FieldCreatedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field created_at", values[i])
+			} else if value.Valid {
+				wcu.CreatedAt = value.Time
+			}
+		case wxcarduser.FieldUpdatedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field updated_at", values[i])
+			} else if value.Valid {
+				wcu.UpdatedAt = value.Time
+			}
+		case wxcarduser.FieldDeletedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field deleted_at", values[i])
+			} else if value.Valid {
+				wcu.DeletedAt = value.Time
+			}
+		case wxcarduser.FieldWxid:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field wxid", values[i])
+			} else if value.Valid {
+				wcu.Wxid = value.String
+			}
+		case wxcarduser.FieldAccount:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field account", values[i])
+			} else if value.Valid {
+				wcu.Account = value.String
+			}
+		case wxcarduser.FieldAvatar:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field avatar", values[i])
+			} else if value.Valid {
+				wcu.Avatar = value.String
+			}
+		case wxcarduser.FieldNickname:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field nickname", values[i])
+			} else if value.Valid {
+				wcu.Nickname = value.String
+			}
+		case wxcarduser.FieldRemark:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field remark", values[i])
+			} else if value.Valid {
+				wcu.Remark = value.String
+			}
+		case wxcarduser.FieldPhone:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field phone", values[i])
+			} else if value.Valid {
+				wcu.Phone = value.String
+			}
+		case wxcarduser.FieldOpenID:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field open_id", values[i])
+			} else if value.Valid {
+				wcu.OpenID = value.String
+			}
+		case wxcarduser.FieldUnionID:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field union_id", values[i])
+			} else if value.Valid {
+				wcu.UnionID = value.String
+			}
+		case wxcarduser.FieldSessionKey:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field session_key", values[i])
+			} else if value.Valid {
+				wcu.SessionKey = value.String
+			}
+		default:
+			wcu.selectValues.Set(columns[i], values[i])
+		}
+	}
+	return nil
+}
+
+// Value returns the ent.Value that was dynamically selected and assigned to the WxCardUser.
+// This includes values selected through modifiers, order, etc.
+func (wcu *WxCardUser) Value(name string) (ent.Value, error) {
+	return wcu.selectValues.Get(name)
+}
+
+// Update returns a builder for updating this WxCardUser.
+// Note that you need to call WxCardUser.Unwrap() before calling this method if this WxCardUser
+// was returned from a transaction, and the transaction was committed or rolled back.
+func (wcu *WxCardUser) Update() *WxCardUserUpdateOne {
+	return NewWxCardUserClient(wcu.config).UpdateOne(wcu)
+}
+
+// Unwrap unwraps the WxCardUser entity that was returned from a transaction after it was closed,
+// so that all future queries will be executed through the driver which created the transaction.
+func (wcu *WxCardUser) Unwrap() *WxCardUser {
+	_tx, ok := wcu.config.driver.(*txDriver)
+	if !ok {
+		panic("ent: WxCardUser is not a transactional entity")
+	}
+	wcu.config.driver = _tx.drv
+	return wcu
+}
+
+// String implements the fmt.Stringer.
+func (wcu *WxCardUser) String() string {
+	var builder strings.Builder
+	builder.WriteString("WxCardUser(")
+	builder.WriteString(fmt.Sprintf("id=%v, ", wcu.ID))
+	builder.WriteString("created_at=")
+	builder.WriteString(wcu.CreatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("updated_at=")
+	builder.WriteString(wcu.UpdatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("deleted_at=")
+	builder.WriteString(wcu.DeletedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("wxid=")
+	builder.WriteString(wcu.Wxid)
+	builder.WriteString(", ")
+	builder.WriteString("account=")
+	builder.WriteString(wcu.Account)
+	builder.WriteString(", ")
+	builder.WriteString("avatar=")
+	builder.WriteString(wcu.Avatar)
+	builder.WriteString(", ")
+	builder.WriteString("nickname=")
+	builder.WriteString(wcu.Nickname)
+	builder.WriteString(", ")
+	builder.WriteString("remark=")
+	builder.WriteString(wcu.Remark)
+	builder.WriteString(", ")
+	builder.WriteString("phone=")
+	builder.WriteString(wcu.Phone)
+	builder.WriteString(", ")
+	builder.WriteString("open_id=")
+	builder.WriteString(wcu.OpenID)
+	builder.WriteString(", ")
+	builder.WriteString("union_id=")
+	builder.WriteString(wcu.UnionID)
+	builder.WriteString(", ")
+	builder.WriteString("session_key=")
+	builder.WriteString(wcu.SessionKey)
+	builder.WriteByte(')')
+	return builder.String()
+}
+
+// WxCardUsers is a parsable slice of WxCardUser.
+type WxCardUsers []*WxCardUser

+ 845 - 0
ent/wxcarduser/where.go

@@ -0,0 +1,845 @@
+// Code generated by ent, DO NOT EDIT.
+
+package wxcarduser
+
+import (
+	"time"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+)
+
+// ID filters vertices based on their ID field.
+func ID(id uint64) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldID, id))
+}
+
+// IDEQ applies the EQ predicate on the ID field.
+func IDEQ(id uint64) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldID, id))
+}
+
+// IDNEQ applies the NEQ predicate on the ID field.
+func IDNEQ(id uint64) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNEQ(FieldID, id))
+}
+
+// IDIn applies the In predicate on the ID field.
+func IDIn(ids ...uint64) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldIn(FieldID, ids...))
+}
+
+// IDNotIn applies the NotIn predicate on the ID field.
+func IDNotIn(ids ...uint64) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNotIn(FieldID, ids...))
+}
+
+// IDGT applies the GT predicate on the ID field.
+func IDGT(id uint64) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGT(FieldID, id))
+}
+
+// IDGTE applies the GTE predicate on the ID field.
+func IDGTE(id uint64) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGTE(FieldID, id))
+}
+
+// IDLT applies the LT predicate on the ID field.
+func IDLT(id uint64) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLT(FieldID, id))
+}
+
+// IDLTE applies the LTE predicate on the ID field.
+func IDLTE(id uint64) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLTE(FieldID, id))
+}
+
+// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
+func CreatedAt(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
+func UpdatedAt(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ.
+func DeletedAt(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// Wxid applies equality check predicate on the "wxid" field. It's identical to WxidEQ.
+func Wxid(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldWxid, v))
+}
+
+// Account applies equality check predicate on the "account" field. It's identical to AccountEQ.
+func Account(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldAccount, v))
+}
+
+// Avatar applies equality check predicate on the "avatar" field. It's identical to AvatarEQ.
+func Avatar(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldAvatar, v))
+}
+
+// Nickname applies equality check predicate on the "nickname" field. It's identical to NicknameEQ.
+func Nickname(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldNickname, v))
+}
+
+// Remark applies equality check predicate on the "remark" field. It's identical to RemarkEQ.
+func Remark(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldRemark, v))
+}
+
+// Phone applies equality check predicate on the "phone" field. It's identical to PhoneEQ.
+func Phone(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldPhone, v))
+}
+
+// OpenID applies equality check predicate on the "open_id" field. It's identical to OpenIDEQ.
+func OpenID(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldOpenID, v))
+}
+
+// UnionID applies equality check predicate on the "union_id" field. It's identical to UnionIDEQ.
+func UnionID(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldUnionID, v))
+}
+
+// SessionKey applies equality check predicate on the "session_key" field. It's identical to SessionKeyEQ.
+func SessionKey(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldSessionKey, v))
+}
+
+// CreatedAtEQ applies the EQ predicate on the "created_at" field.
+func CreatedAtEQ(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
+func CreatedAtNEQ(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtIn applies the In predicate on the "created_at" field.
+func CreatedAtIn(vs ...time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
+func CreatedAtNotIn(vs ...time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNotIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtGT applies the GT predicate on the "created_at" field.
+func CreatedAtGT(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGT(FieldCreatedAt, v))
+}
+
+// CreatedAtGTE applies the GTE predicate on the "created_at" field.
+func CreatedAtGTE(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGTE(FieldCreatedAt, v))
+}
+
+// CreatedAtLT applies the LT predicate on the "created_at" field.
+func CreatedAtLT(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLT(FieldCreatedAt, v))
+}
+
+// CreatedAtLTE applies the LTE predicate on the "created_at" field.
+func CreatedAtLTE(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLTE(FieldCreatedAt, v))
+}
+
+// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
+func UpdatedAtEQ(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
+func UpdatedAtNEQ(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtIn applies the In predicate on the "updated_at" field.
+func UpdatedAtIn(vs ...time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
+func UpdatedAtNotIn(vs ...time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNotIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtGT applies the GT predicate on the "updated_at" field.
+func UpdatedAtGT(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
+func UpdatedAtGTE(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGTE(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLT applies the LT predicate on the "updated_at" field.
+func UpdatedAtLT(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
+func UpdatedAtLTE(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLTE(FieldUpdatedAt, v))
+}
+
+// DeletedAtEQ applies the EQ predicate on the "deleted_at" field.
+func DeletedAtEQ(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field.
+func DeletedAtNEQ(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtIn applies the In predicate on the "deleted_at" field.
+func DeletedAtIn(vs ...time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field.
+func DeletedAtNotIn(vs ...time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNotIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtGT applies the GT predicate on the "deleted_at" field.
+func DeletedAtGT(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGT(FieldDeletedAt, v))
+}
+
+// DeletedAtGTE applies the GTE predicate on the "deleted_at" field.
+func DeletedAtGTE(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGTE(FieldDeletedAt, v))
+}
+
+// DeletedAtLT applies the LT predicate on the "deleted_at" field.
+func DeletedAtLT(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLT(FieldDeletedAt, v))
+}
+
+// DeletedAtLTE applies the LTE predicate on the "deleted_at" field.
+func DeletedAtLTE(v time.Time) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLTE(FieldDeletedAt, v))
+}
+
+// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field.
+func DeletedAtIsNil() predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldIsNull(FieldDeletedAt))
+}
+
+// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field.
+func DeletedAtNotNil() predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNotNull(FieldDeletedAt))
+}
+
+// WxidEQ applies the EQ predicate on the "wxid" field.
+func WxidEQ(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldWxid, v))
+}
+
+// WxidNEQ applies the NEQ predicate on the "wxid" field.
+func WxidNEQ(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNEQ(FieldWxid, v))
+}
+
+// WxidIn applies the In predicate on the "wxid" field.
+func WxidIn(vs ...string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldIn(FieldWxid, vs...))
+}
+
+// WxidNotIn applies the NotIn predicate on the "wxid" field.
+func WxidNotIn(vs ...string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNotIn(FieldWxid, vs...))
+}
+
+// WxidGT applies the GT predicate on the "wxid" field.
+func WxidGT(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGT(FieldWxid, v))
+}
+
+// WxidGTE applies the GTE predicate on the "wxid" field.
+func WxidGTE(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGTE(FieldWxid, v))
+}
+
+// WxidLT applies the LT predicate on the "wxid" field.
+func WxidLT(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLT(FieldWxid, v))
+}
+
+// WxidLTE applies the LTE predicate on the "wxid" field.
+func WxidLTE(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLTE(FieldWxid, v))
+}
+
+// WxidContains applies the Contains predicate on the "wxid" field.
+func WxidContains(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldContains(FieldWxid, v))
+}
+
+// WxidHasPrefix applies the HasPrefix predicate on the "wxid" field.
+func WxidHasPrefix(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldHasPrefix(FieldWxid, v))
+}
+
+// WxidHasSuffix applies the HasSuffix predicate on the "wxid" field.
+func WxidHasSuffix(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldHasSuffix(FieldWxid, v))
+}
+
+// WxidEqualFold applies the EqualFold predicate on the "wxid" field.
+func WxidEqualFold(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEqualFold(FieldWxid, v))
+}
+
+// WxidContainsFold applies the ContainsFold predicate on the "wxid" field.
+func WxidContainsFold(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldContainsFold(FieldWxid, v))
+}
+
+// AccountEQ applies the EQ predicate on the "account" field.
+func AccountEQ(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldAccount, v))
+}
+
+// AccountNEQ applies the NEQ predicate on the "account" field.
+func AccountNEQ(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNEQ(FieldAccount, v))
+}
+
+// AccountIn applies the In predicate on the "account" field.
+func AccountIn(vs ...string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldIn(FieldAccount, vs...))
+}
+
+// AccountNotIn applies the NotIn predicate on the "account" field.
+func AccountNotIn(vs ...string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNotIn(FieldAccount, vs...))
+}
+
+// AccountGT applies the GT predicate on the "account" field.
+func AccountGT(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGT(FieldAccount, v))
+}
+
+// AccountGTE applies the GTE predicate on the "account" field.
+func AccountGTE(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGTE(FieldAccount, v))
+}
+
+// AccountLT applies the LT predicate on the "account" field.
+func AccountLT(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLT(FieldAccount, v))
+}
+
+// AccountLTE applies the LTE predicate on the "account" field.
+func AccountLTE(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLTE(FieldAccount, v))
+}
+
+// AccountContains applies the Contains predicate on the "account" field.
+func AccountContains(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldContains(FieldAccount, v))
+}
+
+// AccountHasPrefix applies the HasPrefix predicate on the "account" field.
+func AccountHasPrefix(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldHasPrefix(FieldAccount, v))
+}
+
+// AccountHasSuffix applies the HasSuffix predicate on the "account" field.
+func AccountHasSuffix(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldHasSuffix(FieldAccount, v))
+}
+
+// AccountEqualFold applies the EqualFold predicate on the "account" field.
+func AccountEqualFold(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEqualFold(FieldAccount, v))
+}
+
+// AccountContainsFold applies the ContainsFold predicate on the "account" field.
+func AccountContainsFold(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldContainsFold(FieldAccount, v))
+}
+
+// AvatarEQ applies the EQ predicate on the "avatar" field.
+func AvatarEQ(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldAvatar, v))
+}
+
+// AvatarNEQ applies the NEQ predicate on the "avatar" field.
+func AvatarNEQ(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNEQ(FieldAvatar, v))
+}
+
+// AvatarIn applies the In predicate on the "avatar" field.
+func AvatarIn(vs ...string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldIn(FieldAvatar, vs...))
+}
+
+// AvatarNotIn applies the NotIn predicate on the "avatar" field.
+func AvatarNotIn(vs ...string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNotIn(FieldAvatar, vs...))
+}
+
+// AvatarGT applies the GT predicate on the "avatar" field.
+func AvatarGT(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGT(FieldAvatar, v))
+}
+
+// AvatarGTE applies the GTE predicate on the "avatar" field.
+func AvatarGTE(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGTE(FieldAvatar, v))
+}
+
+// AvatarLT applies the LT predicate on the "avatar" field.
+func AvatarLT(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLT(FieldAvatar, v))
+}
+
+// AvatarLTE applies the LTE predicate on the "avatar" field.
+func AvatarLTE(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLTE(FieldAvatar, v))
+}
+
+// AvatarContains applies the Contains predicate on the "avatar" field.
+func AvatarContains(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldContains(FieldAvatar, v))
+}
+
+// AvatarHasPrefix applies the HasPrefix predicate on the "avatar" field.
+func AvatarHasPrefix(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldHasPrefix(FieldAvatar, v))
+}
+
+// AvatarHasSuffix applies the HasSuffix predicate on the "avatar" field.
+func AvatarHasSuffix(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldHasSuffix(FieldAvatar, v))
+}
+
+// AvatarEqualFold applies the EqualFold predicate on the "avatar" field.
+func AvatarEqualFold(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEqualFold(FieldAvatar, v))
+}
+
+// AvatarContainsFold applies the ContainsFold predicate on the "avatar" field.
+func AvatarContainsFold(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldContainsFold(FieldAvatar, v))
+}
+
+// NicknameEQ applies the EQ predicate on the "nickname" field.
+func NicknameEQ(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldNickname, v))
+}
+
+// NicknameNEQ applies the NEQ predicate on the "nickname" field.
+func NicknameNEQ(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNEQ(FieldNickname, v))
+}
+
+// NicknameIn applies the In predicate on the "nickname" field.
+func NicknameIn(vs ...string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldIn(FieldNickname, vs...))
+}
+
+// NicknameNotIn applies the NotIn predicate on the "nickname" field.
+func NicknameNotIn(vs ...string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNotIn(FieldNickname, vs...))
+}
+
+// NicknameGT applies the GT predicate on the "nickname" field.
+func NicknameGT(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGT(FieldNickname, v))
+}
+
+// NicknameGTE applies the GTE predicate on the "nickname" field.
+func NicknameGTE(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGTE(FieldNickname, v))
+}
+
+// NicknameLT applies the LT predicate on the "nickname" field.
+func NicknameLT(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLT(FieldNickname, v))
+}
+
+// NicknameLTE applies the LTE predicate on the "nickname" field.
+func NicknameLTE(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLTE(FieldNickname, v))
+}
+
+// NicknameContains applies the Contains predicate on the "nickname" field.
+func NicknameContains(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldContains(FieldNickname, v))
+}
+
+// NicknameHasPrefix applies the HasPrefix predicate on the "nickname" field.
+func NicknameHasPrefix(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldHasPrefix(FieldNickname, v))
+}
+
+// NicknameHasSuffix applies the HasSuffix predicate on the "nickname" field.
+func NicknameHasSuffix(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldHasSuffix(FieldNickname, v))
+}
+
+// NicknameEqualFold applies the EqualFold predicate on the "nickname" field.
+func NicknameEqualFold(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEqualFold(FieldNickname, v))
+}
+
+// NicknameContainsFold applies the ContainsFold predicate on the "nickname" field.
+func NicknameContainsFold(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldContainsFold(FieldNickname, v))
+}
+
+// RemarkEQ applies the EQ predicate on the "remark" field.
+func RemarkEQ(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldRemark, v))
+}
+
+// RemarkNEQ applies the NEQ predicate on the "remark" field.
+func RemarkNEQ(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNEQ(FieldRemark, v))
+}
+
+// RemarkIn applies the In predicate on the "remark" field.
+func RemarkIn(vs ...string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldIn(FieldRemark, vs...))
+}
+
+// RemarkNotIn applies the NotIn predicate on the "remark" field.
+func RemarkNotIn(vs ...string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNotIn(FieldRemark, vs...))
+}
+
+// RemarkGT applies the GT predicate on the "remark" field.
+func RemarkGT(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGT(FieldRemark, v))
+}
+
+// RemarkGTE applies the GTE predicate on the "remark" field.
+func RemarkGTE(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGTE(FieldRemark, v))
+}
+
+// RemarkLT applies the LT predicate on the "remark" field.
+func RemarkLT(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLT(FieldRemark, v))
+}
+
+// RemarkLTE applies the LTE predicate on the "remark" field.
+func RemarkLTE(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLTE(FieldRemark, v))
+}
+
+// RemarkContains applies the Contains predicate on the "remark" field.
+func RemarkContains(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldContains(FieldRemark, v))
+}
+
+// RemarkHasPrefix applies the HasPrefix predicate on the "remark" field.
+func RemarkHasPrefix(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldHasPrefix(FieldRemark, v))
+}
+
+// RemarkHasSuffix applies the HasSuffix predicate on the "remark" field.
+func RemarkHasSuffix(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldHasSuffix(FieldRemark, v))
+}
+
+// RemarkEqualFold applies the EqualFold predicate on the "remark" field.
+func RemarkEqualFold(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEqualFold(FieldRemark, v))
+}
+
+// RemarkContainsFold applies the ContainsFold predicate on the "remark" field.
+func RemarkContainsFold(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldContainsFold(FieldRemark, v))
+}
+
+// PhoneEQ applies the EQ predicate on the "phone" field.
+func PhoneEQ(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldPhone, v))
+}
+
+// PhoneNEQ applies the NEQ predicate on the "phone" field.
+func PhoneNEQ(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNEQ(FieldPhone, v))
+}
+
+// PhoneIn applies the In predicate on the "phone" field.
+func PhoneIn(vs ...string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldIn(FieldPhone, vs...))
+}
+
+// PhoneNotIn applies the NotIn predicate on the "phone" field.
+func PhoneNotIn(vs ...string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNotIn(FieldPhone, vs...))
+}
+
+// PhoneGT applies the GT predicate on the "phone" field.
+func PhoneGT(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGT(FieldPhone, v))
+}
+
+// PhoneGTE applies the GTE predicate on the "phone" field.
+func PhoneGTE(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGTE(FieldPhone, v))
+}
+
+// PhoneLT applies the LT predicate on the "phone" field.
+func PhoneLT(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLT(FieldPhone, v))
+}
+
+// PhoneLTE applies the LTE predicate on the "phone" field.
+func PhoneLTE(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLTE(FieldPhone, v))
+}
+
+// PhoneContains applies the Contains predicate on the "phone" field.
+func PhoneContains(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldContains(FieldPhone, v))
+}
+
+// PhoneHasPrefix applies the HasPrefix predicate on the "phone" field.
+func PhoneHasPrefix(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldHasPrefix(FieldPhone, v))
+}
+
+// PhoneHasSuffix applies the HasSuffix predicate on the "phone" field.
+func PhoneHasSuffix(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldHasSuffix(FieldPhone, v))
+}
+
+// PhoneEqualFold applies the EqualFold predicate on the "phone" field.
+func PhoneEqualFold(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEqualFold(FieldPhone, v))
+}
+
+// PhoneContainsFold applies the ContainsFold predicate on the "phone" field.
+func PhoneContainsFold(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldContainsFold(FieldPhone, v))
+}
+
+// OpenIDEQ applies the EQ predicate on the "open_id" field.
+func OpenIDEQ(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldOpenID, v))
+}
+
+// OpenIDNEQ applies the NEQ predicate on the "open_id" field.
+func OpenIDNEQ(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNEQ(FieldOpenID, v))
+}
+
+// OpenIDIn applies the In predicate on the "open_id" field.
+func OpenIDIn(vs ...string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldIn(FieldOpenID, vs...))
+}
+
+// OpenIDNotIn applies the NotIn predicate on the "open_id" field.
+func OpenIDNotIn(vs ...string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNotIn(FieldOpenID, vs...))
+}
+
+// OpenIDGT applies the GT predicate on the "open_id" field.
+func OpenIDGT(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGT(FieldOpenID, v))
+}
+
+// OpenIDGTE applies the GTE predicate on the "open_id" field.
+func OpenIDGTE(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGTE(FieldOpenID, v))
+}
+
+// OpenIDLT applies the LT predicate on the "open_id" field.
+func OpenIDLT(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLT(FieldOpenID, v))
+}
+
+// OpenIDLTE applies the LTE predicate on the "open_id" field.
+func OpenIDLTE(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLTE(FieldOpenID, v))
+}
+
+// OpenIDContains applies the Contains predicate on the "open_id" field.
+func OpenIDContains(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldContains(FieldOpenID, v))
+}
+
+// OpenIDHasPrefix applies the HasPrefix predicate on the "open_id" field.
+func OpenIDHasPrefix(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldHasPrefix(FieldOpenID, v))
+}
+
+// OpenIDHasSuffix applies the HasSuffix predicate on the "open_id" field.
+func OpenIDHasSuffix(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldHasSuffix(FieldOpenID, v))
+}
+
+// OpenIDEqualFold applies the EqualFold predicate on the "open_id" field.
+func OpenIDEqualFold(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEqualFold(FieldOpenID, v))
+}
+
+// OpenIDContainsFold applies the ContainsFold predicate on the "open_id" field.
+func OpenIDContainsFold(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldContainsFold(FieldOpenID, v))
+}
+
+// UnionIDEQ applies the EQ predicate on the "union_id" field.
+func UnionIDEQ(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldUnionID, v))
+}
+
+// UnionIDNEQ applies the NEQ predicate on the "union_id" field.
+func UnionIDNEQ(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNEQ(FieldUnionID, v))
+}
+
+// UnionIDIn applies the In predicate on the "union_id" field.
+func UnionIDIn(vs ...string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldIn(FieldUnionID, vs...))
+}
+
+// UnionIDNotIn applies the NotIn predicate on the "union_id" field.
+func UnionIDNotIn(vs ...string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNotIn(FieldUnionID, vs...))
+}
+
+// UnionIDGT applies the GT predicate on the "union_id" field.
+func UnionIDGT(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGT(FieldUnionID, v))
+}
+
+// UnionIDGTE applies the GTE predicate on the "union_id" field.
+func UnionIDGTE(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGTE(FieldUnionID, v))
+}
+
+// UnionIDLT applies the LT predicate on the "union_id" field.
+func UnionIDLT(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLT(FieldUnionID, v))
+}
+
+// UnionIDLTE applies the LTE predicate on the "union_id" field.
+func UnionIDLTE(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLTE(FieldUnionID, v))
+}
+
+// UnionIDContains applies the Contains predicate on the "union_id" field.
+func UnionIDContains(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldContains(FieldUnionID, v))
+}
+
+// UnionIDHasPrefix applies the HasPrefix predicate on the "union_id" field.
+func UnionIDHasPrefix(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldHasPrefix(FieldUnionID, v))
+}
+
+// UnionIDHasSuffix applies the HasSuffix predicate on the "union_id" field.
+func UnionIDHasSuffix(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldHasSuffix(FieldUnionID, v))
+}
+
+// UnionIDEqualFold applies the EqualFold predicate on the "union_id" field.
+func UnionIDEqualFold(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEqualFold(FieldUnionID, v))
+}
+
+// UnionIDContainsFold applies the ContainsFold predicate on the "union_id" field.
+func UnionIDContainsFold(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldContainsFold(FieldUnionID, v))
+}
+
+// SessionKeyEQ applies the EQ predicate on the "session_key" field.
+func SessionKeyEQ(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEQ(FieldSessionKey, v))
+}
+
+// SessionKeyNEQ applies the NEQ predicate on the "session_key" field.
+func SessionKeyNEQ(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNEQ(FieldSessionKey, v))
+}
+
+// SessionKeyIn applies the In predicate on the "session_key" field.
+func SessionKeyIn(vs ...string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldIn(FieldSessionKey, vs...))
+}
+
+// SessionKeyNotIn applies the NotIn predicate on the "session_key" field.
+func SessionKeyNotIn(vs ...string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldNotIn(FieldSessionKey, vs...))
+}
+
+// SessionKeyGT applies the GT predicate on the "session_key" field.
+func SessionKeyGT(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGT(FieldSessionKey, v))
+}
+
+// SessionKeyGTE applies the GTE predicate on the "session_key" field.
+func SessionKeyGTE(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldGTE(FieldSessionKey, v))
+}
+
+// SessionKeyLT applies the LT predicate on the "session_key" field.
+func SessionKeyLT(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLT(FieldSessionKey, v))
+}
+
+// SessionKeyLTE applies the LTE predicate on the "session_key" field.
+func SessionKeyLTE(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldLTE(FieldSessionKey, v))
+}
+
+// SessionKeyContains applies the Contains predicate on the "session_key" field.
+func SessionKeyContains(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldContains(FieldSessionKey, v))
+}
+
+// SessionKeyHasPrefix applies the HasPrefix predicate on the "session_key" field.
+func SessionKeyHasPrefix(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldHasPrefix(FieldSessionKey, v))
+}
+
+// SessionKeyHasSuffix applies the HasSuffix predicate on the "session_key" field.
+func SessionKeyHasSuffix(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldHasSuffix(FieldSessionKey, v))
+}
+
+// SessionKeyEqualFold applies the EqualFold predicate on the "session_key" field.
+func SessionKeyEqualFold(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldEqualFold(FieldSessionKey, v))
+}
+
+// SessionKeyContainsFold applies the ContainsFold predicate on the "session_key" field.
+func SessionKeyContainsFold(v string) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.FieldContainsFold(FieldSessionKey, v))
+}
+
+// And groups predicates with the AND operator between them.
+func And(predicates ...predicate.WxCardUser) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.AndPredicates(predicates...))
+}
+
+// Or groups predicates with the OR operator between them.
+func Or(predicates ...predicate.WxCardUser) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.OrPredicates(predicates...))
+}
+
+// Not applies the not operator on the given predicate.
+func Not(p predicate.WxCardUser) predicate.WxCardUser {
+	return predicate.WxCardUser(sql.NotPredicates(p))
+}

+ 172 - 0
ent/wxcarduser/wxcarduser.go

@@ -0,0 +1,172 @@
+// Code generated by ent, DO NOT EDIT.
+
+package wxcarduser
+
+import (
+	"time"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+)
+
+const (
+	// Label holds the string label denoting the wxcarduser type in the database.
+	Label = "wx_card_user"
+	// FieldID holds the string denoting the id field in the database.
+	FieldID = "id"
+	// FieldCreatedAt holds the string denoting the created_at field in the database.
+	FieldCreatedAt = "created_at"
+	// FieldUpdatedAt holds the string denoting the updated_at field in the database.
+	FieldUpdatedAt = "updated_at"
+	// FieldDeletedAt holds the string denoting the deleted_at field in the database.
+	FieldDeletedAt = "deleted_at"
+	// FieldWxid holds the string denoting the wxid field in the database.
+	FieldWxid = "wxid"
+	// FieldAccount holds the string denoting the account field in the database.
+	FieldAccount = "account"
+	// FieldAvatar holds the string denoting the avatar field in the database.
+	FieldAvatar = "avatar"
+	// FieldNickname holds the string denoting the nickname field in the database.
+	FieldNickname = "nickname"
+	// FieldRemark holds the string denoting the remark field in the database.
+	FieldRemark = "remark"
+	// FieldPhone holds the string denoting the phone field in the database.
+	FieldPhone = "phone"
+	// FieldOpenID holds the string denoting the open_id field in the database.
+	FieldOpenID = "open_id"
+	// FieldUnionID holds the string denoting the union_id field in the database.
+	FieldUnionID = "union_id"
+	// FieldSessionKey holds the string denoting the session_key field in the database.
+	FieldSessionKey = "session_key"
+	// Table holds the table name of the wxcarduser in the database.
+	Table = "wx_card_user"
+)
+
+// Columns holds all SQL columns for wxcarduser fields.
+var Columns = []string{
+	FieldID,
+	FieldCreatedAt,
+	FieldUpdatedAt,
+	FieldDeletedAt,
+	FieldWxid,
+	FieldAccount,
+	FieldAvatar,
+	FieldNickname,
+	FieldRemark,
+	FieldPhone,
+	FieldOpenID,
+	FieldUnionID,
+	FieldSessionKey,
+}
+
+// ValidColumn reports if the column name is valid (part of the table columns).
+func ValidColumn(column string) bool {
+	for i := range Columns {
+		if column == Columns[i] {
+			return true
+		}
+	}
+	return false
+}
+
+// Note that the variables below are initialized by the runtime
+// package on the initialization of the application. Therefore,
+// it should be imported in the main as follows:
+//
+//	import _ "wechat-api/ent/runtime"
+var (
+	Hooks        [1]ent.Hook
+	Interceptors [1]ent.Interceptor
+	// DefaultCreatedAt holds the default value on creation for the "created_at" field.
+	DefaultCreatedAt func() time.Time
+	// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
+	DefaultUpdatedAt func() time.Time
+	// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
+	UpdateDefaultUpdatedAt func() time.Time
+	// DefaultWxid holds the default value on creation for the "wxid" field.
+	DefaultWxid string
+	// DefaultAccount holds the default value on creation for the "account" field.
+	DefaultAccount string
+	// DefaultAvatar holds the default value on creation for the "avatar" field.
+	DefaultAvatar string
+	// DefaultNickname holds the default value on creation for the "nickname" field.
+	DefaultNickname string
+	// DefaultRemark holds the default value on creation for the "remark" field.
+	DefaultRemark string
+	// DefaultPhone holds the default value on creation for the "phone" field.
+	DefaultPhone string
+	// DefaultOpenID holds the default value on creation for the "open_id" field.
+	DefaultOpenID string
+	// DefaultUnionID holds the default value on creation for the "union_id" field.
+	DefaultUnionID string
+	// DefaultSessionKey holds the default value on creation for the "session_key" field.
+	DefaultSessionKey string
+)
+
+// OrderOption defines the ordering options for the WxCardUser queries.
+type OrderOption func(*sql.Selector)
+
+// ByID orders the results by the id field.
+func ByID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldID, opts...).ToFunc()
+}
+
+// ByCreatedAt orders the results by the created_at field.
+func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
+}
+
+// ByUpdatedAt orders the results by the updated_at field.
+func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
+}
+
+// ByDeletedAt orders the results by the deleted_at field.
+func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldDeletedAt, opts...).ToFunc()
+}
+
+// ByWxid orders the results by the wxid field.
+func ByWxid(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldWxid, opts...).ToFunc()
+}
+
+// ByAccount orders the results by the account field.
+func ByAccount(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldAccount, opts...).ToFunc()
+}
+
+// ByAvatar orders the results by the avatar field.
+func ByAvatar(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldAvatar, opts...).ToFunc()
+}
+
+// ByNickname orders the results by the nickname field.
+func ByNickname(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldNickname, opts...).ToFunc()
+}
+
+// ByRemark orders the results by the remark field.
+func ByRemark(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldRemark, opts...).ToFunc()
+}
+
+// ByPhone orders the results by the phone field.
+func ByPhone(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldPhone, opts...).ToFunc()
+}
+
+// ByOpenID orders the results by the open_id field.
+func ByOpenID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldOpenID, opts...).ToFunc()
+}
+
+// ByUnionID orders the results by the union_id field.
+func ByUnionID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldUnionID, opts...).ToFunc()
+}
+
+// BySessionKey orders the results by the session_key field.
+func BySessionKey(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldSessionKey, opts...).ToFunc()
+}

+ 1206 - 0
ent/wxcarduser_create.go

@@ -0,0 +1,1206 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/wxcarduser"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// WxCardUserCreate is the builder for creating a WxCardUser entity.
+type WxCardUserCreate struct {
+	config
+	mutation *WxCardUserMutation
+	hooks    []Hook
+	conflict []sql.ConflictOption
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (wcuc *WxCardUserCreate) SetCreatedAt(t time.Time) *WxCardUserCreate {
+	wcuc.mutation.SetCreatedAt(t)
+	return wcuc
+}
+
+// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
+func (wcuc *WxCardUserCreate) SetNillableCreatedAt(t *time.Time) *WxCardUserCreate {
+	if t != nil {
+		wcuc.SetCreatedAt(*t)
+	}
+	return wcuc
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (wcuc *WxCardUserCreate) SetUpdatedAt(t time.Time) *WxCardUserCreate {
+	wcuc.mutation.SetUpdatedAt(t)
+	return wcuc
+}
+
+// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
+func (wcuc *WxCardUserCreate) SetNillableUpdatedAt(t *time.Time) *WxCardUserCreate {
+	if t != nil {
+		wcuc.SetUpdatedAt(*t)
+	}
+	return wcuc
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (wcuc *WxCardUserCreate) SetDeletedAt(t time.Time) *WxCardUserCreate {
+	wcuc.mutation.SetDeletedAt(t)
+	return wcuc
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (wcuc *WxCardUserCreate) SetNillableDeletedAt(t *time.Time) *WxCardUserCreate {
+	if t != nil {
+		wcuc.SetDeletedAt(*t)
+	}
+	return wcuc
+}
+
+// SetWxid sets the "wxid" field.
+func (wcuc *WxCardUserCreate) SetWxid(s string) *WxCardUserCreate {
+	wcuc.mutation.SetWxid(s)
+	return wcuc
+}
+
+// SetNillableWxid sets the "wxid" field if the given value is not nil.
+func (wcuc *WxCardUserCreate) SetNillableWxid(s *string) *WxCardUserCreate {
+	if s != nil {
+		wcuc.SetWxid(*s)
+	}
+	return wcuc
+}
+
+// SetAccount sets the "account" field.
+func (wcuc *WxCardUserCreate) SetAccount(s string) *WxCardUserCreate {
+	wcuc.mutation.SetAccount(s)
+	return wcuc
+}
+
+// SetNillableAccount sets the "account" field if the given value is not nil.
+func (wcuc *WxCardUserCreate) SetNillableAccount(s *string) *WxCardUserCreate {
+	if s != nil {
+		wcuc.SetAccount(*s)
+	}
+	return wcuc
+}
+
+// SetAvatar sets the "avatar" field.
+func (wcuc *WxCardUserCreate) SetAvatar(s string) *WxCardUserCreate {
+	wcuc.mutation.SetAvatar(s)
+	return wcuc
+}
+
+// SetNillableAvatar sets the "avatar" field if the given value is not nil.
+func (wcuc *WxCardUserCreate) SetNillableAvatar(s *string) *WxCardUserCreate {
+	if s != nil {
+		wcuc.SetAvatar(*s)
+	}
+	return wcuc
+}
+
+// SetNickname sets the "nickname" field.
+func (wcuc *WxCardUserCreate) SetNickname(s string) *WxCardUserCreate {
+	wcuc.mutation.SetNickname(s)
+	return wcuc
+}
+
+// SetNillableNickname sets the "nickname" field if the given value is not nil.
+func (wcuc *WxCardUserCreate) SetNillableNickname(s *string) *WxCardUserCreate {
+	if s != nil {
+		wcuc.SetNickname(*s)
+	}
+	return wcuc
+}
+
+// SetRemark sets the "remark" field.
+func (wcuc *WxCardUserCreate) SetRemark(s string) *WxCardUserCreate {
+	wcuc.mutation.SetRemark(s)
+	return wcuc
+}
+
+// SetNillableRemark sets the "remark" field if the given value is not nil.
+func (wcuc *WxCardUserCreate) SetNillableRemark(s *string) *WxCardUserCreate {
+	if s != nil {
+		wcuc.SetRemark(*s)
+	}
+	return wcuc
+}
+
+// SetPhone sets the "phone" field.
+func (wcuc *WxCardUserCreate) SetPhone(s string) *WxCardUserCreate {
+	wcuc.mutation.SetPhone(s)
+	return wcuc
+}
+
+// SetNillablePhone sets the "phone" field if the given value is not nil.
+func (wcuc *WxCardUserCreate) SetNillablePhone(s *string) *WxCardUserCreate {
+	if s != nil {
+		wcuc.SetPhone(*s)
+	}
+	return wcuc
+}
+
+// SetOpenID sets the "open_id" field.
+func (wcuc *WxCardUserCreate) SetOpenID(s string) *WxCardUserCreate {
+	wcuc.mutation.SetOpenID(s)
+	return wcuc
+}
+
+// SetNillableOpenID sets the "open_id" field if the given value is not nil.
+func (wcuc *WxCardUserCreate) SetNillableOpenID(s *string) *WxCardUserCreate {
+	if s != nil {
+		wcuc.SetOpenID(*s)
+	}
+	return wcuc
+}
+
+// SetUnionID sets the "union_id" field.
+func (wcuc *WxCardUserCreate) SetUnionID(s string) *WxCardUserCreate {
+	wcuc.mutation.SetUnionID(s)
+	return wcuc
+}
+
+// SetNillableUnionID sets the "union_id" field if the given value is not nil.
+func (wcuc *WxCardUserCreate) SetNillableUnionID(s *string) *WxCardUserCreate {
+	if s != nil {
+		wcuc.SetUnionID(*s)
+	}
+	return wcuc
+}
+
+// SetSessionKey sets the "session_key" field.
+func (wcuc *WxCardUserCreate) SetSessionKey(s string) *WxCardUserCreate {
+	wcuc.mutation.SetSessionKey(s)
+	return wcuc
+}
+
+// SetNillableSessionKey sets the "session_key" field if the given value is not nil.
+func (wcuc *WxCardUserCreate) SetNillableSessionKey(s *string) *WxCardUserCreate {
+	if s != nil {
+		wcuc.SetSessionKey(*s)
+	}
+	return wcuc
+}
+
+// SetID sets the "id" field.
+func (wcuc *WxCardUserCreate) SetID(u uint64) *WxCardUserCreate {
+	wcuc.mutation.SetID(u)
+	return wcuc
+}
+
+// Mutation returns the WxCardUserMutation object of the builder.
+func (wcuc *WxCardUserCreate) Mutation() *WxCardUserMutation {
+	return wcuc.mutation
+}
+
+// Save creates the WxCardUser in the database.
+func (wcuc *WxCardUserCreate) Save(ctx context.Context) (*WxCardUser, error) {
+	if err := wcuc.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, wcuc.sqlSave, wcuc.mutation, wcuc.hooks)
+}
+
+// SaveX calls Save and panics if Save returns an error.
+func (wcuc *WxCardUserCreate) SaveX(ctx context.Context) *WxCardUser {
+	v, err := wcuc.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (wcuc *WxCardUserCreate) Exec(ctx context.Context) error {
+	_, err := wcuc.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (wcuc *WxCardUserCreate) ExecX(ctx context.Context) {
+	if err := wcuc.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (wcuc *WxCardUserCreate) defaults() error {
+	if _, ok := wcuc.mutation.CreatedAt(); !ok {
+		if wxcarduser.DefaultCreatedAt == nil {
+			return fmt.Errorf("ent: uninitialized wxcarduser.DefaultCreatedAt (forgotten import ent/runtime?)")
+		}
+		v := wxcarduser.DefaultCreatedAt()
+		wcuc.mutation.SetCreatedAt(v)
+	}
+	if _, ok := wcuc.mutation.UpdatedAt(); !ok {
+		if wxcarduser.DefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized wxcarduser.DefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := wxcarduser.DefaultUpdatedAt()
+		wcuc.mutation.SetUpdatedAt(v)
+	}
+	if _, ok := wcuc.mutation.Wxid(); !ok {
+		v := wxcarduser.DefaultWxid
+		wcuc.mutation.SetWxid(v)
+	}
+	if _, ok := wcuc.mutation.Account(); !ok {
+		v := wxcarduser.DefaultAccount
+		wcuc.mutation.SetAccount(v)
+	}
+	if _, ok := wcuc.mutation.Avatar(); !ok {
+		v := wxcarduser.DefaultAvatar
+		wcuc.mutation.SetAvatar(v)
+	}
+	if _, ok := wcuc.mutation.Nickname(); !ok {
+		v := wxcarduser.DefaultNickname
+		wcuc.mutation.SetNickname(v)
+	}
+	if _, ok := wcuc.mutation.Remark(); !ok {
+		v := wxcarduser.DefaultRemark
+		wcuc.mutation.SetRemark(v)
+	}
+	if _, ok := wcuc.mutation.Phone(); !ok {
+		v := wxcarduser.DefaultPhone
+		wcuc.mutation.SetPhone(v)
+	}
+	if _, ok := wcuc.mutation.OpenID(); !ok {
+		v := wxcarduser.DefaultOpenID
+		wcuc.mutation.SetOpenID(v)
+	}
+	if _, ok := wcuc.mutation.UnionID(); !ok {
+		v := wxcarduser.DefaultUnionID
+		wcuc.mutation.SetUnionID(v)
+	}
+	if _, ok := wcuc.mutation.SessionKey(); !ok {
+		v := wxcarduser.DefaultSessionKey
+		wcuc.mutation.SetSessionKey(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (wcuc *WxCardUserCreate) check() error {
+	if _, ok := wcuc.mutation.CreatedAt(); !ok {
+		return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "WxCardUser.created_at"`)}
+	}
+	if _, ok := wcuc.mutation.UpdatedAt(); !ok {
+		return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "WxCardUser.updated_at"`)}
+	}
+	if _, ok := wcuc.mutation.Wxid(); !ok {
+		return &ValidationError{Name: "wxid", err: errors.New(`ent: missing required field "WxCardUser.wxid"`)}
+	}
+	if _, ok := wcuc.mutation.Account(); !ok {
+		return &ValidationError{Name: "account", err: errors.New(`ent: missing required field "WxCardUser.account"`)}
+	}
+	if _, ok := wcuc.mutation.Avatar(); !ok {
+		return &ValidationError{Name: "avatar", err: errors.New(`ent: missing required field "WxCardUser.avatar"`)}
+	}
+	if _, ok := wcuc.mutation.Nickname(); !ok {
+		return &ValidationError{Name: "nickname", err: errors.New(`ent: missing required field "WxCardUser.nickname"`)}
+	}
+	if _, ok := wcuc.mutation.Remark(); !ok {
+		return &ValidationError{Name: "remark", err: errors.New(`ent: missing required field "WxCardUser.remark"`)}
+	}
+	if _, ok := wcuc.mutation.Phone(); !ok {
+		return &ValidationError{Name: "phone", err: errors.New(`ent: missing required field "WxCardUser.phone"`)}
+	}
+	if _, ok := wcuc.mutation.OpenID(); !ok {
+		return &ValidationError{Name: "open_id", err: errors.New(`ent: missing required field "WxCardUser.open_id"`)}
+	}
+	if _, ok := wcuc.mutation.UnionID(); !ok {
+		return &ValidationError{Name: "union_id", err: errors.New(`ent: missing required field "WxCardUser.union_id"`)}
+	}
+	if _, ok := wcuc.mutation.SessionKey(); !ok {
+		return &ValidationError{Name: "session_key", err: errors.New(`ent: missing required field "WxCardUser.session_key"`)}
+	}
+	return nil
+}
+
+func (wcuc *WxCardUserCreate) sqlSave(ctx context.Context) (*WxCardUser, error) {
+	if err := wcuc.check(); err != nil {
+		return nil, err
+	}
+	_node, _spec := wcuc.createSpec()
+	if err := sqlgraph.CreateNode(ctx, wcuc.driver, _spec); err != nil {
+		if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	if _spec.ID.Value != _node.ID {
+		id := _spec.ID.Value.(int64)
+		_node.ID = uint64(id)
+	}
+	wcuc.mutation.id = &_node.ID
+	wcuc.mutation.done = true
+	return _node, nil
+}
+
+func (wcuc *WxCardUserCreate) createSpec() (*WxCardUser, *sqlgraph.CreateSpec) {
+	var (
+		_node = &WxCardUser{config: wcuc.config}
+		_spec = sqlgraph.NewCreateSpec(wxcarduser.Table, sqlgraph.NewFieldSpec(wxcarduser.FieldID, field.TypeUint64))
+	)
+	_spec.OnConflict = wcuc.conflict
+	if id, ok := wcuc.mutation.ID(); ok {
+		_node.ID = id
+		_spec.ID.Value = id
+	}
+	if value, ok := wcuc.mutation.CreatedAt(); ok {
+		_spec.SetField(wxcarduser.FieldCreatedAt, field.TypeTime, value)
+		_node.CreatedAt = value
+	}
+	if value, ok := wcuc.mutation.UpdatedAt(); ok {
+		_spec.SetField(wxcarduser.FieldUpdatedAt, field.TypeTime, value)
+		_node.UpdatedAt = value
+	}
+	if value, ok := wcuc.mutation.DeletedAt(); ok {
+		_spec.SetField(wxcarduser.FieldDeletedAt, field.TypeTime, value)
+		_node.DeletedAt = value
+	}
+	if value, ok := wcuc.mutation.Wxid(); ok {
+		_spec.SetField(wxcarduser.FieldWxid, field.TypeString, value)
+		_node.Wxid = value
+	}
+	if value, ok := wcuc.mutation.Account(); ok {
+		_spec.SetField(wxcarduser.FieldAccount, field.TypeString, value)
+		_node.Account = value
+	}
+	if value, ok := wcuc.mutation.Avatar(); ok {
+		_spec.SetField(wxcarduser.FieldAvatar, field.TypeString, value)
+		_node.Avatar = value
+	}
+	if value, ok := wcuc.mutation.Nickname(); ok {
+		_spec.SetField(wxcarduser.FieldNickname, field.TypeString, value)
+		_node.Nickname = value
+	}
+	if value, ok := wcuc.mutation.Remark(); ok {
+		_spec.SetField(wxcarduser.FieldRemark, field.TypeString, value)
+		_node.Remark = value
+	}
+	if value, ok := wcuc.mutation.Phone(); ok {
+		_spec.SetField(wxcarduser.FieldPhone, field.TypeString, value)
+		_node.Phone = value
+	}
+	if value, ok := wcuc.mutation.OpenID(); ok {
+		_spec.SetField(wxcarduser.FieldOpenID, field.TypeString, value)
+		_node.OpenID = value
+	}
+	if value, ok := wcuc.mutation.UnionID(); ok {
+		_spec.SetField(wxcarduser.FieldUnionID, field.TypeString, value)
+		_node.UnionID = value
+	}
+	if value, ok := wcuc.mutation.SessionKey(); ok {
+		_spec.SetField(wxcarduser.FieldSessionKey, field.TypeString, value)
+		_node.SessionKey = value
+	}
+	return _node, _spec
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.WxCardUser.Create().
+//		SetCreatedAt(v).
+//		OnConflict(
+//			// Update the row with the new values
+//			// the was proposed for insertion.
+//			sql.ResolveWithNewValues(),
+//		).
+//		// Override some of the fields with custom
+//		// update values.
+//		Update(func(u *ent.WxCardUserUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (wcuc *WxCardUserCreate) OnConflict(opts ...sql.ConflictOption) *WxCardUserUpsertOne {
+	wcuc.conflict = opts
+	return &WxCardUserUpsertOne{
+		create: wcuc,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.WxCardUser.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (wcuc *WxCardUserCreate) OnConflictColumns(columns ...string) *WxCardUserUpsertOne {
+	wcuc.conflict = append(wcuc.conflict, sql.ConflictColumns(columns...))
+	return &WxCardUserUpsertOne{
+		create: wcuc,
+	}
+}
+
+type (
+	// WxCardUserUpsertOne is the builder for "upsert"-ing
+	//  one WxCardUser node.
+	WxCardUserUpsertOne struct {
+		create *WxCardUserCreate
+	}
+
+	// WxCardUserUpsert is the "OnConflict" setter.
+	WxCardUserUpsert struct {
+		*sql.UpdateSet
+	}
+)
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *WxCardUserUpsert) SetUpdatedAt(v time.Time) *WxCardUserUpsert {
+	u.Set(wxcarduser.FieldUpdatedAt, v)
+	return u
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *WxCardUserUpsert) UpdateUpdatedAt() *WxCardUserUpsert {
+	u.SetExcluded(wxcarduser.FieldUpdatedAt)
+	return u
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *WxCardUserUpsert) SetDeletedAt(v time.Time) *WxCardUserUpsert {
+	u.Set(wxcarduser.FieldDeletedAt, v)
+	return u
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *WxCardUserUpsert) UpdateDeletedAt() *WxCardUserUpsert {
+	u.SetExcluded(wxcarduser.FieldDeletedAt)
+	return u
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *WxCardUserUpsert) ClearDeletedAt() *WxCardUserUpsert {
+	u.SetNull(wxcarduser.FieldDeletedAt)
+	return u
+}
+
+// SetWxid sets the "wxid" field.
+func (u *WxCardUserUpsert) SetWxid(v string) *WxCardUserUpsert {
+	u.Set(wxcarduser.FieldWxid, v)
+	return u
+}
+
+// UpdateWxid sets the "wxid" field to the value that was provided on create.
+func (u *WxCardUserUpsert) UpdateWxid() *WxCardUserUpsert {
+	u.SetExcluded(wxcarduser.FieldWxid)
+	return u
+}
+
+// SetAccount sets the "account" field.
+func (u *WxCardUserUpsert) SetAccount(v string) *WxCardUserUpsert {
+	u.Set(wxcarduser.FieldAccount, v)
+	return u
+}
+
+// UpdateAccount sets the "account" field to the value that was provided on create.
+func (u *WxCardUserUpsert) UpdateAccount() *WxCardUserUpsert {
+	u.SetExcluded(wxcarduser.FieldAccount)
+	return u
+}
+
+// SetAvatar sets the "avatar" field.
+func (u *WxCardUserUpsert) SetAvatar(v string) *WxCardUserUpsert {
+	u.Set(wxcarduser.FieldAvatar, v)
+	return u
+}
+
+// UpdateAvatar sets the "avatar" field to the value that was provided on create.
+func (u *WxCardUserUpsert) UpdateAvatar() *WxCardUserUpsert {
+	u.SetExcluded(wxcarduser.FieldAvatar)
+	return u
+}
+
+// SetNickname sets the "nickname" field.
+func (u *WxCardUserUpsert) SetNickname(v string) *WxCardUserUpsert {
+	u.Set(wxcarduser.FieldNickname, v)
+	return u
+}
+
+// UpdateNickname sets the "nickname" field to the value that was provided on create.
+func (u *WxCardUserUpsert) UpdateNickname() *WxCardUserUpsert {
+	u.SetExcluded(wxcarduser.FieldNickname)
+	return u
+}
+
+// SetRemark sets the "remark" field.
+func (u *WxCardUserUpsert) SetRemark(v string) *WxCardUserUpsert {
+	u.Set(wxcarduser.FieldRemark, v)
+	return u
+}
+
+// UpdateRemark sets the "remark" field to the value that was provided on create.
+func (u *WxCardUserUpsert) UpdateRemark() *WxCardUserUpsert {
+	u.SetExcluded(wxcarduser.FieldRemark)
+	return u
+}
+
+// SetPhone sets the "phone" field.
+func (u *WxCardUserUpsert) SetPhone(v string) *WxCardUserUpsert {
+	u.Set(wxcarduser.FieldPhone, v)
+	return u
+}
+
+// UpdatePhone sets the "phone" field to the value that was provided on create.
+func (u *WxCardUserUpsert) UpdatePhone() *WxCardUserUpsert {
+	u.SetExcluded(wxcarduser.FieldPhone)
+	return u
+}
+
+// SetOpenID sets the "open_id" field.
+func (u *WxCardUserUpsert) SetOpenID(v string) *WxCardUserUpsert {
+	u.Set(wxcarduser.FieldOpenID, v)
+	return u
+}
+
+// UpdateOpenID sets the "open_id" field to the value that was provided on create.
+func (u *WxCardUserUpsert) UpdateOpenID() *WxCardUserUpsert {
+	u.SetExcluded(wxcarduser.FieldOpenID)
+	return u
+}
+
+// SetUnionID sets the "union_id" field.
+func (u *WxCardUserUpsert) SetUnionID(v string) *WxCardUserUpsert {
+	u.Set(wxcarduser.FieldUnionID, v)
+	return u
+}
+
+// UpdateUnionID sets the "union_id" field to the value that was provided on create.
+func (u *WxCardUserUpsert) UpdateUnionID() *WxCardUserUpsert {
+	u.SetExcluded(wxcarduser.FieldUnionID)
+	return u
+}
+
+// SetSessionKey sets the "session_key" field.
+func (u *WxCardUserUpsert) SetSessionKey(v string) *WxCardUserUpsert {
+	u.Set(wxcarduser.FieldSessionKey, v)
+	return u
+}
+
+// UpdateSessionKey sets the "session_key" field to the value that was provided on create.
+func (u *WxCardUserUpsert) UpdateSessionKey() *WxCardUserUpsert {
+	u.SetExcluded(wxcarduser.FieldSessionKey)
+	return u
+}
+
+// UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field.
+// Using this option is equivalent to using:
+//
+//	client.WxCardUser.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(wxcarduser.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *WxCardUserUpsertOne) UpdateNewValues() *WxCardUserUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
+		if _, exists := u.create.mutation.ID(); exists {
+			s.SetIgnore(wxcarduser.FieldID)
+		}
+		if _, exists := u.create.mutation.CreatedAt(); exists {
+			s.SetIgnore(wxcarduser.FieldCreatedAt)
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.WxCardUser.Create().
+//	    OnConflict(sql.ResolveWithIgnore()).
+//	    Exec(ctx)
+func (u *WxCardUserUpsertOne) Ignore() *WxCardUserUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
+	return u
+}
+
+// DoNothing configures the conflict_action to `DO NOTHING`.
+// Supported only by SQLite and PostgreSQL.
+func (u *WxCardUserUpsertOne) DoNothing() *WxCardUserUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the WxCardUserCreate.OnConflict
+// documentation for more info.
+func (u *WxCardUserUpsertOne) Update(set func(*WxCardUserUpsert)) *WxCardUserUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&WxCardUserUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *WxCardUserUpsertOne) SetUpdatedAt(v time.Time) *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *WxCardUserUpsertOne) UpdateUpdatedAt() *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *WxCardUserUpsertOne) SetDeletedAt(v time.Time) *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *WxCardUserUpsertOne) UpdateDeletedAt() *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *WxCardUserUpsertOne) ClearDeletedAt() *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetWxid sets the "wxid" field.
+func (u *WxCardUserUpsertOne) SetWxid(v string) *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetWxid(v)
+	})
+}
+
+// UpdateWxid sets the "wxid" field to the value that was provided on create.
+func (u *WxCardUserUpsertOne) UpdateWxid() *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateWxid()
+	})
+}
+
+// SetAccount sets the "account" field.
+func (u *WxCardUserUpsertOne) SetAccount(v string) *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetAccount(v)
+	})
+}
+
+// UpdateAccount sets the "account" field to the value that was provided on create.
+func (u *WxCardUserUpsertOne) UpdateAccount() *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateAccount()
+	})
+}
+
+// SetAvatar sets the "avatar" field.
+func (u *WxCardUserUpsertOne) SetAvatar(v string) *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetAvatar(v)
+	})
+}
+
+// UpdateAvatar sets the "avatar" field to the value that was provided on create.
+func (u *WxCardUserUpsertOne) UpdateAvatar() *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateAvatar()
+	})
+}
+
+// SetNickname sets the "nickname" field.
+func (u *WxCardUserUpsertOne) SetNickname(v string) *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetNickname(v)
+	})
+}
+
+// UpdateNickname sets the "nickname" field to the value that was provided on create.
+func (u *WxCardUserUpsertOne) UpdateNickname() *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateNickname()
+	})
+}
+
+// SetRemark sets the "remark" field.
+func (u *WxCardUserUpsertOne) SetRemark(v string) *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetRemark(v)
+	})
+}
+
+// UpdateRemark sets the "remark" field to the value that was provided on create.
+func (u *WxCardUserUpsertOne) UpdateRemark() *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateRemark()
+	})
+}
+
+// SetPhone sets the "phone" field.
+func (u *WxCardUserUpsertOne) SetPhone(v string) *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetPhone(v)
+	})
+}
+
+// UpdatePhone sets the "phone" field to the value that was provided on create.
+func (u *WxCardUserUpsertOne) UpdatePhone() *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdatePhone()
+	})
+}
+
+// SetOpenID sets the "open_id" field.
+func (u *WxCardUserUpsertOne) SetOpenID(v string) *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetOpenID(v)
+	})
+}
+
+// UpdateOpenID sets the "open_id" field to the value that was provided on create.
+func (u *WxCardUserUpsertOne) UpdateOpenID() *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateOpenID()
+	})
+}
+
+// SetUnionID sets the "union_id" field.
+func (u *WxCardUserUpsertOne) SetUnionID(v string) *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetUnionID(v)
+	})
+}
+
+// UpdateUnionID sets the "union_id" field to the value that was provided on create.
+func (u *WxCardUserUpsertOne) UpdateUnionID() *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateUnionID()
+	})
+}
+
+// SetSessionKey sets the "session_key" field.
+func (u *WxCardUserUpsertOne) SetSessionKey(v string) *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetSessionKey(v)
+	})
+}
+
+// UpdateSessionKey sets the "session_key" field to the value that was provided on create.
+func (u *WxCardUserUpsertOne) UpdateSessionKey() *WxCardUserUpsertOne {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateSessionKey()
+	})
+}
+
+// Exec executes the query.
+func (u *WxCardUserUpsertOne) Exec(ctx context.Context) error {
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for WxCardUserCreate.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *WxCardUserUpsertOne) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// Exec executes the UPSERT query and returns the inserted/updated ID.
+func (u *WxCardUserUpsertOne) ID(ctx context.Context) (id uint64, err error) {
+	node, err := u.create.Save(ctx)
+	if err != nil {
+		return id, err
+	}
+	return node.ID, nil
+}
+
+// IDX is like ID, but panics if an error occurs.
+func (u *WxCardUserUpsertOne) IDX(ctx context.Context) uint64 {
+	id, err := u.ID(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+// WxCardUserCreateBulk is the builder for creating many WxCardUser entities in bulk.
+type WxCardUserCreateBulk struct {
+	config
+	err      error
+	builders []*WxCardUserCreate
+	conflict []sql.ConflictOption
+}
+
+// Save creates the WxCardUser entities in the database.
+func (wcucb *WxCardUserCreateBulk) Save(ctx context.Context) ([]*WxCardUser, error) {
+	if wcucb.err != nil {
+		return nil, wcucb.err
+	}
+	specs := make([]*sqlgraph.CreateSpec, len(wcucb.builders))
+	nodes := make([]*WxCardUser, len(wcucb.builders))
+	mutators := make([]Mutator, len(wcucb.builders))
+	for i := range wcucb.builders {
+		func(i int, root context.Context) {
+			builder := wcucb.builders[i]
+			builder.defaults()
+			var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
+				mutation, ok := m.(*WxCardUserMutation)
+				if !ok {
+					return nil, fmt.Errorf("unexpected mutation type %T", m)
+				}
+				if err := builder.check(); err != nil {
+					return nil, err
+				}
+				builder.mutation = mutation
+				var err error
+				nodes[i], specs[i] = builder.createSpec()
+				if i < len(mutators)-1 {
+					_, err = mutators[i+1].Mutate(root, wcucb.builders[i+1].mutation)
+				} else {
+					spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
+					spec.OnConflict = wcucb.conflict
+					// Invoke the actual operation on the latest mutation in the chain.
+					if err = sqlgraph.BatchCreate(ctx, wcucb.driver, spec); err != nil {
+						if sqlgraph.IsConstraintError(err) {
+							err = &ConstraintError{msg: err.Error(), wrap: err}
+						}
+					}
+				}
+				if err != nil {
+					return nil, err
+				}
+				mutation.id = &nodes[i].ID
+				if specs[i].ID.Value != nil && nodes[i].ID == 0 {
+					id := specs[i].ID.Value.(int64)
+					nodes[i].ID = uint64(id)
+				}
+				mutation.done = true
+				return nodes[i], nil
+			})
+			for i := len(builder.hooks) - 1; i >= 0; i-- {
+				mut = builder.hooks[i](mut)
+			}
+			mutators[i] = mut
+		}(i, ctx)
+	}
+	if len(mutators) > 0 {
+		if _, err := mutators[0].Mutate(ctx, wcucb.builders[0].mutation); err != nil {
+			return nil, err
+		}
+	}
+	return nodes, nil
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (wcucb *WxCardUserCreateBulk) SaveX(ctx context.Context) []*WxCardUser {
+	v, err := wcucb.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (wcucb *WxCardUserCreateBulk) Exec(ctx context.Context) error {
+	_, err := wcucb.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (wcucb *WxCardUserCreateBulk) ExecX(ctx context.Context) {
+	if err := wcucb.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.WxCardUser.CreateBulk(builders...).
+//		OnConflict(
+//			// Update the row with the new values
+//			// the was proposed for insertion.
+//			sql.ResolveWithNewValues(),
+//		).
+//		// Override some of the fields with custom
+//		// update values.
+//		Update(func(u *ent.WxCardUserUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (wcucb *WxCardUserCreateBulk) OnConflict(opts ...sql.ConflictOption) *WxCardUserUpsertBulk {
+	wcucb.conflict = opts
+	return &WxCardUserUpsertBulk{
+		create: wcucb,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.WxCardUser.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (wcucb *WxCardUserCreateBulk) OnConflictColumns(columns ...string) *WxCardUserUpsertBulk {
+	wcucb.conflict = append(wcucb.conflict, sql.ConflictColumns(columns...))
+	return &WxCardUserUpsertBulk{
+		create: wcucb,
+	}
+}
+
+// WxCardUserUpsertBulk is the builder for "upsert"-ing
+// a bulk of WxCardUser nodes.
+type WxCardUserUpsertBulk struct {
+	create *WxCardUserCreateBulk
+}
+
+// UpdateNewValues updates the mutable fields using the new values that
+// were set on create. Using this option is equivalent to using:
+//
+//	client.WxCardUser.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(wxcarduser.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *WxCardUserUpsertBulk) UpdateNewValues() *WxCardUserUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
+		for _, b := range u.create.builders {
+			if _, exists := b.mutation.ID(); exists {
+				s.SetIgnore(wxcarduser.FieldID)
+			}
+			if _, exists := b.mutation.CreatedAt(); exists {
+				s.SetIgnore(wxcarduser.FieldCreatedAt)
+			}
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.WxCardUser.Create().
+//		OnConflict(sql.ResolveWithIgnore()).
+//		Exec(ctx)
+func (u *WxCardUserUpsertBulk) Ignore() *WxCardUserUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
+	return u
+}
+
+// DoNothing configures the conflict_action to `DO NOTHING`.
+// Supported only by SQLite and PostgreSQL.
+func (u *WxCardUserUpsertBulk) DoNothing() *WxCardUserUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the WxCardUserCreateBulk.OnConflict
+// documentation for more info.
+func (u *WxCardUserUpsertBulk) Update(set func(*WxCardUserUpsert)) *WxCardUserUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&WxCardUserUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *WxCardUserUpsertBulk) SetUpdatedAt(v time.Time) *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *WxCardUserUpsertBulk) UpdateUpdatedAt() *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *WxCardUserUpsertBulk) SetDeletedAt(v time.Time) *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *WxCardUserUpsertBulk) UpdateDeletedAt() *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *WxCardUserUpsertBulk) ClearDeletedAt() *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetWxid sets the "wxid" field.
+func (u *WxCardUserUpsertBulk) SetWxid(v string) *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetWxid(v)
+	})
+}
+
+// UpdateWxid sets the "wxid" field to the value that was provided on create.
+func (u *WxCardUserUpsertBulk) UpdateWxid() *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateWxid()
+	})
+}
+
+// SetAccount sets the "account" field.
+func (u *WxCardUserUpsertBulk) SetAccount(v string) *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetAccount(v)
+	})
+}
+
+// UpdateAccount sets the "account" field to the value that was provided on create.
+func (u *WxCardUserUpsertBulk) UpdateAccount() *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateAccount()
+	})
+}
+
+// SetAvatar sets the "avatar" field.
+func (u *WxCardUserUpsertBulk) SetAvatar(v string) *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetAvatar(v)
+	})
+}
+
+// UpdateAvatar sets the "avatar" field to the value that was provided on create.
+func (u *WxCardUserUpsertBulk) UpdateAvatar() *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateAvatar()
+	})
+}
+
+// SetNickname sets the "nickname" field.
+func (u *WxCardUserUpsertBulk) SetNickname(v string) *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetNickname(v)
+	})
+}
+
+// UpdateNickname sets the "nickname" field to the value that was provided on create.
+func (u *WxCardUserUpsertBulk) UpdateNickname() *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateNickname()
+	})
+}
+
+// SetRemark sets the "remark" field.
+func (u *WxCardUserUpsertBulk) SetRemark(v string) *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetRemark(v)
+	})
+}
+
+// UpdateRemark sets the "remark" field to the value that was provided on create.
+func (u *WxCardUserUpsertBulk) UpdateRemark() *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateRemark()
+	})
+}
+
+// SetPhone sets the "phone" field.
+func (u *WxCardUserUpsertBulk) SetPhone(v string) *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetPhone(v)
+	})
+}
+
+// UpdatePhone sets the "phone" field to the value that was provided on create.
+func (u *WxCardUserUpsertBulk) UpdatePhone() *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdatePhone()
+	})
+}
+
+// SetOpenID sets the "open_id" field.
+func (u *WxCardUserUpsertBulk) SetOpenID(v string) *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetOpenID(v)
+	})
+}
+
+// UpdateOpenID sets the "open_id" field to the value that was provided on create.
+func (u *WxCardUserUpsertBulk) UpdateOpenID() *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateOpenID()
+	})
+}
+
+// SetUnionID sets the "union_id" field.
+func (u *WxCardUserUpsertBulk) SetUnionID(v string) *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetUnionID(v)
+	})
+}
+
+// UpdateUnionID sets the "union_id" field to the value that was provided on create.
+func (u *WxCardUserUpsertBulk) UpdateUnionID() *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateUnionID()
+	})
+}
+
+// SetSessionKey sets the "session_key" field.
+func (u *WxCardUserUpsertBulk) SetSessionKey(v string) *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.SetSessionKey(v)
+	})
+}
+
+// UpdateSessionKey sets the "session_key" field to the value that was provided on create.
+func (u *WxCardUserUpsertBulk) UpdateSessionKey() *WxCardUserUpsertBulk {
+	return u.Update(func(s *WxCardUserUpsert) {
+		s.UpdateSessionKey()
+	})
+}
+
+// Exec executes the query.
+func (u *WxCardUserUpsertBulk) Exec(ctx context.Context) error {
+	if u.create.err != nil {
+		return u.create.err
+	}
+	for i, b := range u.create.builders {
+		if len(b.conflict) != 0 {
+			return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the WxCardUserCreateBulk instead", i)
+		}
+	}
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for WxCardUserCreateBulk.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *WxCardUserUpsertBulk) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}

+ 88 - 0
ent/wxcarduser_delete.go

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

+ 526 - 0
ent/wxcarduser_query.go

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

+ 582 - 0
ent/wxcarduser_update.go

@@ -0,0 +1,582 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/predicate"
+	"wechat-api/ent/wxcarduser"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// WxCardUserUpdate is the builder for updating WxCardUser entities.
+type WxCardUserUpdate struct {
+	config
+	hooks    []Hook
+	mutation *WxCardUserMutation
+}
+
+// Where appends a list predicates to the WxCardUserUpdate builder.
+func (wcuu *WxCardUserUpdate) Where(ps ...predicate.WxCardUser) *WxCardUserUpdate {
+	wcuu.mutation.Where(ps...)
+	return wcuu
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (wcuu *WxCardUserUpdate) SetUpdatedAt(t time.Time) *WxCardUserUpdate {
+	wcuu.mutation.SetUpdatedAt(t)
+	return wcuu
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (wcuu *WxCardUserUpdate) SetDeletedAt(t time.Time) *WxCardUserUpdate {
+	wcuu.mutation.SetDeletedAt(t)
+	return wcuu
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (wcuu *WxCardUserUpdate) SetNillableDeletedAt(t *time.Time) *WxCardUserUpdate {
+	if t != nil {
+		wcuu.SetDeletedAt(*t)
+	}
+	return wcuu
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (wcuu *WxCardUserUpdate) ClearDeletedAt() *WxCardUserUpdate {
+	wcuu.mutation.ClearDeletedAt()
+	return wcuu
+}
+
+// SetWxid sets the "wxid" field.
+func (wcuu *WxCardUserUpdate) SetWxid(s string) *WxCardUserUpdate {
+	wcuu.mutation.SetWxid(s)
+	return wcuu
+}
+
+// SetNillableWxid sets the "wxid" field if the given value is not nil.
+func (wcuu *WxCardUserUpdate) SetNillableWxid(s *string) *WxCardUserUpdate {
+	if s != nil {
+		wcuu.SetWxid(*s)
+	}
+	return wcuu
+}
+
+// SetAccount sets the "account" field.
+func (wcuu *WxCardUserUpdate) SetAccount(s string) *WxCardUserUpdate {
+	wcuu.mutation.SetAccount(s)
+	return wcuu
+}
+
+// SetNillableAccount sets the "account" field if the given value is not nil.
+func (wcuu *WxCardUserUpdate) SetNillableAccount(s *string) *WxCardUserUpdate {
+	if s != nil {
+		wcuu.SetAccount(*s)
+	}
+	return wcuu
+}
+
+// SetAvatar sets the "avatar" field.
+func (wcuu *WxCardUserUpdate) SetAvatar(s string) *WxCardUserUpdate {
+	wcuu.mutation.SetAvatar(s)
+	return wcuu
+}
+
+// SetNillableAvatar sets the "avatar" field if the given value is not nil.
+func (wcuu *WxCardUserUpdate) SetNillableAvatar(s *string) *WxCardUserUpdate {
+	if s != nil {
+		wcuu.SetAvatar(*s)
+	}
+	return wcuu
+}
+
+// SetNickname sets the "nickname" field.
+func (wcuu *WxCardUserUpdate) SetNickname(s string) *WxCardUserUpdate {
+	wcuu.mutation.SetNickname(s)
+	return wcuu
+}
+
+// SetNillableNickname sets the "nickname" field if the given value is not nil.
+func (wcuu *WxCardUserUpdate) SetNillableNickname(s *string) *WxCardUserUpdate {
+	if s != nil {
+		wcuu.SetNickname(*s)
+	}
+	return wcuu
+}
+
+// SetRemark sets the "remark" field.
+func (wcuu *WxCardUserUpdate) SetRemark(s string) *WxCardUserUpdate {
+	wcuu.mutation.SetRemark(s)
+	return wcuu
+}
+
+// SetNillableRemark sets the "remark" field if the given value is not nil.
+func (wcuu *WxCardUserUpdate) SetNillableRemark(s *string) *WxCardUserUpdate {
+	if s != nil {
+		wcuu.SetRemark(*s)
+	}
+	return wcuu
+}
+
+// SetPhone sets the "phone" field.
+func (wcuu *WxCardUserUpdate) SetPhone(s string) *WxCardUserUpdate {
+	wcuu.mutation.SetPhone(s)
+	return wcuu
+}
+
+// SetNillablePhone sets the "phone" field if the given value is not nil.
+func (wcuu *WxCardUserUpdate) SetNillablePhone(s *string) *WxCardUserUpdate {
+	if s != nil {
+		wcuu.SetPhone(*s)
+	}
+	return wcuu
+}
+
+// SetOpenID sets the "open_id" field.
+func (wcuu *WxCardUserUpdate) SetOpenID(s string) *WxCardUserUpdate {
+	wcuu.mutation.SetOpenID(s)
+	return wcuu
+}
+
+// SetNillableOpenID sets the "open_id" field if the given value is not nil.
+func (wcuu *WxCardUserUpdate) SetNillableOpenID(s *string) *WxCardUserUpdate {
+	if s != nil {
+		wcuu.SetOpenID(*s)
+	}
+	return wcuu
+}
+
+// SetUnionID sets the "union_id" field.
+func (wcuu *WxCardUserUpdate) SetUnionID(s string) *WxCardUserUpdate {
+	wcuu.mutation.SetUnionID(s)
+	return wcuu
+}
+
+// SetNillableUnionID sets the "union_id" field if the given value is not nil.
+func (wcuu *WxCardUserUpdate) SetNillableUnionID(s *string) *WxCardUserUpdate {
+	if s != nil {
+		wcuu.SetUnionID(*s)
+	}
+	return wcuu
+}
+
+// SetSessionKey sets the "session_key" field.
+func (wcuu *WxCardUserUpdate) SetSessionKey(s string) *WxCardUserUpdate {
+	wcuu.mutation.SetSessionKey(s)
+	return wcuu
+}
+
+// SetNillableSessionKey sets the "session_key" field if the given value is not nil.
+func (wcuu *WxCardUserUpdate) SetNillableSessionKey(s *string) *WxCardUserUpdate {
+	if s != nil {
+		wcuu.SetSessionKey(*s)
+	}
+	return wcuu
+}
+
+// Mutation returns the WxCardUserMutation object of the builder.
+func (wcuu *WxCardUserUpdate) Mutation() *WxCardUserMutation {
+	return wcuu.mutation
+}
+
+// Save executes the query and returns the number of nodes affected by the update operation.
+func (wcuu *WxCardUserUpdate) Save(ctx context.Context) (int, error) {
+	if err := wcuu.defaults(); err != nil {
+		return 0, err
+	}
+	return withHooks(ctx, wcuu.sqlSave, wcuu.mutation, wcuu.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (wcuu *WxCardUserUpdate) SaveX(ctx context.Context) int {
+	affected, err := wcuu.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return affected
+}
+
+// Exec executes the query.
+func (wcuu *WxCardUserUpdate) Exec(ctx context.Context) error {
+	_, err := wcuu.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (wcuu *WxCardUserUpdate) ExecX(ctx context.Context) {
+	if err := wcuu.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (wcuu *WxCardUserUpdate) defaults() error {
+	if _, ok := wcuu.mutation.UpdatedAt(); !ok {
+		if wxcarduser.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized wxcarduser.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := wxcarduser.UpdateDefaultUpdatedAt()
+		wcuu.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+func (wcuu *WxCardUserUpdate) sqlSave(ctx context.Context) (n int, err error) {
+	_spec := sqlgraph.NewUpdateSpec(wxcarduser.Table, wxcarduser.Columns, sqlgraph.NewFieldSpec(wxcarduser.FieldID, field.TypeUint64))
+	if ps := wcuu.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := wcuu.mutation.UpdatedAt(); ok {
+		_spec.SetField(wxcarduser.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := wcuu.mutation.DeletedAt(); ok {
+		_spec.SetField(wxcarduser.FieldDeletedAt, field.TypeTime, value)
+	}
+	if wcuu.mutation.DeletedAtCleared() {
+		_spec.ClearField(wxcarduser.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := wcuu.mutation.Wxid(); ok {
+		_spec.SetField(wxcarduser.FieldWxid, field.TypeString, value)
+	}
+	if value, ok := wcuu.mutation.Account(); ok {
+		_spec.SetField(wxcarduser.FieldAccount, field.TypeString, value)
+	}
+	if value, ok := wcuu.mutation.Avatar(); ok {
+		_spec.SetField(wxcarduser.FieldAvatar, field.TypeString, value)
+	}
+	if value, ok := wcuu.mutation.Nickname(); ok {
+		_spec.SetField(wxcarduser.FieldNickname, field.TypeString, value)
+	}
+	if value, ok := wcuu.mutation.Remark(); ok {
+		_spec.SetField(wxcarduser.FieldRemark, field.TypeString, value)
+	}
+	if value, ok := wcuu.mutation.Phone(); ok {
+		_spec.SetField(wxcarduser.FieldPhone, field.TypeString, value)
+	}
+	if value, ok := wcuu.mutation.OpenID(); ok {
+		_spec.SetField(wxcarduser.FieldOpenID, field.TypeString, value)
+	}
+	if value, ok := wcuu.mutation.UnionID(); ok {
+		_spec.SetField(wxcarduser.FieldUnionID, field.TypeString, value)
+	}
+	if value, ok := wcuu.mutation.SessionKey(); ok {
+		_spec.SetField(wxcarduser.FieldSessionKey, field.TypeString, value)
+	}
+	if n, err = sqlgraph.UpdateNodes(ctx, wcuu.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{wxcarduser.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return 0, err
+	}
+	wcuu.mutation.done = true
+	return n, nil
+}
+
+// WxCardUserUpdateOne is the builder for updating a single WxCardUser entity.
+type WxCardUserUpdateOne struct {
+	config
+	fields   []string
+	hooks    []Hook
+	mutation *WxCardUserMutation
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (wcuuo *WxCardUserUpdateOne) SetUpdatedAt(t time.Time) *WxCardUserUpdateOne {
+	wcuuo.mutation.SetUpdatedAt(t)
+	return wcuuo
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (wcuuo *WxCardUserUpdateOne) SetDeletedAt(t time.Time) *WxCardUserUpdateOne {
+	wcuuo.mutation.SetDeletedAt(t)
+	return wcuuo
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (wcuuo *WxCardUserUpdateOne) SetNillableDeletedAt(t *time.Time) *WxCardUserUpdateOne {
+	if t != nil {
+		wcuuo.SetDeletedAt(*t)
+	}
+	return wcuuo
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (wcuuo *WxCardUserUpdateOne) ClearDeletedAt() *WxCardUserUpdateOne {
+	wcuuo.mutation.ClearDeletedAt()
+	return wcuuo
+}
+
+// SetWxid sets the "wxid" field.
+func (wcuuo *WxCardUserUpdateOne) SetWxid(s string) *WxCardUserUpdateOne {
+	wcuuo.mutation.SetWxid(s)
+	return wcuuo
+}
+
+// SetNillableWxid sets the "wxid" field if the given value is not nil.
+func (wcuuo *WxCardUserUpdateOne) SetNillableWxid(s *string) *WxCardUserUpdateOne {
+	if s != nil {
+		wcuuo.SetWxid(*s)
+	}
+	return wcuuo
+}
+
+// SetAccount sets the "account" field.
+func (wcuuo *WxCardUserUpdateOne) SetAccount(s string) *WxCardUserUpdateOne {
+	wcuuo.mutation.SetAccount(s)
+	return wcuuo
+}
+
+// SetNillableAccount sets the "account" field if the given value is not nil.
+func (wcuuo *WxCardUserUpdateOne) SetNillableAccount(s *string) *WxCardUserUpdateOne {
+	if s != nil {
+		wcuuo.SetAccount(*s)
+	}
+	return wcuuo
+}
+
+// SetAvatar sets the "avatar" field.
+func (wcuuo *WxCardUserUpdateOne) SetAvatar(s string) *WxCardUserUpdateOne {
+	wcuuo.mutation.SetAvatar(s)
+	return wcuuo
+}
+
+// SetNillableAvatar sets the "avatar" field if the given value is not nil.
+func (wcuuo *WxCardUserUpdateOne) SetNillableAvatar(s *string) *WxCardUserUpdateOne {
+	if s != nil {
+		wcuuo.SetAvatar(*s)
+	}
+	return wcuuo
+}
+
+// SetNickname sets the "nickname" field.
+func (wcuuo *WxCardUserUpdateOne) SetNickname(s string) *WxCardUserUpdateOne {
+	wcuuo.mutation.SetNickname(s)
+	return wcuuo
+}
+
+// SetNillableNickname sets the "nickname" field if the given value is not nil.
+func (wcuuo *WxCardUserUpdateOne) SetNillableNickname(s *string) *WxCardUserUpdateOne {
+	if s != nil {
+		wcuuo.SetNickname(*s)
+	}
+	return wcuuo
+}
+
+// SetRemark sets the "remark" field.
+func (wcuuo *WxCardUserUpdateOne) SetRemark(s string) *WxCardUserUpdateOne {
+	wcuuo.mutation.SetRemark(s)
+	return wcuuo
+}
+
+// SetNillableRemark sets the "remark" field if the given value is not nil.
+func (wcuuo *WxCardUserUpdateOne) SetNillableRemark(s *string) *WxCardUserUpdateOne {
+	if s != nil {
+		wcuuo.SetRemark(*s)
+	}
+	return wcuuo
+}
+
+// SetPhone sets the "phone" field.
+func (wcuuo *WxCardUserUpdateOne) SetPhone(s string) *WxCardUserUpdateOne {
+	wcuuo.mutation.SetPhone(s)
+	return wcuuo
+}
+
+// SetNillablePhone sets the "phone" field if the given value is not nil.
+func (wcuuo *WxCardUserUpdateOne) SetNillablePhone(s *string) *WxCardUserUpdateOne {
+	if s != nil {
+		wcuuo.SetPhone(*s)
+	}
+	return wcuuo
+}
+
+// SetOpenID sets the "open_id" field.
+func (wcuuo *WxCardUserUpdateOne) SetOpenID(s string) *WxCardUserUpdateOne {
+	wcuuo.mutation.SetOpenID(s)
+	return wcuuo
+}
+
+// SetNillableOpenID sets the "open_id" field if the given value is not nil.
+func (wcuuo *WxCardUserUpdateOne) SetNillableOpenID(s *string) *WxCardUserUpdateOne {
+	if s != nil {
+		wcuuo.SetOpenID(*s)
+	}
+	return wcuuo
+}
+
+// SetUnionID sets the "union_id" field.
+func (wcuuo *WxCardUserUpdateOne) SetUnionID(s string) *WxCardUserUpdateOne {
+	wcuuo.mutation.SetUnionID(s)
+	return wcuuo
+}
+
+// SetNillableUnionID sets the "union_id" field if the given value is not nil.
+func (wcuuo *WxCardUserUpdateOne) SetNillableUnionID(s *string) *WxCardUserUpdateOne {
+	if s != nil {
+		wcuuo.SetUnionID(*s)
+	}
+	return wcuuo
+}
+
+// SetSessionKey sets the "session_key" field.
+func (wcuuo *WxCardUserUpdateOne) SetSessionKey(s string) *WxCardUserUpdateOne {
+	wcuuo.mutation.SetSessionKey(s)
+	return wcuuo
+}
+
+// SetNillableSessionKey sets the "session_key" field if the given value is not nil.
+func (wcuuo *WxCardUserUpdateOne) SetNillableSessionKey(s *string) *WxCardUserUpdateOne {
+	if s != nil {
+		wcuuo.SetSessionKey(*s)
+	}
+	return wcuuo
+}
+
+// Mutation returns the WxCardUserMutation object of the builder.
+func (wcuuo *WxCardUserUpdateOne) Mutation() *WxCardUserMutation {
+	return wcuuo.mutation
+}
+
+// Where appends a list predicates to the WxCardUserUpdate builder.
+func (wcuuo *WxCardUserUpdateOne) Where(ps ...predicate.WxCardUser) *WxCardUserUpdateOne {
+	wcuuo.mutation.Where(ps...)
+	return wcuuo
+}
+
+// Select allows selecting one or more fields (columns) of the returned entity.
+// The default is selecting all fields defined in the entity schema.
+func (wcuuo *WxCardUserUpdateOne) Select(field string, fields ...string) *WxCardUserUpdateOne {
+	wcuuo.fields = append([]string{field}, fields...)
+	return wcuuo
+}
+
+// Save executes the query and returns the updated WxCardUser entity.
+func (wcuuo *WxCardUserUpdateOne) Save(ctx context.Context) (*WxCardUser, error) {
+	if err := wcuuo.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, wcuuo.sqlSave, wcuuo.mutation, wcuuo.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (wcuuo *WxCardUserUpdateOne) SaveX(ctx context.Context) *WxCardUser {
+	node, err := wcuuo.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return node
+}
+
+// Exec executes the query on the entity.
+func (wcuuo *WxCardUserUpdateOne) Exec(ctx context.Context) error {
+	_, err := wcuuo.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (wcuuo *WxCardUserUpdateOne) ExecX(ctx context.Context) {
+	if err := wcuuo.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (wcuuo *WxCardUserUpdateOne) defaults() error {
+	if _, ok := wcuuo.mutation.UpdatedAt(); !ok {
+		if wxcarduser.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized wxcarduser.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := wxcarduser.UpdateDefaultUpdatedAt()
+		wcuuo.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+func (wcuuo *WxCardUserUpdateOne) sqlSave(ctx context.Context) (_node *WxCardUser, err error) {
+	_spec := sqlgraph.NewUpdateSpec(wxcarduser.Table, wxcarduser.Columns, sqlgraph.NewFieldSpec(wxcarduser.FieldID, field.TypeUint64))
+	id, ok := wcuuo.mutation.ID()
+	if !ok {
+		return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "WxCardUser.id" for update`)}
+	}
+	_spec.Node.ID.Value = id
+	if fields := wcuuo.fields; len(fields) > 0 {
+		_spec.Node.Columns = make([]string, 0, len(fields))
+		_spec.Node.Columns = append(_spec.Node.Columns, wxcarduser.FieldID)
+		for _, f := range fields {
+			if !wxcarduser.ValidColumn(f) {
+				return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+			}
+			if f != wxcarduser.FieldID {
+				_spec.Node.Columns = append(_spec.Node.Columns, f)
+			}
+		}
+	}
+	if ps := wcuuo.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := wcuuo.mutation.UpdatedAt(); ok {
+		_spec.SetField(wxcarduser.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := wcuuo.mutation.DeletedAt(); ok {
+		_spec.SetField(wxcarduser.FieldDeletedAt, field.TypeTime, value)
+	}
+	if wcuuo.mutation.DeletedAtCleared() {
+		_spec.ClearField(wxcarduser.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := wcuuo.mutation.Wxid(); ok {
+		_spec.SetField(wxcarduser.FieldWxid, field.TypeString, value)
+	}
+	if value, ok := wcuuo.mutation.Account(); ok {
+		_spec.SetField(wxcarduser.FieldAccount, field.TypeString, value)
+	}
+	if value, ok := wcuuo.mutation.Avatar(); ok {
+		_spec.SetField(wxcarduser.FieldAvatar, field.TypeString, value)
+	}
+	if value, ok := wcuuo.mutation.Nickname(); ok {
+		_spec.SetField(wxcarduser.FieldNickname, field.TypeString, value)
+	}
+	if value, ok := wcuuo.mutation.Remark(); ok {
+		_spec.SetField(wxcarduser.FieldRemark, field.TypeString, value)
+	}
+	if value, ok := wcuuo.mutation.Phone(); ok {
+		_spec.SetField(wxcarduser.FieldPhone, field.TypeString, value)
+	}
+	if value, ok := wcuuo.mutation.OpenID(); ok {
+		_spec.SetField(wxcarduser.FieldOpenID, field.TypeString, value)
+	}
+	if value, ok := wcuuo.mutation.UnionID(); ok {
+		_spec.SetField(wxcarduser.FieldUnionID, field.TypeString, value)
+	}
+	if value, ok := wcuuo.mutation.SessionKey(); ok {
+		_spec.SetField(wxcarduser.FieldSessionKey, field.TypeString, value)
+	}
+	_node = &WxCardUser{config: wcuuo.config}
+	_spec.Assign = _node.assignValues
+	_spec.ScanValues = _node.scanValues
+	if err = sqlgraph.UpdateNode(ctx, wcuuo.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{wxcarduser.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	wcuuo.mutation.done = true
+	return _node, nil
+}

+ 159 - 0
ent/wxcardvisit.go

@@ -0,0 +1,159 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"fmt"
+	"strings"
+	"time"
+	"wechat-api/ent/wxcardvisit"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+)
+
+// WxCardVisit is the model entity for the WxCardVisit schema.
+type WxCardVisit struct {
+	config `json:"-"`
+	// ID of the ent.
+	ID uint64 `json:"id,omitempty"`
+	// Create Time | 创建日期
+	CreatedAt time.Time `json:"created_at,omitempty"`
+	// Update Time | 修改日期
+	UpdatedAt time.Time `json:"updated_at,omitempty"`
+	// Delete Time | 删除日期
+	DeletedAt time.Time `json:"deleted_at,omitempty"`
+	// user表ID
+	UserID uint64 `json:"user_id,omitempty"`
+	// 被访ID
+	BotID uint64 `json:"bot_id,omitempty"`
+	// 类型:1-微信 2-小程序 3-智能体
+	BotType      uint8 `json:"bot_type,omitempty"`
+	selectValues sql.SelectValues
+}
+
+// scanValues returns the types for scanning values from sql.Rows.
+func (*WxCardVisit) scanValues(columns []string) ([]any, error) {
+	values := make([]any, len(columns))
+	for i := range columns {
+		switch columns[i] {
+		case wxcardvisit.FieldID, wxcardvisit.FieldUserID, wxcardvisit.FieldBotID, wxcardvisit.FieldBotType:
+			values[i] = new(sql.NullInt64)
+		case wxcardvisit.FieldCreatedAt, wxcardvisit.FieldUpdatedAt, wxcardvisit.FieldDeletedAt:
+			values[i] = new(sql.NullTime)
+		default:
+			values[i] = new(sql.UnknownType)
+		}
+	}
+	return values, nil
+}
+
+// assignValues assigns the values that were returned from sql.Rows (after scanning)
+// to the WxCardVisit fields.
+func (wcv *WxCardVisit) assignValues(columns []string, values []any) error {
+	if m, n := len(values), len(columns); m < n {
+		return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
+	}
+	for i := range columns {
+		switch columns[i] {
+		case wxcardvisit.FieldID:
+			value, ok := values[i].(*sql.NullInt64)
+			if !ok {
+				return fmt.Errorf("unexpected type %T for field id", value)
+			}
+			wcv.ID = uint64(value.Int64)
+		case wxcardvisit.FieldCreatedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field created_at", values[i])
+			} else if value.Valid {
+				wcv.CreatedAt = value.Time
+			}
+		case wxcardvisit.FieldUpdatedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field updated_at", values[i])
+			} else if value.Valid {
+				wcv.UpdatedAt = value.Time
+			}
+		case wxcardvisit.FieldDeletedAt:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field deleted_at", values[i])
+			} else if value.Valid {
+				wcv.DeletedAt = value.Time
+			}
+		case wxcardvisit.FieldUserID:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field user_id", values[i])
+			} else if value.Valid {
+				wcv.UserID = uint64(value.Int64)
+			}
+		case wxcardvisit.FieldBotID:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field bot_id", values[i])
+			} else if value.Valid {
+				wcv.BotID = uint64(value.Int64)
+			}
+		case wxcardvisit.FieldBotType:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field bot_type", values[i])
+			} else if value.Valid {
+				wcv.BotType = uint8(value.Int64)
+			}
+		default:
+			wcv.selectValues.Set(columns[i], values[i])
+		}
+	}
+	return nil
+}
+
+// Value returns the ent.Value that was dynamically selected and assigned to the WxCardVisit.
+// This includes values selected through modifiers, order, etc.
+func (wcv *WxCardVisit) Value(name string) (ent.Value, error) {
+	return wcv.selectValues.Get(name)
+}
+
+// Update returns a builder for updating this WxCardVisit.
+// Note that you need to call WxCardVisit.Unwrap() before calling this method if this WxCardVisit
+// was returned from a transaction, and the transaction was committed or rolled back.
+func (wcv *WxCardVisit) Update() *WxCardVisitUpdateOne {
+	return NewWxCardVisitClient(wcv.config).UpdateOne(wcv)
+}
+
+// Unwrap unwraps the WxCardVisit entity that was returned from a transaction after it was closed,
+// so that all future queries will be executed through the driver which created the transaction.
+func (wcv *WxCardVisit) Unwrap() *WxCardVisit {
+	_tx, ok := wcv.config.driver.(*txDriver)
+	if !ok {
+		panic("ent: WxCardVisit is not a transactional entity")
+	}
+	wcv.config.driver = _tx.drv
+	return wcv
+}
+
+// String implements the fmt.Stringer.
+func (wcv *WxCardVisit) String() string {
+	var builder strings.Builder
+	builder.WriteString("WxCardVisit(")
+	builder.WriteString(fmt.Sprintf("id=%v, ", wcv.ID))
+	builder.WriteString("created_at=")
+	builder.WriteString(wcv.CreatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("updated_at=")
+	builder.WriteString(wcv.UpdatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("deleted_at=")
+	builder.WriteString(wcv.DeletedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("user_id=")
+	builder.WriteString(fmt.Sprintf("%v", wcv.UserID))
+	builder.WriteString(", ")
+	builder.WriteString("bot_id=")
+	builder.WriteString(fmt.Sprintf("%v", wcv.BotID))
+	builder.WriteString(", ")
+	builder.WriteString("bot_type=")
+	builder.WriteString(fmt.Sprintf("%v", wcv.BotType))
+	builder.WriteByte(')')
+	return builder.String()
+}
+
+// WxCardVisits is a parsable slice of WxCardVisit.
+type WxCardVisits []*WxCardVisit

+ 360 - 0
ent/wxcardvisit/where.go

@@ -0,0 +1,360 @@
+// Code generated by ent, DO NOT EDIT.
+
+package wxcardvisit
+
+import (
+	"time"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+)
+
+// ID filters vertices based on their ID field.
+func ID(id uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldEQ(FieldID, id))
+}
+
+// IDEQ applies the EQ predicate on the ID field.
+func IDEQ(id uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldEQ(FieldID, id))
+}
+
+// IDNEQ applies the NEQ predicate on the ID field.
+func IDNEQ(id uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldNEQ(FieldID, id))
+}
+
+// IDIn applies the In predicate on the ID field.
+func IDIn(ids ...uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldIn(FieldID, ids...))
+}
+
+// IDNotIn applies the NotIn predicate on the ID field.
+func IDNotIn(ids ...uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldNotIn(FieldID, ids...))
+}
+
+// IDGT applies the GT predicate on the ID field.
+func IDGT(id uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldGT(FieldID, id))
+}
+
+// IDGTE applies the GTE predicate on the ID field.
+func IDGTE(id uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldGTE(FieldID, id))
+}
+
+// IDLT applies the LT predicate on the ID field.
+func IDLT(id uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldLT(FieldID, id))
+}
+
+// IDLTE applies the LTE predicate on the ID field.
+func IDLTE(id uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldLTE(FieldID, id))
+}
+
+// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
+func CreatedAt(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
+func UpdatedAt(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ.
+func DeletedAt(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// UserID applies equality check predicate on the "user_id" field. It's identical to UserIDEQ.
+func UserID(v uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldEQ(FieldUserID, v))
+}
+
+// BotID applies equality check predicate on the "bot_id" field. It's identical to BotIDEQ.
+func BotID(v uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldEQ(FieldBotID, v))
+}
+
+// BotType applies equality check predicate on the "bot_type" field. It's identical to BotTypeEQ.
+func BotType(v uint8) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldEQ(FieldBotType, v))
+}
+
+// CreatedAtEQ applies the EQ predicate on the "created_at" field.
+func CreatedAtEQ(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
+func CreatedAtNEQ(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldNEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtIn applies the In predicate on the "created_at" field.
+func CreatedAtIn(vs ...time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
+func CreatedAtNotIn(vs ...time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldNotIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtGT applies the GT predicate on the "created_at" field.
+func CreatedAtGT(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldGT(FieldCreatedAt, v))
+}
+
+// CreatedAtGTE applies the GTE predicate on the "created_at" field.
+func CreatedAtGTE(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldGTE(FieldCreatedAt, v))
+}
+
+// CreatedAtLT applies the LT predicate on the "created_at" field.
+func CreatedAtLT(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldLT(FieldCreatedAt, v))
+}
+
+// CreatedAtLTE applies the LTE predicate on the "created_at" field.
+func CreatedAtLTE(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldLTE(FieldCreatedAt, v))
+}
+
+// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
+func UpdatedAtEQ(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
+func UpdatedAtNEQ(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldNEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtIn applies the In predicate on the "updated_at" field.
+func UpdatedAtIn(vs ...time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
+func UpdatedAtNotIn(vs ...time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldNotIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtGT applies the GT predicate on the "updated_at" field.
+func UpdatedAtGT(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldGT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
+func UpdatedAtGTE(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldGTE(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLT applies the LT predicate on the "updated_at" field.
+func UpdatedAtLT(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldLT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
+func UpdatedAtLTE(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldLTE(FieldUpdatedAt, v))
+}
+
+// DeletedAtEQ applies the EQ predicate on the "deleted_at" field.
+func DeletedAtEQ(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field.
+func DeletedAtNEQ(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldNEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtIn applies the In predicate on the "deleted_at" field.
+func DeletedAtIn(vs ...time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field.
+func DeletedAtNotIn(vs ...time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldNotIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtGT applies the GT predicate on the "deleted_at" field.
+func DeletedAtGT(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldGT(FieldDeletedAt, v))
+}
+
+// DeletedAtGTE applies the GTE predicate on the "deleted_at" field.
+func DeletedAtGTE(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldGTE(FieldDeletedAt, v))
+}
+
+// DeletedAtLT applies the LT predicate on the "deleted_at" field.
+func DeletedAtLT(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldLT(FieldDeletedAt, v))
+}
+
+// DeletedAtLTE applies the LTE predicate on the "deleted_at" field.
+func DeletedAtLTE(v time.Time) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldLTE(FieldDeletedAt, v))
+}
+
+// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field.
+func DeletedAtIsNil() predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldIsNull(FieldDeletedAt))
+}
+
+// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field.
+func DeletedAtNotNil() predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldNotNull(FieldDeletedAt))
+}
+
+// UserIDEQ applies the EQ predicate on the "user_id" field.
+func UserIDEQ(v uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldEQ(FieldUserID, v))
+}
+
+// UserIDNEQ applies the NEQ predicate on the "user_id" field.
+func UserIDNEQ(v uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldNEQ(FieldUserID, v))
+}
+
+// UserIDIn applies the In predicate on the "user_id" field.
+func UserIDIn(vs ...uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldIn(FieldUserID, vs...))
+}
+
+// UserIDNotIn applies the NotIn predicate on the "user_id" field.
+func UserIDNotIn(vs ...uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldNotIn(FieldUserID, vs...))
+}
+
+// UserIDGT applies the GT predicate on the "user_id" field.
+func UserIDGT(v uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldGT(FieldUserID, v))
+}
+
+// UserIDGTE applies the GTE predicate on the "user_id" field.
+func UserIDGTE(v uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldGTE(FieldUserID, v))
+}
+
+// UserIDLT applies the LT predicate on the "user_id" field.
+func UserIDLT(v uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldLT(FieldUserID, v))
+}
+
+// UserIDLTE applies the LTE predicate on the "user_id" field.
+func UserIDLTE(v uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldLTE(FieldUserID, v))
+}
+
+// UserIDIsNil applies the IsNil predicate on the "user_id" field.
+func UserIDIsNil() predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldIsNull(FieldUserID))
+}
+
+// UserIDNotNil applies the NotNil predicate on the "user_id" field.
+func UserIDNotNil() predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldNotNull(FieldUserID))
+}
+
+// BotIDEQ applies the EQ predicate on the "bot_id" field.
+func BotIDEQ(v uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldEQ(FieldBotID, v))
+}
+
+// BotIDNEQ applies the NEQ predicate on the "bot_id" field.
+func BotIDNEQ(v uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldNEQ(FieldBotID, v))
+}
+
+// BotIDIn applies the In predicate on the "bot_id" field.
+func BotIDIn(vs ...uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldIn(FieldBotID, vs...))
+}
+
+// BotIDNotIn applies the NotIn predicate on the "bot_id" field.
+func BotIDNotIn(vs ...uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldNotIn(FieldBotID, vs...))
+}
+
+// BotIDGT applies the GT predicate on the "bot_id" field.
+func BotIDGT(v uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldGT(FieldBotID, v))
+}
+
+// BotIDGTE applies the GTE predicate on the "bot_id" field.
+func BotIDGTE(v uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldGTE(FieldBotID, v))
+}
+
+// BotIDLT applies the LT predicate on the "bot_id" field.
+func BotIDLT(v uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldLT(FieldBotID, v))
+}
+
+// BotIDLTE applies the LTE predicate on the "bot_id" field.
+func BotIDLTE(v uint64) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldLTE(FieldBotID, v))
+}
+
+// BotTypeEQ applies the EQ predicate on the "bot_type" field.
+func BotTypeEQ(v uint8) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldEQ(FieldBotType, v))
+}
+
+// BotTypeNEQ applies the NEQ predicate on the "bot_type" field.
+func BotTypeNEQ(v uint8) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldNEQ(FieldBotType, v))
+}
+
+// BotTypeIn applies the In predicate on the "bot_type" field.
+func BotTypeIn(vs ...uint8) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldIn(FieldBotType, vs...))
+}
+
+// BotTypeNotIn applies the NotIn predicate on the "bot_type" field.
+func BotTypeNotIn(vs ...uint8) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldNotIn(FieldBotType, vs...))
+}
+
+// BotTypeGT applies the GT predicate on the "bot_type" field.
+func BotTypeGT(v uint8) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldGT(FieldBotType, v))
+}
+
+// BotTypeGTE applies the GTE predicate on the "bot_type" field.
+func BotTypeGTE(v uint8) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldGTE(FieldBotType, v))
+}
+
+// BotTypeLT applies the LT predicate on the "bot_type" field.
+func BotTypeLT(v uint8) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldLT(FieldBotType, v))
+}
+
+// BotTypeLTE applies the LTE predicate on the "bot_type" field.
+func BotTypeLTE(v uint8) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.FieldLTE(FieldBotType, v))
+}
+
+// And groups predicates with the AND operator between them.
+func And(predicates ...predicate.WxCardVisit) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.AndPredicates(predicates...))
+}
+
+// Or groups predicates with the OR operator between them.
+func Or(predicates ...predicate.WxCardVisit) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.OrPredicates(predicates...))
+}
+
+// Not applies the not operator on the given predicate.
+func Not(p predicate.WxCardVisit) predicate.WxCardVisit {
+	return predicate.WxCardVisit(sql.NotPredicates(p))
+}

+ 112 - 0
ent/wxcardvisit/wxcardvisit.go

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

+ 893 - 0
ent/wxcardvisit_create.go

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

+ 88 - 0
ent/wxcardvisit_delete.go

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

+ 526 - 0
ent/wxcardvisit_query.go

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

+ 456 - 0
ent/wxcardvisit_update.go

@@ -0,0 +1,456 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/predicate"
+	"wechat-api/ent/wxcardvisit"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// WxCardVisitUpdate is the builder for updating WxCardVisit entities.
+type WxCardVisitUpdate struct {
+	config
+	hooks    []Hook
+	mutation *WxCardVisitMutation
+}
+
+// Where appends a list predicates to the WxCardVisitUpdate builder.
+func (wcvu *WxCardVisitUpdate) Where(ps ...predicate.WxCardVisit) *WxCardVisitUpdate {
+	wcvu.mutation.Where(ps...)
+	return wcvu
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (wcvu *WxCardVisitUpdate) SetUpdatedAt(t time.Time) *WxCardVisitUpdate {
+	wcvu.mutation.SetUpdatedAt(t)
+	return wcvu
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (wcvu *WxCardVisitUpdate) SetDeletedAt(t time.Time) *WxCardVisitUpdate {
+	wcvu.mutation.SetDeletedAt(t)
+	return wcvu
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (wcvu *WxCardVisitUpdate) SetNillableDeletedAt(t *time.Time) *WxCardVisitUpdate {
+	if t != nil {
+		wcvu.SetDeletedAt(*t)
+	}
+	return wcvu
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (wcvu *WxCardVisitUpdate) ClearDeletedAt() *WxCardVisitUpdate {
+	wcvu.mutation.ClearDeletedAt()
+	return wcvu
+}
+
+// SetUserID sets the "user_id" field.
+func (wcvu *WxCardVisitUpdate) SetUserID(u uint64) *WxCardVisitUpdate {
+	wcvu.mutation.ResetUserID()
+	wcvu.mutation.SetUserID(u)
+	return wcvu
+}
+
+// SetNillableUserID sets the "user_id" field if the given value is not nil.
+func (wcvu *WxCardVisitUpdate) SetNillableUserID(u *uint64) *WxCardVisitUpdate {
+	if u != nil {
+		wcvu.SetUserID(*u)
+	}
+	return wcvu
+}
+
+// AddUserID adds u to the "user_id" field.
+func (wcvu *WxCardVisitUpdate) AddUserID(u int64) *WxCardVisitUpdate {
+	wcvu.mutation.AddUserID(u)
+	return wcvu
+}
+
+// ClearUserID clears the value of the "user_id" field.
+func (wcvu *WxCardVisitUpdate) ClearUserID() *WxCardVisitUpdate {
+	wcvu.mutation.ClearUserID()
+	return wcvu
+}
+
+// SetBotID sets the "bot_id" field.
+func (wcvu *WxCardVisitUpdate) SetBotID(u uint64) *WxCardVisitUpdate {
+	wcvu.mutation.ResetBotID()
+	wcvu.mutation.SetBotID(u)
+	return wcvu
+}
+
+// SetNillableBotID sets the "bot_id" field if the given value is not nil.
+func (wcvu *WxCardVisitUpdate) SetNillableBotID(u *uint64) *WxCardVisitUpdate {
+	if u != nil {
+		wcvu.SetBotID(*u)
+	}
+	return wcvu
+}
+
+// AddBotID adds u to the "bot_id" field.
+func (wcvu *WxCardVisitUpdate) AddBotID(u int64) *WxCardVisitUpdate {
+	wcvu.mutation.AddBotID(u)
+	return wcvu
+}
+
+// SetBotType sets the "bot_type" field.
+func (wcvu *WxCardVisitUpdate) SetBotType(u uint8) *WxCardVisitUpdate {
+	wcvu.mutation.ResetBotType()
+	wcvu.mutation.SetBotType(u)
+	return wcvu
+}
+
+// SetNillableBotType sets the "bot_type" field if the given value is not nil.
+func (wcvu *WxCardVisitUpdate) SetNillableBotType(u *uint8) *WxCardVisitUpdate {
+	if u != nil {
+		wcvu.SetBotType(*u)
+	}
+	return wcvu
+}
+
+// AddBotType adds u to the "bot_type" field.
+func (wcvu *WxCardVisitUpdate) AddBotType(u int8) *WxCardVisitUpdate {
+	wcvu.mutation.AddBotType(u)
+	return wcvu
+}
+
+// Mutation returns the WxCardVisitMutation object of the builder.
+func (wcvu *WxCardVisitUpdate) Mutation() *WxCardVisitMutation {
+	return wcvu.mutation
+}
+
+// Save executes the query and returns the number of nodes affected by the update operation.
+func (wcvu *WxCardVisitUpdate) Save(ctx context.Context) (int, error) {
+	if err := wcvu.defaults(); err != nil {
+		return 0, err
+	}
+	return withHooks(ctx, wcvu.sqlSave, wcvu.mutation, wcvu.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (wcvu *WxCardVisitUpdate) SaveX(ctx context.Context) int {
+	affected, err := wcvu.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return affected
+}
+
+// Exec executes the query.
+func (wcvu *WxCardVisitUpdate) Exec(ctx context.Context) error {
+	_, err := wcvu.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (wcvu *WxCardVisitUpdate) ExecX(ctx context.Context) {
+	if err := wcvu.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (wcvu *WxCardVisitUpdate) defaults() error {
+	if _, ok := wcvu.mutation.UpdatedAt(); !ok {
+		if wxcardvisit.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized wxcardvisit.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := wxcardvisit.UpdateDefaultUpdatedAt()
+		wcvu.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+func (wcvu *WxCardVisitUpdate) sqlSave(ctx context.Context) (n int, err error) {
+	_spec := sqlgraph.NewUpdateSpec(wxcardvisit.Table, wxcardvisit.Columns, sqlgraph.NewFieldSpec(wxcardvisit.FieldID, field.TypeUint64))
+	if ps := wcvu.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := wcvu.mutation.UpdatedAt(); ok {
+		_spec.SetField(wxcardvisit.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := wcvu.mutation.DeletedAt(); ok {
+		_spec.SetField(wxcardvisit.FieldDeletedAt, field.TypeTime, value)
+	}
+	if wcvu.mutation.DeletedAtCleared() {
+		_spec.ClearField(wxcardvisit.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := wcvu.mutation.UserID(); ok {
+		_spec.SetField(wxcardvisit.FieldUserID, field.TypeUint64, value)
+	}
+	if value, ok := wcvu.mutation.AddedUserID(); ok {
+		_spec.AddField(wxcardvisit.FieldUserID, field.TypeUint64, value)
+	}
+	if wcvu.mutation.UserIDCleared() {
+		_spec.ClearField(wxcardvisit.FieldUserID, field.TypeUint64)
+	}
+	if value, ok := wcvu.mutation.BotID(); ok {
+		_spec.SetField(wxcardvisit.FieldBotID, field.TypeUint64, value)
+	}
+	if value, ok := wcvu.mutation.AddedBotID(); ok {
+		_spec.AddField(wxcardvisit.FieldBotID, field.TypeUint64, value)
+	}
+	if value, ok := wcvu.mutation.BotType(); ok {
+		_spec.SetField(wxcardvisit.FieldBotType, field.TypeUint8, value)
+	}
+	if value, ok := wcvu.mutation.AddedBotType(); ok {
+		_spec.AddField(wxcardvisit.FieldBotType, field.TypeUint8, value)
+	}
+	if n, err = sqlgraph.UpdateNodes(ctx, wcvu.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{wxcardvisit.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return 0, err
+	}
+	wcvu.mutation.done = true
+	return n, nil
+}
+
+// WxCardVisitUpdateOne is the builder for updating a single WxCardVisit entity.
+type WxCardVisitUpdateOne struct {
+	config
+	fields   []string
+	hooks    []Hook
+	mutation *WxCardVisitMutation
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (wcvuo *WxCardVisitUpdateOne) SetUpdatedAt(t time.Time) *WxCardVisitUpdateOne {
+	wcvuo.mutation.SetUpdatedAt(t)
+	return wcvuo
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (wcvuo *WxCardVisitUpdateOne) SetDeletedAt(t time.Time) *WxCardVisitUpdateOne {
+	wcvuo.mutation.SetDeletedAt(t)
+	return wcvuo
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (wcvuo *WxCardVisitUpdateOne) SetNillableDeletedAt(t *time.Time) *WxCardVisitUpdateOne {
+	if t != nil {
+		wcvuo.SetDeletedAt(*t)
+	}
+	return wcvuo
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (wcvuo *WxCardVisitUpdateOne) ClearDeletedAt() *WxCardVisitUpdateOne {
+	wcvuo.mutation.ClearDeletedAt()
+	return wcvuo
+}
+
+// SetUserID sets the "user_id" field.
+func (wcvuo *WxCardVisitUpdateOne) SetUserID(u uint64) *WxCardVisitUpdateOne {
+	wcvuo.mutation.ResetUserID()
+	wcvuo.mutation.SetUserID(u)
+	return wcvuo
+}
+
+// SetNillableUserID sets the "user_id" field if the given value is not nil.
+func (wcvuo *WxCardVisitUpdateOne) SetNillableUserID(u *uint64) *WxCardVisitUpdateOne {
+	if u != nil {
+		wcvuo.SetUserID(*u)
+	}
+	return wcvuo
+}
+
+// AddUserID adds u to the "user_id" field.
+func (wcvuo *WxCardVisitUpdateOne) AddUserID(u int64) *WxCardVisitUpdateOne {
+	wcvuo.mutation.AddUserID(u)
+	return wcvuo
+}
+
+// ClearUserID clears the value of the "user_id" field.
+func (wcvuo *WxCardVisitUpdateOne) ClearUserID() *WxCardVisitUpdateOne {
+	wcvuo.mutation.ClearUserID()
+	return wcvuo
+}
+
+// SetBotID sets the "bot_id" field.
+func (wcvuo *WxCardVisitUpdateOne) SetBotID(u uint64) *WxCardVisitUpdateOne {
+	wcvuo.mutation.ResetBotID()
+	wcvuo.mutation.SetBotID(u)
+	return wcvuo
+}
+
+// SetNillableBotID sets the "bot_id" field if the given value is not nil.
+func (wcvuo *WxCardVisitUpdateOne) SetNillableBotID(u *uint64) *WxCardVisitUpdateOne {
+	if u != nil {
+		wcvuo.SetBotID(*u)
+	}
+	return wcvuo
+}
+
+// AddBotID adds u to the "bot_id" field.
+func (wcvuo *WxCardVisitUpdateOne) AddBotID(u int64) *WxCardVisitUpdateOne {
+	wcvuo.mutation.AddBotID(u)
+	return wcvuo
+}
+
+// SetBotType sets the "bot_type" field.
+func (wcvuo *WxCardVisitUpdateOne) SetBotType(u uint8) *WxCardVisitUpdateOne {
+	wcvuo.mutation.ResetBotType()
+	wcvuo.mutation.SetBotType(u)
+	return wcvuo
+}
+
+// SetNillableBotType sets the "bot_type" field if the given value is not nil.
+func (wcvuo *WxCardVisitUpdateOne) SetNillableBotType(u *uint8) *WxCardVisitUpdateOne {
+	if u != nil {
+		wcvuo.SetBotType(*u)
+	}
+	return wcvuo
+}
+
+// AddBotType adds u to the "bot_type" field.
+func (wcvuo *WxCardVisitUpdateOne) AddBotType(u int8) *WxCardVisitUpdateOne {
+	wcvuo.mutation.AddBotType(u)
+	return wcvuo
+}
+
+// Mutation returns the WxCardVisitMutation object of the builder.
+func (wcvuo *WxCardVisitUpdateOne) Mutation() *WxCardVisitMutation {
+	return wcvuo.mutation
+}
+
+// Where appends a list predicates to the WxCardVisitUpdate builder.
+func (wcvuo *WxCardVisitUpdateOne) Where(ps ...predicate.WxCardVisit) *WxCardVisitUpdateOne {
+	wcvuo.mutation.Where(ps...)
+	return wcvuo
+}
+
+// Select allows selecting one or more fields (columns) of the returned entity.
+// The default is selecting all fields defined in the entity schema.
+func (wcvuo *WxCardVisitUpdateOne) Select(field string, fields ...string) *WxCardVisitUpdateOne {
+	wcvuo.fields = append([]string{field}, fields...)
+	return wcvuo
+}
+
+// Save executes the query and returns the updated WxCardVisit entity.
+func (wcvuo *WxCardVisitUpdateOne) Save(ctx context.Context) (*WxCardVisit, error) {
+	if err := wcvuo.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, wcvuo.sqlSave, wcvuo.mutation, wcvuo.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (wcvuo *WxCardVisitUpdateOne) SaveX(ctx context.Context) *WxCardVisit {
+	node, err := wcvuo.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return node
+}
+
+// Exec executes the query on the entity.
+func (wcvuo *WxCardVisitUpdateOne) Exec(ctx context.Context) error {
+	_, err := wcvuo.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (wcvuo *WxCardVisitUpdateOne) ExecX(ctx context.Context) {
+	if err := wcvuo.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (wcvuo *WxCardVisitUpdateOne) defaults() error {
+	if _, ok := wcvuo.mutation.UpdatedAt(); !ok {
+		if wxcardvisit.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized wxcardvisit.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := wxcardvisit.UpdateDefaultUpdatedAt()
+		wcvuo.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+func (wcvuo *WxCardVisitUpdateOne) sqlSave(ctx context.Context) (_node *WxCardVisit, err error) {
+	_spec := sqlgraph.NewUpdateSpec(wxcardvisit.Table, wxcardvisit.Columns, sqlgraph.NewFieldSpec(wxcardvisit.FieldID, field.TypeUint64))
+	id, ok := wcvuo.mutation.ID()
+	if !ok {
+		return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "WxCardVisit.id" for update`)}
+	}
+	_spec.Node.ID.Value = id
+	if fields := wcvuo.fields; len(fields) > 0 {
+		_spec.Node.Columns = make([]string, 0, len(fields))
+		_spec.Node.Columns = append(_spec.Node.Columns, wxcardvisit.FieldID)
+		for _, f := range fields {
+			if !wxcardvisit.ValidColumn(f) {
+				return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+			}
+			if f != wxcardvisit.FieldID {
+				_spec.Node.Columns = append(_spec.Node.Columns, f)
+			}
+		}
+	}
+	if ps := wcvuo.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := wcvuo.mutation.UpdatedAt(); ok {
+		_spec.SetField(wxcardvisit.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := wcvuo.mutation.DeletedAt(); ok {
+		_spec.SetField(wxcardvisit.FieldDeletedAt, field.TypeTime, value)
+	}
+	if wcvuo.mutation.DeletedAtCleared() {
+		_spec.ClearField(wxcardvisit.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := wcvuo.mutation.UserID(); ok {
+		_spec.SetField(wxcardvisit.FieldUserID, field.TypeUint64, value)
+	}
+	if value, ok := wcvuo.mutation.AddedUserID(); ok {
+		_spec.AddField(wxcardvisit.FieldUserID, field.TypeUint64, value)
+	}
+	if wcvuo.mutation.UserIDCleared() {
+		_spec.ClearField(wxcardvisit.FieldUserID, field.TypeUint64)
+	}
+	if value, ok := wcvuo.mutation.BotID(); ok {
+		_spec.SetField(wxcardvisit.FieldBotID, field.TypeUint64, value)
+	}
+	if value, ok := wcvuo.mutation.AddedBotID(); ok {
+		_spec.AddField(wxcardvisit.FieldBotID, field.TypeUint64, value)
+	}
+	if value, ok := wcvuo.mutation.BotType(); ok {
+		_spec.SetField(wxcardvisit.FieldBotType, field.TypeUint8, value)
+	}
+	if value, ok := wcvuo.mutation.AddedBotType(); ok {
+		_spec.AddField(wxcardvisit.FieldBotType, field.TypeUint8, value)
+	}
+	_node = &WxCardVisit{config: wcvuo.config}
+	_spec.Assign = _node.assignValues
+	_spec.ScanValues = _node.scanValues
+	if err = sqlgraph.UpdateNode(ctx, wcvuo.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{wxcardvisit.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	wcvuo.mutation.done = true
+	return _node, nil
+}

+ 37 - 18
go.mod

@@ -4,11 +4,18 @@ go 1.22.1
 
 require (
 	entgo.io/ent v0.13.1
+	github.com/ArtisanCloud/PowerWeChat/v2 v2.0.40
+	github.com/alibabacloud-go/avatar-20220130/v2 v2.5.3
+	github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10
+	github.com/alibabacloud-go/tea v1.2.2
+	github.com/alibabacloud-go/tea-utils/v2 v2.0.7
 	github.com/casbin/casbin/v2 v2.85.0
 	github.com/go-resty/resty/v2 v2.14.0
+	github.com/golang-jwt/jwt/v5 v5.2.1
 	github.com/imroc/req/v3 v3.43.1
-	github.com/redis/go-redis/v9 v9.5.1
+	github.com/redis/go-redis/v9 v9.6.1
 	github.com/robfig/cron/v3 v3.0.1
+	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
 	github.com/suyuan32/simple-admin-core v1.3.11
@@ -18,7 +25,15 @@ require (
 require (
 	ariga.io/atlas v0.19.2 // indirect
 	filippo.io/edwards25519 v1.1.0 // indirect
+	github.com/ArtisanCloud/PowerLibs/v2 v2.0.49 // indirect
 	github.com/agext/levenshtein v1.2.3 // indirect
+	github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect
+	github.com/alibabacloud-go/debug v1.0.1 // indirect
+	github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect
+	github.com/alibabacloud-go/openapi-util v0.1.0 // indirect
+	github.com/alibabacloud-go/tea-utils v1.3.1 // indirect
+	github.com/alibabacloud-go/tea-xml v1.1.3 // indirect
+	github.com/aliyun/credentials-go v1.3.10 // indirect
 	github.com/andybalholm/brotli v1.1.0 // indirect
 	github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
@@ -26,7 +41,8 @@ require (
 	github.com/casbin/govaluate v1.1.1 // indirect
 	github.com/casbin/redis-watcher/v2 v2.5.0 // indirect
 	github.com/cenkalti/backoff/v4 v4.2.1 // indirect
-	github.com/cespare/xxhash/v2 v2.2.0 // indirect
+	github.com/cespare/xxhash/v2 v2.3.0 // indirect
+	github.com/clbanning/mxj/v2 v2.7.0 // indirect
 	github.com/cloudflare/circl v1.3.7 // indirect
 	github.com/coreos/go-semver v0.3.1 // indirect
 	github.com/coreos/go-systemd/v22 v22.5.0 // indirect
@@ -34,8 +50,8 @@ require (
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 	github.com/emicklei/go-restful/v3 v3.11.0 // indirect
 	github.com/fatih/color v1.16.0 // indirect
-	github.com/gabriel-vasile/mimetype v1.4.3 // indirect
-	github.com/go-logr/logr v1.4.1 // indirect
+	github.com/gabriel-vasile/mimetype v1.4.5 // indirect
+	github.com/go-logr/logr v1.4.2 // indirect
 	github.com/go-logr/stdr v1.2.2 // indirect
 	github.com/go-openapi/inflect v0.21.0 // indirect
 	github.com/go-openapi/jsonpointer v0.19.6 // indirect
@@ -43,12 +59,12 @@ require (
 	github.com/go-openapi/swag v0.22.4 // indirect
 	github.com/go-playground/locales v0.14.1 // indirect
 	github.com/go-playground/universal-translator v0.18.1 // indirect
-	github.com/go-playground/validator/v10 v10.19.0 // indirect
+	github.com/go-playground/validator/v10 v10.22.1 // indirect
+	github.com/go-redis/redis/v8 v8.11.0 // indirect
 	github.com/go-sql-driver/mysql v1.8.0 // indirect
 	github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
 	github.com/gofrs/uuid/v5 v5.0.0 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
-	github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
 	github.com/golang/mock v1.6.0 // indirect
 	github.com/golang/protobuf v1.5.4 // indirect
 	github.com/google/gnostic-models v0.6.8 // indirect
@@ -57,6 +73,7 @@ require (
 	github.com/google/pprof v0.0.0-20240320155624-b11c3daa6f07 // indirect
 	github.com/google/uuid v1.6.0 // indirect
 	github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
+	github.com/guonaihong/gout v0.3.1 // indirect
 	github.com/hashicorp/errwrap v1.1.0 // indirect
 	github.com/hashicorp/go-multierror v1.1.1 // indirect
 	github.com/hashicorp/hcl/v2 v2.20.0 // indirect
@@ -84,6 +101,7 @@ require (
 	github.com/nicksnyder/go-i18n/v2 v2.4.0 // indirect
 	github.com/onsi/ginkgo/v2 v2.17.1 // indirect
 	github.com/openzipkin/zipkin-go v0.4.2 // indirect
+	github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
 	github.com/pelletier/go-toml/v2 v2.1.1 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/prometheus/client_golang v1.19.0 // indirect
@@ -94,42 +112,43 @@ 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/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
 	go.etcd.io/etcd/client/pkg/v3 v3.5.12 // indirect
 	go.etcd.io/etcd/client/v3 v3.5.12 // indirect
-	go.opentelemetry.io/otel v1.24.0 // indirect
+	go.opentelemetry.io/otel v1.30.0 // indirect
 	go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect
 	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect
 	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect
 	go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 // indirect
 	go.opentelemetry.io/otel/exporters/zipkin v1.24.0 // indirect
-	go.opentelemetry.io/otel/metric v1.24.0 // indirect
-	go.opentelemetry.io/otel/sdk v1.24.0 // indirect
-	go.opentelemetry.io/otel/trace v1.24.0 // indirect
+	go.opentelemetry.io/otel/metric v1.30.0 // indirect
+	go.opentelemetry.io/otel/sdk v1.30.0 // indirect
+	go.opentelemetry.io/otel/trace v1.30.0 // indirect
 	go.opentelemetry.io/proto/otlp v1.1.0 // indirect
-	go.uber.org/atomic v1.11.0 // indirect
 	go.uber.org/automaxprocs v1.5.3 // indirect
 	go.uber.org/mock v0.4.0 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
-	go.uber.org/zap v1.24.0 // indirect
-	golang.org/x/crypto v0.26.0 // indirect
+	go.uber.org/zap v1.27.0 // indirect
+	golang.org/x/crypto v0.27.0 // indirect
 	golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect
 	golang.org/x/mod v0.17.0 // indirect
-	golang.org/x/net v0.28.0 // indirect
+	golang.org/x/net v0.29.0 // indirect
 	golang.org/x/oauth2 v0.18.0 // indirect
 	golang.org/x/sync v0.8.0 // indirect
-	golang.org/x/sys v0.23.0 // indirect
-	golang.org/x/term v0.23.0 // indirect
-	golang.org/x/text v0.17.0 // indirect
+	golang.org/x/sys v0.25.0 // indirect
+	golang.org/x/term v0.24.0 // indirect
+	golang.org/x/text v0.18.0 // indirect
 	golang.org/x/time v0.6.0 // indirect
 	golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
 	google.golang.org/appengine v1.6.8 // indirect
 	google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect
 	google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect
 	google.golang.org/grpc v1.62.1 // indirect
-	google.golang.org/protobuf v1.33.0 // indirect
+	google.golang.org/protobuf v1.34.2 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
+	gopkg.in/ini.v1 v1.67.0 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 	k8s.io/api v0.29.3 // indirect

+ 172 - 40
go.sum

@@ -18,6 +18,10 @@ entgo.io/ent v0.13.1 h1:uD8QwN1h6SNphdCCzmkMN3feSUzNnVvV/WIkHKMbzOE=
 entgo.io/ent v0.13.1/go.mod h1:qCEmo+biw3ccBn9OyL4ZK5dfpwg++l1Gxwac5B1206A=
 filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
 filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
+github.com/ArtisanCloud/PowerLibs/v2 v2.0.49 h1:/dOBsCtExdd9/PojKMCaa+n6GXvpIL56TMvyLIQ1CEw=
+github.com/ArtisanCloud/PowerLibs/v2 v2.0.49/go.mod h1:d13Xz4I57htBopbQ8kArvoKBopXGGi6nw9ggRB/DLbQ=
+github.com/ArtisanCloud/PowerWeChat/v2 v2.0.40 h1:i4AR60+xhV3ltJ2OWCzq2bpeg/LDcLSlU18YsP7gAis=
+github.com/ArtisanCloud/PowerWeChat/v2 v2.0.40/go.mod h1:J3iLkEehiwwWAWkMkwEAZcj2xXxp9AcHtoZnCu/E/R4=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
 github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
@@ -33,10 +37,60 @@ github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7l
 github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6 h1:eIf+iGJxdU4U9ypaUfbtOWCsZSbTb8AUHvyPrxu6mAA=
+github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6/go.mod h1:4EUIoxs/do24zMOGGqYVWgw0s9NtiylnJglOeEB5UJo=
+github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4/go.mod h1:sCavSAvdzOjul4cEqeVtvlSaSScfNsTQ+46HwlTL1hc=
+github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 h1:zE8vH9C7JiZLNJJQ5OwjU9mSi4T9ef9u3BURT6LCLC8=
+github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5/go.mod h1:tWnyE9AjF8J8qqLk645oUmVUnFybApTQWklQmi5tY6g=
+github.com/alibabacloud-go/avatar-20220130/v2 v2.5.3 h1:p9rOE5EJDs16TaCcheGNoFUtgDubBTkh8jQ25/cZqdI=
+github.com/alibabacloud-go/avatar-20220130/v2 v2.5.3/go.mod h1:P7j834LZ5IDHVj4Zp/8Yq+KYbJ3PQRUSfXccEKQfTs0=
+github.com/alibabacloud-go/darabonba-array v0.1.0 h1:vR8s7b1fWAQIjEjWnuF0JiKsCvclSRTfDzZHTYqfufY=
+github.com/alibabacloud-go/darabonba-array v0.1.0/go.mod h1:BLKxr0brnggqOJPqT09DFJ8g3fsDshapUD3C3aOEFaI=
+github.com/alibabacloud-go/darabonba-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC2NG0Ax+GpOM5gtupki31XE=
+github.com/alibabacloud-go/darabonba-encode-util v0.0.2/go.mod h1:JiW9higWHYXm7F4PKuMgEUETNZasrDM6vqVr/Can7H8=
+github.com/alibabacloud-go/darabonba-map v0.0.2 h1:qvPnGB4+dJbJIxOOfawxzF3hzMnIpjmafa0qOTp6udc=
+github.com/alibabacloud-go/darabonba-map v0.0.2/go.mod h1:28AJaX8FOE/ym8OUFWga+MtEzBunJwQGceGQlvaPGPc=
+github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.6/go.mod h1:CzQnh+94WDnJOnKZH5YRyouL+OOcdBnXY5VWAf0McgI=
+github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10 h1:GEYkMApgpKEVDn6z12DcH1EGYpDYRB8JxsazM4Rywak=
+github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10/go.mod h1:26a14FGhZVELuz2cc2AolvW4RHmIO3/HRwsdHhaIPDE=
+github.com/alibabacloud-go/darabonba-signature-util v0.0.7 h1:UzCnKvsjPFzApvODDNEYqBHMFt1w98wC7FOo0InLyxg=
+github.com/alibabacloud-go/darabonba-signature-util v0.0.7/go.mod h1:oUzCYV2fcCH797xKdL6BDH8ADIHlzrtKVjeRtunBNTQ=
+github.com/alibabacloud-go/darabonba-string v1.0.2 h1:E714wms5ibdzCqGeYJ9JCFywE5nDyvIXIIQbZVFkkqo=
+github.com/alibabacloud-go/darabonba-string v1.0.2/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA=
+github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68/go.mod h1:6pb/Qy8c+lqua8cFpEy7g39NRRqOWc3rOwAy8m5Y2BY=
+github.com/alibabacloud-go/debug v1.0.0/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc=
+github.com/alibabacloud-go/debug v1.0.1 h1:MsW9SmUtbb1Fnt3ieC6NNZi6aEwrXfDksD4QA6GSbPg=
+github.com/alibabacloud-go/debug v1.0.1/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc=
+github.com/alibabacloud-go/endpoint-util v1.1.0 h1:r/4D3VSw888XGaeNpP994zDUaxdgTSHBbVfZlzf6b5Q=
+github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE=
+github.com/alibabacloud-go/openapi-util v0.1.0 h1:0z75cIULkDrdEhkLWgi9tnLe+KhAFE/r5Pb3312/eAY=
+github.com/alibabacloud-go/openapi-util v0.1.0/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws=
+github.com/alibabacloud-go/tea v1.1.0/go.mod h1:IkGyUSX4Ba1V+k4pCtJUc6jDpZLFph9QMy2VUPTwukg=
+github.com/alibabacloud-go/tea v1.1.7/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
+github.com/alibabacloud-go/tea v1.1.8/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
+github.com/alibabacloud-go/tea v1.1.11/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
+github.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
+github.com/alibabacloud-go/tea v1.1.20/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
+github.com/alibabacloud-go/tea v1.2.1/go.mod h1:qbzof29bM/IFhLMtJPrgTGK3eauV5J2wSyEUo4OEmnA=
+github.com/alibabacloud-go/tea v1.2.2 h1:aTsR6Rl3ANWPfqeQugPglfurloyBJY85eFy7Gc1+8oU=
+github.com/alibabacloud-go/tea v1.2.2/go.mod h1:CF3vOzEMAG+bR4WOql8gc2G9H3EkH3ZLAQdpmpXMgwk=
+github.com/alibabacloud-go/tea-utils v1.3.1 h1:iWQeRzRheqCMuiF3+XkfybB3kTgUXkXX+JMrqfLeB2I=
+github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
+github.com/alibabacloud-go/tea-utils/v2 v2.0.5/go.mod h1:dL6vbUT35E4F4bFTHL845eUloqaerYBYPsdWR2/jhe4=
+github.com/alibabacloud-go/tea-utils/v2 v2.0.6/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I=
+github.com/alibabacloud-go/tea-utils/v2 v2.0.7 h1:WDx5qW3Xa5ZgJ1c8NfqJkF6w+AU5wB8835UdhPr6Ax0=
+github.com/alibabacloud-go/tea-utils/v2 v2.0.7/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I=
+github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzYtqw7dgt0=
+github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
 github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk=
 github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
 github.com/alicebob/miniredis/v2 v2.32.1 h1:Bz7CciDnYSaa0mX5xODh6GUITRSx+cVhjNoOR4JssBo=
 github.com/alicebob/miniredis/v2 v2.32.1/go.mod h1:AqkLNAfUm0K07J28hnAyyQKf/x0YkCY/g5DCtuL01Mw=
+github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw=
+github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0=
+github.com/aliyun/credentials-go v1.3.6/go.mod h1:1LxUuX7L5YrZUWzBrRyk0SwSdH4OmPrib8NVePL3fxM=
+github.com/aliyun/credentials-go v1.3.10 h1:45Xxrae/evfzQL9V10zL3xX31eqgLWEaIdCoPipOEQA=
+github.com/aliyun/credentials-go v1.3.10/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=
 github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
 github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
 github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
@@ -44,8 +98,6 @@ github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmms
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
-github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
-github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -70,8 +122,12 @@ github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqy
 github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
-github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
-github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
+github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
+github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
 github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
@@ -111,9 +167,15 @@ github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4Nij
 github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
 github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
-github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
-github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
+github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
+github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.7.0 h1:jGB9xAJQ12AIGNB4HguylppmDK1Am9ppF7XnGXXJuoU=
+github.com/gin-gonic/gin v1.7.0/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
 github.com/go-bindata/go-bindata v1.0.1-0.20190711162640-ee3c2418e368/go.mod h1:7xCgX1lzlrXPHkfvn3EhumqHkmSlzt8at9q7v0ax19c=
 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
@@ -123,8 +185,8 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
 github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
 github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
-github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
-github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
+github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
 github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
 github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4=
@@ -143,8 +205,10 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
 github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
 github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
 github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
-github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4=
-github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
+github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
+github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
+github.com/go-redis/redis/v8 v8.11.0 h1:O1Td0mQ8UFChQ3N9zFQqo6kTU2cJ+/it88gDB+zg0wo=
+github.com/go-redis/redis/v8 v8.11.0/go.mod h1:DLomh7y2e3ggQXQLd1YgmvIfecPJoFl7WU5SOQ/r06M=
 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=
@@ -178,12 +242,14 @@ github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+Licev
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
 github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
 github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
 github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
 github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
 github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
 github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
 github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
@@ -200,6 +266,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
 github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
@@ -219,12 +286,15 @@ github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
 github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU=
+github.com/guonaihong/gout v0.3.1 h1:pj/44Jw0TTmcHF2RjMaCWhKPwCH98YuQejbN15Hts/o=
+github.com/guonaihong/gout v0.3.1/go.mod h1:lhje0jRkh/gcIogrG22ENPITo9tylQa3kwD9eVxcDrk=
 github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
 github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
 github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
@@ -253,6 +323,7 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
 github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
 github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
 github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/imroc/req/v3 v3.43.1 h1:tsWAhvxik4egtHAvMlxcjaWJtHlJL8EpBqJMOm5rmyQ=
 github.com/imroc/req/v3 v3.43.1/go.mod h1:SQIz5iYop16MJxbo8ib+4LnostGCok8NQf8ToyQc2xA=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
@@ -364,7 +435,6 @@ 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.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
@@ -394,16 +464,27 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM=
 github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+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=
+github.com/onsi/ginkgo v1.15.0 h1:1V1NfVQR87RtWAgp1lv9JZJ5Jap+XFGKPi00andXGi4=
+github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg=
 github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8=
 github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
+github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
+github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
+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/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=
+github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
+github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
 github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
@@ -439,8 +520,8 @@ github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
 github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
 github.com/quic-go/quic-go v0.42.0 h1:uSfdap0eveIl8KXnipv9K7nlwZ5IqLlYOpJ58u5utpM=
 github.com/quic-go/quic-go v0.42.0/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
-github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8=
-github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
+github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4=
+github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA=
 github.com/refraction-networking/utls v1.6.3 h1:MFOfRN35sSx6K5AZNIoESsBuBxS2LCgRilRIdHb6fDc=
 github.com/refraction-networking/utls v1.6.3/go.mod h1:yil9+7qSl+gBwJqztoQseO6Pr3h62pQoY1lXiNR/FPs=
 github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
@@ -466,18 +547,19 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
 github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
 github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
 github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
 github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/speps/go-hashids/v2 v2.0.1 h1:ViWOEqWES/pdOSq+C1SLVa8/Tnsd52XC34RY7lt7m4g=
+github.com/speps/go-hashids/v2 v2.0.1/go.mod h1:47LKunwvDZki/uRVD6NImtyk712yFzIs3UF3KlHohGw=
 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 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=
@@ -507,9 +589,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/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=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
+github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
+github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
+github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
@@ -528,8 +617,8 @@ go.etcd.io/etcd/client/v3 v3.5.12/go.mod h1:tSbBCakoWmmddL+BKVAJHa9km+O/E+bumDe9
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
-go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
-go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
+go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts=
+go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc=
 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8=
 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA=
 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE=
@@ -540,20 +629,18 @@ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 h1:s0PHtIkN+3xrbDO
 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0/go.mod h1:hZlFbDbRt++MMPCCfSJfmhkGIWnX1h3XjkfxZUjLrIA=
 go.opentelemetry.io/otel/exporters/zipkin v1.24.0 h1:3evrL5poBuh1KF51D9gO/S+N/1msnm4DaBqs/rpXUqY=
 go.opentelemetry.io/otel/exporters/zipkin v1.24.0/go.mod h1:0EHgD8R0+8yRhUYJOGR8Hfg2dpiJQxDOszd5smVO9wM=
-go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
-go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
-go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw=
-go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
-go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
-go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
+go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w=
+go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ=
+go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE=
+go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg=
+go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc=
+go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o=
 go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI=
 go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY=
 go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
 go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
-go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
-go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
 go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
 go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
 go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
@@ -569,8 +656,8 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9E
 go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
-go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
-go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@@ -579,18 +666,25 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
 golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
+golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
 golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
 golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
+golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
 golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
 golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
-golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
-golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
+golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
+golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -623,6 +717,7 @@ golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
 golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -637,19 +732,28 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
 golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
 golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
+golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
 golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
 golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
-golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
-golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
+golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
+golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -661,6 +765,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -673,6 +778,7 @@ golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -687,11 +793,17 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -703,24 +815,32 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
-golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
+golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
 golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
+golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
 golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
+golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
+golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
 golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
+golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
 golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
 golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
-golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
-golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
+golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
+golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@@ -731,12 +851,13 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
-golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
-golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
+golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
+golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
@@ -766,7 +887,9 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn
 golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
@@ -812,6 +935,7 @@ google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
 google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
 google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
 google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
@@ -826,26 +950,34 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
 google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
-google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
+google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=
 gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0=
 gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
 gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
+gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 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=

+ 123 - 0
hook/aliyun/client.go

@@ -0,0 +1,123 @@
+package aliyun
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	avatar20220130 "github.com/alibabacloud-go/avatar-20220130/v2/client"
+	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
+	util "github.com/alibabacloud-go/tea-utils/v2/service"
+	"github.com/alibabacloud-go/tea/tea"
+	"os"
+	"strings"
+)
+
+// CreateClient 使用AK&SK初始化账号Client
+// @return Client
+// @throws Exception
+func CreateClient() (_result *avatar20220130.Client, _err error) {
+	// 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。
+	// 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378661.html。
+	config := &openapi.Config{
+		// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
+		AccessKeyId: tea.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")),
+		// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
+		AccessKeySecret: tea.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")),
+	}
+
+	// Endpoint 请参考 https://api.aliyun.com/product/avatar
+	config.Endpoint = tea.String("avatar.cn-zhangjiakou.aliyuncs.com")
+	_result = &avatar20220130.Client{}
+	_result, _err = avatar20220130.NewClient(config)
+	return _result, _err
+}
+
+// userId=23423 bizId=xxxxxxx
+func startInstance(userId, bizId string) (*avatar20220130.StartInstanceResponseBodyData, error) {
+	client, _err := CreateClient()
+	if _err != nil {
+		return nil, _err
+	}
+
+	tenantId := int64(9185)
+	appId := "ALIPUB5748B17121450"
+	startInstanceRequest := &avatar20220130.StartInstanceRequest{
+		TenantId: tea.Int64(tenantId),
+		App: &avatar20220130.StartInstanceRequestApp{
+			AppId: tea.String(appId),
+		},
+		User: &avatar20220130.StartInstanceRequestUser{
+			UserId: tea.String(userId),
+		},
+		BizId: tea.String(bizId),
+	}
+
+	_result, _err := client.StartInstance(startInstanceRequest)
+	if _err != nil {
+		return nil, _err
+	}
+	if *_result.Body.Success {
+		fmt.Println(_result.Body.Data)
+		return _result.Body.Data, nil
+	}
+	return nil, errors.New(*_result.Body.Message)
+}
+
+func _main(args []*string) (_err error) {
+	client, _err := CreateClient()
+	if _err != nil {
+		return _err
+	}
+
+	sendMessageRequest := &avatar20220130.SendMessageRequest{
+		SessionId: tea.String("your_value"),
+		TenantId:  tea.Int64(1),
+		Feedback:  tea.Bool(false),
+	}
+	tryErr := func() (_e error) {
+		defer func() {
+			if r := tea.Recover(recover()); r != nil {
+				_e = r
+			}
+		}()
+		// 复制代码运行请自行打印 API 的返回值
+		_, _err = client.SendMessageWithOptions(sendMessageRequest, &util.RuntimeOptions{})
+		if _err != nil {
+			return _err
+		}
+
+		return nil
+	}()
+
+	if tryErr != nil {
+		var error = &tea.SDKError{}
+		if _t, ok := tryErr.(*tea.SDKError); ok {
+			error = _t
+		} else {
+			error.Message = tea.String(tryErr.Error())
+		}
+		// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
+		// 错误 message
+		fmt.Println(tea.StringValue(error.Message))
+		// 诊断地址
+		var data interface{}
+		d := json.NewDecoder(strings.NewReader(tea.StringValue(error.Data)))
+		d.Decode(&data)
+		if m, ok := data.(map[string]interface{}); ok {
+			recommend, _ := m["Recommend"]
+			fmt.Println(recommend)
+		}
+		_, _err = util.AssertAsString(error.Message)
+		if _err != nil {
+			return _err
+		}
+	}
+	return _err
+}
+
+//func main() {
+//	err := _main(tea.StringSlice(os.Args[1:]))
+//	if err != nil {
+//		panic(err)
+//	}
+//}

+ 42 - 0
hook/dify/chat.go

@@ -0,0 +1,42 @@
+package dify
+
+type ChatReq struct {
+	Query          string      `json:"query"`
+	ConversationId string      `json:"conversation_id"`
+	User           string      `json:"user"`
+	ResponseMode   string      `json:"response_mode"`
+	Files          []File      `json:"files"`
+	Inputs         interface{} `json:"inputs"`
+}
+
+type File struct {
+	Type           string `json:"type"`
+	TransferMethod string `json:"transfer_method"`
+	Url            string `json:"url"`
+}
+
+type ChatResp struct {
+	Event          string `json:"event"`
+	ConversationId string `json:"conversation_id"`
+	MessageId      string `json:"message_id"`
+	CreatedAt      uint64 `json:"created_at"`
+	TaskId         string `json:"task_id"`
+	Id             string `json:"id"`
+	Answer         string `json:"answer,optional"`
+}
+
+type Metadata struct {
+}
+
+// GetChatUrl 请求地址
+func GetChatUrl() string {
+	return "/chat-messages"
+}
+
+func GetBaseUrl() string {
+	return "https://dify.gkscrm.com/v1"
+}
+
+func GetChatToken() string {
+	return "app-NhSN24G0AQV804gWtPfDnFZx"
+}

+ 54 - 0
hook/fastgpt/chat.go

@@ -0,0 +1,54 @@
+package fastgpt
+
+type ChatReq struct {
+	ChatId    string    `json:"chatId"`
+	Stream    bool      `json:"stream"`
+	Detail    bool      `json:"detail"`
+	Variables Variables `json:"variables"`
+	Messages  []Message `json:"messages"`
+}
+
+type ChatResp struct {
+	Id      string   `json:"id"`
+	Object  string   `json:"object"`
+	Created uint64   `json:"created"`
+	Model   string   `json:"model"`
+	Choices []Choice `json:"choices"`
+}
+
+type Choice struct {
+	Delta        Delta  `json:"delta"`
+	FinishReason string `json:"finish_reason,optional"`
+	Index        uint64 `json:"index"`
+}
+
+type Delta struct {
+	Content string `json:"content"`
+	Role    string `json:"role"`
+}
+
+type Variables struct {
+	Uid  string `json:"uid"`
+	Name string `json:"name"`
+}
+type Message struct {
+	Content string `json:"content"`
+	Role    string `json:"role"`
+}
+
+type ChatResponse struct {
+	Id      string   `json:"id"`
+	Object  string   `json:"object"`
+	Created uint64   `json:"created"`
+	Model   string   `json:"model"`
+	Choices []Choice `json:"choices"`
+}
+
+// GetChatUrl 请求地址
+func GetChatUrl() string {
+	return "/v1/chat/completions"
+}
+
+func GetChatToken() string {
+	return "fastgpt-eEvIvCz2ccEmgbp4nUEbUDHLoCN2wz4BnpI3ucxECFRbG9xiNBOfjd797vIkT"
+}

+ 16 - 0
hook/fastgpt/resty.go

@@ -19,11 +19,27 @@ func NewResty() *resty.Client {
 	return client
 }
 
+func NewDiyResty(token string) *resty.Client {
+	client := resty.New()
+	logger := newLogger()
+	client.SetRetryCount(2).
+		SetLogger(logger).
+		SetHeader("Content-Type", "application/json").
+		SetBaseURL(GetBaseUrl()).
+		SetHeader("Authorization", "Bearer "+token)
+
+	return client
+}
+
 // getToken 获取配置的可用的Token
 func getToken() string {
 	return "fastgpt-czbAiqKKse65hwwviZhwkgvyDEKE3aeB31Fx18oUsAGojyWQ672HdsWZi1E1C"
 }
 
+func GetBaseUrl() string {
+	return "https://fastgpt.gkscrm.com/api"
+}
+
 type logger struct {
 	l *log.Logger
 }

+ 2 - 0
internal/config/config.go

@@ -5,6 +5,7 @@ import (
 	"github.com/suyuan32/simple-admin-common/plugins/casbin"
 	"github.com/zeromicro/go-zero/rest"
 	"github.com/zeromicro/go-zero/zrpc"
+	"wechat-api/internal/types"
 )
 
 type Config struct {
@@ -15,5 +16,6 @@ type Config struct {
 	RedisConf          config.RedisConf
 	CasbinConf         casbin.CasbinConf
 	DatabaseConf       config.DatabaseConf
+	Miniprogram        types.Miniprogram
 	CoreRpc            zrpc.RpcClientConf
 }

+ 44 - 0
internal/handler/User/do_api_user_login_handler.go

@@ -0,0 +1,44 @@
+package User
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/User"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route get /api/user/login User DoApiUserLogin
+//
+// Get user basic information | 获取用户基本信息
+//
+// Get user basic information | 获取用户基本信息
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: UserLoginReq
+//
+// Responses:
+//  200: UserLoginResp
+
+func DoApiUserLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.UserLoginReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := User.NewDoApiUserLoginLogic(r.Context(), svcCtx)
+		resp, err := l.DoApiUserLogin(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 31 - 0
internal/handler/category/get_api_category_list_handler.go

@@ -0,0 +1,31 @@
+package category
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/category"
+	"wechat-api/internal/svc"
+)
+
+// swagger:route post /api/category/list category GetApiCategoryList
+//
+// Get category list | 获取 category 列表
+//
+// Get category list | 获取 category 列表
+//
+// Responses:
+//  200: CategoryListResp
+
+func GetApiCategoryListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		l := category.NewGetApiCategoryListLogic(r.Context(), svcCtx)
+		resp, err := l.GetApiCategoryList()
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/chatrecords/create_chat_records_handler.go

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

+ 44 - 0
internal/handler/chatrecords/delete_chat_records_handler.go

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

+ 44 - 0
internal/handler/chatrecords/get_api_chat_list_handler.go

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

+ 44 - 0
internal/handler/chatrecords/get_chat_records_by_id_handler.go

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

+ 44 - 0
internal/handler/chatrecords/get_chat_records_list_handler.go

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

+ 44 - 0
internal/handler/chatrecords/save_api_chat_handler.go

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

+ 44 - 0
internal/handler/chatrecords/submit_api_chat_handler.go

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

+ 44 - 0
internal/handler/chatrecords/update_chat_records_handler.go

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

+ 44 - 0
internal/handler/chatsession/create_chat_session_handler.go

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

+ 44 - 0
internal/handler/chatsession/delete_api_session_handler.go

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

+ 44 - 0
internal/handler/chatsession/delete_chat_session_handler.go

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

+ 44 - 0
internal/handler/chatsession/get_api_session_list_handler.go

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

+ 44 - 0
internal/handler/chatsession/get_chat_session_by_id_handler.go

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

+ 44 - 0
internal/handler/chatsession/get_chat_session_list_handler.go

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

+ 44 - 0
internal/handler/chatsession/update_api_session_handler.go

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

+ 44 - 0
internal/handler/chatsession/update_chat_session_handler.go

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

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

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

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

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

+ 3 - 3
internal/handler/employee/get_employee_search_test_handler.go

@@ -20,14 +20,14 @@ import (
 //  + name: body
 //    require: true
 //    in: body
-//    type: EmployeeListReq
+//    type: AuthReq
 //
 // Responses:
-//  200: EmployeeListResp
+//  200: AuthResp
 
 func GetEmployeeSearchTestHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
-		var req types.EmployeeListReq
+		var req types.AuthReq
 		if err := httpx.Parse(r, &req, true); err != nil {
 			httpx.ErrorCtx(r.Context(), w, err)
 			return

+ 313 - 0
internal/handler/routes.go

@@ -16,6 +16,8 @@ import (
 	base "wechat-api/internal/handler/base"
 	batch_msg "wechat-api/internal/handler/batch_msg"
 	category "wechat-api/internal/handler/category"
+	chatrecords "wechat-api/internal/handler/chatrecords"
+	chatsession "wechat-api/internal/handler/chatsession"
 	contact "wechat-api/internal/handler/contact"
 	employee "wechat-api/internal/handler/employee"
 	employee_config "wechat-api/internal/handler/employee_config"
@@ -29,6 +31,9 @@ import (
 	token "wechat-api/internal/handler/token"
 	tutorial "wechat-api/internal/handler/tutorial"
 	work_experience "wechat-api/internal/handler/work_experience"
+	wxcard "wechat-api/internal/handler/wxcard"
+	wxcarduser "wechat-api/internal/handler/wxcarduser"
+	wxcardvisit "wechat-api/internal/handler/wxcardvisit"
 	"wechat-api/internal/svc"
 
 	"github.com/zeromicro/go-zero/rest"
@@ -598,6 +603,16 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 	)
 
 	server.AddRoutes(
+		[]rest.Route{
+			{
+				Method:  http.MethodGet,
+				Path:    "/api/user/login",
+				Handler: User.DoApiUserLoginHandler(serverCtx),
+			},
+		},
+	)
+
+	server.AddRoutes(
 		rest.WithMiddlewares(
 			[]rest.Middleware{serverCtx.Authority},
 			[]rest.Route{
@@ -701,6 +716,25 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 	)
 
 	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Miniprogram},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/api/employee/list",
+					Handler: employee.GetApiEmployeeListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/api/employee/detail",
+					Handler: employee.GetApiEmployeeDetailHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
+
+	server.AddRoutes(
 		[]rest.Route{
 			{
 				Method:  http.MethodPost,
@@ -881,6 +915,20 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 	)
 
 	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Miniprogram},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/api/category/list",
+					Handler: category.GetApiCategoryListHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
+
+	server.AddRoutes(
 		[]rest.Route{
 			{
 				Method:  http.MethodPost,
@@ -952,4 +1000,269 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 		),
 		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
 	)
+
+	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Miniprogram},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/api/chat/create",
+					Handler: chatrecords.SubmitApiChatHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/api/chat/list",
+					Handler: chatrecords.GetApiChatListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/api/chat/save",
+					Handler: chatrecords.SaveApiChatHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
+
+	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Authority},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/chat_records/create",
+					Handler: chatrecords.CreateChatRecordsHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/chat_records/update",
+					Handler: chatrecords.UpdateChatRecordsHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/chat_records/delete",
+					Handler: chatrecords.DeleteChatRecordsHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/chat_records/list",
+					Handler: chatrecords.GetChatRecordsListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/chat_records",
+					Handler: chatrecords.GetChatRecordsByIdHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
+
+	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Miniprogram},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/api/session/list",
+					Handler: chatsession.GetApiSessionListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/api/session/update",
+					Handler: chatsession.UpdateApiSessionHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/api/session/delete",
+					Handler: chatsession.DeleteApiSessionHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
+
+	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Authority},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/chat_session/create",
+					Handler: chatsession.CreateChatSessionHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/chat_session/update",
+					Handler: chatsession.UpdateChatSessionHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/chat_session/delete",
+					Handler: chatsession.DeleteChatSessionHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/chat_session/list",
+					Handler: chatsession.GetChatSessionListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/chat_session",
+					Handler: chatsession.GetChatSessionByIdHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
+
+	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Miniprogram},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/api/card/detail",
+					Handler: wxcard.GetApiWxCardDetailHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
+
+	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Authority},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/wx_card/create",
+					Handler: wxcard.CreateWxCardHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/wx_card/update",
+					Handler: wxcard.UpdateWxCardHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/wx_card/delete",
+					Handler: wxcard.DeleteWxCardHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/wx_card/list",
+					Handler: wxcard.GetWxCardListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/wx_card",
+					Handler: wxcard.GetWxCardByIdHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
+
+	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Miniprogram},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/api/user/update",
+					Handler: wxcarduser.UpdateApiWxCardUserHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
+
+	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Authority},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/wx_card_user/create",
+					Handler: wxcarduser.CreateWxCardUserHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/wx_card_user/update",
+					Handler: wxcarduser.UpdateWxCardUserHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/wx_card_user/delete",
+					Handler: wxcarduser.DeleteWxCardUserHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/wx_card_user/list",
+					Handler: wxcarduser.GetWxCardUserListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/wx_card_user",
+					Handler: wxcarduser.GetWxCardUserByIdHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
+
+	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Miniprogram},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/api/card/visit",
+					Handler: wxcardvisit.SubmitApiWxCardVisitHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/api/card/visit/history",
+					Handler: wxcardvisit.GetApiWxCardVisitListHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
+
+	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Authority},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/wx_card_visit/create",
+					Handler: wxcardvisit.CreateWxCardVisitHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/wx_card_visit/update",
+					Handler: wxcardvisit.UpdateWxCardVisitHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/wx_card_visit/delete",
+					Handler: wxcardvisit.DeleteWxCardVisitHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/wx_card_visit/list",
+					Handler: wxcardvisit.GetWxCardVisitListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/wx_card_visit",
+					Handler: wxcardvisit.GetWxCardVisitByIdHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
 }

+ 44 - 0
internal/handler/wxcard/create_wx_card_handler.go

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

+ 44 - 0
internal/handler/wxcard/delete_wx_card_handler.go

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

+ 44 - 0
internal/handler/wxcard/get_api_wx_card_detail_handler.go

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

+ 44 - 0
internal/handler/wxcard/get_wx_card_by_id_handler.go

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

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff