Browse Source

fix:submit employee API

jimmyyem 7 months ago
parent
commit
5a55db7cba
72 changed files with 16728 additions and 234 deletions
  1. 4 1
      desc/all.api
  2. 117 0
      desc/wechat/employee.api
  3. 83 0
      desc/wechat/tutorial.api
  4. 85 0
      desc/wechat/work_experience.api
  5. 505 8
      ent/client.go
  6. 324 0
      ent/employee.go
  7. 297 0
      ent/employee/employee.go
  8. 1142 0
      ent/employee/where.go
  9. 1682 0
      ent/employee_create.go
  10. 88 0
      ent/employee_delete.go
  11. 679 0
      ent/employee_query.go
  12. 1284 0
      ent/employee_update.go
  13. 6 0
      ent/ent.go
  14. 36 0
      ent/hook/hook.go
  15. 90 0
      ent/intercept/intercept.go
  16. 115 0
      ent/migrate/schema.go
  17. 495 225
      ent/mutation.go
  18. 246 0
      ent/pagination.go
  19. 9 0
      ent/predicate/predicate.go
  20. 138 0
      ent/runtime/runtime.go
  21. 63 0
      ent/schema/employee.go
  22. 57 0
      ent/schema/tutorial.go
  23. 58 0
      ent/schema/work_experience.go
  24. 744 0
      ent/set_not_nil.go
  25. 212 0
      ent/tutorial.go
  26. 150 0
      ent/tutorial/tutorial.go
  27. 494 0
      ent/tutorial/where.go
  28. 958 0
      ent/tutorial_create.go
  29. 88 0
      ent/tutorial_delete.go
  30. 605 0
      ent/tutorial_query.go
  31. 603 0
      ent/tutorial_update.go
  32. 9 0
      ent/tx.go
  33. 223 0
      ent/workexperience.go
  34. 539 0
      ent/workexperience/where.go
  35. 154 0
      ent/workexperience/workexperience.go
  36. 981 0
      ent/workexperience_create.go
  37. 88 0
      ent/workexperience_delete.go
  38. 605 0
      ent/workexperience_query.go
  39. 597 0
      ent/workexperience_update.go
  40. 44 0
      internal/handler/employee/create_employee_handler.go
  41. 44 0
      internal/handler/employee/delete_employee_handler.go
  42. 44 0
      internal/handler/employee/get_employee_by_id_handler.go
  43. 44 0
      internal/handler/employee/get_employee_list_handler.go
  44. 44 0
      internal/handler/employee/update_employee_handler.go
  45. 105 0
      internal/handler/routes.go
  46. 44 0
      internal/handler/tutorial/create_tutorial_handler.go
  47. 44 0
      internal/handler/tutorial/delete_tutorial_handler.go
  48. 44 0
      internal/handler/tutorial/get_tutorial_by_id_handler.go
  49. 44 0
      internal/handler/tutorial/get_tutorial_list_handler.go
  50. 44 0
      internal/handler/tutorial/update_tutorial_handler.go
  51. 44 0
      internal/handler/work_experience/create_work_experience_handler.go
  52. 44 0
      internal/handler/work_experience/delete_work_experience_handler.go
  53. 44 0
      internal/handler/work_experience/get_work_experience_by_id_handler.go
  54. 44 0
      internal/handler/work_experience/get_work_experience_list_handler.go
  55. 44 0
      internal/handler/work_experience/update_work_experience_handler.go
  56. 186 0
      internal/logic/base/init_api_data.go
  57. 114 0
      internal/logic/employee/create_employee_logic.go
  58. 38 0
      internal/logic/employee/delete_employee_logic.go
  59. 100 0
      internal/logic/employee/get_employee_by_id_logic.go
  60. 114 0
      internal/logic/employee/get_employee_list_logic.go
  61. 98 0
      internal/logic/employee/update_employee_logic.go
  62. 42 0
      internal/logic/tutorial/create_tutorial_logic.go
  63. 37 0
      internal/logic/tutorial/delete_tutorial_logic.go
  64. 53 0
      internal/logic/tutorial/get_tutorial_by_id_logic.go
  65. 66 0
      internal/logic/tutorial/get_tutorial_list_logic.go
  66. 41 0
      internal/logic/tutorial/update_tutorial_logic.go
  67. 49 0
      internal/logic/work_experience/create_work_experience_logic.go
  68. 37 0
      internal/logic/work_experience/delete_work_experience_logic.go
  69. 55 0
      internal/logic/work_experience/get_work_experience_by_id_logic.go
  70. 64 0
      internal/logic/work_experience/get_work_experience_list_logic.go
  71. 49 0
      internal/logic/work_experience/update_work_experience_logic.go
  72. 167 0
      internal/types/types.go

+ 4 - 1
desc/all.api

@@ -14,4 +14,7 @@ import "./wechat/chatroom_member.api"
 import "./wechat/user.api"
 import "./openapi/contact.api"
 import "./wechat/batch_msg.api"
-import "./wechat/agent.api"
+import "./wechat/agent.api"
+import "./wechat/employee.api"
+import "./wechat/work_experience.api"
+import "./wechat/tutorial.api"

+ 117 - 0
desc/wechat/employee.api

@@ -0,0 +1,117 @@
+import "../base.api"
+import "./work_experience.api"
+import "./tutorial.api"
+
+type (
+    // The data of employee information | Employee信息
+    EmployeeInfo {
+        BaseIDInfo
+
+        // title | 标题 
+        Title  *string `json:"title,optional"`
+
+        // avatar | 头像 
+        Avatar  *string `json:"avatar,optional"`
+
+        // tags | 个人标签 
+        Tags  *string `json:"tags,optional"`
+
+        // hire_count | 被雇佣次数 
+        HireCount  *int `json:"hireCount,optional"`
+
+        // service_count | 已服务次数 
+        ServiceCount  *int `json:"serviceCount,optional"`
+
+        // achievement_count | 业绩单数 
+        AchievementCount  *int `json:"achievementCount,optional"`
+
+        // intro | 个人介绍 
+        Intro  *string `json:"intro,optional"`
+
+        // estimate | 自我评价 
+        Estimate  *string `json:"estimate,optional"`
+
+        // skill | 技能卡 
+        Skill  *string `json:"skill,optional"`
+
+        // ability_type | 能力类型 
+        AbilityType  *string `json:"abilityType,optional"`
+
+        // scene | 使用场景 
+        Scene  *string `json:"scene,optional"`
+
+        // switch_in | 支持介入 
+        SwitchIn  *string `json:"switchIn,optional"`
+
+        Tutorial  []TutorialInfo `json:"tutorial,optional"`
+
+        // video_url | 视频地址
+        VideoUrl  *string `json:"videoUrl,optional"`
+
+		// work_experience | 工作经验
+		WorkExperience []WorkExperienceInfo `json:"workExperience,optional"`
+    }
+
+    // The response data of employee list | Employee列表数据
+    EmployeeListResp {
+        BaseDataInfo
+
+        // Employee list data | Employee列表数据
+        Data EmployeeListInfo `json:"data"`
+    }
+
+    // Employee list data | Employee列表数据
+    EmployeeListInfo {
+        BaseListInfo
+
+        // The API list data | Employee列表数据
+        Data  []EmployeeInfo  `json:"data"`
+    }
+
+    // Get employee list request params | Employee列表请求参数
+    EmployeeListReq {
+        PageInfo
+
+        // title | 标题 
+        Title  *string `json:"title,optional"`
+
+        // tags | 个人标签 
+        Tags  *string `json:"tags,optional"`
+    }
+
+    // Employee information response | Employee信息返回体
+    EmployeeInfoResp {
+        BaseDataInfo
+
+        // Employee information | Employee数据
+        Data EmployeeInfo `json:"data"`
+    }
+)
+
+@server(
+    jwt: Auth
+    group: employee
+    middleware: Authority
+)
+
+service Wechat {
+    // Create employee information | 创建Employee
+    @handler createEmployee
+    post /employee/create (EmployeeInfo) returns (BaseMsgResp)
+
+    // Update employee information | 更新Employee
+    @handler updateEmployee
+    post /employee/update (EmployeeInfo) returns (BaseMsgResp)
+
+    // Delete employee information | 删除Employee信息
+    @handler deleteEmployee
+    post /employee/delete (IDsReq) returns (BaseMsgResp)
+
+    // Get employee list | 获取Employee列表
+    @handler getEmployeeList
+    post /employee/list (EmployeeListReq) returns (EmployeeListResp)
+
+    // Get employee by ID | 通过ID获取Employee
+    @handler getEmployeeById
+    post /employee (IDReq) returns (EmployeeInfoResp)
+}

+ 83 - 0
desc/wechat/tutorial.api

@@ -0,0 +1,83 @@
+import "../base.api"
+
+type (
+    // The data of tutorial information | Tutorial信息
+    TutorialInfo {
+        BaseIDInfo
+
+        // employee_id | 员工ID 
+        EmployeeId  *uint64 `json:"employeeId,optional"`
+
+        // index | 序号 
+        Index  *int `json:"index,optional"`
+
+        // title | 标题 
+        Title  *string `json:"title,optional"`
+
+        // content | 内容 
+        Content  *string `json:"content,optional"`
+    }
+
+    // The response data of tutorial list | Tutorial列表数据
+    TutorialListResp {
+        BaseDataInfo
+
+        // Tutorial list data | Tutorial列表数据
+        Data TutorialListInfo `json:"data"`
+    }
+
+    // Tutorial list data | Tutorial列表数据
+    TutorialListInfo {
+        BaseListInfo
+
+        // The API list data | Tutorial列表数据
+        Data  []TutorialInfo  `json:"data"`
+    }
+
+    // Get tutorial list request params | Tutorial列表请求参数
+    TutorialListReq {
+        PageInfo
+
+        // title | 标题 
+        Title  *string `json:"title,optional"`
+
+        // content | 内容 
+        Content  *string `json:"content,optional"`
+    }
+
+    // Tutorial information response | Tutorial信息返回体
+    TutorialInfoResp {
+        BaseDataInfo
+
+        // Tutorial information | Tutorial数据
+        Data TutorialInfo `json:"data"`
+    }
+)
+
+@server(
+    jwt: Auth
+    group: tutorial
+    middleware: Authority
+)
+
+service Wechat {
+    // Create tutorial information | 创建Tutorial
+    @handler createTutorial
+    post /tutorial/create (TutorialInfo) returns (BaseMsgResp)
+
+    // Update tutorial information | 更新Tutorial
+    @handler updateTutorial
+    post /tutorial/update (TutorialInfo) returns (BaseMsgResp)
+
+    // Delete tutorial information | 删除Tutorial信息
+    @handler deleteTutorial
+    post /tutorial/delete (IDsReq) returns (BaseMsgResp)
+
+    // Get tutorial list | 获取Tutorial列表
+    @handler getTutorialList
+    post /tutorial/list (TutorialListReq) returns (TutorialListResp)
+
+    // Get tutorial by ID | 通过ID获取Tutorial
+    @handler getTutorialById
+    post /tutorial (IDReq) returns (TutorialInfoResp)
+}

+ 85 - 0
desc/wechat/work_experience.api

@@ -0,0 +1,85 @@
+import "../base.api"
+
+type (
+    // The data of work experience information | WorkExperience信息
+    WorkExperienceInfo {
+        BaseIDInfo
+
+        // employee_id | 员工ID 
+        EmployeeId  *uint64 `json:"employeeId,optional"`
+
+        // start_date | 开始时间 
+        StartDate  *int64 `json:"startDate,optional"`
+		StartDateStr  *string `json:"startDateStr,optional"`
+
+        // end_date | 结束时间 
+        EndDate  *int64 `json:"endDate,optional"`
+		EndDateStr  *string `json:"endDateStr,optional"`
+
+        // company | 公司名 
+        Company  *string `json:"company,optional"`
+
+        // experience | 工作内容 
+        Experience  *string `json:"experience,optional"`
+    }
+
+    // The response data of work experience list | WorkExperience列表数据
+    WorkExperienceListResp {
+        BaseDataInfo
+
+        // WorkExperience list data | WorkExperience列表数据
+        Data WorkExperienceListInfo `json:"data"`
+    }
+
+    // WorkExperience list data | WorkExperience列表数据
+    WorkExperienceListInfo {
+        BaseListInfo
+
+        // The API list data | WorkExperience列表数据
+        Data  []WorkExperienceInfo  `json:"data"`
+    }
+
+    // Get work experience list request params | WorkExperience列表请求参数
+    WorkExperienceListReq {
+        PageInfo
+
+        // company | 公司名 
+        Company  *string `json:"company,optional"`
+    }
+
+    // WorkExperience information response | WorkExperience信息返回体
+    WorkExperienceInfoResp {
+        BaseDataInfo
+
+        // WorkExperience information | WorkExperience数据
+        Data WorkExperienceInfo `json:"data"`
+    }
+)
+
+@server(
+    jwt: Auth
+    group: work_experience
+    middleware: Authority
+)
+
+service Wechat {
+    // Create work experience information | 创建WorkExperience
+    @handler createWorkExperience
+    post /work_experience/create (WorkExperienceInfo) returns (BaseMsgResp)
+
+    // Update work experience information | 更新WorkExperience
+    @handler updateWorkExperience
+    post /work_experience/update (WorkExperienceInfo) returns (BaseMsgResp)
+
+    // Delete work experience information | 删除WorkExperience信息
+    @handler deleteWorkExperience
+    post /work_experience/delete (IDsReq) returns (BaseMsgResp)
+
+    // Get work experience list | 获取WorkExperience列表
+    @handler getWorkExperienceList
+    post /work_experience/list (WorkExperienceListReq) returns (WorkExperienceListResp)
+
+    // Get work experience by ID | 通过ID获取WorkExperience
+    @handler getWorkExperienceById
+    post /work_experience (IDReq) returns (WorkExperienceInfoResp)
+}

+ 505 - 8
ent/client.go

@@ -14,6 +14,7 @@ import (
 	"wechat-api/ent/agent"
 	"wechat-api/ent/batchmsg"
 	"wechat-api/ent/contact"
+	"wechat-api/ent/employee"
 	"wechat-api/ent/label"
 	"wechat-api/ent/labelrelationship"
 	"wechat-api/ent/message"
@@ -23,6 +24,8 @@ import (
 	"wechat-api/ent/sopnode"
 	"wechat-api/ent/sopstage"
 	"wechat-api/ent/soptask"
+	"wechat-api/ent/tutorial"
+	"wechat-api/ent/workexperience"
 	"wechat-api/ent/wx"
 
 	"entgo.io/ent"
@@ -44,6 +47,8 @@ type Client struct {
 	BatchMsg *BatchMsgClient
 	// Contact is the client for interacting with the Contact builders.
 	Contact *ContactClient
+	// Employee is the client for interacting with the Employee builders.
+	Employee *EmployeeClient
 	// Label is the client for interacting with the Label builders.
 	Label *LabelClient
 	// LabelRelationship is the client for interacting with the LabelRelationship builders.
@@ -62,6 +67,10 @@ type Client struct {
 	SopStage *SopStageClient
 	// SopTask is the client for interacting with the SopTask builders.
 	SopTask *SopTaskClient
+	// Tutorial is the client for interacting with the Tutorial builders.
+	Tutorial *TutorialClient
+	// WorkExperience is the client for interacting with the WorkExperience builders.
+	WorkExperience *WorkExperienceClient
 	// Wx is the client for interacting with the Wx builders.
 	Wx *WxClient
 }
@@ -78,6 +87,7 @@ func (c *Client) init() {
 	c.Agent = NewAgentClient(c.config)
 	c.BatchMsg = NewBatchMsgClient(c.config)
 	c.Contact = NewContactClient(c.config)
+	c.Employee = NewEmployeeClient(c.config)
 	c.Label = NewLabelClient(c.config)
 	c.LabelRelationship = NewLabelRelationshipClient(c.config)
 	c.Message = NewMessageClient(c.config)
@@ -87,6 +97,8 @@ func (c *Client) init() {
 	c.SopNode = NewSopNodeClient(c.config)
 	c.SopStage = NewSopStageClient(c.config)
 	c.SopTask = NewSopTaskClient(c.config)
+	c.Tutorial = NewTutorialClient(c.config)
+	c.WorkExperience = NewWorkExperienceClient(c.config)
 	c.Wx = NewWxClient(c.config)
 }
 
@@ -183,6 +195,7 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
 		Agent:             NewAgentClient(cfg),
 		BatchMsg:          NewBatchMsgClient(cfg),
 		Contact:           NewContactClient(cfg),
+		Employee:          NewEmployeeClient(cfg),
 		Label:             NewLabelClient(cfg),
 		LabelRelationship: NewLabelRelationshipClient(cfg),
 		Message:           NewMessageClient(cfg),
@@ -192,6 +205,8 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
 		SopNode:           NewSopNodeClient(cfg),
 		SopStage:          NewSopStageClient(cfg),
 		SopTask:           NewSopTaskClient(cfg),
+		Tutorial:          NewTutorialClient(cfg),
+		WorkExperience:    NewWorkExperienceClient(cfg),
 		Wx:                NewWxClient(cfg),
 	}, nil
 }
@@ -215,6 +230,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
 		Agent:             NewAgentClient(cfg),
 		BatchMsg:          NewBatchMsgClient(cfg),
 		Contact:           NewContactClient(cfg),
+		Employee:          NewEmployeeClient(cfg),
 		Label:             NewLabelClient(cfg),
 		LabelRelationship: NewLabelRelationshipClient(cfg),
 		Message:           NewMessageClient(cfg),
@@ -224,6 +240,8 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
 		SopNode:           NewSopNodeClient(cfg),
 		SopStage:          NewSopStageClient(cfg),
 		SopTask:           NewSopTaskClient(cfg),
+		Tutorial:          NewTutorialClient(cfg),
+		WorkExperience:    NewWorkExperienceClient(cfg),
 		Wx:                NewWxClient(cfg),
 	}, nil
 }
@@ -254,8 +272,9 @@ 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.BatchMsg, c.Contact, c.Label, c.LabelRelationship, c.Message,
-		c.MessageRecords, c.Msg, c.Server, c.SopNode, c.SopStage, c.SopTask, c.Wx,
+		c.Agent, c.BatchMsg, c.Contact, c.Employee, c.Label, c.LabelRelationship,
+		c.Message, c.MessageRecords, c.Msg, c.Server, c.SopNode, c.SopStage, c.SopTask,
+		c.Tutorial, c.WorkExperience, c.Wx,
 	} {
 		n.Use(hooks...)
 	}
@@ -265,8 +284,9 @@ 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.BatchMsg, c.Contact, c.Label, c.LabelRelationship, c.Message,
-		c.MessageRecords, c.Msg, c.Server, c.SopNode, c.SopStage, c.SopTask, c.Wx,
+		c.Agent, c.BatchMsg, c.Contact, c.Employee, c.Label, c.LabelRelationship,
+		c.Message, c.MessageRecords, c.Msg, c.Server, c.SopNode, c.SopStage, c.SopTask,
+		c.Tutorial, c.WorkExperience, c.Wx,
 	} {
 		n.Intercept(interceptors...)
 	}
@@ -281,6 +301,8 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
 		return c.BatchMsg.mutate(ctx, m)
 	case *ContactMutation:
 		return c.Contact.mutate(ctx, m)
+	case *EmployeeMutation:
+		return c.Employee.mutate(ctx, m)
 	case *LabelMutation:
 		return c.Label.mutate(ctx, m)
 	case *LabelRelationshipMutation:
@@ -299,6 +321,10 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
 		return c.SopStage.mutate(ctx, m)
 	case *SopTaskMutation:
 		return c.SopTask.mutate(ctx, m)
+	case *TutorialMutation:
+		return c.Tutorial.mutate(ctx, m)
+	case *WorkExperienceMutation:
+		return c.WorkExperience.mutate(ctx, m)
 	case *WxMutation:
 		return c.Wx.mutate(ctx, m)
 	default:
@@ -759,6 +785,173 @@ func (c *ContactClient) mutate(ctx context.Context, m *ContactMutation) (Value,
 	}
 }
 
+// EmployeeClient is a client for the Employee schema.
+type EmployeeClient struct {
+	config
+}
+
+// NewEmployeeClient returns a client for the Employee from the given config.
+func NewEmployeeClient(c config) *EmployeeClient {
+	return &EmployeeClient{config: c}
+}
+
+// Use adds a list of mutation hooks to the hooks stack.
+// A call to `Use(f, g, h)` equals to `employee.Hooks(f(g(h())))`.
+func (c *EmployeeClient) Use(hooks ...Hook) {
+	c.hooks.Employee = append(c.hooks.Employee, hooks...)
+}
+
+// Intercept adds a list of query interceptors to the interceptors stack.
+// A call to `Intercept(f, g, h)` equals to `employee.Intercept(f(g(h())))`.
+func (c *EmployeeClient) Intercept(interceptors ...Interceptor) {
+	c.inters.Employee = append(c.inters.Employee, interceptors...)
+}
+
+// Create returns a builder for creating a Employee entity.
+func (c *EmployeeClient) Create() *EmployeeCreate {
+	mutation := newEmployeeMutation(c.config, OpCreate)
+	return &EmployeeCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// CreateBulk returns a builder for creating a bulk of Employee entities.
+func (c *EmployeeClient) CreateBulk(builders ...*EmployeeCreate) *EmployeeCreateBulk {
+	return &EmployeeCreateBulk{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 *EmployeeClient) MapCreateBulk(slice any, setFunc func(*EmployeeCreate, int)) *EmployeeCreateBulk {
+	rv := reflect.ValueOf(slice)
+	if rv.Kind() != reflect.Slice {
+		return &EmployeeCreateBulk{err: fmt.Errorf("calling to EmployeeClient.MapCreateBulk with wrong type %T, need slice", slice)}
+	}
+	builders := make([]*EmployeeCreate, rv.Len())
+	for i := 0; i < rv.Len(); i++ {
+		builders[i] = c.Create()
+		setFunc(builders[i], i)
+	}
+	return &EmployeeCreateBulk{config: c.config, builders: builders}
+}
+
+// Update returns an update builder for Employee.
+func (c *EmployeeClient) Update() *EmployeeUpdate {
+	mutation := newEmployeeMutation(c.config, OpUpdate)
+	return &EmployeeUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOne returns an update builder for the given entity.
+func (c *EmployeeClient) UpdateOne(e *Employee) *EmployeeUpdateOne {
+	mutation := newEmployeeMutation(c.config, OpUpdateOne, withEmployee(e))
+	return &EmployeeUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOneID returns an update builder for the given id.
+func (c *EmployeeClient) UpdateOneID(id uint64) *EmployeeUpdateOne {
+	mutation := newEmployeeMutation(c.config, OpUpdateOne, withEmployeeID(id))
+	return &EmployeeUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// Delete returns a delete builder for Employee.
+func (c *EmployeeClient) Delete() *EmployeeDelete {
+	mutation := newEmployeeMutation(c.config, OpDelete)
+	return &EmployeeDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// DeleteOne returns a builder for deleting the given entity.
+func (c *EmployeeClient) DeleteOne(e *Employee) *EmployeeDeleteOne {
+	return c.DeleteOneID(e.ID)
+}
+
+// DeleteOneID returns a builder for deleting the given entity by its id.
+func (c *EmployeeClient) DeleteOneID(id uint64) *EmployeeDeleteOne {
+	builder := c.Delete().Where(employee.ID(id))
+	builder.mutation.id = &id
+	builder.mutation.op = OpDeleteOne
+	return &EmployeeDeleteOne{builder}
+}
+
+// Query returns a query builder for Employee.
+func (c *EmployeeClient) Query() *EmployeeQuery {
+	return &EmployeeQuery{
+		config: c.config,
+		ctx:    &QueryContext{Type: TypeEmployee},
+		inters: c.Interceptors(),
+	}
+}
+
+// Get returns a Employee entity by its id.
+func (c *EmployeeClient) Get(ctx context.Context, id uint64) (*Employee, error) {
+	return c.Query().Where(employee.ID(id)).Only(ctx)
+}
+
+// GetX is like Get, but panics if an error occurs.
+func (c *EmployeeClient) GetX(ctx context.Context, id uint64) *Employee {
+	obj, err := c.Get(ctx, id)
+	if err != nil {
+		panic(err)
+	}
+	return obj
+}
+
+// QueryEmWorkExperiences queries the em_work_experiences edge of a Employee.
+func (c *EmployeeClient) QueryEmWorkExperiences(e *Employee) *WorkExperienceQuery {
+	query := (&WorkExperienceClient{config: c.config}).Query()
+	query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+		id := e.ID
+		step := sqlgraph.NewStep(
+			sqlgraph.From(employee.Table, employee.FieldID, id),
+			sqlgraph.To(workexperience.Table, workexperience.FieldID),
+			sqlgraph.Edge(sqlgraph.O2M, false, employee.EmWorkExperiencesTable, employee.EmWorkExperiencesColumn),
+		)
+		fromV = sqlgraph.Neighbors(e.driver.Dialect(), step)
+		return fromV, nil
+	}
+	return query
+}
+
+// QueryEmTutorial queries the em_tutorial edge of a Employee.
+func (c *EmployeeClient) QueryEmTutorial(e *Employee) *TutorialQuery {
+	query := (&TutorialClient{config: c.config}).Query()
+	query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+		id := e.ID
+		step := sqlgraph.NewStep(
+			sqlgraph.From(employee.Table, employee.FieldID, id),
+			sqlgraph.To(tutorial.Table, tutorial.FieldID),
+			sqlgraph.Edge(sqlgraph.O2M, false, employee.EmTutorialTable, employee.EmTutorialColumn),
+		)
+		fromV = sqlgraph.Neighbors(e.driver.Dialect(), step)
+		return fromV, nil
+	}
+	return query
+}
+
+// Hooks returns the client hooks.
+func (c *EmployeeClient) Hooks() []Hook {
+	hooks := c.hooks.Employee
+	return append(hooks[:len(hooks):len(hooks)], employee.Hooks[:]...)
+}
+
+// Interceptors returns the client interceptors.
+func (c *EmployeeClient) Interceptors() []Interceptor {
+	inters := c.inters.Employee
+	return append(inters[:len(inters):len(inters)], employee.Interceptors[:]...)
+}
+
+func (c *EmployeeClient) mutate(ctx context.Context, m *EmployeeMutation) (Value, error) {
+	switch m.Op() {
+	case OpCreate:
+		return (&EmployeeCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdate:
+		return (&EmployeeUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdateOne:
+		return (&EmployeeUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpDelete, OpDeleteOne:
+		return (&EmployeeDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
+	default:
+		return nil, fmt.Errorf("ent: unknown Employee mutation op: %q", m.Op())
+	}
+}
+
 // LabelClient is a client for the Label schema.
 type LabelClient struct {
 	config
@@ -2178,6 +2371,308 @@ func (c *SopTaskClient) mutate(ctx context.Context, m *SopTaskMutation) (Value,
 	}
 }
 
+// TutorialClient is a client for the Tutorial schema.
+type TutorialClient struct {
+	config
+}
+
+// NewTutorialClient returns a client for the Tutorial from the given config.
+func NewTutorialClient(c config) *TutorialClient {
+	return &TutorialClient{config: c}
+}
+
+// Use adds a list of mutation hooks to the hooks stack.
+// A call to `Use(f, g, h)` equals to `tutorial.Hooks(f(g(h())))`.
+func (c *TutorialClient) Use(hooks ...Hook) {
+	c.hooks.Tutorial = append(c.hooks.Tutorial, hooks...)
+}
+
+// Intercept adds a list of query interceptors to the interceptors stack.
+// A call to `Intercept(f, g, h)` equals to `tutorial.Intercept(f(g(h())))`.
+func (c *TutorialClient) Intercept(interceptors ...Interceptor) {
+	c.inters.Tutorial = append(c.inters.Tutorial, interceptors...)
+}
+
+// Create returns a builder for creating a Tutorial entity.
+func (c *TutorialClient) Create() *TutorialCreate {
+	mutation := newTutorialMutation(c.config, OpCreate)
+	return &TutorialCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// CreateBulk returns a builder for creating a bulk of Tutorial entities.
+func (c *TutorialClient) CreateBulk(builders ...*TutorialCreate) *TutorialCreateBulk {
+	return &TutorialCreateBulk{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 *TutorialClient) MapCreateBulk(slice any, setFunc func(*TutorialCreate, int)) *TutorialCreateBulk {
+	rv := reflect.ValueOf(slice)
+	if rv.Kind() != reflect.Slice {
+		return &TutorialCreateBulk{err: fmt.Errorf("calling to TutorialClient.MapCreateBulk with wrong type %T, need slice", slice)}
+	}
+	builders := make([]*TutorialCreate, rv.Len())
+	for i := 0; i < rv.Len(); i++ {
+		builders[i] = c.Create()
+		setFunc(builders[i], i)
+	}
+	return &TutorialCreateBulk{config: c.config, builders: builders}
+}
+
+// Update returns an update builder for Tutorial.
+func (c *TutorialClient) Update() *TutorialUpdate {
+	mutation := newTutorialMutation(c.config, OpUpdate)
+	return &TutorialUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOne returns an update builder for the given entity.
+func (c *TutorialClient) UpdateOne(t *Tutorial) *TutorialUpdateOne {
+	mutation := newTutorialMutation(c.config, OpUpdateOne, withTutorial(t))
+	return &TutorialUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOneID returns an update builder for the given id.
+func (c *TutorialClient) UpdateOneID(id uint64) *TutorialUpdateOne {
+	mutation := newTutorialMutation(c.config, OpUpdateOne, withTutorialID(id))
+	return &TutorialUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// Delete returns a delete builder for Tutorial.
+func (c *TutorialClient) Delete() *TutorialDelete {
+	mutation := newTutorialMutation(c.config, OpDelete)
+	return &TutorialDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// DeleteOne returns a builder for deleting the given entity.
+func (c *TutorialClient) DeleteOne(t *Tutorial) *TutorialDeleteOne {
+	return c.DeleteOneID(t.ID)
+}
+
+// DeleteOneID returns a builder for deleting the given entity by its id.
+func (c *TutorialClient) DeleteOneID(id uint64) *TutorialDeleteOne {
+	builder := c.Delete().Where(tutorial.ID(id))
+	builder.mutation.id = &id
+	builder.mutation.op = OpDeleteOne
+	return &TutorialDeleteOne{builder}
+}
+
+// Query returns a query builder for Tutorial.
+func (c *TutorialClient) Query() *TutorialQuery {
+	return &TutorialQuery{
+		config: c.config,
+		ctx:    &QueryContext{Type: TypeTutorial},
+		inters: c.Interceptors(),
+	}
+}
+
+// Get returns a Tutorial entity by its id.
+func (c *TutorialClient) Get(ctx context.Context, id uint64) (*Tutorial, error) {
+	return c.Query().Where(tutorial.ID(id)).Only(ctx)
+}
+
+// GetX is like Get, but panics if an error occurs.
+func (c *TutorialClient) GetX(ctx context.Context, id uint64) *Tutorial {
+	obj, err := c.Get(ctx, id)
+	if err != nil {
+		panic(err)
+	}
+	return obj
+}
+
+// QueryEmployee queries the employee edge of a Tutorial.
+func (c *TutorialClient) QueryEmployee(t *Tutorial) *EmployeeQuery {
+	query := (&EmployeeClient{config: c.config}).Query()
+	query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+		id := t.ID
+		step := sqlgraph.NewStep(
+			sqlgraph.From(tutorial.Table, tutorial.FieldID, id),
+			sqlgraph.To(employee.Table, employee.FieldID),
+			sqlgraph.Edge(sqlgraph.M2O, true, tutorial.EmployeeTable, tutorial.EmployeeColumn),
+		)
+		fromV = sqlgraph.Neighbors(t.driver.Dialect(), step)
+		return fromV, nil
+	}
+	return query
+}
+
+// Hooks returns the client hooks.
+func (c *TutorialClient) Hooks() []Hook {
+	hooks := c.hooks.Tutorial
+	return append(hooks[:len(hooks):len(hooks)], tutorial.Hooks[:]...)
+}
+
+// Interceptors returns the client interceptors.
+func (c *TutorialClient) Interceptors() []Interceptor {
+	inters := c.inters.Tutorial
+	return append(inters[:len(inters):len(inters)], tutorial.Interceptors[:]...)
+}
+
+func (c *TutorialClient) mutate(ctx context.Context, m *TutorialMutation) (Value, error) {
+	switch m.Op() {
+	case OpCreate:
+		return (&TutorialCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdate:
+		return (&TutorialUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdateOne:
+		return (&TutorialUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpDelete, OpDeleteOne:
+		return (&TutorialDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
+	default:
+		return nil, fmt.Errorf("ent: unknown Tutorial mutation op: %q", m.Op())
+	}
+}
+
+// WorkExperienceClient is a client for the WorkExperience schema.
+type WorkExperienceClient struct {
+	config
+}
+
+// NewWorkExperienceClient returns a client for the WorkExperience from the given config.
+func NewWorkExperienceClient(c config) *WorkExperienceClient {
+	return &WorkExperienceClient{config: c}
+}
+
+// Use adds a list of mutation hooks to the hooks stack.
+// A call to `Use(f, g, h)` equals to `workexperience.Hooks(f(g(h())))`.
+func (c *WorkExperienceClient) Use(hooks ...Hook) {
+	c.hooks.WorkExperience = append(c.hooks.WorkExperience, hooks...)
+}
+
+// Intercept adds a list of query interceptors to the interceptors stack.
+// A call to `Intercept(f, g, h)` equals to `workexperience.Intercept(f(g(h())))`.
+func (c *WorkExperienceClient) Intercept(interceptors ...Interceptor) {
+	c.inters.WorkExperience = append(c.inters.WorkExperience, interceptors...)
+}
+
+// Create returns a builder for creating a WorkExperience entity.
+func (c *WorkExperienceClient) Create() *WorkExperienceCreate {
+	mutation := newWorkExperienceMutation(c.config, OpCreate)
+	return &WorkExperienceCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// CreateBulk returns a builder for creating a bulk of WorkExperience entities.
+func (c *WorkExperienceClient) CreateBulk(builders ...*WorkExperienceCreate) *WorkExperienceCreateBulk {
+	return &WorkExperienceCreateBulk{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 *WorkExperienceClient) MapCreateBulk(slice any, setFunc func(*WorkExperienceCreate, int)) *WorkExperienceCreateBulk {
+	rv := reflect.ValueOf(slice)
+	if rv.Kind() != reflect.Slice {
+		return &WorkExperienceCreateBulk{err: fmt.Errorf("calling to WorkExperienceClient.MapCreateBulk with wrong type %T, need slice", slice)}
+	}
+	builders := make([]*WorkExperienceCreate, rv.Len())
+	for i := 0; i < rv.Len(); i++ {
+		builders[i] = c.Create()
+		setFunc(builders[i], i)
+	}
+	return &WorkExperienceCreateBulk{config: c.config, builders: builders}
+}
+
+// Update returns an update builder for WorkExperience.
+func (c *WorkExperienceClient) Update() *WorkExperienceUpdate {
+	mutation := newWorkExperienceMutation(c.config, OpUpdate)
+	return &WorkExperienceUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOne returns an update builder for the given entity.
+func (c *WorkExperienceClient) UpdateOne(we *WorkExperience) *WorkExperienceUpdateOne {
+	mutation := newWorkExperienceMutation(c.config, OpUpdateOne, withWorkExperience(we))
+	return &WorkExperienceUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOneID returns an update builder for the given id.
+func (c *WorkExperienceClient) UpdateOneID(id uint64) *WorkExperienceUpdateOne {
+	mutation := newWorkExperienceMutation(c.config, OpUpdateOne, withWorkExperienceID(id))
+	return &WorkExperienceUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// Delete returns a delete builder for WorkExperience.
+func (c *WorkExperienceClient) Delete() *WorkExperienceDelete {
+	mutation := newWorkExperienceMutation(c.config, OpDelete)
+	return &WorkExperienceDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// DeleteOne returns a builder for deleting the given entity.
+func (c *WorkExperienceClient) DeleteOne(we *WorkExperience) *WorkExperienceDeleteOne {
+	return c.DeleteOneID(we.ID)
+}
+
+// DeleteOneID returns a builder for deleting the given entity by its id.
+func (c *WorkExperienceClient) DeleteOneID(id uint64) *WorkExperienceDeleteOne {
+	builder := c.Delete().Where(workexperience.ID(id))
+	builder.mutation.id = &id
+	builder.mutation.op = OpDeleteOne
+	return &WorkExperienceDeleteOne{builder}
+}
+
+// Query returns a query builder for WorkExperience.
+func (c *WorkExperienceClient) Query() *WorkExperienceQuery {
+	return &WorkExperienceQuery{
+		config: c.config,
+		ctx:    &QueryContext{Type: TypeWorkExperience},
+		inters: c.Interceptors(),
+	}
+}
+
+// Get returns a WorkExperience entity by its id.
+func (c *WorkExperienceClient) Get(ctx context.Context, id uint64) (*WorkExperience, error) {
+	return c.Query().Where(workexperience.ID(id)).Only(ctx)
+}
+
+// GetX is like Get, but panics if an error occurs.
+func (c *WorkExperienceClient) GetX(ctx context.Context, id uint64) *WorkExperience {
+	obj, err := c.Get(ctx, id)
+	if err != nil {
+		panic(err)
+	}
+	return obj
+}
+
+// QueryEmployee queries the employee edge of a WorkExperience.
+func (c *WorkExperienceClient) QueryEmployee(we *WorkExperience) *EmployeeQuery {
+	query := (&EmployeeClient{config: c.config}).Query()
+	query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+		id := we.ID
+		step := sqlgraph.NewStep(
+			sqlgraph.From(workexperience.Table, workexperience.FieldID, id),
+			sqlgraph.To(employee.Table, employee.FieldID),
+			sqlgraph.Edge(sqlgraph.M2O, true, workexperience.EmployeeTable, workexperience.EmployeeColumn),
+		)
+		fromV = sqlgraph.Neighbors(we.driver.Dialect(), step)
+		return fromV, nil
+	}
+	return query
+}
+
+// Hooks returns the client hooks.
+func (c *WorkExperienceClient) Hooks() []Hook {
+	hooks := c.hooks.WorkExperience
+	return append(hooks[:len(hooks):len(hooks)], workexperience.Hooks[:]...)
+}
+
+// Interceptors returns the client interceptors.
+func (c *WorkExperienceClient) Interceptors() []Interceptor {
+	inters := c.inters.WorkExperience
+	return append(inters[:len(inters):len(inters)], workexperience.Interceptors[:]...)
+}
+
+func (c *WorkExperienceClient) mutate(ctx context.Context, m *WorkExperienceMutation) (Value, error) {
+	switch m.Op() {
+	case OpCreate:
+		return (&WorkExperienceCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdate:
+		return (&WorkExperienceUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpUpdateOne:
+		return (&WorkExperienceUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+	case OpDelete, OpDeleteOne:
+		return (&WorkExperienceDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
+	default:
+		return nil, fmt.Errorf("ent: unknown WorkExperience mutation op: %q", m.Op())
+	}
+}
+
 // WxClient is a client for the Wx schema.
 type WxClient struct {
 	config
@@ -2348,12 +2843,14 @@ func (c *WxClient) mutate(ctx context.Context, m *WxMutation) (Value, error) {
 // hooks and interceptors per client, for fast access.
 type (
 	hooks struct {
-		Agent, BatchMsg, Contact, Label, LabelRelationship, Message, MessageRecords,
-		Msg, Server, SopNode, SopStage, SopTask, Wx []ent.Hook
+		Agent, BatchMsg, Contact, Employee, Label, LabelRelationship, Message,
+		MessageRecords, Msg, Server, SopNode, SopStage, SopTask, Tutorial,
+		WorkExperience, Wx []ent.Hook
 	}
 	inters struct {
-		Agent, BatchMsg, Contact, Label, LabelRelationship, Message, MessageRecords,
-		Msg, Server, SopNode, SopStage, SopTask, Wx []ent.Interceptor
+		Agent, BatchMsg, Contact, Employee, Label, LabelRelationship, Message,
+		MessageRecords, Msg, Server, SopNode, SopStage, SopTask, Tutorial,
+		WorkExperience, Wx []ent.Interceptor
 	}
 )
 

+ 324 - 0
ent/employee.go

@@ -0,0 +1,324 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"fmt"
+	"strings"
+	"time"
+	"wechat-api/ent/employee"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+)
+
+// Employee is the model entity for the Employee schema.
+type Employee 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"`
+	// title | 标题
+	Title string `json:"title,omitempty"`
+	// avatar | 头像
+	Avatar string `json:"avatar,omitempty"`
+	// tags | 个人标签
+	Tags string `json:"tags,omitempty"`
+	// hire_count | 被雇佣次数
+	HireCount int `json:"hire_count,omitempty"`
+	// service_count | 已服务次数
+	ServiceCount int `json:"service_count,omitempty"`
+	// achievement_count | 业绩单数
+	AchievementCount int `json:"achievement_count,omitempty"`
+	// intro | 个人介绍
+	Intro string `json:"intro,omitempty"`
+	// estimate | 自我评价
+	Estimate string `json:"estimate,omitempty"`
+	// skill | 技能卡
+	Skill string `json:"skill,omitempty"`
+	// ability_type | 能力类型
+	AbilityType string `json:"ability_type,omitempty"`
+	// scene | 使用场景
+	Scene string `json:"scene,omitempty"`
+	// switch_in | 支持介入
+	SwitchIn string `json:"switch_in,omitempty"`
+	// video_url | 视频地址
+	VideoURL string `json:"video_url,omitempty"`
+	// organization_id | 租户ID
+	OrganizationID uint64 `json:"organization_id,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"`
+	selectValues sql.SelectValues
+}
+
+// EmployeeEdges holds the relations/edges for other nodes in the graph.
+type EmployeeEdges struct {
+	// EmWorkExperiences holds the value of the em_work_experiences edge.
+	EmWorkExperiences []*WorkExperience `json:"em_work_experiences,omitempty"`
+	// EmTutorial holds the value of the em_tutorial edge.
+	EmTutorial []*Tutorial `json:"em_tutorial,omitempty"`
+	// loadedTypes holds the information for reporting if a
+	// type was loaded (or requested) in eager-loading or not.
+	loadedTypes [2]bool
+}
+
+// EmWorkExperiencesOrErr returns the EmWorkExperiences value or an error if the edge
+// was not loaded in eager-loading.
+func (e EmployeeEdges) EmWorkExperiencesOrErr() ([]*WorkExperience, error) {
+	if e.loadedTypes[0] {
+		return e.EmWorkExperiences, nil
+	}
+	return nil, &NotLoadedError{edge: "em_work_experiences"}
+}
+
+// EmTutorialOrErr returns the EmTutorial value or an error if the edge
+// was not loaded in eager-loading.
+func (e EmployeeEdges) EmTutorialOrErr() ([]*Tutorial, error) {
+	if e.loadedTypes[1] {
+		return e.EmTutorial, nil
+	}
+	return nil, &NotLoadedError{edge: "em_tutorial"}
+}
+
+// scanValues returns the types for scanning values from sql.Rows.
+func (*Employee) scanValues(columns []string) ([]any, error) {
+	values := make([]any, len(columns))
+	for i := range columns {
+		switch columns[i] {
+		case employee.FieldID, employee.FieldHireCount, employee.FieldServiceCount, employee.FieldAchievementCount, employee.FieldOrganizationID:
+			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:
+			values[i] = new(sql.NullString)
+		case employee.FieldCreatedAt, employee.FieldUpdatedAt, employee.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 Employee fields.
+func (e *Employee) 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 employee.FieldID:
+			value, ok := values[i].(*sql.NullInt64)
+			if !ok {
+				return fmt.Errorf("unexpected type %T for field id", value)
+			}
+			e.ID = uint64(value.Int64)
+		case employee.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 {
+				e.CreatedAt = value.Time
+			}
+		case employee.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 {
+				e.UpdatedAt = value.Time
+			}
+		case employee.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 {
+				e.DeletedAt = value.Time
+			}
+		case employee.FieldTitle:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field title", values[i])
+			} else if value.Valid {
+				e.Title = value.String
+			}
+		case employee.FieldAvatar:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field avatar", values[i])
+			} else if value.Valid {
+				e.Avatar = value.String
+			}
+		case employee.FieldTags:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field tags", values[i])
+			} else if value.Valid {
+				e.Tags = value.String
+			}
+		case employee.FieldHireCount:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field hire_count", values[i])
+			} else if value.Valid {
+				e.HireCount = int(value.Int64)
+			}
+		case employee.FieldServiceCount:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field service_count", values[i])
+			} else if value.Valid {
+				e.ServiceCount = int(value.Int64)
+			}
+		case employee.FieldAchievementCount:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field achievement_count", values[i])
+			} else if value.Valid {
+				e.AchievementCount = int(value.Int64)
+			}
+		case employee.FieldIntro:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field intro", values[i])
+			} else if value.Valid {
+				e.Intro = value.String
+			}
+		case employee.FieldEstimate:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field estimate", values[i])
+			} else if value.Valid {
+				e.Estimate = value.String
+			}
+		case employee.FieldSkill:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field skill", values[i])
+			} else if value.Valid {
+				e.Skill = value.String
+			}
+		case employee.FieldAbilityType:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field ability_type", values[i])
+			} else if value.Valid {
+				e.AbilityType = value.String
+			}
+		case employee.FieldScene:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field scene", values[i])
+			} else if value.Valid {
+				e.Scene = value.String
+			}
+		case employee.FieldSwitchIn:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field switch_in", values[i])
+			} else if value.Valid {
+				e.SwitchIn = value.String
+			}
+		case employee.FieldVideoURL:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field video_url", values[i])
+			} else if value.Valid {
+				e.VideoURL = value.String
+			}
+		case employee.FieldOrganizationID:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field organization_id", values[i])
+			} else if value.Valid {
+				e.OrganizationID = uint64(value.Int64)
+			}
+		default:
+			e.selectValues.Set(columns[i], values[i])
+		}
+	}
+	return nil
+}
+
+// Value returns the ent.Value that was dynamically selected and assigned to the Employee.
+// This includes values selected through modifiers, order, etc.
+func (e *Employee) Value(name string) (ent.Value, error) {
+	return e.selectValues.Get(name)
+}
+
+// QueryEmWorkExperiences queries the "em_work_experiences" edge of the Employee entity.
+func (e *Employee) QueryEmWorkExperiences() *WorkExperienceQuery {
+	return NewEmployeeClient(e.config).QueryEmWorkExperiences(e)
+}
+
+// QueryEmTutorial queries the "em_tutorial" edge of the Employee entity.
+func (e *Employee) QueryEmTutorial() *TutorialQuery {
+	return NewEmployeeClient(e.config).QueryEmTutorial(e)
+}
+
+// Update returns a builder for updating this Employee.
+// Note that you need to call Employee.Unwrap() before calling this method if this Employee
+// was returned from a transaction, and the transaction was committed or rolled back.
+func (e *Employee) Update() *EmployeeUpdateOne {
+	return NewEmployeeClient(e.config).UpdateOne(e)
+}
+
+// Unwrap unwraps the Employee 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 (e *Employee) Unwrap() *Employee {
+	_tx, ok := e.config.driver.(*txDriver)
+	if !ok {
+		panic("ent: Employee is not a transactional entity")
+	}
+	e.config.driver = _tx.drv
+	return e
+}
+
+// String implements the fmt.Stringer.
+func (e *Employee) String() string {
+	var builder strings.Builder
+	builder.WriteString("Employee(")
+	builder.WriteString(fmt.Sprintf("id=%v, ", e.ID))
+	builder.WriteString("created_at=")
+	builder.WriteString(e.CreatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("updated_at=")
+	builder.WriteString(e.UpdatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("deleted_at=")
+	builder.WriteString(e.DeletedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("title=")
+	builder.WriteString(e.Title)
+	builder.WriteString(", ")
+	builder.WriteString("avatar=")
+	builder.WriteString(e.Avatar)
+	builder.WriteString(", ")
+	builder.WriteString("tags=")
+	builder.WriteString(e.Tags)
+	builder.WriteString(", ")
+	builder.WriteString("hire_count=")
+	builder.WriteString(fmt.Sprintf("%v", e.HireCount))
+	builder.WriteString(", ")
+	builder.WriteString("service_count=")
+	builder.WriteString(fmt.Sprintf("%v", e.ServiceCount))
+	builder.WriteString(", ")
+	builder.WriteString("achievement_count=")
+	builder.WriteString(fmt.Sprintf("%v", e.AchievementCount))
+	builder.WriteString(", ")
+	builder.WriteString("intro=")
+	builder.WriteString(e.Intro)
+	builder.WriteString(", ")
+	builder.WriteString("estimate=")
+	builder.WriteString(e.Estimate)
+	builder.WriteString(", ")
+	builder.WriteString("skill=")
+	builder.WriteString(e.Skill)
+	builder.WriteString(", ")
+	builder.WriteString("ability_type=")
+	builder.WriteString(e.AbilityType)
+	builder.WriteString(", ")
+	builder.WriteString("scene=")
+	builder.WriteString(e.Scene)
+	builder.WriteString(", ")
+	builder.WriteString("switch_in=")
+	builder.WriteString(e.SwitchIn)
+	builder.WriteString(", ")
+	builder.WriteString("video_url=")
+	builder.WriteString(e.VideoURL)
+	builder.WriteString(", ")
+	builder.WriteString("organization_id=")
+	builder.WriteString(fmt.Sprintf("%v", e.OrganizationID))
+	builder.WriteByte(')')
+	return builder.String()
+}
+
+// Employees is a parsable slice of Employee.
+type Employees []*Employee

+ 297 - 0
ent/employee/employee.go

@@ -0,0 +1,297 @@
+// Code generated by ent, DO NOT EDIT.
+
+package employee
+
+import (
+	"time"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+)
+
+const (
+	// Label holds the string label denoting the employee type in the database.
+	Label = "employee"
+	// 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"
+	// FieldTitle holds the string denoting the title field in the database.
+	FieldTitle = "title"
+	// FieldAvatar holds the string denoting the avatar field in the database.
+	FieldAvatar = "avatar"
+	// FieldTags holds the string denoting the tags field in the database.
+	FieldTags = "tags"
+	// FieldHireCount holds the string denoting the hire_count field in the database.
+	FieldHireCount = "hire_count"
+	// FieldServiceCount holds the string denoting the service_count field in the database.
+	FieldServiceCount = "service_count"
+	// FieldAchievementCount holds the string denoting the achievement_count field in the database.
+	FieldAchievementCount = "achievement_count"
+	// FieldIntro holds the string denoting the intro field in the database.
+	FieldIntro = "intro"
+	// FieldEstimate holds the string denoting the estimate field in the database.
+	FieldEstimate = "estimate"
+	// FieldSkill holds the string denoting the skill field in the database.
+	FieldSkill = "skill"
+	// FieldAbilityType holds the string denoting the ability_type field in the database.
+	FieldAbilityType = "ability_type"
+	// FieldScene holds the string denoting the scene field in the database.
+	FieldScene = "scene"
+	// FieldSwitchIn holds the string denoting the switch_in field in the database.
+	FieldSwitchIn = "switch_in"
+	// FieldVideoURL holds the string denoting the video_url field in the database.
+	FieldVideoURL = "video_url"
+	// FieldOrganizationID holds the string denoting the organization_id field in the database.
+	FieldOrganizationID = "organization_id"
+	// 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.
+	EdgeEmTutorial = "em_tutorial"
+	// Table holds the table name of the employee in the database.
+	Table = "employee"
+	// EmWorkExperiencesTable is the table that holds the em_work_experiences relation/edge.
+	EmWorkExperiencesTable = "work_experience"
+	// EmWorkExperiencesInverseTable is the table name for the WorkExperience entity.
+	// It exists in this package in order to avoid circular dependency with the "workexperience" package.
+	EmWorkExperiencesInverseTable = "work_experience"
+	// EmWorkExperiencesColumn is the table column denoting the em_work_experiences relation/edge.
+	EmWorkExperiencesColumn = "employee_id"
+	// EmTutorialTable is the table that holds the em_tutorial relation/edge.
+	EmTutorialTable = "tutorial"
+	// EmTutorialInverseTable is the table name for the Tutorial entity.
+	// It exists in this package in order to avoid circular dependency with the "tutorial" package.
+	EmTutorialInverseTable = "tutorial"
+	// EmTutorialColumn is the table column denoting the em_tutorial relation/edge.
+	EmTutorialColumn = "employee_id"
+)
+
+// Columns holds all SQL columns for employee fields.
+var Columns = []string{
+	FieldID,
+	FieldCreatedAt,
+	FieldUpdatedAt,
+	FieldDeletedAt,
+	FieldTitle,
+	FieldAvatar,
+	FieldTags,
+	FieldHireCount,
+	FieldServiceCount,
+	FieldAchievementCount,
+	FieldIntro,
+	FieldEstimate,
+	FieldSkill,
+	FieldAbilityType,
+	FieldScene,
+	FieldSwitchIn,
+	FieldVideoURL,
+	FieldOrganizationID,
+}
+
+// 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
+	// TitleValidator is a validator for the "title" field. It is called by the builders before save.
+	TitleValidator func(string) error
+	// AvatarValidator is a validator for the "avatar" field. It is called by the builders before save.
+	AvatarValidator func(string) error
+	// TagsValidator is a validator for the "tags" field. It is called by the builders before save.
+	TagsValidator func(string) error
+	// DefaultHireCount holds the default value on creation for the "hire_count" field.
+	DefaultHireCount int
+	// HireCountValidator is a validator for the "hire_count" field. It is called by the builders before save.
+	HireCountValidator func(int) error
+	// DefaultServiceCount holds the default value on creation for the "service_count" field.
+	DefaultServiceCount int
+	// ServiceCountValidator is a validator for the "service_count" field. It is called by the builders before save.
+	ServiceCountValidator func(int) error
+	// DefaultAchievementCount holds the default value on creation for the "achievement_count" field.
+	DefaultAchievementCount int
+	// AchievementCountValidator is a validator for the "achievement_count" field. It is called by the builders before save.
+	AchievementCountValidator func(int) error
+	// DefaultIntro holds the default value on creation for the "intro" field.
+	DefaultIntro string
+	// IntroValidator is a validator for the "intro" field. It is called by the builders before save.
+	IntroValidator func(string) error
+	// DefaultEstimate holds the default value on creation for the "estimate" field.
+	DefaultEstimate string
+	// EstimateValidator is a validator for the "estimate" field. It is called by the builders before save.
+	EstimateValidator func(string) error
+	// DefaultSkill holds the default value on creation for the "skill" field.
+	DefaultSkill string
+	// SkillValidator is a validator for the "skill" field. It is called by the builders before save.
+	SkillValidator func(string) error
+	// DefaultAbilityType holds the default value on creation for the "ability_type" field.
+	DefaultAbilityType string
+	// DefaultScene holds the default value on creation for the "scene" field.
+	DefaultScene string
+	// DefaultSwitchIn holds the default value on creation for the "switch_in" field.
+	DefaultSwitchIn string
+	// DefaultVideoURL holds the default value on creation for the "video_url" field.
+	DefaultVideoURL string
+	// VideoURLValidator is a validator for the "video_url" field. It is called by the builders before save.
+	VideoURLValidator func(string) error
+	// OrganizationIDValidator is a validator for the "organization_id" field. It is called by the builders before save.
+	OrganizationIDValidator func(uint64) error
+)
+
+// OrderOption defines the ordering options for the Employee 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()
+}
+
+// ByTitle orders the results by the title field.
+func ByTitle(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldTitle, opts...).ToFunc()
+}
+
+// ByAvatar orders the results by the avatar field.
+func ByAvatar(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldAvatar, opts...).ToFunc()
+}
+
+// ByTags orders the results by the tags field.
+func ByTags(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldTags, opts...).ToFunc()
+}
+
+// ByHireCount orders the results by the hire_count field.
+func ByHireCount(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldHireCount, opts...).ToFunc()
+}
+
+// ByServiceCount orders the results by the service_count field.
+func ByServiceCount(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldServiceCount, opts...).ToFunc()
+}
+
+// ByAchievementCount orders the results by the achievement_count field.
+func ByAchievementCount(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldAchievementCount, opts...).ToFunc()
+}
+
+// ByIntro orders the results by the intro field.
+func ByIntro(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldIntro, opts...).ToFunc()
+}
+
+// ByEstimate orders the results by the estimate field.
+func ByEstimate(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldEstimate, opts...).ToFunc()
+}
+
+// BySkill orders the results by the skill field.
+func BySkill(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldSkill, opts...).ToFunc()
+}
+
+// ByAbilityType orders the results by the ability_type field.
+func ByAbilityType(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldAbilityType, opts...).ToFunc()
+}
+
+// ByScene orders the results by the scene field.
+func ByScene(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldScene, opts...).ToFunc()
+}
+
+// BySwitchIn orders the results by the switch_in field.
+func BySwitchIn(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldSwitchIn, opts...).ToFunc()
+}
+
+// ByVideoURL orders the results by the video_url field.
+func ByVideoURL(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldVideoURL, opts...).ToFunc()
+}
+
+// ByOrganizationID orders the results by the organization_id field.
+func ByOrganizationID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldOrganizationID, opts...).ToFunc()
+}
+
+// ByEmWorkExperiencesCount orders the results by em_work_experiences count.
+func ByEmWorkExperiencesCount(opts ...sql.OrderTermOption) OrderOption {
+	return func(s *sql.Selector) {
+		sqlgraph.OrderByNeighborsCount(s, newEmWorkExperiencesStep(), opts...)
+	}
+}
+
+// ByEmWorkExperiences orders the results by em_work_experiences terms.
+func ByEmWorkExperiences(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
+	return func(s *sql.Selector) {
+		sqlgraph.OrderByNeighborTerms(s, newEmWorkExperiencesStep(), append([]sql.OrderTerm{term}, terms...)...)
+	}
+}
+
+// ByEmTutorialCount orders the results by em_tutorial count.
+func ByEmTutorialCount(opts ...sql.OrderTermOption) OrderOption {
+	return func(s *sql.Selector) {
+		sqlgraph.OrderByNeighborsCount(s, newEmTutorialStep(), opts...)
+	}
+}
+
+// ByEmTutorial orders the results by em_tutorial terms.
+func ByEmTutorial(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
+	return func(s *sql.Selector) {
+		sqlgraph.OrderByNeighborTerms(s, newEmTutorialStep(), append([]sql.OrderTerm{term}, terms...)...)
+	}
+}
+func newEmWorkExperiencesStep() *sqlgraph.Step {
+	return sqlgraph.NewStep(
+		sqlgraph.From(Table, FieldID),
+		sqlgraph.To(EmWorkExperiencesInverseTable, FieldID),
+		sqlgraph.Edge(sqlgraph.O2M, false, EmWorkExperiencesTable, EmWorkExperiencesColumn),
+	)
+}
+func newEmTutorialStep() *sqlgraph.Step {
+	return sqlgraph.NewStep(
+		sqlgraph.From(Table, FieldID),
+		sqlgraph.To(EmTutorialInverseTable, FieldID),
+		sqlgraph.Edge(sqlgraph.O2M, false, EmTutorialTable, EmTutorialColumn),
+	)
+}

+ 1142 - 0
ent/employee/where.go

@@ -0,0 +1,1142 @@
+// Code generated by ent, DO NOT EDIT.
+
+package employee
+
+import (
+	"time"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+)
+
+// ID filters vertices based on their ID field.
+func ID(id uint64) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldID, id))
+}
+
+// IDEQ applies the EQ predicate on the ID field.
+func IDEQ(id uint64) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldID, id))
+}
+
+// IDNEQ applies the NEQ predicate on the ID field.
+func IDNEQ(id uint64) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldID, id))
+}
+
+// IDIn applies the In predicate on the ID field.
+func IDIn(ids ...uint64) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldID, ids...))
+}
+
+// IDNotIn applies the NotIn predicate on the ID field.
+func IDNotIn(ids ...uint64) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldID, ids...))
+}
+
+// IDGT applies the GT predicate on the ID field.
+func IDGT(id uint64) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldID, id))
+}
+
+// IDGTE applies the GTE predicate on the ID field.
+func IDGTE(id uint64) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldID, id))
+}
+
+// IDLT applies the LT predicate on the ID field.
+func IDLT(id uint64) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldID, id))
+}
+
+// IDLTE applies the LTE predicate on the ID field.
+func IDLTE(id uint64) predicate.Employee {
+	return predicate.Employee(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.Employee {
+	return predicate.Employee(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.Employee {
+	return predicate.Employee(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.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// Title applies equality check predicate on the "title" field. It's identical to TitleEQ.
+func Title(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldTitle, v))
+}
+
+// Avatar applies equality check predicate on the "avatar" field. It's identical to AvatarEQ.
+func Avatar(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldAvatar, v))
+}
+
+// Tags applies equality check predicate on the "tags" field. It's identical to TagsEQ.
+func Tags(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldTags, v))
+}
+
+// HireCount applies equality check predicate on the "hire_count" field. It's identical to HireCountEQ.
+func HireCount(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldHireCount, v))
+}
+
+// ServiceCount applies equality check predicate on the "service_count" field. It's identical to ServiceCountEQ.
+func ServiceCount(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldServiceCount, v))
+}
+
+// AchievementCount applies equality check predicate on the "achievement_count" field. It's identical to AchievementCountEQ.
+func AchievementCount(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldAchievementCount, v))
+}
+
+// Intro applies equality check predicate on the "intro" field. It's identical to IntroEQ.
+func Intro(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldIntro, v))
+}
+
+// Estimate applies equality check predicate on the "estimate" field. It's identical to EstimateEQ.
+func Estimate(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldEstimate, v))
+}
+
+// Skill applies equality check predicate on the "skill" field. It's identical to SkillEQ.
+func Skill(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldSkill, v))
+}
+
+// AbilityType applies equality check predicate on the "ability_type" field. It's identical to AbilityTypeEQ.
+func AbilityType(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldAbilityType, v))
+}
+
+// Scene applies equality check predicate on the "scene" field. It's identical to SceneEQ.
+func Scene(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldScene, v))
+}
+
+// SwitchIn applies equality check predicate on the "switch_in" field. It's identical to SwitchInEQ.
+func SwitchIn(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldSwitchIn, v))
+}
+
+// VideoURL applies equality check predicate on the "video_url" field. It's identical to VideoURLEQ.
+func VideoURL(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldVideoURL, v))
+}
+
+// OrganizationID applies equality check predicate on the "organization_id" field. It's identical to OrganizationIDEQ.
+func OrganizationID(v uint64) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldOrganizationID, 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))
+}
+
+// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
+func CreatedAtNEQ(v time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtIn applies the In predicate on the "created_at" field.
+func CreatedAtIn(vs ...time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
+func CreatedAtNotIn(vs ...time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtGT applies the GT predicate on the "created_at" field.
+func CreatedAtGT(v time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldCreatedAt, v))
+}
+
+// CreatedAtGTE applies the GTE predicate on the "created_at" field.
+func CreatedAtGTE(v time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldCreatedAt, v))
+}
+
+// CreatedAtLT applies the LT predicate on the "created_at" field.
+func CreatedAtLT(v time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldCreatedAt, v))
+}
+
+// CreatedAtLTE applies the LTE predicate on the "created_at" field.
+func CreatedAtLTE(v time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldCreatedAt, v))
+}
+
+// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
+func UpdatedAtEQ(v time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
+func UpdatedAtNEQ(v time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtIn applies the In predicate on the "updated_at" field.
+func UpdatedAtIn(vs ...time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
+func UpdatedAtNotIn(vs ...time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtGT applies the GT predicate on the "updated_at" field.
+func UpdatedAtGT(v time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
+func UpdatedAtGTE(v time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLT applies the LT predicate on the "updated_at" field.
+func UpdatedAtLT(v time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
+func UpdatedAtLTE(v time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldUpdatedAt, v))
+}
+
+// DeletedAtEQ applies the EQ predicate on the "deleted_at" field.
+func DeletedAtEQ(v time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field.
+func DeletedAtNEQ(v time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtIn applies the In predicate on the "deleted_at" field.
+func DeletedAtIn(vs ...time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field.
+func DeletedAtNotIn(vs ...time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtGT applies the GT predicate on the "deleted_at" field.
+func DeletedAtGT(v time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldDeletedAt, v))
+}
+
+// DeletedAtGTE applies the GTE predicate on the "deleted_at" field.
+func DeletedAtGTE(v time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldDeletedAt, v))
+}
+
+// DeletedAtLT applies the LT predicate on the "deleted_at" field.
+func DeletedAtLT(v time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldDeletedAt, v))
+}
+
+// DeletedAtLTE applies the LTE predicate on the "deleted_at" field.
+func DeletedAtLTE(v time.Time) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldDeletedAt, v))
+}
+
+// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field.
+func DeletedAtIsNil() predicate.Employee {
+	return predicate.Employee(sql.FieldIsNull(FieldDeletedAt))
+}
+
+// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field.
+func DeletedAtNotNil() predicate.Employee {
+	return predicate.Employee(sql.FieldNotNull(FieldDeletedAt))
+}
+
+// TitleEQ applies the EQ predicate on the "title" field.
+func TitleEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldTitle, v))
+}
+
+// TitleNEQ applies the NEQ predicate on the "title" field.
+func TitleNEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldTitle, v))
+}
+
+// TitleIn applies the In predicate on the "title" field.
+func TitleIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldTitle, vs...))
+}
+
+// TitleNotIn applies the NotIn predicate on the "title" field.
+func TitleNotIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldTitle, vs...))
+}
+
+// TitleGT applies the GT predicate on the "title" field.
+func TitleGT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldTitle, v))
+}
+
+// TitleGTE applies the GTE predicate on the "title" field.
+func TitleGTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldTitle, v))
+}
+
+// TitleLT applies the LT predicate on the "title" field.
+func TitleLT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldTitle, v))
+}
+
+// TitleLTE applies the LTE predicate on the "title" field.
+func TitleLTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldTitle, v))
+}
+
+// TitleContains applies the Contains predicate on the "title" field.
+func TitleContains(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContains(FieldTitle, v))
+}
+
+// TitleHasPrefix applies the HasPrefix predicate on the "title" field.
+func TitleHasPrefix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasPrefix(FieldTitle, v))
+}
+
+// TitleHasSuffix applies the HasSuffix predicate on the "title" field.
+func TitleHasSuffix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasSuffix(FieldTitle, v))
+}
+
+// TitleEqualFold applies the EqualFold predicate on the "title" field.
+func TitleEqualFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEqualFold(FieldTitle, v))
+}
+
+// TitleContainsFold applies the ContainsFold predicate on the "title" field.
+func TitleContainsFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContainsFold(FieldTitle, v))
+}
+
+// AvatarEQ applies the EQ predicate on the "avatar" field.
+func AvatarEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldAvatar, v))
+}
+
+// AvatarNEQ applies the NEQ predicate on the "avatar" field.
+func AvatarNEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldAvatar, v))
+}
+
+// AvatarIn applies the In predicate on the "avatar" field.
+func AvatarIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldAvatar, vs...))
+}
+
+// AvatarNotIn applies the NotIn predicate on the "avatar" field.
+func AvatarNotIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldAvatar, vs...))
+}
+
+// AvatarGT applies the GT predicate on the "avatar" field.
+func AvatarGT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldAvatar, v))
+}
+
+// AvatarGTE applies the GTE predicate on the "avatar" field.
+func AvatarGTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldAvatar, v))
+}
+
+// AvatarLT applies the LT predicate on the "avatar" field.
+func AvatarLT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldAvatar, v))
+}
+
+// AvatarLTE applies the LTE predicate on the "avatar" field.
+func AvatarLTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldAvatar, v))
+}
+
+// AvatarContains applies the Contains predicate on the "avatar" field.
+func AvatarContains(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContains(FieldAvatar, v))
+}
+
+// AvatarHasPrefix applies the HasPrefix predicate on the "avatar" field.
+func AvatarHasPrefix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasPrefix(FieldAvatar, v))
+}
+
+// AvatarHasSuffix applies the HasSuffix predicate on the "avatar" field.
+func AvatarHasSuffix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasSuffix(FieldAvatar, v))
+}
+
+// AvatarEqualFold applies the EqualFold predicate on the "avatar" field.
+func AvatarEqualFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEqualFold(FieldAvatar, v))
+}
+
+// AvatarContainsFold applies the ContainsFold predicate on the "avatar" field.
+func AvatarContainsFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContainsFold(FieldAvatar, v))
+}
+
+// TagsEQ applies the EQ predicate on the "tags" field.
+func TagsEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldTags, v))
+}
+
+// TagsNEQ applies the NEQ predicate on the "tags" field.
+func TagsNEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldTags, v))
+}
+
+// TagsIn applies the In predicate on the "tags" field.
+func TagsIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldTags, vs...))
+}
+
+// TagsNotIn applies the NotIn predicate on the "tags" field.
+func TagsNotIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldTags, vs...))
+}
+
+// TagsGT applies the GT predicate on the "tags" field.
+func TagsGT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldTags, v))
+}
+
+// TagsGTE applies the GTE predicate on the "tags" field.
+func TagsGTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldTags, v))
+}
+
+// TagsLT applies the LT predicate on the "tags" field.
+func TagsLT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldTags, v))
+}
+
+// TagsLTE applies the LTE predicate on the "tags" field.
+func TagsLTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldTags, v))
+}
+
+// TagsContains applies the Contains predicate on the "tags" field.
+func TagsContains(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContains(FieldTags, v))
+}
+
+// TagsHasPrefix applies the HasPrefix predicate on the "tags" field.
+func TagsHasPrefix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasPrefix(FieldTags, v))
+}
+
+// TagsHasSuffix applies the HasSuffix predicate on the "tags" field.
+func TagsHasSuffix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasSuffix(FieldTags, v))
+}
+
+// TagsEqualFold applies the EqualFold predicate on the "tags" field.
+func TagsEqualFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEqualFold(FieldTags, v))
+}
+
+// TagsContainsFold applies the ContainsFold predicate on the "tags" field.
+func TagsContainsFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContainsFold(FieldTags, v))
+}
+
+// HireCountEQ applies the EQ predicate on the "hire_count" field.
+func HireCountEQ(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldHireCount, v))
+}
+
+// HireCountNEQ applies the NEQ predicate on the "hire_count" field.
+func HireCountNEQ(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldHireCount, v))
+}
+
+// HireCountIn applies the In predicate on the "hire_count" field.
+func HireCountIn(vs ...int) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldHireCount, vs...))
+}
+
+// HireCountNotIn applies the NotIn predicate on the "hire_count" field.
+func HireCountNotIn(vs ...int) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldHireCount, vs...))
+}
+
+// HireCountGT applies the GT predicate on the "hire_count" field.
+func HireCountGT(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldHireCount, v))
+}
+
+// HireCountGTE applies the GTE predicate on the "hire_count" field.
+func HireCountGTE(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldHireCount, v))
+}
+
+// HireCountLT applies the LT predicate on the "hire_count" field.
+func HireCountLT(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldHireCount, v))
+}
+
+// HireCountLTE applies the LTE predicate on the "hire_count" field.
+func HireCountLTE(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldHireCount, v))
+}
+
+// ServiceCountEQ applies the EQ predicate on the "service_count" field.
+func ServiceCountEQ(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldServiceCount, v))
+}
+
+// ServiceCountNEQ applies the NEQ predicate on the "service_count" field.
+func ServiceCountNEQ(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldServiceCount, v))
+}
+
+// ServiceCountIn applies the In predicate on the "service_count" field.
+func ServiceCountIn(vs ...int) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldServiceCount, vs...))
+}
+
+// ServiceCountNotIn applies the NotIn predicate on the "service_count" field.
+func ServiceCountNotIn(vs ...int) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldServiceCount, vs...))
+}
+
+// ServiceCountGT applies the GT predicate on the "service_count" field.
+func ServiceCountGT(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldServiceCount, v))
+}
+
+// ServiceCountGTE applies the GTE predicate on the "service_count" field.
+func ServiceCountGTE(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldServiceCount, v))
+}
+
+// ServiceCountLT applies the LT predicate on the "service_count" field.
+func ServiceCountLT(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldServiceCount, v))
+}
+
+// ServiceCountLTE applies the LTE predicate on the "service_count" field.
+func ServiceCountLTE(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldServiceCount, v))
+}
+
+// AchievementCountEQ applies the EQ predicate on the "achievement_count" field.
+func AchievementCountEQ(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldAchievementCount, v))
+}
+
+// AchievementCountNEQ applies the NEQ predicate on the "achievement_count" field.
+func AchievementCountNEQ(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldAchievementCount, v))
+}
+
+// AchievementCountIn applies the In predicate on the "achievement_count" field.
+func AchievementCountIn(vs ...int) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldAchievementCount, vs...))
+}
+
+// AchievementCountNotIn applies the NotIn predicate on the "achievement_count" field.
+func AchievementCountNotIn(vs ...int) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldAchievementCount, vs...))
+}
+
+// AchievementCountGT applies the GT predicate on the "achievement_count" field.
+func AchievementCountGT(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldAchievementCount, v))
+}
+
+// AchievementCountGTE applies the GTE predicate on the "achievement_count" field.
+func AchievementCountGTE(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldAchievementCount, v))
+}
+
+// AchievementCountLT applies the LT predicate on the "achievement_count" field.
+func AchievementCountLT(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldAchievementCount, v))
+}
+
+// AchievementCountLTE applies the LTE predicate on the "achievement_count" field.
+func AchievementCountLTE(v int) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldAchievementCount, v))
+}
+
+// IntroEQ applies the EQ predicate on the "intro" field.
+func IntroEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldIntro, v))
+}
+
+// IntroNEQ applies the NEQ predicate on the "intro" field.
+func IntroNEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldIntro, v))
+}
+
+// IntroIn applies the In predicate on the "intro" field.
+func IntroIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldIntro, vs...))
+}
+
+// IntroNotIn applies the NotIn predicate on the "intro" field.
+func IntroNotIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldIntro, vs...))
+}
+
+// IntroGT applies the GT predicate on the "intro" field.
+func IntroGT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldIntro, v))
+}
+
+// IntroGTE applies the GTE predicate on the "intro" field.
+func IntroGTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldIntro, v))
+}
+
+// IntroLT applies the LT predicate on the "intro" field.
+func IntroLT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldIntro, v))
+}
+
+// IntroLTE applies the LTE predicate on the "intro" field.
+func IntroLTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldIntro, v))
+}
+
+// IntroContains applies the Contains predicate on the "intro" field.
+func IntroContains(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContains(FieldIntro, v))
+}
+
+// IntroHasPrefix applies the HasPrefix predicate on the "intro" field.
+func IntroHasPrefix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasPrefix(FieldIntro, v))
+}
+
+// IntroHasSuffix applies the HasSuffix predicate on the "intro" field.
+func IntroHasSuffix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasSuffix(FieldIntro, v))
+}
+
+// IntroEqualFold applies the EqualFold predicate on the "intro" field.
+func IntroEqualFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEqualFold(FieldIntro, v))
+}
+
+// IntroContainsFold applies the ContainsFold predicate on the "intro" field.
+func IntroContainsFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContainsFold(FieldIntro, v))
+}
+
+// EstimateEQ applies the EQ predicate on the "estimate" field.
+func EstimateEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldEstimate, v))
+}
+
+// EstimateNEQ applies the NEQ predicate on the "estimate" field.
+func EstimateNEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldEstimate, v))
+}
+
+// EstimateIn applies the In predicate on the "estimate" field.
+func EstimateIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldEstimate, vs...))
+}
+
+// EstimateNotIn applies the NotIn predicate on the "estimate" field.
+func EstimateNotIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldEstimate, vs...))
+}
+
+// EstimateGT applies the GT predicate on the "estimate" field.
+func EstimateGT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldEstimate, v))
+}
+
+// EstimateGTE applies the GTE predicate on the "estimate" field.
+func EstimateGTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldEstimate, v))
+}
+
+// EstimateLT applies the LT predicate on the "estimate" field.
+func EstimateLT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldEstimate, v))
+}
+
+// EstimateLTE applies the LTE predicate on the "estimate" field.
+func EstimateLTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldEstimate, v))
+}
+
+// EstimateContains applies the Contains predicate on the "estimate" field.
+func EstimateContains(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContains(FieldEstimate, v))
+}
+
+// EstimateHasPrefix applies the HasPrefix predicate on the "estimate" field.
+func EstimateHasPrefix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasPrefix(FieldEstimate, v))
+}
+
+// EstimateHasSuffix applies the HasSuffix predicate on the "estimate" field.
+func EstimateHasSuffix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasSuffix(FieldEstimate, v))
+}
+
+// EstimateEqualFold applies the EqualFold predicate on the "estimate" field.
+func EstimateEqualFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEqualFold(FieldEstimate, v))
+}
+
+// EstimateContainsFold applies the ContainsFold predicate on the "estimate" field.
+func EstimateContainsFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContainsFold(FieldEstimate, v))
+}
+
+// SkillEQ applies the EQ predicate on the "skill" field.
+func SkillEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldSkill, v))
+}
+
+// SkillNEQ applies the NEQ predicate on the "skill" field.
+func SkillNEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldSkill, v))
+}
+
+// SkillIn applies the In predicate on the "skill" field.
+func SkillIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldSkill, vs...))
+}
+
+// SkillNotIn applies the NotIn predicate on the "skill" field.
+func SkillNotIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldSkill, vs...))
+}
+
+// SkillGT applies the GT predicate on the "skill" field.
+func SkillGT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldSkill, v))
+}
+
+// SkillGTE applies the GTE predicate on the "skill" field.
+func SkillGTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldSkill, v))
+}
+
+// SkillLT applies the LT predicate on the "skill" field.
+func SkillLT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldSkill, v))
+}
+
+// SkillLTE applies the LTE predicate on the "skill" field.
+func SkillLTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldSkill, v))
+}
+
+// SkillContains applies the Contains predicate on the "skill" field.
+func SkillContains(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContains(FieldSkill, v))
+}
+
+// SkillHasPrefix applies the HasPrefix predicate on the "skill" field.
+func SkillHasPrefix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasPrefix(FieldSkill, v))
+}
+
+// SkillHasSuffix applies the HasSuffix predicate on the "skill" field.
+func SkillHasSuffix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasSuffix(FieldSkill, v))
+}
+
+// SkillEqualFold applies the EqualFold predicate on the "skill" field.
+func SkillEqualFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEqualFold(FieldSkill, v))
+}
+
+// SkillContainsFold applies the ContainsFold predicate on the "skill" field.
+func SkillContainsFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContainsFold(FieldSkill, v))
+}
+
+// AbilityTypeEQ applies the EQ predicate on the "ability_type" field.
+func AbilityTypeEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldAbilityType, v))
+}
+
+// AbilityTypeNEQ applies the NEQ predicate on the "ability_type" field.
+func AbilityTypeNEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldAbilityType, v))
+}
+
+// AbilityTypeIn applies the In predicate on the "ability_type" field.
+func AbilityTypeIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldAbilityType, vs...))
+}
+
+// AbilityTypeNotIn applies the NotIn predicate on the "ability_type" field.
+func AbilityTypeNotIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldAbilityType, vs...))
+}
+
+// AbilityTypeGT applies the GT predicate on the "ability_type" field.
+func AbilityTypeGT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldAbilityType, v))
+}
+
+// AbilityTypeGTE applies the GTE predicate on the "ability_type" field.
+func AbilityTypeGTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldAbilityType, v))
+}
+
+// AbilityTypeLT applies the LT predicate on the "ability_type" field.
+func AbilityTypeLT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldAbilityType, v))
+}
+
+// AbilityTypeLTE applies the LTE predicate on the "ability_type" field.
+func AbilityTypeLTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldAbilityType, v))
+}
+
+// AbilityTypeContains applies the Contains predicate on the "ability_type" field.
+func AbilityTypeContains(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContains(FieldAbilityType, v))
+}
+
+// AbilityTypeHasPrefix applies the HasPrefix predicate on the "ability_type" field.
+func AbilityTypeHasPrefix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasPrefix(FieldAbilityType, v))
+}
+
+// AbilityTypeHasSuffix applies the HasSuffix predicate on the "ability_type" field.
+func AbilityTypeHasSuffix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasSuffix(FieldAbilityType, v))
+}
+
+// AbilityTypeEqualFold applies the EqualFold predicate on the "ability_type" field.
+func AbilityTypeEqualFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEqualFold(FieldAbilityType, v))
+}
+
+// AbilityTypeContainsFold applies the ContainsFold predicate on the "ability_type" field.
+func AbilityTypeContainsFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContainsFold(FieldAbilityType, v))
+}
+
+// SceneEQ applies the EQ predicate on the "scene" field.
+func SceneEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldScene, v))
+}
+
+// SceneNEQ applies the NEQ predicate on the "scene" field.
+func SceneNEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldScene, v))
+}
+
+// SceneIn applies the In predicate on the "scene" field.
+func SceneIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldScene, vs...))
+}
+
+// SceneNotIn applies the NotIn predicate on the "scene" field.
+func SceneNotIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldScene, vs...))
+}
+
+// SceneGT applies the GT predicate on the "scene" field.
+func SceneGT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldScene, v))
+}
+
+// SceneGTE applies the GTE predicate on the "scene" field.
+func SceneGTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldScene, v))
+}
+
+// SceneLT applies the LT predicate on the "scene" field.
+func SceneLT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldScene, v))
+}
+
+// SceneLTE applies the LTE predicate on the "scene" field.
+func SceneLTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldScene, v))
+}
+
+// SceneContains applies the Contains predicate on the "scene" field.
+func SceneContains(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContains(FieldScene, v))
+}
+
+// SceneHasPrefix applies the HasPrefix predicate on the "scene" field.
+func SceneHasPrefix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasPrefix(FieldScene, v))
+}
+
+// SceneHasSuffix applies the HasSuffix predicate on the "scene" field.
+func SceneHasSuffix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasSuffix(FieldScene, v))
+}
+
+// SceneEqualFold applies the EqualFold predicate on the "scene" field.
+func SceneEqualFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEqualFold(FieldScene, v))
+}
+
+// SceneContainsFold applies the ContainsFold predicate on the "scene" field.
+func SceneContainsFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContainsFold(FieldScene, v))
+}
+
+// SwitchInEQ applies the EQ predicate on the "switch_in" field.
+func SwitchInEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldSwitchIn, v))
+}
+
+// SwitchInNEQ applies the NEQ predicate on the "switch_in" field.
+func SwitchInNEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldSwitchIn, v))
+}
+
+// SwitchInIn applies the In predicate on the "switch_in" field.
+func SwitchInIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldSwitchIn, vs...))
+}
+
+// SwitchInNotIn applies the NotIn predicate on the "switch_in" field.
+func SwitchInNotIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldSwitchIn, vs...))
+}
+
+// SwitchInGT applies the GT predicate on the "switch_in" field.
+func SwitchInGT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldSwitchIn, v))
+}
+
+// SwitchInGTE applies the GTE predicate on the "switch_in" field.
+func SwitchInGTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldSwitchIn, v))
+}
+
+// SwitchInLT applies the LT predicate on the "switch_in" field.
+func SwitchInLT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldSwitchIn, v))
+}
+
+// SwitchInLTE applies the LTE predicate on the "switch_in" field.
+func SwitchInLTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldSwitchIn, v))
+}
+
+// SwitchInContains applies the Contains predicate on the "switch_in" field.
+func SwitchInContains(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContains(FieldSwitchIn, v))
+}
+
+// SwitchInHasPrefix applies the HasPrefix predicate on the "switch_in" field.
+func SwitchInHasPrefix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasPrefix(FieldSwitchIn, v))
+}
+
+// SwitchInHasSuffix applies the HasSuffix predicate on the "switch_in" field.
+func SwitchInHasSuffix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasSuffix(FieldSwitchIn, v))
+}
+
+// SwitchInEqualFold applies the EqualFold predicate on the "switch_in" field.
+func SwitchInEqualFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEqualFold(FieldSwitchIn, v))
+}
+
+// SwitchInContainsFold applies the ContainsFold predicate on the "switch_in" field.
+func SwitchInContainsFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContainsFold(FieldSwitchIn, v))
+}
+
+// VideoURLEQ applies the EQ predicate on the "video_url" field.
+func VideoURLEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldVideoURL, v))
+}
+
+// VideoURLNEQ applies the NEQ predicate on the "video_url" field.
+func VideoURLNEQ(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldVideoURL, v))
+}
+
+// VideoURLIn applies the In predicate on the "video_url" field.
+func VideoURLIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldVideoURL, vs...))
+}
+
+// VideoURLNotIn applies the NotIn predicate on the "video_url" field.
+func VideoURLNotIn(vs ...string) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldVideoURL, vs...))
+}
+
+// VideoURLGT applies the GT predicate on the "video_url" field.
+func VideoURLGT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldVideoURL, v))
+}
+
+// VideoURLGTE applies the GTE predicate on the "video_url" field.
+func VideoURLGTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldVideoURL, v))
+}
+
+// VideoURLLT applies the LT predicate on the "video_url" field.
+func VideoURLLT(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldVideoURL, v))
+}
+
+// VideoURLLTE applies the LTE predicate on the "video_url" field.
+func VideoURLLTE(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldVideoURL, v))
+}
+
+// VideoURLContains applies the Contains predicate on the "video_url" field.
+func VideoURLContains(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContains(FieldVideoURL, v))
+}
+
+// VideoURLHasPrefix applies the HasPrefix predicate on the "video_url" field.
+func VideoURLHasPrefix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasPrefix(FieldVideoURL, v))
+}
+
+// VideoURLHasSuffix applies the HasSuffix predicate on the "video_url" field.
+func VideoURLHasSuffix(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldHasSuffix(FieldVideoURL, v))
+}
+
+// VideoURLEqualFold applies the EqualFold predicate on the "video_url" field.
+func VideoURLEqualFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldEqualFold(FieldVideoURL, v))
+}
+
+// VideoURLContainsFold applies the ContainsFold predicate on the "video_url" field.
+func VideoURLContainsFold(v string) predicate.Employee {
+	return predicate.Employee(sql.FieldContainsFold(FieldVideoURL, v))
+}
+
+// OrganizationIDEQ applies the EQ predicate on the "organization_id" field.
+func OrganizationIDEQ(v uint64) predicate.Employee {
+	return predicate.Employee(sql.FieldEQ(FieldOrganizationID, v))
+}
+
+// OrganizationIDNEQ applies the NEQ predicate on the "organization_id" field.
+func OrganizationIDNEQ(v uint64) predicate.Employee {
+	return predicate.Employee(sql.FieldNEQ(FieldOrganizationID, v))
+}
+
+// OrganizationIDIn applies the In predicate on the "organization_id" field.
+func OrganizationIDIn(vs ...uint64) predicate.Employee {
+	return predicate.Employee(sql.FieldIn(FieldOrganizationID, vs...))
+}
+
+// OrganizationIDNotIn applies the NotIn predicate on the "organization_id" field.
+func OrganizationIDNotIn(vs ...uint64) predicate.Employee {
+	return predicate.Employee(sql.FieldNotIn(FieldOrganizationID, vs...))
+}
+
+// OrganizationIDGT applies the GT predicate on the "organization_id" field.
+func OrganizationIDGT(v uint64) predicate.Employee {
+	return predicate.Employee(sql.FieldGT(FieldOrganizationID, v))
+}
+
+// OrganizationIDGTE applies the GTE predicate on the "organization_id" field.
+func OrganizationIDGTE(v uint64) predicate.Employee {
+	return predicate.Employee(sql.FieldGTE(FieldOrganizationID, v))
+}
+
+// OrganizationIDLT applies the LT predicate on the "organization_id" field.
+func OrganizationIDLT(v uint64) predicate.Employee {
+	return predicate.Employee(sql.FieldLT(FieldOrganizationID, v))
+}
+
+// OrganizationIDLTE applies the LTE predicate on the "organization_id" field.
+func OrganizationIDLTE(v uint64) predicate.Employee {
+	return predicate.Employee(sql.FieldLTE(FieldOrganizationID, v))
+}
+
+// HasEmWorkExperiences applies the HasEdge predicate on the "em_work_experiences" edge.
+func HasEmWorkExperiences() predicate.Employee {
+	return predicate.Employee(func(s *sql.Selector) {
+		step := sqlgraph.NewStep(
+			sqlgraph.From(Table, FieldID),
+			sqlgraph.Edge(sqlgraph.O2M, false, EmWorkExperiencesTable, EmWorkExperiencesColumn),
+		)
+		sqlgraph.HasNeighbors(s, step)
+	})
+}
+
+// HasEmWorkExperiencesWith applies the HasEdge predicate on the "em_work_experiences" edge with a given conditions (other predicates).
+func HasEmWorkExperiencesWith(preds ...predicate.WorkExperience) predicate.Employee {
+	return predicate.Employee(func(s *sql.Selector) {
+		step := newEmWorkExperiencesStep()
+		sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+			for _, p := range preds {
+				p(s)
+			}
+		})
+	})
+}
+
+// HasEmTutorial applies the HasEdge predicate on the "em_tutorial" edge.
+func HasEmTutorial() predicate.Employee {
+	return predicate.Employee(func(s *sql.Selector) {
+		step := sqlgraph.NewStep(
+			sqlgraph.From(Table, FieldID),
+			sqlgraph.Edge(sqlgraph.O2M, false, EmTutorialTable, EmTutorialColumn),
+		)
+		sqlgraph.HasNeighbors(s, step)
+	})
+}
+
+// HasEmTutorialWith applies the HasEdge predicate on the "em_tutorial" edge with a given conditions (other predicates).
+func HasEmTutorialWith(preds ...predicate.Tutorial) predicate.Employee {
+	return predicate.Employee(func(s *sql.Selector) {
+		step := newEmTutorialStep()
+		sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+			for _, p := range preds {
+				p(s)
+			}
+		})
+	})
+}
+
+// And groups predicates with the AND operator between them.
+func And(predicates ...predicate.Employee) predicate.Employee {
+	return predicate.Employee(sql.AndPredicates(predicates...))
+}
+
+// Or groups predicates with the OR operator between them.
+func Or(predicates ...predicate.Employee) predicate.Employee {
+	return predicate.Employee(sql.OrPredicates(predicates...))
+}
+
+// Not applies the not operator on the given predicate.
+func Not(p predicate.Employee) predicate.Employee {
+	return predicate.Employee(sql.NotPredicates(p))
+}

+ 1682 - 0
ent/employee_create.go

@@ -0,0 +1,1682 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/employee"
+	"wechat-api/ent/tutorial"
+	"wechat-api/ent/workexperience"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// EmployeeCreate is the builder for creating a Employee entity.
+type EmployeeCreate struct {
+	config
+	mutation *EmployeeMutation
+	hooks    []Hook
+	conflict []sql.ConflictOption
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (ec *EmployeeCreate) SetCreatedAt(t time.Time) *EmployeeCreate {
+	ec.mutation.SetCreatedAt(t)
+	return ec
+}
+
+// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
+func (ec *EmployeeCreate) SetNillableCreatedAt(t *time.Time) *EmployeeCreate {
+	if t != nil {
+		ec.SetCreatedAt(*t)
+	}
+	return ec
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (ec *EmployeeCreate) SetUpdatedAt(t time.Time) *EmployeeCreate {
+	ec.mutation.SetUpdatedAt(t)
+	return ec
+}
+
+// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
+func (ec *EmployeeCreate) SetNillableUpdatedAt(t *time.Time) *EmployeeCreate {
+	if t != nil {
+		ec.SetUpdatedAt(*t)
+	}
+	return ec
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (ec *EmployeeCreate) SetDeletedAt(t time.Time) *EmployeeCreate {
+	ec.mutation.SetDeletedAt(t)
+	return ec
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (ec *EmployeeCreate) SetNillableDeletedAt(t *time.Time) *EmployeeCreate {
+	if t != nil {
+		ec.SetDeletedAt(*t)
+	}
+	return ec
+}
+
+// SetTitle sets the "title" field.
+func (ec *EmployeeCreate) SetTitle(s string) *EmployeeCreate {
+	ec.mutation.SetTitle(s)
+	return ec
+}
+
+// SetAvatar sets the "avatar" field.
+func (ec *EmployeeCreate) SetAvatar(s string) *EmployeeCreate {
+	ec.mutation.SetAvatar(s)
+	return ec
+}
+
+// SetTags sets the "tags" field.
+func (ec *EmployeeCreate) SetTags(s string) *EmployeeCreate {
+	ec.mutation.SetTags(s)
+	return ec
+}
+
+// SetHireCount sets the "hire_count" field.
+func (ec *EmployeeCreate) SetHireCount(i int) *EmployeeCreate {
+	ec.mutation.SetHireCount(i)
+	return ec
+}
+
+// SetNillableHireCount sets the "hire_count" field if the given value is not nil.
+func (ec *EmployeeCreate) SetNillableHireCount(i *int) *EmployeeCreate {
+	if i != nil {
+		ec.SetHireCount(*i)
+	}
+	return ec
+}
+
+// SetServiceCount sets the "service_count" field.
+func (ec *EmployeeCreate) SetServiceCount(i int) *EmployeeCreate {
+	ec.mutation.SetServiceCount(i)
+	return ec
+}
+
+// SetNillableServiceCount sets the "service_count" field if the given value is not nil.
+func (ec *EmployeeCreate) SetNillableServiceCount(i *int) *EmployeeCreate {
+	if i != nil {
+		ec.SetServiceCount(*i)
+	}
+	return ec
+}
+
+// SetAchievementCount sets the "achievement_count" field.
+func (ec *EmployeeCreate) SetAchievementCount(i int) *EmployeeCreate {
+	ec.mutation.SetAchievementCount(i)
+	return ec
+}
+
+// SetNillableAchievementCount sets the "achievement_count" field if the given value is not nil.
+func (ec *EmployeeCreate) SetNillableAchievementCount(i *int) *EmployeeCreate {
+	if i != nil {
+		ec.SetAchievementCount(*i)
+	}
+	return ec
+}
+
+// SetIntro sets the "intro" field.
+func (ec *EmployeeCreate) SetIntro(s string) *EmployeeCreate {
+	ec.mutation.SetIntro(s)
+	return ec
+}
+
+// SetNillableIntro sets the "intro" field if the given value is not nil.
+func (ec *EmployeeCreate) SetNillableIntro(s *string) *EmployeeCreate {
+	if s != nil {
+		ec.SetIntro(*s)
+	}
+	return ec
+}
+
+// SetEstimate sets the "estimate" field.
+func (ec *EmployeeCreate) SetEstimate(s string) *EmployeeCreate {
+	ec.mutation.SetEstimate(s)
+	return ec
+}
+
+// SetNillableEstimate sets the "estimate" field if the given value is not nil.
+func (ec *EmployeeCreate) SetNillableEstimate(s *string) *EmployeeCreate {
+	if s != nil {
+		ec.SetEstimate(*s)
+	}
+	return ec
+}
+
+// SetSkill sets the "skill" field.
+func (ec *EmployeeCreate) SetSkill(s string) *EmployeeCreate {
+	ec.mutation.SetSkill(s)
+	return ec
+}
+
+// SetNillableSkill sets the "skill" field if the given value is not nil.
+func (ec *EmployeeCreate) SetNillableSkill(s *string) *EmployeeCreate {
+	if s != nil {
+		ec.SetSkill(*s)
+	}
+	return ec
+}
+
+// SetAbilityType sets the "ability_type" field.
+func (ec *EmployeeCreate) SetAbilityType(s string) *EmployeeCreate {
+	ec.mutation.SetAbilityType(s)
+	return ec
+}
+
+// SetNillableAbilityType sets the "ability_type" field if the given value is not nil.
+func (ec *EmployeeCreate) SetNillableAbilityType(s *string) *EmployeeCreate {
+	if s != nil {
+		ec.SetAbilityType(*s)
+	}
+	return ec
+}
+
+// SetScene sets the "scene" field.
+func (ec *EmployeeCreate) SetScene(s string) *EmployeeCreate {
+	ec.mutation.SetScene(s)
+	return ec
+}
+
+// SetNillableScene sets the "scene" field if the given value is not nil.
+func (ec *EmployeeCreate) SetNillableScene(s *string) *EmployeeCreate {
+	if s != nil {
+		ec.SetScene(*s)
+	}
+	return ec
+}
+
+// SetSwitchIn sets the "switch_in" field.
+func (ec *EmployeeCreate) SetSwitchIn(s string) *EmployeeCreate {
+	ec.mutation.SetSwitchIn(s)
+	return ec
+}
+
+// SetNillableSwitchIn sets the "switch_in" field if the given value is not nil.
+func (ec *EmployeeCreate) SetNillableSwitchIn(s *string) *EmployeeCreate {
+	if s != nil {
+		ec.SetSwitchIn(*s)
+	}
+	return ec
+}
+
+// SetVideoURL sets the "video_url" field.
+func (ec *EmployeeCreate) SetVideoURL(s string) *EmployeeCreate {
+	ec.mutation.SetVideoURL(s)
+	return ec
+}
+
+// SetNillableVideoURL sets the "video_url" field if the given value is not nil.
+func (ec *EmployeeCreate) SetNillableVideoURL(s *string) *EmployeeCreate {
+	if s != nil {
+		ec.SetVideoURL(*s)
+	}
+	return ec
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (ec *EmployeeCreate) SetOrganizationID(u uint64) *EmployeeCreate {
+	ec.mutation.SetOrganizationID(u)
+	return ec
+}
+
+// SetID sets the "id" field.
+func (ec *EmployeeCreate) SetID(u uint64) *EmployeeCreate {
+	ec.mutation.SetID(u)
+	return ec
+}
+
+// AddEmWorkExperienceIDs adds the "em_work_experiences" edge to the WorkExperience entity by IDs.
+func (ec *EmployeeCreate) AddEmWorkExperienceIDs(ids ...uint64) *EmployeeCreate {
+	ec.mutation.AddEmWorkExperienceIDs(ids...)
+	return ec
+}
+
+// AddEmWorkExperiences adds the "em_work_experiences" edges to the WorkExperience entity.
+func (ec *EmployeeCreate) AddEmWorkExperiences(w ...*WorkExperience) *EmployeeCreate {
+	ids := make([]uint64, len(w))
+	for i := range w {
+		ids[i] = w[i].ID
+	}
+	return ec.AddEmWorkExperienceIDs(ids...)
+}
+
+// AddEmTutorialIDs adds the "em_tutorial" edge to the Tutorial entity by IDs.
+func (ec *EmployeeCreate) AddEmTutorialIDs(ids ...uint64) *EmployeeCreate {
+	ec.mutation.AddEmTutorialIDs(ids...)
+	return ec
+}
+
+// AddEmTutorial adds the "em_tutorial" edges to the Tutorial entity.
+func (ec *EmployeeCreate) AddEmTutorial(t ...*Tutorial) *EmployeeCreate {
+	ids := make([]uint64, len(t))
+	for i := range t {
+		ids[i] = t[i].ID
+	}
+	return ec.AddEmTutorialIDs(ids...)
+}
+
+// Mutation returns the EmployeeMutation object of the builder.
+func (ec *EmployeeCreate) Mutation() *EmployeeMutation {
+	return ec.mutation
+}
+
+// Save creates the Employee in the database.
+func (ec *EmployeeCreate) Save(ctx context.Context) (*Employee, error) {
+	if err := ec.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, ec.sqlSave, ec.mutation, ec.hooks)
+}
+
+// SaveX calls Save and panics if Save returns an error.
+func (ec *EmployeeCreate) SaveX(ctx context.Context) *Employee {
+	v, err := ec.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (ec *EmployeeCreate) Exec(ctx context.Context) error {
+	_, err := ec.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (ec *EmployeeCreate) ExecX(ctx context.Context) {
+	if err := ec.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (ec *EmployeeCreate) defaults() error {
+	if _, ok := ec.mutation.CreatedAt(); !ok {
+		if employee.DefaultCreatedAt == nil {
+			return fmt.Errorf("ent: uninitialized employee.DefaultCreatedAt (forgotten import ent/runtime?)")
+		}
+		v := employee.DefaultCreatedAt()
+		ec.mutation.SetCreatedAt(v)
+	}
+	if _, ok := ec.mutation.UpdatedAt(); !ok {
+		if employee.DefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized employee.DefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := employee.DefaultUpdatedAt()
+		ec.mutation.SetUpdatedAt(v)
+	}
+	if _, ok := ec.mutation.HireCount(); !ok {
+		v := employee.DefaultHireCount
+		ec.mutation.SetHireCount(v)
+	}
+	if _, ok := ec.mutation.ServiceCount(); !ok {
+		v := employee.DefaultServiceCount
+		ec.mutation.SetServiceCount(v)
+	}
+	if _, ok := ec.mutation.AchievementCount(); !ok {
+		v := employee.DefaultAchievementCount
+		ec.mutation.SetAchievementCount(v)
+	}
+	if _, ok := ec.mutation.Intro(); !ok {
+		v := employee.DefaultIntro
+		ec.mutation.SetIntro(v)
+	}
+	if _, ok := ec.mutation.Estimate(); !ok {
+		v := employee.DefaultEstimate
+		ec.mutation.SetEstimate(v)
+	}
+	if _, ok := ec.mutation.Skill(); !ok {
+		v := employee.DefaultSkill
+		ec.mutation.SetSkill(v)
+	}
+	if _, ok := ec.mutation.AbilityType(); !ok {
+		v := employee.DefaultAbilityType
+		ec.mutation.SetAbilityType(v)
+	}
+	if _, ok := ec.mutation.Scene(); !ok {
+		v := employee.DefaultScene
+		ec.mutation.SetScene(v)
+	}
+	if _, ok := ec.mutation.SwitchIn(); !ok {
+		v := employee.DefaultSwitchIn
+		ec.mutation.SetSwitchIn(v)
+	}
+	if _, ok := ec.mutation.VideoURL(); !ok {
+		v := employee.DefaultVideoURL
+		ec.mutation.SetVideoURL(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (ec *EmployeeCreate) check() error {
+	if _, ok := ec.mutation.CreatedAt(); !ok {
+		return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "Employee.created_at"`)}
+	}
+	if _, ok := ec.mutation.UpdatedAt(); !ok {
+		return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "Employee.updated_at"`)}
+	}
+	if _, ok := ec.mutation.Title(); !ok {
+		return &ValidationError{Name: "title", err: errors.New(`ent: missing required field "Employee.title"`)}
+	}
+	if v, ok := ec.mutation.Title(); ok {
+		if err := employee.TitleValidator(v); err != nil {
+			return &ValidationError{Name: "title", err: fmt.Errorf(`ent: validator failed for field "Employee.title": %w`, err)}
+		}
+	}
+	if _, ok := ec.mutation.Avatar(); !ok {
+		return &ValidationError{Name: "avatar", err: errors.New(`ent: missing required field "Employee.avatar"`)}
+	}
+	if v, ok := ec.mutation.Avatar(); ok {
+		if err := employee.AvatarValidator(v); err != nil {
+			return &ValidationError{Name: "avatar", err: fmt.Errorf(`ent: validator failed for field "Employee.avatar": %w`, err)}
+		}
+	}
+	if _, ok := ec.mutation.Tags(); !ok {
+		return &ValidationError{Name: "tags", err: errors.New(`ent: missing required field "Employee.tags"`)}
+	}
+	if v, ok := ec.mutation.Tags(); ok {
+		if err := employee.TagsValidator(v); err != nil {
+			return &ValidationError{Name: "tags", err: fmt.Errorf(`ent: validator failed for field "Employee.tags": %w`, err)}
+		}
+	}
+	if _, ok := ec.mutation.HireCount(); !ok {
+		return &ValidationError{Name: "hire_count", err: errors.New(`ent: missing required field "Employee.hire_count"`)}
+	}
+	if v, ok := ec.mutation.HireCount(); ok {
+		if err := employee.HireCountValidator(v); err != nil {
+			return &ValidationError{Name: "hire_count", err: fmt.Errorf(`ent: validator failed for field "Employee.hire_count": %w`, err)}
+		}
+	}
+	if _, ok := ec.mutation.ServiceCount(); !ok {
+		return &ValidationError{Name: "service_count", err: errors.New(`ent: missing required field "Employee.service_count"`)}
+	}
+	if v, ok := ec.mutation.ServiceCount(); ok {
+		if err := employee.ServiceCountValidator(v); err != nil {
+			return &ValidationError{Name: "service_count", err: fmt.Errorf(`ent: validator failed for field "Employee.service_count": %w`, err)}
+		}
+	}
+	if _, ok := ec.mutation.AchievementCount(); !ok {
+		return &ValidationError{Name: "achievement_count", err: errors.New(`ent: missing required field "Employee.achievement_count"`)}
+	}
+	if v, ok := ec.mutation.AchievementCount(); ok {
+		if err := employee.AchievementCountValidator(v); err != nil {
+			return &ValidationError{Name: "achievement_count", err: fmt.Errorf(`ent: validator failed for field "Employee.achievement_count": %w`, err)}
+		}
+	}
+	if _, ok := ec.mutation.Intro(); !ok {
+		return &ValidationError{Name: "intro", err: errors.New(`ent: missing required field "Employee.intro"`)}
+	}
+	if v, ok := ec.mutation.Intro(); ok {
+		if err := employee.IntroValidator(v); err != nil {
+			return &ValidationError{Name: "intro", err: fmt.Errorf(`ent: validator failed for field "Employee.intro": %w`, err)}
+		}
+	}
+	if _, ok := ec.mutation.Estimate(); !ok {
+		return &ValidationError{Name: "estimate", err: errors.New(`ent: missing required field "Employee.estimate"`)}
+	}
+	if v, ok := ec.mutation.Estimate(); ok {
+		if err := employee.EstimateValidator(v); err != nil {
+			return &ValidationError{Name: "estimate", err: fmt.Errorf(`ent: validator failed for field "Employee.estimate": %w`, err)}
+		}
+	}
+	if _, ok := ec.mutation.Skill(); !ok {
+		return &ValidationError{Name: "skill", err: errors.New(`ent: missing required field "Employee.skill"`)}
+	}
+	if v, ok := ec.mutation.Skill(); ok {
+		if err := employee.SkillValidator(v); err != nil {
+			return &ValidationError{Name: "skill", err: fmt.Errorf(`ent: validator failed for field "Employee.skill": %w`, err)}
+		}
+	}
+	if _, ok := ec.mutation.AbilityType(); !ok {
+		return &ValidationError{Name: "ability_type", err: errors.New(`ent: missing required field "Employee.ability_type"`)}
+	}
+	if _, ok := ec.mutation.Scene(); !ok {
+		return &ValidationError{Name: "scene", err: errors.New(`ent: missing required field "Employee.scene"`)}
+	}
+	if _, ok := ec.mutation.SwitchIn(); !ok {
+		return &ValidationError{Name: "switch_in", err: errors.New(`ent: missing required field "Employee.switch_in"`)}
+	}
+	if _, ok := ec.mutation.VideoURL(); !ok {
+		return &ValidationError{Name: "video_url", err: errors.New(`ent: missing required field "Employee.video_url"`)}
+	}
+	if v, ok := ec.mutation.VideoURL(); ok {
+		if err := employee.VideoURLValidator(v); err != nil {
+			return &ValidationError{Name: "video_url", err: fmt.Errorf(`ent: validator failed for field "Employee.video_url": %w`, err)}
+		}
+	}
+	if _, ok := ec.mutation.OrganizationID(); !ok {
+		return &ValidationError{Name: "organization_id", err: errors.New(`ent: missing required field "Employee.organization_id"`)}
+	}
+	if v, ok := ec.mutation.OrganizationID(); ok {
+		if err := employee.OrganizationIDValidator(v); err != nil {
+			return &ValidationError{Name: "organization_id", err: fmt.Errorf(`ent: validator failed for field "Employee.organization_id": %w`, err)}
+		}
+	}
+	return nil
+}
+
+func (ec *EmployeeCreate) sqlSave(ctx context.Context) (*Employee, error) {
+	if err := ec.check(); err != nil {
+		return nil, err
+	}
+	_node, _spec := ec.createSpec()
+	if err := sqlgraph.CreateNode(ctx, ec.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)
+	}
+	ec.mutation.id = &_node.ID
+	ec.mutation.done = true
+	return _node, nil
+}
+
+func (ec *EmployeeCreate) createSpec() (*Employee, *sqlgraph.CreateSpec) {
+	var (
+		_node = &Employee{config: ec.config}
+		_spec = sqlgraph.NewCreateSpec(employee.Table, sqlgraph.NewFieldSpec(employee.FieldID, field.TypeUint64))
+	)
+	_spec.OnConflict = ec.conflict
+	if id, ok := ec.mutation.ID(); ok {
+		_node.ID = id
+		_spec.ID.Value = id
+	}
+	if value, ok := ec.mutation.CreatedAt(); ok {
+		_spec.SetField(employee.FieldCreatedAt, field.TypeTime, value)
+		_node.CreatedAt = value
+	}
+	if value, ok := ec.mutation.UpdatedAt(); ok {
+		_spec.SetField(employee.FieldUpdatedAt, field.TypeTime, value)
+		_node.UpdatedAt = value
+	}
+	if value, ok := ec.mutation.DeletedAt(); ok {
+		_spec.SetField(employee.FieldDeletedAt, field.TypeTime, value)
+		_node.DeletedAt = value
+	}
+	if value, ok := ec.mutation.Title(); ok {
+		_spec.SetField(employee.FieldTitle, field.TypeString, value)
+		_node.Title = value
+	}
+	if value, ok := ec.mutation.Avatar(); ok {
+		_spec.SetField(employee.FieldAvatar, field.TypeString, value)
+		_node.Avatar = value
+	}
+	if value, ok := ec.mutation.Tags(); ok {
+		_spec.SetField(employee.FieldTags, field.TypeString, value)
+		_node.Tags = value
+	}
+	if value, ok := ec.mutation.HireCount(); ok {
+		_spec.SetField(employee.FieldHireCount, field.TypeInt, value)
+		_node.HireCount = value
+	}
+	if value, ok := ec.mutation.ServiceCount(); ok {
+		_spec.SetField(employee.FieldServiceCount, field.TypeInt, value)
+		_node.ServiceCount = value
+	}
+	if value, ok := ec.mutation.AchievementCount(); ok {
+		_spec.SetField(employee.FieldAchievementCount, field.TypeInt, value)
+		_node.AchievementCount = value
+	}
+	if value, ok := ec.mutation.Intro(); ok {
+		_spec.SetField(employee.FieldIntro, field.TypeString, value)
+		_node.Intro = value
+	}
+	if value, ok := ec.mutation.Estimate(); ok {
+		_spec.SetField(employee.FieldEstimate, field.TypeString, value)
+		_node.Estimate = value
+	}
+	if value, ok := ec.mutation.Skill(); ok {
+		_spec.SetField(employee.FieldSkill, field.TypeString, value)
+		_node.Skill = value
+	}
+	if value, ok := ec.mutation.AbilityType(); ok {
+		_spec.SetField(employee.FieldAbilityType, field.TypeString, value)
+		_node.AbilityType = value
+	}
+	if value, ok := ec.mutation.Scene(); ok {
+		_spec.SetField(employee.FieldScene, field.TypeString, value)
+		_node.Scene = value
+	}
+	if value, ok := ec.mutation.SwitchIn(); ok {
+		_spec.SetField(employee.FieldSwitchIn, field.TypeString, value)
+		_node.SwitchIn = value
+	}
+	if value, ok := ec.mutation.VideoURL(); ok {
+		_spec.SetField(employee.FieldVideoURL, field.TypeString, value)
+		_node.VideoURL = value
+	}
+	if value, ok := ec.mutation.OrganizationID(); ok {
+		_spec.SetField(employee.FieldOrganizationID, field.TypeUint64, value)
+		_node.OrganizationID = value
+	}
+	if nodes := ec.mutation.EmWorkExperiencesIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   employee.EmWorkExperiencesTable,
+			Columns: []string{employee.EmWorkExperiencesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(workexperience.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges = append(_spec.Edges, edge)
+	}
+	if nodes := ec.mutation.EmTutorialIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   employee.EmTutorialTable,
+			Columns: []string{employee.EmTutorialColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(tutorial.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges = append(_spec.Edges, edge)
+	}
+	return _node, _spec
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.Employee.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.EmployeeUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (ec *EmployeeCreate) OnConflict(opts ...sql.ConflictOption) *EmployeeUpsertOne {
+	ec.conflict = opts
+	return &EmployeeUpsertOne{
+		create: ec,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.Employee.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (ec *EmployeeCreate) OnConflictColumns(columns ...string) *EmployeeUpsertOne {
+	ec.conflict = append(ec.conflict, sql.ConflictColumns(columns...))
+	return &EmployeeUpsertOne{
+		create: ec,
+	}
+}
+
+type (
+	// EmployeeUpsertOne is the builder for "upsert"-ing
+	//  one Employee node.
+	EmployeeUpsertOne struct {
+		create *EmployeeCreate
+	}
+
+	// EmployeeUpsert is the "OnConflict" setter.
+	EmployeeUpsert struct {
+		*sql.UpdateSet
+	}
+)
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *EmployeeUpsert) SetUpdatedAt(v time.Time) *EmployeeUpsert {
+	u.Set(employee.FieldUpdatedAt, v)
+	return u
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *EmployeeUpsert) UpdateUpdatedAt() *EmployeeUpsert {
+	u.SetExcluded(employee.FieldUpdatedAt)
+	return u
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *EmployeeUpsert) SetDeletedAt(v time.Time) *EmployeeUpsert {
+	u.Set(employee.FieldDeletedAt, v)
+	return u
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *EmployeeUpsert) UpdateDeletedAt() *EmployeeUpsert {
+	u.SetExcluded(employee.FieldDeletedAt)
+	return u
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *EmployeeUpsert) ClearDeletedAt() *EmployeeUpsert {
+	u.SetNull(employee.FieldDeletedAt)
+	return u
+}
+
+// SetTitle sets the "title" field.
+func (u *EmployeeUpsert) SetTitle(v string) *EmployeeUpsert {
+	u.Set(employee.FieldTitle, v)
+	return u
+}
+
+// UpdateTitle sets the "title" field to the value that was provided on create.
+func (u *EmployeeUpsert) UpdateTitle() *EmployeeUpsert {
+	u.SetExcluded(employee.FieldTitle)
+	return u
+}
+
+// SetAvatar sets the "avatar" field.
+func (u *EmployeeUpsert) SetAvatar(v string) *EmployeeUpsert {
+	u.Set(employee.FieldAvatar, v)
+	return u
+}
+
+// UpdateAvatar sets the "avatar" field to the value that was provided on create.
+func (u *EmployeeUpsert) UpdateAvatar() *EmployeeUpsert {
+	u.SetExcluded(employee.FieldAvatar)
+	return u
+}
+
+// SetTags sets the "tags" field.
+func (u *EmployeeUpsert) SetTags(v string) *EmployeeUpsert {
+	u.Set(employee.FieldTags, v)
+	return u
+}
+
+// UpdateTags sets the "tags" field to the value that was provided on create.
+func (u *EmployeeUpsert) UpdateTags() *EmployeeUpsert {
+	u.SetExcluded(employee.FieldTags)
+	return u
+}
+
+// SetHireCount sets the "hire_count" field.
+func (u *EmployeeUpsert) SetHireCount(v int) *EmployeeUpsert {
+	u.Set(employee.FieldHireCount, v)
+	return u
+}
+
+// UpdateHireCount sets the "hire_count" field to the value that was provided on create.
+func (u *EmployeeUpsert) UpdateHireCount() *EmployeeUpsert {
+	u.SetExcluded(employee.FieldHireCount)
+	return u
+}
+
+// AddHireCount adds v to the "hire_count" field.
+func (u *EmployeeUpsert) AddHireCount(v int) *EmployeeUpsert {
+	u.Add(employee.FieldHireCount, v)
+	return u
+}
+
+// SetServiceCount sets the "service_count" field.
+func (u *EmployeeUpsert) SetServiceCount(v int) *EmployeeUpsert {
+	u.Set(employee.FieldServiceCount, v)
+	return u
+}
+
+// UpdateServiceCount sets the "service_count" field to the value that was provided on create.
+func (u *EmployeeUpsert) UpdateServiceCount() *EmployeeUpsert {
+	u.SetExcluded(employee.FieldServiceCount)
+	return u
+}
+
+// AddServiceCount adds v to the "service_count" field.
+func (u *EmployeeUpsert) AddServiceCount(v int) *EmployeeUpsert {
+	u.Add(employee.FieldServiceCount, v)
+	return u
+}
+
+// SetAchievementCount sets the "achievement_count" field.
+func (u *EmployeeUpsert) SetAchievementCount(v int) *EmployeeUpsert {
+	u.Set(employee.FieldAchievementCount, v)
+	return u
+}
+
+// UpdateAchievementCount sets the "achievement_count" field to the value that was provided on create.
+func (u *EmployeeUpsert) UpdateAchievementCount() *EmployeeUpsert {
+	u.SetExcluded(employee.FieldAchievementCount)
+	return u
+}
+
+// AddAchievementCount adds v to the "achievement_count" field.
+func (u *EmployeeUpsert) AddAchievementCount(v int) *EmployeeUpsert {
+	u.Add(employee.FieldAchievementCount, v)
+	return u
+}
+
+// SetIntro sets the "intro" field.
+func (u *EmployeeUpsert) SetIntro(v string) *EmployeeUpsert {
+	u.Set(employee.FieldIntro, v)
+	return u
+}
+
+// UpdateIntro sets the "intro" field to the value that was provided on create.
+func (u *EmployeeUpsert) UpdateIntro() *EmployeeUpsert {
+	u.SetExcluded(employee.FieldIntro)
+	return u
+}
+
+// SetEstimate sets the "estimate" field.
+func (u *EmployeeUpsert) SetEstimate(v string) *EmployeeUpsert {
+	u.Set(employee.FieldEstimate, v)
+	return u
+}
+
+// UpdateEstimate sets the "estimate" field to the value that was provided on create.
+func (u *EmployeeUpsert) UpdateEstimate() *EmployeeUpsert {
+	u.SetExcluded(employee.FieldEstimate)
+	return u
+}
+
+// SetSkill sets the "skill" field.
+func (u *EmployeeUpsert) SetSkill(v string) *EmployeeUpsert {
+	u.Set(employee.FieldSkill, v)
+	return u
+}
+
+// UpdateSkill sets the "skill" field to the value that was provided on create.
+func (u *EmployeeUpsert) UpdateSkill() *EmployeeUpsert {
+	u.SetExcluded(employee.FieldSkill)
+	return u
+}
+
+// SetAbilityType sets the "ability_type" field.
+func (u *EmployeeUpsert) SetAbilityType(v string) *EmployeeUpsert {
+	u.Set(employee.FieldAbilityType, v)
+	return u
+}
+
+// UpdateAbilityType sets the "ability_type" field to the value that was provided on create.
+func (u *EmployeeUpsert) UpdateAbilityType() *EmployeeUpsert {
+	u.SetExcluded(employee.FieldAbilityType)
+	return u
+}
+
+// SetScene sets the "scene" field.
+func (u *EmployeeUpsert) SetScene(v string) *EmployeeUpsert {
+	u.Set(employee.FieldScene, v)
+	return u
+}
+
+// UpdateScene sets the "scene" field to the value that was provided on create.
+func (u *EmployeeUpsert) UpdateScene() *EmployeeUpsert {
+	u.SetExcluded(employee.FieldScene)
+	return u
+}
+
+// SetSwitchIn sets the "switch_in" field.
+func (u *EmployeeUpsert) SetSwitchIn(v string) *EmployeeUpsert {
+	u.Set(employee.FieldSwitchIn, v)
+	return u
+}
+
+// UpdateSwitchIn sets the "switch_in" field to the value that was provided on create.
+func (u *EmployeeUpsert) UpdateSwitchIn() *EmployeeUpsert {
+	u.SetExcluded(employee.FieldSwitchIn)
+	return u
+}
+
+// SetVideoURL sets the "video_url" field.
+func (u *EmployeeUpsert) SetVideoURL(v string) *EmployeeUpsert {
+	u.Set(employee.FieldVideoURL, v)
+	return u
+}
+
+// UpdateVideoURL sets the "video_url" field to the value that was provided on create.
+func (u *EmployeeUpsert) UpdateVideoURL() *EmployeeUpsert {
+	u.SetExcluded(employee.FieldVideoURL)
+	return u
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (u *EmployeeUpsert) SetOrganizationID(v uint64) *EmployeeUpsert {
+	u.Set(employee.FieldOrganizationID, v)
+	return u
+}
+
+// UpdateOrganizationID sets the "organization_id" field to the value that was provided on create.
+func (u *EmployeeUpsert) UpdateOrganizationID() *EmployeeUpsert {
+	u.SetExcluded(employee.FieldOrganizationID)
+	return u
+}
+
+// AddOrganizationID adds v to the "organization_id" field.
+func (u *EmployeeUpsert) AddOrganizationID(v uint64) *EmployeeUpsert {
+	u.Add(employee.FieldOrganizationID, 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.Employee.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(employee.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *EmployeeUpsertOne) UpdateNewValues() *EmployeeUpsertOne {
+	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(employee.FieldID)
+		}
+		if _, exists := u.create.mutation.CreatedAt(); exists {
+			s.SetIgnore(employee.FieldCreatedAt)
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.Employee.Create().
+//	    OnConflict(sql.ResolveWithIgnore()).
+//	    Exec(ctx)
+func (u *EmployeeUpsertOne) Ignore() *EmployeeUpsertOne {
+	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 *EmployeeUpsertOne) DoNothing() *EmployeeUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the EmployeeCreate.OnConflict
+// documentation for more info.
+func (u *EmployeeUpsertOne) Update(set func(*EmployeeUpsert)) *EmployeeUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&EmployeeUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *EmployeeUpsertOne) SetUpdatedAt(v time.Time) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *EmployeeUpsertOne) UpdateUpdatedAt() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *EmployeeUpsertOne) SetDeletedAt(v time.Time) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *EmployeeUpsertOne) UpdateDeletedAt() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *EmployeeUpsertOne) ClearDeletedAt() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetTitle sets the "title" field.
+func (u *EmployeeUpsertOne) SetTitle(v string) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetTitle(v)
+	})
+}
+
+// UpdateTitle sets the "title" field to the value that was provided on create.
+func (u *EmployeeUpsertOne) UpdateTitle() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateTitle()
+	})
+}
+
+// SetAvatar sets the "avatar" field.
+func (u *EmployeeUpsertOne) SetAvatar(v string) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetAvatar(v)
+	})
+}
+
+// UpdateAvatar sets the "avatar" field to the value that was provided on create.
+func (u *EmployeeUpsertOne) UpdateAvatar() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateAvatar()
+	})
+}
+
+// SetTags sets the "tags" field.
+func (u *EmployeeUpsertOne) SetTags(v string) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetTags(v)
+	})
+}
+
+// UpdateTags sets the "tags" field to the value that was provided on create.
+func (u *EmployeeUpsertOne) UpdateTags() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateTags()
+	})
+}
+
+// SetHireCount sets the "hire_count" field.
+func (u *EmployeeUpsertOne) SetHireCount(v int) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetHireCount(v)
+	})
+}
+
+// AddHireCount adds v to the "hire_count" field.
+func (u *EmployeeUpsertOne) AddHireCount(v int) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.AddHireCount(v)
+	})
+}
+
+// UpdateHireCount sets the "hire_count" field to the value that was provided on create.
+func (u *EmployeeUpsertOne) UpdateHireCount() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateHireCount()
+	})
+}
+
+// SetServiceCount sets the "service_count" field.
+func (u *EmployeeUpsertOne) SetServiceCount(v int) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetServiceCount(v)
+	})
+}
+
+// AddServiceCount adds v to the "service_count" field.
+func (u *EmployeeUpsertOne) AddServiceCount(v int) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.AddServiceCount(v)
+	})
+}
+
+// UpdateServiceCount sets the "service_count" field to the value that was provided on create.
+func (u *EmployeeUpsertOne) UpdateServiceCount() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateServiceCount()
+	})
+}
+
+// SetAchievementCount sets the "achievement_count" field.
+func (u *EmployeeUpsertOne) SetAchievementCount(v int) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetAchievementCount(v)
+	})
+}
+
+// AddAchievementCount adds v to the "achievement_count" field.
+func (u *EmployeeUpsertOne) AddAchievementCount(v int) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.AddAchievementCount(v)
+	})
+}
+
+// UpdateAchievementCount sets the "achievement_count" field to the value that was provided on create.
+func (u *EmployeeUpsertOne) UpdateAchievementCount() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateAchievementCount()
+	})
+}
+
+// SetIntro sets the "intro" field.
+func (u *EmployeeUpsertOne) SetIntro(v string) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetIntro(v)
+	})
+}
+
+// UpdateIntro sets the "intro" field to the value that was provided on create.
+func (u *EmployeeUpsertOne) UpdateIntro() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateIntro()
+	})
+}
+
+// SetEstimate sets the "estimate" field.
+func (u *EmployeeUpsertOne) SetEstimate(v string) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetEstimate(v)
+	})
+}
+
+// UpdateEstimate sets the "estimate" field to the value that was provided on create.
+func (u *EmployeeUpsertOne) UpdateEstimate() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateEstimate()
+	})
+}
+
+// SetSkill sets the "skill" field.
+func (u *EmployeeUpsertOne) SetSkill(v string) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetSkill(v)
+	})
+}
+
+// UpdateSkill sets the "skill" field to the value that was provided on create.
+func (u *EmployeeUpsertOne) UpdateSkill() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateSkill()
+	})
+}
+
+// SetAbilityType sets the "ability_type" field.
+func (u *EmployeeUpsertOne) SetAbilityType(v string) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetAbilityType(v)
+	})
+}
+
+// UpdateAbilityType sets the "ability_type" field to the value that was provided on create.
+func (u *EmployeeUpsertOne) UpdateAbilityType() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateAbilityType()
+	})
+}
+
+// SetScene sets the "scene" field.
+func (u *EmployeeUpsertOne) SetScene(v string) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetScene(v)
+	})
+}
+
+// UpdateScene sets the "scene" field to the value that was provided on create.
+func (u *EmployeeUpsertOne) UpdateScene() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateScene()
+	})
+}
+
+// SetSwitchIn sets the "switch_in" field.
+func (u *EmployeeUpsertOne) SetSwitchIn(v string) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetSwitchIn(v)
+	})
+}
+
+// UpdateSwitchIn sets the "switch_in" field to the value that was provided on create.
+func (u *EmployeeUpsertOne) UpdateSwitchIn() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateSwitchIn()
+	})
+}
+
+// SetVideoURL sets the "video_url" field.
+func (u *EmployeeUpsertOne) SetVideoURL(v string) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetVideoURL(v)
+	})
+}
+
+// UpdateVideoURL sets the "video_url" field to the value that was provided on create.
+func (u *EmployeeUpsertOne) UpdateVideoURL() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateVideoURL()
+	})
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (u *EmployeeUpsertOne) SetOrganizationID(v uint64) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetOrganizationID(v)
+	})
+}
+
+// AddOrganizationID adds v to the "organization_id" field.
+func (u *EmployeeUpsertOne) AddOrganizationID(v uint64) *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.AddOrganizationID(v)
+	})
+}
+
+// UpdateOrganizationID sets the "organization_id" field to the value that was provided on create.
+func (u *EmployeeUpsertOne) UpdateOrganizationID() *EmployeeUpsertOne {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateOrganizationID()
+	})
+}
+
+// Exec executes the query.
+func (u *EmployeeUpsertOne) Exec(ctx context.Context) error {
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for EmployeeCreate.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *EmployeeUpsertOne) 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 *EmployeeUpsertOne) 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 *EmployeeUpsertOne) IDX(ctx context.Context) uint64 {
+	id, err := u.ID(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+// EmployeeCreateBulk is the builder for creating many Employee entities in bulk.
+type EmployeeCreateBulk struct {
+	config
+	err      error
+	builders []*EmployeeCreate
+	conflict []sql.ConflictOption
+}
+
+// Save creates the Employee entities in the database.
+func (ecb *EmployeeCreateBulk) Save(ctx context.Context) ([]*Employee, error) {
+	if ecb.err != nil {
+		return nil, ecb.err
+	}
+	specs := make([]*sqlgraph.CreateSpec, len(ecb.builders))
+	nodes := make([]*Employee, len(ecb.builders))
+	mutators := make([]Mutator, len(ecb.builders))
+	for i := range ecb.builders {
+		func(i int, root context.Context) {
+			builder := ecb.builders[i]
+			builder.defaults()
+			var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
+				mutation, ok := m.(*EmployeeMutation)
+				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, ecb.builders[i+1].mutation)
+				} else {
+					spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
+					spec.OnConflict = ecb.conflict
+					// Invoke the actual operation on the latest mutation in the chain.
+					if err = sqlgraph.BatchCreate(ctx, ecb.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, ecb.builders[0].mutation); err != nil {
+			return nil, err
+		}
+	}
+	return nodes, nil
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (ecb *EmployeeCreateBulk) SaveX(ctx context.Context) []*Employee {
+	v, err := ecb.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (ecb *EmployeeCreateBulk) Exec(ctx context.Context) error {
+	_, err := ecb.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (ecb *EmployeeCreateBulk) ExecX(ctx context.Context) {
+	if err := ecb.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.Employee.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.EmployeeUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (ecb *EmployeeCreateBulk) OnConflict(opts ...sql.ConflictOption) *EmployeeUpsertBulk {
+	ecb.conflict = opts
+	return &EmployeeUpsertBulk{
+		create: ecb,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.Employee.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (ecb *EmployeeCreateBulk) OnConflictColumns(columns ...string) *EmployeeUpsertBulk {
+	ecb.conflict = append(ecb.conflict, sql.ConflictColumns(columns...))
+	return &EmployeeUpsertBulk{
+		create: ecb,
+	}
+}
+
+// EmployeeUpsertBulk is the builder for "upsert"-ing
+// a bulk of Employee nodes.
+type EmployeeUpsertBulk struct {
+	create *EmployeeCreateBulk
+}
+
+// UpdateNewValues updates the mutable fields using the new values that
+// were set on create. Using this option is equivalent to using:
+//
+//	client.Employee.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(employee.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *EmployeeUpsertBulk) UpdateNewValues() *EmployeeUpsertBulk {
+	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(employee.FieldID)
+			}
+			if _, exists := b.mutation.CreatedAt(); exists {
+				s.SetIgnore(employee.FieldCreatedAt)
+			}
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.Employee.Create().
+//		OnConflict(sql.ResolveWithIgnore()).
+//		Exec(ctx)
+func (u *EmployeeUpsertBulk) Ignore() *EmployeeUpsertBulk {
+	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 *EmployeeUpsertBulk) DoNothing() *EmployeeUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the EmployeeCreateBulk.OnConflict
+// documentation for more info.
+func (u *EmployeeUpsertBulk) Update(set func(*EmployeeUpsert)) *EmployeeUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&EmployeeUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *EmployeeUpsertBulk) SetUpdatedAt(v time.Time) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *EmployeeUpsertBulk) UpdateUpdatedAt() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *EmployeeUpsertBulk) SetDeletedAt(v time.Time) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *EmployeeUpsertBulk) UpdateDeletedAt() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *EmployeeUpsertBulk) ClearDeletedAt() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetTitle sets the "title" field.
+func (u *EmployeeUpsertBulk) SetTitle(v string) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetTitle(v)
+	})
+}
+
+// UpdateTitle sets the "title" field to the value that was provided on create.
+func (u *EmployeeUpsertBulk) UpdateTitle() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateTitle()
+	})
+}
+
+// SetAvatar sets the "avatar" field.
+func (u *EmployeeUpsertBulk) SetAvatar(v string) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetAvatar(v)
+	})
+}
+
+// UpdateAvatar sets the "avatar" field to the value that was provided on create.
+func (u *EmployeeUpsertBulk) UpdateAvatar() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateAvatar()
+	})
+}
+
+// SetTags sets the "tags" field.
+func (u *EmployeeUpsertBulk) SetTags(v string) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetTags(v)
+	})
+}
+
+// UpdateTags sets the "tags" field to the value that was provided on create.
+func (u *EmployeeUpsertBulk) UpdateTags() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateTags()
+	})
+}
+
+// SetHireCount sets the "hire_count" field.
+func (u *EmployeeUpsertBulk) SetHireCount(v int) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetHireCount(v)
+	})
+}
+
+// AddHireCount adds v to the "hire_count" field.
+func (u *EmployeeUpsertBulk) AddHireCount(v int) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.AddHireCount(v)
+	})
+}
+
+// UpdateHireCount sets the "hire_count" field to the value that was provided on create.
+func (u *EmployeeUpsertBulk) UpdateHireCount() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateHireCount()
+	})
+}
+
+// SetServiceCount sets the "service_count" field.
+func (u *EmployeeUpsertBulk) SetServiceCount(v int) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetServiceCount(v)
+	})
+}
+
+// AddServiceCount adds v to the "service_count" field.
+func (u *EmployeeUpsertBulk) AddServiceCount(v int) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.AddServiceCount(v)
+	})
+}
+
+// UpdateServiceCount sets the "service_count" field to the value that was provided on create.
+func (u *EmployeeUpsertBulk) UpdateServiceCount() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateServiceCount()
+	})
+}
+
+// SetAchievementCount sets the "achievement_count" field.
+func (u *EmployeeUpsertBulk) SetAchievementCount(v int) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetAchievementCount(v)
+	})
+}
+
+// AddAchievementCount adds v to the "achievement_count" field.
+func (u *EmployeeUpsertBulk) AddAchievementCount(v int) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.AddAchievementCount(v)
+	})
+}
+
+// UpdateAchievementCount sets the "achievement_count" field to the value that was provided on create.
+func (u *EmployeeUpsertBulk) UpdateAchievementCount() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateAchievementCount()
+	})
+}
+
+// SetIntro sets the "intro" field.
+func (u *EmployeeUpsertBulk) SetIntro(v string) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetIntro(v)
+	})
+}
+
+// UpdateIntro sets the "intro" field to the value that was provided on create.
+func (u *EmployeeUpsertBulk) UpdateIntro() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateIntro()
+	})
+}
+
+// SetEstimate sets the "estimate" field.
+func (u *EmployeeUpsertBulk) SetEstimate(v string) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetEstimate(v)
+	})
+}
+
+// UpdateEstimate sets the "estimate" field to the value that was provided on create.
+func (u *EmployeeUpsertBulk) UpdateEstimate() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateEstimate()
+	})
+}
+
+// SetSkill sets the "skill" field.
+func (u *EmployeeUpsertBulk) SetSkill(v string) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetSkill(v)
+	})
+}
+
+// UpdateSkill sets the "skill" field to the value that was provided on create.
+func (u *EmployeeUpsertBulk) UpdateSkill() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateSkill()
+	})
+}
+
+// SetAbilityType sets the "ability_type" field.
+func (u *EmployeeUpsertBulk) SetAbilityType(v string) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetAbilityType(v)
+	})
+}
+
+// UpdateAbilityType sets the "ability_type" field to the value that was provided on create.
+func (u *EmployeeUpsertBulk) UpdateAbilityType() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateAbilityType()
+	})
+}
+
+// SetScene sets the "scene" field.
+func (u *EmployeeUpsertBulk) SetScene(v string) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetScene(v)
+	})
+}
+
+// UpdateScene sets the "scene" field to the value that was provided on create.
+func (u *EmployeeUpsertBulk) UpdateScene() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateScene()
+	})
+}
+
+// SetSwitchIn sets the "switch_in" field.
+func (u *EmployeeUpsertBulk) SetSwitchIn(v string) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetSwitchIn(v)
+	})
+}
+
+// UpdateSwitchIn sets the "switch_in" field to the value that was provided on create.
+func (u *EmployeeUpsertBulk) UpdateSwitchIn() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateSwitchIn()
+	})
+}
+
+// SetVideoURL sets the "video_url" field.
+func (u *EmployeeUpsertBulk) SetVideoURL(v string) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetVideoURL(v)
+	})
+}
+
+// UpdateVideoURL sets the "video_url" field to the value that was provided on create.
+func (u *EmployeeUpsertBulk) UpdateVideoURL() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateVideoURL()
+	})
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (u *EmployeeUpsertBulk) SetOrganizationID(v uint64) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.SetOrganizationID(v)
+	})
+}
+
+// AddOrganizationID adds v to the "organization_id" field.
+func (u *EmployeeUpsertBulk) AddOrganizationID(v uint64) *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.AddOrganizationID(v)
+	})
+}
+
+// UpdateOrganizationID sets the "organization_id" field to the value that was provided on create.
+func (u *EmployeeUpsertBulk) UpdateOrganizationID() *EmployeeUpsertBulk {
+	return u.Update(func(s *EmployeeUpsert) {
+		s.UpdateOrganizationID()
+	})
+}
+
+// Exec executes the query.
+func (u *EmployeeUpsertBulk) 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 EmployeeCreateBulk instead", i)
+		}
+	}
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for EmployeeCreateBulk.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *EmployeeUpsertBulk) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}

+ 88 - 0
ent/employee_delete.go

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

+ 679 - 0
ent/employee_query.go

@@ -0,0 +1,679 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"database/sql/driver"
+	"fmt"
+	"math"
+	"wechat-api/ent/employee"
+	"wechat-api/ent/predicate"
+	"wechat-api/ent/tutorial"
+	"wechat-api/ent/workexperience"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// EmployeeQuery is the builder for querying Employee entities.
+type EmployeeQuery struct {
+	config
+	ctx                   *QueryContext
+	order                 []employee.OrderOption
+	inters                []Interceptor
+	predicates            []predicate.Employee
+	withEmWorkExperiences *WorkExperienceQuery
+	withEmTutorial        *TutorialQuery
+	// intermediate query (i.e. traversal path).
+	sql  *sql.Selector
+	path func(context.Context) (*sql.Selector, error)
+}
+
+// Where adds a new predicate for the EmployeeQuery builder.
+func (eq *EmployeeQuery) Where(ps ...predicate.Employee) *EmployeeQuery {
+	eq.predicates = append(eq.predicates, ps...)
+	return eq
+}
+
+// Limit the number of records to be returned by this query.
+func (eq *EmployeeQuery) Limit(limit int) *EmployeeQuery {
+	eq.ctx.Limit = &limit
+	return eq
+}
+
+// Offset to start from.
+func (eq *EmployeeQuery) Offset(offset int) *EmployeeQuery {
+	eq.ctx.Offset = &offset
+	return eq
+}
+
+// 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 (eq *EmployeeQuery) Unique(unique bool) *EmployeeQuery {
+	eq.ctx.Unique = &unique
+	return eq
+}
+
+// Order specifies how the records should be ordered.
+func (eq *EmployeeQuery) Order(o ...employee.OrderOption) *EmployeeQuery {
+	eq.order = append(eq.order, o...)
+	return eq
+}
+
+// QueryEmWorkExperiences chains the current query on the "em_work_experiences" edge.
+func (eq *EmployeeQuery) QueryEmWorkExperiences() *WorkExperienceQuery {
+	query := (&WorkExperienceClient{config: eq.config}).Query()
+	query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+		if err := eq.prepareQuery(ctx); err != nil {
+			return nil, err
+		}
+		selector := eq.sqlQuery(ctx)
+		if err := selector.Err(); err != nil {
+			return nil, err
+		}
+		step := sqlgraph.NewStep(
+			sqlgraph.From(employee.Table, employee.FieldID, selector),
+			sqlgraph.To(workexperience.Table, workexperience.FieldID),
+			sqlgraph.Edge(sqlgraph.O2M, false, employee.EmWorkExperiencesTable, employee.EmWorkExperiencesColumn),
+		)
+		fromU = sqlgraph.SetNeighbors(eq.driver.Dialect(), step)
+		return fromU, nil
+	}
+	return query
+}
+
+// QueryEmTutorial chains the current query on the "em_tutorial" edge.
+func (eq *EmployeeQuery) QueryEmTutorial() *TutorialQuery {
+	query := (&TutorialClient{config: eq.config}).Query()
+	query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+		if err := eq.prepareQuery(ctx); err != nil {
+			return nil, err
+		}
+		selector := eq.sqlQuery(ctx)
+		if err := selector.Err(); err != nil {
+			return nil, err
+		}
+		step := sqlgraph.NewStep(
+			sqlgraph.From(employee.Table, employee.FieldID, selector),
+			sqlgraph.To(tutorial.Table, tutorial.FieldID),
+			sqlgraph.Edge(sqlgraph.O2M, false, employee.EmTutorialTable, employee.EmTutorialColumn),
+		)
+		fromU = sqlgraph.SetNeighbors(eq.driver.Dialect(), step)
+		return fromU, nil
+	}
+	return query
+}
+
+// First returns the first Employee entity from the query.
+// Returns a *NotFoundError when no Employee was found.
+func (eq *EmployeeQuery) First(ctx context.Context) (*Employee, error) {
+	nodes, err := eq.Limit(1).All(setContextOp(ctx, eq.ctx, "First"))
+	if err != nil {
+		return nil, err
+	}
+	if len(nodes) == 0 {
+		return nil, &NotFoundError{employee.Label}
+	}
+	return nodes[0], nil
+}
+
+// FirstX is like First, but panics if an error occurs.
+func (eq *EmployeeQuery) FirstX(ctx context.Context) *Employee {
+	node, err := eq.First(ctx)
+	if err != nil && !IsNotFound(err) {
+		panic(err)
+	}
+	return node
+}
+
+// FirstID returns the first Employee ID from the query.
+// Returns a *NotFoundError when no Employee ID was found.
+func (eq *EmployeeQuery) FirstID(ctx context.Context) (id uint64, err error) {
+	var ids []uint64
+	if ids, err = eq.Limit(1).IDs(setContextOp(ctx, eq.ctx, "FirstID")); err != nil {
+		return
+	}
+	if len(ids) == 0 {
+		err = &NotFoundError{employee.Label}
+		return
+	}
+	return ids[0], nil
+}
+
+// FirstIDX is like FirstID, but panics if an error occurs.
+func (eq *EmployeeQuery) FirstIDX(ctx context.Context) uint64 {
+	id, err := eq.FirstID(ctx)
+	if err != nil && !IsNotFound(err) {
+		panic(err)
+	}
+	return id
+}
+
+// Only returns a single Employee entity found by the query, ensuring it only returns one.
+// Returns a *NotSingularError when more than one Employee entity is found.
+// Returns a *NotFoundError when no Employee entities are found.
+func (eq *EmployeeQuery) Only(ctx context.Context) (*Employee, error) {
+	nodes, err := eq.Limit(2).All(setContextOp(ctx, eq.ctx, "Only"))
+	if err != nil {
+		return nil, err
+	}
+	switch len(nodes) {
+	case 1:
+		return nodes[0], nil
+	case 0:
+		return nil, &NotFoundError{employee.Label}
+	default:
+		return nil, &NotSingularError{employee.Label}
+	}
+}
+
+// OnlyX is like Only, but panics if an error occurs.
+func (eq *EmployeeQuery) OnlyX(ctx context.Context) *Employee {
+	node, err := eq.Only(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return node
+}
+
+// OnlyID is like Only, but returns the only Employee ID in the query.
+// Returns a *NotSingularError when more than one Employee ID is found.
+// Returns a *NotFoundError when no entities are found.
+func (eq *EmployeeQuery) OnlyID(ctx context.Context) (id uint64, err error) {
+	var ids []uint64
+	if ids, err = eq.Limit(2).IDs(setContextOp(ctx, eq.ctx, "OnlyID")); err != nil {
+		return
+	}
+	switch len(ids) {
+	case 1:
+		id = ids[0]
+	case 0:
+		err = &NotFoundError{employee.Label}
+	default:
+		err = &NotSingularError{employee.Label}
+	}
+	return
+}
+
+// OnlyIDX is like OnlyID, but panics if an error occurs.
+func (eq *EmployeeQuery) OnlyIDX(ctx context.Context) uint64 {
+	id, err := eq.OnlyID(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+// All executes the query and returns a list of Employees.
+func (eq *EmployeeQuery) All(ctx context.Context) ([]*Employee, error) {
+	ctx = setContextOp(ctx, eq.ctx, "All")
+	if err := eq.prepareQuery(ctx); err != nil {
+		return nil, err
+	}
+	qr := querierAll[[]*Employee, *EmployeeQuery]()
+	return withInterceptors[[]*Employee](ctx, eq, qr, eq.inters)
+}
+
+// AllX is like All, but panics if an error occurs.
+func (eq *EmployeeQuery) AllX(ctx context.Context) []*Employee {
+	nodes, err := eq.All(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return nodes
+}
+
+// IDs executes the query and returns a list of Employee IDs.
+func (eq *EmployeeQuery) IDs(ctx context.Context) (ids []uint64, err error) {
+	if eq.ctx.Unique == nil && eq.path != nil {
+		eq.Unique(true)
+	}
+	ctx = setContextOp(ctx, eq.ctx, "IDs")
+	if err = eq.Select(employee.FieldID).Scan(ctx, &ids); err != nil {
+		return nil, err
+	}
+	return ids, nil
+}
+
+// IDsX is like IDs, but panics if an error occurs.
+func (eq *EmployeeQuery) IDsX(ctx context.Context) []uint64 {
+	ids, err := eq.IDs(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return ids
+}
+
+// Count returns the count of the given query.
+func (eq *EmployeeQuery) Count(ctx context.Context) (int, error) {
+	ctx = setContextOp(ctx, eq.ctx, "Count")
+	if err := eq.prepareQuery(ctx); err != nil {
+		return 0, err
+	}
+	return withInterceptors[int](ctx, eq, querierCount[*EmployeeQuery](), eq.inters)
+}
+
+// CountX is like Count, but panics if an error occurs.
+func (eq *EmployeeQuery) CountX(ctx context.Context) int {
+	count, err := eq.Count(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return count
+}
+
+// Exist returns true if the query has elements in the graph.
+func (eq *EmployeeQuery) Exist(ctx context.Context) (bool, error) {
+	ctx = setContextOp(ctx, eq.ctx, "Exist")
+	switch _, err := eq.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 (eq *EmployeeQuery) ExistX(ctx context.Context) bool {
+	exist, err := eq.Exist(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return exist
+}
+
+// Clone returns a duplicate of the EmployeeQuery builder, including all associated steps. It can be
+// used to prepare common query builders and use them differently after the clone is made.
+func (eq *EmployeeQuery) Clone() *EmployeeQuery {
+	if eq == nil {
+		return nil
+	}
+	return &EmployeeQuery{
+		config:                eq.config,
+		ctx:                   eq.ctx.Clone(),
+		order:                 append([]employee.OrderOption{}, eq.order...),
+		inters:                append([]Interceptor{}, eq.inters...),
+		predicates:            append([]predicate.Employee{}, eq.predicates...),
+		withEmWorkExperiences: eq.withEmWorkExperiences.Clone(),
+		withEmTutorial:        eq.withEmTutorial.Clone(),
+		// clone intermediate query.
+		sql:  eq.sql.Clone(),
+		path: eq.path,
+	}
+}
+
+// WithEmWorkExperiences tells the query-builder to eager-load the nodes that are connected to
+// the "em_work_experiences" edge. The optional arguments are used to configure the query builder of the edge.
+func (eq *EmployeeQuery) WithEmWorkExperiences(opts ...func(*WorkExperienceQuery)) *EmployeeQuery {
+	query := (&WorkExperienceClient{config: eq.config}).Query()
+	for _, opt := range opts {
+		opt(query)
+	}
+	eq.withEmWorkExperiences = query
+	return eq
+}
+
+// WithEmTutorial tells the query-builder to eager-load the nodes that are connected to
+// the "em_tutorial" edge. The optional arguments are used to configure the query builder of the edge.
+func (eq *EmployeeQuery) WithEmTutorial(opts ...func(*TutorialQuery)) *EmployeeQuery {
+	query := (&TutorialClient{config: eq.config}).Query()
+	for _, opt := range opts {
+		opt(query)
+	}
+	eq.withEmTutorial = query
+	return eq
+}
+
+// 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.Employee.Query().
+//		GroupBy(employee.FieldCreatedAt).
+//		Aggregate(ent.Count()).
+//		Scan(ctx, &v)
+func (eq *EmployeeQuery) GroupBy(field string, fields ...string) *EmployeeGroupBy {
+	eq.ctx.Fields = append([]string{field}, fields...)
+	grbuild := &EmployeeGroupBy{build: eq}
+	grbuild.flds = &eq.ctx.Fields
+	grbuild.label = employee.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.Employee.Query().
+//		Select(employee.FieldCreatedAt).
+//		Scan(ctx, &v)
+func (eq *EmployeeQuery) Select(fields ...string) *EmployeeSelect {
+	eq.ctx.Fields = append(eq.ctx.Fields, fields...)
+	sbuild := &EmployeeSelect{EmployeeQuery: eq}
+	sbuild.label = employee.Label
+	sbuild.flds, sbuild.scan = &eq.ctx.Fields, sbuild.Scan
+	return sbuild
+}
+
+// Aggregate returns a EmployeeSelect configured with the given aggregations.
+func (eq *EmployeeQuery) Aggregate(fns ...AggregateFunc) *EmployeeSelect {
+	return eq.Select().Aggregate(fns...)
+}
+
+func (eq *EmployeeQuery) prepareQuery(ctx context.Context) error {
+	for _, inter := range eq.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, eq); err != nil {
+				return err
+			}
+		}
+	}
+	for _, f := range eq.ctx.Fields {
+		if !employee.ValidColumn(f) {
+			return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+		}
+	}
+	if eq.path != nil {
+		prev, err := eq.path(ctx)
+		if err != nil {
+			return err
+		}
+		eq.sql = prev
+	}
+	return nil
+}
+
+func (eq *EmployeeQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Employee, error) {
+	var (
+		nodes       = []*Employee{}
+		_spec       = eq.querySpec()
+		loadedTypes = [2]bool{
+			eq.withEmWorkExperiences != nil,
+			eq.withEmTutorial != nil,
+		}
+	)
+	_spec.ScanValues = func(columns []string) ([]any, error) {
+		return (*Employee).scanValues(nil, columns)
+	}
+	_spec.Assign = func(columns []string, values []any) error {
+		node := &Employee{config: eq.config}
+		nodes = append(nodes, node)
+		node.Edges.loadedTypes = loadedTypes
+		return node.assignValues(columns, values)
+	}
+	for i := range hooks {
+		hooks[i](ctx, _spec)
+	}
+	if err := sqlgraph.QueryNodes(ctx, eq.driver, _spec); err != nil {
+		return nil, err
+	}
+	if len(nodes) == 0 {
+		return nodes, nil
+	}
+	if query := eq.withEmWorkExperiences; query != nil {
+		if err := eq.loadEmWorkExperiences(ctx, query, nodes,
+			func(n *Employee) { n.Edges.EmWorkExperiences = []*WorkExperience{} },
+			func(n *Employee, e *WorkExperience) { n.Edges.EmWorkExperiences = append(n.Edges.EmWorkExperiences, e) }); err != nil {
+			return nil, err
+		}
+	}
+	if query := eq.withEmTutorial; query != nil {
+		if err := eq.loadEmTutorial(ctx, query, nodes,
+			func(n *Employee) { n.Edges.EmTutorial = []*Tutorial{} },
+			func(n *Employee, e *Tutorial) { n.Edges.EmTutorial = append(n.Edges.EmTutorial, e) }); err != nil {
+			return nil, err
+		}
+	}
+	return nodes, nil
+}
+
+func (eq *EmployeeQuery) loadEmWorkExperiences(ctx context.Context, query *WorkExperienceQuery, nodes []*Employee, init func(*Employee), assign func(*Employee, *WorkExperience)) error {
+	fks := make([]driver.Value, 0, len(nodes))
+	nodeids := make(map[uint64]*Employee)
+	for i := range nodes {
+		fks = append(fks, nodes[i].ID)
+		nodeids[nodes[i].ID] = nodes[i]
+		if init != nil {
+			init(nodes[i])
+		}
+	}
+	if len(query.ctx.Fields) > 0 {
+		query.ctx.AppendFieldOnce(workexperience.FieldEmployeeID)
+	}
+	query.Where(predicate.WorkExperience(func(s *sql.Selector) {
+		s.Where(sql.InValues(s.C(employee.EmWorkExperiencesColumn), fks...))
+	}))
+	neighbors, err := query.All(ctx)
+	if err != nil {
+		return err
+	}
+	for _, n := range neighbors {
+		fk := n.EmployeeID
+		node, ok := nodeids[fk]
+		if !ok {
+			return fmt.Errorf(`unexpected referenced foreign-key "employee_id" returned %v for node %v`, fk, n.ID)
+		}
+		assign(node, n)
+	}
+	return nil
+}
+func (eq *EmployeeQuery) loadEmTutorial(ctx context.Context, query *TutorialQuery, nodes []*Employee, init func(*Employee), assign func(*Employee, *Tutorial)) error {
+	fks := make([]driver.Value, 0, len(nodes))
+	nodeids := make(map[uint64]*Employee)
+	for i := range nodes {
+		fks = append(fks, nodes[i].ID)
+		nodeids[nodes[i].ID] = nodes[i]
+		if init != nil {
+			init(nodes[i])
+		}
+	}
+	if len(query.ctx.Fields) > 0 {
+		query.ctx.AppendFieldOnce(tutorial.FieldEmployeeID)
+	}
+	query.Where(predicate.Tutorial(func(s *sql.Selector) {
+		s.Where(sql.InValues(s.C(employee.EmTutorialColumn), fks...))
+	}))
+	neighbors, err := query.All(ctx)
+	if err != nil {
+		return err
+	}
+	for _, n := range neighbors {
+		fk := n.EmployeeID
+		node, ok := nodeids[fk]
+		if !ok {
+			return fmt.Errorf(`unexpected referenced foreign-key "employee_id" returned %v for node %v`, fk, n.ID)
+		}
+		assign(node, n)
+	}
+	return nil
+}
+
+func (eq *EmployeeQuery) sqlCount(ctx context.Context) (int, error) {
+	_spec := eq.querySpec()
+	_spec.Node.Columns = eq.ctx.Fields
+	if len(eq.ctx.Fields) > 0 {
+		_spec.Unique = eq.ctx.Unique != nil && *eq.ctx.Unique
+	}
+	return sqlgraph.CountNodes(ctx, eq.driver, _spec)
+}
+
+func (eq *EmployeeQuery) querySpec() *sqlgraph.QuerySpec {
+	_spec := sqlgraph.NewQuerySpec(employee.Table, employee.Columns, sqlgraph.NewFieldSpec(employee.FieldID, field.TypeUint64))
+	_spec.From = eq.sql
+	if unique := eq.ctx.Unique; unique != nil {
+		_spec.Unique = *unique
+	} else if eq.path != nil {
+		_spec.Unique = true
+	}
+	if fields := eq.ctx.Fields; len(fields) > 0 {
+		_spec.Node.Columns = make([]string, 0, len(fields))
+		_spec.Node.Columns = append(_spec.Node.Columns, employee.FieldID)
+		for i := range fields {
+			if fields[i] != employee.FieldID {
+				_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
+			}
+		}
+	}
+	if ps := eq.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if limit := eq.ctx.Limit; limit != nil {
+		_spec.Limit = *limit
+	}
+	if offset := eq.ctx.Offset; offset != nil {
+		_spec.Offset = *offset
+	}
+	if ps := eq.order; len(ps) > 0 {
+		_spec.Order = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	return _spec
+}
+
+func (eq *EmployeeQuery) sqlQuery(ctx context.Context) *sql.Selector {
+	builder := sql.Dialect(eq.driver.Dialect())
+	t1 := builder.Table(employee.Table)
+	columns := eq.ctx.Fields
+	if len(columns) == 0 {
+		columns = employee.Columns
+	}
+	selector := builder.Select(t1.Columns(columns...)...).From(t1)
+	if eq.sql != nil {
+		selector = eq.sql
+		selector.Select(selector.Columns(columns...)...)
+	}
+	if eq.ctx.Unique != nil && *eq.ctx.Unique {
+		selector.Distinct()
+	}
+	for _, p := range eq.predicates {
+		p(selector)
+	}
+	for _, p := range eq.order {
+		p(selector)
+	}
+	if offset := eq.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 := eq.ctx.Limit; limit != nil {
+		selector.Limit(*limit)
+	}
+	return selector
+}
+
+// EmployeeGroupBy is the group-by builder for Employee entities.
+type EmployeeGroupBy struct {
+	selector
+	build *EmployeeQuery
+}
+
+// Aggregate adds the given aggregation functions to the group-by query.
+func (egb *EmployeeGroupBy) Aggregate(fns ...AggregateFunc) *EmployeeGroupBy {
+	egb.fns = append(egb.fns, fns...)
+	return egb
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (egb *EmployeeGroupBy) Scan(ctx context.Context, v any) error {
+	ctx = setContextOp(ctx, egb.build.ctx, "GroupBy")
+	if err := egb.build.prepareQuery(ctx); err != nil {
+		return err
+	}
+	return scanWithInterceptors[*EmployeeQuery, *EmployeeGroupBy](ctx, egb.build, egb, egb.build.inters, v)
+}
+
+func (egb *EmployeeGroupBy) sqlScan(ctx context.Context, root *EmployeeQuery, v any) error {
+	selector := root.sqlQuery(ctx).Select()
+	aggregation := make([]string, 0, len(egb.fns))
+	for _, fn := range egb.fns {
+		aggregation = append(aggregation, fn(selector))
+	}
+	if len(selector.SelectedColumns()) == 0 {
+		columns := make([]string, 0, len(*egb.flds)+len(egb.fns))
+		for _, f := range *egb.flds {
+			columns = append(columns, selector.C(f))
+		}
+		columns = append(columns, aggregation...)
+		selector.Select(columns...)
+	}
+	selector.GroupBy(selector.Columns(*egb.flds...)...)
+	if err := selector.Err(); err != nil {
+		return err
+	}
+	rows := &sql.Rows{}
+	query, args := selector.Query()
+	if err := egb.build.driver.Query(ctx, query, args, rows); err != nil {
+		return err
+	}
+	defer rows.Close()
+	return sql.ScanSlice(rows, v)
+}
+
+// EmployeeSelect is the builder for selecting fields of Employee entities.
+type EmployeeSelect struct {
+	*EmployeeQuery
+	selector
+}
+
+// Aggregate adds the given aggregation functions to the selector query.
+func (es *EmployeeSelect) Aggregate(fns ...AggregateFunc) *EmployeeSelect {
+	es.fns = append(es.fns, fns...)
+	return es
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (es *EmployeeSelect) Scan(ctx context.Context, v any) error {
+	ctx = setContextOp(ctx, es.ctx, "Select")
+	if err := es.prepareQuery(ctx); err != nil {
+		return err
+	}
+	return scanWithInterceptors[*EmployeeQuery, *EmployeeSelect](ctx, es.EmployeeQuery, es, es.inters, v)
+}
+
+func (es *EmployeeSelect) sqlScan(ctx context.Context, root *EmployeeQuery, v any) error {
+	selector := root.sqlQuery(ctx)
+	aggregation := make([]string, 0, len(es.fns))
+	for _, fn := range es.fns {
+		aggregation = append(aggregation, fn(selector))
+	}
+	switch n := len(*es.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 := es.driver.Query(ctx, query, args, rows); err != nil {
+		return err
+	}
+	defer rows.Close()
+	return sql.ScanSlice(rows, v)
+}

+ 1284 - 0
ent/employee_update.go

@@ -0,0 +1,1284 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/employee"
+	"wechat-api/ent/predicate"
+	"wechat-api/ent/tutorial"
+	"wechat-api/ent/workexperience"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// EmployeeUpdate is the builder for updating Employee entities.
+type EmployeeUpdate struct {
+	config
+	hooks    []Hook
+	mutation *EmployeeMutation
+}
+
+// Where appends a list predicates to the EmployeeUpdate builder.
+func (eu *EmployeeUpdate) Where(ps ...predicate.Employee) *EmployeeUpdate {
+	eu.mutation.Where(ps...)
+	return eu
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (eu *EmployeeUpdate) SetUpdatedAt(t time.Time) *EmployeeUpdate {
+	eu.mutation.SetUpdatedAt(t)
+	return eu
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (eu *EmployeeUpdate) SetDeletedAt(t time.Time) *EmployeeUpdate {
+	eu.mutation.SetDeletedAt(t)
+	return eu
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (eu *EmployeeUpdate) SetNillableDeletedAt(t *time.Time) *EmployeeUpdate {
+	if t != nil {
+		eu.SetDeletedAt(*t)
+	}
+	return eu
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (eu *EmployeeUpdate) ClearDeletedAt() *EmployeeUpdate {
+	eu.mutation.ClearDeletedAt()
+	return eu
+}
+
+// SetTitle sets the "title" field.
+func (eu *EmployeeUpdate) SetTitle(s string) *EmployeeUpdate {
+	eu.mutation.SetTitle(s)
+	return eu
+}
+
+// SetNillableTitle sets the "title" field if the given value is not nil.
+func (eu *EmployeeUpdate) SetNillableTitle(s *string) *EmployeeUpdate {
+	if s != nil {
+		eu.SetTitle(*s)
+	}
+	return eu
+}
+
+// SetAvatar sets the "avatar" field.
+func (eu *EmployeeUpdate) SetAvatar(s string) *EmployeeUpdate {
+	eu.mutation.SetAvatar(s)
+	return eu
+}
+
+// SetNillableAvatar sets the "avatar" field if the given value is not nil.
+func (eu *EmployeeUpdate) SetNillableAvatar(s *string) *EmployeeUpdate {
+	if s != nil {
+		eu.SetAvatar(*s)
+	}
+	return eu
+}
+
+// SetTags sets the "tags" field.
+func (eu *EmployeeUpdate) SetTags(s string) *EmployeeUpdate {
+	eu.mutation.SetTags(s)
+	return eu
+}
+
+// SetNillableTags sets the "tags" field if the given value is not nil.
+func (eu *EmployeeUpdate) SetNillableTags(s *string) *EmployeeUpdate {
+	if s != nil {
+		eu.SetTags(*s)
+	}
+	return eu
+}
+
+// SetHireCount sets the "hire_count" field.
+func (eu *EmployeeUpdate) SetHireCount(i int) *EmployeeUpdate {
+	eu.mutation.ResetHireCount()
+	eu.mutation.SetHireCount(i)
+	return eu
+}
+
+// SetNillableHireCount sets the "hire_count" field if the given value is not nil.
+func (eu *EmployeeUpdate) SetNillableHireCount(i *int) *EmployeeUpdate {
+	if i != nil {
+		eu.SetHireCount(*i)
+	}
+	return eu
+}
+
+// AddHireCount adds i to the "hire_count" field.
+func (eu *EmployeeUpdate) AddHireCount(i int) *EmployeeUpdate {
+	eu.mutation.AddHireCount(i)
+	return eu
+}
+
+// SetServiceCount sets the "service_count" field.
+func (eu *EmployeeUpdate) SetServiceCount(i int) *EmployeeUpdate {
+	eu.mutation.ResetServiceCount()
+	eu.mutation.SetServiceCount(i)
+	return eu
+}
+
+// SetNillableServiceCount sets the "service_count" field if the given value is not nil.
+func (eu *EmployeeUpdate) SetNillableServiceCount(i *int) *EmployeeUpdate {
+	if i != nil {
+		eu.SetServiceCount(*i)
+	}
+	return eu
+}
+
+// AddServiceCount adds i to the "service_count" field.
+func (eu *EmployeeUpdate) AddServiceCount(i int) *EmployeeUpdate {
+	eu.mutation.AddServiceCount(i)
+	return eu
+}
+
+// SetAchievementCount sets the "achievement_count" field.
+func (eu *EmployeeUpdate) SetAchievementCount(i int) *EmployeeUpdate {
+	eu.mutation.ResetAchievementCount()
+	eu.mutation.SetAchievementCount(i)
+	return eu
+}
+
+// SetNillableAchievementCount sets the "achievement_count" field if the given value is not nil.
+func (eu *EmployeeUpdate) SetNillableAchievementCount(i *int) *EmployeeUpdate {
+	if i != nil {
+		eu.SetAchievementCount(*i)
+	}
+	return eu
+}
+
+// AddAchievementCount adds i to the "achievement_count" field.
+func (eu *EmployeeUpdate) AddAchievementCount(i int) *EmployeeUpdate {
+	eu.mutation.AddAchievementCount(i)
+	return eu
+}
+
+// SetIntro sets the "intro" field.
+func (eu *EmployeeUpdate) SetIntro(s string) *EmployeeUpdate {
+	eu.mutation.SetIntro(s)
+	return eu
+}
+
+// SetNillableIntro sets the "intro" field if the given value is not nil.
+func (eu *EmployeeUpdate) SetNillableIntro(s *string) *EmployeeUpdate {
+	if s != nil {
+		eu.SetIntro(*s)
+	}
+	return eu
+}
+
+// SetEstimate sets the "estimate" field.
+func (eu *EmployeeUpdate) SetEstimate(s string) *EmployeeUpdate {
+	eu.mutation.SetEstimate(s)
+	return eu
+}
+
+// SetNillableEstimate sets the "estimate" field if the given value is not nil.
+func (eu *EmployeeUpdate) SetNillableEstimate(s *string) *EmployeeUpdate {
+	if s != nil {
+		eu.SetEstimate(*s)
+	}
+	return eu
+}
+
+// SetSkill sets the "skill" field.
+func (eu *EmployeeUpdate) SetSkill(s string) *EmployeeUpdate {
+	eu.mutation.SetSkill(s)
+	return eu
+}
+
+// SetNillableSkill sets the "skill" field if the given value is not nil.
+func (eu *EmployeeUpdate) SetNillableSkill(s *string) *EmployeeUpdate {
+	if s != nil {
+		eu.SetSkill(*s)
+	}
+	return eu
+}
+
+// SetAbilityType sets the "ability_type" field.
+func (eu *EmployeeUpdate) SetAbilityType(s string) *EmployeeUpdate {
+	eu.mutation.SetAbilityType(s)
+	return eu
+}
+
+// SetNillableAbilityType sets the "ability_type" field if the given value is not nil.
+func (eu *EmployeeUpdate) SetNillableAbilityType(s *string) *EmployeeUpdate {
+	if s != nil {
+		eu.SetAbilityType(*s)
+	}
+	return eu
+}
+
+// SetScene sets the "scene" field.
+func (eu *EmployeeUpdate) SetScene(s string) *EmployeeUpdate {
+	eu.mutation.SetScene(s)
+	return eu
+}
+
+// SetNillableScene sets the "scene" field if the given value is not nil.
+func (eu *EmployeeUpdate) SetNillableScene(s *string) *EmployeeUpdate {
+	if s != nil {
+		eu.SetScene(*s)
+	}
+	return eu
+}
+
+// SetSwitchIn sets the "switch_in" field.
+func (eu *EmployeeUpdate) SetSwitchIn(s string) *EmployeeUpdate {
+	eu.mutation.SetSwitchIn(s)
+	return eu
+}
+
+// SetNillableSwitchIn sets the "switch_in" field if the given value is not nil.
+func (eu *EmployeeUpdate) SetNillableSwitchIn(s *string) *EmployeeUpdate {
+	if s != nil {
+		eu.SetSwitchIn(*s)
+	}
+	return eu
+}
+
+// SetVideoURL sets the "video_url" field.
+func (eu *EmployeeUpdate) SetVideoURL(s string) *EmployeeUpdate {
+	eu.mutation.SetVideoURL(s)
+	return eu
+}
+
+// SetNillableVideoURL sets the "video_url" field if the given value is not nil.
+func (eu *EmployeeUpdate) SetNillableVideoURL(s *string) *EmployeeUpdate {
+	if s != nil {
+		eu.SetVideoURL(*s)
+	}
+	return eu
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (eu *EmployeeUpdate) SetOrganizationID(u uint64) *EmployeeUpdate {
+	eu.mutation.ResetOrganizationID()
+	eu.mutation.SetOrganizationID(u)
+	return eu
+}
+
+// SetNillableOrganizationID sets the "organization_id" field if the given value is not nil.
+func (eu *EmployeeUpdate) SetNillableOrganizationID(u *uint64) *EmployeeUpdate {
+	if u != nil {
+		eu.SetOrganizationID(*u)
+	}
+	return eu
+}
+
+// AddOrganizationID adds u to the "organization_id" field.
+func (eu *EmployeeUpdate) AddOrganizationID(u int64) *EmployeeUpdate {
+	eu.mutation.AddOrganizationID(u)
+	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...)
+	return eu
+}
+
+// AddEmWorkExperiences adds the "em_work_experiences" edges to the WorkExperience entity.
+func (eu *EmployeeUpdate) AddEmWorkExperiences(w ...*WorkExperience) *EmployeeUpdate {
+	ids := make([]uint64, len(w))
+	for i := range w {
+		ids[i] = w[i].ID
+	}
+	return eu.AddEmWorkExperienceIDs(ids...)
+}
+
+// AddEmTutorialIDs adds the "em_tutorial" edge to the Tutorial entity by IDs.
+func (eu *EmployeeUpdate) AddEmTutorialIDs(ids ...uint64) *EmployeeUpdate {
+	eu.mutation.AddEmTutorialIDs(ids...)
+	return eu
+}
+
+// AddEmTutorial adds the "em_tutorial" edges to the Tutorial entity.
+func (eu *EmployeeUpdate) AddEmTutorial(t ...*Tutorial) *EmployeeUpdate {
+	ids := make([]uint64, len(t))
+	for i := range t {
+		ids[i] = t[i].ID
+	}
+	return eu.AddEmTutorialIDs(ids...)
+}
+
+// Mutation returns the EmployeeMutation object of the builder.
+func (eu *EmployeeUpdate) Mutation() *EmployeeMutation {
+	return eu.mutation
+}
+
+// ClearEmWorkExperiences clears all "em_work_experiences" edges to the WorkExperience entity.
+func (eu *EmployeeUpdate) ClearEmWorkExperiences() *EmployeeUpdate {
+	eu.mutation.ClearEmWorkExperiences()
+	return eu
+}
+
+// RemoveEmWorkExperienceIDs removes the "em_work_experiences" edge to WorkExperience entities by IDs.
+func (eu *EmployeeUpdate) RemoveEmWorkExperienceIDs(ids ...uint64) *EmployeeUpdate {
+	eu.mutation.RemoveEmWorkExperienceIDs(ids...)
+	return eu
+}
+
+// RemoveEmWorkExperiences removes "em_work_experiences" edges to WorkExperience entities.
+func (eu *EmployeeUpdate) RemoveEmWorkExperiences(w ...*WorkExperience) *EmployeeUpdate {
+	ids := make([]uint64, len(w))
+	for i := range w {
+		ids[i] = w[i].ID
+	}
+	return eu.RemoveEmWorkExperienceIDs(ids...)
+}
+
+// ClearEmTutorial clears all "em_tutorial" edges to the Tutorial entity.
+func (eu *EmployeeUpdate) ClearEmTutorial() *EmployeeUpdate {
+	eu.mutation.ClearEmTutorial()
+	return eu
+}
+
+// RemoveEmTutorialIDs removes the "em_tutorial" edge to Tutorial entities by IDs.
+func (eu *EmployeeUpdate) RemoveEmTutorialIDs(ids ...uint64) *EmployeeUpdate {
+	eu.mutation.RemoveEmTutorialIDs(ids...)
+	return eu
+}
+
+// RemoveEmTutorial removes "em_tutorial" edges to Tutorial entities.
+func (eu *EmployeeUpdate) RemoveEmTutorial(t ...*Tutorial) *EmployeeUpdate {
+	ids := make([]uint64, len(t))
+	for i := range t {
+		ids[i] = t[i].ID
+	}
+	return eu.RemoveEmTutorialIDs(ids...)
+}
+
+// Save executes the query and returns the number of nodes affected by the update operation.
+func (eu *EmployeeUpdate) Save(ctx context.Context) (int, error) {
+	if err := eu.defaults(); err != nil {
+		return 0, err
+	}
+	return withHooks(ctx, eu.sqlSave, eu.mutation, eu.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (eu *EmployeeUpdate) SaveX(ctx context.Context) int {
+	affected, err := eu.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return affected
+}
+
+// Exec executes the query.
+func (eu *EmployeeUpdate) Exec(ctx context.Context) error {
+	_, err := eu.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (eu *EmployeeUpdate) ExecX(ctx context.Context) {
+	if err := eu.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (eu *EmployeeUpdate) defaults() error {
+	if _, ok := eu.mutation.UpdatedAt(); !ok {
+		if employee.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized employee.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := employee.UpdateDefaultUpdatedAt()
+		eu.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (eu *EmployeeUpdate) check() error {
+	if v, ok := eu.mutation.Title(); ok {
+		if err := employee.TitleValidator(v); err != nil {
+			return &ValidationError{Name: "title", err: fmt.Errorf(`ent: validator failed for field "Employee.title": %w`, err)}
+		}
+	}
+	if v, ok := eu.mutation.Avatar(); ok {
+		if err := employee.AvatarValidator(v); err != nil {
+			return &ValidationError{Name: "avatar", err: fmt.Errorf(`ent: validator failed for field "Employee.avatar": %w`, err)}
+		}
+	}
+	if v, ok := eu.mutation.Tags(); ok {
+		if err := employee.TagsValidator(v); err != nil {
+			return &ValidationError{Name: "tags", err: fmt.Errorf(`ent: validator failed for field "Employee.tags": %w`, err)}
+		}
+	}
+	if v, ok := eu.mutation.HireCount(); ok {
+		if err := employee.HireCountValidator(v); err != nil {
+			return &ValidationError{Name: "hire_count", err: fmt.Errorf(`ent: validator failed for field "Employee.hire_count": %w`, err)}
+		}
+	}
+	if v, ok := eu.mutation.ServiceCount(); ok {
+		if err := employee.ServiceCountValidator(v); err != nil {
+			return &ValidationError{Name: "service_count", err: fmt.Errorf(`ent: validator failed for field "Employee.service_count": %w`, err)}
+		}
+	}
+	if v, ok := eu.mutation.AchievementCount(); ok {
+		if err := employee.AchievementCountValidator(v); err != nil {
+			return &ValidationError{Name: "achievement_count", err: fmt.Errorf(`ent: validator failed for field "Employee.achievement_count": %w`, err)}
+		}
+	}
+	if v, ok := eu.mutation.Intro(); ok {
+		if err := employee.IntroValidator(v); err != nil {
+			return &ValidationError{Name: "intro", err: fmt.Errorf(`ent: validator failed for field "Employee.intro": %w`, err)}
+		}
+	}
+	if v, ok := eu.mutation.Estimate(); ok {
+		if err := employee.EstimateValidator(v); err != nil {
+			return &ValidationError{Name: "estimate", err: fmt.Errorf(`ent: validator failed for field "Employee.estimate": %w`, err)}
+		}
+	}
+	if v, ok := eu.mutation.Skill(); ok {
+		if err := employee.SkillValidator(v); err != nil {
+			return &ValidationError{Name: "skill", err: fmt.Errorf(`ent: validator failed for field "Employee.skill": %w`, err)}
+		}
+	}
+	if v, ok := eu.mutation.VideoURL(); ok {
+		if err := employee.VideoURLValidator(v); err != nil {
+			return &ValidationError{Name: "video_url", err: fmt.Errorf(`ent: validator failed for field "Employee.video_url": %w`, err)}
+		}
+	}
+	if v, ok := eu.mutation.OrganizationID(); ok {
+		if err := employee.OrganizationIDValidator(v); err != nil {
+			return &ValidationError{Name: "organization_id", err: fmt.Errorf(`ent: validator failed for field "Employee.organization_id": %w`, err)}
+		}
+	}
+	return nil
+}
+
+func (eu *EmployeeUpdate) sqlSave(ctx context.Context) (n int, err error) {
+	if err := eu.check(); err != nil {
+		return n, err
+	}
+	_spec := sqlgraph.NewUpdateSpec(employee.Table, employee.Columns, sqlgraph.NewFieldSpec(employee.FieldID, field.TypeUint64))
+	if ps := eu.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := eu.mutation.UpdatedAt(); ok {
+		_spec.SetField(employee.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := eu.mutation.DeletedAt(); ok {
+		_spec.SetField(employee.FieldDeletedAt, field.TypeTime, value)
+	}
+	if eu.mutation.DeletedAtCleared() {
+		_spec.ClearField(employee.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := eu.mutation.Title(); ok {
+		_spec.SetField(employee.FieldTitle, field.TypeString, value)
+	}
+	if value, ok := eu.mutation.Avatar(); ok {
+		_spec.SetField(employee.FieldAvatar, field.TypeString, value)
+	}
+	if value, ok := eu.mutation.Tags(); ok {
+		_spec.SetField(employee.FieldTags, field.TypeString, value)
+	}
+	if value, ok := eu.mutation.HireCount(); ok {
+		_spec.SetField(employee.FieldHireCount, field.TypeInt, value)
+	}
+	if value, ok := eu.mutation.AddedHireCount(); ok {
+		_spec.AddField(employee.FieldHireCount, field.TypeInt, value)
+	}
+	if value, ok := eu.mutation.ServiceCount(); ok {
+		_spec.SetField(employee.FieldServiceCount, field.TypeInt, value)
+	}
+	if value, ok := eu.mutation.AddedServiceCount(); ok {
+		_spec.AddField(employee.FieldServiceCount, field.TypeInt, value)
+	}
+	if value, ok := eu.mutation.AchievementCount(); ok {
+		_spec.SetField(employee.FieldAchievementCount, field.TypeInt, value)
+	}
+	if value, ok := eu.mutation.AddedAchievementCount(); ok {
+		_spec.AddField(employee.FieldAchievementCount, field.TypeInt, value)
+	}
+	if value, ok := eu.mutation.Intro(); ok {
+		_spec.SetField(employee.FieldIntro, field.TypeString, value)
+	}
+	if value, ok := eu.mutation.Estimate(); ok {
+		_spec.SetField(employee.FieldEstimate, field.TypeString, value)
+	}
+	if value, ok := eu.mutation.Skill(); ok {
+		_spec.SetField(employee.FieldSkill, field.TypeString, value)
+	}
+	if value, ok := eu.mutation.AbilityType(); ok {
+		_spec.SetField(employee.FieldAbilityType, field.TypeString, value)
+	}
+	if value, ok := eu.mutation.Scene(); ok {
+		_spec.SetField(employee.FieldScene, field.TypeString, value)
+	}
+	if value, ok := eu.mutation.SwitchIn(); ok {
+		_spec.SetField(employee.FieldSwitchIn, field.TypeString, value)
+	}
+	if value, ok := eu.mutation.VideoURL(); ok {
+		_spec.SetField(employee.FieldVideoURL, field.TypeString, value)
+	}
+	if value, ok := eu.mutation.OrganizationID(); ok {
+		_spec.SetField(employee.FieldOrganizationID, field.TypeUint64, value)
+	}
+	if value, ok := eu.mutation.AddedOrganizationID(); ok {
+		_spec.AddField(employee.FieldOrganizationID, field.TypeUint64, value)
+	}
+	if eu.mutation.EmWorkExperiencesCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   employee.EmWorkExperiencesTable,
+			Columns: []string{employee.EmWorkExperiencesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(workexperience.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := eu.mutation.RemovedEmWorkExperiencesIDs(); len(nodes) > 0 && !eu.mutation.EmWorkExperiencesCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   employee.EmWorkExperiencesTable,
+			Columns: []string{employee.EmWorkExperiencesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(workexperience.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := eu.mutation.EmWorkExperiencesIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   employee.EmWorkExperiencesTable,
+			Columns: []string{employee.EmWorkExperiencesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(workexperience.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
+	if eu.mutation.EmTutorialCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   employee.EmTutorialTable,
+			Columns: []string{employee.EmTutorialColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(tutorial.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := eu.mutation.RemovedEmTutorialIDs(); len(nodes) > 0 && !eu.mutation.EmTutorialCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   employee.EmTutorialTable,
+			Columns: []string{employee.EmTutorialColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(tutorial.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := eu.mutation.EmTutorialIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   employee.EmTutorialTable,
+			Columns: []string{employee.EmTutorialColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(tutorial.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
+	if n, err = sqlgraph.UpdateNodes(ctx, eu.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{employee.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return 0, err
+	}
+	eu.mutation.done = true
+	return n, nil
+}
+
+// EmployeeUpdateOne is the builder for updating a single Employee entity.
+type EmployeeUpdateOne struct {
+	config
+	fields   []string
+	hooks    []Hook
+	mutation *EmployeeMutation
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (euo *EmployeeUpdateOne) SetUpdatedAt(t time.Time) *EmployeeUpdateOne {
+	euo.mutation.SetUpdatedAt(t)
+	return euo
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (euo *EmployeeUpdateOne) SetDeletedAt(t time.Time) *EmployeeUpdateOne {
+	euo.mutation.SetDeletedAt(t)
+	return euo
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (euo *EmployeeUpdateOne) SetNillableDeletedAt(t *time.Time) *EmployeeUpdateOne {
+	if t != nil {
+		euo.SetDeletedAt(*t)
+	}
+	return euo
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (euo *EmployeeUpdateOne) ClearDeletedAt() *EmployeeUpdateOne {
+	euo.mutation.ClearDeletedAt()
+	return euo
+}
+
+// SetTitle sets the "title" field.
+func (euo *EmployeeUpdateOne) SetTitle(s string) *EmployeeUpdateOne {
+	euo.mutation.SetTitle(s)
+	return euo
+}
+
+// SetNillableTitle sets the "title" field if the given value is not nil.
+func (euo *EmployeeUpdateOne) SetNillableTitle(s *string) *EmployeeUpdateOne {
+	if s != nil {
+		euo.SetTitle(*s)
+	}
+	return euo
+}
+
+// SetAvatar sets the "avatar" field.
+func (euo *EmployeeUpdateOne) SetAvatar(s string) *EmployeeUpdateOne {
+	euo.mutation.SetAvatar(s)
+	return euo
+}
+
+// SetNillableAvatar sets the "avatar" field if the given value is not nil.
+func (euo *EmployeeUpdateOne) SetNillableAvatar(s *string) *EmployeeUpdateOne {
+	if s != nil {
+		euo.SetAvatar(*s)
+	}
+	return euo
+}
+
+// SetTags sets the "tags" field.
+func (euo *EmployeeUpdateOne) SetTags(s string) *EmployeeUpdateOne {
+	euo.mutation.SetTags(s)
+	return euo
+}
+
+// SetNillableTags sets the "tags" field if the given value is not nil.
+func (euo *EmployeeUpdateOne) SetNillableTags(s *string) *EmployeeUpdateOne {
+	if s != nil {
+		euo.SetTags(*s)
+	}
+	return euo
+}
+
+// SetHireCount sets the "hire_count" field.
+func (euo *EmployeeUpdateOne) SetHireCount(i int) *EmployeeUpdateOne {
+	euo.mutation.ResetHireCount()
+	euo.mutation.SetHireCount(i)
+	return euo
+}
+
+// SetNillableHireCount sets the "hire_count" field if the given value is not nil.
+func (euo *EmployeeUpdateOne) SetNillableHireCount(i *int) *EmployeeUpdateOne {
+	if i != nil {
+		euo.SetHireCount(*i)
+	}
+	return euo
+}
+
+// AddHireCount adds i to the "hire_count" field.
+func (euo *EmployeeUpdateOne) AddHireCount(i int) *EmployeeUpdateOne {
+	euo.mutation.AddHireCount(i)
+	return euo
+}
+
+// SetServiceCount sets the "service_count" field.
+func (euo *EmployeeUpdateOne) SetServiceCount(i int) *EmployeeUpdateOne {
+	euo.mutation.ResetServiceCount()
+	euo.mutation.SetServiceCount(i)
+	return euo
+}
+
+// SetNillableServiceCount sets the "service_count" field if the given value is not nil.
+func (euo *EmployeeUpdateOne) SetNillableServiceCount(i *int) *EmployeeUpdateOne {
+	if i != nil {
+		euo.SetServiceCount(*i)
+	}
+	return euo
+}
+
+// AddServiceCount adds i to the "service_count" field.
+func (euo *EmployeeUpdateOne) AddServiceCount(i int) *EmployeeUpdateOne {
+	euo.mutation.AddServiceCount(i)
+	return euo
+}
+
+// SetAchievementCount sets the "achievement_count" field.
+func (euo *EmployeeUpdateOne) SetAchievementCount(i int) *EmployeeUpdateOne {
+	euo.mutation.ResetAchievementCount()
+	euo.mutation.SetAchievementCount(i)
+	return euo
+}
+
+// SetNillableAchievementCount sets the "achievement_count" field if the given value is not nil.
+func (euo *EmployeeUpdateOne) SetNillableAchievementCount(i *int) *EmployeeUpdateOne {
+	if i != nil {
+		euo.SetAchievementCount(*i)
+	}
+	return euo
+}
+
+// AddAchievementCount adds i to the "achievement_count" field.
+func (euo *EmployeeUpdateOne) AddAchievementCount(i int) *EmployeeUpdateOne {
+	euo.mutation.AddAchievementCount(i)
+	return euo
+}
+
+// SetIntro sets the "intro" field.
+func (euo *EmployeeUpdateOne) SetIntro(s string) *EmployeeUpdateOne {
+	euo.mutation.SetIntro(s)
+	return euo
+}
+
+// SetNillableIntro sets the "intro" field if the given value is not nil.
+func (euo *EmployeeUpdateOne) SetNillableIntro(s *string) *EmployeeUpdateOne {
+	if s != nil {
+		euo.SetIntro(*s)
+	}
+	return euo
+}
+
+// SetEstimate sets the "estimate" field.
+func (euo *EmployeeUpdateOne) SetEstimate(s string) *EmployeeUpdateOne {
+	euo.mutation.SetEstimate(s)
+	return euo
+}
+
+// SetNillableEstimate sets the "estimate" field if the given value is not nil.
+func (euo *EmployeeUpdateOne) SetNillableEstimate(s *string) *EmployeeUpdateOne {
+	if s != nil {
+		euo.SetEstimate(*s)
+	}
+	return euo
+}
+
+// SetSkill sets the "skill" field.
+func (euo *EmployeeUpdateOne) SetSkill(s string) *EmployeeUpdateOne {
+	euo.mutation.SetSkill(s)
+	return euo
+}
+
+// SetNillableSkill sets the "skill" field if the given value is not nil.
+func (euo *EmployeeUpdateOne) SetNillableSkill(s *string) *EmployeeUpdateOne {
+	if s != nil {
+		euo.SetSkill(*s)
+	}
+	return euo
+}
+
+// SetAbilityType sets the "ability_type" field.
+func (euo *EmployeeUpdateOne) SetAbilityType(s string) *EmployeeUpdateOne {
+	euo.mutation.SetAbilityType(s)
+	return euo
+}
+
+// SetNillableAbilityType sets the "ability_type" field if the given value is not nil.
+func (euo *EmployeeUpdateOne) SetNillableAbilityType(s *string) *EmployeeUpdateOne {
+	if s != nil {
+		euo.SetAbilityType(*s)
+	}
+	return euo
+}
+
+// SetScene sets the "scene" field.
+func (euo *EmployeeUpdateOne) SetScene(s string) *EmployeeUpdateOne {
+	euo.mutation.SetScene(s)
+	return euo
+}
+
+// SetNillableScene sets the "scene" field if the given value is not nil.
+func (euo *EmployeeUpdateOne) SetNillableScene(s *string) *EmployeeUpdateOne {
+	if s != nil {
+		euo.SetScene(*s)
+	}
+	return euo
+}
+
+// SetSwitchIn sets the "switch_in" field.
+func (euo *EmployeeUpdateOne) SetSwitchIn(s string) *EmployeeUpdateOne {
+	euo.mutation.SetSwitchIn(s)
+	return euo
+}
+
+// SetNillableSwitchIn sets the "switch_in" field if the given value is not nil.
+func (euo *EmployeeUpdateOne) SetNillableSwitchIn(s *string) *EmployeeUpdateOne {
+	if s != nil {
+		euo.SetSwitchIn(*s)
+	}
+	return euo
+}
+
+// SetVideoURL sets the "video_url" field.
+func (euo *EmployeeUpdateOne) SetVideoURL(s string) *EmployeeUpdateOne {
+	euo.mutation.SetVideoURL(s)
+	return euo
+}
+
+// SetNillableVideoURL sets the "video_url" field if the given value is not nil.
+func (euo *EmployeeUpdateOne) SetNillableVideoURL(s *string) *EmployeeUpdateOne {
+	if s != nil {
+		euo.SetVideoURL(*s)
+	}
+	return euo
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (euo *EmployeeUpdateOne) SetOrganizationID(u uint64) *EmployeeUpdateOne {
+	euo.mutation.ResetOrganizationID()
+	euo.mutation.SetOrganizationID(u)
+	return euo
+}
+
+// SetNillableOrganizationID sets the "organization_id" field if the given value is not nil.
+func (euo *EmployeeUpdateOne) SetNillableOrganizationID(u *uint64) *EmployeeUpdateOne {
+	if u != nil {
+		euo.SetOrganizationID(*u)
+	}
+	return euo
+}
+
+// AddOrganizationID adds u to the "organization_id" field.
+func (euo *EmployeeUpdateOne) AddOrganizationID(u int64) *EmployeeUpdateOne {
+	euo.mutation.AddOrganizationID(u)
+	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...)
+	return euo
+}
+
+// AddEmWorkExperiences adds the "em_work_experiences" edges to the WorkExperience entity.
+func (euo *EmployeeUpdateOne) AddEmWorkExperiences(w ...*WorkExperience) *EmployeeUpdateOne {
+	ids := make([]uint64, len(w))
+	for i := range w {
+		ids[i] = w[i].ID
+	}
+	return euo.AddEmWorkExperienceIDs(ids...)
+}
+
+// AddEmTutorialIDs adds the "em_tutorial" edge to the Tutorial entity by IDs.
+func (euo *EmployeeUpdateOne) AddEmTutorialIDs(ids ...uint64) *EmployeeUpdateOne {
+	euo.mutation.AddEmTutorialIDs(ids...)
+	return euo
+}
+
+// AddEmTutorial adds the "em_tutorial" edges to the Tutorial entity.
+func (euo *EmployeeUpdateOne) AddEmTutorial(t ...*Tutorial) *EmployeeUpdateOne {
+	ids := make([]uint64, len(t))
+	for i := range t {
+		ids[i] = t[i].ID
+	}
+	return euo.AddEmTutorialIDs(ids...)
+}
+
+// Mutation returns the EmployeeMutation object of the builder.
+func (euo *EmployeeUpdateOne) Mutation() *EmployeeMutation {
+	return euo.mutation
+}
+
+// ClearEmWorkExperiences clears all "em_work_experiences" edges to the WorkExperience entity.
+func (euo *EmployeeUpdateOne) ClearEmWorkExperiences() *EmployeeUpdateOne {
+	euo.mutation.ClearEmWorkExperiences()
+	return euo
+}
+
+// RemoveEmWorkExperienceIDs removes the "em_work_experiences" edge to WorkExperience entities by IDs.
+func (euo *EmployeeUpdateOne) RemoveEmWorkExperienceIDs(ids ...uint64) *EmployeeUpdateOne {
+	euo.mutation.RemoveEmWorkExperienceIDs(ids...)
+	return euo
+}
+
+// RemoveEmWorkExperiences removes "em_work_experiences" edges to WorkExperience entities.
+func (euo *EmployeeUpdateOne) RemoveEmWorkExperiences(w ...*WorkExperience) *EmployeeUpdateOne {
+	ids := make([]uint64, len(w))
+	for i := range w {
+		ids[i] = w[i].ID
+	}
+	return euo.RemoveEmWorkExperienceIDs(ids...)
+}
+
+// ClearEmTutorial clears all "em_tutorial" edges to the Tutorial entity.
+func (euo *EmployeeUpdateOne) ClearEmTutorial() *EmployeeUpdateOne {
+	euo.mutation.ClearEmTutorial()
+	return euo
+}
+
+// RemoveEmTutorialIDs removes the "em_tutorial" edge to Tutorial entities by IDs.
+func (euo *EmployeeUpdateOne) RemoveEmTutorialIDs(ids ...uint64) *EmployeeUpdateOne {
+	euo.mutation.RemoveEmTutorialIDs(ids...)
+	return euo
+}
+
+// RemoveEmTutorial removes "em_tutorial" edges to Tutorial entities.
+func (euo *EmployeeUpdateOne) RemoveEmTutorial(t ...*Tutorial) *EmployeeUpdateOne {
+	ids := make([]uint64, len(t))
+	for i := range t {
+		ids[i] = t[i].ID
+	}
+	return euo.RemoveEmTutorialIDs(ids...)
+}
+
+// Where appends a list predicates to the EmployeeUpdate builder.
+func (euo *EmployeeUpdateOne) Where(ps ...predicate.Employee) *EmployeeUpdateOne {
+	euo.mutation.Where(ps...)
+	return euo
+}
+
+// Select allows selecting one or more fields (columns) of the returned entity.
+// The default is selecting all fields defined in the entity schema.
+func (euo *EmployeeUpdateOne) Select(field string, fields ...string) *EmployeeUpdateOne {
+	euo.fields = append([]string{field}, fields...)
+	return euo
+}
+
+// Save executes the query and returns the updated Employee entity.
+func (euo *EmployeeUpdateOne) Save(ctx context.Context) (*Employee, error) {
+	if err := euo.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, euo.sqlSave, euo.mutation, euo.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (euo *EmployeeUpdateOne) SaveX(ctx context.Context) *Employee {
+	node, err := euo.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return node
+}
+
+// Exec executes the query on the entity.
+func (euo *EmployeeUpdateOne) Exec(ctx context.Context) error {
+	_, err := euo.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (euo *EmployeeUpdateOne) ExecX(ctx context.Context) {
+	if err := euo.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (euo *EmployeeUpdateOne) defaults() error {
+	if _, ok := euo.mutation.UpdatedAt(); !ok {
+		if employee.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized employee.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := employee.UpdateDefaultUpdatedAt()
+		euo.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (euo *EmployeeUpdateOne) check() error {
+	if v, ok := euo.mutation.Title(); ok {
+		if err := employee.TitleValidator(v); err != nil {
+			return &ValidationError{Name: "title", err: fmt.Errorf(`ent: validator failed for field "Employee.title": %w`, err)}
+		}
+	}
+	if v, ok := euo.mutation.Avatar(); ok {
+		if err := employee.AvatarValidator(v); err != nil {
+			return &ValidationError{Name: "avatar", err: fmt.Errorf(`ent: validator failed for field "Employee.avatar": %w`, err)}
+		}
+	}
+	if v, ok := euo.mutation.Tags(); ok {
+		if err := employee.TagsValidator(v); err != nil {
+			return &ValidationError{Name: "tags", err: fmt.Errorf(`ent: validator failed for field "Employee.tags": %w`, err)}
+		}
+	}
+	if v, ok := euo.mutation.HireCount(); ok {
+		if err := employee.HireCountValidator(v); err != nil {
+			return &ValidationError{Name: "hire_count", err: fmt.Errorf(`ent: validator failed for field "Employee.hire_count": %w`, err)}
+		}
+	}
+	if v, ok := euo.mutation.ServiceCount(); ok {
+		if err := employee.ServiceCountValidator(v); err != nil {
+			return &ValidationError{Name: "service_count", err: fmt.Errorf(`ent: validator failed for field "Employee.service_count": %w`, err)}
+		}
+	}
+	if v, ok := euo.mutation.AchievementCount(); ok {
+		if err := employee.AchievementCountValidator(v); err != nil {
+			return &ValidationError{Name: "achievement_count", err: fmt.Errorf(`ent: validator failed for field "Employee.achievement_count": %w`, err)}
+		}
+	}
+	if v, ok := euo.mutation.Intro(); ok {
+		if err := employee.IntroValidator(v); err != nil {
+			return &ValidationError{Name: "intro", err: fmt.Errorf(`ent: validator failed for field "Employee.intro": %w`, err)}
+		}
+	}
+	if v, ok := euo.mutation.Estimate(); ok {
+		if err := employee.EstimateValidator(v); err != nil {
+			return &ValidationError{Name: "estimate", err: fmt.Errorf(`ent: validator failed for field "Employee.estimate": %w`, err)}
+		}
+	}
+	if v, ok := euo.mutation.Skill(); ok {
+		if err := employee.SkillValidator(v); err != nil {
+			return &ValidationError{Name: "skill", err: fmt.Errorf(`ent: validator failed for field "Employee.skill": %w`, err)}
+		}
+	}
+	if v, ok := euo.mutation.VideoURL(); ok {
+		if err := employee.VideoURLValidator(v); err != nil {
+			return &ValidationError{Name: "video_url", err: fmt.Errorf(`ent: validator failed for field "Employee.video_url": %w`, err)}
+		}
+	}
+	if v, ok := euo.mutation.OrganizationID(); ok {
+		if err := employee.OrganizationIDValidator(v); err != nil {
+			return &ValidationError{Name: "organization_id", err: fmt.Errorf(`ent: validator failed for field "Employee.organization_id": %w`, err)}
+		}
+	}
+	return nil
+}
+
+func (euo *EmployeeUpdateOne) sqlSave(ctx context.Context) (_node *Employee, err error) {
+	if err := euo.check(); err != nil {
+		return _node, err
+	}
+	_spec := sqlgraph.NewUpdateSpec(employee.Table, employee.Columns, sqlgraph.NewFieldSpec(employee.FieldID, field.TypeUint64))
+	id, ok := euo.mutation.ID()
+	if !ok {
+		return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Employee.id" for update`)}
+	}
+	_spec.Node.ID.Value = id
+	if fields := euo.fields; len(fields) > 0 {
+		_spec.Node.Columns = make([]string, 0, len(fields))
+		_spec.Node.Columns = append(_spec.Node.Columns, employee.FieldID)
+		for _, f := range fields {
+			if !employee.ValidColumn(f) {
+				return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+			}
+			if f != employee.FieldID {
+				_spec.Node.Columns = append(_spec.Node.Columns, f)
+			}
+		}
+	}
+	if ps := euo.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := euo.mutation.UpdatedAt(); ok {
+		_spec.SetField(employee.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := euo.mutation.DeletedAt(); ok {
+		_spec.SetField(employee.FieldDeletedAt, field.TypeTime, value)
+	}
+	if euo.mutation.DeletedAtCleared() {
+		_spec.ClearField(employee.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := euo.mutation.Title(); ok {
+		_spec.SetField(employee.FieldTitle, field.TypeString, value)
+	}
+	if value, ok := euo.mutation.Avatar(); ok {
+		_spec.SetField(employee.FieldAvatar, field.TypeString, value)
+	}
+	if value, ok := euo.mutation.Tags(); ok {
+		_spec.SetField(employee.FieldTags, field.TypeString, value)
+	}
+	if value, ok := euo.mutation.HireCount(); ok {
+		_spec.SetField(employee.FieldHireCount, field.TypeInt, value)
+	}
+	if value, ok := euo.mutation.AddedHireCount(); ok {
+		_spec.AddField(employee.FieldHireCount, field.TypeInt, value)
+	}
+	if value, ok := euo.mutation.ServiceCount(); ok {
+		_spec.SetField(employee.FieldServiceCount, field.TypeInt, value)
+	}
+	if value, ok := euo.mutation.AddedServiceCount(); ok {
+		_spec.AddField(employee.FieldServiceCount, field.TypeInt, value)
+	}
+	if value, ok := euo.mutation.AchievementCount(); ok {
+		_spec.SetField(employee.FieldAchievementCount, field.TypeInt, value)
+	}
+	if value, ok := euo.mutation.AddedAchievementCount(); ok {
+		_spec.AddField(employee.FieldAchievementCount, field.TypeInt, value)
+	}
+	if value, ok := euo.mutation.Intro(); ok {
+		_spec.SetField(employee.FieldIntro, field.TypeString, value)
+	}
+	if value, ok := euo.mutation.Estimate(); ok {
+		_spec.SetField(employee.FieldEstimate, field.TypeString, value)
+	}
+	if value, ok := euo.mutation.Skill(); ok {
+		_spec.SetField(employee.FieldSkill, field.TypeString, value)
+	}
+	if value, ok := euo.mutation.AbilityType(); ok {
+		_spec.SetField(employee.FieldAbilityType, field.TypeString, value)
+	}
+	if value, ok := euo.mutation.Scene(); ok {
+		_spec.SetField(employee.FieldScene, field.TypeString, value)
+	}
+	if value, ok := euo.mutation.SwitchIn(); ok {
+		_spec.SetField(employee.FieldSwitchIn, field.TypeString, value)
+	}
+	if value, ok := euo.mutation.VideoURL(); ok {
+		_spec.SetField(employee.FieldVideoURL, field.TypeString, value)
+	}
+	if value, ok := euo.mutation.OrganizationID(); ok {
+		_spec.SetField(employee.FieldOrganizationID, field.TypeUint64, value)
+	}
+	if value, ok := euo.mutation.AddedOrganizationID(); ok {
+		_spec.AddField(employee.FieldOrganizationID, field.TypeUint64, value)
+	}
+	if euo.mutation.EmWorkExperiencesCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   employee.EmWorkExperiencesTable,
+			Columns: []string{employee.EmWorkExperiencesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(workexperience.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := euo.mutation.RemovedEmWorkExperiencesIDs(); len(nodes) > 0 && !euo.mutation.EmWorkExperiencesCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   employee.EmWorkExperiencesTable,
+			Columns: []string{employee.EmWorkExperiencesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(workexperience.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := euo.mutation.EmWorkExperiencesIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   employee.EmWorkExperiencesTable,
+			Columns: []string{employee.EmWorkExperiencesColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(workexperience.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
+	if euo.mutation.EmTutorialCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   employee.EmTutorialTable,
+			Columns: []string{employee.EmTutorialColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(tutorial.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := euo.mutation.RemovedEmTutorialIDs(); len(nodes) > 0 && !euo.mutation.EmTutorialCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   employee.EmTutorialTable,
+			Columns: []string{employee.EmTutorialColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(tutorial.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := euo.mutation.EmTutorialIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.O2M,
+			Inverse: false,
+			Table:   employee.EmTutorialTable,
+			Columns: []string{employee.EmTutorialColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(tutorial.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
+	_node = &Employee{config: euo.config}
+	_spec.Assign = _node.assignValues
+	_spec.ScanValues = _node.scanValues
+	if err = sqlgraph.UpdateNode(ctx, euo.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{employee.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	euo.mutation.done = true
+	return _node, nil
+}

+ 6 - 0
ent/ent.go

@@ -11,6 +11,7 @@ import (
 	"wechat-api/ent/agent"
 	"wechat-api/ent/batchmsg"
 	"wechat-api/ent/contact"
+	"wechat-api/ent/employee"
 	"wechat-api/ent/label"
 	"wechat-api/ent/labelrelationship"
 	"wechat-api/ent/message"
@@ -20,6 +21,8 @@ import (
 	"wechat-api/ent/sopnode"
 	"wechat-api/ent/sopstage"
 	"wechat-api/ent/soptask"
+	"wechat-api/ent/tutorial"
+	"wechat-api/ent/workexperience"
 	"wechat-api/ent/wx"
 
 	"entgo.io/ent"
@@ -88,6 +91,7 @@ func checkColumn(table, column string) error {
 			agent.Table:             agent.ValidColumn,
 			batchmsg.Table:          batchmsg.ValidColumn,
 			contact.Table:           contact.ValidColumn,
+			employee.Table:          employee.ValidColumn,
 			label.Table:             label.ValidColumn,
 			labelrelationship.Table: labelrelationship.ValidColumn,
 			message.Table:           message.ValidColumn,
@@ -97,6 +101,8 @@ func checkColumn(table, column string) error {
 			sopnode.Table:           sopnode.ValidColumn,
 			sopstage.Table:          sopstage.ValidColumn,
 			soptask.Table:           soptask.ValidColumn,
+			tutorial.Table:          tutorial.ValidColumn,
+			workexperience.Table:    workexperience.ValidColumn,
 			wx.Table:                wx.ValidColumn,
 		})
 	})

+ 36 - 0
ent/hook/hook.go

@@ -44,6 +44,18 @@ func (f ContactFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, err
 	return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ContactMutation", m)
 }
 
+// The EmployeeFunc type is an adapter to allow the use of ordinary
+// function as Employee mutator.
+type EmployeeFunc func(context.Context, *ent.EmployeeMutation) (ent.Value, error)
+
+// Mutate calls f(ctx, m).
+func (f EmployeeFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
+	if mv, ok := m.(*ent.EmployeeMutation); ok {
+		return f(ctx, mv)
+	}
+	return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.EmployeeMutation", m)
+}
+
 // The LabelFunc type is an adapter to allow the use of ordinary
 // function as Label mutator.
 type LabelFunc func(context.Context, *ent.LabelMutation) (ent.Value, error)
@@ -152,6 +164,30 @@ func (f SopTaskFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, err
 	return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.SopTaskMutation", m)
 }
 
+// The TutorialFunc type is an adapter to allow the use of ordinary
+// function as Tutorial mutator.
+type TutorialFunc func(context.Context, *ent.TutorialMutation) (ent.Value, error)
+
+// Mutate calls f(ctx, m).
+func (f TutorialFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
+	if mv, ok := m.(*ent.TutorialMutation); ok {
+		return f(ctx, mv)
+	}
+	return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.TutorialMutation", m)
+}
+
+// The WorkExperienceFunc type is an adapter to allow the use of ordinary
+// function as WorkExperience mutator.
+type WorkExperienceFunc func(context.Context, *ent.WorkExperienceMutation) (ent.Value, error)
+
+// Mutate calls f(ctx, m).
+func (f WorkExperienceFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
+	if mv, ok := m.(*ent.WorkExperienceMutation); ok {
+		return f(ctx, mv)
+	}
+	return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.WorkExperienceMutation", m)
+}
+
 // The WxFunc type is an adapter to allow the use of ordinary
 // function as Wx mutator.
 type WxFunc func(context.Context, *ent.WxMutation) (ent.Value, error)

+ 90 - 0
ent/intercept/intercept.go

@@ -9,6 +9,7 @@ import (
 	"wechat-api/ent/agent"
 	"wechat-api/ent/batchmsg"
 	"wechat-api/ent/contact"
+	"wechat-api/ent/employee"
 	"wechat-api/ent/label"
 	"wechat-api/ent/labelrelationship"
 	"wechat-api/ent/message"
@@ -19,6 +20,8 @@ import (
 	"wechat-api/ent/sopnode"
 	"wechat-api/ent/sopstage"
 	"wechat-api/ent/soptask"
+	"wechat-api/ent/tutorial"
+	"wechat-api/ent/workexperience"
 	"wechat-api/ent/wx"
 
 	"entgo.io/ent/dialect/sql"
@@ -161,6 +164,33 @@ func (f TraverseContact) Traverse(ctx context.Context, q ent.Query) error {
 	return fmt.Errorf("unexpected query type %T. expect *ent.ContactQuery", q)
 }
 
+// The EmployeeFunc type is an adapter to allow the use of ordinary function as a Querier.
+type EmployeeFunc func(context.Context, *ent.EmployeeQuery) (ent.Value, error)
+
+// Query calls f(ctx, q).
+func (f EmployeeFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
+	if q, ok := q.(*ent.EmployeeQuery); ok {
+		return f(ctx, q)
+	}
+	return nil, fmt.Errorf("unexpected query type %T. expect *ent.EmployeeQuery", q)
+}
+
+// The TraverseEmployee type is an adapter to allow the use of ordinary function as Traverser.
+type TraverseEmployee func(context.Context, *ent.EmployeeQuery) error
+
+// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
+func (f TraverseEmployee) Intercept(next ent.Querier) ent.Querier {
+	return next
+}
+
+// Traverse calls f(ctx, q).
+func (f TraverseEmployee) Traverse(ctx context.Context, q ent.Query) error {
+	if q, ok := q.(*ent.EmployeeQuery); ok {
+		return f(ctx, q)
+	}
+	return fmt.Errorf("unexpected query type %T. expect *ent.EmployeeQuery", q)
+}
+
 // The LabelFunc type is an adapter to allow the use of ordinary function as a Querier.
 type LabelFunc func(context.Context, *ent.LabelQuery) (ent.Value, error)
 
@@ -404,6 +434,60 @@ func (f TraverseSopTask) Traverse(ctx context.Context, q ent.Query) error {
 	return fmt.Errorf("unexpected query type %T. expect *ent.SopTaskQuery", q)
 }
 
+// The TutorialFunc type is an adapter to allow the use of ordinary function as a Querier.
+type TutorialFunc func(context.Context, *ent.TutorialQuery) (ent.Value, error)
+
+// Query calls f(ctx, q).
+func (f TutorialFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
+	if q, ok := q.(*ent.TutorialQuery); ok {
+		return f(ctx, q)
+	}
+	return nil, fmt.Errorf("unexpected query type %T. expect *ent.TutorialQuery", q)
+}
+
+// The TraverseTutorial type is an adapter to allow the use of ordinary function as Traverser.
+type TraverseTutorial func(context.Context, *ent.TutorialQuery) error
+
+// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
+func (f TraverseTutorial) Intercept(next ent.Querier) ent.Querier {
+	return next
+}
+
+// Traverse calls f(ctx, q).
+func (f TraverseTutorial) Traverse(ctx context.Context, q ent.Query) error {
+	if q, ok := q.(*ent.TutorialQuery); ok {
+		return f(ctx, q)
+	}
+	return fmt.Errorf("unexpected query type %T. expect *ent.TutorialQuery", q)
+}
+
+// The WorkExperienceFunc type is an adapter to allow the use of ordinary function as a Querier.
+type WorkExperienceFunc func(context.Context, *ent.WorkExperienceQuery) (ent.Value, error)
+
+// Query calls f(ctx, q).
+func (f WorkExperienceFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
+	if q, ok := q.(*ent.WorkExperienceQuery); ok {
+		return f(ctx, q)
+	}
+	return nil, fmt.Errorf("unexpected query type %T. expect *ent.WorkExperienceQuery", q)
+}
+
+// The TraverseWorkExperience type is an adapter to allow the use of ordinary function as Traverser.
+type TraverseWorkExperience func(context.Context, *ent.WorkExperienceQuery) error
+
+// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
+func (f TraverseWorkExperience) Intercept(next ent.Querier) ent.Querier {
+	return next
+}
+
+// Traverse calls f(ctx, q).
+func (f TraverseWorkExperience) Traverse(ctx context.Context, q ent.Query) error {
+	if q, ok := q.(*ent.WorkExperienceQuery); ok {
+		return f(ctx, q)
+	}
+	return fmt.Errorf("unexpected query type %T. expect *ent.WorkExperienceQuery", q)
+}
+
 // The WxFunc type is an adapter to allow the use of ordinary function as a Querier.
 type WxFunc func(context.Context, *ent.WxQuery) (ent.Value, error)
 
@@ -440,6 +524,8 @@ func NewQuery(q ent.Query) (Query, error) {
 		return &query[*ent.BatchMsgQuery, predicate.BatchMsg, batchmsg.OrderOption]{typ: ent.TypeBatchMsg, tq: q}, nil
 	case *ent.ContactQuery:
 		return &query[*ent.ContactQuery, predicate.Contact, contact.OrderOption]{typ: ent.TypeContact, tq: q}, nil
+	case *ent.EmployeeQuery:
+		return &query[*ent.EmployeeQuery, predicate.Employee, employee.OrderOption]{typ: ent.TypeEmployee, tq: q}, nil
 	case *ent.LabelQuery:
 		return &query[*ent.LabelQuery, predicate.Label, label.OrderOption]{typ: ent.TypeLabel, tq: q}, nil
 	case *ent.LabelRelationshipQuery:
@@ -458,6 +544,10 @@ func NewQuery(q ent.Query) (Query, error) {
 		return &query[*ent.SopStageQuery, predicate.SopStage, sopstage.OrderOption]{typ: ent.TypeSopStage, tq: q}, nil
 	case *ent.SopTaskQuery:
 		return &query[*ent.SopTaskQuery, predicate.SopTask, soptask.OrderOption]{typ: ent.TypeSopTask, tq: q}, nil
+	case *ent.TutorialQuery:
+		return &query[*ent.TutorialQuery, predicate.Tutorial, tutorial.OrderOption]{typ: ent.TypeTutorial, tq: q}, nil
+	case *ent.WorkExperienceQuery:
+		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
 	default:

+ 115 - 0
ent/migrate/schema.go

@@ -125,6 +125,40 @@ var (
 			},
 		},
 	}
+	// EmployeeColumns holds the columns for the "employee" table.
+	EmployeeColumns = []*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: "title", Type: field.TypeString, Size: 255, Comment: "title | 标题"},
+		{Name: "avatar", Type: field.TypeString, Size: 1000, Comment: "avatar | 头像"},
+		{Name: "tags", Type: field.TypeString, Size: 255, Comment: "tags | 个人标签"},
+		{Name: "hire_count", Type: field.TypeInt, Comment: "hire_count | 被雇佣次数", Default: 0},
+		{Name: "service_count", Type: field.TypeInt, Comment: "service_count | 已服务次数", Default: 0},
+		{Name: "achievement_count", Type: field.TypeInt, Comment: "achievement_count | 业绩单数", Default: 0},
+		{Name: "intro", Type: field.TypeString, Size: 1000, Comment: "intro | 个人介绍", Default: ""},
+		{Name: "estimate", Type: field.TypeString, Size: 1000, Comment: "estimate | 自我评价", Default: ""},
+		{Name: "skill", Type: field.TypeString, Size: 1000, Comment: "skill | 技能卡", Default: ""},
+		{Name: "ability_type", Type: field.TypeString, Comment: "ability_type | 能力类型", Default: ""},
+		{Name: "scene", Type: field.TypeString, Comment: "scene | 使用场景", Default: ""},
+		{Name: "switch_in", Type: field.TypeString, Comment: "switch_in | 支持介入", Default: ""},
+		{Name: "video_url", Type: field.TypeString, Size: 1000, Comment: "video_url | 视频地址", Default: ""},
+		{Name: "organization_id", Type: field.TypeUint64, Comment: "organization_id | 租户ID"},
+	}
+	// EmployeeTable holds the schema information for the "employee" table.
+	EmployeeTable = &schema.Table{
+		Name:       "employee",
+		Columns:    EmployeeColumns,
+		PrimaryKey: []*schema.Column{EmployeeColumns[0]},
+		Indexes: []*schema.Index{
+			{
+				Name:    "employee_organization_id",
+				Unique:  false,
+				Columns: []*schema.Column{EmployeeColumns[17]},
+			},
+		},
+	}
 	// LabelColumns holds the columns for the "label" table.
 	LabelColumns = []*schema.Column{
 		{Name: "id", Type: field.TypeUint64, Increment: true},
@@ -434,6 +468,73 @@ var (
 			},
 		},
 	}
+	// TutorialColumns holds the columns for the "tutorial" table.
+	TutorialColumns = []*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: "index", Type: field.TypeInt, Comment: "index | 序号"},
+		{Name: "title", Type: field.TypeString, Comment: "title | 标题"},
+		{Name: "content", Type: field.TypeString, Comment: "content | 内容"},
+		{Name: "organization_id", Type: field.TypeUint64, Comment: "organization_id | 租户ID"},
+		{Name: "employee_id", Type: field.TypeUint64, Comment: "employee_id | 员工ID"},
+	}
+	// TutorialTable holds the schema information for the "tutorial" table.
+	TutorialTable = &schema.Table{
+		Name:       "tutorial",
+		Columns:    TutorialColumns,
+		PrimaryKey: []*schema.Column{TutorialColumns[0]},
+		ForeignKeys: []*schema.ForeignKey{
+			{
+				Symbol:     "tutorial_employee_em_tutorial",
+				Columns:    []*schema.Column{TutorialColumns[8]},
+				RefColumns: []*schema.Column{EmployeeColumns[0]},
+				OnDelete:   schema.NoAction,
+			},
+		},
+		Indexes: []*schema.Index{
+			{
+				Name:    "tutorial_employee_id",
+				Unique:  false,
+				Columns: []*schema.Column{TutorialColumns[8]},
+			},
+		},
+	}
+	// WorkExperienceColumns holds the columns for the "work_experience" table.
+	WorkExperienceColumns = []*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: "start_date", Type: field.TypeTime, Comment: "start_date | 开始时间"},
+		{Name: "end_date", Type: field.TypeTime, Comment: "end_date | 结束时间"},
+		{Name: "company", Type: field.TypeString, Comment: "company | 公司名"},
+		{Name: "experience", Type: field.TypeString, Size: 2147483647, Comment: "experience | 工作内容"},
+		{Name: "organization_id", Type: field.TypeUint64, Comment: "organization_id | 租户ID"},
+		{Name: "employee_id", Type: field.TypeUint64, Comment: "employee_id | 员工ID"},
+	}
+	// WorkExperienceTable holds the schema information for the "work_experience" table.
+	WorkExperienceTable = &schema.Table{
+		Name:       "work_experience",
+		Columns:    WorkExperienceColumns,
+		PrimaryKey: []*schema.Column{WorkExperienceColumns[0]},
+		ForeignKeys: []*schema.ForeignKey{
+			{
+				Symbol:     "work_experience_employee_em_work_experiences",
+				Columns:    []*schema.Column{WorkExperienceColumns[9]},
+				RefColumns: []*schema.Column{EmployeeColumns[0]},
+				OnDelete:   schema.NoAction,
+			},
+		},
+		Indexes: []*schema.Index{
+			{
+				Name:    "workexperience_employee_id",
+				Unique:  false,
+				Columns: []*schema.Column{WorkExperienceColumns[9]},
+			},
+		},
+	}
 	// WxColumns holds the columns for the "wx" table.
 	WxColumns = []*schema.Column{
 		{Name: "id", Type: field.TypeUint64, Increment: true},
@@ -505,6 +606,7 @@ var (
 		AgentTable,
 		BatchMsgTable,
 		ContactTable,
+		EmployeeTable,
 		LabelTable,
 		LabelRelationshipTable,
 		MessagesTable,
@@ -514,6 +616,8 @@ var (
 		SopNodeTable,
 		SopStageTable,
 		SopTaskTable,
+		TutorialTable,
+		WorkExperienceTable,
 		WxTable,
 	}
 )
@@ -528,6 +632,9 @@ func init() {
 	ContactTable.Annotation = &entsql.Annotation{
 		Table: "contact",
 	}
+	EmployeeTable.Annotation = &entsql.Annotation{
+		Table: "employee",
+	}
 	LabelTable.Annotation = &entsql.Annotation{
 		Table: "label",
 	}
@@ -562,6 +669,14 @@ func init() {
 	SopTaskTable.Annotation = &entsql.Annotation{
 		Table: "sop_task",
 	}
+	TutorialTable.ForeignKeys[0].RefTable = EmployeeTable
+	TutorialTable.Annotation = &entsql.Annotation{
+		Table: "tutorial",
+	}
+	WorkExperienceTable.ForeignKeys[0].RefTable = EmployeeTable
+	WorkExperienceTable.Annotation = &entsql.Annotation{
+		Table: "work_experience",
+	}
 	WxTable.ForeignKeys[0].RefTable = AgentTable
 	WxTable.ForeignKeys[1].RefTable = ServerTable
 	WxTable.Annotation = &entsql.Annotation{

File diff suppressed because it is too large
+ 495 - 225
ent/mutation.go


+ 246 - 0
ent/pagination.go

@@ -8,6 +8,7 @@ import (
 	"wechat-api/ent/agent"
 	"wechat-api/ent/batchmsg"
 	"wechat-api/ent/contact"
+	"wechat-api/ent/employee"
 	"wechat-api/ent/label"
 	"wechat-api/ent/labelrelationship"
 	"wechat-api/ent/message"
@@ -17,6 +18,8 @@ import (
 	"wechat-api/ent/sopnode"
 	"wechat-api/ent/sopstage"
 	"wechat-api/ent/soptask"
+	"wechat-api/ent/tutorial"
+	"wechat-api/ent/workexperience"
 	"wechat-api/ent/wx"
 )
 
@@ -309,6 +312,87 @@ func (c *ContactQuery) Page(
 	return ret, nil
 }
 
+type EmployeePager struct {
+	Order  employee.OrderOption
+	Filter func(*EmployeeQuery) (*EmployeeQuery, error)
+}
+
+// EmployeePaginateOption enables pagination customization.
+type EmployeePaginateOption func(*EmployeePager)
+
+// DefaultEmployeeOrder is the default ordering of Employee.
+var DefaultEmployeeOrder = Desc(employee.FieldID)
+
+func newEmployeePager(opts []EmployeePaginateOption) (*EmployeePager, error) {
+	pager := &EmployeePager{}
+	for _, opt := range opts {
+		opt(pager)
+	}
+	if pager.Order == nil {
+		pager.Order = DefaultEmployeeOrder
+	}
+	return pager, nil
+}
+
+func (p *EmployeePager) ApplyFilter(query *EmployeeQuery) (*EmployeeQuery, error) {
+	if p.Filter != nil {
+		return p.Filter(query)
+	}
+	return query, nil
+}
+
+// EmployeePageList is Employee PageList result.
+type EmployeePageList struct {
+	List        []*Employee  `json:"list"`
+	PageDetails *PageDetails `json:"pageDetails"`
+}
+
+func (e *EmployeeQuery) Page(
+	ctx context.Context, pageNum uint64, pageSize uint64, opts ...EmployeePaginateOption,
+) (*EmployeePageList, error) {
+
+	pager, err := newEmployeePager(opts)
+	if err != nil {
+		return nil, err
+	}
+
+	if e, err = pager.ApplyFilter(e); err != nil {
+		return nil, err
+	}
+
+	ret := &EmployeePageList{}
+
+	ret.PageDetails = &PageDetails{
+		Page: pageNum,
+		Size: pageSize,
+	}
+
+	query := e.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 {
+		e = e.Order(pager.Order)
+	} else {
+		e = e.Order(DefaultEmployeeOrder)
+	}
+
+	e = e.Offset(int((pageNum - 1) * pageSize)).Limit(int(pageSize))
+	list, err := e.All(ctx)
+	if err != nil {
+		return nil, err
+	}
+	ret.List = list
+
+	return ret, nil
+}
+
 type LabelPager struct {
 	Order  label.OrderOption
 	Filter func(*LabelQuery) (*LabelQuery, error)
@@ -1038,6 +1122,168 @@ func (st *SopTaskQuery) Page(
 	return ret, nil
 }
 
+type TutorialPager struct {
+	Order  tutorial.OrderOption
+	Filter func(*TutorialQuery) (*TutorialQuery, error)
+}
+
+// TutorialPaginateOption enables pagination customization.
+type TutorialPaginateOption func(*TutorialPager)
+
+// DefaultTutorialOrder is the default ordering of Tutorial.
+var DefaultTutorialOrder = Desc(tutorial.FieldID)
+
+func newTutorialPager(opts []TutorialPaginateOption) (*TutorialPager, error) {
+	pager := &TutorialPager{}
+	for _, opt := range opts {
+		opt(pager)
+	}
+	if pager.Order == nil {
+		pager.Order = DefaultTutorialOrder
+	}
+	return pager, nil
+}
+
+func (p *TutorialPager) ApplyFilter(query *TutorialQuery) (*TutorialQuery, error) {
+	if p.Filter != nil {
+		return p.Filter(query)
+	}
+	return query, nil
+}
+
+// TutorialPageList is Tutorial PageList result.
+type TutorialPageList struct {
+	List        []*Tutorial  `json:"list"`
+	PageDetails *PageDetails `json:"pageDetails"`
+}
+
+func (t *TutorialQuery) Page(
+	ctx context.Context, pageNum uint64, pageSize uint64, opts ...TutorialPaginateOption,
+) (*TutorialPageList, error) {
+
+	pager, err := newTutorialPager(opts)
+	if err != nil {
+		return nil, err
+	}
+
+	if t, err = pager.ApplyFilter(t); err != nil {
+		return nil, err
+	}
+
+	ret := &TutorialPageList{}
+
+	ret.PageDetails = &PageDetails{
+		Page: pageNum,
+		Size: pageSize,
+	}
+
+	query := t.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 {
+		t = t.Order(pager.Order)
+	} else {
+		t = t.Order(DefaultTutorialOrder)
+	}
+
+	t = t.Offset(int((pageNum - 1) * pageSize)).Limit(int(pageSize))
+	list, err := t.All(ctx)
+	if err != nil {
+		return nil, err
+	}
+	ret.List = list
+
+	return ret, nil
+}
+
+type WorkExperiencePager struct {
+	Order  workexperience.OrderOption
+	Filter func(*WorkExperienceQuery) (*WorkExperienceQuery, error)
+}
+
+// WorkExperiencePaginateOption enables pagination customization.
+type WorkExperiencePaginateOption func(*WorkExperiencePager)
+
+// DefaultWorkExperienceOrder is the default ordering of WorkExperience.
+var DefaultWorkExperienceOrder = Desc(workexperience.FieldID)
+
+func newWorkExperiencePager(opts []WorkExperiencePaginateOption) (*WorkExperiencePager, error) {
+	pager := &WorkExperiencePager{}
+	for _, opt := range opts {
+		opt(pager)
+	}
+	if pager.Order == nil {
+		pager.Order = DefaultWorkExperienceOrder
+	}
+	return pager, nil
+}
+
+func (p *WorkExperiencePager) ApplyFilter(query *WorkExperienceQuery) (*WorkExperienceQuery, error) {
+	if p.Filter != nil {
+		return p.Filter(query)
+	}
+	return query, nil
+}
+
+// WorkExperiencePageList is WorkExperience PageList result.
+type WorkExperiencePageList struct {
+	List        []*WorkExperience `json:"list"`
+	PageDetails *PageDetails      `json:"pageDetails"`
+}
+
+func (we *WorkExperienceQuery) Page(
+	ctx context.Context, pageNum uint64, pageSize uint64, opts ...WorkExperiencePaginateOption,
+) (*WorkExperiencePageList, error) {
+
+	pager, err := newWorkExperiencePager(opts)
+	if err != nil {
+		return nil, err
+	}
+
+	if we, err = pager.ApplyFilter(we); err != nil {
+		return nil, err
+	}
+
+	ret := &WorkExperiencePageList{}
+
+	ret.PageDetails = &PageDetails{
+		Page: pageNum,
+		Size: pageSize,
+	}
+
+	query := we.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 {
+		we = we.Order(pager.Order)
+	} else {
+		we = we.Order(DefaultWorkExperienceOrder)
+	}
+
+	we = we.Offset(int((pageNum - 1) * pageSize)).Limit(int(pageSize))
+	list, err := we.All(ctx)
+	if err != nil {
+		return nil, err
+	}
+	ret.List = list
+
+	return ret, nil
+}
+
 type WxPager struct {
 	Order  wx.OrderOption
 	Filter func(*WxQuery) (*WxQuery, error)

+ 9 - 0
ent/predicate/predicate.go

@@ -15,6 +15,9 @@ type BatchMsg func(*sql.Selector)
 // Contact is the predicate function for contact builders.
 type Contact func(*sql.Selector)
 
+// Employee is the predicate function for employee builders.
+type Employee func(*sql.Selector)
+
 // Label is the predicate function for label builders.
 type Label func(*sql.Selector)
 
@@ -42,5 +45,11 @@ type SopStage func(*sql.Selector)
 // SopTask is the predicate function for soptask builders.
 type SopTask func(*sql.Selector)
 
+// Tutorial is the predicate function for tutorial builders.
+type Tutorial func(*sql.Selector)
+
+// WorkExperience is the predicate function for workexperience builders.
+type WorkExperience func(*sql.Selector)
+
 // Wx is the predicate function for wx builders.
 type Wx func(*sql.Selector)

+ 138 - 0
ent/runtime/runtime.go

@@ -7,6 +7,7 @@ import (
 	"wechat-api/ent/agent"
 	"wechat-api/ent/batchmsg"
 	"wechat-api/ent/contact"
+	"wechat-api/ent/employee"
 	"wechat-api/ent/label"
 	"wechat-api/ent/labelrelationship"
 	"wechat-api/ent/message"
@@ -17,6 +18,8 @@ import (
 	"wechat-api/ent/sopnode"
 	"wechat-api/ent/sopstage"
 	"wechat-api/ent/soptask"
+	"wechat-api/ent/tutorial"
+	"wechat-api/ent/workexperience"
 	"wechat-api/ent/wx"
 )
 
@@ -185,6 +188,95 @@ func init() {
 	contactDescOrganizationID := contactFields[15].Descriptor()
 	// contact.DefaultOrganizationID holds the default value on creation for the organization_id field.
 	contact.DefaultOrganizationID = contactDescOrganizationID.Default.(uint64)
+	employeeMixin := schema.Employee{}.Mixin()
+	employeeMixinHooks1 := employeeMixin[1].Hooks()
+	employee.Hooks[0] = employeeMixinHooks1[0]
+	employeeMixinInters1 := employeeMixin[1].Interceptors()
+	employee.Interceptors[0] = employeeMixinInters1[0]
+	employeeMixinFields0 := employeeMixin[0].Fields()
+	_ = employeeMixinFields0
+	employeeFields := schema.Employee{}.Fields()
+	_ = employeeFields
+	// employeeDescCreatedAt is the schema descriptor for created_at field.
+	employeeDescCreatedAt := employeeMixinFields0[1].Descriptor()
+	// employee.DefaultCreatedAt holds the default value on creation for the created_at field.
+	employee.DefaultCreatedAt = employeeDescCreatedAt.Default.(func() time.Time)
+	// employeeDescUpdatedAt is the schema descriptor for updated_at field.
+	employeeDescUpdatedAt := employeeMixinFields0[2].Descriptor()
+	// employee.DefaultUpdatedAt holds the default value on creation for the updated_at field.
+	employee.DefaultUpdatedAt = employeeDescUpdatedAt.Default.(func() time.Time)
+	// employee.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
+	employee.UpdateDefaultUpdatedAt = employeeDescUpdatedAt.UpdateDefault.(func() time.Time)
+	// employeeDescTitle is the schema descriptor for title field.
+	employeeDescTitle := employeeFields[0].Descriptor()
+	// employee.TitleValidator is a validator for the "title" field. It is called by the builders before save.
+	employee.TitleValidator = employeeDescTitle.Validators[0].(func(string) error)
+	// employeeDescAvatar is the schema descriptor for avatar field.
+	employeeDescAvatar := employeeFields[1].Descriptor()
+	// employee.AvatarValidator is a validator for the "avatar" field. It is called by the builders before save.
+	employee.AvatarValidator = employeeDescAvatar.Validators[0].(func(string) error)
+	// employeeDescTags is the schema descriptor for tags field.
+	employeeDescTags := employeeFields[2].Descriptor()
+	// employee.TagsValidator is a validator for the "tags" field. It is called by the builders before save.
+	employee.TagsValidator = employeeDescTags.Validators[0].(func(string) error)
+	// employeeDescHireCount is the schema descriptor for hire_count field.
+	employeeDescHireCount := employeeFields[3].Descriptor()
+	// employee.DefaultHireCount holds the default value on creation for the hire_count field.
+	employee.DefaultHireCount = employeeDescHireCount.Default.(int)
+	// employee.HireCountValidator is a validator for the "hire_count" field. It is called by the builders before save.
+	employee.HireCountValidator = employeeDescHireCount.Validators[0].(func(int) error)
+	// employeeDescServiceCount is the schema descriptor for service_count field.
+	employeeDescServiceCount := employeeFields[4].Descriptor()
+	// employee.DefaultServiceCount holds the default value on creation for the service_count field.
+	employee.DefaultServiceCount = employeeDescServiceCount.Default.(int)
+	// employee.ServiceCountValidator is a validator for the "service_count" field. It is called by the builders before save.
+	employee.ServiceCountValidator = employeeDescServiceCount.Validators[0].(func(int) error)
+	// employeeDescAchievementCount is the schema descriptor for achievement_count field.
+	employeeDescAchievementCount := employeeFields[5].Descriptor()
+	// employee.DefaultAchievementCount holds the default value on creation for the achievement_count field.
+	employee.DefaultAchievementCount = employeeDescAchievementCount.Default.(int)
+	// employee.AchievementCountValidator is a validator for the "achievement_count" field. It is called by the builders before save.
+	employee.AchievementCountValidator = employeeDescAchievementCount.Validators[0].(func(int) error)
+	// employeeDescIntro is the schema descriptor for intro field.
+	employeeDescIntro := employeeFields[6].Descriptor()
+	// employee.DefaultIntro holds the default value on creation for the intro field.
+	employee.DefaultIntro = employeeDescIntro.Default.(string)
+	// employee.IntroValidator is a validator for the "intro" field. It is called by the builders before save.
+	employee.IntroValidator = employeeDescIntro.Validators[0].(func(string) error)
+	// employeeDescEstimate is the schema descriptor for estimate field.
+	employeeDescEstimate := employeeFields[7].Descriptor()
+	// employee.DefaultEstimate holds the default value on creation for the estimate field.
+	employee.DefaultEstimate = employeeDescEstimate.Default.(string)
+	// employee.EstimateValidator is a validator for the "estimate" field. It is called by the builders before save.
+	employee.EstimateValidator = employeeDescEstimate.Validators[0].(func(string) error)
+	// employeeDescSkill is the schema descriptor for skill field.
+	employeeDescSkill := employeeFields[8].Descriptor()
+	// employee.DefaultSkill holds the default value on creation for the skill field.
+	employee.DefaultSkill = employeeDescSkill.Default.(string)
+	// employee.SkillValidator is a validator for the "skill" field. It is called by the builders before save.
+	employee.SkillValidator = employeeDescSkill.Validators[0].(func(string) error)
+	// employeeDescAbilityType is the schema descriptor for ability_type field.
+	employeeDescAbilityType := employeeFields[9].Descriptor()
+	// employee.DefaultAbilityType holds the default value on creation for the ability_type field.
+	employee.DefaultAbilityType = employeeDescAbilityType.Default.(string)
+	// employeeDescScene is the schema descriptor for scene field.
+	employeeDescScene := employeeFields[10].Descriptor()
+	// employee.DefaultScene holds the default value on creation for the scene field.
+	employee.DefaultScene = employeeDescScene.Default.(string)
+	// employeeDescSwitchIn is the schema descriptor for switch_in field.
+	employeeDescSwitchIn := employeeFields[11].Descriptor()
+	// employee.DefaultSwitchIn holds the default value on creation for the switch_in field.
+	employee.DefaultSwitchIn = employeeDescSwitchIn.Default.(string)
+	// employeeDescVideoURL is the schema descriptor for video_url field.
+	employeeDescVideoURL := employeeFields[12].Descriptor()
+	// employee.DefaultVideoURL holds the default value on creation for the video_url field.
+	employee.DefaultVideoURL = employeeDescVideoURL.Default.(string)
+	// employee.VideoURLValidator is a validator for the "video_url" field. It is called by the builders before save.
+	employee.VideoURLValidator = employeeDescVideoURL.Validators[0].(func(string) error)
+	// employeeDescOrganizationID is the schema descriptor for organization_id field.
+	employeeDescOrganizationID := employeeFields[13].Descriptor()
+	// employee.OrganizationIDValidator is a validator for the "organization_id" field. It is called by the builders before save.
+	employee.OrganizationIDValidator = employeeDescOrganizationID.Validators[0].(func(uint64) error)
 	labelMixin := schema.Label{}.Mixin()
 	labelMixinFields0 := labelMixin[0].Fields()
 	_ = labelMixinFields0
@@ -501,6 +593,52 @@ func init() {
 	soptaskDescOrganizationID := soptaskFields[6].Descriptor()
 	// soptask.DefaultOrganizationID holds the default value on creation for the organization_id field.
 	soptask.DefaultOrganizationID = soptaskDescOrganizationID.Default.(uint64)
+	tutorialMixin := schema.Tutorial{}.Mixin()
+	tutorialMixinHooks1 := tutorialMixin[1].Hooks()
+	tutorial.Hooks[0] = tutorialMixinHooks1[0]
+	tutorialMixinInters1 := tutorialMixin[1].Interceptors()
+	tutorial.Interceptors[0] = tutorialMixinInters1[0]
+	tutorialMixinFields0 := tutorialMixin[0].Fields()
+	_ = tutorialMixinFields0
+	tutorialFields := schema.Tutorial{}.Fields()
+	_ = tutorialFields
+	// tutorialDescCreatedAt is the schema descriptor for created_at field.
+	tutorialDescCreatedAt := tutorialMixinFields0[1].Descriptor()
+	// tutorial.DefaultCreatedAt holds the default value on creation for the created_at field.
+	tutorial.DefaultCreatedAt = tutorialDescCreatedAt.Default.(func() time.Time)
+	// tutorialDescUpdatedAt is the schema descriptor for updated_at field.
+	tutorialDescUpdatedAt := tutorialMixinFields0[2].Descriptor()
+	// tutorial.DefaultUpdatedAt holds the default value on creation for the updated_at field.
+	tutorial.DefaultUpdatedAt = tutorialDescUpdatedAt.Default.(func() time.Time)
+	// tutorial.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
+	tutorial.UpdateDefaultUpdatedAt = tutorialDescUpdatedAt.UpdateDefault.(func() time.Time)
+	// tutorialDescEmployeeID is the schema descriptor for employee_id field.
+	tutorialDescEmployeeID := tutorialFields[0].Descriptor()
+	// tutorial.EmployeeIDValidator is a validator for the "employee_id" field. It is called by the builders before save.
+	tutorial.EmployeeIDValidator = tutorialDescEmployeeID.Validators[0].(func(uint64) error)
+	// tutorialDescOrganizationID is the schema descriptor for organization_id field.
+	tutorialDescOrganizationID := tutorialFields[4].Descriptor()
+	// tutorial.OrganizationIDValidator is a validator for the "organization_id" field. It is called by the builders before save.
+	tutorial.OrganizationIDValidator = tutorialDescOrganizationID.Validators[0].(func(uint64) error)
+	workexperienceMixin := schema.WorkExperience{}.Mixin()
+	workexperienceMixinHooks1 := workexperienceMixin[1].Hooks()
+	workexperience.Hooks[0] = workexperienceMixinHooks1[0]
+	workexperienceMixinInters1 := workexperienceMixin[1].Interceptors()
+	workexperience.Interceptors[0] = workexperienceMixinInters1[0]
+	workexperienceMixinFields0 := workexperienceMixin[0].Fields()
+	_ = workexperienceMixinFields0
+	workexperienceFields := schema.WorkExperience{}.Fields()
+	_ = workexperienceFields
+	// workexperienceDescCreatedAt is the schema descriptor for created_at field.
+	workexperienceDescCreatedAt := workexperienceMixinFields0[1].Descriptor()
+	// workexperience.DefaultCreatedAt holds the default value on creation for the created_at field.
+	workexperience.DefaultCreatedAt = workexperienceDescCreatedAt.Default.(func() time.Time)
+	// workexperienceDescUpdatedAt is the schema descriptor for updated_at field.
+	workexperienceDescUpdatedAt := workexperienceMixinFields0[2].Descriptor()
+	// workexperience.DefaultUpdatedAt holds the default value on creation for the updated_at field.
+	workexperience.DefaultUpdatedAt = workexperienceDescUpdatedAt.Default.(func() time.Time)
+	// workexperience.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
+	workexperience.UpdateDefaultUpdatedAt = workexperienceDescUpdatedAt.UpdateDefault.(func() time.Time)
 	wxMixin := schema.Wx{}.Mixin()
 	wxMixinHooks2 := wxMixin[2].Hooks()
 	wx.Hooks[0] = wxMixinHooks2[0]

+ 63 - 0
ent/schema/employee.go

@@ -0,0 +1,63 @@
+package schema
+
+import (
+	"entgo.io/ent/schema/edge"
+	"entgo.io/ent/schema/index"
+	"wechat-api/ent/schema/localmixin"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/entsql"
+	"entgo.io/ent/schema"
+	"entgo.io/ent/schema/field"
+	"github.com/suyuan32/simple-admin-common/orm/ent/mixins"
+)
+
+type Employee struct {
+	ent.Schema
+}
+
+func (Employee) Fields() []ent.Field {
+	return []ent.Field{
+		field.String("title").MaxLen(255).Comment("title | 标题"),
+		field.String("avatar").MaxLen(1000).Comment("avatar | 头像"),
+		field.String("tags").MaxLen(255).Comment("tags | 个人标签"),
+		field.Int("hire_count").Positive().Default(0).Comment("hire_count | 被雇佣次数"),
+		field.Int("service_count").Positive().Default(0).Comment("service_count | 已服务次数"),
+		field.Int("achievement_count").Positive().Default(0).Comment("achievement_count | 业绩单数"),
+		field.String("intro").MaxLen(1000).Default("").Comment("intro | 个人介绍"),
+		field.String("estimate").MaxLen(1000).Default("").Comment("estimate | 自我评价"),
+		field.String("skill").MaxLen(1000).Default("").Comment("skill | 技能卡"),
+		field.String("ability_type").Default("").Comment("ability_type | 能力类型"),
+		field.String("scene").Default("").Comment("scene | 使用场景"),
+		field.String("switch_in").Default("").Comment("switch_in | 支持介入"),
+		field.String("video_url").MaxLen(1000).Default("").Comment("video_url | 视频地址"),
+		field.Uint64("organization_id").Positive().Comment("organization_id | 租户ID"),
+	}
+}
+
+func (Employee) Mixin() []ent.Mixin {
+	return []ent.Mixin{
+		mixins.IDMixin{},
+		localmixin.SoftDeleteMixin{},
+	}
+}
+
+func (Employee) Edges() []ent.Edge {
+	return []ent.Edge{
+		edge.To("em_work_experiences", WorkExperience.Type),
+		edge.To("em_tutorial", Tutorial.Type),
+	}
+}
+
+func (Employee) Indexes() []ent.Index {
+	return []ent.Index{
+		index.Fields("organization_id"),
+	}
+}
+
+func (Employee) Annotations() []schema.Annotation {
+	return []schema.Annotation{
+		entsql.WithComments(true),
+		entsql.Annotation{Table: "employee"},
+	}
+}

+ 57 - 0
ent/schema/tutorial.go

@@ -0,0 +1,57 @@
+package schema
+
+import (
+	"entgo.io/ent/schema/edge"
+	"entgo.io/ent/schema/index"
+	"wechat-api/ent/schema/localmixin"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/entsql"
+	"entgo.io/ent/schema"
+	"entgo.io/ent/schema/field"
+	"github.com/suyuan32/simple-admin-common/orm/ent/mixins"
+)
+
+type Tutorial struct {
+	ent.Schema
+}
+
+func (Tutorial) Fields() []ent.Field {
+	return []ent.Field{
+		field.Uint64("employee_id").Positive().Comment("employee_id | 员工ID"),
+		field.Int("index").Comment("index | 序号"),
+		field.String("title").Comment("title | 标题"),
+		field.String("content").Comment("content | 内容"),
+		field.Uint64("organization_id").Positive().Comment("organization_id | 租户ID"),
+	}
+}
+
+func (Tutorial) Mixin() []ent.Mixin {
+	return []ent.Mixin{
+		mixins.IDMixin{},
+		localmixin.SoftDeleteMixin{},
+	}
+}
+
+func (Tutorial) Edges() []ent.Edge {
+	return []ent.Edge{
+		edge.From("employee", Employee.Type).
+			Ref("em_tutorial").
+			Field("employee_id").
+			Unique().
+			Required(),
+	}
+}
+
+func (Tutorial) Indexes() []ent.Index {
+	return []ent.Index{
+		index.Fields("employee_id"),
+	}
+}
+
+func (Tutorial) Annotations() []schema.Annotation {
+	return []schema.Annotation{
+		entsql.WithComments(true),
+		entsql.Annotation{Table: "tutorial"},
+	}
+}

+ 58 - 0
ent/schema/work_experience.go

@@ -0,0 +1,58 @@
+package schema
+
+import (
+	"entgo.io/ent/schema/edge"
+	"entgo.io/ent/schema/index"
+	"wechat-api/ent/schema/localmixin"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/entsql"
+	"entgo.io/ent/schema"
+	"entgo.io/ent/schema/field"
+	"github.com/suyuan32/simple-admin-common/orm/ent/mixins"
+)
+
+type WorkExperience struct {
+	ent.Schema
+}
+
+func (WorkExperience) Fields() []ent.Field {
+	return []ent.Field{
+		field.Uint64("employee_id").Comment("employee_id | 员工ID"),
+		field.Time("start_date").Comment("start_date | 开始时间"),
+		field.Time("end_date").Comment("end_date | 结束时间"),
+		field.String("company").Comment("company | 公司名"),
+		field.Text("experience").Comment("experience | 工作内容"),
+		field.Uint64("organization_id").Comment("organization_id | 租户ID"),
+	}
+}
+
+func (WorkExperience) Mixin() []ent.Mixin {
+	return []ent.Mixin{
+		mixins.IDMixin{},
+		localmixin.SoftDeleteMixin{},
+	}
+}
+
+func (WorkExperience) Edges() []ent.Edge {
+	return []ent.Edge{
+		edge.From("employee", Employee.Type).
+			Ref("em_work_experiences").
+			Field("employee_id").
+			Unique().
+			Required(),
+	}
+}
+
+func (WorkExperience) Indexes() []ent.Index {
+	return []ent.Index{
+		index.Fields("employee_id"),
+	}
+}
+
+func (WorkExperience) Annotations() []schema.Annotation {
+	return []schema.Annotation{
+		entsql.WithComments(true),
+		entsql.Annotation{Table: "work_experience"},
+	}
+}

+ 744 - 0
ent/set_not_nil.go

@@ -1016,6 +1016,390 @@ func (c *ContactCreate) SetNotNilOrganizationID(value *uint64) *ContactCreate {
 }
 
 // set field if value's pointer is not nil.
+func (e *EmployeeUpdate) SetNotNilUpdatedAt(value *time.Time) *EmployeeUpdate {
+	if value != nil {
+		return e.SetUpdatedAt(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdateOne) SetNotNilUpdatedAt(value *time.Time) *EmployeeUpdateOne {
+	if value != nil {
+		return e.SetUpdatedAt(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeCreate) SetNotNilUpdatedAt(value *time.Time) *EmployeeCreate {
+	if value != nil {
+		return e.SetUpdatedAt(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdate) SetNotNilDeletedAt(value *time.Time) *EmployeeUpdate {
+	if value != nil {
+		return e.SetDeletedAt(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdateOne) SetNotNilDeletedAt(value *time.Time) *EmployeeUpdateOne {
+	if value != nil {
+		return e.SetDeletedAt(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeCreate) SetNotNilDeletedAt(value *time.Time) *EmployeeCreate {
+	if value != nil {
+		return e.SetDeletedAt(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdate) SetNotNilTitle(value *string) *EmployeeUpdate {
+	if value != nil {
+		return e.SetTitle(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdateOne) SetNotNilTitle(value *string) *EmployeeUpdateOne {
+	if value != nil {
+		return e.SetTitle(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeCreate) SetNotNilTitle(value *string) *EmployeeCreate {
+	if value != nil {
+		return e.SetTitle(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdate) SetNotNilAvatar(value *string) *EmployeeUpdate {
+	if value != nil {
+		return e.SetAvatar(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdateOne) SetNotNilAvatar(value *string) *EmployeeUpdateOne {
+	if value != nil {
+		return e.SetAvatar(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeCreate) SetNotNilAvatar(value *string) *EmployeeCreate {
+	if value != nil {
+		return e.SetAvatar(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdate) SetNotNilTags(value *string) *EmployeeUpdate {
+	if value != nil {
+		return e.SetTags(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdateOne) SetNotNilTags(value *string) *EmployeeUpdateOne {
+	if value != nil {
+		return e.SetTags(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeCreate) SetNotNilTags(value *string) *EmployeeCreate {
+	if value != nil {
+		return e.SetTags(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdate) SetNotNilHireCount(value *int) *EmployeeUpdate {
+	if value != nil {
+		return e.SetHireCount(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdateOne) SetNotNilHireCount(value *int) *EmployeeUpdateOne {
+	if value != nil {
+		return e.SetHireCount(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeCreate) SetNotNilHireCount(value *int) *EmployeeCreate {
+	if value != nil {
+		return e.SetHireCount(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdate) SetNotNilServiceCount(value *int) *EmployeeUpdate {
+	if value != nil {
+		return e.SetServiceCount(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdateOne) SetNotNilServiceCount(value *int) *EmployeeUpdateOne {
+	if value != nil {
+		return e.SetServiceCount(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeCreate) SetNotNilServiceCount(value *int) *EmployeeCreate {
+	if value != nil {
+		return e.SetServiceCount(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdate) SetNotNilAchievementCount(value *int) *EmployeeUpdate {
+	if value != nil {
+		return e.SetAchievementCount(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdateOne) SetNotNilAchievementCount(value *int) *EmployeeUpdateOne {
+	if value != nil {
+		return e.SetAchievementCount(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeCreate) SetNotNilAchievementCount(value *int) *EmployeeCreate {
+	if value != nil {
+		return e.SetAchievementCount(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdate) SetNotNilIntro(value *string) *EmployeeUpdate {
+	if value != nil {
+		return e.SetIntro(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdateOne) SetNotNilIntro(value *string) *EmployeeUpdateOne {
+	if value != nil {
+		return e.SetIntro(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeCreate) SetNotNilIntro(value *string) *EmployeeCreate {
+	if value != nil {
+		return e.SetIntro(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdate) SetNotNilEstimate(value *string) *EmployeeUpdate {
+	if value != nil {
+		return e.SetEstimate(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdateOne) SetNotNilEstimate(value *string) *EmployeeUpdateOne {
+	if value != nil {
+		return e.SetEstimate(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeCreate) SetNotNilEstimate(value *string) *EmployeeCreate {
+	if value != nil {
+		return e.SetEstimate(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdate) SetNotNilSkill(value *string) *EmployeeUpdate {
+	if value != nil {
+		return e.SetSkill(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdateOne) SetNotNilSkill(value *string) *EmployeeUpdateOne {
+	if value != nil {
+		return e.SetSkill(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeCreate) SetNotNilSkill(value *string) *EmployeeCreate {
+	if value != nil {
+		return e.SetSkill(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdate) SetNotNilAbilityType(value *string) *EmployeeUpdate {
+	if value != nil {
+		return e.SetAbilityType(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdateOne) SetNotNilAbilityType(value *string) *EmployeeUpdateOne {
+	if value != nil {
+		return e.SetAbilityType(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeCreate) SetNotNilAbilityType(value *string) *EmployeeCreate {
+	if value != nil {
+		return e.SetAbilityType(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdate) SetNotNilScene(value *string) *EmployeeUpdate {
+	if value != nil {
+		return e.SetScene(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdateOne) SetNotNilScene(value *string) *EmployeeUpdateOne {
+	if value != nil {
+		return e.SetScene(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeCreate) SetNotNilScene(value *string) *EmployeeCreate {
+	if value != nil {
+		return e.SetScene(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdate) SetNotNilSwitchIn(value *string) *EmployeeUpdate {
+	if value != nil {
+		return e.SetSwitchIn(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdateOne) SetNotNilSwitchIn(value *string) *EmployeeUpdateOne {
+	if value != nil {
+		return e.SetSwitchIn(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeCreate) SetNotNilSwitchIn(value *string) *EmployeeCreate {
+	if value != nil {
+		return e.SetSwitchIn(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdate) SetNotNilVideoURL(value *string) *EmployeeUpdate {
+	if value != nil {
+		return e.SetVideoURL(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdateOne) SetNotNilVideoURL(value *string) *EmployeeUpdateOne {
+	if value != nil {
+		return e.SetVideoURL(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeCreate) SetNotNilVideoURL(value *string) *EmployeeCreate {
+	if value != nil {
+		return e.SetVideoURL(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdate) SetNotNilOrganizationID(value *uint64) *EmployeeUpdate {
+	if value != nil {
+		return e.SetOrganizationID(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeUpdateOne) SetNotNilOrganizationID(value *uint64) *EmployeeUpdateOne {
+	if value != nil {
+		return e.SetOrganizationID(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
+func (e *EmployeeCreate) SetNotNilOrganizationID(value *uint64) *EmployeeCreate {
+	if value != nil {
+		return e.SetOrganizationID(*value)
+	}
+	return e
+}
+
+// set field if value's pointer is not nil.
 func (l *LabelUpdate) SetNotNilUpdatedAt(value *time.Time) *LabelUpdate {
 	if value != nil {
 		return l.SetUpdatedAt(*value)
@@ -2936,6 +3320,366 @@ func (st *SopTaskCreate) SetNotNilOrganizationID(value *uint64) *SopTaskCreate {
 }
 
 // set field if value's pointer is not nil.
+func (t *TutorialUpdate) SetNotNilUpdatedAt(value *time.Time) *TutorialUpdate {
+	if value != nil {
+		return t.SetUpdatedAt(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialUpdateOne) SetNotNilUpdatedAt(value *time.Time) *TutorialUpdateOne {
+	if value != nil {
+		return t.SetUpdatedAt(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialCreate) SetNotNilUpdatedAt(value *time.Time) *TutorialCreate {
+	if value != nil {
+		return t.SetUpdatedAt(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialUpdate) SetNotNilDeletedAt(value *time.Time) *TutorialUpdate {
+	if value != nil {
+		return t.SetDeletedAt(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialUpdateOne) SetNotNilDeletedAt(value *time.Time) *TutorialUpdateOne {
+	if value != nil {
+		return t.SetDeletedAt(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialCreate) SetNotNilDeletedAt(value *time.Time) *TutorialCreate {
+	if value != nil {
+		return t.SetDeletedAt(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialUpdate) SetNotNilEmployeeID(value *uint64) *TutorialUpdate {
+	if value != nil {
+		return t.SetEmployeeID(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialUpdateOne) SetNotNilEmployeeID(value *uint64) *TutorialUpdateOne {
+	if value != nil {
+		return t.SetEmployeeID(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialCreate) SetNotNilEmployeeID(value *uint64) *TutorialCreate {
+	if value != nil {
+		return t.SetEmployeeID(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialUpdate) SetNotNilIndex(value *int) *TutorialUpdate {
+	if value != nil {
+		return t.SetIndex(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialUpdateOne) SetNotNilIndex(value *int) *TutorialUpdateOne {
+	if value != nil {
+		return t.SetIndex(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialCreate) SetNotNilIndex(value *int) *TutorialCreate {
+	if value != nil {
+		return t.SetIndex(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialUpdate) SetNotNilTitle(value *string) *TutorialUpdate {
+	if value != nil {
+		return t.SetTitle(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialUpdateOne) SetNotNilTitle(value *string) *TutorialUpdateOne {
+	if value != nil {
+		return t.SetTitle(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialCreate) SetNotNilTitle(value *string) *TutorialCreate {
+	if value != nil {
+		return t.SetTitle(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialUpdate) SetNotNilContent(value *string) *TutorialUpdate {
+	if value != nil {
+		return t.SetContent(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialUpdateOne) SetNotNilContent(value *string) *TutorialUpdateOne {
+	if value != nil {
+		return t.SetContent(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialCreate) SetNotNilContent(value *string) *TutorialCreate {
+	if value != nil {
+		return t.SetContent(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialUpdate) SetNotNilOrganizationID(value *uint64) *TutorialUpdate {
+	if value != nil {
+		return t.SetOrganizationID(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialUpdateOne) SetNotNilOrganizationID(value *uint64) *TutorialUpdateOne {
+	if value != nil {
+		return t.SetOrganizationID(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (t *TutorialCreate) SetNotNilOrganizationID(value *uint64) *TutorialCreate {
+	if value != nil {
+		return t.SetOrganizationID(*value)
+	}
+	return t
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceUpdate) SetNotNilUpdatedAt(value *time.Time) *WorkExperienceUpdate {
+	if value != nil {
+		return we.SetUpdatedAt(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceUpdateOne) SetNotNilUpdatedAt(value *time.Time) *WorkExperienceUpdateOne {
+	if value != nil {
+		return we.SetUpdatedAt(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceCreate) SetNotNilUpdatedAt(value *time.Time) *WorkExperienceCreate {
+	if value != nil {
+		return we.SetUpdatedAt(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceUpdate) SetNotNilDeletedAt(value *time.Time) *WorkExperienceUpdate {
+	if value != nil {
+		return we.SetDeletedAt(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceUpdateOne) SetNotNilDeletedAt(value *time.Time) *WorkExperienceUpdateOne {
+	if value != nil {
+		return we.SetDeletedAt(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceCreate) SetNotNilDeletedAt(value *time.Time) *WorkExperienceCreate {
+	if value != nil {
+		return we.SetDeletedAt(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceUpdate) SetNotNilEmployeeID(value *uint64) *WorkExperienceUpdate {
+	if value != nil {
+		return we.SetEmployeeID(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceUpdateOne) SetNotNilEmployeeID(value *uint64) *WorkExperienceUpdateOne {
+	if value != nil {
+		return we.SetEmployeeID(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceCreate) SetNotNilEmployeeID(value *uint64) *WorkExperienceCreate {
+	if value != nil {
+		return we.SetEmployeeID(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceUpdate) SetNotNilStartDate(value *time.Time) *WorkExperienceUpdate {
+	if value != nil {
+		return we.SetStartDate(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceUpdateOne) SetNotNilStartDate(value *time.Time) *WorkExperienceUpdateOne {
+	if value != nil {
+		return we.SetStartDate(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceCreate) SetNotNilStartDate(value *time.Time) *WorkExperienceCreate {
+	if value != nil {
+		return we.SetStartDate(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceUpdate) SetNotNilEndDate(value *time.Time) *WorkExperienceUpdate {
+	if value != nil {
+		return we.SetEndDate(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceUpdateOne) SetNotNilEndDate(value *time.Time) *WorkExperienceUpdateOne {
+	if value != nil {
+		return we.SetEndDate(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceCreate) SetNotNilEndDate(value *time.Time) *WorkExperienceCreate {
+	if value != nil {
+		return we.SetEndDate(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceUpdate) SetNotNilCompany(value *string) *WorkExperienceUpdate {
+	if value != nil {
+		return we.SetCompany(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceUpdateOne) SetNotNilCompany(value *string) *WorkExperienceUpdateOne {
+	if value != nil {
+		return we.SetCompany(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceCreate) SetNotNilCompany(value *string) *WorkExperienceCreate {
+	if value != nil {
+		return we.SetCompany(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceUpdate) SetNotNilExperience(value *string) *WorkExperienceUpdate {
+	if value != nil {
+		return we.SetExperience(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceUpdateOne) SetNotNilExperience(value *string) *WorkExperienceUpdateOne {
+	if value != nil {
+		return we.SetExperience(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceCreate) SetNotNilExperience(value *string) *WorkExperienceCreate {
+	if value != nil {
+		return we.SetExperience(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceUpdate) SetNotNilOrganizationID(value *uint64) *WorkExperienceUpdate {
+	if value != nil {
+		return we.SetOrganizationID(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceUpdateOne) SetNotNilOrganizationID(value *uint64) *WorkExperienceUpdateOne {
+	if value != nil {
+		return we.SetOrganizationID(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
+func (we *WorkExperienceCreate) SetNotNilOrganizationID(value *uint64) *WorkExperienceCreate {
+	if value != nil {
+		return we.SetOrganizationID(*value)
+	}
+	return we
+}
+
+// set field if value's pointer is not nil.
 func (w *WxUpdate) SetNotNilUpdatedAt(value *time.Time) *WxUpdate {
 	if value != nil {
 		return w.SetUpdatedAt(*value)

+ 212 - 0
ent/tutorial.go

@@ -0,0 +1,212 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"fmt"
+	"strings"
+	"time"
+	"wechat-api/ent/employee"
+	"wechat-api/ent/tutorial"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+)
+
+// Tutorial is the model entity for the Tutorial schema.
+type Tutorial 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"`
+	// employee_id | 员工ID
+	EmployeeID uint64 `json:"employee_id,omitempty"`
+	// index | 序号
+	Index int `json:"index,omitempty"`
+	// title | 标题
+	Title string `json:"title,omitempty"`
+	// content | 内容
+	Content string `json:"content,omitempty"`
+	// organization_id | 租户ID
+	OrganizationID uint64 `json:"organization_id,omitempty"`
+	// Edges holds the relations/edges for other nodes in the graph.
+	// The values are being populated by the TutorialQuery when eager-loading is set.
+	Edges        TutorialEdges `json:"edges"`
+	selectValues sql.SelectValues
+}
+
+// TutorialEdges holds the relations/edges for other nodes in the graph.
+type TutorialEdges struct {
+	// Employee holds the value of the employee edge.
+	Employee *Employee `json:"employee,omitempty"`
+	// loadedTypes holds the information for reporting if a
+	// type was loaded (or requested) in eager-loading or not.
+	loadedTypes [1]bool
+}
+
+// EmployeeOrErr returns the Employee value or an error if the edge
+// was not loaded in eager-loading, or loaded but was not found.
+func (e TutorialEdges) EmployeeOrErr() (*Employee, error) {
+	if e.Employee != nil {
+		return e.Employee, nil
+	} else if e.loadedTypes[0] {
+		return nil, &NotFoundError{label: employee.Label}
+	}
+	return nil, &NotLoadedError{edge: "employee"}
+}
+
+// scanValues returns the types for scanning values from sql.Rows.
+func (*Tutorial) scanValues(columns []string) ([]any, error) {
+	values := make([]any, len(columns))
+	for i := range columns {
+		switch columns[i] {
+		case tutorial.FieldID, tutorial.FieldEmployeeID, tutorial.FieldIndex, tutorial.FieldOrganizationID:
+			values[i] = new(sql.NullInt64)
+		case tutorial.FieldTitle, tutorial.FieldContent:
+			values[i] = new(sql.NullString)
+		case tutorial.FieldCreatedAt, tutorial.FieldUpdatedAt, tutorial.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 Tutorial fields.
+func (t *Tutorial) 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 tutorial.FieldID:
+			value, ok := values[i].(*sql.NullInt64)
+			if !ok {
+				return fmt.Errorf("unexpected type %T for field id", value)
+			}
+			t.ID = uint64(value.Int64)
+		case tutorial.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 {
+				t.CreatedAt = value.Time
+			}
+		case tutorial.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 {
+				t.UpdatedAt = value.Time
+			}
+		case tutorial.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 {
+				t.DeletedAt = value.Time
+			}
+		case tutorial.FieldEmployeeID:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field employee_id", values[i])
+			} else if value.Valid {
+				t.EmployeeID = uint64(value.Int64)
+			}
+		case tutorial.FieldIndex:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field index", values[i])
+			} else if value.Valid {
+				t.Index = int(value.Int64)
+			}
+		case tutorial.FieldTitle:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field title", values[i])
+			} else if value.Valid {
+				t.Title = value.String
+			}
+		case tutorial.FieldContent:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field content", values[i])
+			} else if value.Valid {
+				t.Content = value.String
+			}
+		case tutorial.FieldOrganizationID:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field organization_id", values[i])
+			} else if value.Valid {
+				t.OrganizationID = uint64(value.Int64)
+			}
+		default:
+			t.selectValues.Set(columns[i], values[i])
+		}
+	}
+	return nil
+}
+
+// Value returns the ent.Value that was dynamically selected and assigned to the Tutorial.
+// This includes values selected through modifiers, order, etc.
+func (t *Tutorial) Value(name string) (ent.Value, error) {
+	return t.selectValues.Get(name)
+}
+
+// QueryEmployee queries the "employee" edge of the Tutorial entity.
+func (t *Tutorial) QueryEmployee() *EmployeeQuery {
+	return NewTutorialClient(t.config).QueryEmployee(t)
+}
+
+// Update returns a builder for updating this Tutorial.
+// Note that you need to call Tutorial.Unwrap() before calling this method if this Tutorial
+// was returned from a transaction, and the transaction was committed or rolled back.
+func (t *Tutorial) Update() *TutorialUpdateOne {
+	return NewTutorialClient(t.config).UpdateOne(t)
+}
+
+// Unwrap unwraps the Tutorial 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 (t *Tutorial) Unwrap() *Tutorial {
+	_tx, ok := t.config.driver.(*txDriver)
+	if !ok {
+		panic("ent: Tutorial is not a transactional entity")
+	}
+	t.config.driver = _tx.drv
+	return t
+}
+
+// String implements the fmt.Stringer.
+func (t *Tutorial) String() string {
+	var builder strings.Builder
+	builder.WriteString("Tutorial(")
+	builder.WriteString(fmt.Sprintf("id=%v, ", t.ID))
+	builder.WriteString("created_at=")
+	builder.WriteString(t.CreatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("updated_at=")
+	builder.WriteString(t.UpdatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("deleted_at=")
+	builder.WriteString(t.DeletedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("employee_id=")
+	builder.WriteString(fmt.Sprintf("%v", t.EmployeeID))
+	builder.WriteString(", ")
+	builder.WriteString("index=")
+	builder.WriteString(fmt.Sprintf("%v", t.Index))
+	builder.WriteString(", ")
+	builder.WriteString("title=")
+	builder.WriteString(t.Title)
+	builder.WriteString(", ")
+	builder.WriteString("content=")
+	builder.WriteString(t.Content)
+	builder.WriteString(", ")
+	builder.WriteString("organization_id=")
+	builder.WriteString(fmt.Sprintf("%v", t.OrganizationID))
+	builder.WriteByte(')')
+	return builder.String()
+}
+
+// Tutorials is a parsable slice of Tutorial.
+type Tutorials []*Tutorial

+ 150 - 0
ent/tutorial/tutorial.go

@@ -0,0 +1,150 @@
+// Code generated by ent, DO NOT EDIT.
+
+package tutorial
+
+import (
+	"time"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+)
+
+const (
+	// Label holds the string label denoting the tutorial type in the database.
+	Label = "tutorial"
+	// 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"
+	// FieldEmployeeID holds the string denoting the employee_id field in the database.
+	FieldEmployeeID = "employee_id"
+	// FieldIndex holds the string denoting the index field in the database.
+	FieldIndex = "index"
+	// FieldTitle holds the string denoting the title field in the database.
+	FieldTitle = "title"
+	// FieldContent holds the string denoting the content field in the database.
+	FieldContent = "content"
+	// FieldOrganizationID holds the string denoting the organization_id field in the database.
+	FieldOrganizationID = "organization_id"
+	// EdgeEmployee holds the string denoting the employee edge name in mutations.
+	EdgeEmployee = "employee"
+	// Table holds the table name of the tutorial in the database.
+	Table = "tutorial"
+	// EmployeeTable is the table that holds the employee relation/edge.
+	EmployeeTable = "tutorial"
+	// EmployeeInverseTable is the table name for the Employee entity.
+	// It exists in this package in order to avoid circular dependency with the "employee" package.
+	EmployeeInverseTable = "employee"
+	// EmployeeColumn is the table column denoting the employee relation/edge.
+	EmployeeColumn = "employee_id"
+)
+
+// Columns holds all SQL columns for tutorial fields.
+var Columns = []string{
+	FieldID,
+	FieldCreatedAt,
+	FieldUpdatedAt,
+	FieldDeletedAt,
+	FieldEmployeeID,
+	FieldIndex,
+	FieldTitle,
+	FieldContent,
+	FieldOrganizationID,
+}
+
+// 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
+	// EmployeeIDValidator is a validator for the "employee_id" field. It is called by the builders before save.
+	EmployeeIDValidator func(uint64) error
+	// OrganizationIDValidator is a validator for the "organization_id" field. It is called by the builders before save.
+	OrganizationIDValidator func(uint64) error
+)
+
+// OrderOption defines the ordering options for the Tutorial 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()
+}
+
+// ByEmployeeID orders the results by the employee_id field.
+func ByEmployeeID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldEmployeeID, opts...).ToFunc()
+}
+
+// ByIndex orders the results by the index field.
+func ByIndex(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldIndex, opts...).ToFunc()
+}
+
+// ByTitle orders the results by the title field.
+func ByTitle(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldTitle, opts...).ToFunc()
+}
+
+// ByContent orders the results by the content field.
+func ByContent(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldContent, opts...).ToFunc()
+}
+
+// ByOrganizationID orders the results by the organization_id field.
+func ByOrganizationID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldOrganizationID, opts...).ToFunc()
+}
+
+// ByEmployeeField orders the results by employee field.
+func ByEmployeeField(field string, opts ...sql.OrderTermOption) OrderOption {
+	return func(s *sql.Selector) {
+		sqlgraph.OrderByNeighborTerms(s, newEmployeeStep(), sql.OrderByField(field, opts...))
+	}
+}
+func newEmployeeStep() *sqlgraph.Step {
+	return sqlgraph.NewStep(
+		sqlgraph.From(Table, FieldID),
+		sqlgraph.To(EmployeeInverseTable, FieldID),
+		sqlgraph.Edge(sqlgraph.M2O, true, EmployeeTable, EmployeeColumn),
+	)
+}

+ 494 - 0
ent/tutorial/where.go

@@ -0,0 +1,494 @@
+// Code generated by ent, DO NOT EDIT.
+
+package tutorial
+
+import (
+	"time"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+)
+
+// ID filters vertices based on their ID field.
+func ID(id uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldEQ(FieldID, id))
+}
+
+// IDEQ applies the EQ predicate on the ID field.
+func IDEQ(id uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldEQ(FieldID, id))
+}
+
+// IDNEQ applies the NEQ predicate on the ID field.
+func IDNEQ(id uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNEQ(FieldID, id))
+}
+
+// IDIn applies the In predicate on the ID field.
+func IDIn(ids ...uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldIn(FieldID, ids...))
+}
+
+// IDNotIn applies the NotIn predicate on the ID field.
+func IDNotIn(ids ...uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNotIn(FieldID, ids...))
+}
+
+// IDGT applies the GT predicate on the ID field.
+func IDGT(id uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldGT(FieldID, id))
+}
+
+// IDGTE applies the GTE predicate on the ID field.
+func IDGTE(id uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldGTE(FieldID, id))
+}
+
+// IDLT applies the LT predicate on the ID field.
+func IDLT(id uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldLT(FieldID, id))
+}
+
+// IDLTE applies the LTE predicate on the ID field.
+func IDLTE(id uint64) predicate.Tutorial {
+	return predicate.Tutorial(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.Tutorial {
+	return predicate.Tutorial(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.Tutorial {
+	return predicate.Tutorial(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.Tutorial {
+	return predicate.Tutorial(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// EmployeeID applies equality check predicate on the "employee_id" field. It's identical to EmployeeIDEQ.
+func EmployeeID(v uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldEQ(FieldEmployeeID, v))
+}
+
+// Index applies equality check predicate on the "index" field. It's identical to IndexEQ.
+func Index(v int) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldEQ(FieldIndex, v))
+}
+
+// Title applies equality check predicate on the "title" field. It's identical to TitleEQ.
+func Title(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldEQ(FieldTitle, v))
+}
+
+// Content applies equality check predicate on the "content" field. It's identical to ContentEQ.
+func Content(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldEQ(FieldContent, v))
+}
+
+// OrganizationID applies equality check predicate on the "organization_id" field. It's identical to OrganizationIDEQ.
+func OrganizationID(v uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldEQ(FieldOrganizationID, v))
+}
+
+// CreatedAtEQ applies the EQ predicate on the "created_at" field.
+func CreatedAtEQ(v time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
+func CreatedAtNEQ(v time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtIn applies the In predicate on the "created_at" field.
+func CreatedAtIn(vs ...time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
+func CreatedAtNotIn(vs ...time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNotIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtGT applies the GT predicate on the "created_at" field.
+func CreatedAtGT(v time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldGT(FieldCreatedAt, v))
+}
+
+// CreatedAtGTE applies the GTE predicate on the "created_at" field.
+func CreatedAtGTE(v time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldGTE(FieldCreatedAt, v))
+}
+
+// CreatedAtLT applies the LT predicate on the "created_at" field.
+func CreatedAtLT(v time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldLT(FieldCreatedAt, v))
+}
+
+// CreatedAtLTE applies the LTE predicate on the "created_at" field.
+func CreatedAtLTE(v time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldLTE(FieldCreatedAt, v))
+}
+
+// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
+func UpdatedAtEQ(v time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
+func UpdatedAtNEQ(v time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtIn applies the In predicate on the "updated_at" field.
+func UpdatedAtIn(vs ...time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
+func UpdatedAtNotIn(vs ...time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNotIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtGT applies the GT predicate on the "updated_at" field.
+func UpdatedAtGT(v time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldGT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
+func UpdatedAtGTE(v time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldGTE(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLT applies the LT predicate on the "updated_at" field.
+func UpdatedAtLT(v time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldLT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
+func UpdatedAtLTE(v time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldLTE(FieldUpdatedAt, v))
+}
+
+// DeletedAtEQ applies the EQ predicate on the "deleted_at" field.
+func DeletedAtEQ(v time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field.
+func DeletedAtNEQ(v time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtIn applies the In predicate on the "deleted_at" field.
+func DeletedAtIn(vs ...time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field.
+func DeletedAtNotIn(vs ...time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNotIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtGT applies the GT predicate on the "deleted_at" field.
+func DeletedAtGT(v time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldGT(FieldDeletedAt, v))
+}
+
+// DeletedAtGTE applies the GTE predicate on the "deleted_at" field.
+func DeletedAtGTE(v time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldGTE(FieldDeletedAt, v))
+}
+
+// DeletedAtLT applies the LT predicate on the "deleted_at" field.
+func DeletedAtLT(v time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldLT(FieldDeletedAt, v))
+}
+
+// DeletedAtLTE applies the LTE predicate on the "deleted_at" field.
+func DeletedAtLTE(v time.Time) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldLTE(FieldDeletedAt, v))
+}
+
+// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field.
+func DeletedAtIsNil() predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldIsNull(FieldDeletedAt))
+}
+
+// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field.
+func DeletedAtNotNil() predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNotNull(FieldDeletedAt))
+}
+
+// EmployeeIDEQ applies the EQ predicate on the "employee_id" field.
+func EmployeeIDEQ(v uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldEQ(FieldEmployeeID, v))
+}
+
+// EmployeeIDNEQ applies the NEQ predicate on the "employee_id" field.
+func EmployeeIDNEQ(v uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNEQ(FieldEmployeeID, v))
+}
+
+// EmployeeIDIn applies the In predicate on the "employee_id" field.
+func EmployeeIDIn(vs ...uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldIn(FieldEmployeeID, vs...))
+}
+
+// EmployeeIDNotIn applies the NotIn predicate on the "employee_id" field.
+func EmployeeIDNotIn(vs ...uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNotIn(FieldEmployeeID, vs...))
+}
+
+// IndexEQ applies the EQ predicate on the "index" field.
+func IndexEQ(v int) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldEQ(FieldIndex, v))
+}
+
+// IndexNEQ applies the NEQ predicate on the "index" field.
+func IndexNEQ(v int) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNEQ(FieldIndex, v))
+}
+
+// IndexIn applies the In predicate on the "index" field.
+func IndexIn(vs ...int) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldIn(FieldIndex, vs...))
+}
+
+// IndexNotIn applies the NotIn predicate on the "index" field.
+func IndexNotIn(vs ...int) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNotIn(FieldIndex, vs...))
+}
+
+// IndexGT applies the GT predicate on the "index" field.
+func IndexGT(v int) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldGT(FieldIndex, v))
+}
+
+// IndexGTE applies the GTE predicate on the "index" field.
+func IndexGTE(v int) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldGTE(FieldIndex, v))
+}
+
+// IndexLT applies the LT predicate on the "index" field.
+func IndexLT(v int) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldLT(FieldIndex, v))
+}
+
+// IndexLTE applies the LTE predicate on the "index" field.
+func IndexLTE(v int) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldLTE(FieldIndex, v))
+}
+
+// TitleEQ applies the EQ predicate on the "title" field.
+func TitleEQ(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldEQ(FieldTitle, v))
+}
+
+// TitleNEQ applies the NEQ predicate on the "title" field.
+func TitleNEQ(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNEQ(FieldTitle, v))
+}
+
+// TitleIn applies the In predicate on the "title" field.
+func TitleIn(vs ...string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldIn(FieldTitle, vs...))
+}
+
+// TitleNotIn applies the NotIn predicate on the "title" field.
+func TitleNotIn(vs ...string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNotIn(FieldTitle, vs...))
+}
+
+// TitleGT applies the GT predicate on the "title" field.
+func TitleGT(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldGT(FieldTitle, v))
+}
+
+// TitleGTE applies the GTE predicate on the "title" field.
+func TitleGTE(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldGTE(FieldTitle, v))
+}
+
+// TitleLT applies the LT predicate on the "title" field.
+func TitleLT(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldLT(FieldTitle, v))
+}
+
+// TitleLTE applies the LTE predicate on the "title" field.
+func TitleLTE(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldLTE(FieldTitle, v))
+}
+
+// TitleContains applies the Contains predicate on the "title" field.
+func TitleContains(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldContains(FieldTitle, v))
+}
+
+// TitleHasPrefix applies the HasPrefix predicate on the "title" field.
+func TitleHasPrefix(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldHasPrefix(FieldTitle, v))
+}
+
+// TitleHasSuffix applies the HasSuffix predicate on the "title" field.
+func TitleHasSuffix(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldHasSuffix(FieldTitle, v))
+}
+
+// TitleEqualFold applies the EqualFold predicate on the "title" field.
+func TitleEqualFold(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldEqualFold(FieldTitle, v))
+}
+
+// TitleContainsFold applies the ContainsFold predicate on the "title" field.
+func TitleContainsFold(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldContainsFold(FieldTitle, v))
+}
+
+// ContentEQ applies the EQ predicate on the "content" field.
+func ContentEQ(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldEQ(FieldContent, v))
+}
+
+// ContentNEQ applies the NEQ predicate on the "content" field.
+func ContentNEQ(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNEQ(FieldContent, v))
+}
+
+// ContentIn applies the In predicate on the "content" field.
+func ContentIn(vs ...string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldIn(FieldContent, vs...))
+}
+
+// ContentNotIn applies the NotIn predicate on the "content" field.
+func ContentNotIn(vs ...string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNotIn(FieldContent, vs...))
+}
+
+// ContentGT applies the GT predicate on the "content" field.
+func ContentGT(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldGT(FieldContent, v))
+}
+
+// ContentGTE applies the GTE predicate on the "content" field.
+func ContentGTE(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldGTE(FieldContent, v))
+}
+
+// ContentLT applies the LT predicate on the "content" field.
+func ContentLT(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldLT(FieldContent, v))
+}
+
+// ContentLTE applies the LTE predicate on the "content" field.
+func ContentLTE(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldLTE(FieldContent, v))
+}
+
+// ContentContains applies the Contains predicate on the "content" field.
+func ContentContains(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldContains(FieldContent, v))
+}
+
+// ContentHasPrefix applies the HasPrefix predicate on the "content" field.
+func ContentHasPrefix(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldHasPrefix(FieldContent, v))
+}
+
+// ContentHasSuffix applies the HasSuffix predicate on the "content" field.
+func ContentHasSuffix(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldHasSuffix(FieldContent, v))
+}
+
+// ContentEqualFold applies the EqualFold predicate on the "content" field.
+func ContentEqualFold(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldEqualFold(FieldContent, v))
+}
+
+// ContentContainsFold applies the ContainsFold predicate on the "content" field.
+func ContentContainsFold(v string) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldContainsFold(FieldContent, v))
+}
+
+// OrganizationIDEQ applies the EQ predicate on the "organization_id" field.
+func OrganizationIDEQ(v uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldEQ(FieldOrganizationID, v))
+}
+
+// OrganizationIDNEQ applies the NEQ predicate on the "organization_id" field.
+func OrganizationIDNEQ(v uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNEQ(FieldOrganizationID, v))
+}
+
+// OrganizationIDIn applies the In predicate on the "organization_id" field.
+func OrganizationIDIn(vs ...uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldIn(FieldOrganizationID, vs...))
+}
+
+// OrganizationIDNotIn applies the NotIn predicate on the "organization_id" field.
+func OrganizationIDNotIn(vs ...uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldNotIn(FieldOrganizationID, vs...))
+}
+
+// OrganizationIDGT applies the GT predicate on the "organization_id" field.
+func OrganizationIDGT(v uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldGT(FieldOrganizationID, v))
+}
+
+// OrganizationIDGTE applies the GTE predicate on the "organization_id" field.
+func OrganizationIDGTE(v uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldGTE(FieldOrganizationID, v))
+}
+
+// OrganizationIDLT applies the LT predicate on the "organization_id" field.
+func OrganizationIDLT(v uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldLT(FieldOrganizationID, v))
+}
+
+// OrganizationIDLTE applies the LTE predicate on the "organization_id" field.
+func OrganizationIDLTE(v uint64) predicate.Tutorial {
+	return predicate.Tutorial(sql.FieldLTE(FieldOrganizationID, v))
+}
+
+// HasEmployee applies the HasEdge predicate on the "employee" edge.
+func HasEmployee() predicate.Tutorial {
+	return predicate.Tutorial(func(s *sql.Selector) {
+		step := sqlgraph.NewStep(
+			sqlgraph.From(Table, FieldID),
+			sqlgraph.Edge(sqlgraph.M2O, true, EmployeeTable, EmployeeColumn),
+		)
+		sqlgraph.HasNeighbors(s, step)
+	})
+}
+
+// HasEmployeeWith applies the HasEdge predicate on the "employee" edge with a given conditions (other predicates).
+func HasEmployeeWith(preds ...predicate.Employee) predicate.Tutorial {
+	return predicate.Tutorial(func(s *sql.Selector) {
+		step := newEmployeeStep()
+		sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+			for _, p := range preds {
+				p(s)
+			}
+		})
+	})
+}
+
+// And groups predicates with the AND operator between them.
+func And(predicates ...predicate.Tutorial) predicate.Tutorial {
+	return predicate.Tutorial(sql.AndPredicates(predicates...))
+}
+
+// Or groups predicates with the OR operator between them.
+func Or(predicates ...predicate.Tutorial) predicate.Tutorial {
+	return predicate.Tutorial(sql.OrPredicates(predicates...))
+}
+
+// Not applies the not operator on the given predicate.
+func Not(p predicate.Tutorial) predicate.Tutorial {
+	return predicate.Tutorial(sql.NotPredicates(p))
+}

+ 958 - 0
ent/tutorial_create.go

@@ -0,0 +1,958 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/employee"
+	"wechat-api/ent/tutorial"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// TutorialCreate is the builder for creating a Tutorial entity.
+type TutorialCreate struct {
+	config
+	mutation *TutorialMutation
+	hooks    []Hook
+	conflict []sql.ConflictOption
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (tc *TutorialCreate) SetCreatedAt(t time.Time) *TutorialCreate {
+	tc.mutation.SetCreatedAt(t)
+	return tc
+}
+
+// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
+func (tc *TutorialCreate) SetNillableCreatedAt(t *time.Time) *TutorialCreate {
+	if t != nil {
+		tc.SetCreatedAt(*t)
+	}
+	return tc
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (tc *TutorialCreate) SetUpdatedAt(t time.Time) *TutorialCreate {
+	tc.mutation.SetUpdatedAt(t)
+	return tc
+}
+
+// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
+func (tc *TutorialCreate) SetNillableUpdatedAt(t *time.Time) *TutorialCreate {
+	if t != nil {
+		tc.SetUpdatedAt(*t)
+	}
+	return tc
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (tc *TutorialCreate) SetDeletedAt(t time.Time) *TutorialCreate {
+	tc.mutation.SetDeletedAt(t)
+	return tc
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (tc *TutorialCreate) SetNillableDeletedAt(t *time.Time) *TutorialCreate {
+	if t != nil {
+		tc.SetDeletedAt(*t)
+	}
+	return tc
+}
+
+// SetEmployeeID sets the "employee_id" field.
+func (tc *TutorialCreate) SetEmployeeID(u uint64) *TutorialCreate {
+	tc.mutation.SetEmployeeID(u)
+	return tc
+}
+
+// SetIndex sets the "index" field.
+func (tc *TutorialCreate) SetIndex(i int) *TutorialCreate {
+	tc.mutation.SetIndex(i)
+	return tc
+}
+
+// SetTitle sets the "title" field.
+func (tc *TutorialCreate) SetTitle(s string) *TutorialCreate {
+	tc.mutation.SetTitle(s)
+	return tc
+}
+
+// SetContent sets the "content" field.
+func (tc *TutorialCreate) SetContent(s string) *TutorialCreate {
+	tc.mutation.SetContent(s)
+	return tc
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (tc *TutorialCreate) SetOrganizationID(u uint64) *TutorialCreate {
+	tc.mutation.SetOrganizationID(u)
+	return tc
+}
+
+// SetID sets the "id" field.
+func (tc *TutorialCreate) SetID(u uint64) *TutorialCreate {
+	tc.mutation.SetID(u)
+	return tc
+}
+
+// SetEmployee sets the "employee" edge to the Employee entity.
+func (tc *TutorialCreate) SetEmployee(e *Employee) *TutorialCreate {
+	return tc.SetEmployeeID(e.ID)
+}
+
+// Mutation returns the TutorialMutation object of the builder.
+func (tc *TutorialCreate) Mutation() *TutorialMutation {
+	return tc.mutation
+}
+
+// Save creates the Tutorial in the database.
+func (tc *TutorialCreate) Save(ctx context.Context) (*Tutorial, error) {
+	if err := tc.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, tc.sqlSave, tc.mutation, tc.hooks)
+}
+
+// SaveX calls Save and panics if Save returns an error.
+func (tc *TutorialCreate) SaveX(ctx context.Context) *Tutorial {
+	v, err := tc.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (tc *TutorialCreate) Exec(ctx context.Context) error {
+	_, err := tc.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (tc *TutorialCreate) ExecX(ctx context.Context) {
+	if err := tc.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (tc *TutorialCreate) defaults() error {
+	if _, ok := tc.mutation.CreatedAt(); !ok {
+		if tutorial.DefaultCreatedAt == nil {
+			return fmt.Errorf("ent: uninitialized tutorial.DefaultCreatedAt (forgotten import ent/runtime?)")
+		}
+		v := tutorial.DefaultCreatedAt()
+		tc.mutation.SetCreatedAt(v)
+	}
+	if _, ok := tc.mutation.UpdatedAt(); !ok {
+		if tutorial.DefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized tutorial.DefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := tutorial.DefaultUpdatedAt()
+		tc.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (tc *TutorialCreate) check() error {
+	if _, ok := tc.mutation.CreatedAt(); !ok {
+		return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "Tutorial.created_at"`)}
+	}
+	if _, ok := tc.mutation.UpdatedAt(); !ok {
+		return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "Tutorial.updated_at"`)}
+	}
+	if _, ok := tc.mutation.EmployeeID(); !ok {
+		return &ValidationError{Name: "employee_id", err: errors.New(`ent: missing required field "Tutorial.employee_id"`)}
+	}
+	if v, ok := tc.mutation.EmployeeID(); ok {
+		if err := tutorial.EmployeeIDValidator(v); err != nil {
+			return &ValidationError{Name: "employee_id", err: fmt.Errorf(`ent: validator failed for field "Tutorial.employee_id": %w`, err)}
+		}
+	}
+	if _, ok := tc.mutation.Index(); !ok {
+		return &ValidationError{Name: "index", err: errors.New(`ent: missing required field "Tutorial.index"`)}
+	}
+	if _, ok := tc.mutation.Title(); !ok {
+		return &ValidationError{Name: "title", err: errors.New(`ent: missing required field "Tutorial.title"`)}
+	}
+	if _, ok := tc.mutation.Content(); !ok {
+		return &ValidationError{Name: "content", err: errors.New(`ent: missing required field "Tutorial.content"`)}
+	}
+	if _, ok := tc.mutation.OrganizationID(); !ok {
+		return &ValidationError{Name: "organization_id", err: errors.New(`ent: missing required field "Tutorial.organization_id"`)}
+	}
+	if v, ok := tc.mutation.OrganizationID(); ok {
+		if err := tutorial.OrganizationIDValidator(v); err != nil {
+			return &ValidationError{Name: "organization_id", err: fmt.Errorf(`ent: validator failed for field "Tutorial.organization_id": %w`, err)}
+		}
+	}
+	if _, ok := tc.mutation.EmployeeID(); !ok {
+		return &ValidationError{Name: "employee", err: errors.New(`ent: missing required edge "Tutorial.employee"`)}
+	}
+	return nil
+}
+
+func (tc *TutorialCreate) sqlSave(ctx context.Context) (*Tutorial, error) {
+	if err := tc.check(); err != nil {
+		return nil, err
+	}
+	_node, _spec := tc.createSpec()
+	if err := sqlgraph.CreateNode(ctx, tc.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)
+	}
+	tc.mutation.id = &_node.ID
+	tc.mutation.done = true
+	return _node, nil
+}
+
+func (tc *TutorialCreate) createSpec() (*Tutorial, *sqlgraph.CreateSpec) {
+	var (
+		_node = &Tutorial{config: tc.config}
+		_spec = sqlgraph.NewCreateSpec(tutorial.Table, sqlgraph.NewFieldSpec(tutorial.FieldID, field.TypeUint64))
+	)
+	_spec.OnConflict = tc.conflict
+	if id, ok := tc.mutation.ID(); ok {
+		_node.ID = id
+		_spec.ID.Value = id
+	}
+	if value, ok := tc.mutation.CreatedAt(); ok {
+		_spec.SetField(tutorial.FieldCreatedAt, field.TypeTime, value)
+		_node.CreatedAt = value
+	}
+	if value, ok := tc.mutation.UpdatedAt(); ok {
+		_spec.SetField(tutorial.FieldUpdatedAt, field.TypeTime, value)
+		_node.UpdatedAt = value
+	}
+	if value, ok := tc.mutation.DeletedAt(); ok {
+		_spec.SetField(tutorial.FieldDeletedAt, field.TypeTime, value)
+		_node.DeletedAt = value
+	}
+	if value, ok := tc.mutation.Index(); ok {
+		_spec.SetField(tutorial.FieldIndex, field.TypeInt, value)
+		_node.Index = value
+	}
+	if value, ok := tc.mutation.Title(); ok {
+		_spec.SetField(tutorial.FieldTitle, field.TypeString, value)
+		_node.Title = value
+	}
+	if value, ok := tc.mutation.Content(); ok {
+		_spec.SetField(tutorial.FieldContent, field.TypeString, value)
+		_node.Content = value
+	}
+	if value, ok := tc.mutation.OrganizationID(); ok {
+		_spec.SetField(tutorial.FieldOrganizationID, field.TypeUint64, value)
+		_node.OrganizationID = value
+	}
+	if nodes := tc.mutation.EmployeeIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   tutorial.EmployeeTable,
+			Columns: []string{tutorial.EmployeeColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(employee.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_node.EmployeeID = nodes[0]
+		_spec.Edges = append(_spec.Edges, edge)
+	}
+	return _node, _spec
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.Tutorial.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.TutorialUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (tc *TutorialCreate) OnConflict(opts ...sql.ConflictOption) *TutorialUpsertOne {
+	tc.conflict = opts
+	return &TutorialUpsertOne{
+		create: tc,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.Tutorial.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (tc *TutorialCreate) OnConflictColumns(columns ...string) *TutorialUpsertOne {
+	tc.conflict = append(tc.conflict, sql.ConflictColumns(columns...))
+	return &TutorialUpsertOne{
+		create: tc,
+	}
+}
+
+type (
+	// TutorialUpsertOne is the builder for "upsert"-ing
+	//  one Tutorial node.
+	TutorialUpsertOne struct {
+		create *TutorialCreate
+	}
+
+	// TutorialUpsert is the "OnConflict" setter.
+	TutorialUpsert struct {
+		*sql.UpdateSet
+	}
+)
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *TutorialUpsert) SetUpdatedAt(v time.Time) *TutorialUpsert {
+	u.Set(tutorial.FieldUpdatedAt, v)
+	return u
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *TutorialUpsert) UpdateUpdatedAt() *TutorialUpsert {
+	u.SetExcluded(tutorial.FieldUpdatedAt)
+	return u
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *TutorialUpsert) SetDeletedAt(v time.Time) *TutorialUpsert {
+	u.Set(tutorial.FieldDeletedAt, v)
+	return u
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *TutorialUpsert) UpdateDeletedAt() *TutorialUpsert {
+	u.SetExcluded(tutorial.FieldDeletedAt)
+	return u
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *TutorialUpsert) ClearDeletedAt() *TutorialUpsert {
+	u.SetNull(tutorial.FieldDeletedAt)
+	return u
+}
+
+// SetEmployeeID sets the "employee_id" field.
+func (u *TutorialUpsert) SetEmployeeID(v uint64) *TutorialUpsert {
+	u.Set(tutorial.FieldEmployeeID, v)
+	return u
+}
+
+// UpdateEmployeeID sets the "employee_id" field to the value that was provided on create.
+func (u *TutorialUpsert) UpdateEmployeeID() *TutorialUpsert {
+	u.SetExcluded(tutorial.FieldEmployeeID)
+	return u
+}
+
+// SetIndex sets the "index" field.
+func (u *TutorialUpsert) SetIndex(v int) *TutorialUpsert {
+	u.Set(tutorial.FieldIndex, v)
+	return u
+}
+
+// UpdateIndex sets the "index" field to the value that was provided on create.
+func (u *TutorialUpsert) UpdateIndex() *TutorialUpsert {
+	u.SetExcluded(tutorial.FieldIndex)
+	return u
+}
+
+// AddIndex adds v to the "index" field.
+func (u *TutorialUpsert) AddIndex(v int) *TutorialUpsert {
+	u.Add(tutorial.FieldIndex, v)
+	return u
+}
+
+// SetTitle sets the "title" field.
+func (u *TutorialUpsert) SetTitle(v string) *TutorialUpsert {
+	u.Set(tutorial.FieldTitle, v)
+	return u
+}
+
+// UpdateTitle sets the "title" field to the value that was provided on create.
+func (u *TutorialUpsert) UpdateTitle() *TutorialUpsert {
+	u.SetExcluded(tutorial.FieldTitle)
+	return u
+}
+
+// SetContent sets the "content" field.
+func (u *TutorialUpsert) SetContent(v string) *TutorialUpsert {
+	u.Set(tutorial.FieldContent, v)
+	return u
+}
+
+// UpdateContent sets the "content" field to the value that was provided on create.
+func (u *TutorialUpsert) UpdateContent() *TutorialUpsert {
+	u.SetExcluded(tutorial.FieldContent)
+	return u
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (u *TutorialUpsert) SetOrganizationID(v uint64) *TutorialUpsert {
+	u.Set(tutorial.FieldOrganizationID, v)
+	return u
+}
+
+// UpdateOrganizationID sets the "organization_id" field to the value that was provided on create.
+func (u *TutorialUpsert) UpdateOrganizationID() *TutorialUpsert {
+	u.SetExcluded(tutorial.FieldOrganizationID)
+	return u
+}
+
+// AddOrganizationID adds v to the "organization_id" field.
+func (u *TutorialUpsert) AddOrganizationID(v uint64) *TutorialUpsert {
+	u.Add(tutorial.FieldOrganizationID, 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.Tutorial.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(tutorial.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *TutorialUpsertOne) UpdateNewValues() *TutorialUpsertOne {
+	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(tutorial.FieldID)
+		}
+		if _, exists := u.create.mutation.CreatedAt(); exists {
+			s.SetIgnore(tutorial.FieldCreatedAt)
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.Tutorial.Create().
+//	    OnConflict(sql.ResolveWithIgnore()).
+//	    Exec(ctx)
+func (u *TutorialUpsertOne) Ignore() *TutorialUpsertOne {
+	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 *TutorialUpsertOne) DoNothing() *TutorialUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the TutorialCreate.OnConflict
+// documentation for more info.
+func (u *TutorialUpsertOne) Update(set func(*TutorialUpsert)) *TutorialUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&TutorialUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *TutorialUpsertOne) SetUpdatedAt(v time.Time) *TutorialUpsertOne {
+	return u.Update(func(s *TutorialUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *TutorialUpsertOne) UpdateUpdatedAt() *TutorialUpsertOne {
+	return u.Update(func(s *TutorialUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *TutorialUpsertOne) SetDeletedAt(v time.Time) *TutorialUpsertOne {
+	return u.Update(func(s *TutorialUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *TutorialUpsertOne) UpdateDeletedAt() *TutorialUpsertOne {
+	return u.Update(func(s *TutorialUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *TutorialUpsertOne) ClearDeletedAt() *TutorialUpsertOne {
+	return u.Update(func(s *TutorialUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetEmployeeID sets the "employee_id" field.
+func (u *TutorialUpsertOne) SetEmployeeID(v uint64) *TutorialUpsertOne {
+	return u.Update(func(s *TutorialUpsert) {
+		s.SetEmployeeID(v)
+	})
+}
+
+// UpdateEmployeeID sets the "employee_id" field to the value that was provided on create.
+func (u *TutorialUpsertOne) UpdateEmployeeID() *TutorialUpsertOne {
+	return u.Update(func(s *TutorialUpsert) {
+		s.UpdateEmployeeID()
+	})
+}
+
+// SetIndex sets the "index" field.
+func (u *TutorialUpsertOne) SetIndex(v int) *TutorialUpsertOne {
+	return u.Update(func(s *TutorialUpsert) {
+		s.SetIndex(v)
+	})
+}
+
+// AddIndex adds v to the "index" field.
+func (u *TutorialUpsertOne) AddIndex(v int) *TutorialUpsertOne {
+	return u.Update(func(s *TutorialUpsert) {
+		s.AddIndex(v)
+	})
+}
+
+// UpdateIndex sets the "index" field to the value that was provided on create.
+func (u *TutorialUpsertOne) UpdateIndex() *TutorialUpsertOne {
+	return u.Update(func(s *TutorialUpsert) {
+		s.UpdateIndex()
+	})
+}
+
+// SetTitle sets the "title" field.
+func (u *TutorialUpsertOne) SetTitle(v string) *TutorialUpsertOne {
+	return u.Update(func(s *TutorialUpsert) {
+		s.SetTitle(v)
+	})
+}
+
+// UpdateTitle sets the "title" field to the value that was provided on create.
+func (u *TutorialUpsertOne) UpdateTitle() *TutorialUpsertOne {
+	return u.Update(func(s *TutorialUpsert) {
+		s.UpdateTitle()
+	})
+}
+
+// SetContent sets the "content" field.
+func (u *TutorialUpsertOne) SetContent(v string) *TutorialUpsertOne {
+	return u.Update(func(s *TutorialUpsert) {
+		s.SetContent(v)
+	})
+}
+
+// UpdateContent sets the "content" field to the value that was provided on create.
+func (u *TutorialUpsertOne) UpdateContent() *TutorialUpsertOne {
+	return u.Update(func(s *TutorialUpsert) {
+		s.UpdateContent()
+	})
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (u *TutorialUpsertOne) SetOrganizationID(v uint64) *TutorialUpsertOne {
+	return u.Update(func(s *TutorialUpsert) {
+		s.SetOrganizationID(v)
+	})
+}
+
+// AddOrganizationID adds v to the "organization_id" field.
+func (u *TutorialUpsertOne) AddOrganizationID(v uint64) *TutorialUpsertOne {
+	return u.Update(func(s *TutorialUpsert) {
+		s.AddOrganizationID(v)
+	})
+}
+
+// UpdateOrganizationID sets the "organization_id" field to the value that was provided on create.
+func (u *TutorialUpsertOne) UpdateOrganizationID() *TutorialUpsertOne {
+	return u.Update(func(s *TutorialUpsert) {
+		s.UpdateOrganizationID()
+	})
+}
+
+// Exec executes the query.
+func (u *TutorialUpsertOne) Exec(ctx context.Context) error {
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for TutorialCreate.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *TutorialUpsertOne) 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 *TutorialUpsertOne) 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 *TutorialUpsertOne) IDX(ctx context.Context) uint64 {
+	id, err := u.ID(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+// TutorialCreateBulk is the builder for creating many Tutorial entities in bulk.
+type TutorialCreateBulk struct {
+	config
+	err      error
+	builders []*TutorialCreate
+	conflict []sql.ConflictOption
+}
+
+// Save creates the Tutorial entities in the database.
+func (tcb *TutorialCreateBulk) Save(ctx context.Context) ([]*Tutorial, error) {
+	if tcb.err != nil {
+		return nil, tcb.err
+	}
+	specs := make([]*sqlgraph.CreateSpec, len(tcb.builders))
+	nodes := make([]*Tutorial, len(tcb.builders))
+	mutators := make([]Mutator, len(tcb.builders))
+	for i := range tcb.builders {
+		func(i int, root context.Context) {
+			builder := tcb.builders[i]
+			builder.defaults()
+			var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
+				mutation, ok := m.(*TutorialMutation)
+				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, tcb.builders[i+1].mutation)
+				} else {
+					spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
+					spec.OnConflict = tcb.conflict
+					// Invoke the actual operation on the latest mutation in the chain.
+					if err = sqlgraph.BatchCreate(ctx, tcb.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, tcb.builders[0].mutation); err != nil {
+			return nil, err
+		}
+	}
+	return nodes, nil
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (tcb *TutorialCreateBulk) SaveX(ctx context.Context) []*Tutorial {
+	v, err := tcb.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (tcb *TutorialCreateBulk) Exec(ctx context.Context) error {
+	_, err := tcb.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (tcb *TutorialCreateBulk) ExecX(ctx context.Context) {
+	if err := tcb.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.Tutorial.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.TutorialUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (tcb *TutorialCreateBulk) OnConflict(opts ...sql.ConflictOption) *TutorialUpsertBulk {
+	tcb.conflict = opts
+	return &TutorialUpsertBulk{
+		create: tcb,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.Tutorial.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (tcb *TutorialCreateBulk) OnConflictColumns(columns ...string) *TutorialUpsertBulk {
+	tcb.conflict = append(tcb.conflict, sql.ConflictColumns(columns...))
+	return &TutorialUpsertBulk{
+		create: tcb,
+	}
+}
+
+// TutorialUpsertBulk is the builder for "upsert"-ing
+// a bulk of Tutorial nodes.
+type TutorialUpsertBulk struct {
+	create *TutorialCreateBulk
+}
+
+// UpdateNewValues updates the mutable fields using the new values that
+// were set on create. Using this option is equivalent to using:
+//
+//	client.Tutorial.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(tutorial.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *TutorialUpsertBulk) UpdateNewValues() *TutorialUpsertBulk {
+	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(tutorial.FieldID)
+			}
+			if _, exists := b.mutation.CreatedAt(); exists {
+				s.SetIgnore(tutorial.FieldCreatedAt)
+			}
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.Tutorial.Create().
+//		OnConflict(sql.ResolveWithIgnore()).
+//		Exec(ctx)
+func (u *TutorialUpsertBulk) Ignore() *TutorialUpsertBulk {
+	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 *TutorialUpsertBulk) DoNothing() *TutorialUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the TutorialCreateBulk.OnConflict
+// documentation for more info.
+func (u *TutorialUpsertBulk) Update(set func(*TutorialUpsert)) *TutorialUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&TutorialUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *TutorialUpsertBulk) SetUpdatedAt(v time.Time) *TutorialUpsertBulk {
+	return u.Update(func(s *TutorialUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *TutorialUpsertBulk) UpdateUpdatedAt() *TutorialUpsertBulk {
+	return u.Update(func(s *TutorialUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *TutorialUpsertBulk) SetDeletedAt(v time.Time) *TutorialUpsertBulk {
+	return u.Update(func(s *TutorialUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *TutorialUpsertBulk) UpdateDeletedAt() *TutorialUpsertBulk {
+	return u.Update(func(s *TutorialUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *TutorialUpsertBulk) ClearDeletedAt() *TutorialUpsertBulk {
+	return u.Update(func(s *TutorialUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetEmployeeID sets the "employee_id" field.
+func (u *TutorialUpsertBulk) SetEmployeeID(v uint64) *TutorialUpsertBulk {
+	return u.Update(func(s *TutorialUpsert) {
+		s.SetEmployeeID(v)
+	})
+}
+
+// UpdateEmployeeID sets the "employee_id" field to the value that was provided on create.
+func (u *TutorialUpsertBulk) UpdateEmployeeID() *TutorialUpsertBulk {
+	return u.Update(func(s *TutorialUpsert) {
+		s.UpdateEmployeeID()
+	})
+}
+
+// SetIndex sets the "index" field.
+func (u *TutorialUpsertBulk) SetIndex(v int) *TutorialUpsertBulk {
+	return u.Update(func(s *TutorialUpsert) {
+		s.SetIndex(v)
+	})
+}
+
+// AddIndex adds v to the "index" field.
+func (u *TutorialUpsertBulk) AddIndex(v int) *TutorialUpsertBulk {
+	return u.Update(func(s *TutorialUpsert) {
+		s.AddIndex(v)
+	})
+}
+
+// UpdateIndex sets the "index" field to the value that was provided on create.
+func (u *TutorialUpsertBulk) UpdateIndex() *TutorialUpsertBulk {
+	return u.Update(func(s *TutorialUpsert) {
+		s.UpdateIndex()
+	})
+}
+
+// SetTitle sets the "title" field.
+func (u *TutorialUpsertBulk) SetTitle(v string) *TutorialUpsertBulk {
+	return u.Update(func(s *TutorialUpsert) {
+		s.SetTitle(v)
+	})
+}
+
+// UpdateTitle sets the "title" field to the value that was provided on create.
+func (u *TutorialUpsertBulk) UpdateTitle() *TutorialUpsertBulk {
+	return u.Update(func(s *TutorialUpsert) {
+		s.UpdateTitle()
+	})
+}
+
+// SetContent sets the "content" field.
+func (u *TutorialUpsertBulk) SetContent(v string) *TutorialUpsertBulk {
+	return u.Update(func(s *TutorialUpsert) {
+		s.SetContent(v)
+	})
+}
+
+// UpdateContent sets the "content" field to the value that was provided on create.
+func (u *TutorialUpsertBulk) UpdateContent() *TutorialUpsertBulk {
+	return u.Update(func(s *TutorialUpsert) {
+		s.UpdateContent()
+	})
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (u *TutorialUpsertBulk) SetOrganizationID(v uint64) *TutorialUpsertBulk {
+	return u.Update(func(s *TutorialUpsert) {
+		s.SetOrganizationID(v)
+	})
+}
+
+// AddOrganizationID adds v to the "organization_id" field.
+func (u *TutorialUpsertBulk) AddOrganizationID(v uint64) *TutorialUpsertBulk {
+	return u.Update(func(s *TutorialUpsert) {
+		s.AddOrganizationID(v)
+	})
+}
+
+// UpdateOrganizationID sets the "organization_id" field to the value that was provided on create.
+func (u *TutorialUpsertBulk) UpdateOrganizationID() *TutorialUpsertBulk {
+	return u.Update(func(s *TutorialUpsert) {
+		s.UpdateOrganizationID()
+	})
+}
+
+// Exec executes the query.
+func (u *TutorialUpsertBulk) 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 TutorialCreateBulk instead", i)
+		}
+	}
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for TutorialCreateBulk.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *TutorialUpsertBulk) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}

+ 88 - 0
ent/tutorial_delete.go

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

+ 605 - 0
ent/tutorial_query.go

@@ -0,0 +1,605 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"fmt"
+	"math"
+	"wechat-api/ent/employee"
+	"wechat-api/ent/predicate"
+	"wechat-api/ent/tutorial"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// TutorialQuery is the builder for querying Tutorial entities.
+type TutorialQuery struct {
+	config
+	ctx          *QueryContext
+	order        []tutorial.OrderOption
+	inters       []Interceptor
+	predicates   []predicate.Tutorial
+	withEmployee *EmployeeQuery
+	// intermediate query (i.e. traversal path).
+	sql  *sql.Selector
+	path func(context.Context) (*sql.Selector, error)
+}
+
+// Where adds a new predicate for the TutorialQuery builder.
+func (tq *TutorialQuery) Where(ps ...predicate.Tutorial) *TutorialQuery {
+	tq.predicates = append(tq.predicates, ps...)
+	return tq
+}
+
+// Limit the number of records to be returned by this query.
+func (tq *TutorialQuery) Limit(limit int) *TutorialQuery {
+	tq.ctx.Limit = &limit
+	return tq
+}
+
+// Offset to start from.
+func (tq *TutorialQuery) Offset(offset int) *TutorialQuery {
+	tq.ctx.Offset = &offset
+	return tq
+}
+
+// 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 (tq *TutorialQuery) Unique(unique bool) *TutorialQuery {
+	tq.ctx.Unique = &unique
+	return tq
+}
+
+// Order specifies how the records should be ordered.
+func (tq *TutorialQuery) Order(o ...tutorial.OrderOption) *TutorialQuery {
+	tq.order = append(tq.order, o...)
+	return tq
+}
+
+// QueryEmployee chains the current query on the "employee" edge.
+func (tq *TutorialQuery) QueryEmployee() *EmployeeQuery {
+	query := (&EmployeeClient{config: tq.config}).Query()
+	query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+		if err := tq.prepareQuery(ctx); err != nil {
+			return nil, err
+		}
+		selector := tq.sqlQuery(ctx)
+		if err := selector.Err(); err != nil {
+			return nil, err
+		}
+		step := sqlgraph.NewStep(
+			sqlgraph.From(tutorial.Table, tutorial.FieldID, selector),
+			sqlgraph.To(employee.Table, employee.FieldID),
+			sqlgraph.Edge(sqlgraph.M2O, true, tutorial.EmployeeTable, tutorial.EmployeeColumn),
+		)
+		fromU = sqlgraph.SetNeighbors(tq.driver.Dialect(), step)
+		return fromU, nil
+	}
+	return query
+}
+
+// First returns the first Tutorial entity from the query.
+// Returns a *NotFoundError when no Tutorial was found.
+func (tq *TutorialQuery) First(ctx context.Context) (*Tutorial, error) {
+	nodes, err := tq.Limit(1).All(setContextOp(ctx, tq.ctx, "First"))
+	if err != nil {
+		return nil, err
+	}
+	if len(nodes) == 0 {
+		return nil, &NotFoundError{tutorial.Label}
+	}
+	return nodes[0], nil
+}
+
+// FirstX is like First, but panics if an error occurs.
+func (tq *TutorialQuery) FirstX(ctx context.Context) *Tutorial {
+	node, err := tq.First(ctx)
+	if err != nil && !IsNotFound(err) {
+		panic(err)
+	}
+	return node
+}
+
+// FirstID returns the first Tutorial ID from the query.
+// Returns a *NotFoundError when no Tutorial ID was found.
+func (tq *TutorialQuery) FirstID(ctx context.Context) (id uint64, err error) {
+	var ids []uint64
+	if ids, err = tq.Limit(1).IDs(setContextOp(ctx, tq.ctx, "FirstID")); err != nil {
+		return
+	}
+	if len(ids) == 0 {
+		err = &NotFoundError{tutorial.Label}
+		return
+	}
+	return ids[0], nil
+}
+
+// FirstIDX is like FirstID, but panics if an error occurs.
+func (tq *TutorialQuery) FirstIDX(ctx context.Context) uint64 {
+	id, err := tq.FirstID(ctx)
+	if err != nil && !IsNotFound(err) {
+		panic(err)
+	}
+	return id
+}
+
+// Only returns a single Tutorial entity found by the query, ensuring it only returns one.
+// Returns a *NotSingularError when more than one Tutorial entity is found.
+// Returns a *NotFoundError when no Tutorial entities are found.
+func (tq *TutorialQuery) Only(ctx context.Context) (*Tutorial, error) {
+	nodes, err := tq.Limit(2).All(setContextOp(ctx, tq.ctx, "Only"))
+	if err != nil {
+		return nil, err
+	}
+	switch len(nodes) {
+	case 1:
+		return nodes[0], nil
+	case 0:
+		return nil, &NotFoundError{tutorial.Label}
+	default:
+		return nil, &NotSingularError{tutorial.Label}
+	}
+}
+
+// OnlyX is like Only, but panics if an error occurs.
+func (tq *TutorialQuery) OnlyX(ctx context.Context) *Tutorial {
+	node, err := tq.Only(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return node
+}
+
+// OnlyID is like Only, but returns the only Tutorial ID in the query.
+// Returns a *NotSingularError when more than one Tutorial ID is found.
+// Returns a *NotFoundError when no entities are found.
+func (tq *TutorialQuery) OnlyID(ctx context.Context) (id uint64, err error) {
+	var ids []uint64
+	if ids, err = tq.Limit(2).IDs(setContextOp(ctx, tq.ctx, "OnlyID")); err != nil {
+		return
+	}
+	switch len(ids) {
+	case 1:
+		id = ids[0]
+	case 0:
+		err = &NotFoundError{tutorial.Label}
+	default:
+		err = &NotSingularError{tutorial.Label}
+	}
+	return
+}
+
+// OnlyIDX is like OnlyID, but panics if an error occurs.
+func (tq *TutorialQuery) OnlyIDX(ctx context.Context) uint64 {
+	id, err := tq.OnlyID(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+// All executes the query and returns a list of Tutorials.
+func (tq *TutorialQuery) All(ctx context.Context) ([]*Tutorial, error) {
+	ctx = setContextOp(ctx, tq.ctx, "All")
+	if err := tq.prepareQuery(ctx); err != nil {
+		return nil, err
+	}
+	qr := querierAll[[]*Tutorial, *TutorialQuery]()
+	return withInterceptors[[]*Tutorial](ctx, tq, qr, tq.inters)
+}
+
+// AllX is like All, but panics if an error occurs.
+func (tq *TutorialQuery) AllX(ctx context.Context) []*Tutorial {
+	nodes, err := tq.All(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return nodes
+}
+
+// IDs executes the query and returns a list of Tutorial IDs.
+func (tq *TutorialQuery) IDs(ctx context.Context) (ids []uint64, err error) {
+	if tq.ctx.Unique == nil && tq.path != nil {
+		tq.Unique(true)
+	}
+	ctx = setContextOp(ctx, tq.ctx, "IDs")
+	if err = tq.Select(tutorial.FieldID).Scan(ctx, &ids); err != nil {
+		return nil, err
+	}
+	return ids, nil
+}
+
+// IDsX is like IDs, but panics if an error occurs.
+func (tq *TutorialQuery) IDsX(ctx context.Context) []uint64 {
+	ids, err := tq.IDs(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return ids
+}
+
+// Count returns the count of the given query.
+func (tq *TutorialQuery) Count(ctx context.Context) (int, error) {
+	ctx = setContextOp(ctx, tq.ctx, "Count")
+	if err := tq.prepareQuery(ctx); err != nil {
+		return 0, err
+	}
+	return withInterceptors[int](ctx, tq, querierCount[*TutorialQuery](), tq.inters)
+}
+
+// CountX is like Count, but panics if an error occurs.
+func (tq *TutorialQuery) CountX(ctx context.Context) int {
+	count, err := tq.Count(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return count
+}
+
+// Exist returns true if the query has elements in the graph.
+func (tq *TutorialQuery) Exist(ctx context.Context) (bool, error) {
+	ctx = setContextOp(ctx, tq.ctx, "Exist")
+	switch _, err := tq.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 (tq *TutorialQuery) ExistX(ctx context.Context) bool {
+	exist, err := tq.Exist(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return exist
+}
+
+// Clone returns a duplicate of the TutorialQuery builder, including all associated steps. It can be
+// used to prepare common query builders and use them differently after the clone is made.
+func (tq *TutorialQuery) Clone() *TutorialQuery {
+	if tq == nil {
+		return nil
+	}
+	return &TutorialQuery{
+		config:       tq.config,
+		ctx:          tq.ctx.Clone(),
+		order:        append([]tutorial.OrderOption{}, tq.order...),
+		inters:       append([]Interceptor{}, tq.inters...),
+		predicates:   append([]predicate.Tutorial{}, tq.predicates...),
+		withEmployee: tq.withEmployee.Clone(),
+		// clone intermediate query.
+		sql:  tq.sql.Clone(),
+		path: tq.path,
+	}
+}
+
+// WithEmployee tells the query-builder to eager-load the nodes that are connected to
+// the "employee" edge. The optional arguments are used to configure the query builder of the edge.
+func (tq *TutorialQuery) WithEmployee(opts ...func(*EmployeeQuery)) *TutorialQuery {
+	query := (&EmployeeClient{config: tq.config}).Query()
+	for _, opt := range opts {
+		opt(query)
+	}
+	tq.withEmployee = query
+	return tq
+}
+
+// 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.Tutorial.Query().
+//		GroupBy(tutorial.FieldCreatedAt).
+//		Aggregate(ent.Count()).
+//		Scan(ctx, &v)
+func (tq *TutorialQuery) GroupBy(field string, fields ...string) *TutorialGroupBy {
+	tq.ctx.Fields = append([]string{field}, fields...)
+	grbuild := &TutorialGroupBy{build: tq}
+	grbuild.flds = &tq.ctx.Fields
+	grbuild.label = tutorial.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.Tutorial.Query().
+//		Select(tutorial.FieldCreatedAt).
+//		Scan(ctx, &v)
+func (tq *TutorialQuery) Select(fields ...string) *TutorialSelect {
+	tq.ctx.Fields = append(tq.ctx.Fields, fields...)
+	sbuild := &TutorialSelect{TutorialQuery: tq}
+	sbuild.label = tutorial.Label
+	sbuild.flds, sbuild.scan = &tq.ctx.Fields, sbuild.Scan
+	return sbuild
+}
+
+// Aggregate returns a TutorialSelect configured with the given aggregations.
+func (tq *TutorialQuery) Aggregate(fns ...AggregateFunc) *TutorialSelect {
+	return tq.Select().Aggregate(fns...)
+}
+
+func (tq *TutorialQuery) prepareQuery(ctx context.Context) error {
+	for _, inter := range tq.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, tq); err != nil {
+				return err
+			}
+		}
+	}
+	for _, f := range tq.ctx.Fields {
+		if !tutorial.ValidColumn(f) {
+			return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+		}
+	}
+	if tq.path != nil {
+		prev, err := tq.path(ctx)
+		if err != nil {
+			return err
+		}
+		tq.sql = prev
+	}
+	return nil
+}
+
+func (tq *TutorialQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Tutorial, error) {
+	var (
+		nodes       = []*Tutorial{}
+		_spec       = tq.querySpec()
+		loadedTypes = [1]bool{
+			tq.withEmployee != nil,
+		}
+	)
+	_spec.ScanValues = func(columns []string) ([]any, error) {
+		return (*Tutorial).scanValues(nil, columns)
+	}
+	_spec.Assign = func(columns []string, values []any) error {
+		node := &Tutorial{config: tq.config}
+		nodes = append(nodes, node)
+		node.Edges.loadedTypes = loadedTypes
+		return node.assignValues(columns, values)
+	}
+	for i := range hooks {
+		hooks[i](ctx, _spec)
+	}
+	if err := sqlgraph.QueryNodes(ctx, tq.driver, _spec); err != nil {
+		return nil, err
+	}
+	if len(nodes) == 0 {
+		return nodes, nil
+	}
+	if query := tq.withEmployee; query != nil {
+		if err := tq.loadEmployee(ctx, query, nodes, nil,
+			func(n *Tutorial, e *Employee) { n.Edges.Employee = e }); err != nil {
+			return nil, err
+		}
+	}
+	return nodes, nil
+}
+
+func (tq *TutorialQuery) loadEmployee(ctx context.Context, query *EmployeeQuery, nodes []*Tutorial, init func(*Tutorial), assign func(*Tutorial, *Employee)) error {
+	ids := make([]uint64, 0, len(nodes))
+	nodeids := make(map[uint64][]*Tutorial)
+	for i := range nodes {
+		fk := nodes[i].EmployeeID
+		if _, ok := nodeids[fk]; !ok {
+			ids = append(ids, fk)
+		}
+		nodeids[fk] = append(nodeids[fk], nodes[i])
+	}
+	if len(ids) == 0 {
+		return nil
+	}
+	query.Where(employee.IDIn(ids...))
+	neighbors, err := query.All(ctx)
+	if err != nil {
+		return err
+	}
+	for _, n := range neighbors {
+		nodes, ok := nodeids[n.ID]
+		if !ok {
+			return fmt.Errorf(`unexpected foreign-key "employee_id" returned %v`, n.ID)
+		}
+		for i := range nodes {
+			assign(nodes[i], n)
+		}
+	}
+	return nil
+}
+
+func (tq *TutorialQuery) sqlCount(ctx context.Context) (int, error) {
+	_spec := tq.querySpec()
+	_spec.Node.Columns = tq.ctx.Fields
+	if len(tq.ctx.Fields) > 0 {
+		_spec.Unique = tq.ctx.Unique != nil && *tq.ctx.Unique
+	}
+	return sqlgraph.CountNodes(ctx, tq.driver, _spec)
+}
+
+func (tq *TutorialQuery) querySpec() *sqlgraph.QuerySpec {
+	_spec := sqlgraph.NewQuerySpec(tutorial.Table, tutorial.Columns, sqlgraph.NewFieldSpec(tutorial.FieldID, field.TypeUint64))
+	_spec.From = tq.sql
+	if unique := tq.ctx.Unique; unique != nil {
+		_spec.Unique = *unique
+	} else if tq.path != nil {
+		_spec.Unique = true
+	}
+	if fields := tq.ctx.Fields; len(fields) > 0 {
+		_spec.Node.Columns = make([]string, 0, len(fields))
+		_spec.Node.Columns = append(_spec.Node.Columns, tutorial.FieldID)
+		for i := range fields {
+			if fields[i] != tutorial.FieldID {
+				_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
+			}
+		}
+		if tq.withEmployee != nil {
+			_spec.Node.AddColumnOnce(tutorial.FieldEmployeeID)
+		}
+	}
+	if ps := tq.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if limit := tq.ctx.Limit; limit != nil {
+		_spec.Limit = *limit
+	}
+	if offset := tq.ctx.Offset; offset != nil {
+		_spec.Offset = *offset
+	}
+	if ps := tq.order; len(ps) > 0 {
+		_spec.Order = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	return _spec
+}
+
+func (tq *TutorialQuery) sqlQuery(ctx context.Context) *sql.Selector {
+	builder := sql.Dialect(tq.driver.Dialect())
+	t1 := builder.Table(tutorial.Table)
+	columns := tq.ctx.Fields
+	if len(columns) == 0 {
+		columns = tutorial.Columns
+	}
+	selector := builder.Select(t1.Columns(columns...)...).From(t1)
+	if tq.sql != nil {
+		selector = tq.sql
+		selector.Select(selector.Columns(columns...)...)
+	}
+	if tq.ctx.Unique != nil && *tq.ctx.Unique {
+		selector.Distinct()
+	}
+	for _, p := range tq.predicates {
+		p(selector)
+	}
+	for _, p := range tq.order {
+		p(selector)
+	}
+	if offset := tq.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 := tq.ctx.Limit; limit != nil {
+		selector.Limit(*limit)
+	}
+	return selector
+}
+
+// TutorialGroupBy is the group-by builder for Tutorial entities.
+type TutorialGroupBy struct {
+	selector
+	build *TutorialQuery
+}
+
+// Aggregate adds the given aggregation functions to the group-by query.
+func (tgb *TutorialGroupBy) Aggregate(fns ...AggregateFunc) *TutorialGroupBy {
+	tgb.fns = append(tgb.fns, fns...)
+	return tgb
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (tgb *TutorialGroupBy) Scan(ctx context.Context, v any) error {
+	ctx = setContextOp(ctx, tgb.build.ctx, "GroupBy")
+	if err := tgb.build.prepareQuery(ctx); err != nil {
+		return err
+	}
+	return scanWithInterceptors[*TutorialQuery, *TutorialGroupBy](ctx, tgb.build, tgb, tgb.build.inters, v)
+}
+
+func (tgb *TutorialGroupBy) sqlScan(ctx context.Context, root *TutorialQuery, v any) error {
+	selector := root.sqlQuery(ctx).Select()
+	aggregation := make([]string, 0, len(tgb.fns))
+	for _, fn := range tgb.fns {
+		aggregation = append(aggregation, fn(selector))
+	}
+	if len(selector.SelectedColumns()) == 0 {
+		columns := make([]string, 0, len(*tgb.flds)+len(tgb.fns))
+		for _, f := range *tgb.flds {
+			columns = append(columns, selector.C(f))
+		}
+		columns = append(columns, aggregation...)
+		selector.Select(columns...)
+	}
+	selector.GroupBy(selector.Columns(*tgb.flds...)...)
+	if err := selector.Err(); err != nil {
+		return err
+	}
+	rows := &sql.Rows{}
+	query, args := selector.Query()
+	if err := tgb.build.driver.Query(ctx, query, args, rows); err != nil {
+		return err
+	}
+	defer rows.Close()
+	return sql.ScanSlice(rows, v)
+}
+
+// TutorialSelect is the builder for selecting fields of Tutorial entities.
+type TutorialSelect struct {
+	*TutorialQuery
+	selector
+}
+
+// Aggregate adds the given aggregation functions to the selector query.
+func (ts *TutorialSelect) Aggregate(fns ...AggregateFunc) *TutorialSelect {
+	ts.fns = append(ts.fns, fns...)
+	return ts
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (ts *TutorialSelect) Scan(ctx context.Context, v any) error {
+	ctx = setContextOp(ctx, ts.ctx, "Select")
+	if err := ts.prepareQuery(ctx); err != nil {
+		return err
+	}
+	return scanWithInterceptors[*TutorialQuery, *TutorialSelect](ctx, ts.TutorialQuery, ts, ts.inters, v)
+}
+
+func (ts *TutorialSelect) sqlScan(ctx context.Context, root *TutorialQuery, v any) error {
+	selector := root.sqlQuery(ctx)
+	aggregation := make([]string, 0, len(ts.fns))
+	for _, fn := range ts.fns {
+		aggregation = append(aggregation, fn(selector))
+	}
+	switch n := len(*ts.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 := ts.driver.Query(ctx, query, args, rows); err != nil {
+		return err
+	}
+	defer rows.Close()
+	return sql.ScanSlice(rows, v)
+}

+ 603 - 0
ent/tutorial_update.go

@@ -0,0 +1,603 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/employee"
+	"wechat-api/ent/predicate"
+	"wechat-api/ent/tutorial"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// TutorialUpdate is the builder for updating Tutorial entities.
+type TutorialUpdate struct {
+	config
+	hooks    []Hook
+	mutation *TutorialMutation
+}
+
+// Where appends a list predicates to the TutorialUpdate builder.
+func (tu *TutorialUpdate) Where(ps ...predicate.Tutorial) *TutorialUpdate {
+	tu.mutation.Where(ps...)
+	return tu
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (tu *TutorialUpdate) SetUpdatedAt(t time.Time) *TutorialUpdate {
+	tu.mutation.SetUpdatedAt(t)
+	return tu
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (tu *TutorialUpdate) SetDeletedAt(t time.Time) *TutorialUpdate {
+	tu.mutation.SetDeletedAt(t)
+	return tu
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (tu *TutorialUpdate) SetNillableDeletedAt(t *time.Time) *TutorialUpdate {
+	if t != nil {
+		tu.SetDeletedAt(*t)
+	}
+	return tu
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (tu *TutorialUpdate) ClearDeletedAt() *TutorialUpdate {
+	tu.mutation.ClearDeletedAt()
+	return tu
+}
+
+// SetEmployeeID sets the "employee_id" field.
+func (tu *TutorialUpdate) SetEmployeeID(u uint64) *TutorialUpdate {
+	tu.mutation.SetEmployeeID(u)
+	return tu
+}
+
+// SetNillableEmployeeID sets the "employee_id" field if the given value is not nil.
+func (tu *TutorialUpdate) SetNillableEmployeeID(u *uint64) *TutorialUpdate {
+	if u != nil {
+		tu.SetEmployeeID(*u)
+	}
+	return tu
+}
+
+// SetIndex sets the "index" field.
+func (tu *TutorialUpdate) SetIndex(i int) *TutorialUpdate {
+	tu.mutation.ResetIndex()
+	tu.mutation.SetIndex(i)
+	return tu
+}
+
+// SetNillableIndex sets the "index" field if the given value is not nil.
+func (tu *TutorialUpdate) SetNillableIndex(i *int) *TutorialUpdate {
+	if i != nil {
+		tu.SetIndex(*i)
+	}
+	return tu
+}
+
+// AddIndex adds i to the "index" field.
+func (tu *TutorialUpdate) AddIndex(i int) *TutorialUpdate {
+	tu.mutation.AddIndex(i)
+	return tu
+}
+
+// SetTitle sets the "title" field.
+func (tu *TutorialUpdate) SetTitle(s string) *TutorialUpdate {
+	tu.mutation.SetTitle(s)
+	return tu
+}
+
+// SetNillableTitle sets the "title" field if the given value is not nil.
+func (tu *TutorialUpdate) SetNillableTitle(s *string) *TutorialUpdate {
+	if s != nil {
+		tu.SetTitle(*s)
+	}
+	return tu
+}
+
+// SetContent sets the "content" field.
+func (tu *TutorialUpdate) SetContent(s string) *TutorialUpdate {
+	tu.mutation.SetContent(s)
+	return tu
+}
+
+// SetNillableContent sets the "content" field if the given value is not nil.
+func (tu *TutorialUpdate) SetNillableContent(s *string) *TutorialUpdate {
+	if s != nil {
+		tu.SetContent(*s)
+	}
+	return tu
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (tu *TutorialUpdate) SetOrganizationID(u uint64) *TutorialUpdate {
+	tu.mutation.ResetOrganizationID()
+	tu.mutation.SetOrganizationID(u)
+	return tu
+}
+
+// SetNillableOrganizationID sets the "organization_id" field if the given value is not nil.
+func (tu *TutorialUpdate) SetNillableOrganizationID(u *uint64) *TutorialUpdate {
+	if u != nil {
+		tu.SetOrganizationID(*u)
+	}
+	return tu
+}
+
+// AddOrganizationID adds u to the "organization_id" field.
+func (tu *TutorialUpdate) AddOrganizationID(u int64) *TutorialUpdate {
+	tu.mutation.AddOrganizationID(u)
+	return tu
+}
+
+// SetEmployee sets the "employee" edge to the Employee entity.
+func (tu *TutorialUpdate) SetEmployee(e *Employee) *TutorialUpdate {
+	return tu.SetEmployeeID(e.ID)
+}
+
+// Mutation returns the TutorialMutation object of the builder.
+func (tu *TutorialUpdate) Mutation() *TutorialMutation {
+	return tu.mutation
+}
+
+// ClearEmployee clears the "employee" edge to the Employee entity.
+func (tu *TutorialUpdate) ClearEmployee() *TutorialUpdate {
+	tu.mutation.ClearEmployee()
+	return tu
+}
+
+// Save executes the query and returns the number of nodes affected by the update operation.
+func (tu *TutorialUpdate) Save(ctx context.Context) (int, error) {
+	if err := tu.defaults(); err != nil {
+		return 0, err
+	}
+	return withHooks(ctx, tu.sqlSave, tu.mutation, tu.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (tu *TutorialUpdate) SaveX(ctx context.Context) int {
+	affected, err := tu.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return affected
+}
+
+// Exec executes the query.
+func (tu *TutorialUpdate) Exec(ctx context.Context) error {
+	_, err := tu.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (tu *TutorialUpdate) ExecX(ctx context.Context) {
+	if err := tu.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (tu *TutorialUpdate) defaults() error {
+	if _, ok := tu.mutation.UpdatedAt(); !ok {
+		if tutorial.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized tutorial.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := tutorial.UpdateDefaultUpdatedAt()
+		tu.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (tu *TutorialUpdate) check() error {
+	if v, ok := tu.mutation.EmployeeID(); ok {
+		if err := tutorial.EmployeeIDValidator(v); err != nil {
+			return &ValidationError{Name: "employee_id", err: fmt.Errorf(`ent: validator failed for field "Tutorial.employee_id": %w`, err)}
+		}
+	}
+	if v, ok := tu.mutation.OrganizationID(); ok {
+		if err := tutorial.OrganizationIDValidator(v); err != nil {
+			return &ValidationError{Name: "organization_id", err: fmt.Errorf(`ent: validator failed for field "Tutorial.organization_id": %w`, err)}
+		}
+	}
+	if _, ok := tu.mutation.EmployeeID(); tu.mutation.EmployeeCleared() && !ok {
+		return errors.New(`ent: clearing a required unique edge "Tutorial.employee"`)
+	}
+	return nil
+}
+
+func (tu *TutorialUpdate) sqlSave(ctx context.Context) (n int, err error) {
+	if err := tu.check(); err != nil {
+		return n, err
+	}
+	_spec := sqlgraph.NewUpdateSpec(tutorial.Table, tutorial.Columns, sqlgraph.NewFieldSpec(tutorial.FieldID, field.TypeUint64))
+	if ps := tu.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := tu.mutation.UpdatedAt(); ok {
+		_spec.SetField(tutorial.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := tu.mutation.DeletedAt(); ok {
+		_spec.SetField(tutorial.FieldDeletedAt, field.TypeTime, value)
+	}
+	if tu.mutation.DeletedAtCleared() {
+		_spec.ClearField(tutorial.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := tu.mutation.Index(); ok {
+		_spec.SetField(tutorial.FieldIndex, field.TypeInt, value)
+	}
+	if value, ok := tu.mutation.AddedIndex(); ok {
+		_spec.AddField(tutorial.FieldIndex, field.TypeInt, value)
+	}
+	if value, ok := tu.mutation.Title(); ok {
+		_spec.SetField(tutorial.FieldTitle, field.TypeString, value)
+	}
+	if value, ok := tu.mutation.Content(); ok {
+		_spec.SetField(tutorial.FieldContent, field.TypeString, value)
+	}
+	if value, ok := tu.mutation.OrganizationID(); ok {
+		_spec.SetField(tutorial.FieldOrganizationID, field.TypeUint64, value)
+	}
+	if value, ok := tu.mutation.AddedOrganizationID(); ok {
+		_spec.AddField(tutorial.FieldOrganizationID, field.TypeUint64, value)
+	}
+	if tu.mutation.EmployeeCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   tutorial.EmployeeTable,
+			Columns: []string{tutorial.EmployeeColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(employee.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := tu.mutation.EmployeeIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   tutorial.EmployeeTable,
+			Columns: []string{tutorial.EmployeeColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(employee.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
+	if n, err = sqlgraph.UpdateNodes(ctx, tu.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{tutorial.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return 0, err
+	}
+	tu.mutation.done = true
+	return n, nil
+}
+
+// TutorialUpdateOne is the builder for updating a single Tutorial entity.
+type TutorialUpdateOne struct {
+	config
+	fields   []string
+	hooks    []Hook
+	mutation *TutorialMutation
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (tuo *TutorialUpdateOne) SetUpdatedAt(t time.Time) *TutorialUpdateOne {
+	tuo.mutation.SetUpdatedAt(t)
+	return tuo
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (tuo *TutorialUpdateOne) SetDeletedAt(t time.Time) *TutorialUpdateOne {
+	tuo.mutation.SetDeletedAt(t)
+	return tuo
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (tuo *TutorialUpdateOne) SetNillableDeletedAt(t *time.Time) *TutorialUpdateOne {
+	if t != nil {
+		tuo.SetDeletedAt(*t)
+	}
+	return tuo
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (tuo *TutorialUpdateOne) ClearDeletedAt() *TutorialUpdateOne {
+	tuo.mutation.ClearDeletedAt()
+	return tuo
+}
+
+// SetEmployeeID sets the "employee_id" field.
+func (tuo *TutorialUpdateOne) SetEmployeeID(u uint64) *TutorialUpdateOne {
+	tuo.mutation.SetEmployeeID(u)
+	return tuo
+}
+
+// SetNillableEmployeeID sets the "employee_id" field if the given value is not nil.
+func (tuo *TutorialUpdateOne) SetNillableEmployeeID(u *uint64) *TutorialUpdateOne {
+	if u != nil {
+		tuo.SetEmployeeID(*u)
+	}
+	return tuo
+}
+
+// SetIndex sets the "index" field.
+func (tuo *TutorialUpdateOne) SetIndex(i int) *TutorialUpdateOne {
+	tuo.mutation.ResetIndex()
+	tuo.mutation.SetIndex(i)
+	return tuo
+}
+
+// SetNillableIndex sets the "index" field if the given value is not nil.
+func (tuo *TutorialUpdateOne) SetNillableIndex(i *int) *TutorialUpdateOne {
+	if i != nil {
+		tuo.SetIndex(*i)
+	}
+	return tuo
+}
+
+// AddIndex adds i to the "index" field.
+func (tuo *TutorialUpdateOne) AddIndex(i int) *TutorialUpdateOne {
+	tuo.mutation.AddIndex(i)
+	return tuo
+}
+
+// SetTitle sets the "title" field.
+func (tuo *TutorialUpdateOne) SetTitle(s string) *TutorialUpdateOne {
+	tuo.mutation.SetTitle(s)
+	return tuo
+}
+
+// SetNillableTitle sets the "title" field if the given value is not nil.
+func (tuo *TutorialUpdateOne) SetNillableTitle(s *string) *TutorialUpdateOne {
+	if s != nil {
+		tuo.SetTitle(*s)
+	}
+	return tuo
+}
+
+// SetContent sets the "content" field.
+func (tuo *TutorialUpdateOne) SetContent(s string) *TutorialUpdateOne {
+	tuo.mutation.SetContent(s)
+	return tuo
+}
+
+// SetNillableContent sets the "content" field if the given value is not nil.
+func (tuo *TutorialUpdateOne) SetNillableContent(s *string) *TutorialUpdateOne {
+	if s != nil {
+		tuo.SetContent(*s)
+	}
+	return tuo
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (tuo *TutorialUpdateOne) SetOrganizationID(u uint64) *TutorialUpdateOne {
+	tuo.mutation.ResetOrganizationID()
+	tuo.mutation.SetOrganizationID(u)
+	return tuo
+}
+
+// SetNillableOrganizationID sets the "organization_id" field if the given value is not nil.
+func (tuo *TutorialUpdateOne) SetNillableOrganizationID(u *uint64) *TutorialUpdateOne {
+	if u != nil {
+		tuo.SetOrganizationID(*u)
+	}
+	return tuo
+}
+
+// AddOrganizationID adds u to the "organization_id" field.
+func (tuo *TutorialUpdateOne) AddOrganizationID(u int64) *TutorialUpdateOne {
+	tuo.mutation.AddOrganizationID(u)
+	return tuo
+}
+
+// SetEmployee sets the "employee" edge to the Employee entity.
+func (tuo *TutorialUpdateOne) SetEmployee(e *Employee) *TutorialUpdateOne {
+	return tuo.SetEmployeeID(e.ID)
+}
+
+// Mutation returns the TutorialMutation object of the builder.
+func (tuo *TutorialUpdateOne) Mutation() *TutorialMutation {
+	return tuo.mutation
+}
+
+// ClearEmployee clears the "employee" edge to the Employee entity.
+func (tuo *TutorialUpdateOne) ClearEmployee() *TutorialUpdateOne {
+	tuo.mutation.ClearEmployee()
+	return tuo
+}
+
+// Where appends a list predicates to the TutorialUpdate builder.
+func (tuo *TutorialUpdateOne) Where(ps ...predicate.Tutorial) *TutorialUpdateOne {
+	tuo.mutation.Where(ps...)
+	return tuo
+}
+
+// Select allows selecting one or more fields (columns) of the returned entity.
+// The default is selecting all fields defined in the entity schema.
+func (tuo *TutorialUpdateOne) Select(field string, fields ...string) *TutorialUpdateOne {
+	tuo.fields = append([]string{field}, fields...)
+	return tuo
+}
+
+// Save executes the query and returns the updated Tutorial entity.
+func (tuo *TutorialUpdateOne) Save(ctx context.Context) (*Tutorial, error) {
+	if err := tuo.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, tuo.sqlSave, tuo.mutation, tuo.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (tuo *TutorialUpdateOne) SaveX(ctx context.Context) *Tutorial {
+	node, err := tuo.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return node
+}
+
+// Exec executes the query on the entity.
+func (tuo *TutorialUpdateOne) Exec(ctx context.Context) error {
+	_, err := tuo.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (tuo *TutorialUpdateOne) ExecX(ctx context.Context) {
+	if err := tuo.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (tuo *TutorialUpdateOne) defaults() error {
+	if _, ok := tuo.mutation.UpdatedAt(); !ok {
+		if tutorial.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized tutorial.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := tutorial.UpdateDefaultUpdatedAt()
+		tuo.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (tuo *TutorialUpdateOne) check() error {
+	if v, ok := tuo.mutation.EmployeeID(); ok {
+		if err := tutorial.EmployeeIDValidator(v); err != nil {
+			return &ValidationError{Name: "employee_id", err: fmt.Errorf(`ent: validator failed for field "Tutorial.employee_id": %w`, err)}
+		}
+	}
+	if v, ok := tuo.mutation.OrganizationID(); ok {
+		if err := tutorial.OrganizationIDValidator(v); err != nil {
+			return &ValidationError{Name: "organization_id", err: fmt.Errorf(`ent: validator failed for field "Tutorial.organization_id": %w`, err)}
+		}
+	}
+	if _, ok := tuo.mutation.EmployeeID(); tuo.mutation.EmployeeCleared() && !ok {
+		return errors.New(`ent: clearing a required unique edge "Tutorial.employee"`)
+	}
+	return nil
+}
+
+func (tuo *TutorialUpdateOne) sqlSave(ctx context.Context) (_node *Tutorial, err error) {
+	if err := tuo.check(); err != nil {
+		return _node, err
+	}
+	_spec := sqlgraph.NewUpdateSpec(tutorial.Table, tutorial.Columns, sqlgraph.NewFieldSpec(tutorial.FieldID, field.TypeUint64))
+	id, ok := tuo.mutation.ID()
+	if !ok {
+		return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Tutorial.id" for update`)}
+	}
+	_spec.Node.ID.Value = id
+	if fields := tuo.fields; len(fields) > 0 {
+		_spec.Node.Columns = make([]string, 0, len(fields))
+		_spec.Node.Columns = append(_spec.Node.Columns, tutorial.FieldID)
+		for _, f := range fields {
+			if !tutorial.ValidColumn(f) {
+				return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+			}
+			if f != tutorial.FieldID {
+				_spec.Node.Columns = append(_spec.Node.Columns, f)
+			}
+		}
+	}
+	if ps := tuo.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := tuo.mutation.UpdatedAt(); ok {
+		_spec.SetField(tutorial.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := tuo.mutation.DeletedAt(); ok {
+		_spec.SetField(tutorial.FieldDeletedAt, field.TypeTime, value)
+	}
+	if tuo.mutation.DeletedAtCleared() {
+		_spec.ClearField(tutorial.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := tuo.mutation.Index(); ok {
+		_spec.SetField(tutorial.FieldIndex, field.TypeInt, value)
+	}
+	if value, ok := tuo.mutation.AddedIndex(); ok {
+		_spec.AddField(tutorial.FieldIndex, field.TypeInt, value)
+	}
+	if value, ok := tuo.mutation.Title(); ok {
+		_spec.SetField(tutorial.FieldTitle, field.TypeString, value)
+	}
+	if value, ok := tuo.mutation.Content(); ok {
+		_spec.SetField(tutorial.FieldContent, field.TypeString, value)
+	}
+	if value, ok := tuo.mutation.OrganizationID(); ok {
+		_spec.SetField(tutorial.FieldOrganizationID, field.TypeUint64, value)
+	}
+	if value, ok := tuo.mutation.AddedOrganizationID(); ok {
+		_spec.AddField(tutorial.FieldOrganizationID, field.TypeUint64, value)
+	}
+	if tuo.mutation.EmployeeCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   tutorial.EmployeeTable,
+			Columns: []string{tutorial.EmployeeColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(employee.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := tuo.mutation.EmployeeIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   tutorial.EmployeeTable,
+			Columns: []string{tutorial.EmployeeColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(employee.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
+	_node = &Tutorial{config: tuo.config}
+	_spec.Assign = _node.assignValues
+	_spec.ScanValues = _node.scanValues
+	if err = sqlgraph.UpdateNode(ctx, tuo.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{tutorial.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	tuo.mutation.done = true
+	return _node, nil
+}

+ 9 - 0
ent/tx.go

@@ -20,6 +20,8 @@ type Tx struct {
 	BatchMsg *BatchMsgClient
 	// Contact is the client for interacting with the Contact builders.
 	Contact *ContactClient
+	// Employee is the client for interacting with the Employee builders.
+	Employee *EmployeeClient
 	// Label is the client for interacting with the Label builders.
 	Label *LabelClient
 	// LabelRelationship is the client for interacting with the LabelRelationship builders.
@@ -38,6 +40,10 @@ type Tx struct {
 	SopStage *SopStageClient
 	// SopTask is the client for interacting with the SopTask builders.
 	SopTask *SopTaskClient
+	// Tutorial is the client for interacting with the Tutorial builders.
+	Tutorial *TutorialClient
+	// WorkExperience is the client for interacting with the WorkExperience builders.
+	WorkExperience *WorkExperienceClient
 	// Wx is the client for interacting with the Wx builders.
 	Wx *WxClient
 
@@ -174,6 +180,7 @@ func (tx *Tx) init() {
 	tx.Agent = NewAgentClient(tx.config)
 	tx.BatchMsg = NewBatchMsgClient(tx.config)
 	tx.Contact = NewContactClient(tx.config)
+	tx.Employee = NewEmployeeClient(tx.config)
 	tx.Label = NewLabelClient(tx.config)
 	tx.LabelRelationship = NewLabelRelationshipClient(tx.config)
 	tx.Message = NewMessageClient(tx.config)
@@ -183,6 +190,8 @@ func (tx *Tx) init() {
 	tx.SopNode = NewSopNodeClient(tx.config)
 	tx.SopStage = NewSopStageClient(tx.config)
 	tx.SopTask = NewSopTaskClient(tx.config)
+	tx.Tutorial = NewTutorialClient(tx.config)
+	tx.WorkExperience = NewWorkExperienceClient(tx.config)
 	tx.Wx = NewWxClient(tx.config)
 }
 

+ 223 - 0
ent/workexperience.go

@@ -0,0 +1,223 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"fmt"
+	"strings"
+	"time"
+	"wechat-api/ent/employee"
+	"wechat-api/ent/workexperience"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+)
+
+// WorkExperience is the model entity for the WorkExperience schema.
+type WorkExperience 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"`
+	// employee_id | 员工ID
+	EmployeeID uint64 `json:"employee_id,omitempty"`
+	// start_date | 开始时间
+	StartDate time.Time `json:"start_date,omitempty"`
+	// end_date | 结束时间
+	EndDate time.Time `json:"end_date,omitempty"`
+	// company | 公司名
+	Company string `json:"company,omitempty"`
+	// experience | 工作内容
+	Experience string `json:"experience,omitempty"`
+	// organization_id | 租户ID
+	OrganizationID uint64 `json:"organization_id,omitempty"`
+	// Edges holds the relations/edges for other nodes in the graph.
+	// The values are being populated by the WorkExperienceQuery when eager-loading is set.
+	Edges        WorkExperienceEdges `json:"edges"`
+	selectValues sql.SelectValues
+}
+
+// WorkExperienceEdges holds the relations/edges for other nodes in the graph.
+type WorkExperienceEdges struct {
+	// Employee holds the value of the employee edge.
+	Employee *Employee `json:"employee,omitempty"`
+	// loadedTypes holds the information for reporting if a
+	// type was loaded (or requested) in eager-loading or not.
+	loadedTypes [1]bool
+}
+
+// EmployeeOrErr returns the Employee value or an error if the edge
+// was not loaded in eager-loading, or loaded but was not found.
+func (e WorkExperienceEdges) EmployeeOrErr() (*Employee, error) {
+	if e.Employee != nil {
+		return e.Employee, nil
+	} else if e.loadedTypes[0] {
+		return nil, &NotFoundError{label: employee.Label}
+	}
+	return nil, &NotLoadedError{edge: "employee"}
+}
+
+// scanValues returns the types for scanning values from sql.Rows.
+func (*WorkExperience) scanValues(columns []string) ([]any, error) {
+	values := make([]any, len(columns))
+	for i := range columns {
+		switch columns[i] {
+		case workexperience.FieldID, workexperience.FieldEmployeeID, workexperience.FieldOrganizationID:
+			values[i] = new(sql.NullInt64)
+		case workexperience.FieldCompany, workexperience.FieldExperience:
+			values[i] = new(sql.NullString)
+		case workexperience.FieldCreatedAt, workexperience.FieldUpdatedAt, workexperience.FieldDeletedAt, workexperience.FieldStartDate, workexperience.FieldEndDate:
+			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 WorkExperience fields.
+func (we *WorkExperience) 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 workexperience.FieldID:
+			value, ok := values[i].(*sql.NullInt64)
+			if !ok {
+				return fmt.Errorf("unexpected type %T for field id", value)
+			}
+			we.ID = uint64(value.Int64)
+		case workexperience.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 {
+				we.CreatedAt = value.Time
+			}
+		case workexperience.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 {
+				we.UpdatedAt = value.Time
+			}
+		case workexperience.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 {
+				we.DeletedAt = value.Time
+			}
+		case workexperience.FieldEmployeeID:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field employee_id", values[i])
+			} else if value.Valid {
+				we.EmployeeID = uint64(value.Int64)
+			}
+		case workexperience.FieldStartDate:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field start_date", values[i])
+			} else if value.Valid {
+				we.StartDate = value.Time
+			}
+		case workexperience.FieldEndDate:
+			if value, ok := values[i].(*sql.NullTime); !ok {
+				return fmt.Errorf("unexpected type %T for field end_date", values[i])
+			} else if value.Valid {
+				we.EndDate = value.Time
+			}
+		case workexperience.FieldCompany:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field company", values[i])
+			} else if value.Valid {
+				we.Company = value.String
+			}
+		case workexperience.FieldExperience:
+			if value, ok := values[i].(*sql.NullString); !ok {
+				return fmt.Errorf("unexpected type %T for field experience", values[i])
+			} else if value.Valid {
+				we.Experience = value.String
+			}
+		case workexperience.FieldOrganizationID:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field organization_id", values[i])
+			} else if value.Valid {
+				we.OrganizationID = uint64(value.Int64)
+			}
+		default:
+			we.selectValues.Set(columns[i], values[i])
+		}
+	}
+	return nil
+}
+
+// Value returns the ent.Value that was dynamically selected and assigned to the WorkExperience.
+// This includes values selected through modifiers, order, etc.
+func (we *WorkExperience) Value(name string) (ent.Value, error) {
+	return we.selectValues.Get(name)
+}
+
+// QueryEmployee queries the "employee" edge of the WorkExperience entity.
+func (we *WorkExperience) QueryEmployee() *EmployeeQuery {
+	return NewWorkExperienceClient(we.config).QueryEmployee(we)
+}
+
+// Update returns a builder for updating this WorkExperience.
+// Note that you need to call WorkExperience.Unwrap() before calling this method if this WorkExperience
+// was returned from a transaction, and the transaction was committed or rolled back.
+func (we *WorkExperience) Update() *WorkExperienceUpdateOne {
+	return NewWorkExperienceClient(we.config).UpdateOne(we)
+}
+
+// Unwrap unwraps the WorkExperience 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 (we *WorkExperience) Unwrap() *WorkExperience {
+	_tx, ok := we.config.driver.(*txDriver)
+	if !ok {
+		panic("ent: WorkExperience is not a transactional entity")
+	}
+	we.config.driver = _tx.drv
+	return we
+}
+
+// String implements the fmt.Stringer.
+func (we *WorkExperience) String() string {
+	var builder strings.Builder
+	builder.WriteString("WorkExperience(")
+	builder.WriteString(fmt.Sprintf("id=%v, ", we.ID))
+	builder.WriteString("created_at=")
+	builder.WriteString(we.CreatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("updated_at=")
+	builder.WriteString(we.UpdatedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("deleted_at=")
+	builder.WriteString(we.DeletedAt.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("employee_id=")
+	builder.WriteString(fmt.Sprintf("%v", we.EmployeeID))
+	builder.WriteString(", ")
+	builder.WriteString("start_date=")
+	builder.WriteString(we.StartDate.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("end_date=")
+	builder.WriteString(we.EndDate.Format(time.ANSIC))
+	builder.WriteString(", ")
+	builder.WriteString("company=")
+	builder.WriteString(we.Company)
+	builder.WriteString(", ")
+	builder.WriteString("experience=")
+	builder.WriteString(we.Experience)
+	builder.WriteString(", ")
+	builder.WriteString("organization_id=")
+	builder.WriteString(fmt.Sprintf("%v", we.OrganizationID))
+	builder.WriteByte(')')
+	return builder.String()
+}
+
+// WorkExperiences is a parsable slice of WorkExperience.
+type WorkExperiences []*WorkExperience

+ 539 - 0
ent/workexperience/where.go

@@ -0,0 +1,539 @@
+// Code generated by ent, DO NOT EDIT.
+
+package workexperience
+
+import (
+	"time"
+	"wechat-api/ent/predicate"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+)
+
+// ID filters vertices based on their ID field.
+func ID(id uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEQ(FieldID, id))
+}
+
+// IDEQ applies the EQ predicate on the ID field.
+func IDEQ(id uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEQ(FieldID, id))
+}
+
+// IDNEQ applies the NEQ predicate on the ID field.
+func IDNEQ(id uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNEQ(FieldID, id))
+}
+
+// IDIn applies the In predicate on the ID field.
+func IDIn(ids ...uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldIn(FieldID, ids...))
+}
+
+// IDNotIn applies the NotIn predicate on the ID field.
+func IDNotIn(ids ...uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNotIn(FieldID, ids...))
+}
+
+// IDGT applies the GT predicate on the ID field.
+func IDGT(id uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldGT(FieldID, id))
+}
+
+// IDGTE applies the GTE predicate on the ID field.
+func IDGTE(id uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldGTE(FieldID, id))
+}
+
+// IDLT applies the LT predicate on the ID field.
+func IDLT(id uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldLT(FieldID, id))
+}
+
+// IDLTE applies the LTE predicate on the ID field.
+func IDLTE(id uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(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.WorkExperience {
+	return predicate.WorkExperience(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.WorkExperience {
+	return predicate.WorkExperience(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.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// EmployeeID applies equality check predicate on the "employee_id" field. It's identical to EmployeeIDEQ.
+func EmployeeID(v uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEQ(FieldEmployeeID, v))
+}
+
+// StartDate applies equality check predicate on the "start_date" field. It's identical to StartDateEQ.
+func StartDate(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEQ(FieldStartDate, v))
+}
+
+// EndDate applies equality check predicate on the "end_date" field. It's identical to EndDateEQ.
+func EndDate(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEQ(FieldEndDate, v))
+}
+
+// Company applies equality check predicate on the "company" field. It's identical to CompanyEQ.
+func Company(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEQ(FieldCompany, v))
+}
+
+// Experience applies equality check predicate on the "experience" field. It's identical to ExperienceEQ.
+func Experience(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEQ(FieldExperience, v))
+}
+
+// OrganizationID applies equality check predicate on the "organization_id" field. It's identical to OrganizationIDEQ.
+func OrganizationID(v uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEQ(FieldOrganizationID, v))
+}
+
+// CreatedAtEQ applies the EQ predicate on the "created_at" field.
+func CreatedAtEQ(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
+func CreatedAtNEQ(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNEQ(FieldCreatedAt, v))
+}
+
+// CreatedAtIn applies the In predicate on the "created_at" field.
+func CreatedAtIn(vs ...time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
+func CreatedAtNotIn(vs ...time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNotIn(FieldCreatedAt, vs...))
+}
+
+// CreatedAtGT applies the GT predicate on the "created_at" field.
+func CreatedAtGT(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldGT(FieldCreatedAt, v))
+}
+
+// CreatedAtGTE applies the GTE predicate on the "created_at" field.
+func CreatedAtGTE(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldGTE(FieldCreatedAt, v))
+}
+
+// CreatedAtLT applies the LT predicate on the "created_at" field.
+func CreatedAtLT(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldLT(FieldCreatedAt, v))
+}
+
+// CreatedAtLTE applies the LTE predicate on the "created_at" field.
+func CreatedAtLTE(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldLTE(FieldCreatedAt, v))
+}
+
+// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
+func UpdatedAtEQ(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
+func UpdatedAtNEQ(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNEQ(FieldUpdatedAt, v))
+}
+
+// UpdatedAtIn applies the In predicate on the "updated_at" field.
+func UpdatedAtIn(vs ...time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
+func UpdatedAtNotIn(vs ...time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNotIn(FieldUpdatedAt, vs...))
+}
+
+// UpdatedAtGT applies the GT predicate on the "updated_at" field.
+func UpdatedAtGT(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldGT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
+func UpdatedAtGTE(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldGTE(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLT applies the LT predicate on the "updated_at" field.
+func UpdatedAtLT(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldLT(FieldUpdatedAt, v))
+}
+
+// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
+func UpdatedAtLTE(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldLTE(FieldUpdatedAt, v))
+}
+
+// DeletedAtEQ applies the EQ predicate on the "deleted_at" field.
+func DeletedAtEQ(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field.
+func DeletedAtNEQ(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNEQ(FieldDeletedAt, v))
+}
+
+// DeletedAtIn applies the In predicate on the "deleted_at" field.
+func DeletedAtIn(vs ...time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field.
+func DeletedAtNotIn(vs ...time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNotIn(FieldDeletedAt, vs...))
+}
+
+// DeletedAtGT applies the GT predicate on the "deleted_at" field.
+func DeletedAtGT(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldGT(FieldDeletedAt, v))
+}
+
+// DeletedAtGTE applies the GTE predicate on the "deleted_at" field.
+func DeletedAtGTE(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldGTE(FieldDeletedAt, v))
+}
+
+// DeletedAtLT applies the LT predicate on the "deleted_at" field.
+func DeletedAtLT(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldLT(FieldDeletedAt, v))
+}
+
+// DeletedAtLTE applies the LTE predicate on the "deleted_at" field.
+func DeletedAtLTE(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldLTE(FieldDeletedAt, v))
+}
+
+// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field.
+func DeletedAtIsNil() predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldIsNull(FieldDeletedAt))
+}
+
+// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field.
+func DeletedAtNotNil() predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNotNull(FieldDeletedAt))
+}
+
+// EmployeeIDEQ applies the EQ predicate on the "employee_id" field.
+func EmployeeIDEQ(v uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEQ(FieldEmployeeID, v))
+}
+
+// EmployeeIDNEQ applies the NEQ predicate on the "employee_id" field.
+func EmployeeIDNEQ(v uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNEQ(FieldEmployeeID, v))
+}
+
+// EmployeeIDIn applies the In predicate on the "employee_id" field.
+func EmployeeIDIn(vs ...uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldIn(FieldEmployeeID, vs...))
+}
+
+// EmployeeIDNotIn applies the NotIn predicate on the "employee_id" field.
+func EmployeeIDNotIn(vs ...uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNotIn(FieldEmployeeID, vs...))
+}
+
+// StartDateEQ applies the EQ predicate on the "start_date" field.
+func StartDateEQ(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEQ(FieldStartDate, v))
+}
+
+// StartDateNEQ applies the NEQ predicate on the "start_date" field.
+func StartDateNEQ(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNEQ(FieldStartDate, v))
+}
+
+// StartDateIn applies the In predicate on the "start_date" field.
+func StartDateIn(vs ...time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldIn(FieldStartDate, vs...))
+}
+
+// StartDateNotIn applies the NotIn predicate on the "start_date" field.
+func StartDateNotIn(vs ...time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNotIn(FieldStartDate, vs...))
+}
+
+// StartDateGT applies the GT predicate on the "start_date" field.
+func StartDateGT(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldGT(FieldStartDate, v))
+}
+
+// StartDateGTE applies the GTE predicate on the "start_date" field.
+func StartDateGTE(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldGTE(FieldStartDate, v))
+}
+
+// StartDateLT applies the LT predicate on the "start_date" field.
+func StartDateLT(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldLT(FieldStartDate, v))
+}
+
+// StartDateLTE applies the LTE predicate on the "start_date" field.
+func StartDateLTE(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldLTE(FieldStartDate, v))
+}
+
+// EndDateEQ applies the EQ predicate on the "end_date" field.
+func EndDateEQ(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEQ(FieldEndDate, v))
+}
+
+// EndDateNEQ applies the NEQ predicate on the "end_date" field.
+func EndDateNEQ(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNEQ(FieldEndDate, v))
+}
+
+// EndDateIn applies the In predicate on the "end_date" field.
+func EndDateIn(vs ...time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldIn(FieldEndDate, vs...))
+}
+
+// EndDateNotIn applies the NotIn predicate on the "end_date" field.
+func EndDateNotIn(vs ...time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNotIn(FieldEndDate, vs...))
+}
+
+// EndDateGT applies the GT predicate on the "end_date" field.
+func EndDateGT(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldGT(FieldEndDate, v))
+}
+
+// EndDateGTE applies the GTE predicate on the "end_date" field.
+func EndDateGTE(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldGTE(FieldEndDate, v))
+}
+
+// EndDateLT applies the LT predicate on the "end_date" field.
+func EndDateLT(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldLT(FieldEndDate, v))
+}
+
+// EndDateLTE applies the LTE predicate on the "end_date" field.
+func EndDateLTE(v time.Time) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldLTE(FieldEndDate, v))
+}
+
+// CompanyEQ applies the EQ predicate on the "company" field.
+func CompanyEQ(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEQ(FieldCompany, v))
+}
+
+// CompanyNEQ applies the NEQ predicate on the "company" field.
+func CompanyNEQ(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNEQ(FieldCompany, v))
+}
+
+// CompanyIn applies the In predicate on the "company" field.
+func CompanyIn(vs ...string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldIn(FieldCompany, vs...))
+}
+
+// CompanyNotIn applies the NotIn predicate on the "company" field.
+func CompanyNotIn(vs ...string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNotIn(FieldCompany, vs...))
+}
+
+// CompanyGT applies the GT predicate on the "company" field.
+func CompanyGT(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldGT(FieldCompany, v))
+}
+
+// CompanyGTE applies the GTE predicate on the "company" field.
+func CompanyGTE(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldGTE(FieldCompany, v))
+}
+
+// CompanyLT applies the LT predicate on the "company" field.
+func CompanyLT(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldLT(FieldCompany, v))
+}
+
+// CompanyLTE applies the LTE predicate on the "company" field.
+func CompanyLTE(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldLTE(FieldCompany, v))
+}
+
+// CompanyContains applies the Contains predicate on the "company" field.
+func CompanyContains(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldContains(FieldCompany, v))
+}
+
+// CompanyHasPrefix applies the HasPrefix predicate on the "company" field.
+func CompanyHasPrefix(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldHasPrefix(FieldCompany, v))
+}
+
+// CompanyHasSuffix applies the HasSuffix predicate on the "company" field.
+func CompanyHasSuffix(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldHasSuffix(FieldCompany, v))
+}
+
+// CompanyEqualFold applies the EqualFold predicate on the "company" field.
+func CompanyEqualFold(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEqualFold(FieldCompany, v))
+}
+
+// CompanyContainsFold applies the ContainsFold predicate on the "company" field.
+func CompanyContainsFold(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldContainsFold(FieldCompany, v))
+}
+
+// ExperienceEQ applies the EQ predicate on the "experience" field.
+func ExperienceEQ(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEQ(FieldExperience, v))
+}
+
+// ExperienceNEQ applies the NEQ predicate on the "experience" field.
+func ExperienceNEQ(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNEQ(FieldExperience, v))
+}
+
+// ExperienceIn applies the In predicate on the "experience" field.
+func ExperienceIn(vs ...string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldIn(FieldExperience, vs...))
+}
+
+// ExperienceNotIn applies the NotIn predicate on the "experience" field.
+func ExperienceNotIn(vs ...string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNotIn(FieldExperience, vs...))
+}
+
+// ExperienceGT applies the GT predicate on the "experience" field.
+func ExperienceGT(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldGT(FieldExperience, v))
+}
+
+// ExperienceGTE applies the GTE predicate on the "experience" field.
+func ExperienceGTE(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldGTE(FieldExperience, v))
+}
+
+// ExperienceLT applies the LT predicate on the "experience" field.
+func ExperienceLT(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldLT(FieldExperience, v))
+}
+
+// ExperienceLTE applies the LTE predicate on the "experience" field.
+func ExperienceLTE(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldLTE(FieldExperience, v))
+}
+
+// ExperienceContains applies the Contains predicate on the "experience" field.
+func ExperienceContains(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldContains(FieldExperience, v))
+}
+
+// ExperienceHasPrefix applies the HasPrefix predicate on the "experience" field.
+func ExperienceHasPrefix(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldHasPrefix(FieldExperience, v))
+}
+
+// ExperienceHasSuffix applies the HasSuffix predicate on the "experience" field.
+func ExperienceHasSuffix(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldHasSuffix(FieldExperience, v))
+}
+
+// ExperienceEqualFold applies the EqualFold predicate on the "experience" field.
+func ExperienceEqualFold(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEqualFold(FieldExperience, v))
+}
+
+// ExperienceContainsFold applies the ContainsFold predicate on the "experience" field.
+func ExperienceContainsFold(v string) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldContainsFold(FieldExperience, v))
+}
+
+// OrganizationIDEQ applies the EQ predicate on the "organization_id" field.
+func OrganizationIDEQ(v uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldEQ(FieldOrganizationID, v))
+}
+
+// OrganizationIDNEQ applies the NEQ predicate on the "organization_id" field.
+func OrganizationIDNEQ(v uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNEQ(FieldOrganizationID, v))
+}
+
+// OrganizationIDIn applies the In predicate on the "organization_id" field.
+func OrganizationIDIn(vs ...uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldIn(FieldOrganizationID, vs...))
+}
+
+// OrganizationIDNotIn applies the NotIn predicate on the "organization_id" field.
+func OrganizationIDNotIn(vs ...uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldNotIn(FieldOrganizationID, vs...))
+}
+
+// OrganizationIDGT applies the GT predicate on the "organization_id" field.
+func OrganizationIDGT(v uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldGT(FieldOrganizationID, v))
+}
+
+// OrganizationIDGTE applies the GTE predicate on the "organization_id" field.
+func OrganizationIDGTE(v uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldGTE(FieldOrganizationID, v))
+}
+
+// OrganizationIDLT applies the LT predicate on the "organization_id" field.
+func OrganizationIDLT(v uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldLT(FieldOrganizationID, v))
+}
+
+// OrganizationIDLTE applies the LTE predicate on the "organization_id" field.
+func OrganizationIDLTE(v uint64) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.FieldLTE(FieldOrganizationID, v))
+}
+
+// HasEmployee applies the HasEdge predicate on the "employee" edge.
+func HasEmployee() predicate.WorkExperience {
+	return predicate.WorkExperience(func(s *sql.Selector) {
+		step := sqlgraph.NewStep(
+			sqlgraph.From(Table, FieldID),
+			sqlgraph.Edge(sqlgraph.M2O, true, EmployeeTable, EmployeeColumn),
+		)
+		sqlgraph.HasNeighbors(s, step)
+	})
+}
+
+// HasEmployeeWith applies the HasEdge predicate on the "employee" edge with a given conditions (other predicates).
+func HasEmployeeWith(preds ...predicate.Employee) predicate.WorkExperience {
+	return predicate.WorkExperience(func(s *sql.Selector) {
+		step := newEmployeeStep()
+		sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+			for _, p := range preds {
+				p(s)
+			}
+		})
+	})
+}
+
+// And groups predicates with the AND operator between them.
+func And(predicates ...predicate.WorkExperience) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.AndPredicates(predicates...))
+}
+
+// Or groups predicates with the OR operator between them.
+func Or(predicates ...predicate.WorkExperience) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.OrPredicates(predicates...))
+}
+
+// Not applies the not operator on the given predicate.
+func Not(p predicate.WorkExperience) predicate.WorkExperience {
+	return predicate.WorkExperience(sql.NotPredicates(p))
+}

+ 154 - 0
ent/workexperience/workexperience.go

@@ -0,0 +1,154 @@
+// Code generated by ent, DO NOT EDIT.
+
+package workexperience
+
+import (
+	"time"
+
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+)
+
+const (
+	// Label holds the string label denoting the workexperience type in the database.
+	Label = "work_experience"
+	// 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"
+	// FieldEmployeeID holds the string denoting the employee_id field in the database.
+	FieldEmployeeID = "employee_id"
+	// FieldStartDate holds the string denoting the start_date field in the database.
+	FieldStartDate = "start_date"
+	// FieldEndDate holds the string denoting the end_date field in the database.
+	FieldEndDate = "end_date"
+	// FieldCompany holds the string denoting the company field in the database.
+	FieldCompany = "company"
+	// FieldExperience holds the string denoting the experience field in the database.
+	FieldExperience = "experience"
+	// FieldOrganizationID holds the string denoting the organization_id field in the database.
+	FieldOrganizationID = "organization_id"
+	// EdgeEmployee holds the string denoting the employee edge name in mutations.
+	EdgeEmployee = "employee"
+	// Table holds the table name of the workexperience in the database.
+	Table = "work_experience"
+	// EmployeeTable is the table that holds the employee relation/edge.
+	EmployeeTable = "work_experience"
+	// EmployeeInverseTable is the table name for the Employee entity.
+	// It exists in this package in order to avoid circular dependency with the "employee" package.
+	EmployeeInverseTable = "employee"
+	// EmployeeColumn is the table column denoting the employee relation/edge.
+	EmployeeColumn = "employee_id"
+)
+
+// Columns holds all SQL columns for workexperience fields.
+var Columns = []string{
+	FieldID,
+	FieldCreatedAt,
+	FieldUpdatedAt,
+	FieldDeletedAt,
+	FieldEmployeeID,
+	FieldStartDate,
+	FieldEndDate,
+	FieldCompany,
+	FieldExperience,
+	FieldOrganizationID,
+}
+
+// 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
+)
+
+// OrderOption defines the ordering options for the WorkExperience 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()
+}
+
+// ByEmployeeID orders the results by the employee_id field.
+func ByEmployeeID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldEmployeeID, opts...).ToFunc()
+}
+
+// ByStartDate orders the results by the start_date field.
+func ByStartDate(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldStartDate, opts...).ToFunc()
+}
+
+// ByEndDate orders the results by the end_date field.
+func ByEndDate(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldEndDate, opts...).ToFunc()
+}
+
+// ByCompany orders the results by the company field.
+func ByCompany(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldCompany, opts...).ToFunc()
+}
+
+// ByExperience orders the results by the experience field.
+func ByExperience(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldExperience, opts...).ToFunc()
+}
+
+// ByOrganizationID orders the results by the organization_id field.
+func ByOrganizationID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldOrganizationID, opts...).ToFunc()
+}
+
+// ByEmployeeField orders the results by employee field.
+func ByEmployeeField(field string, opts ...sql.OrderTermOption) OrderOption {
+	return func(s *sql.Selector) {
+		sqlgraph.OrderByNeighborTerms(s, newEmployeeStep(), sql.OrderByField(field, opts...))
+	}
+}
+func newEmployeeStep() *sqlgraph.Step {
+	return sqlgraph.NewStep(
+		sqlgraph.From(Table, FieldID),
+		sqlgraph.To(EmployeeInverseTable, FieldID),
+		sqlgraph.Edge(sqlgraph.M2O, true, EmployeeTable, EmployeeColumn),
+	)
+}

+ 981 - 0
ent/workexperience_create.go

@@ -0,0 +1,981 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/employee"
+	"wechat-api/ent/workexperience"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// WorkExperienceCreate is the builder for creating a WorkExperience entity.
+type WorkExperienceCreate struct {
+	config
+	mutation *WorkExperienceMutation
+	hooks    []Hook
+	conflict []sql.ConflictOption
+}
+
+// SetCreatedAt sets the "created_at" field.
+func (wec *WorkExperienceCreate) SetCreatedAt(t time.Time) *WorkExperienceCreate {
+	wec.mutation.SetCreatedAt(t)
+	return wec
+}
+
+// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
+func (wec *WorkExperienceCreate) SetNillableCreatedAt(t *time.Time) *WorkExperienceCreate {
+	if t != nil {
+		wec.SetCreatedAt(*t)
+	}
+	return wec
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (wec *WorkExperienceCreate) SetUpdatedAt(t time.Time) *WorkExperienceCreate {
+	wec.mutation.SetUpdatedAt(t)
+	return wec
+}
+
+// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
+func (wec *WorkExperienceCreate) SetNillableUpdatedAt(t *time.Time) *WorkExperienceCreate {
+	if t != nil {
+		wec.SetUpdatedAt(*t)
+	}
+	return wec
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (wec *WorkExperienceCreate) SetDeletedAt(t time.Time) *WorkExperienceCreate {
+	wec.mutation.SetDeletedAt(t)
+	return wec
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (wec *WorkExperienceCreate) SetNillableDeletedAt(t *time.Time) *WorkExperienceCreate {
+	if t != nil {
+		wec.SetDeletedAt(*t)
+	}
+	return wec
+}
+
+// SetEmployeeID sets the "employee_id" field.
+func (wec *WorkExperienceCreate) SetEmployeeID(u uint64) *WorkExperienceCreate {
+	wec.mutation.SetEmployeeID(u)
+	return wec
+}
+
+// SetStartDate sets the "start_date" field.
+func (wec *WorkExperienceCreate) SetStartDate(t time.Time) *WorkExperienceCreate {
+	wec.mutation.SetStartDate(t)
+	return wec
+}
+
+// SetEndDate sets the "end_date" field.
+func (wec *WorkExperienceCreate) SetEndDate(t time.Time) *WorkExperienceCreate {
+	wec.mutation.SetEndDate(t)
+	return wec
+}
+
+// SetCompany sets the "company" field.
+func (wec *WorkExperienceCreate) SetCompany(s string) *WorkExperienceCreate {
+	wec.mutation.SetCompany(s)
+	return wec
+}
+
+// SetExperience sets the "experience" field.
+func (wec *WorkExperienceCreate) SetExperience(s string) *WorkExperienceCreate {
+	wec.mutation.SetExperience(s)
+	return wec
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (wec *WorkExperienceCreate) SetOrganizationID(u uint64) *WorkExperienceCreate {
+	wec.mutation.SetOrganizationID(u)
+	return wec
+}
+
+// SetID sets the "id" field.
+func (wec *WorkExperienceCreate) SetID(u uint64) *WorkExperienceCreate {
+	wec.mutation.SetID(u)
+	return wec
+}
+
+// SetEmployee sets the "employee" edge to the Employee entity.
+func (wec *WorkExperienceCreate) SetEmployee(e *Employee) *WorkExperienceCreate {
+	return wec.SetEmployeeID(e.ID)
+}
+
+// Mutation returns the WorkExperienceMutation object of the builder.
+func (wec *WorkExperienceCreate) Mutation() *WorkExperienceMutation {
+	return wec.mutation
+}
+
+// Save creates the WorkExperience in the database.
+func (wec *WorkExperienceCreate) Save(ctx context.Context) (*WorkExperience, error) {
+	if err := wec.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, wec.sqlSave, wec.mutation, wec.hooks)
+}
+
+// SaveX calls Save and panics if Save returns an error.
+func (wec *WorkExperienceCreate) SaveX(ctx context.Context) *WorkExperience {
+	v, err := wec.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (wec *WorkExperienceCreate) Exec(ctx context.Context) error {
+	_, err := wec.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (wec *WorkExperienceCreate) ExecX(ctx context.Context) {
+	if err := wec.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (wec *WorkExperienceCreate) defaults() error {
+	if _, ok := wec.mutation.CreatedAt(); !ok {
+		if workexperience.DefaultCreatedAt == nil {
+			return fmt.Errorf("ent: uninitialized workexperience.DefaultCreatedAt (forgotten import ent/runtime?)")
+		}
+		v := workexperience.DefaultCreatedAt()
+		wec.mutation.SetCreatedAt(v)
+	}
+	if _, ok := wec.mutation.UpdatedAt(); !ok {
+		if workexperience.DefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized workexperience.DefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := workexperience.DefaultUpdatedAt()
+		wec.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (wec *WorkExperienceCreate) check() error {
+	if _, ok := wec.mutation.CreatedAt(); !ok {
+		return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "WorkExperience.created_at"`)}
+	}
+	if _, ok := wec.mutation.UpdatedAt(); !ok {
+		return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "WorkExperience.updated_at"`)}
+	}
+	if _, ok := wec.mutation.EmployeeID(); !ok {
+		return &ValidationError{Name: "employee_id", err: errors.New(`ent: missing required field "WorkExperience.employee_id"`)}
+	}
+	if _, ok := wec.mutation.StartDate(); !ok {
+		return &ValidationError{Name: "start_date", err: errors.New(`ent: missing required field "WorkExperience.start_date"`)}
+	}
+	if _, ok := wec.mutation.EndDate(); !ok {
+		return &ValidationError{Name: "end_date", err: errors.New(`ent: missing required field "WorkExperience.end_date"`)}
+	}
+	if _, ok := wec.mutation.Company(); !ok {
+		return &ValidationError{Name: "company", err: errors.New(`ent: missing required field "WorkExperience.company"`)}
+	}
+	if _, ok := wec.mutation.Experience(); !ok {
+		return &ValidationError{Name: "experience", err: errors.New(`ent: missing required field "WorkExperience.experience"`)}
+	}
+	if _, ok := wec.mutation.OrganizationID(); !ok {
+		return &ValidationError{Name: "organization_id", err: errors.New(`ent: missing required field "WorkExperience.organization_id"`)}
+	}
+	if _, ok := wec.mutation.EmployeeID(); !ok {
+		return &ValidationError{Name: "employee", err: errors.New(`ent: missing required edge "WorkExperience.employee"`)}
+	}
+	return nil
+}
+
+func (wec *WorkExperienceCreate) sqlSave(ctx context.Context) (*WorkExperience, error) {
+	if err := wec.check(); err != nil {
+		return nil, err
+	}
+	_node, _spec := wec.createSpec()
+	if err := sqlgraph.CreateNode(ctx, wec.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)
+	}
+	wec.mutation.id = &_node.ID
+	wec.mutation.done = true
+	return _node, nil
+}
+
+func (wec *WorkExperienceCreate) createSpec() (*WorkExperience, *sqlgraph.CreateSpec) {
+	var (
+		_node = &WorkExperience{config: wec.config}
+		_spec = sqlgraph.NewCreateSpec(workexperience.Table, sqlgraph.NewFieldSpec(workexperience.FieldID, field.TypeUint64))
+	)
+	_spec.OnConflict = wec.conflict
+	if id, ok := wec.mutation.ID(); ok {
+		_node.ID = id
+		_spec.ID.Value = id
+	}
+	if value, ok := wec.mutation.CreatedAt(); ok {
+		_spec.SetField(workexperience.FieldCreatedAt, field.TypeTime, value)
+		_node.CreatedAt = value
+	}
+	if value, ok := wec.mutation.UpdatedAt(); ok {
+		_spec.SetField(workexperience.FieldUpdatedAt, field.TypeTime, value)
+		_node.UpdatedAt = value
+	}
+	if value, ok := wec.mutation.DeletedAt(); ok {
+		_spec.SetField(workexperience.FieldDeletedAt, field.TypeTime, value)
+		_node.DeletedAt = value
+	}
+	if value, ok := wec.mutation.StartDate(); ok {
+		_spec.SetField(workexperience.FieldStartDate, field.TypeTime, value)
+		_node.StartDate = value
+	}
+	if value, ok := wec.mutation.EndDate(); ok {
+		_spec.SetField(workexperience.FieldEndDate, field.TypeTime, value)
+		_node.EndDate = value
+	}
+	if value, ok := wec.mutation.Company(); ok {
+		_spec.SetField(workexperience.FieldCompany, field.TypeString, value)
+		_node.Company = value
+	}
+	if value, ok := wec.mutation.Experience(); ok {
+		_spec.SetField(workexperience.FieldExperience, field.TypeString, value)
+		_node.Experience = value
+	}
+	if value, ok := wec.mutation.OrganizationID(); ok {
+		_spec.SetField(workexperience.FieldOrganizationID, field.TypeUint64, value)
+		_node.OrganizationID = value
+	}
+	if nodes := wec.mutation.EmployeeIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   workexperience.EmployeeTable,
+			Columns: []string{workexperience.EmployeeColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(employee.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_node.EmployeeID = nodes[0]
+		_spec.Edges = append(_spec.Edges, edge)
+	}
+	return _node, _spec
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.WorkExperience.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.WorkExperienceUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (wec *WorkExperienceCreate) OnConflict(opts ...sql.ConflictOption) *WorkExperienceUpsertOne {
+	wec.conflict = opts
+	return &WorkExperienceUpsertOne{
+		create: wec,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.WorkExperience.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (wec *WorkExperienceCreate) OnConflictColumns(columns ...string) *WorkExperienceUpsertOne {
+	wec.conflict = append(wec.conflict, sql.ConflictColumns(columns...))
+	return &WorkExperienceUpsertOne{
+		create: wec,
+	}
+}
+
+type (
+	// WorkExperienceUpsertOne is the builder for "upsert"-ing
+	//  one WorkExperience node.
+	WorkExperienceUpsertOne struct {
+		create *WorkExperienceCreate
+	}
+
+	// WorkExperienceUpsert is the "OnConflict" setter.
+	WorkExperienceUpsert struct {
+		*sql.UpdateSet
+	}
+)
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *WorkExperienceUpsert) SetUpdatedAt(v time.Time) *WorkExperienceUpsert {
+	u.Set(workexperience.FieldUpdatedAt, v)
+	return u
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *WorkExperienceUpsert) UpdateUpdatedAt() *WorkExperienceUpsert {
+	u.SetExcluded(workexperience.FieldUpdatedAt)
+	return u
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *WorkExperienceUpsert) SetDeletedAt(v time.Time) *WorkExperienceUpsert {
+	u.Set(workexperience.FieldDeletedAt, v)
+	return u
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *WorkExperienceUpsert) UpdateDeletedAt() *WorkExperienceUpsert {
+	u.SetExcluded(workexperience.FieldDeletedAt)
+	return u
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *WorkExperienceUpsert) ClearDeletedAt() *WorkExperienceUpsert {
+	u.SetNull(workexperience.FieldDeletedAt)
+	return u
+}
+
+// SetEmployeeID sets the "employee_id" field.
+func (u *WorkExperienceUpsert) SetEmployeeID(v uint64) *WorkExperienceUpsert {
+	u.Set(workexperience.FieldEmployeeID, v)
+	return u
+}
+
+// UpdateEmployeeID sets the "employee_id" field to the value that was provided on create.
+func (u *WorkExperienceUpsert) UpdateEmployeeID() *WorkExperienceUpsert {
+	u.SetExcluded(workexperience.FieldEmployeeID)
+	return u
+}
+
+// SetStartDate sets the "start_date" field.
+func (u *WorkExperienceUpsert) SetStartDate(v time.Time) *WorkExperienceUpsert {
+	u.Set(workexperience.FieldStartDate, v)
+	return u
+}
+
+// UpdateStartDate sets the "start_date" field to the value that was provided on create.
+func (u *WorkExperienceUpsert) UpdateStartDate() *WorkExperienceUpsert {
+	u.SetExcluded(workexperience.FieldStartDate)
+	return u
+}
+
+// SetEndDate sets the "end_date" field.
+func (u *WorkExperienceUpsert) SetEndDate(v time.Time) *WorkExperienceUpsert {
+	u.Set(workexperience.FieldEndDate, v)
+	return u
+}
+
+// UpdateEndDate sets the "end_date" field to the value that was provided on create.
+func (u *WorkExperienceUpsert) UpdateEndDate() *WorkExperienceUpsert {
+	u.SetExcluded(workexperience.FieldEndDate)
+	return u
+}
+
+// SetCompany sets the "company" field.
+func (u *WorkExperienceUpsert) SetCompany(v string) *WorkExperienceUpsert {
+	u.Set(workexperience.FieldCompany, v)
+	return u
+}
+
+// UpdateCompany sets the "company" field to the value that was provided on create.
+func (u *WorkExperienceUpsert) UpdateCompany() *WorkExperienceUpsert {
+	u.SetExcluded(workexperience.FieldCompany)
+	return u
+}
+
+// SetExperience sets the "experience" field.
+func (u *WorkExperienceUpsert) SetExperience(v string) *WorkExperienceUpsert {
+	u.Set(workexperience.FieldExperience, v)
+	return u
+}
+
+// UpdateExperience sets the "experience" field to the value that was provided on create.
+func (u *WorkExperienceUpsert) UpdateExperience() *WorkExperienceUpsert {
+	u.SetExcluded(workexperience.FieldExperience)
+	return u
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (u *WorkExperienceUpsert) SetOrganizationID(v uint64) *WorkExperienceUpsert {
+	u.Set(workexperience.FieldOrganizationID, v)
+	return u
+}
+
+// UpdateOrganizationID sets the "organization_id" field to the value that was provided on create.
+func (u *WorkExperienceUpsert) UpdateOrganizationID() *WorkExperienceUpsert {
+	u.SetExcluded(workexperience.FieldOrganizationID)
+	return u
+}
+
+// AddOrganizationID adds v to the "organization_id" field.
+func (u *WorkExperienceUpsert) AddOrganizationID(v uint64) *WorkExperienceUpsert {
+	u.Add(workexperience.FieldOrganizationID, 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.WorkExperience.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(workexperience.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *WorkExperienceUpsertOne) UpdateNewValues() *WorkExperienceUpsertOne {
+	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(workexperience.FieldID)
+		}
+		if _, exists := u.create.mutation.CreatedAt(); exists {
+			s.SetIgnore(workexperience.FieldCreatedAt)
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.WorkExperience.Create().
+//	    OnConflict(sql.ResolveWithIgnore()).
+//	    Exec(ctx)
+func (u *WorkExperienceUpsertOne) Ignore() *WorkExperienceUpsertOne {
+	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 *WorkExperienceUpsertOne) DoNothing() *WorkExperienceUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the WorkExperienceCreate.OnConflict
+// documentation for more info.
+func (u *WorkExperienceUpsertOne) Update(set func(*WorkExperienceUpsert)) *WorkExperienceUpsertOne {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&WorkExperienceUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *WorkExperienceUpsertOne) SetUpdatedAt(v time.Time) *WorkExperienceUpsertOne {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *WorkExperienceUpsertOne) UpdateUpdatedAt() *WorkExperienceUpsertOne {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *WorkExperienceUpsertOne) SetDeletedAt(v time.Time) *WorkExperienceUpsertOne {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *WorkExperienceUpsertOne) UpdateDeletedAt() *WorkExperienceUpsertOne {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *WorkExperienceUpsertOne) ClearDeletedAt() *WorkExperienceUpsertOne {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetEmployeeID sets the "employee_id" field.
+func (u *WorkExperienceUpsertOne) SetEmployeeID(v uint64) *WorkExperienceUpsertOne {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.SetEmployeeID(v)
+	})
+}
+
+// UpdateEmployeeID sets the "employee_id" field to the value that was provided on create.
+func (u *WorkExperienceUpsertOne) UpdateEmployeeID() *WorkExperienceUpsertOne {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.UpdateEmployeeID()
+	})
+}
+
+// SetStartDate sets the "start_date" field.
+func (u *WorkExperienceUpsertOne) SetStartDate(v time.Time) *WorkExperienceUpsertOne {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.SetStartDate(v)
+	})
+}
+
+// UpdateStartDate sets the "start_date" field to the value that was provided on create.
+func (u *WorkExperienceUpsertOne) UpdateStartDate() *WorkExperienceUpsertOne {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.UpdateStartDate()
+	})
+}
+
+// SetEndDate sets the "end_date" field.
+func (u *WorkExperienceUpsertOne) SetEndDate(v time.Time) *WorkExperienceUpsertOne {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.SetEndDate(v)
+	})
+}
+
+// UpdateEndDate sets the "end_date" field to the value that was provided on create.
+func (u *WorkExperienceUpsertOne) UpdateEndDate() *WorkExperienceUpsertOne {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.UpdateEndDate()
+	})
+}
+
+// SetCompany sets the "company" field.
+func (u *WorkExperienceUpsertOne) SetCompany(v string) *WorkExperienceUpsertOne {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.SetCompany(v)
+	})
+}
+
+// UpdateCompany sets the "company" field to the value that was provided on create.
+func (u *WorkExperienceUpsertOne) UpdateCompany() *WorkExperienceUpsertOne {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.UpdateCompany()
+	})
+}
+
+// SetExperience sets the "experience" field.
+func (u *WorkExperienceUpsertOne) SetExperience(v string) *WorkExperienceUpsertOne {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.SetExperience(v)
+	})
+}
+
+// UpdateExperience sets the "experience" field to the value that was provided on create.
+func (u *WorkExperienceUpsertOne) UpdateExperience() *WorkExperienceUpsertOne {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.UpdateExperience()
+	})
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (u *WorkExperienceUpsertOne) SetOrganizationID(v uint64) *WorkExperienceUpsertOne {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.SetOrganizationID(v)
+	})
+}
+
+// AddOrganizationID adds v to the "organization_id" field.
+func (u *WorkExperienceUpsertOne) AddOrganizationID(v uint64) *WorkExperienceUpsertOne {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.AddOrganizationID(v)
+	})
+}
+
+// UpdateOrganizationID sets the "organization_id" field to the value that was provided on create.
+func (u *WorkExperienceUpsertOne) UpdateOrganizationID() *WorkExperienceUpsertOne {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.UpdateOrganizationID()
+	})
+}
+
+// Exec executes the query.
+func (u *WorkExperienceUpsertOne) Exec(ctx context.Context) error {
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for WorkExperienceCreate.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *WorkExperienceUpsertOne) 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 *WorkExperienceUpsertOne) 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 *WorkExperienceUpsertOne) IDX(ctx context.Context) uint64 {
+	id, err := u.ID(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+// WorkExperienceCreateBulk is the builder for creating many WorkExperience entities in bulk.
+type WorkExperienceCreateBulk struct {
+	config
+	err      error
+	builders []*WorkExperienceCreate
+	conflict []sql.ConflictOption
+}
+
+// Save creates the WorkExperience entities in the database.
+func (wecb *WorkExperienceCreateBulk) Save(ctx context.Context) ([]*WorkExperience, error) {
+	if wecb.err != nil {
+		return nil, wecb.err
+	}
+	specs := make([]*sqlgraph.CreateSpec, len(wecb.builders))
+	nodes := make([]*WorkExperience, len(wecb.builders))
+	mutators := make([]Mutator, len(wecb.builders))
+	for i := range wecb.builders {
+		func(i int, root context.Context) {
+			builder := wecb.builders[i]
+			builder.defaults()
+			var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
+				mutation, ok := m.(*WorkExperienceMutation)
+				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, wecb.builders[i+1].mutation)
+				} else {
+					spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
+					spec.OnConflict = wecb.conflict
+					// Invoke the actual operation on the latest mutation in the chain.
+					if err = sqlgraph.BatchCreate(ctx, wecb.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, wecb.builders[0].mutation); err != nil {
+			return nil, err
+		}
+	}
+	return nodes, nil
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (wecb *WorkExperienceCreateBulk) SaveX(ctx context.Context) []*WorkExperience {
+	v, err := wecb.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return v
+}
+
+// Exec executes the query.
+func (wecb *WorkExperienceCreateBulk) Exec(ctx context.Context) error {
+	_, err := wecb.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (wecb *WorkExperienceCreateBulk) ExecX(ctx context.Context) {
+	if err := wecb.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
+// of the `INSERT` statement. For example:
+//
+//	client.WorkExperience.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.WorkExperienceUpsert) {
+//			SetCreatedAt(v+v).
+//		}).
+//		Exec(ctx)
+func (wecb *WorkExperienceCreateBulk) OnConflict(opts ...sql.ConflictOption) *WorkExperienceUpsertBulk {
+	wecb.conflict = opts
+	return &WorkExperienceUpsertBulk{
+		create: wecb,
+	}
+}
+
+// OnConflictColumns calls `OnConflict` and configures the columns
+// as conflict target. Using this option is equivalent to using:
+//
+//	client.WorkExperience.Create().
+//		OnConflict(sql.ConflictColumns(columns...)).
+//		Exec(ctx)
+func (wecb *WorkExperienceCreateBulk) OnConflictColumns(columns ...string) *WorkExperienceUpsertBulk {
+	wecb.conflict = append(wecb.conflict, sql.ConflictColumns(columns...))
+	return &WorkExperienceUpsertBulk{
+		create: wecb,
+	}
+}
+
+// WorkExperienceUpsertBulk is the builder for "upsert"-ing
+// a bulk of WorkExperience nodes.
+type WorkExperienceUpsertBulk struct {
+	create *WorkExperienceCreateBulk
+}
+
+// UpdateNewValues updates the mutable fields using the new values that
+// were set on create. Using this option is equivalent to using:
+//
+//	client.WorkExperience.Create().
+//		OnConflict(
+//			sql.ResolveWithNewValues(),
+//			sql.ResolveWith(func(u *sql.UpdateSet) {
+//				u.SetIgnore(workexperience.FieldID)
+//			}),
+//		).
+//		Exec(ctx)
+func (u *WorkExperienceUpsertBulk) UpdateNewValues() *WorkExperienceUpsertBulk {
+	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(workexperience.FieldID)
+			}
+			if _, exists := b.mutation.CreatedAt(); exists {
+				s.SetIgnore(workexperience.FieldCreatedAt)
+			}
+		}
+	}))
+	return u
+}
+
+// Ignore sets each column to itself in case of conflict.
+// Using this option is equivalent to using:
+//
+//	client.WorkExperience.Create().
+//		OnConflict(sql.ResolveWithIgnore()).
+//		Exec(ctx)
+func (u *WorkExperienceUpsertBulk) Ignore() *WorkExperienceUpsertBulk {
+	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 *WorkExperienceUpsertBulk) DoNothing() *WorkExperienceUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.DoNothing())
+	return u
+}
+
+// Update allows overriding fields `UPDATE` values. See the WorkExperienceCreateBulk.OnConflict
+// documentation for more info.
+func (u *WorkExperienceUpsertBulk) Update(set func(*WorkExperienceUpsert)) *WorkExperienceUpsertBulk {
+	u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
+		set(&WorkExperienceUpsert{UpdateSet: update})
+	}))
+	return u
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (u *WorkExperienceUpsertBulk) SetUpdatedAt(v time.Time) *WorkExperienceUpsertBulk {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.SetUpdatedAt(v)
+	})
+}
+
+// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
+func (u *WorkExperienceUpsertBulk) UpdateUpdatedAt() *WorkExperienceUpsertBulk {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.UpdateUpdatedAt()
+	})
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (u *WorkExperienceUpsertBulk) SetDeletedAt(v time.Time) *WorkExperienceUpsertBulk {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.SetDeletedAt(v)
+	})
+}
+
+// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create.
+func (u *WorkExperienceUpsertBulk) UpdateDeletedAt() *WorkExperienceUpsertBulk {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.UpdateDeletedAt()
+	})
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (u *WorkExperienceUpsertBulk) ClearDeletedAt() *WorkExperienceUpsertBulk {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.ClearDeletedAt()
+	})
+}
+
+// SetEmployeeID sets the "employee_id" field.
+func (u *WorkExperienceUpsertBulk) SetEmployeeID(v uint64) *WorkExperienceUpsertBulk {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.SetEmployeeID(v)
+	})
+}
+
+// UpdateEmployeeID sets the "employee_id" field to the value that was provided on create.
+func (u *WorkExperienceUpsertBulk) UpdateEmployeeID() *WorkExperienceUpsertBulk {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.UpdateEmployeeID()
+	})
+}
+
+// SetStartDate sets the "start_date" field.
+func (u *WorkExperienceUpsertBulk) SetStartDate(v time.Time) *WorkExperienceUpsertBulk {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.SetStartDate(v)
+	})
+}
+
+// UpdateStartDate sets the "start_date" field to the value that was provided on create.
+func (u *WorkExperienceUpsertBulk) UpdateStartDate() *WorkExperienceUpsertBulk {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.UpdateStartDate()
+	})
+}
+
+// SetEndDate sets the "end_date" field.
+func (u *WorkExperienceUpsertBulk) SetEndDate(v time.Time) *WorkExperienceUpsertBulk {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.SetEndDate(v)
+	})
+}
+
+// UpdateEndDate sets the "end_date" field to the value that was provided on create.
+func (u *WorkExperienceUpsertBulk) UpdateEndDate() *WorkExperienceUpsertBulk {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.UpdateEndDate()
+	})
+}
+
+// SetCompany sets the "company" field.
+func (u *WorkExperienceUpsertBulk) SetCompany(v string) *WorkExperienceUpsertBulk {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.SetCompany(v)
+	})
+}
+
+// UpdateCompany sets the "company" field to the value that was provided on create.
+func (u *WorkExperienceUpsertBulk) UpdateCompany() *WorkExperienceUpsertBulk {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.UpdateCompany()
+	})
+}
+
+// SetExperience sets the "experience" field.
+func (u *WorkExperienceUpsertBulk) SetExperience(v string) *WorkExperienceUpsertBulk {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.SetExperience(v)
+	})
+}
+
+// UpdateExperience sets the "experience" field to the value that was provided on create.
+func (u *WorkExperienceUpsertBulk) UpdateExperience() *WorkExperienceUpsertBulk {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.UpdateExperience()
+	})
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (u *WorkExperienceUpsertBulk) SetOrganizationID(v uint64) *WorkExperienceUpsertBulk {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.SetOrganizationID(v)
+	})
+}
+
+// AddOrganizationID adds v to the "organization_id" field.
+func (u *WorkExperienceUpsertBulk) AddOrganizationID(v uint64) *WorkExperienceUpsertBulk {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.AddOrganizationID(v)
+	})
+}
+
+// UpdateOrganizationID sets the "organization_id" field to the value that was provided on create.
+func (u *WorkExperienceUpsertBulk) UpdateOrganizationID() *WorkExperienceUpsertBulk {
+	return u.Update(func(s *WorkExperienceUpsert) {
+		s.UpdateOrganizationID()
+	})
+}
+
+// Exec executes the query.
+func (u *WorkExperienceUpsertBulk) 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 WorkExperienceCreateBulk instead", i)
+		}
+	}
+	if len(u.create.conflict) == 0 {
+		return errors.New("ent: missing options for WorkExperienceCreateBulk.OnConflict")
+	}
+	return u.create.Exec(ctx)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (u *WorkExperienceUpsertBulk) ExecX(ctx context.Context) {
+	if err := u.create.Exec(ctx); err != nil {
+		panic(err)
+	}
+}

+ 88 - 0
ent/workexperience_delete.go

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

+ 605 - 0
ent/workexperience_query.go

@@ -0,0 +1,605 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"fmt"
+	"math"
+	"wechat-api/ent/employee"
+	"wechat-api/ent/predicate"
+	"wechat-api/ent/workexperience"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// WorkExperienceQuery is the builder for querying WorkExperience entities.
+type WorkExperienceQuery struct {
+	config
+	ctx          *QueryContext
+	order        []workexperience.OrderOption
+	inters       []Interceptor
+	predicates   []predicate.WorkExperience
+	withEmployee *EmployeeQuery
+	// intermediate query (i.e. traversal path).
+	sql  *sql.Selector
+	path func(context.Context) (*sql.Selector, error)
+}
+
+// Where adds a new predicate for the WorkExperienceQuery builder.
+func (weq *WorkExperienceQuery) Where(ps ...predicate.WorkExperience) *WorkExperienceQuery {
+	weq.predicates = append(weq.predicates, ps...)
+	return weq
+}
+
+// Limit the number of records to be returned by this query.
+func (weq *WorkExperienceQuery) Limit(limit int) *WorkExperienceQuery {
+	weq.ctx.Limit = &limit
+	return weq
+}
+
+// Offset to start from.
+func (weq *WorkExperienceQuery) Offset(offset int) *WorkExperienceQuery {
+	weq.ctx.Offset = &offset
+	return weq
+}
+
+// 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 (weq *WorkExperienceQuery) Unique(unique bool) *WorkExperienceQuery {
+	weq.ctx.Unique = &unique
+	return weq
+}
+
+// Order specifies how the records should be ordered.
+func (weq *WorkExperienceQuery) Order(o ...workexperience.OrderOption) *WorkExperienceQuery {
+	weq.order = append(weq.order, o...)
+	return weq
+}
+
+// QueryEmployee chains the current query on the "employee" edge.
+func (weq *WorkExperienceQuery) QueryEmployee() *EmployeeQuery {
+	query := (&EmployeeClient{config: weq.config}).Query()
+	query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+		if err := weq.prepareQuery(ctx); err != nil {
+			return nil, err
+		}
+		selector := weq.sqlQuery(ctx)
+		if err := selector.Err(); err != nil {
+			return nil, err
+		}
+		step := sqlgraph.NewStep(
+			sqlgraph.From(workexperience.Table, workexperience.FieldID, selector),
+			sqlgraph.To(employee.Table, employee.FieldID),
+			sqlgraph.Edge(sqlgraph.M2O, true, workexperience.EmployeeTable, workexperience.EmployeeColumn),
+		)
+		fromU = sqlgraph.SetNeighbors(weq.driver.Dialect(), step)
+		return fromU, nil
+	}
+	return query
+}
+
+// First returns the first WorkExperience entity from the query.
+// Returns a *NotFoundError when no WorkExperience was found.
+func (weq *WorkExperienceQuery) First(ctx context.Context) (*WorkExperience, error) {
+	nodes, err := weq.Limit(1).All(setContextOp(ctx, weq.ctx, "First"))
+	if err != nil {
+		return nil, err
+	}
+	if len(nodes) == 0 {
+		return nil, &NotFoundError{workexperience.Label}
+	}
+	return nodes[0], nil
+}
+
+// FirstX is like First, but panics if an error occurs.
+func (weq *WorkExperienceQuery) FirstX(ctx context.Context) *WorkExperience {
+	node, err := weq.First(ctx)
+	if err != nil && !IsNotFound(err) {
+		panic(err)
+	}
+	return node
+}
+
+// FirstID returns the first WorkExperience ID from the query.
+// Returns a *NotFoundError when no WorkExperience ID was found.
+func (weq *WorkExperienceQuery) FirstID(ctx context.Context) (id uint64, err error) {
+	var ids []uint64
+	if ids, err = weq.Limit(1).IDs(setContextOp(ctx, weq.ctx, "FirstID")); err != nil {
+		return
+	}
+	if len(ids) == 0 {
+		err = &NotFoundError{workexperience.Label}
+		return
+	}
+	return ids[0], nil
+}
+
+// FirstIDX is like FirstID, but panics if an error occurs.
+func (weq *WorkExperienceQuery) FirstIDX(ctx context.Context) uint64 {
+	id, err := weq.FirstID(ctx)
+	if err != nil && !IsNotFound(err) {
+		panic(err)
+	}
+	return id
+}
+
+// Only returns a single WorkExperience entity found by the query, ensuring it only returns one.
+// Returns a *NotSingularError when more than one WorkExperience entity is found.
+// Returns a *NotFoundError when no WorkExperience entities are found.
+func (weq *WorkExperienceQuery) Only(ctx context.Context) (*WorkExperience, error) {
+	nodes, err := weq.Limit(2).All(setContextOp(ctx, weq.ctx, "Only"))
+	if err != nil {
+		return nil, err
+	}
+	switch len(nodes) {
+	case 1:
+		return nodes[0], nil
+	case 0:
+		return nil, &NotFoundError{workexperience.Label}
+	default:
+		return nil, &NotSingularError{workexperience.Label}
+	}
+}
+
+// OnlyX is like Only, but panics if an error occurs.
+func (weq *WorkExperienceQuery) OnlyX(ctx context.Context) *WorkExperience {
+	node, err := weq.Only(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return node
+}
+
+// OnlyID is like Only, but returns the only WorkExperience ID in the query.
+// Returns a *NotSingularError when more than one WorkExperience ID is found.
+// Returns a *NotFoundError when no entities are found.
+func (weq *WorkExperienceQuery) OnlyID(ctx context.Context) (id uint64, err error) {
+	var ids []uint64
+	if ids, err = weq.Limit(2).IDs(setContextOp(ctx, weq.ctx, "OnlyID")); err != nil {
+		return
+	}
+	switch len(ids) {
+	case 1:
+		id = ids[0]
+	case 0:
+		err = &NotFoundError{workexperience.Label}
+	default:
+		err = &NotSingularError{workexperience.Label}
+	}
+	return
+}
+
+// OnlyIDX is like OnlyID, but panics if an error occurs.
+func (weq *WorkExperienceQuery) OnlyIDX(ctx context.Context) uint64 {
+	id, err := weq.OnlyID(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return id
+}
+
+// All executes the query and returns a list of WorkExperiences.
+func (weq *WorkExperienceQuery) All(ctx context.Context) ([]*WorkExperience, error) {
+	ctx = setContextOp(ctx, weq.ctx, "All")
+	if err := weq.prepareQuery(ctx); err != nil {
+		return nil, err
+	}
+	qr := querierAll[[]*WorkExperience, *WorkExperienceQuery]()
+	return withInterceptors[[]*WorkExperience](ctx, weq, qr, weq.inters)
+}
+
+// AllX is like All, but panics if an error occurs.
+func (weq *WorkExperienceQuery) AllX(ctx context.Context) []*WorkExperience {
+	nodes, err := weq.All(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return nodes
+}
+
+// IDs executes the query and returns a list of WorkExperience IDs.
+func (weq *WorkExperienceQuery) IDs(ctx context.Context) (ids []uint64, err error) {
+	if weq.ctx.Unique == nil && weq.path != nil {
+		weq.Unique(true)
+	}
+	ctx = setContextOp(ctx, weq.ctx, "IDs")
+	if err = weq.Select(workexperience.FieldID).Scan(ctx, &ids); err != nil {
+		return nil, err
+	}
+	return ids, nil
+}
+
+// IDsX is like IDs, but panics if an error occurs.
+func (weq *WorkExperienceQuery) IDsX(ctx context.Context) []uint64 {
+	ids, err := weq.IDs(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return ids
+}
+
+// Count returns the count of the given query.
+func (weq *WorkExperienceQuery) Count(ctx context.Context) (int, error) {
+	ctx = setContextOp(ctx, weq.ctx, "Count")
+	if err := weq.prepareQuery(ctx); err != nil {
+		return 0, err
+	}
+	return withInterceptors[int](ctx, weq, querierCount[*WorkExperienceQuery](), weq.inters)
+}
+
+// CountX is like Count, but panics if an error occurs.
+func (weq *WorkExperienceQuery) CountX(ctx context.Context) int {
+	count, err := weq.Count(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return count
+}
+
+// Exist returns true if the query has elements in the graph.
+func (weq *WorkExperienceQuery) Exist(ctx context.Context) (bool, error) {
+	ctx = setContextOp(ctx, weq.ctx, "Exist")
+	switch _, err := weq.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 (weq *WorkExperienceQuery) ExistX(ctx context.Context) bool {
+	exist, err := weq.Exist(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return exist
+}
+
+// Clone returns a duplicate of the WorkExperienceQuery builder, including all associated steps. It can be
+// used to prepare common query builders and use them differently after the clone is made.
+func (weq *WorkExperienceQuery) Clone() *WorkExperienceQuery {
+	if weq == nil {
+		return nil
+	}
+	return &WorkExperienceQuery{
+		config:       weq.config,
+		ctx:          weq.ctx.Clone(),
+		order:        append([]workexperience.OrderOption{}, weq.order...),
+		inters:       append([]Interceptor{}, weq.inters...),
+		predicates:   append([]predicate.WorkExperience{}, weq.predicates...),
+		withEmployee: weq.withEmployee.Clone(),
+		// clone intermediate query.
+		sql:  weq.sql.Clone(),
+		path: weq.path,
+	}
+}
+
+// WithEmployee tells the query-builder to eager-load the nodes that are connected to
+// the "employee" edge. The optional arguments are used to configure the query builder of the edge.
+func (weq *WorkExperienceQuery) WithEmployee(opts ...func(*EmployeeQuery)) *WorkExperienceQuery {
+	query := (&EmployeeClient{config: weq.config}).Query()
+	for _, opt := range opts {
+		opt(query)
+	}
+	weq.withEmployee = query
+	return weq
+}
+
+// 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.WorkExperience.Query().
+//		GroupBy(workexperience.FieldCreatedAt).
+//		Aggregate(ent.Count()).
+//		Scan(ctx, &v)
+func (weq *WorkExperienceQuery) GroupBy(field string, fields ...string) *WorkExperienceGroupBy {
+	weq.ctx.Fields = append([]string{field}, fields...)
+	grbuild := &WorkExperienceGroupBy{build: weq}
+	grbuild.flds = &weq.ctx.Fields
+	grbuild.label = workexperience.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.WorkExperience.Query().
+//		Select(workexperience.FieldCreatedAt).
+//		Scan(ctx, &v)
+func (weq *WorkExperienceQuery) Select(fields ...string) *WorkExperienceSelect {
+	weq.ctx.Fields = append(weq.ctx.Fields, fields...)
+	sbuild := &WorkExperienceSelect{WorkExperienceQuery: weq}
+	sbuild.label = workexperience.Label
+	sbuild.flds, sbuild.scan = &weq.ctx.Fields, sbuild.Scan
+	return sbuild
+}
+
+// Aggregate returns a WorkExperienceSelect configured with the given aggregations.
+func (weq *WorkExperienceQuery) Aggregate(fns ...AggregateFunc) *WorkExperienceSelect {
+	return weq.Select().Aggregate(fns...)
+}
+
+func (weq *WorkExperienceQuery) prepareQuery(ctx context.Context) error {
+	for _, inter := range weq.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, weq); err != nil {
+				return err
+			}
+		}
+	}
+	for _, f := range weq.ctx.Fields {
+		if !workexperience.ValidColumn(f) {
+			return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+		}
+	}
+	if weq.path != nil {
+		prev, err := weq.path(ctx)
+		if err != nil {
+			return err
+		}
+		weq.sql = prev
+	}
+	return nil
+}
+
+func (weq *WorkExperienceQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*WorkExperience, error) {
+	var (
+		nodes       = []*WorkExperience{}
+		_spec       = weq.querySpec()
+		loadedTypes = [1]bool{
+			weq.withEmployee != nil,
+		}
+	)
+	_spec.ScanValues = func(columns []string) ([]any, error) {
+		return (*WorkExperience).scanValues(nil, columns)
+	}
+	_spec.Assign = func(columns []string, values []any) error {
+		node := &WorkExperience{config: weq.config}
+		nodes = append(nodes, node)
+		node.Edges.loadedTypes = loadedTypes
+		return node.assignValues(columns, values)
+	}
+	for i := range hooks {
+		hooks[i](ctx, _spec)
+	}
+	if err := sqlgraph.QueryNodes(ctx, weq.driver, _spec); err != nil {
+		return nil, err
+	}
+	if len(nodes) == 0 {
+		return nodes, nil
+	}
+	if query := weq.withEmployee; query != nil {
+		if err := weq.loadEmployee(ctx, query, nodes, nil,
+			func(n *WorkExperience, e *Employee) { n.Edges.Employee = e }); err != nil {
+			return nil, err
+		}
+	}
+	return nodes, nil
+}
+
+func (weq *WorkExperienceQuery) loadEmployee(ctx context.Context, query *EmployeeQuery, nodes []*WorkExperience, init func(*WorkExperience), assign func(*WorkExperience, *Employee)) error {
+	ids := make([]uint64, 0, len(nodes))
+	nodeids := make(map[uint64][]*WorkExperience)
+	for i := range nodes {
+		fk := nodes[i].EmployeeID
+		if _, ok := nodeids[fk]; !ok {
+			ids = append(ids, fk)
+		}
+		nodeids[fk] = append(nodeids[fk], nodes[i])
+	}
+	if len(ids) == 0 {
+		return nil
+	}
+	query.Where(employee.IDIn(ids...))
+	neighbors, err := query.All(ctx)
+	if err != nil {
+		return err
+	}
+	for _, n := range neighbors {
+		nodes, ok := nodeids[n.ID]
+		if !ok {
+			return fmt.Errorf(`unexpected foreign-key "employee_id" returned %v`, n.ID)
+		}
+		for i := range nodes {
+			assign(nodes[i], n)
+		}
+	}
+	return nil
+}
+
+func (weq *WorkExperienceQuery) sqlCount(ctx context.Context) (int, error) {
+	_spec := weq.querySpec()
+	_spec.Node.Columns = weq.ctx.Fields
+	if len(weq.ctx.Fields) > 0 {
+		_spec.Unique = weq.ctx.Unique != nil && *weq.ctx.Unique
+	}
+	return sqlgraph.CountNodes(ctx, weq.driver, _spec)
+}
+
+func (weq *WorkExperienceQuery) querySpec() *sqlgraph.QuerySpec {
+	_spec := sqlgraph.NewQuerySpec(workexperience.Table, workexperience.Columns, sqlgraph.NewFieldSpec(workexperience.FieldID, field.TypeUint64))
+	_spec.From = weq.sql
+	if unique := weq.ctx.Unique; unique != nil {
+		_spec.Unique = *unique
+	} else if weq.path != nil {
+		_spec.Unique = true
+	}
+	if fields := weq.ctx.Fields; len(fields) > 0 {
+		_spec.Node.Columns = make([]string, 0, len(fields))
+		_spec.Node.Columns = append(_spec.Node.Columns, workexperience.FieldID)
+		for i := range fields {
+			if fields[i] != workexperience.FieldID {
+				_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
+			}
+		}
+		if weq.withEmployee != nil {
+			_spec.Node.AddColumnOnce(workexperience.FieldEmployeeID)
+		}
+	}
+	if ps := weq.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if limit := weq.ctx.Limit; limit != nil {
+		_spec.Limit = *limit
+	}
+	if offset := weq.ctx.Offset; offset != nil {
+		_spec.Offset = *offset
+	}
+	if ps := weq.order; len(ps) > 0 {
+		_spec.Order = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	return _spec
+}
+
+func (weq *WorkExperienceQuery) sqlQuery(ctx context.Context) *sql.Selector {
+	builder := sql.Dialect(weq.driver.Dialect())
+	t1 := builder.Table(workexperience.Table)
+	columns := weq.ctx.Fields
+	if len(columns) == 0 {
+		columns = workexperience.Columns
+	}
+	selector := builder.Select(t1.Columns(columns...)...).From(t1)
+	if weq.sql != nil {
+		selector = weq.sql
+		selector.Select(selector.Columns(columns...)...)
+	}
+	if weq.ctx.Unique != nil && *weq.ctx.Unique {
+		selector.Distinct()
+	}
+	for _, p := range weq.predicates {
+		p(selector)
+	}
+	for _, p := range weq.order {
+		p(selector)
+	}
+	if offset := weq.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 := weq.ctx.Limit; limit != nil {
+		selector.Limit(*limit)
+	}
+	return selector
+}
+
+// WorkExperienceGroupBy is the group-by builder for WorkExperience entities.
+type WorkExperienceGroupBy struct {
+	selector
+	build *WorkExperienceQuery
+}
+
+// Aggregate adds the given aggregation functions to the group-by query.
+func (wegb *WorkExperienceGroupBy) Aggregate(fns ...AggregateFunc) *WorkExperienceGroupBy {
+	wegb.fns = append(wegb.fns, fns...)
+	return wegb
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (wegb *WorkExperienceGroupBy) Scan(ctx context.Context, v any) error {
+	ctx = setContextOp(ctx, wegb.build.ctx, "GroupBy")
+	if err := wegb.build.prepareQuery(ctx); err != nil {
+		return err
+	}
+	return scanWithInterceptors[*WorkExperienceQuery, *WorkExperienceGroupBy](ctx, wegb.build, wegb, wegb.build.inters, v)
+}
+
+func (wegb *WorkExperienceGroupBy) sqlScan(ctx context.Context, root *WorkExperienceQuery, v any) error {
+	selector := root.sqlQuery(ctx).Select()
+	aggregation := make([]string, 0, len(wegb.fns))
+	for _, fn := range wegb.fns {
+		aggregation = append(aggregation, fn(selector))
+	}
+	if len(selector.SelectedColumns()) == 0 {
+		columns := make([]string, 0, len(*wegb.flds)+len(wegb.fns))
+		for _, f := range *wegb.flds {
+			columns = append(columns, selector.C(f))
+		}
+		columns = append(columns, aggregation...)
+		selector.Select(columns...)
+	}
+	selector.GroupBy(selector.Columns(*wegb.flds...)...)
+	if err := selector.Err(); err != nil {
+		return err
+	}
+	rows := &sql.Rows{}
+	query, args := selector.Query()
+	if err := wegb.build.driver.Query(ctx, query, args, rows); err != nil {
+		return err
+	}
+	defer rows.Close()
+	return sql.ScanSlice(rows, v)
+}
+
+// WorkExperienceSelect is the builder for selecting fields of WorkExperience entities.
+type WorkExperienceSelect struct {
+	*WorkExperienceQuery
+	selector
+}
+
+// Aggregate adds the given aggregation functions to the selector query.
+func (wes *WorkExperienceSelect) Aggregate(fns ...AggregateFunc) *WorkExperienceSelect {
+	wes.fns = append(wes.fns, fns...)
+	return wes
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (wes *WorkExperienceSelect) Scan(ctx context.Context, v any) error {
+	ctx = setContextOp(ctx, wes.ctx, "Select")
+	if err := wes.prepareQuery(ctx); err != nil {
+		return err
+	}
+	return scanWithInterceptors[*WorkExperienceQuery, *WorkExperienceSelect](ctx, wes.WorkExperienceQuery, wes, wes.inters, v)
+}
+
+func (wes *WorkExperienceSelect) sqlScan(ctx context.Context, root *WorkExperienceQuery, v any) error {
+	selector := root.sqlQuery(ctx)
+	aggregation := make([]string, 0, len(wes.fns))
+	for _, fn := range wes.fns {
+		aggregation = append(aggregation, fn(selector))
+	}
+	switch n := len(*wes.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 := wes.driver.Query(ctx, query, args, rows); err != nil {
+		return err
+	}
+	defer rows.Close()
+	return sql.ScanSlice(rows, v)
+}

+ 597 - 0
ent/workexperience_update.go

@@ -0,0 +1,597 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"time"
+	"wechat-api/ent/employee"
+	"wechat-api/ent/predicate"
+	"wechat-api/ent/workexperience"
+
+	"entgo.io/ent/dialect/sql"
+	"entgo.io/ent/dialect/sql/sqlgraph"
+	"entgo.io/ent/schema/field"
+)
+
+// WorkExperienceUpdate is the builder for updating WorkExperience entities.
+type WorkExperienceUpdate struct {
+	config
+	hooks    []Hook
+	mutation *WorkExperienceMutation
+}
+
+// Where appends a list predicates to the WorkExperienceUpdate builder.
+func (weu *WorkExperienceUpdate) Where(ps ...predicate.WorkExperience) *WorkExperienceUpdate {
+	weu.mutation.Where(ps...)
+	return weu
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (weu *WorkExperienceUpdate) SetUpdatedAt(t time.Time) *WorkExperienceUpdate {
+	weu.mutation.SetUpdatedAt(t)
+	return weu
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (weu *WorkExperienceUpdate) SetDeletedAt(t time.Time) *WorkExperienceUpdate {
+	weu.mutation.SetDeletedAt(t)
+	return weu
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (weu *WorkExperienceUpdate) SetNillableDeletedAt(t *time.Time) *WorkExperienceUpdate {
+	if t != nil {
+		weu.SetDeletedAt(*t)
+	}
+	return weu
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (weu *WorkExperienceUpdate) ClearDeletedAt() *WorkExperienceUpdate {
+	weu.mutation.ClearDeletedAt()
+	return weu
+}
+
+// SetEmployeeID sets the "employee_id" field.
+func (weu *WorkExperienceUpdate) SetEmployeeID(u uint64) *WorkExperienceUpdate {
+	weu.mutation.SetEmployeeID(u)
+	return weu
+}
+
+// SetNillableEmployeeID sets the "employee_id" field if the given value is not nil.
+func (weu *WorkExperienceUpdate) SetNillableEmployeeID(u *uint64) *WorkExperienceUpdate {
+	if u != nil {
+		weu.SetEmployeeID(*u)
+	}
+	return weu
+}
+
+// SetStartDate sets the "start_date" field.
+func (weu *WorkExperienceUpdate) SetStartDate(t time.Time) *WorkExperienceUpdate {
+	weu.mutation.SetStartDate(t)
+	return weu
+}
+
+// SetNillableStartDate sets the "start_date" field if the given value is not nil.
+func (weu *WorkExperienceUpdate) SetNillableStartDate(t *time.Time) *WorkExperienceUpdate {
+	if t != nil {
+		weu.SetStartDate(*t)
+	}
+	return weu
+}
+
+// SetEndDate sets the "end_date" field.
+func (weu *WorkExperienceUpdate) SetEndDate(t time.Time) *WorkExperienceUpdate {
+	weu.mutation.SetEndDate(t)
+	return weu
+}
+
+// SetNillableEndDate sets the "end_date" field if the given value is not nil.
+func (weu *WorkExperienceUpdate) SetNillableEndDate(t *time.Time) *WorkExperienceUpdate {
+	if t != nil {
+		weu.SetEndDate(*t)
+	}
+	return weu
+}
+
+// SetCompany sets the "company" field.
+func (weu *WorkExperienceUpdate) SetCompany(s string) *WorkExperienceUpdate {
+	weu.mutation.SetCompany(s)
+	return weu
+}
+
+// SetNillableCompany sets the "company" field if the given value is not nil.
+func (weu *WorkExperienceUpdate) SetNillableCompany(s *string) *WorkExperienceUpdate {
+	if s != nil {
+		weu.SetCompany(*s)
+	}
+	return weu
+}
+
+// SetExperience sets the "experience" field.
+func (weu *WorkExperienceUpdate) SetExperience(s string) *WorkExperienceUpdate {
+	weu.mutation.SetExperience(s)
+	return weu
+}
+
+// SetNillableExperience sets the "experience" field if the given value is not nil.
+func (weu *WorkExperienceUpdate) SetNillableExperience(s *string) *WorkExperienceUpdate {
+	if s != nil {
+		weu.SetExperience(*s)
+	}
+	return weu
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (weu *WorkExperienceUpdate) SetOrganizationID(u uint64) *WorkExperienceUpdate {
+	weu.mutation.ResetOrganizationID()
+	weu.mutation.SetOrganizationID(u)
+	return weu
+}
+
+// SetNillableOrganizationID sets the "organization_id" field if the given value is not nil.
+func (weu *WorkExperienceUpdate) SetNillableOrganizationID(u *uint64) *WorkExperienceUpdate {
+	if u != nil {
+		weu.SetOrganizationID(*u)
+	}
+	return weu
+}
+
+// AddOrganizationID adds u to the "organization_id" field.
+func (weu *WorkExperienceUpdate) AddOrganizationID(u int64) *WorkExperienceUpdate {
+	weu.mutation.AddOrganizationID(u)
+	return weu
+}
+
+// SetEmployee sets the "employee" edge to the Employee entity.
+func (weu *WorkExperienceUpdate) SetEmployee(e *Employee) *WorkExperienceUpdate {
+	return weu.SetEmployeeID(e.ID)
+}
+
+// Mutation returns the WorkExperienceMutation object of the builder.
+func (weu *WorkExperienceUpdate) Mutation() *WorkExperienceMutation {
+	return weu.mutation
+}
+
+// ClearEmployee clears the "employee" edge to the Employee entity.
+func (weu *WorkExperienceUpdate) ClearEmployee() *WorkExperienceUpdate {
+	weu.mutation.ClearEmployee()
+	return weu
+}
+
+// Save executes the query and returns the number of nodes affected by the update operation.
+func (weu *WorkExperienceUpdate) Save(ctx context.Context) (int, error) {
+	if err := weu.defaults(); err != nil {
+		return 0, err
+	}
+	return withHooks(ctx, weu.sqlSave, weu.mutation, weu.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (weu *WorkExperienceUpdate) SaveX(ctx context.Context) int {
+	affected, err := weu.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return affected
+}
+
+// Exec executes the query.
+func (weu *WorkExperienceUpdate) Exec(ctx context.Context) error {
+	_, err := weu.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (weu *WorkExperienceUpdate) ExecX(ctx context.Context) {
+	if err := weu.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (weu *WorkExperienceUpdate) defaults() error {
+	if _, ok := weu.mutation.UpdatedAt(); !ok {
+		if workexperience.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized workexperience.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := workexperience.UpdateDefaultUpdatedAt()
+		weu.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (weu *WorkExperienceUpdate) check() error {
+	if _, ok := weu.mutation.EmployeeID(); weu.mutation.EmployeeCleared() && !ok {
+		return errors.New(`ent: clearing a required unique edge "WorkExperience.employee"`)
+	}
+	return nil
+}
+
+func (weu *WorkExperienceUpdate) sqlSave(ctx context.Context) (n int, err error) {
+	if err := weu.check(); err != nil {
+		return n, err
+	}
+	_spec := sqlgraph.NewUpdateSpec(workexperience.Table, workexperience.Columns, sqlgraph.NewFieldSpec(workexperience.FieldID, field.TypeUint64))
+	if ps := weu.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := weu.mutation.UpdatedAt(); ok {
+		_spec.SetField(workexperience.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := weu.mutation.DeletedAt(); ok {
+		_spec.SetField(workexperience.FieldDeletedAt, field.TypeTime, value)
+	}
+	if weu.mutation.DeletedAtCleared() {
+		_spec.ClearField(workexperience.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := weu.mutation.StartDate(); ok {
+		_spec.SetField(workexperience.FieldStartDate, field.TypeTime, value)
+	}
+	if value, ok := weu.mutation.EndDate(); ok {
+		_spec.SetField(workexperience.FieldEndDate, field.TypeTime, value)
+	}
+	if value, ok := weu.mutation.Company(); ok {
+		_spec.SetField(workexperience.FieldCompany, field.TypeString, value)
+	}
+	if value, ok := weu.mutation.Experience(); ok {
+		_spec.SetField(workexperience.FieldExperience, field.TypeString, value)
+	}
+	if value, ok := weu.mutation.OrganizationID(); ok {
+		_spec.SetField(workexperience.FieldOrganizationID, field.TypeUint64, value)
+	}
+	if value, ok := weu.mutation.AddedOrganizationID(); ok {
+		_spec.AddField(workexperience.FieldOrganizationID, field.TypeUint64, value)
+	}
+	if weu.mutation.EmployeeCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   workexperience.EmployeeTable,
+			Columns: []string{workexperience.EmployeeColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(employee.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := weu.mutation.EmployeeIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   workexperience.EmployeeTable,
+			Columns: []string{workexperience.EmployeeColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(employee.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
+	if n, err = sqlgraph.UpdateNodes(ctx, weu.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{workexperience.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return 0, err
+	}
+	weu.mutation.done = true
+	return n, nil
+}
+
+// WorkExperienceUpdateOne is the builder for updating a single WorkExperience entity.
+type WorkExperienceUpdateOne struct {
+	config
+	fields   []string
+	hooks    []Hook
+	mutation *WorkExperienceMutation
+}
+
+// SetUpdatedAt sets the "updated_at" field.
+func (weuo *WorkExperienceUpdateOne) SetUpdatedAt(t time.Time) *WorkExperienceUpdateOne {
+	weuo.mutation.SetUpdatedAt(t)
+	return weuo
+}
+
+// SetDeletedAt sets the "deleted_at" field.
+func (weuo *WorkExperienceUpdateOne) SetDeletedAt(t time.Time) *WorkExperienceUpdateOne {
+	weuo.mutation.SetDeletedAt(t)
+	return weuo
+}
+
+// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil.
+func (weuo *WorkExperienceUpdateOne) SetNillableDeletedAt(t *time.Time) *WorkExperienceUpdateOne {
+	if t != nil {
+		weuo.SetDeletedAt(*t)
+	}
+	return weuo
+}
+
+// ClearDeletedAt clears the value of the "deleted_at" field.
+func (weuo *WorkExperienceUpdateOne) ClearDeletedAt() *WorkExperienceUpdateOne {
+	weuo.mutation.ClearDeletedAt()
+	return weuo
+}
+
+// SetEmployeeID sets the "employee_id" field.
+func (weuo *WorkExperienceUpdateOne) SetEmployeeID(u uint64) *WorkExperienceUpdateOne {
+	weuo.mutation.SetEmployeeID(u)
+	return weuo
+}
+
+// SetNillableEmployeeID sets the "employee_id" field if the given value is not nil.
+func (weuo *WorkExperienceUpdateOne) SetNillableEmployeeID(u *uint64) *WorkExperienceUpdateOne {
+	if u != nil {
+		weuo.SetEmployeeID(*u)
+	}
+	return weuo
+}
+
+// SetStartDate sets the "start_date" field.
+func (weuo *WorkExperienceUpdateOne) SetStartDate(t time.Time) *WorkExperienceUpdateOne {
+	weuo.mutation.SetStartDate(t)
+	return weuo
+}
+
+// SetNillableStartDate sets the "start_date" field if the given value is not nil.
+func (weuo *WorkExperienceUpdateOne) SetNillableStartDate(t *time.Time) *WorkExperienceUpdateOne {
+	if t != nil {
+		weuo.SetStartDate(*t)
+	}
+	return weuo
+}
+
+// SetEndDate sets the "end_date" field.
+func (weuo *WorkExperienceUpdateOne) SetEndDate(t time.Time) *WorkExperienceUpdateOne {
+	weuo.mutation.SetEndDate(t)
+	return weuo
+}
+
+// SetNillableEndDate sets the "end_date" field if the given value is not nil.
+func (weuo *WorkExperienceUpdateOne) SetNillableEndDate(t *time.Time) *WorkExperienceUpdateOne {
+	if t != nil {
+		weuo.SetEndDate(*t)
+	}
+	return weuo
+}
+
+// SetCompany sets the "company" field.
+func (weuo *WorkExperienceUpdateOne) SetCompany(s string) *WorkExperienceUpdateOne {
+	weuo.mutation.SetCompany(s)
+	return weuo
+}
+
+// SetNillableCompany sets the "company" field if the given value is not nil.
+func (weuo *WorkExperienceUpdateOne) SetNillableCompany(s *string) *WorkExperienceUpdateOne {
+	if s != nil {
+		weuo.SetCompany(*s)
+	}
+	return weuo
+}
+
+// SetExperience sets the "experience" field.
+func (weuo *WorkExperienceUpdateOne) SetExperience(s string) *WorkExperienceUpdateOne {
+	weuo.mutation.SetExperience(s)
+	return weuo
+}
+
+// SetNillableExperience sets the "experience" field if the given value is not nil.
+func (weuo *WorkExperienceUpdateOne) SetNillableExperience(s *string) *WorkExperienceUpdateOne {
+	if s != nil {
+		weuo.SetExperience(*s)
+	}
+	return weuo
+}
+
+// SetOrganizationID sets the "organization_id" field.
+func (weuo *WorkExperienceUpdateOne) SetOrganizationID(u uint64) *WorkExperienceUpdateOne {
+	weuo.mutation.ResetOrganizationID()
+	weuo.mutation.SetOrganizationID(u)
+	return weuo
+}
+
+// SetNillableOrganizationID sets the "organization_id" field if the given value is not nil.
+func (weuo *WorkExperienceUpdateOne) SetNillableOrganizationID(u *uint64) *WorkExperienceUpdateOne {
+	if u != nil {
+		weuo.SetOrganizationID(*u)
+	}
+	return weuo
+}
+
+// AddOrganizationID adds u to the "organization_id" field.
+func (weuo *WorkExperienceUpdateOne) AddOrganizationID(u int64) *WorkExperienceUpdateOne {
+	weuo.mutation.AddOrganizationID(u)
+	return weuo
+}
+
+// SetEmployee sets the "employee" edge to the Employee entity.
+func (weuo *WorkExperienceUpdateOne) SetEmployee(e *Employee) *WorkExperienceUpdateOne {
+	return weuo.SetEmployeeID(e.ID)
+}
+
+// Mutation returns the WorkExperienceMutation object of the builder.
+func (weuo *WorkExperienceUpdateOne) Mutation() *WorkExperienceMutation {
+	return weuo.mutation
+}
+
+// ClearEmployee clears the "employee" edge to the Employee entity.
+func (weuo *WorkExperienceUpdateOne) ClearEmployee() *WorkExperienceUpdateOne {
+	weuo.mutation.ClearEmployee()
+	return weuo
+}
+
+// Where appends a list predicates to the WorkExperienceUpdate builder.
+func (weuo *WorkExperienceUpdateOne) Where(ps ...predicate.WorkExperience) *WorkExperienceUpdateOne {
+	weuo.mutation.Where(ps...)
+	return weuo
+}
+
+// Select allows selecting one or more fields (columns) of the returned entity.
+// The default is selecting all fields defined in the entity schema.
+func (weuo *WorkExperienceUpdateOne) Select(field string, fields ...string) *WorkExperienceUpdateOne {
+	weuo.fields = append([]string{field}, fields...)
+	return weuo
+}
+
+// Save executes the query and returns the updated WorkExperience entity.
+func (weuo *WorkExperienceUpdateOne) Save(ctx context.Context) (*WorkExperience, error) {
+	if err := weuo.defaults(); err != nil {
+		return nil, err
+	}
+	return withHooks(ctx, weuo.sqlSave, weuo.mutation, weuo.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (weuo *WorkExperienceUpdateOne) SaveX(ctx context.Context) *WorkExperience {
+	node, err := weuo.Save(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return node
+}
+
+// Exec executes the query on the entity.
+func (weuo *WorkExperienceUpdateOne) Exec(ctx context.Context) error {
+	_, err := weuo.Save(ctx)
+	return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (weuo *WorkExperienceUpdateOne) ExecX(ctx context.Context) {
+	if err := weuo.Exec(ctx); err != nil {
+		panic(err)
+	}
+}
+
+// defaults sets the default values of the builder before save.
+func (weuo *WorkExperienceUpdateOne) defaults() error {
+	if _, ok := weuo.mutation.UpdatedAt(); !ok {
+		if workexperience.UpdateDefaultUpdatedAt == nil {
+			return fmt.Errorf("ent: uninitialized workexperience.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)")
+		}
+		v := workexperience.UpdateDefaultUpdatedAt()
+		weuo.mutation.SetUpdatedAt(v)
+	}
+	return nil
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (weuo *WorkExperienceUpdateOne) check() error {
+	if _, ok := weuo.mutation.EmployeeID(); weuo.mutation.EmployeeCleared() && !ok {
+		return errors.New(`ent: clearing a required unique edge "WorkExperience.employee"`)
+	}
+	return nil
+}
+
+func (weuo *WorkExperienceUpdateOne) sqlSave(ctx context.Context) (_node *WorkExperience, err error) {
+	if err := weuo.check(); err != nil {
+		return _node, err
+	}
+	_spec := sqlgraph.NewUpdateSpec(workexperience.Table, workexperience.Columns, sqlgraph.NewFieldSpec(workexperience.FieldID, field.TypeUint64))
+	id, ok := weuo.mutation.ID()
+	if !ok {
+		return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "WorkExperience.id" for update`)}
+	}
+	_spec.Node.ID.Value = id
+	if fields := weuo.fields; len(fields) > 0 {
+		_spec.Node.Columns = make([]string, 0, len(fields))
+		_spec.Node.Columns = append(_spec.Node.Columns, workexperience.FieldID)
+		for _, f := range fields {
+			if !workexperience.ValidColumn(f) {
+				return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+			}
+			if f != workexperience.FieldID {
+				_spec.Node.Columns = append(_spec.Node.Columns, f)
+			}
+		}
+	}
+	if ps := weuo.mutation.predicates; len(ps) > 0 {
+		_spec.Predicate = func(selector *sql.Selector) {
+			for i := range ps {
+				ps[i](selector)
+			}
+		}
+	}
+	if value, ok := weuo.mutation.UpdatedAt(); ok {
+		_spec.SetField(workexperience.FieldUpdatedAt, field.TypeTime, value)
+	}
+	if value, ok := weuo.mutation.DeletedAt(); ok {
+		_spec.SetField(workexperience.FieldDeletedAt, field.TypeTime, value)
+	}
+	if weuo.mutation.DeletedAtCleared() {
+		_spec.ClearField(workexperience.FieldDeletedAt, field.TypeTime)
+	}
+	if value, ok := weuo.mutation.StartDate(); ok {
+		_spec.SetField(workexperience.FieldStartDate, field.TypeTime, value)
+	}
+	if value, ok := weuo.mutation.EndDate(); ok {
+		_spec.SetField(workexperience.FieldEndDate, field.TypeTime, value)
+	}
+	if value, ok := weuo.mutation.Company(); ok {
+		_spec.SetField(workexperience.FieldCompany, field.TypeString, value)
+	}
+	if value, ok := weuo.mutation.Experience(); ok {
+		_spec.SetField(workexperience.FieldExperience, field.TypeString, value)
+	}
+	if value, ok := weuo.mutation.OrganizationID(); ok {
+		_spec.SetField(workexperience.FieldOrganizationID, field.TypeUint64, value)
+	}
+	if value, ok := weuo.mutation.AddedOrganizationID(); ok {
+		_spec.AddField(workexperience.FieldOrganizationID, field.TypeUint64, value)
+	}
+	if weuo.mutation.EmployeeCleared() {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   workexperience.EmployeeTable,
+			Columns: []string{workexperience.EmployeeColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(employee.FieldID, field.TypeUint64),
+			},
+		}
+		_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+	}
+	if nodes := weuo.mutation.EmployeeIDs(); len(nodes) > 0 {
+		edge := &sqlgraph.EdgeSpec{
+			Rel:     sqlgraph.M2O,
+			Inverse: true,
+			Table:   workexperience.EmployeeTable,
+			Columns: []string{workexperience.EmployeeColumn},
+			Bidi:    false,
+			Target: &sqlgraph.EdgeTarget{
+				IDSpec: sqlgraph.NewFieldSpec(employee.FieldID, field.TypeUint64),
+			},
+		}
+		for _, k := range nodes {
+			edge.Target.Nodes = append(edge.Target.Nodes, k)
+		}
+		_spec.Edges.Add = append(_spec.Edges.Add, edge)
+	}
+	_node = &WorkExperience{config: weuo.config}
+	_spec.Assign = _node.assignValues
+	_spec.ScanValues = _node.scanValues
+	if err = sqlgraph.UpdateNode(ctx, weuo.driver, _spec); err != nil {
+		if _, ok := err.(*sqlgraph.NotFoundError); ok {
+			err = &NotFoundError{workexperience.Label}
+		} else if sqlgraph.IsConstraintError(err) {
+			err = &ConstraintError{msg: err.Error(), wrap: err}
+		}
+		return nil, err
+	}
+	weuo.mutation.done = true
+	return _node, nil
+}

+ 44 - 0
internal/handler/employee/create_employee_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 /employee/create employee CreateEmployee
+//
+// Create employee information | 创建Employee
+//
+// Create employee information | 创建Employee
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: EmployeeInfo
+//
+// Responses:
+//  200: BaseMsgResp
+
+func CreateEmployeeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.EmployeeInfo
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := employee.NewCreateEmployeeLogic(r.Context(), svcCtx)
+		resp, err := l.CreateEmployee(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/employee/delete_employee_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 /employee/delete employee DeleteEmployee
+//
+// Delete employee information | 删除Employee信息
+//
+// Delete employee information | 删除Employee信息
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: IDsReq
+//
+// Responses:
+//  200: BaseMsgResp
+
+func DeleteEmployeeHandler(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 := employee.NewDeleteEmployeeLogic(r.Context(), svcCtx)
+		resp, err := l.DeleteEmployee(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/employee/get_employee_by_id_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 /employee employee GetEmployeeById
+//
+// 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 GetEmployeeByIdHandler(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.NewGetEmployeeByIdLogic(r.Context(), svcCtx)
+		resp, err := l.GetEmployeeById(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/employee/get_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 /employee/list employee GetEmployeeList
+//
+// Get employee list | 获取Employee列表
+//
+// Get employee list | 获取Employee列表
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: EmployeeListReq
+//
+// Responses:
+//  200: EmployeeListResp
+
+func GetEmployeeListHandler(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.NewGetEmployeeListLogic(r.Context(), svcCtx)
+		resp, err := l.GetEmployeeList(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/employee/update_employee_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 /employee/update employee UpdateEmployee
+//
+// Update employee information | 更新Employee
+//
+// Update employee information | 更新Employee
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: EmployeeInfo
+//
+// Responses:
+//  200: BaseMsgResp
+
+func UpdateEmployeeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.EmployeeInfo
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := employee.NewUpdateEmployeeLogic(r.Context(), svcCtx)
+		resp, err := l.UpdateEmployee(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 105 - 0
internal/handler/routes.go

@@ -14,6 +14,7 @@ import (
 	base "wechat-api/internal/handler/base"
 	batch_msg "wechat-api/internal/handler/batch_msg"
 	contact "wechat-api/internal/handler/contact"
+	employee "wechat-api/internal/handler/employee"
 	label "wechat-api/internal/handler/label"
 	label_relationship "wechat-api/internal/handler/label_relationship"
 	message_records "wechat-api/internal/handler/message_records"
@@ -21,6 +22,8 @@ import (
 	sop_node "wechat-api/internal/handler/sop_node"
 	sop_stage "wechat-api/internal/handler/sop_stage"
 	sop_task "wechat-api/internal/handler/sop_task"
+	tutorial "wechat-api/internal/handler/tutorial"
+	work_experience "wechat-api/internal/handler/work_experience"
 	"wechat-api/internal/svc"
 
 	"github.com/zeromicro/go-zero/rest"
@@ -592,4 +595,106 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 		),
 		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
 	)
+
+	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Authority},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/employee/create",
+					Handler: employee.CreateEmployeeHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/employee/update",
+					Handler: employee.UpdateEmployeeHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/employee/delete",
+					Handler: employee.DeleteEmployeeHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/employee/list",
+					Handler: employee.GetEmployeeListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/employee",
+					Handler: employee.GetEmployeeByIdHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
+
+	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Authority},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/work_experience/create",
+					Handler: work_experience.CreateWorkExperienceHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/work_experience/update",
+					Handler: work_experience.UpdateWorkExperienceHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/work_experience/delete",
+					Handler: work_experience.DeleteWorkExperienceHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/work_experience/list",
+					Handler: work_experience.GetWorkExperienceListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/work_experience",
+					Handler: work_experience.GetWorkExperienceByIdHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
+
+	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Authority},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/tutorial/create",
+					Handler: tutorial.CreateTutorialHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/tutorial/update",
+					Handler: tutorial.UpdateTutorialHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/tutorial/delete",
+					Handler: tutorial.DeleteTutorialHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/tutorial/list",
+					Handler: tutorial.GetTutorialListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/tutorial",
+					Handler: tutorial.GetTutorialByIdHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
 }

+ 44 - 0
internal/handler/tutorial/create_tutorial_handler.go

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

+ 44 - 0
internal/handler/tutorial/delete_tutorial_handler.go

@@ -0,0 +1,44 @@
+package tutorial
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/tutorial"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /tutorial/delete tutorial DeleteTutorial
+//
+// Delete tutorial information | 删除Tutorial信息
+//
+// Delete tutorial information | 删除Tutorial信息
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: IDsReq
+//
+// Responses:
+//  200: BaseMsgResp
+
+func DeleteTutorialHandler(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 := tutorial.NewDeleteTutorialLogic(r.Context(), svcCtx)
+		resp, err := l.DeleteTutorial(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/tutorial/get_tutorial_by_id_handler.go

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

+ 44 - 0
internal/handler/tutorial/get_tutorial_list_handler.go

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

+ 44 - 0
internal/handler/tutorial/update_tutorial_handler.go

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

+ 44 - 0
internal/handler/work_experience/create_work_experience_handler.go

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

+ 44 - 0
internal/handler/work_experience/delete_work_experience_handler.go

@@ -0,0 +1,44 @@
+package work_experience
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/work_experience"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /work_experience/delete work_experience DeleteWorkExperience
+//
+// Delete work experience information | 删除WorkExperience信息
+//
+// Delete work experience information | 删除WorkExperience信息
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: IDsReq
+//
+// Responses:
+//  200: BaseMsgResp
+
+func DeleteWorkExperienceHandler(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 := work_experience.NewDeleteWorkExperienceLogic(r.Context(), svcCtx)
+		resp, err := l.DeleteWorkExperience(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/work_experience/get_work_experience_by_id_handler.go

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

+ 44 - 0
internal/handler/work_experience/get_work_experience_list_handler.go

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

+ 44 - 0
internal/handler/work_experience/update_work_experience_handler.go

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

+ 186 - 0
internal/logic/base/init_api_data.go

@@ -6,6 +6,192 @@ import (
 )
 
 func (l *InitDatabaseLogic) insertApiData() (err error) {
+	// Tutorial
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/tutorial/create"),
+		Description: pointy.GetPointer("apiDesc.createTutorial"),
+		ApiGroup:    pointy.GetPointer("tutorial"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/tutorial/update"),
+		Description: pointy.GetPointer("apiDesc.updateTutorial"),
+		ApiGroup:    pointy.GetPointer("tutorial"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/tutorial/delete"),
+		Description: pointy.GetPointer("apiDesc.deleteTutorial"),
+		ApiGroup:    pointy.GetPointer("tutorial"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/tutorial/list"),
+		Description: pointy.GetPointer("apiDesc.getTutorialList"),
+		ApiGroup:    pointy.GetPointer("tutorial"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/tutorial"),
+		Description: pointy.GetPointer("apiDesc.getTutorialById"),
+		ApiGroup:    pointy.GetPointer("tutorial"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
+	// WorkExperience
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/work_experience/create"),
+		Description: pointy.GetPointer("apiDesc.createWorkExperience"),
+		ApiGroup:    pointy.GetPointer("work_experience"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/work_experience/update"),
+		Description: pointy.GetPointer("apiDesc.updateWorkExperience"),
+		ApiGroup:    pointy.GetPointer("work_experience"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/work_experience/delete"),
+		Description: pointy.GetPointer("apiDesc.deleteWorkExperience"),
+		ApiGroup:    pointy.GetPointer("work_experience"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/work_experience/list"),
+		Description: pointy.GetPointer("apiDesc.getWorkExperienceList"),
+		ApiGroup:    pointy.GetPointer("work_experience"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/work_experience"),
+		Description: pointy.GetPointer("apiDesc.getWorkExperienceById"),
+		ApiGroup:    pointy.GetPointer("work_experience"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
+	// Employee
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/employee/create"),
+		Description: pointy.GetPointer("apiDesc.createEmployee"),
+		ApiGroup:    pointy.GetPointer("employee"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/employee/update"),
+		Description: pointy.GetPointer("apiDesc.updateEmployee"),
+		ApiGroup:    pointy.GetPointer("employee"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/employee/delete"),
+		Description: pointy.GetPointer("apiDesc.deleteEmployee"),
+		ApiGroup:    pointy.GetPointer("employee"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/employee/list"),
+		Description: pointy.GetPointer("apiDesc.getEmployeeList"),
+		ApiGroup:    pointy.GetPointer("employee"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
+	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{
+		ServiceName: pointy.GetPointer("Wechat"),
+		Path:        pointy.GetPointer("/employee"),
+		Description: pointy.GetPointer("apiDesc.getEmployeeById"),
+		ApiGroup:    pointy.GetPointer("employee"),
+		Method:      pointy.GetPointer("POST"),
+	})
+
+	if err != nil {
+		return err
+	}
+
 	// Agent
 
 	_, err = l.svcCtx.CoreRpc.CreateApi(l.ctx, &core.ApiInfo{

+ 114 - 0
internal/logic/employee/create_employee_logic.go

@@ -0,0 +1,114 @@
+package employee
+
+import (
+	"context"
+	"time"
+	"wechat-api/ent"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type CreateEmployeeLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewCreateEmployeeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateEmployeeLogic {
+	return &CreateEmployeeLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *CreateEmployeeLogic) CreateEmployee(req *types.EmployeeInfo) (*types.BaseMsgResp, error) {
+	organizationId := l.ctx.Value("organizationId").(uint64)
+
+	// 开始事务
+	tx, err := l.svcCtx.DB.Tx(context.Background())
+
+	employee, err := tx.Employee.Create().
+		SetNotNilTitle(req.Title).
+		SetNotNilAvatar(req.Avatar).
+		SetNotNilTags(req.Tags).
+		SetNotNilHireCount(req.HireCount).
+		SetNotNilServiceCount(req.ServiceCount).
+		SetNotNilAchievementCount(req.AchievementCount).
+		SetNotNilIntro(req.Intro).
+		SetNotNilEstimate(req.Estimate).
+		SetNotNilSkill(req.Skill).
+		SetNotNilAbilityType(req.AbilityType).
+		SetNotNilScene(req.Scene).
+		SetNotNilSwitchIn(req.SwitchIn).
+		SetNotNilVideoURL(req.VideoUrl).
+		SetNotNilOrganizationID(&organizationId).
+		Save(l.ctx)
+
+	if err != nil {
+		_ = tx.Rollback()
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	// 批量插入工作经历
+	if len(req.WorkExperience) > 0 {
+		bulkCreateWork := make([]*ent.WorkExperienceCreate, 0, len(req.WorkExperience))
+		for _, work := range req.WorkExperience {
+			var startDate, endDate *time.Time
+			startDateStr, _ := time.Parse("2006-01-02 15:04:05", *work.StartDateStr)
+
+			startDate = &startDateStr
+			if work.EndDateStr != nil && *work.EndDateStr != "" {
+				endDateStr, _ := time.Parse("2006-01-02 15:04:05", *work.EndDateStr)
+				endDate = &endDateStr
+			}
+
+			bulkCreateWork = append(bulkCreateWork, tx.WorkExperience.Create().
+				SetNotNilEmployeeID(&employee.ID).
+				SetNotNilStartDate(startDate).
+				SetNotNilEndDate(endDate).
+				SetNotNilCompany(work.Company).
+				SetNotNilOrganizationID(&organizationId).
+				SetNotNilExperience(work.Experience),
+			)
+		}
+
+		if len(bulkCreateWork) > 0 {
+			err = tx.WorkExperience.CreateBulk(bulkCreateWork...).Exec(l.ctx)
+			if err != nil {
+				_ = tx.Rollback()
+				return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+			}
+		}
+	}
+
+	// 批量插入使用教程
+	if len(req.Tutorial) > 0 {
+		bulkCreateTutorial := make([]*ent.TutorialCreate, 0, len(req.Tutorial))
+		for _, work := range req.Tutorial {
+			bulkCreateTutorial = append(bulkCreateTutorial, tx.Tutorial.Create().
+				SetNotNilEmployeeID(&employee.ID).
+				SetNotNilOrganizationID(&organizationId).
+				SetNotNilIndex(work.Index).
+				SetNotNilTitle(work.Title).
+				SetNotNilContent(work.Content),
+			)
+		}
+		if len(bulkCreateTutorial) > 0 {
+			err = tx.Tutorial.CreateBulk(bulkCreateTutorial...).Exec(l.ctx)
+			if err != nil {
+				_ = tx.Rollback()
+				return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+			}
+		}
+	}
+
+	_ = tx.Commit()
+
+	return &types.BaseMsgResp{Msg: errormsg.CreateSuccess}, nil
+}

+ 38 - 0
internal/logic/employee/delete_employee_logic.go

@@ -0,0 +1,38 @@
+package employee
+
+import (
+	"context"
+
+	"wechat-api/ent/employee"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type DeleteEmployeeLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewDeleteEmployeeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteEmployeeLogic {
+	return &DeleteEmployeeLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *DeleteEmployeeLogic) DeleteEmployee(req *types.IDsReq) (*types.BaseMsgResp, error) {
+	organizationId := l.ctx.Value("organizationId").(uint64)
+	_, err := l.svcCtx.DB.Employee.Delete().Where(employee.IDIn(req.Ids...), employee.OrganizationIDEQ(organizationId)).Exec(l.ctx)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	return &types.BaseMsgResp{Msg: errormsg.DeleteSuccess}, nil
+}

+ 100 - 0
internal/logic/employee/get_employee_by_id_logic.go

@@ -0,0 +1,100 @@
+package employee
+
+import (
+	"context"
+	"wechat-api/ent/employee"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+
+	"github.com/suyuan32/simple-admin-common/utils/pointy"
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetEmployeeByIdLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewGetEmployeeByIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetEmployeeByIdLogic {
+	return &GetEmployeeByIdLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *GetEmployeeByIdLogic) GetEmployeeById(req *types.IDReq) (*types.EmployeeInfoResp, error) {
+	organizationId := l.ctx.Value("organizationId").(uint64)
+
+	data, err := l.svcCtx.DB.Employee.Query().WithEmWorkExperiences().WithEmTutorial().Where(employee.ID(req.Id), employee.OrganizationIDEQ(organizationId)).Only(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	workExperience := make([]types.WorkExperienceInfo, 0)
+	for _, work := range data.Edges.EmWorkExperiences {
+		workExperience = append(workExperience, types.WorkExperienceInfo{
+			BaseIDInfo: types.BaseIDInfo{
+				Id:        &work.ID,
+				CreatedAt: pointy.GetPointer(work.CreatedAt.UnixMilli()),
+				UpdatedAt: pointy.GetPointer(work.UpdatedAt.UnixMilli()),
+			},
+			EmployeeId:   &work.EmployeeID,
+			Company:      &work.Company,
+			StartDate:    pointy.GetPointer(work.StartDate.UnixMilli()),
+			StartDateStr: pointy.GetPointer(work.StartDate.Format("2006-01-02 15:04:05")),
+			EndDate:      pointy.GetPointer(work.EndDate.UnixMilli()),
+			EndDateStr:   pointy.GetPointer(work.EndDate.Format("2006-01-02 15:04:05")),
+			Experience:   &work.Experience,
+		})
+	}
+
+	tutorial := make([]types.TutorialInfo, 0)
+	for _, tt := range data.Edges.EmTutorial {
+		tutorial = append(tutorial, types.TutorialInfo{
+			BaseIDInfo: types.BaseIDInfo{
+				Id:        &tt.ID,
+				CreatedAt: pointy.GetPointer(tt.CreatedAt.UnixMilli()),
+				UpdatedAt: pointy.GetPointer(tt.UpdatedAt.UnixMilli()),
+			},
+			EmployeeId: &tt.EmployeeID,
+			Content:    &tt.Content,
+			Title:      &tt.Title,
+			Index:      &tt.Index,
+		})
+	}
+
+	return &types.EmployeeInfoResp{
+		BaseDataInfo: types.BaseDataInfo{
+			Code: 0,
+			Msg:  errormsg.Success,
+		},
+		Data: types.EmployeeInfo{
+			BaseIDInfo: types.BaseIDInfo{
+				Id:        &data.ID,
+				CreatedAt: pointy.GetPointer(data.CreatedAt.UnixMilli()),
+				UpdatedAt: pointy.GetPointer(data.UpdatedAt.UnixMilli()),
+			},
+			Title:            &data.Title,
+			Avatar:           &data.Avatar,
+			Tags:             &data.Tags,
+			HireCount:        &data.HireCount,
+			ServiceCount:     &data.ServiceCount,
+			AchievementCount: &data.AchievementCount,
+			Intro:            &data.Intro,
+			Estimate:         &data.Estimate,
+			Skill:            &data.Skill,
+			AbilityType:      &data.AbilityType,
+			Scene:            &data.Scene,
+			Tutorial:         tutorial,
+			SwitchIn:         &data.SwitchIn,
+			VideoUrl:         &data.VideoURL,
+			WorkExperience:   workExperience,
+		},
+	}, nil
+}

+ 114 - 0
internal/logic/employee/get_employee_list_logic.go

@@ -0,0 +1,114 @@
+package employee
+
+import (
+	"context"
+
+	"wechat-api/ent/employee"
+	"wechat-api/ent/predicate"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+
+	"github.com/suyuan32/simple-admin-common/utils/pointy"
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetEmployeeListLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewGetEmployeeListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetEmployeeListLogic {
+	return &GetEmployeeListLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *GetEmployeeListLogic) GetEmployeeList(req *types.EmployeeListReq) (*types.EmployeeListResp, error) {
+	organizationId := l.ctx.Value("organizationId").(uint64)
+
+	var predicates []predicate.Employee
+	predicates = append(predicates, employee.OrganizationIDEQ(organizationId))
+
+	if req.Title != nil {
+		predicates = append(predicates, employee.TitleContains(*req.Title))
+	}
+	//if req.Tags != nil {
+	//	predicates = append(predicates, employee.TagsContains(*req.Tags))
+	//}
+	data, err := l.svcCtx.DB.Employee.Query().Where(predicates...).WithEmWorkExperiences().WithEmTutorial().Page(l.ctx, req.Page, req.PageSize)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	resp := &types.EmployeeListResp{}
+	resp.Msg = errormsg.Success
+	resp.Data.Total = data.PageDetails.Total
+
+	for _, v := range data.List {
+		workExperience := make([]types.WorkExperienceInfo, 0)
+		for _, work := range v.Edges.EmWorkExperiences {
+			workExperience = append(workExperience, types.WorkExperienceInfo{
+				BaseIDInfo: types.BaseIDInfo{
+					Id:        &work.ID,
+					CreatedAt: pointy.GetPointer(work.CreatedAt.UnixMilli()),
+					UpdatedAt: pointy.GetPointer(work.UpdatedAt.UnixMilli()),
+				},
+				EmployeeId:   &work.EmployeeID,
+				Company:      &work.Company,
+				StartDate:    pointy.GetPointer(work.StartDate.UnixMilli()),
+				StartDateStr: pointy.GetPointer(work.StartDate.Format("2006-01-02 15:04:05")),
+				EndDate:      pointy.GetPointer(work.EndDate.UnixMilli()),
+				EndDateStr:   pointy.GetPointer(work.EndDate.Format("2006-01-02 15:04:05")),
+				Experience:   &work.Experience,
+			})
+		}
+
+		tutorial := make([]types.TutorialInfo, 0)
+		for _, tt := range v.Edges.EmTutorial {
+			tutorial = append(tutorial, types.TutorialInfo{
+				BaseIDInfo: types.BaseIDInfo{
+					Id:        &tt.ID,
+					CreatedAt: pointy.GetPointer(tt.CreatedAt.UnixMilli()),
+					UpdatedAt: pointy.GetPointer(tt.UpdatedAt.UnixMilli()),
+				},
+				EmployeeId: &tt.EmployeeID,
+				Content:    &tt.Content,
+				Title:      &tt.Title,
+				Index:      &tt.Index,
+			})
+		}
+
+		resp.Data.Data = append(resp.Data.Data,
+			types.EmployeeInfo{
+				BaseIDInfo: types.BaseIDInfo{
+					Id:        &v.ID,
+					CreatedAt: pointy.GetPointer(v.CreatedAt.UnixMilli()),
+					UpdatedAt: pointy.GetPointer(v.UpdatedAt.UnixMilli()),
+				},
+				Title:            &v.Title,
+				Avatar:           &v.Avatar,
+				Tags:             &v.Tags,
+				HireCount:        &v.HireCount,
+				ServiceCount:     &v.ServiceCount,
+				AchievementCount: &v.AchievementCount,
+				Intro:            &v.Intro,
+				Estimate:         &v.Estimate,
+				Skill:            &v.Skill,
+				AbilityType:      &v.AbilityType,
+				Scene:            &v.Scene,
+				SwitchIn:         &v.SwitchIn,
+				Tutorial:         tutorial,
+				VideoUrl:         &v.VideoURL,
+				WorkExperience:   workExperience,
+			})
+	}
+
+	return resp, nil
+}

+ 98 - 0
internal/logic/employee/update_employee_logic.go

@@ -0,0 +1,98 @@
+package employee
+
+import (
+	"context"
+	"time"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type UpdateEmployeeLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewUpdateEmployeeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateEmployeeLogic {
+	return &UpdateEmployeeLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *UpdateEmployeeLogic) UpdateEmployee(req *types.EmployeeInfo) (*types.BaseMsgResp, error) {
+	// 开始事务
+	tx, err := l.svcCtx.DB.Tx(context.Background())
+
+	_, err = tx.Employee.UpdateOneID(*req.Id).
+		SetNotNilTitle(req.Title).
+		SetNotNilAvatar(req.Avatar).
+		SetNotNilTags(req.Tags).
+		SetNotNilHireCount(req.HireCount).
+		SetNotNilServiceCount(req.ServiceCount).
+		SetNotNilAchievementCount(req.AchievementCount).
+		SetNotNilIntro(req.Intro).
+		SetNotNilEstimate(req.Estimate).
+		SetNotNilSkill(req.Skill).
+		SetNotNilAbilityType(req.AbilityType).
+		SetNotNilScene(req.Scene).
+		SetNotNilSwitchIn(req.SwitchIn).
+		SetNotNilVideoURL(req.VideoUrl).
+		Save(l.ctx)
+
+	if err != nil {
+		_ = tx.Rollback()
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	// 批量修改工作经历
+	if len(req.WorkExperience) > 0 {
+		for _, work := range req.WorkExperience {
+			var startDate, endDate *time.Time
+			startDateStr, _ := time.Parse("2006-01-02 15:04:05", *work.StartDateStr)
+
+			startDate = &startDateStr
+			if work.EndDateStr != nil && *work.EndDateStr != "" {
+				endDateStr, _ := time.Parse("2006-01-02 15:04:05", *work.EndDateStr)
+				endDate = &endDateStr
+			}
+
+			_, err = tx.WorkExperience.UpdateOneID(*work.Id).
+				SetNotNilStartDate(startDate).
+				SetNotNilEndDate(endDate).
+				SetNotNilCompany(work.Company).
+				SetNotNilExperience(work.Experience).
+				Save(l.ctx)
+
+			if err != nil {
+				_ = tx.Rollback()
+				return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+			}
+		}
+	}
+
+	// 批量修改使用教程
+	if len(req.Tutorial) > 0 {
+		for _, tt := range req.Tutorial {
+			_, err = tx.Tutorial.UpdateOneID(*tt.Id).
+				SetNotNilIndex(tt.Index).
+				SetNotNilTitle(tt.Title).
+				SetNotNilContent(tt.Content).
+				Save(l.ctx)
+
+			if err != nil {
+				_ = tx.Rollback()
+				return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+			}
+		}
+	}
+
+	_ = tx.Commit()
+
+	return &types.BaseMsgResp{Msg: errormsg.UpdateSuccess}, nil
+}

+ 42 - 0
internal/logic/tutorial/create_tutorial_logic.go

@@ -0,0 +1,42 @@
+package tutorial
+
+import (
+	"context"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type CreateTutorialLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewCreateTutorialLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateTutorialLogic {
+	return &CreateTutorialLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *CreateTutorialLogic) CreateTutorial(req *types.TutorialInfo) (*types.BaseMsgResp, error) {
+	_, err := l.svcCtx.DB.Tutorial.Create().
+		SetNotNilEmployeeID(req.EmployeeId).
+		SetNotNilIndex(req.Index).
+		SetNotNilTitle(req.Title).
+		SetNotNilContent(req.Content).
+		Save(l.ctx)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	return &types.BaseMsgResp{Msg: errormsg.CreateSuccess}, nil
+}

+ 37 - 0
internal/logic/tutorial/delete_tutorial_logic.go

@@ -0,0 +1,37 @@
+package tutorial
+
+import (
+	"context"
+
+    "wechat-api/ent/tutorial"
+    "wechat-api/internal/svc"
+    "wechat-api/internal/types"
+    "wechat-api/internal/utils/dberrorhandler"
+
+    "github.com/suyuan32/simple-admin-common/msg/errormsg"
+    "github.com/zeromicro/go-zero/core/logx"
+)
+
+type DeleteTutorialLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewDeleteTutorialLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteTutorialLogic {
+	return &DeleteTutorialLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *DeleteTutorialLogic) DeleteTutorial(req *types.IDsReq) (*types.BaseMsgResp, error) {
+	_, err := l.svcCtx.DB.Tutorial.Delete().Where(tutorial.IDIn(req.Ids...)).Exec(l.ctx)
+
+    if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+    return &types.BaseMsgResp{Msg: errormsg.DeleteSuccess}, nil
+}

+ 53 - 0
internal/logic/tutorial/get_tutorial_by_id_logic.go

@@ -0,0 +1,53 @@
+package tutorial
+
+import (
+	"context"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+
+	"github.com/suyuan32/simple-admin-common/utils/pointy"
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetTutorialByIdLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewGetTutorialByIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetTutorialByIdLogic {
+	return &GetTutorialByIdLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *GetTutorialByIdLogic) GetTutorialById(req *types.IDReq) (*types.TutorialInfoResp, error) {
+	data, err := l.svcCtx.DB.Tutorial.Get(l.ctx, req.Id)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	return &types.TutorialInfoResp{
+		BaseDataInfo: types.BaseDataInfo{
+			Code: 0,
+			Msg:  errormsg.Success,
+		},
+		Data: types.TutorialInfo{
+			BaseIDInfo: types.BaseIDInfo{
+				Id:        &data.ID,
+				CreatedAt: pointy.GetPointer(data.CreatedAt.UnixMilli()),
+				UpdatedAt: pointy.GetPointer(data.UpdatedAt.UnixMilli()),
+			},
+			EmployeeId: &data.EmployeeID,
+			Index:      &data.Index,
+			Title:      &data.Title,
+			Content:    &data.Content,
+		},
+	}, nil
+}

+ 66 - 0
internal/logic/tutorial/get_tutorial_list_logic.go

@@ -0,0 +1,66 @@
+package tutorial
+
+import (
+	"context"
+
+	"wechat-api/ent/predicate"
+	"wechat-api/ent/tutorial"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+
+	"github.com/suyuan32/simple-admin-common/utils/pointy"
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetTutorialListLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewGetTutorialListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetTutorialListLogic {
+	return &GetTutorialListLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *GetTutorialListLogic) GetTutorialList(req *types.TutorialListReq) (*types.TutorialListResp, error) {
+	var predicates []predicate.Tutorial
+	if req.Title != nil {
+		predicates = append(predicates, tutorial.TitleContains(*req.Title))
+	}
+	if req.Content != nil {
+		predicates = append(predicates, tutorial.ContentContains(*req.Content))
+	}
+	data, err := l.svcCtx.DB.Tutorial.Query().Where(predicates...).Page(l.ctx, req.Page, req.PageSize)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	resp := &types.TutorialListResp{}
+	resp.Msg = errormsg.Success
+	resp.Data.Total = data.PageDetails.Total
+
+	for _, v := range data.List {
+		resp.Data.Data = append(resp.Data.Data,
+			types.TutorialInfo{
+				BaseIDInfo: types.BaseIDInfo{
+					Id:        &v.ID,
+					CreatedAt: pointy.GetPointer(v.CreatedAt.UnixMilli()),
+					UpdatedAt: pointy.GetPointer(v.UpdatedAt.UnixMilli()),
+				},
+				EmployeeId: &v.EmployeeID,
+				Index:      &v.Index,
+				Title:      &v.Title,
+				Content:    &v.Content,
+			})
+	}
+
+	return resp, nil
+}

+ 41 - 0
internal/logic/tutorial/update_tutorial_logic.go

@@ -0,0 +1,41 @@
+package tutorial
+
+import (
+	"context"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type UpdateTutorialLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewUpdateTutorialLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateTutorialLogic {
+	return &UpdateTutorialLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *UpdateTutorialLogic) UpdateTutorial(req *types.TutorialInfo) (*types.BaseMsgResp, error) {
+	err := l.svcCtx.DB.Tutorial.UpdateOneID(*req.Id).
+		SetNotNilEmployeeID(req.EmployeeId).
+		SetNotNilIndex(req.Index).
+		SetNotNilTitle(req.Title).
+		SetNotNilContent(req.Content).
+		Exec(l.ctx)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	return &types.BaseMsgResp{Msg: errormsg.UpdateSuccess}, nil
+}

+ 49 - 0
internal/logic/work_experience/create_work_experience_logic.go

@@ -0,0 +1,49 @@
+package work_experience
+
+import (
+	"context"
+	"time"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type CreateWorkExperienceLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewCreateWorkExperienceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateWorkExperienceLogic {
+	return &CreateWorkExperienceLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *CreateWorkExperienceLogic) CreateWorkExperience(req *types.WorkExperienceInfo) (*types.BaseMsgResp, error) {
+	var startDate, endDate *time.Time
+	*startDate, _ = time.Parse("2006-01-02 15:04:05", *req.StartDateStr)
+	if req.EndDateStr != nil && *req.EndDateStr != "" {
+		*endDate, _ = time.Parse("2006-01-02 15:04:05", *req.EndDateStr)
+	}
+
+	_, err := l.svcCtx.DB.WorkExperience.Create().
+		SetNotNilEmployeeID(req.EmployeeId).
+		SetNotNilStartDate(startDate).
+		SetNotNilEndDate(endDate).
+		SetNotNilCompany(req.Company).
+		SetNotNilExperience(req.Experience).
+		Save(l.ctx)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	return &types.BaseMsgResp{Msg: errormsg.CreateSuccess}, nil
+}

+ 37 - 0
internal/logic/work_experience/delete_work_experience_logic.go

@@ -0,0 +1,37 @@
+package work_experience
+
+import (
+	"context"
+
+    "wechat-api/ent/workexperience"
+    "wechat-api/internal/svc"
+    "wechat-api/internal/types"
+    "wechat-api/internal/utils/dberrorhandler"
+
+    "github.com/suyuan32/simple-admin-common/msg/errormsg"
+    "github.com/zeromicro/go-zero/core/logx"
+)
+
+type DeleteWorkExperienceLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewDeleteWorkExperienceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteWorkExperienceLogic {
+	return &DeleteWorkExperienceLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *DeleteWorkExperienceLogic) DeleteWorkExperience(req *types.IDsReq) (*types.BaseMsgResp, error) {
+	_, err := l.svcCtx.DB.WorkExperience.Delete().Where(workexperience.IDIn(req.Ids...)).Exec(l.ctx)
+
+    if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+    return &types.BaseMsgResp{Msg: errormsg.DeleteSuccess}, nil
+}

+ 55 - 0
internal/logic/work_experience/get_work_experience_by_id_logic.go

@@ -0,0 +1,55 @@
+package work_experience
+
+import (
+	"context"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+    "github.com/suyuan32/simple-admin-common/msg/errormsg"
+
+	"github.com/suyuan32/simple-admin-common/utils/pointy"
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetWorkExperienceByIdLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewGetWorkExperienceByIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetWorkExperienceByIdLogic {
+	return &GetWorkExperienceByIdLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *GetWorkExperienceByIdLogic) GetWorkExperienceById(req *types.IDReq) (*types.WorkExperienceInfoResp, error) {
+	data, err := l.svcCtx.DB.WorkExperience.Get(l.ctx, req.Id)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	return &types.WorkExperienceInfoResp{
+	    BaseDataInfo: types.BaseDataInfo{
+            Code: 0,
+            Msg:  errormsg.Success,
+        },
+        Data: types.WorkExperienceInfo{
+            BaseIDInfo:    types.BaseIDInfo{
+				Id:          &data.ID,
+				CreatedAt:    pointy.GetPointer(data.CreatedAt.UnixMilli()),
+				UpdatedAt:    pointy.GetPointer(data.UpdatedAt.UnixMilli()),
+            },
+			EmployeeId:	&data.EmployeeID,
+			StartDate:	pointy.GetPointer(data.StartDate.UnixMilli()),
+			EndDate:	pointy.GetPointer(data.EndDate.UnixMilli()),
+			Company:	&data.Company,
+			Experience:	&data.Experience,
+        },
+	}, nil
+}
+

+ 64 - 0
internal/logic/work_experience/get_work_experience_list_logic.go

@@ -0,0 +1,64 @@
+package work_experience
+
+import (
+	"context"
+
+	"wechat-api/ent/predicate"
+	"wechat-api/ent/workexperience"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+
+	"github.com/suyuan32/simple-admin-common/utils/pointy"
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetWorkExperienceListLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewGetWorkExperienceListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetWorkExperienceListLogic {
+	return &GetWorkExperienceListLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *GetWorkExperienceListLogic) GetWorkExperienceList(req *types.WorkExperienceListReq) (*types.WorkExperienceListResp, error) {
+	var predicates []predicate.WorkExperience
+	if req.Company != nil {
+		predicates = append(predicates, workexperience.CompanyContains(*req.Company))
+	}
+	data, err := l.svcCtx.DB.WorkExperience.Query().Where(predicates...).Page(l.ctx, req.Page, req.PageSize)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	resp := &types.WorkExperienceListResp{}
+	resp.Msg = errormsg.Success
+	resp.Data.Total = data.PageDetails.Total
+
+	for _, v := range data.List {
+		resp.Data.Data = append(resp.Data.Data,
+			types.WorkExperienceInfo{
+				BaseIDInfo: types.BaseIDInfo{
+					Id:        &v.ID,
+					CreatedAt: pointy.GetPointer(v.CreatedAt.UnixMilli()),
+					UpdatedAt: pointy.GetPointer(v.UpdatedAt.UnixMilli()),
+				},
+				EmployeeId: &v.EmployeeID,
+				StartDate:  pointy.GetPointer(v.StartDate.UnixMilli()),
+				EndDate:    pointy.GetPointer(v.EndDate.UnixMilli()),
+				Company:    &v.Company,
+				Experience: &v.Experience,
+			})
+	}
+
+	return resp, nil
+}

+ 49 - 0
internal/logic/work_experience/update_work_experience_logic.go

@@ -0,0 +1,49 @@
+package work_experience
+
+import (
+	"context"
+	"time"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type UpdateWorkExperienceLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewUpdateWorkExperienceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateWorkExperienceLogic {
+	return &UpdateWorkExperienceLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *UpdateWorkExperienceLogic) UpdateWorkExperience(req *types.WorkExperienceInfo) (*types.BaseMsgResp, error) {
+	var startDate, endDate *time.Time
+	*startDate, _ = time.Parse("2006-01-02 15:04:05", *req.StartDateStr)
+	if req.EndDateStr != nil && *req.EndDateStr != "" {
+		*endDate, _ = time.Parse("2006-01-02 15:04:05", *req.EndDateStr)
+	}
+
+	err := l.svcCtx.DB.WorkExperience.UpdateOneID(*req.Id).
+		SetNotNilEmployeeID(req.EmployeeId).
+		SetNotNilStartDate(startDate).
+		SetNotNilEndDate(endDate).
+		SetNotNilCompany(req.Company).
+		SetNotNilExperience(req.Experience).
+		Exec(l.ctx)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	return &types.BaseMsgResp{Msg: errormsg.UpdateSuccess}, nil
+}

+ 167 - 0
internal/types/types.go

@@ -1281,3 +1281,170 @@ type BatchMsgInfoResp struct {
 	// BatchMsg information | BatchMsg数据
 	Data BatchMsgInfo `json:"data"`
 }
+
+// The data of employee information | Employee信息
+// swagger:model EmployeeInfo
+type EmployeeInfo struct {
+	BaseIDInfo
+	// title | 标题
+	Title *string `json:"title,optional"`
+	// avatar | 头像
+	Avatar *string `json:"avatar,optional"`
+	// tags | 个人标签
+	Tags *string `json:"tags,optional"`
+	// hire_count | 被雇佣次数
+	HireCount *int `json:"hireCount,optional"`
+	// service_count | 已服务次数
+	ServiceCount *int `json:"serviceCount,optional"`
+	// achievement_count | 业绩单数
+	AchievementCount *int `json:"achievementCount,optional"`
+	// intro | 个人介绍
+	Intro *string `json:"intro,optional"`
+	// estimate | 自我评价
+	Estimate *string `json:"estimate,optional"`
+	// skill | 技能卡
+	Skill *string `json:"skill,optional"`
+	// ability_type | 能力类型
+	AbilityType *string `json:"abilityType,optional"`
+	// scene | 使用场景
+	Scene *string `json:"scene,optional"`
+	// switch_in | 支持介入
+	SwitchIn *string        `json:"switchIn,optional"`
+	Tutorial []TutorialInfo `json:"tutorial,optional"`
+	// video_url | 视频地址
+	VideoUrl *string `json:"videoUrl,optional"`
+	// work_experience | 工作经验
+	WorkExperience []WorkExperienceInfo `json:"workExperience,optional"`
+}
+
+// The response data of employee list | Employee列表数据
+// swagger:model EmployeeListResp
+type EmployeeListResp struct {
+	BaseDataInfo
+	// Employee list data | Employee列表数据
+	Data EmployeeListInfo `json:"data"`
+}
+
+// Employee list data | Employee列表数据
+// swagger:model EmployeeListInfo
+type EmployeeListInfo struct {
+	BaseListInfo
+	// The API list data | Employee列表数据
+	Data []EmployeeInfo `json:"data"`
+}
+
+// Get employee list request params | Employee列表请求参数
+// swagger:model EmployeeListReq
+type EmployeeListReq struct {
+	PageInfo
+	// title | 标题
+	Title *string `json:"title,optional"`
+	// tags | 个人标签
+	Tags *string `json:"tags,optional"`
+}
+
+// Employee information response | Employee信息返回体
+// swagger:model EmployeeInfoResp
+type EmployeeInfoResp struct {
+	BaseDataInfo
+	// Employee information | Employee数据
+	Data EmployeeInfo `json:"data"`
+}
+
+// The data of work experience information | WorkExperience信息
+// swagger:model WorkExperienceInfo
+type WorkExperienceInfo struct {
+	BaseIDInfo
+	// employee_id | 员工ID
+	EmployeeId *uint64 `json:"employeeId,optional"`
+	// start_date | 开始时间
+	StartDate    *int64  `json:"startDate,optional"`
+	StartDateStr *string `json:"startDateStr,optional"`
+	// end_date | 结束时间
+	EndDate    *int64  `json:"endDate,optional"`
+	EndDateStr *string `json:"endDateStr,optional"`
+	// company | 公司名
+	Company *string `json:"company,optional"`
+	// experience | 工作内容
+	Experience *string `json:"experience,optional"`
+}
+
+// The response data of work experience list | WorkExperience列表数据
+// swagger:model WorkExperienceListResp
+type WorkExperienceListResp struct {
+	BaseDataInfo
+	// WorkExperience list data | WorkExperience列表数据
+	Data WorkExperienceListInfo `json:"data"`
+}
+
+// WorkExperience list data | WorkExperience列表数据
+// swagger:model WorkExperienceListInfo
+type WorkExperienceListInfo struct {
+	BaseListInfo
+	// The API list data | WorkExperience列表数据
+	Data []WorkExperienceInfo `json:"data"`
+}
+
+// Get work experience list request params | WorkExperience列表请求参数
+// swagger:model WorkExperienceListReq
+type WorkExperienceListReq struct {
+	PageInfo
+	// company | 公司名
+	Company *string `json:"company,optional"`
+}
+
+// WorkExperience information response | WorkExperience信息返回体
+// swagger:model WorkExperienceInfoResp
+type WorkExperienceInfoResp struct {
+	BaseDataInfo
+	// WorkExperience information | WorkExperience数据
+	Data WorkExperienceInfo `json:"data"`
+}
+
+// The data of tutorial information | Tutorial信息
+// swagger:model TutorialInfo
+type TutorialInfo struct {
+	BaseIDInfo
+	// employee_id | 员工ID
+	EmployeeId *uint64 `json:"employeeId,optional"`
+	// index | 序号
+	Index *int `json:"index,optional"`
+	// title | 标题
+	Title *string `json:"title,optional"`
+	// content | 内容
+	Content *string `json:"content,optional"`
+}
+
+// The response data of tutorial list | Tutorial列表数据
+// swagger:model TutorialListResp
+type TutorialListResp struct {
+	BaseDataInfo
+	// Tutorial list data | Tutorial列表数据
+	Data TutorialListInfo `json:"data"`
+}
+
+// Tutorial list data | Tutorial列表数据
+// swagger:model TutorialListInfo
+type TutorialListInfo struct {
+	BaseListInfo
+	// The API list data | Tutorial列表数据
+	Data []TutorialInfo `json:"data"`
+}
+
+// Get tutorial list request params | Tutorial列表请求参数
+// swagger:model TutorialListReq
+type TutorialListReq struct {
+	PageInfo
+	// title | 标题
+	Title *string `json:"title,optional"`
+	// content | 内容
+	Content *string `json:"content,optional"`
+}
+
+// Tutorial information response | Tutorial信息返回体
+// swagger:model TutorialInfoResp
+type TutorialInfoResp struct {
+	BaseDataInfo
+	// Tutorial information | Tutorial数据
+	Data TutorialInfo `json:"data"`
+}

Some files were not shown because too many files changed in this diff