Browse Source

增加 sop 任务、阶段、节点基础接口

boweniac 9 months ago
parent
commit
ac20e4a98a
38 changed files with 1282 additions and 296 deletions
  1. 1 1
      desc/base.api
  2. 2 30
      desc/wechat/sop_node.api
  3. 84 1
      desc/wechat/sop_stage.api
  4. 5 26
      desc/wechat/sop_task.api
  5. 2 2
      ent/custom_types/types.go
  6. 7 7
      ent/migrate/schema.go
  7. 144 24
      ent/mutation.go
  8. 4 4
      ent/schema/sop_node.go
  9. 3 3
      ent/schema/sop_stage.go
  10. 6 6
      ent/set_not_nil.go
  11. 3 3
      ent/sopnode.go
  12. 39 9
      ent/sopnode/where.go
  13. 74 23
      ent/sopnode_create.go
  14. 84 30
      ent/sopnode_update.go
  15. 30 0
      ent/sopstage/where.go
  16. 60 9
      ent/sopstage_create.go
  17. 54 0
      ent/sopstage_update.go
  18. 15 0
      internal/handler/routes.go
  19. 1 1
      internal/handler/sop_node/delete_sop_node_handler.go
  20. 2 2
      internal/handler/sop_stage/delete_sop_stage_handler.go
  21. 44 0
      internal/handler/sop_stage/get_sop_stage_detail_handler.go
  22. 44 0
      internal/handler/sop_stage/move_sop_stage_handler.go
  23. 44 0
      internal/handler/sop_task/get_sop_task_detail_handler.go
  24. 14 9
      internal/logic/sop_node/create_sop_node_logic.go
  25. 75 10
      internal/logic/sop_node/delete_sop_node_logic.go
  26. 1 9
      internal/logic/sop_node/get_sop_node_by_id_logic.go
  27. 1 9
      internal/logic/sop_node/get_sop_node_list_logic.go
  28. 18 8
      internal/logic/sop_node/update_sop_node_logic.go
  29. 17 2
      internal/logic/sop_stage/create_sop_stage_logic.go
  30. 55 10
      internal/logic/sop_stage/delete_sop_stage_logic.go
  31. 21 2
      internal/logic/sop_stage/get_sop_stage_by_id_logic.go
  32. 76 0
      internal/logic/sop_stage/get_sop_stage_detail_logic.go
  33. 83 0
      internal/logic/sop_stage/move_sop_stage_logic.go
  34. 15 1
      internal/logic/sop_stage/update_sop_stage_logic.go
  35. 18 0
      internal/logic/sop_task/get_sop_task_by_id_logic.go
  36. 58 0
      internal/logic/sop_task/get_sop_task_detail_logic.go
  37. 21 14
      internal/logic/sop_task/update_sop_task_logic.go
  38. 57 41
      internal/types/types.go

+ 1 - 1
desc/base.api

@@ -208,7 +208,7 @@ type BaseUUIDInfo {
 
 type Condition struct {
 	Equal       int   `json:"equal"`
-	LabelIdList []int `json:"labelIdList"`
+	LabelIdList []uint64 `json:"labelIdList"`
 }
 
 type Action struct {

+ 2 - 30
desc/wechat/sop_node.api

@@ -1,35 +1,7 @@
 import "../base.api"
+import "./sop_stage.api"
 
 type (
-    // The response data of sop node information | SopNode信息
-    SopNodeInfo {
-        BaseIDInfo
-
-        // Status 1: normal 2: ban | 状态 1 正常 2 禁用 
-        Status  *uint8 `json:"status,optional"`
-
-        // 阶段 ID 
-        StageId  *uint64 `json:"stageId,optional"`
-
-        // 父节点 ID 
-        ParentId  *int `json:"parentId,optional"`
-
-        // 节点名称 
-        Name  *string `json:"name,optional"`
-
-        // 触发条件类型 1 客户回复后触发 2 超时后触发 
-        ConditionType  *int `json:"conditionType,optional"`
-
-        // 触发语义列表 当为空时则代表用户回复任意内容后触发 
-        ConditionList  []Condition `json:"conditionList,optional"`
-
-        // 命中后发送的消息内容 
-        ActionMessage  []Action `json:"actionMessage,optional"`
-
-        // 命中后需要打的标签 
-        ActionLabel  []int `json:"actionLabel,optional"`
-    }
-
     // The response data of sop node list | SopNode列表数据
     SopNodeListResp {
         BaseDataInfo
@@ -80,7 +52,7 @@ service Wechat {
 
     // Delete sop node information | 删除SopNode信息
     @handler deleteSopNode
-    post /sop_node/delete (IDsReq) returns (BaseMsgResp)
+    post /sop_node/delete (IDReq) returns (BaseMsgResp)
 
     // Get sop node list | 获取SopNode列表
     @handler getSopNodeList

+ 84 - 1
desc/wechat/sop_stage.api

@@ -31,6 +31,73 @@ type (
 
         // 阶段顺序 
         IndexSort  *int `json:"indexSort,optional"`
+
+        // sop 任务信息
+        TaskInfo  *SopTaskInfo `json:"taskInfo,optional"`
+
+        // node 信息
+        NodeList  []SopNodeInfo `json:"nodeList,optional"`
+    }
+
+    // The response data of sop task information | SopTask信息
+    SopTaskInfo {
+        BaseIDInfo
+
+        // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+        Status  *uint8 `json:"status,optional"`
+
+        // SOP 任务名称
+        Name  *string `json:"name,optional"`
+
+        // 机器人微信 id 列表
+        BotWxidList  []string `json:"botWxidList,optional"`
+
+        // 标签类型:1好友,2群组,3企业微信联系人
+        Type  *int `json:"type,optional"`
+
+        // 任务计划开始时间
+        PlanStartTime  *int64 `json:"planStartTime,optional"`
+
+        // 任务计划结束时间
+        PlanEndTime  *int64 `json:"planEndTime,optional"`
+
+        // 创建者 id
+        CreatorId  *string `json:"creatorId,optional"`
+
+        // 阶段信息
+        StageList  []SopStageInfo `json:"stageList,optional"`
+    }
+
+    // The response data of sop node information | SopNode信息
+    SopNodeInfo {
+        BaseIDInfo
+
+        // Status 1: normal 2: ban | 状态 1 正常 2 禁用
+        Status  *uint8 `json:"status,optional"`
+
+        // 阶段 ID
+        StageId  *uint64 `json:"stageId,optional"`
+
+        // 父节点 ID
+        ParentId  *uint64 `json:"parentId,optional"`
+
+        // 节点名称
+        Name  *string `json:"name,optional"`
+
+        // 触发条件类型 1 客户回复后触发 2 超时后触发
+        ConditionType  *int `json:"conditionType,optional"`
+
+        // 触发语义列表 当为空时则代表用户回复任意内容后触发
+        ConditionList  []string `json:"conditionList,optional"`
+
+        // 命中后发送的消息内容
+        ActionMessage  []Action `json:"actionMessage,optional"`
+
+        // 命中后需要打的标签
+        ActionLabel  []int `json:"actionLabel,optional"`
+
+        // 阶段信息
+        StageInfo  *SopStageInfo `json:"stageInfo,optional"`
     }
 
     // The response data of sop stage list | SopStage列表数据
@@ -64,6 +131,14 @@ type (
         // SopStage information | SopStage数据
         Data SopStageInfo `json:"data"`
     }
+
+    // Move sop stage request params | 移动阶段请求参数
+    SopStageMoveReq {
+        BaseIDInfo
+
+        // 阶段名称
+        Offset  *int `json:"offset,optional"`
+    }
 )
 
 @server(
@@ -83,7 +158,7 @@ service Wechat {
 
     // Delete sop stage information | 删除SopStage信息
     @handler deleteSopStage
-    post /sop_stage/delete (IDsReq) returns (BaseMsgResp)
+    post /sop_stage/delete (IDReq) returns (BaseMsgResp)
 
     // Get sop stage list | 获取SopStage列表
     @handler getSopStageList
@@ -92,4 +167,12 @@ service Wechat {
     // Get sop stage by ID | 通过ID获取SopStage
     @handler getSopStageById
     post /sop_stage (IDReq) returns (SopStageInfoResp)
+
+    // Get sop stage by ID | 通过ID获取SopStage细节
+    @handler getSopStageDetail
+    post /sop_stage/detail (IDReq) returns (SopStageInfoResp)
+
+    // Get sop stage move | 移动阶段顺序
+    @handler moveSopStage
+    post /sop_stage/move (SopStageMoveReq) returns (BaseMsgResp)
 }

+ 5 - 26
desc/wechat/sop_task.api

@@ -1,32 +1,7 @@
 import "../base.api"
+import "./sop_stage.api"
 
 type (
-    // The response data of sop task information | SopTask信息
-    SopTaskInfo {
-        BaseIDInfo
-
-        // Status 1: normal 2: ban | 状态 1 正常 2 禁用 
-        Status  *uint8 `json:"status,optional"`
-
-        // SOP 任务名称 
-        Name  *string `json:"name,optional"`
-
-        // 机器人微信 id 列表 
-        BotWxidList  []string `json:"botWxidList,optional"`
-
-        // 标签类型:1好友,2群组,3企业微信联系人 
-        Type  *int `json:"type,optional"`
-
-        // 任务计划开始时间 
-        PlanStartTime  *int64 `json:"planStartTime,optional"`
-
-        // 任务计划结束时间 
-        PlanEndTime  *int64 `json:"planEndTime,optional"`
-
-        // 创建者 id 
-        CreatorId  *string `json:"creatorId,optional"`
-    }
-
     // The response data of sop task list | SopTask列表数据
     SopTaskListResp {
         BaseDataInfo
@@ -89,4 +64,8 @@ service Wechat {
     // Get sop task by ID | 通过ID获取SopTask
     @handler getSopTaskById
     post /sop_task (IDReq) returns (SopTaskInfoResp)
+
+    // Get sop task by ID | 通过ID获取SopTask细节
+    @handler getSopTaskDetail
+    post /sop_task/detail (IDReq) returns (SopTaskInfoResp)
 }

+ 2 - 2
ent/custom_types/types.go

@@ -1,8 +1,8 @@
 package custom_types
 
 type Condition struct {
-	Equal       int   `json:"equal"`
-	LabelIdList []int `json:"labelIdList"`
+	Equal       int      `json:"equal"`
+	LabelIdList []uint64 `json:"labelIdList"`
 }
 
 type Action struct {

+ 7 - 7
ent/migrate/schema.go

@@ -215,12 +215,12 @@ var (
 		{Name: "updated_at", Type: field.TypeTime, Comment: "Update Time | 修改日期"},
 		{Name: "status", Type: field.TypeUint8, Nullable: true, Comment: "Status 1: normal 2: ban | 状态 1 正常 2 禁用", Default: 1},
 		{Name: "deleted_at", Type: field.TypeTime, Nullable: true, Comment: "Delete Time | 删除日期"},
-		{Name: "parent_id", Type: field.TypeInt, Comment: "父节点 ID"},
+		{Name: "parent_id", Type: field.TypeUint64, Comment: "父节点 ID"},
 		{Name: "name", Type: field.TypeString, Comment: "节点名称", Default: ""},
 		{Name: "condition_type", Type: field.TypeInt, Comment: "触发条件类型 1 客户回复后触发 2 超时后触发", Default: 1},
-		{Name: "condition_list", Type: field.TypeJSON, Comment: "触发语义列表 当为空时则代表用户回复任意内容后触发"},
-		{Name: "action_message", Type: field.TypeJSON, Comment: "命中后发送的消息内容"},
-		{Name: "action_label", Type: field.TypeJSON, Comment: "命中后需要打的标签"},
+		{Name: "condition_list", Type: field.TypeJSON, Nullable: true, Comment: "触发语义列表 当为空时则代表用户回复任意内容后触发"},
+		{Name: "action_message", Type: field.TypeJSON, Nullable: true, Comment: "命中后发送的消息内容"},
+		{Name: "action_label", Type: field.TypeJSON, Nullable: true, Comment: "命中后需要打的标签"},
 		{Name: "stage_id", Type: field.TypeUint64, Comment: "阶段 ID"},
 	}
 	// SopNodeTable holds the schema information for the "sop_node" table.
@@ -255,9 +255,9 @@ var (
 		{Name: "condition_type", Type: field.TypeInt, Comment: "客群筛选条件类型  1 按标签筛选 2 按客户基本信息筛选", Default: 1},
 		{Name: "condition_operator", Type: field.TypeInt, Comment: "筛选条件关系  1 满足所有条件(and) 2 满足任意条件(or)", Default: 1},
 		{Name: "condition_list", Type: field.TypeJSON, Comment: "筛选条件列表"},
-		{Name: "action_message", Type: field.TypeJSON, Comment: "命中后发送的消息内容"},
-		{Name: "action_label", Type: field.TypeJSON, Comment: "命中后需要打的标签"},
-		{Name: "index_sort", Type: field.TypeInt, Comment: "阶段顺序", Default: 1},
+		{Name: "action_message", Type: field.TypeJSON, Nullable: true, Comment: "命中后发送的消息内容"},
+		{Name: "action_label", Type: field.TypeJSON, Nullable: true, Comment: "命中后需要打的标签"},
+		{Name: "index_sort", Type: field.TypeInt, Nullable: true, Comment: "阶段顺序", Default: 1},
 		{Name: "task_id", Type: field.TypeUint64, Comment: "SOP 任务 ID"},
 	}
 	// SopStageTable holds the schema information for the "sop_stage" table.

+ 144 - 24
ent/mutation.go

@@ -6282,13 +6282,13 @@ type SopNodeMutation struct {
 	status               *uint8
 	addstatus            *int8
 	deleted_at           *time.Time
-	parent_id            *int
-	addparent_id         *int
+	parent_id            *uint64
+	addparent_id         *int64
 	name                 *string
 	condition_type       *int
 	addcondition_type    *int
-	condition_list       *[]custom_types.Condition
-	appendcondition_list []custom_types.Condition
+	condition_list       *[]string
+	appendcondition_list []string
 	action_message       *[]custom_types.Action
 	appendaction_message []custom_types.Action
 	action_label         *[]int
@@ -6633,13 +6633,13 @@ func (m *SopNodeMutation) ResetStageID() {
 }
 
 // SetParentID sets the "parent_id" field.
-func (m *SopNodeMutation) SetParentID(i int) {
-	m.parent_id = &i
+func (m *SopNodeMutation) SetParentID(u uint64) {
+	m.parent_id = &u
 	m.addparent_id = nil
 }
 
 // ParentID returns the value of the "parent_id" field in the mutation.
-func (m *SopNodeMutation) ParentID() (r int, exists bool) {
+func (m *SopNodeMutation) ParentID() (r uint64, exists bool) {
 	v := m.parent_id
 	if v == nil {
 		return
@@ -6650,7 +6650,7 @@ func (m *SopNodeMutation) ParentID() (r int, exists bool) {
 // OldParentID returns the old "parent_id" field's value of the SopNode entity.
 // If the SopNode object wasn't provided to the builder, the object is fetched from the database.
 // An error is returned if the mutation operation is not UpdateOne, or the database query fails.
-func (m *SopNodeMutation) OldParentID(ctx context.Context) (v int, err error) {
+func (m *SopNodeMutation) OldParentID(ctx context.Context) (v uint64, err error) {
 	if !m.op.Is(OpUpdateOne) {
 		return v, errors.New("OldParentID is only allowed on UpdateOne operations")
 	}
@@ -6664,17 +6664,17 @@ func (m *SopNodeMutation) OldParentID(ctx context.Context) (v int, err error) {
 	return oldValue.ParentID, nil
 }
 
-// AddParentID adds i to the "parent_id" field.
-func (m *SopNodeMutation) AddParentID(i int) {
+// AddParentID adds u to the "parent_id" field.
+func (m *SopNodeMutation) AddParentID(u int64) {
 	if m.addparent_id != nil {
-		*m.addparent_id += i
+		*m.addparent_id += u
 	} else {
-		m.addparent_id = &i
+		m.addparent_id = &u
 	}
 }
 
 // AddedParentID returns the value that was added to the "parent_id" field in this mutation.
-func (m *SopNodeMutation) AddedParentID() (r int, exists bool) {
+func (m *SopNodeMutation) AddedParentID() (r int64, exists bool) {
 	v := m.addparent_id
 	if v == nil {
 		return
@@ -6781,13 +6781,13 @@ func (m *SopNodeMutation) ResetConditionType() {
 }
 
 // SetConditionList sets the "condition_list" field.
-func (m *SopNodeMutation) SetConditionList(ct []custom_types.Condition) {
-	m.condition_list = &ct
+func (m *SopNodeMutation) SetConditionList(s []string) {
+	m.condition_list = &s
 	m.appendcondition_list = nil
 }
 
 // ConditionList returns the value of the "condition_list" field in the mutation.
-func (m *SopNodeMutation) ConditionList() (r []custom_types.Condition, exists bool) {
+func (m *SopNodeMutation) ConditionList() (r []string, exists bool) {
 	v := m.condition_list
 	if v == nil {
 		return
@@ -6798,7 +6798,7 @@ func (m *SopNodeMutation) ConditionList() (r []custom_types.Condition, exists bo
 // OldConditionList returns the old "condition_list" field's value of the SopNode entity.
 // If the SopNode object wasn't provided to the builder, the object is fetched from the database.
 // An error is returned if the mutation operation is not UpdateOne, or the database query fails.
-func (m *SopNodeMutation) OldConditionList(ctx context.Context) (v []custom_types.Condition, err error) {
+func (m *SopNodeMutation) OldConditionList(ctx context.Context) (v []string, err error) {
 	if !m.op.Is(OpUpdateOne) {
 		return v, errors.New("OldConditionList is only allowed on UpdateOne operations")
 	}
@@ -6812,23 +6812,37 @@ func (m *SopNodeMutation) OldConditionList(ctx context.Context) (v []custom_type
 	return oldValue.ConditionList, nil
 }
 
-// AppendConditionList adds ct to the "condition_list" field.
-func (m *SopNodeMutation) AppendConditionList(ct []custom_types.Condition) {
-	m.appendcondition_list = append(m.appendcondition_list, ct...)
+// AppendConditionList adds s to the "condition_list" field.
+func (m *SopNodeMutation) AppendConditionList(s []string) {
+	m.appendcondition_list = append(m.appendcondition_list, s...)
 }
 
 // AppendedConditionList returns the list of values that were appended to the "condition_list" field in this mutation.
-func (m *SopNodeMutation) AppendedConditionList() ([]custom_types.Condition, bool) {
+func (m *SopNodeMutation) AppendedConditionList() ([]string, bool) {
 	if len(m.appendcondition_list) == 0 {
 		return nil, false
 	}
 	return m.appendcondition_list, true
 }
 
+// ClearConditionList clears the value of the "condition_list" field.
+func (m *SopNodeMutation) ClearConditionList() {
+	m.condition_list = nil
+	m.appendcondition_list = nil
+	m.clearedFields[sopnode.FieldConditionList] = struct{}{}
+}
+
+// ConditionListCleared returns if the "condition_list" field was cleared in this mutation.
+func (m *SopNodeMutation) ConditionListCleared() bool {
+	_, ok := m.clearedFields[sopnode.FieldConditionList]
+	return ok
+}
+
 // ResetConditionList resets all changes to the "condition_list" field.
 func (m *SopNodeMutation) ResetConditionList() {
 	m.condition_list = nil
 	m.appendcondition_list = nil
+	delete(m.clearedFields, sopnode.FieldConditionList)
 }
 
 // SetActionMessage sets the "action_message" field.
@@ -6876,10 +6890,24 @@ func (m *SopNodeMutation) AppendedActionMessage() ([]custom_types.Action, bool)
 	return m.appendaction_message, true
 }
 
+// ClearActionMessage clears the value of the "action_message" field.
+func (m *SopNodeMutation) ClearActionMessage() {
+	m.action_message = nil
+	m.appendaction_message = nil
+	m.clearedFields[sopnode.FieldActionMessage] = struct{}{}
+}
+
+// ActionMessageCleared returns if the "action_message" field was cleared in this mutation.
+func (m *SopNodeMutation) ActionMessageCleared() bool {
+	_, ok := m.clearedFields[sopnode.FieldActionMessage]
+	return ok
+}
+
 // ResetActionMessage resets all changes to the "action_message" field.
 func (m *SopNodeMutation) ResetActionMessage() {
 	m.action_message = nil
 	m.appendaction_message = nil
+	delete(m.clearedFields, sopnode.FieldActionMessage)
 }
 
 // SetActionLabel sets the "action_label" field.
@@ -6927,10 +6955,24 @@ func (m *SopNodeMutation) AppendedActionLabel() ([]int, bool) {
 	return m.appendaction_label, true
 }
 
+// ClearActionLabel clears the value of the "action_label" field.
+func (m *SopNodeMutation) ClearActionLabel() {
+	m.action_label = nil
+	m.appendaction_label = nil
+	m.clearedFields[sopnode.FieldActionLabel] = struct{}{}
+}
+
+// ActionLabelCleared returns if the "action_label" field was cleared in this mutation.
+func (m *SopNodeMutation) ActionLabelCleared() bool {
+	_, ok := m.clearedFields[sopnode.FieldActionLabel]
+	return ok
+}
+
 // ResetActionLabel resets all changes to the "action_label" field.
 func (m *SopNodeMutation) ResetActionLabel() {
 	m.action_label = nil
 	m.appendaction_label = nil
+	delete(m.clearedFields, sopnode.FieldActionLabel)
 }
 
 // SetSopStageID sets the "sop_stage" edge to the SopStage entity by id.
@@ -7147,7 +7189,7 @@ func (m *SopNodeMutation) SetField(name string, value ent.Value) error {
 		m.SetStageID(v)
 		return nil
 	case sopnode.FieldParentID:
-		v, ok := value.(int)
+		v, ok := value.(uint64)
 		if !ok {
 			return fmt.Errorf("unexpected type %T for field %s", value, name)
 		}
@@ -7168,7 +7210,7 @@ func (m *SopNodeMutation) SetField(name string, value ent.Value) error {
 		m.SetConditionType(v)
 		return nil
 	case sopnode.FieldConditionList:
-		v, ok := value.([]custom_types.Condition)
+		v, ok := value.([]string)
 		if !ok {
 			return fmt.Errorf("unexpected type %T for field %s", value, name)
 		}
@@ -7236,7 +7278,7 @@ func (m *SopNodeMutation) AddField(name string, value ent.Value) error {
 		m.AddStatus(v)
 		return nil
 	case sopnode.FieldParentID:
-		v, ok := value.(int)
+		v, ok := value.(int64)
 		if !ok {
 			return fmt.Errorf("unexpected type %T for field %s", value, name)
 		}
@@ -7263,6 +7305,15 @@ func (m *SopNodeMutation) ClearedFields() []string {
 	if m.FieldCleared(sopnode.FieldDeletedAt) {
 		fields = append(fields, sopnode.FieldDeletedAt)
 	}
+	if m.FieldCleared(sopnode.FieldConditionList) {
+		fields = append(fields, sopnode.FieldConditionList)
+	}
+	if m.FieldCleared(sopnode.FieldActionMessage) {
+		fields = append(fields, sopnode.FieldActionMessage)
+	}
+	if m.FieldCleared(sopnode.FieldActionLabel) {
+		fields = append(fields, sopnode.FieldActionLabel)
+	}
 	return fields
 }
 
@@ -7283,6 +7334,15 @@ func (m *SopNodeMutation) ClearField(name string) error {
 	case sopnode.FieldDeletedAt:
 		m.ClearDeletedAt()
 		return nil
+	case sopnode.FieldConditionList:
+		m.ClearConditionList()
+		return nil
+	case sopnode.FieldActionMessage:
+		m.ClearActionMessage()
+		return nil
+	case sopnode.FieldActionLabel:
+		m.ClearActionLabel()
+		return nil
 	}
 	return fmt.Errorf("unknown SopNode nullable field %s", name)
 }
@@ -8012,10 +8072,24 @@ func (m *SopStageMutation) AppendedActionMessage() ([]custom_types.Action, bool)
 	return m.appendaction_message, true
 }
 
+// ClearActionMessage clears the value of the "action_message" field.
+func (m *SopStageMutation) ClearActionMessage() {
+	m.action_message = nil
+	m.appendaction_message = nil
+	m.clearedFields[sopstage.FieldActionMessage] = struct{}{}
+}
+
+// ActionMessageCleared returns if the "action_message" field was cleared in this mutation.
+func (m *SopStageMutation) ActionMessageCleared() bool {
+	_, ok := m.clearedFields[sopstage.FieldActionMessage]
+	return ok
+}
+
 // ResetActionMessage resets all changes to the "action_message" field.
 func (m *SopStageMutation) ResetActionMessage() {
 	m.action_message = nil
 	m.appendaction_message = nil
+	delete(m.clearedFields, sopstage.FieldActionMessage)
 }
 
 // SetActionLabel sets the "action_label" field.
@@ -8063,10 +8137,24 @@ func (m *SopStageMutation) AppendedActionLabel() ([]int, bool) {
 	return m.appendaction_label, true
 }
 
+// ClearActionLabel clears the value of the "action_label" field.
+func (m *SopStageMutation) ClearActionLabel() {
+	m.action_label = nil
+	m.appendaction_label = nil
+	m.clearedFields[sopstage.FieldActionLabel] = struct{}{}
+}
+
+// ActionLabelCleared returns if the "action_label" field was cleared in this mutation.
+func (m *SopStageMutation) ActionLabelCleared() bool {
+	_, ok := m.clearedFields[sopstage.FieldActionLabel]
+	return ok
+}
+
 // ResetActionLabel resets all changes to the "action_label" field.
 func (m *SopStageMutation) ResetActionLabel() {
 	m.action_label = nil
 	m.appendaction_label = nil
+	delete(m.clearedFields, sopstage.FieldActionLabel)
 }
 
 // SetIndexSort sets the "index_sort" field.
@@ -8119,10 +8207,24 @@ func (m *SopStageMutation) AddedIndexSort() (r int, exists bool) {
 	return *v, true
 }
 
+// ClearIndexSort clears the value of the "index_sort" field.
+func (m *SopStageMutation) ClearIndexSort() {
+	m.index_sort = nil
+	m.addindex_sort = nil
+	m.clearedFields[sopstage.FieldIndexSort] = struct{}{}
+}
+
+// IndexSortCleared returns if the "index_sort" field was cleared in this mutation.
+func (m *SopStageMutation) IndexSortCleared() bool {
+	_, ok := m.clearedFields[sopstage.FieldIndexSort]
+	return ok
+}
+
 // ResetIndexSort resets all changes to the "index_sort" field.
 func (m *SopStageMutation) ResetIndexSort() {
 	m.index_sort = nil
 	m.addindex_sort = nil
+	delete(m.clearedFields, sopstage.FieldIndexSort)
 }
 
 // SetSopTaskID sets the "sop_task" edge to the SopTask entity by id.
@@ -8535,6 +8637,15 @@ func (m *SopStageMutation) ClearedFields() []string {
 	if m.FieldCleared(sopstage.FieldDeletedAt) {
 		fields = append(fields, sopstage.FieldDeletedAt)
 	}
+	if m.FieldCleared(sopstage.FieldActionMessage) {
+		fields = append(fields, sopstage.FieldActionMessage)
+	}
+	if m.FieldCleared(sopstage.FieldActionLabel) {
+		fields = append(fields, sopstage.FieldActionLabel)
+	}
+	if m.FieldCleared(sopstage.FieldIndexSort) {
+		fields = append(fields, sopstage.FieldIndexSort)
+	}
 	return fields
 }
 
@@ -8555,6 +8666,15 @@ func (m *SopStageMutation) ClearField(name string) error {
 	case sopstage.FieldDeletedAt:
 		m.ClearDeletedAt()
 		return nil
+	case sopstage.FieldActionMessage:
+		m.ClearActionMessage()
+		return nil
+	case sopstage.FieldActionLabel:
+		m.ClearActionLabel()
+		return nil
+	case sopstage.FieldIndexSort:
+		m.ClearIndexSort()
+		return nil
 	}
 	return fmt.Errorf("unknown SopStage nullable field %s", name)
 }

+ 4 - 4
ent/schema/sop_node.go

@@ -21,7 +21,7 @@ func (SopNode) Fields() []ent.Field {
 		field.Uint64("stage_id").
 			Annotations(entsql.WithComments(true)).
 			Comment("阶段 ID"),
-		field.Int("parent_id").
+		field.Uint64("parent_id").
 			Annotations(entsql.WithComments(true)).
 			Comment("父节点 ID"),
 		field.String("name").Default("").
@@ -30,13 +30,13 @@ func (SopNode) Fields() []ent.Field {
 		field.Int("condition_type").Default(1).
 			Annotations(entsql.WithComments(true)).
 			Comment("触发条件类型 1 客户回复后触发 2 超时后触发"),
-		field.JSON("condition_list", []custom_types.Condition{}).
+		field.JSON("condition_list", []string{}).Optional().
 			Annotations(entsql.WithComments(true)).
 			Comment("触发语义列表 当为空时则代表用户回复任意内容后触发"),
-		field.JSON("action_message", []custom_types.Action{}).
+		field.JSON("action_message", []custom_types.Action{}).Optional().
 			Annotations(entsql.WithComments(true)).
 			Comment("命中后发送的消息内容"),
-		field.JSON("action_label", []int{}).
+		field.JSON("action_label", []int{}).Optional().
 			Annotations(entsql.WithComments(true)).
 			Comment("命中后需要打的标签"),
 	}

+ 3 - 3
ent/schema/sop_stage.go

@@ -33,13 +33,13 @@ func (SopStage) Fields() []ent.Field {
 		field.JSON("condition_list", []custom_types.Condition{}).
 			Annotations(entsql.WithComments(true)).
 			Comment("筛选条件列表"),
-		field.JSON("action_message", []custom_types.Action{}).
+		field.JSON("action_message", []custom_types.Action{}).Optional().
 			Annotations(entsql.WithComments(true)).
 			Comment("命中后发送的消息内容"),
-		field.JSON("action_label", []int{}).
+		field.JSON("action_label", []int{}).Optional().
 			Annotations(entsql.WithComments(true)).
 			Comment("命中后需要打的标签"),
-		field.Int("index_sort").Default(1).
+		field.Int("index_sort").Default(1).Optional().
 			Annotations(entsql.WithComments(true)).
 			Comment("阶段顺序"),
 	}

+ 6 - 6
ent/set_not_nil.go

@@ -1424,7 +1424,7 @@ func (sn *SopNodeCreate) SetNotNilStageID(value *uint64) *SopNodeCreate {
 }
 
 // set field if value's pointer is not nil.
-func (sn *SopNodeUpdate) SetNotNilParentID(value *int) *SopNodeUpdate {
+func (sn *SopNodeUpdate) SetNotNilParentID(value *uint64) *SopNodeUpdate {
 	if value != nil {
 		return sn.SetParentID(*value)
 	}
@@ -1432,7 +1432,7 @@ func (sn *SopNodeUpdate) SetNotNilParentID(value *int) *SopNodeUpdate {
 }
 
 // set field if value's pointer is not nil.
-func (sn *SopNodeUpdateOne) SetNotNilParentID(value *int) *SopNodeUpdateOne {
+func (sn *SopNodeUpdateOne) SetNotNilParentID(value *uint64) *SopNodeUpdateOne {
 	if value != nil {
 		return sn.SetParentID(*value)
 	}
@@ -1440,7 +1440,7 @@ func (sn *SopNodeUpdateOne) SetNotNilParentID(value *int) *SopNodeUpdateOne {
 }
 
 // set field if value's pointer is not nil.
-func (sn *SopNodeCreate) SetNotNilParentID(value *int) *SopNodeCreate {
+func (sn *SopNodeCreate) SetNotNilParentID(value *uint64) *SopNodeCreate {
 	if value != nil {
 		return sn.SetParentID(*value)
 	}
@@ -1496,7 +1496,7 @@ func (sn *SopNodeCreate) SetNotNilConditionType(value *int) *SopNodeCreate {
 }
 
 // set field if value's pointer is not nil.
-func (sn *SopNodeUpdate) SetNotNilConditionList(value []custom_types.Condition) *SopNodeUpdate {
+func (sn *SopNodeUpdate) SetNotNilConditionList(value []string) *SopNodeUpdate {
 	if value != nil {
 		return sn.SetConditionList(value)
 	}
@@ -1504,7 +1504,7 @@ func (sn *SopNodeUpdate) SetNotNilConditionList(value []custom_types.Condition)
 }
 
 // set field if value's pointer is not nil.
-func (sn *SopNodeUpdateOne) SetNotNilConditionList(value []custom_types.Condition) *SopNodeUpdateOne {
+func (sn *SopNodeUpdateOne) SetNotNilConditionList(value []string) *SopNodeUpdateOne {
 	if value != nil {
 		return sn.SetConditionList(value)
 	}
@@ -1512,7 +1512,7 @@ func (sn *SopNodeUpdateOne) SetNotNilConditionList(value []custom_types.Conditio
 }
 
 // set field if value's pointer is not nil.
-func (sn *SopNodeCreate) SetNotNilConditionList(value []custom_types.Condition) *SopNodeCreate {
+func (sn *SopNodeCreate) SetNotNilConditionList(value []string) *SopNodeCreate {
 	if value != nil {
 		return sn.SetConditionList(value)
 	}

+ 3 - 3
ent/sopnode.go

@@ -31,13 +31,13 @@ type SopNode struct {
 	// 阶段 ID
 	StageID uint64 `json:"stage_id,omitempty"`
 	// 父节点 ID
-	ParentID int `json:"parent_id,omitempty"`
+	ParentID uint64 `json:"parent_id,omitempty"`
 	// 节点名称
 	Name string `json:"name,omitempty"`
 	// 触发条件类型 1 客户回复后触发 2 超时后触发
 	ConditionType int `json:"condition_type,omitempty"`
 	// 触发语义列表 当为空时则代表用户回复任意内容后触发
-	ConditionList []custom_types.Condition `json:"condition_list,omitempty"`
+	ConditionList []string `json:"condition_list,omitempty"`
 	// 命中后发送的消息内容
 	ActionMessage []custom_types.Action `json:"action_message,omitempty"`
 	// 命中后需要打的标签
@@ -136,7 +136,7 @@ func (sn *SopNode) assignValues(columns []string, values []any) error {
 			if value, ok := values[i].(*sql.NullInt64); !ok {
 				return fmt.Errorf("unexpected type %T for field parent_id", values[i])
 			} else if value.Valid {
-				sn.ParentID = int(value.Int64)
+				sn.ParentID = uint64(value.Int64)
 			}
 		case sopnode.FieldName:
 			if value, ok := values[i].(*sql.NullString); !ok {

+ 39 - 9
ent/sopnode/where.go

@@ -81,7 +81,7 @@ func StageID(v uint64) predicate.SopNode {
 }
 
 // ParentID applies equality check predicate on the "parent_id" field. It's identical to ParentIDEQ.
-func ParentID(v int) predicate.SopNode {
+func ParentID(v uint64) predicate.SopNode {
 	return predicate.SopNode(sql.FieldEQ(FieldParentID, v))
 }
 
@@ -296,42 +296,42 @@ func StageIDNotIn(vs ...uint64) predicate.SopNode {
 }
 
 // ParentIDEQ applies the EQ predicate on the "parent_id" field.
-func ParentIDEQ(v int) predicate.SopNode {
+func ParentIDEQ(v uint64) predicate.SopNode {
 	return predicate.SopNode(sql.FieldEQ(FieldParentID, v))
 }
 
 // ParentIDNEQ applies the NEQ predicate on the "parent_id" field.
-func ParentIDNEQ(v int) predicate.SopNode {
+func ParentIDNEQ(v uint64) predicate.SopNode {
 	return predicate.SopNode(sql.FieldNEQ(FieldParentID, v))
 }
 
 // ParentIDIn applies the In predicate on the "parent_id" field.
-func ParentIDIn(vs ...int) predicate.SopNode {
+func ParentIDIn(vs ...uint64) predicate.SopNode {
 	return predicate.SopNode(sql.FieldIn(FieldParentID, vs...))
 }
 
 // ParentIDNotIn applies the NotIn predicate on the "parent_id" field.
-func ParentIDNotIn(vs ...int) predicate.SopNode {
+func ParentIDNotIn(vs ...uint64) predicate.SopNode {
 	return predicate.SopNode(sql.FieldNotIn(FieldParentID, vs...))
 }
 
 // ParentIDGT applies the GT predicate on the "parent_id" field.
-func ParentIDGT(v int) predicate.SopNode {
+func ParentIDGT(v uint64) predicate.SopNode {
 	return predicate.SopNode(sql.FieldGT(FieldParentID, v))
 }
 
 // ParentIDGTE applies the GTE predicate on the "parent_id" field.
-func ParentIDGTE(v int) predicate.SopNode {
+func ParentIDGTE(v uint64) predicate.SopNode {
 	return predicate.SopNode(sql.FieldGTE(FieldParentID, v))
 }
 
 // ParentIDLT applies the LT predicate on the "parent_id" field.
-func ParentIDLT(v int) predicate.SopNode {
+func ParentIDLT(v uint64) predicate.SopNode {
 	return predicate.SopNode(sql.FieldLT(FieldParentID, v))
 }
 
 // ParentIDLTE applies the LTE predicate on the "parent_id" field.
-func ParentIDLTE(v int) predicate.SopNode {
+func ParentIDLTE(v uint64) predicate.SopNode {
 	return predicate.SopNode(sql.FieldLTE(FieldParentID, v))
 }
 
@@ -440,6 +440,36 @@ func ConditionTypeLTE(v int) predicate.SopNode {
 	return predicate.SopNode(sql.FieldLTE(FieldConditionType, v))
 }
 
+// ConditionListIsNil applies the IsNil predicate on the "condition_list" field.
+func ConditionListIsNil() predicate.SopNode {
+	return predicate.SopNode(sql.FieldIsNull(FieldConditionList))
+}
+
+// ConditionListNotNil applies the NotNil predicate on the "condition_list" field.
+func ConditionListNotNil() predicate.SopNode {
+	return predicate.SopNode(sql.FieldNotNull(FieldConditionList))
+}
+
+// ActionMessageIsNil applies the IsNil predicate on the "action_message" field.
+func ActionMessageIsNil() predicate.SopNode {
+	return predicate.SopNode(sql.FieldIsNull(FieldActionMessage))
+}
+
+// ActionMessageNotNil applies the NotNil predicate on the "action_message" field.
+func ActionMessageNotNil() predicate.SopNode {
+	return predicate.SopNode(sql.FieldNotNull(FieldActionMessage))
+}
+
+// ActionLabelIsNil applies the IsNil predicate on the "action_label" field.
+func ActionLabelIsNil() predicate.SopNode {
+	return predicate.SopNode(sql.FieldIsNull(FieldActionLabel))
+}
+
+// ActionLabelNotNil applies the NotNil predicate on the "action_label" field.
+func ActionLabelNotNil() predicate.SopNode {
+	return predicate.SopNode(sql.FieldNotNull(FieldActionLabel))
+}
+
 // HasSopStage applies the HasEdge predicate on the "sop_stage" edge.
 func HasSopStage() predicate.SopNode {
 	return predicate.SopNode(func(s *sql.Selector) {

+ 74 - 23
ent/sopnode_create.go

@@ -87,8 +87,8 @@ func (snc *SopNodeCreate) SetStageID(u uint64) *SopNodeCreate {
 }
 
 // SetParentID sets the "parent_id" field.
-func (snc *SopNodeCreate) SetParentID(i int) *SopNodeCreate {
-	snc.mutation.SetParentID(i)
+func (snc *SopNodeCreate) SetParentID(u uint64) *SopNodeCreate {
+	snc.mutation.SetParentID(u)
 	return snc
 }
 
@@ -121,8 +121,8 @@ func (snc *SopNodeCreate) SetNillableConditionType(i *int) *SopNodeCreate {
 }
 
 // SetConditionList sets the "condition_list" field.
-func (snc *SopNodeCreate) SetConditionList(ct []custom_types.Condition) *SopNodeCreate {
-	snc.mutation.SetConditionList(ct)
+func (snc *SopNodeCreate) SetConditionList(s []string) *SopNodeCreate {
+	snc.mutation.SetConditionList(s)
 	return snc
 }
 
@@ -241,15 +241,6 @@ func (snc *SopNodeCreate) check() error {
 	if _, ok := snc.mutation.ConditionType(); !ok {
 		return &ValidationError{Name: "condition_type", err: errors.New(`ent: missing required field "SopNode.condition_type"`)}
 	}
-	if _, ok := snc.mutation.ConditionList(); !ok {
-		return &ValidationError{Name: "condition_list", err: errors.New(`ent: missing required field "SopNode.condition_list"`)}
-	}
-	if _, ok := snc.mutation.ActionMessage(); !ok {
-		return &ValidationError{Name: "action_message", err: errors.New(`ent: missing required field "SopNode.action_message"`)}
-	}
-	if _, ok := snc.mutation.ActionLabel(); !ok {
-		return &ValidationError{Name: "action_label", err: errors.New(`ent: missing required field "SopNode.action_label"`)}
-	}
 	if _, ok := snc.mutation.SopStageID(); !ok {
 		return &ValidationError{Name: "sop_stage", err: errors.New(`ent: missing required edge "SopNode.sop_stage"`)}
 	}
@@ -303,7 +294,7 @@ func (snc *SopNodeCreate) createSpec() (*SopNode, *sqlgraph.CreateSpec) {
 		_node.DeletedAt = value
 	}
 	if value, ok := snc.mutation.ParentID(); ok {
-		_spec.SetField(sopnode.FieldParentID, field.TypeInt, value)
+		_spec.SetField(sopnode.FieldParentID, field.TypeUint64, value)
 		_node.ParentID = value
 	}
 	if value, ok := snc.mutation.Name(); ok {
@@ -462,7 +453,7 @@ func (u *SopNodeUpsert) UpdateStageID() *SopNodeUpsert {
 }
 
 // SetParentID sets the "parent_id" field.
-func (u *SopNodeUpsert) SetParentID(v int) *SopNodeUpsert {
+func (u *SopNodeUpsert) SetParentID(v uint64) *SopNodeUpsert {
 	u.Set(sopnode.FieldParentID, v)
 	return u
 }
@@ -474,7 +465,7 @@ func (u *SopNodeUpsert) UpdateParentID() *SopNodeUpsert {
 }
 
 // AddParentID adds v to the "parent_id" field.
-func (u *SopNodeUpsert) AddParentID(v int) *SopNodeUpsert {
+func (u *SopNodeUpsert) AddParentID(v uint64) *SopNodeUpsert {
 	u.Add(sopnode.FieldParentID, v)
 	return u
 }
@@ -510,7 +501,7 @@ func (u *SopNodeUpsert) AddConditionType(v int) *SopNodeUpsert {
 }
 
 // SetConditionList sets the "condition_list" field.
-func (u *SopNodeUpsert) SetConditionList(v []custom_types.Condition) *SopNodeUpsert {
+func (u *SopNodeUpsert) SetConditionList(v []string) *SopNodeUpsert {
 	u.Set(sopnode.FieldConditionList, v)
 	return u
 }
@@ -521,6 +512,12 @@ func (u *SopNodeUpsert) UpdateConditionList() *SopNodeUpsert {
 	return u
 }
 
+// ClearConditionList clears the value of the "condition_list" field.
+func (u *SopNodeUpsert) ClearConditionList() *SopNodeUpsert {
+	u.SetNull(sopnode.FieldConditionList)
+	return u
+}
+
 // SetActionMessage sets the "action_message" field.
 func (u *SopNodeUpsert) SetActionMessage(v []custom_types.Action) *SopNodeUpsert {
 	u.Set(sopnode.FieldActionMessage, v)
@@ -533,6 +530,12 @@ func (u *SopNodeUpsert) UpdateActionMessage() *SopNodeUpsert {
 	return u
 }
 
+// ClearActionMessage clears the value of the "action_message" field.
+func (u *SopNodeUpsert) ClearActionMessage() *SopNodeUpsert {
+	u.SetNull(sopnode.FieldActionMessage)
+	return u
+}
+
 // SetActionLabel sets the "action_label" field.
 func (u *SopNodeUpsert) SetActionLabel(v []int) *SopNodeUpsert {
 	u.Set(sopnode.FieldActionLabel, v)
@@ -545,6 +548,12 @@ func (u *SopNodeUpsert) UpdateActionLabel() *SopNodeUpsert {
 	return u
 }
 
+// ClearActionLabel clears the value of the "action_label" field.
+func (u *SopNodeUpsert) ClearActionLabel() *SopNodeUpsert {
+	u.SetNull(sopnode.FieldActionLabel)
+	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:
 //
@@ -674,14 +683,14 @@ func (u *SopNodeUpsertOne) UpdateStageID() *SopNodeUpsertOne {
 }
 
 // SetParentID sets the "parent_id" field.
-func (u *SopNodeUpsertOne) SetParentID(v int) *SopNodeUpsertOne {
+func (u *SopNodeUpsertOne) SetParentID(v uint64) *SopNodeUpsertOne {
 	return u.Update(func(s *SopNodeUpsert) {
 		s.SetParentID(v)
 	})
 }
 
 // AddParentID adds v to the "parent_id" field.
-func (u *SopNodeUpsertOne) AddParentID(v int) *SopNodeUpsertOne {
+func (u *SopNodeUpsertOne) AddParentID(v uint64) *SopNodeUpsertOne {
 	return u.Update(func(s *SopNodeUpsert) {
 		s.AddParentID(v)
 	})
@@ -730,7 +739,7 @@ func (u *SopNodeUpsertOne) UpdateConditionType() *SopNodeUpsertOne {
 }
 
 // SetConditionList sets the "condition_list" field.
-func (u *SopNodeUpsertOne) SetConditionList(v []custom_types.Condition) *SopNodeUpsertOne {
+func (u *SopNodeUpsertOne) SetConditionList(v []string) *SopNodeUpsertOne {
 	return u.Update(func(s *SopNodeUpsert) {
 		s.SetConditionList(v)
 	})
@@ -743,6 +752,13 @@ func (u *SopNodeUpsertOne) UpdateConditionList() *SopNodeUpsertOne {
 	})
 }
 
+// ClearConditionList clears the value of the "condition_list" field.
+func (u *SopNodeUpsertOne) ClearConditionList() *SopNodeUpsertOne {
+	return u.Update(func(s *SopNodeUpsert) {
+		s.ClearConditionList()
+	})
+}
+
 // SetActionMessage sets the "action_message" field.
 func (u *SopNodeUpsertOne) SetActionMessage(v []custom_types.Action) *SopNodeUpsertOne {
 	return u.Update(func(s *SopNodeUpsert) {
@@ -757,6 +773,13 @@ func (u *SopNodeUpsertOne) UpdateActionMessage() *SopNodeUpsertOne {
 	})
 }
 
+// ClearActionMessage clears the value of the "action_message" field.
+func (u *SopNodeUpsertOne) ClearActionMessage() *SopNodeUpsertOne {
+	return u.Update(func(s *SopNodeUpsert) {
+		s.ClearActionMessage()
+	})
+}
+
 // SetActionLabel sets the "action_label" field.
 func (u *SopNodeUpsertOne) SetActionLabel(v []int) *SopNodeUpsertOne {
 	return u.Update(func(s *SopNodeUpsert) {
@@ -771,6 +794,13 @@ func (u *SopNodeUpsertOne) UpdateActionLabel() *SopNodeUpsertOne {
 	})
 }
 
+// ClearActionLabel clears the value of the "action_label" field.
+func (u *SopNodeUpsertOne) ClearActionLabel() *SopNodeUpsertOne {
+	return u.Update(func(s *SopNodeUpsert) {
+		s.ClearActionLabel()
+	})
+}
+
 // Exec executes the query.
 func (u *SopNodeUpsertOne) Exec(ctx context.Context) error {
 	if len(u.create.conflict) == 0 {
@@ -1066,14 +1096,14 @@ func (u *SopNodeUpsertBulk) UpdateStageID() *SopNodeUpsertBulk {
 }
 
 // SetParentID sets the "parent_id" field.
-func (u *SopNodeUpsertBulk) SetParentID(v int) *SopNodeUpsertBulk {
+func (u *SopNodeUpsertBulk) SetParentID(v uint64) *SopNodeUpsertBulk {
 	return u.Update(func(s *SopNodeUpsert) {
 		s.SetParentID(v)
 	})
 }
 
 // AddParentID adds v to the "parent_id" field.
-func (u *SopNodeUpsertBulk) AddParentID(v int) *SopNodeUpsertBulk {
+func (u *SopNodeUpsertBulk) AddParentID(v uint64) *SopNodeUpsertBulk {
 	return u.Update(func(s *SopNodeUpsert) {
 		s.AddParentID(v)
 	})
@@ -1122,7 +1152,7 @@ func (u *SopNodeUpsertBulk) UpdateConditionType() *SopNodeUpsertBulk {
 }
 
 // SetConditionList sets the "condition_list" field.
-func (u *SopNodeUpsertBulk) SetConditionList(v []custom_types.Condition) *SopNodeUpsertBulk {
+func (u *SopNodeUpsertBulk) SetConditionList(v []string) *SopNodeUpsertBulk {
 	return u.Update(func(s *SopNodeUpsert) {
 		s.SetConditionList(v)
 	})
@@ -1135,6 +1165,13 @@ func (u *SopNodeUpsertBulk) UpdateConditionList() *SopNodeUpsertBulk {
 	})
 }
 
+// ClearConditionList clears the value of the "condition_list" field.
+func (u *SopNodeUpsertBulk) ClearConditionList() *SopNodeUpsertBulk {
+	return u.Update(func(s *SopNodeUpsert) {
+		s.ClearConditionList()
+	})
+}
+
 // SetActionMessage sets the "action_message" field.
 func (u *SopNodeUpsertBulk) SetActionMessage(v []custom_types.Action) *SopNodeUpsertBulk {
 	return u.Update(func(s *SopNodeUpsert) {
@@ -1149,6 +1186,13 @@ func (u *SopNodeUpsertBulk) UpdateActionMessage() *SopNodeUpsertBulk {
 	})
 }
 
+// ClearActionMessage clears the value of the "action_message" field.
+func (u *SopNodeUpsertBulk) ClearActionMessage() *SopNodeUpsertBulk {
+	return u.Update(func(s *SopNodeUpsert) {
+		s.ClearActionMessage()
+	})
+}
+
 // SetActionLabel sets the "action_label" field.
 func (u *SopNodeUpsertBulk) SetActionLabel(v []int) *SopNodeUpsertBulk {
 	return u.Update(func(s *SopNodeUpsert) {
@@ -1163,6 +1207,13 @@ func (u *SopNodeUpsertBulk) UpdateActionLabel() *SopNodeUpsertBulk {
 	})
 }
 
+// ClearActionLabel clears the value of the "action_label" field.
+func (u *SopNodeUpsertBulk) ClearActionLabel() *SopNodeUpsertBulk {
+	return u.Update(func(s *SopNodeUpsert) {
+		s.ClearActionLabel()
+	})
+}
+
 // Exec executes the query.
 func (u *SopNodeUpsertBulk) Exec(ctx context.Context) error {
 	if u.create.err != nil {

+ 84 - 30
ent/sopnode_update.go

@@ -99,23 +99,23 @@ func (snu *SopNodeUpdate) SetNillableStageID(u *uint64) *SopNodeUpdate {
 }
 
 // SetParentID sets the "parent_id" field.
-func (snu *SopNodeUpdate) SetParentID(i int) *SopNodeUpdate {
+func (snu *SopNodeUpdate) SetParentID(u uint64) *SopNodeUpdate {
 	snu.mutation.ResetParentID()
-	snu.mutation.SetParentID(i)
+	snu.mutation.SetParentID(u)
 	return snu
 }
 
 // SetNillableParentID sets the "parent_id" field if the given value is not nil.
-func (snu *SopNodeUpdate) SetNillableParentID(i *int) *SopNodeUpdate {
-	if i != nil {
-		snu.SetParentID(*i)
+func (snu *SopNodeUpdate) SetNillableParentID(u *uint64) *SopNodeUpdate {
+	if u != nil {
+		snu.SetParentID(*u)
 	}
 	return snu
 }
 
-// AddParentID adds i to the "parent_id" field.
-func (snu *SopNodeUpdate) AddParentID(i int) *SopNodeUpdate {
-	snu.mutation.AddParentID(i)
+// AddParentID adds u to the "parent_id" field.
+func (snu *SopNodeUpdate) AddParentID(u int64) *SopNodeUpdate {
+	snu.mutation.AddParentID(u)
 	return snu
 }
 
@@ -155,14 +155,20 @@ func (snu *SopNodeUpdate) AddConditionType(i int) *SopNodeUpdate {
 }
 
 // SetConditionList sets the "condition_list" field.
-func (snu *SopNodeUpdate) SetConditionList(ct []custom_types.Condition) *SopNodeUpdate {
-	snu.mutation.SetConditionList(ct)
+func (snu *SopNodeUpdate) SetConditionList(s []string) *SopNodeUpdate {
+	snu.mutation.SetConditionList(s)
 	return snu
 }
 
-// AppendConditionList appends ct to the "condition_list" field.
-func (snu *SopNodeUpdate) AppendConditionList(ct []custom_types.Condition) *SopNodeUpdate {
-	snu.mutation.AppendConditionList(ct)
+// AppendConditionList appends s to the "condition_list" field.
+func (snu *SopNodeUpdate) AppendConditionList(s []string) *SopNodeUpdate {
+	snu.mutation.AppendConditionList(s)
+	return snu
+}
+
+// ClearConditionList clears the value of the "condition_list" field.
+func (snu *SopNodeUpdate) ClearConditionList() *SopNodeUpdate {
+	snu.mutation.ClearConditionList()
 	return snu
 }
 
@@ -178,6 +184,12 @@ func (snu *SopNodeUpdate) AppendActionMessage(ct []custom_types.Action) *SopNode
 	return snu
 }
 
+// ClearActionMessage clears the value of the "action_message" field.
+func (snu *SopNodeUpdate) ClearActionMessage() *SopNodeUpdate {
+	snu.mutation.ClearActionMessage()
+	return snu
+}
+
 // SetActionLabel sets the "action_label" field.
 func (snu *SopNodeUpdate) SetActionLabel(i []int) *SopNodeUpdate {
 	snu.mutation.SetActionLabel(i)
@@ -190,6 +202,12 @@ func (snu *SopNodeUpdate) AppendActionLabel(i []int) *SopNodeUpdate {
 	return snu
 }
 
+// ClearActionLabel clears the value of the "action_label" field.
+func (snu *SopNodeUpdate) ClearActionLabel() *SopNodeUpdate {
+	snu.mutation.ClearActionLabel()
+	return snu
+}
+
 // SetSopStageID sets the "sop_stage" edge to the SopStage entity by ID.
 func (snu *SopNodeUpdate) SetSopStageID(id uint64) *SopNodeUpdate {
 	snu.mutation.SetSopStageID(id)
@@ -293,10 +311,10 @@ func (snu *SopNodeUpdate) sqlSave(ctx context.Context) (n int, err error) {
 		_spec.ClearField(sopnode.FieldDeletedAt, field.TypeTime)
 	}
 	if value, ok := snu.mutation.ParentID(); ok {
-		_spec.SetField(sopnode.FieldParentID, field.TypeInt, value)
+		_spec.SetField(sopnode.FieldParentID, field.TypeUint64, value)
 	}
 	if value, ok := snu.mutation.AddedParentID(); ok {
-		_spec.AddField(sopnode.FieldParentID, field.TypeInt, value)
+		_spec.AddField(sopnode.FieldParentID, field.TypeUint64, value)
 	}
 	if value, ok := snu.mutation.Name(); ok {
 		_spec.SetField(sopnode.FieldName, field.TypeString, value)
@@ -315,6 +333,9 @@ func (snu *SopNodeUpdate) sqlSave(ctx context.Context) (n int, err error) {
 			sqljson.Append(u, sopnode.FieldConditionList, value)
 		})
 	}
+	if snu.mutation.ConditionListCleared() {
+		_spec.ClearField(sopnode.FieldConditionList, field.TypeJSON)
+	}
 	if value, ok := snu.mutation.ActionMessage(); ok {
 		_spec.SetField(sopnode.FieldActionMessage, field.TypeJSON, value)
 	}
@@ -323,6 +344,9 @@ func (snu *SopNodeUpdate) sqlSave(ctx context.Context) (n int, err error) {
 			sqljson.Append(u, sopnode.FieldActionMessage, value)
 		})
 	}
+	if snu.mutation.ActionMessageCleared() {
+		_spec.ClearField(sopnode.FieldActionMessage, field.TypeJSON)
+	}
 	if value, ok := snu.mutation.ActionLabel(); ok {
 		_spec.SetField(sopnode.FieldActionLabel, field.TypeJSON, value)
 	}
@@ -331,6 +355,9 @@ func (snu *SopNodeUpdate) sqlSave(ctx context.Context) (n int, err error) {
 			sqljson.Append(u, sopnode.FieldActionLabel, value)
 		})
 	}
+	if snu.mutation.ActionLabelCleared() {
+		_spec.ClearField(sopnode.FieldActionLabel, field.TypeJSON)
+	}
 	if snu.mutation.SopStageCleared() {
 		edge := &sqlgraph.EdgeSpec{
 			Rel:     sqlgraph.M2O,
@@ -448,23 +475,23 @@ func (snuo *SopNodeUpdateOne) SetNillableStageID(u *uint64) *SopNodeUpdateOne {
 }
 
 // SetParentID sets the "parent_id" field.
-func (snuo *SopNodeUpdateOne) SetParentID(i int) *SopNodeUpdateOne {
+func (snuo *SopNodeUpdateOne) SetParentID(u uint64) *SopNodeUpdateOne {
 	snuo.mutation.ResetParentID()
-	snuo.mutation.SetParentID(i)
+	snuo.mutation.SetParentID(u)
 	return snuo
 }
 
 // SetNillableParentID sets the "parent_id" field if the given value is not nil.
-func (snuo *SopNodeUpdateOne) SetNillableParentID(i *int) *SopNodeUpdateOne {
-	if i != nil {
-		snuo.SetParentID(*i)
+func (snuo *SopNodeUpdateOne) SetNillableParentID(u *uint64) *SopNodeUpdateOne {
+	if u != nil {
+		snuo.SetParentID(*u)
 	}
 	return snuo
 }
 
-// AddParentID adds i to the "parent_id" field.
-func (snuo *SopNodeUpdateOne) AddParentID(i int) *SopNodeUpdateOne {
-	snuo.mutation.AddParentID(i)
+// AddParentID adds u to the "parent_id" field.
+func (snuo *SopNodeUpdateOne) AddParentID(u int64) *SopNodeUpdateOne {
+	snuo.mutation.AddParentID(u)
 	return snuo
 }
 
@@ -504,14 +531,20 @@ func (snuo *SopNodeUpdateOne) AddConditionType(i int) *SopNodeUpdateOne {
 }
 
 // SetConditionList sets the "condition_list" field.
-func (snuo *SopNodeUpdateOne) SetConditionList(ct []custom_types.Condition) *SopNodeUpdateOne {
-	snuo.mutation.SetConditionList(ct)
+func (snuo *SopNodeUpdateOne) SetConditionList(s []string) *SopNodeUpdateOne {
+	snuo.mutation.SetConditionList(s)
 	return snuo
 }
 
-// AppendConditionList appends ct to the "condition_list" field.
-func (snuo *SopNodeUpdateOne) AppendConditionList(ct []custom_types.Condition) *SopNodeUpdateOne {
-	snuo.mutation.AppendConditionList(ct)
+// AppendConditionList appends s to the "condition_list" field.
+func (snuo *SopNodeUpdateOne) AppendConditionList(s []string) *SopNodeUpdateOne {
+	snuo.mutation.AppendConditionList(s)
+	return snuo
+}
+
+// ClearConditionList clears the value of the "condition_list" field.
+func (snuo *SopNodeUpdateOne) ClearConditionList() *SopNodeUpdateOne {
+	snuo.mutation.ClearConditionList()
 	return snuo
 }
 
@@ -527,6 +560,12 @@ func (snuo *SopNodeUpdateOne) AppendActionMessage(ct []custom_types.Action) *Sop
 	return snuo
 }
 
+// ClearActionMessage clears the value of the "action_message" field.
+func (snuo *SopNodeUpdateOne) ClearActionMessage() *SopNodeUpdateOne {
+	snuo.mutation.ClearActionMessage()
+	return snuo
+}
+
 // SetActionLabel sets the "action_label" field.
 func (snuo *SopNodeUpdateOne) SetActionLabel(i []int) *SopNodeUpdateOne {
 	snuo.mutation.SetActionLabel(i)
@@ -539,6 +578,12 @@ func (snuo *SopNodeUpdateOne) AppendActionLabel(i []int) *SopNodeUpdateOne {
 	return snuo
 }
 
+// ClearActionLabel clears the value of the "action_label" field.
+func (snuo *SopNodeUpdateOne) ClearActionLabel() *SopNodeUpdateOne {
+	snuo.mutation.ClearActionLabel()
+	return snuo
+}
+
 // SetSopStageID sets the "sop_stage" edge to the SopStage entity by ID.
 func (snuo *SopNodeUpdateOne) SetSopStageID(id uint64) *SopNodeUpdateOne {
 	snuo.mutation.SetSopStageID(id)
@@ -672,10 +717,10 @@ func (snuo *SopNodeUpdateOne) sqlSave(ctx context.Context) (_node *SopNode, err
 		_spec.ClearField(sopnode.FieldDeletedAt, field.TypeTime)
 	}
 	if value, ok := snuo.mutation.ParentID(); ok {
-		_spec.SetField(sopnode.FieldParentID, field.TypeInt, value)
+		_spec.SetField(sopnode.FieldParentID, field.TypeUint64, value)
 	}
 	if value, ok := snuo.mutation.AddedParentID(); ok {
-		_spec.AddField(sopnode.FieldParentID, field.TypeInt, value)
+		_spec.AddField(sopnode.FieldParentID, field.TypeUint64, value)
 	}
 	if value, ok := snuo.mutation.Name(); ok {
 		_spec.SetField(sopnode.FieldName, field.TypeString, value)
@@ -694,6 +739,9 @@ func (snuo *SopNodeUpdateOne) sqlSave(ctx context.Context) (_node *SopNode, err
 			sqljson.Append(u, sopnode.FieldConditionList, value)
 		})
 	}
+	if snuo.mutation.ConditionListCleared() {
+		_spec.ClearField(sopnode.FieldConditionList, field.TypeJSON)
+	}
 	if value, ok := snuo.mutation.ActionMessage(); ok {
 		_spec.SetField(sopnode.FieldActionMessage, field.TypeJSON, value)
 	}
@@ -702,6 +750,9 @@ func (snuo *SopNodeUpdateOne) sqlSave(ctx context.Context) (_node *SopNode, err
 			sqljson.Append(u, sopnode.FieldActionMessage, value)
 		})
 	}
+	if snuo.mutation.ActionMessageCleared() {
+		_spec.ClearField(sopnode.FieldActionMessage, field.TypeJSON)
+	}
 	if value, ok := snuo.mutation.ActionLabel(); ok {
 		_spec.SetField(sopnode.FieldActionLabel, field.TypeJSON, value)
 	}
@@ -710,6 +761,9 @@ func (snuo *SopNodeUpdateOne) sqlSave(ctx context.Context) (_node *SopNode, err
 			sqljson.Append(u, sopnode.FieldActionLabel, value)
 		})
 	}
+	if snuo.mutation.ActionLabelCleared() {
+		_spec.ClearField(sopnode.FieldActionLabel, field.TypeJSON)
+	}
 	if snuo.mutation.SopStageCleared() {
 		edge := &sqlgraph.EdgeSpec{
 			Rel:     sqlgraph.M2O,

+ 30 - 0
ent/sopstage/where.go

@@ -445,6 +445,26 @@ func ConditionOperatorLTE(v int) predicate.SopStage {
 	return predicate.SopStage(sql.FieldLTE(FieldConditionOperator, v))
 }
 
+// ActionMessageIsNil applies the IsNil predicate on the "action_message" field.
+func ActionMessageIsNil() predicate.SopStage {
+	return predicate.SopStage(sql.FieldIsNull(FieldActionMessage))
+}
+
+// ActionMessageNotNil applies the NotNil predicate on the "action_message" field.
+func ActionMessageNotNil() predicate.SopStage {
+	return predicate.SopStage(sql.FieldNotNull(FieldActionMessage))
+}
+
+// ActionLabelIsNil applies the IsNil predicate on the "action_label" field.
+func ActionLabelIsNil() predicate.SopStage {
+	return predicate.SopStage(sql.FieldIsNull(FieldActionLabel))
+}
+
+// ActionLabelNotNil applies the NotNil predicate on the "action_label" field.
+func ActionLabelNotNil() predicate.SopStage {
+	return predicate.SopStage(sql.FieldNotNull(FieldActionLabel))
+}
+
 // IndexSortEQ applies the EQ predicate on the "index_sort" field.
 func IndexSortEQ(v int) predicate.SopStage {
 	return predicate.SopStage(sql.FieldEQ(FieldIndexSort, v))
@@ -485,6 +505,16 @@ func IndexSortLTE(v int) predicate.SopStage {
 	return predicate.SopStage(sql.FieldLTE(FieldIndexSort, v))
 }
 
+// IndexSortIsNil applies the IsNil predicate on the "index_sort" field.
+func IndexSortIsNil() predicate.SopStage {
+	return predicate.SopStage(sql.FieldIsNull(FieldIndexSort))
+}
+
+// IndexSortNotNil applies the NotNil predicate on the "index_sort" field.
+func IndexSortNotNil() predicate.SopStage {
+	return predicate.SopStage(sql.FieldNotNull(FieldIndexSort))
+}
+
 // HasSopTask applies the HasEdge predicate on the "sop_task" edge.
 func HasSopTask() predicate.SopStage {
 	return predicate.SopStage(func(s *sql.Selector) {

+ 60 - 9
ent/sopstage_create.go

@@ -290,15 +290,6 @@ func (ssc *SopStageCreate) check() error {
 	if _, ok := ssc.mutation.ConditionList(); !ok {
 		return &ValidationError{Name: "condition_list", err: errors.New(`ent: missing required field "SopStage.condition_list"`)}
 	}
-	if _, ok := ssc.mutation.ActionMessage(); !ok {
-		return &ValidationError{Name: "action_message", err: errors.New(`ent: missing required field "SopStage.action_message"`)}
-	}
-	if _, ok := ssc.mutation.ActionLabel(); !ok {
-		return &ValidationError{Name: "action_label", err: errors.New(`ent: missing required field "SopStage.action_label"`)}
-	}
-	if _, ok := ssc.mutation.IndexSort(); !ok {
-		return &ValidationError{Name: "index_sort", err: errors.New(`ent: missing required field "SopStage.index_sort"`)}
-	}
 	if _, ok := ssc.mutation.SopTaskID(); !ok {
 		return &ValidationError{Name: "sop_task", err: errors.New(`ent: missing required edge "SopStage.sop_task"`)}
 	}
@@ -602,6 +593,12 @@ func (u *SopStageUpsert) UpdateActionMessage() *SopStageUpsert {
 	return u
 }
 
+// ClearActionMessage clears the value of the "action_message" field.
+func (u *SopStageUpsert) ClearActionMessage() *SopStageUpsert {
+	u.SetNull(sopstage.FieldActionMessage)
+	return u
+}
+
 // SetActionLabel sets the "action_label" field.
 func (u *SopStageUpsert) SetActionLabel(v []int) *SopStageUpsert {
 	u.Set(sopstage.FieldActionLabel, v)
@@ -614,6 +611,12 @@ func (u *SopStageUpsert) UpdateActionLabel() *SopStageUpsert {
 	return u
 }
 
+// ClearActionLabel clears the value of the "action_label" field.
+func (u *SopStageUpsert) ClearActionLabel() *SopStageUpsert {
+	u.SetNull(sopstage.FieldActionLabel)
+	return u
+}
+
 // SetIndexSort sets the "index_sort" field.
 func (u *SopStageUpsert) SetIndexSort(v int) *SopStageUpsert {
 	u.Set(sopstage.FieldIndexSort, v)
@@ -632,6 +635,12 @@ func (u *SopStageUpsert) AddIndexSort(v int) *SopStageUpsert {
 	return u
 }
 
+// ClearIndexSort clears the value of the "index_sort" field.
+func (u *SopStageUpsert) ClearIndexSort() *SopStageUpsert {
+	u.SetNull(sopstage.FieldIndexSort)
+	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:
 //
@@ -844,6 +853,13 @@ func (u *SopStageUpsertOne) UpdateActionMessage() *SopStageUpsertOne {
 	})
 }
 
+// ClearActionMessage clears the value of the "action_message" field.
+func (u *SopStageUpsertOne) ClearActionMessage() *SopStageUpsertOne {
+	return u.Update(func(s *SopStageUpsert) {
+		s.ClearActionMessage()
+	})
+}
+
 // SetActionLabel sets the "action_label" field.
 func (u *SopStageUpsertOne) SetActionLabel(v []int) *SopStageUpsertOne {
 	return u.Update(func(s *SopStageUpsert) {
@@ -858,6 +874,13 @@ func (u *SopStageUpsertOne) UpdateActionLabel() *SopStageUpsertOne {
 	})
 }
 
+// ClearActionLabel clears the value of the "action_label" field.
+func (u *SopStageUpsertOne) ClearActionLabel() *SopStageUpsertOne {
+	return u.Update(func(s *SopStageUpsert) {
+		s.ClearActionLabel()
+	})
+}
+
 // SetIndexSort sets the "index_sort" field.
 func (u *SopStageUpsertOne) SetIndexSort(v int) *SopStageUpsertOne {
 	return u.Update(func(s *SopStageUpsert) {
@@ -879,6 +902,13 @@ func (u *SopStageUpsertOne) UpdateIndexSort() *SopStageUpsertOne {
 	})
 }
 
+// ClearIndexSort clears the value of the "index_sort" field.
+func (u *SopStageUpsertOne) ClearIndexSort() *SopStageUpsertOne {
+	return u.Update(func(s *SopStageUpsert) {
+		s.ClearIndexSort()
+	})
+}
+
 // Exec executes the query.
 func (u *SopStageUpsertOne) Exec(ctx context.Context) error {
 	if len(u.create.conflict) == 0 {
@@ -1257,6 +1287,13 @@ func (u *SopStageUpsertBulk) UpdateActionMessage() *SopStageUpsertBulk {
 	})
 }
 
+// ClearActionMessage clears the value of the "action_message" field.
+func (u *SopStageUpsertBulk) ClearActionMessage() *SopStageUpsertBulk {
+	return u.Update(func(s *SopStageUpsert) {
+		s.ClearActionMessage()
+	})
+}
+
 // SetActionLabel sets the "action_label" field.
 func (u *SopStageUpsertBulk) SetActionLabel(v []int) *SopStageUpsertBulk {
 	return u.Update(func(s *SopStageUpsert) {
@@ -1271,6 +1308,13 @@ func (u *SopStageUpsertBulk) UpdateActionLabel() *SopStageUpsertBulk {
 	})
 }
 
+// ClearActionLabel clears the value of the "action_label" field.
+func (u *SopStageUpsertBulk) ClearActionLabel() *SopStageUpsertBulk {
+	return u.Update(func(s *SopStageUpsert) {
+		s.ClearActionLabel()
+	})
+}
+
 // SetIndexSort sets the "index_sort" field.
 func (u *SopStageUpsertBulk) SetIndexSort(v int) *SopStageUpsertBulk {
 	return u.Update(func(s *SopStageUpsert) {
@@ -1292,6 +1336,13 @@ func (u *SopStageUpsertBulk) UpdateIndexSort() *SopStageUpsertBulk {
 	})
 }
 
+// ClearIndexSort clears the value of the "index_sort" field.
+func (u *SopStageUpsertBulk) ClearIndexSort() *SopStageUpsertBulk {
+	return u.Update(func(s *SopStageUpsert) {
+		s.ClearIndexSort()
+	})
+}
+
 // Exec executes the query.
 func (u *SopStageUpsertBulk) Exec(ctx context.Context) error {
 	if u.create.err != nil {

+ 54 - 0
ent/sopstage_update.go

@@ -179,6 +179,12 @@ func (ssu *SopStageUpdate) AppendActionMessage(ct []custom_types.Action) *SopSta
 	return ssu
 }
 
+// ClearActionMessage clears the value of the "action_message" field.
+func (ssu *SopStageUpdate) ClearActionMessage() *SopStageUpdate {
+	ssu.mutation.ClearActionMessage()
+	return ssu
+}
+
 // SetActionLabel sets the "action_label" field.
 func (ssu *SopStageUpdate) SetActionLabel(i []int) *SopStageUpdate {
 	ssu.mutation.SetActionLabel(i)
@@ -191,6 +197,12 @@ func (ssu *SopStageUpdate) AppendActionLabel(i []int) *SopStageUpdate {
 	return ssu
 }
 
+// ClearActionLabel clears the value of the "action_label" field.
+func (ssu *SopStageUpdate) ClearActionLabel() *SopStageUpdate {
+	ssu.mutation.ClearActionLabel()
+	return ssu
+}
+
 // SetIndexSort sets the "index_sort" field.
 func (ssu *SopStageUpdate) SetIndexSort(i int) *SopStageUpdate {
 	ssu.mutation.ResetIndexSort()
@@ -212,6 +224,12 @@ func (ssu *SopStageUpdate) AddIndexSort(i int) *SopStageUpdate {
 	return ssu
 }
 
+// ClearIndexSort clears the value of the "index_sort" field.
+func (ssu *SopStageUpdate) ClearIndexSort() *SopStageUpdate {
+	ssu.mutation.ClearIndexSort()
+	return ssu
+}
+
 // SetSopTaskID sets the "sop_task" edge to the SopTask entity by ID.
 func (ssu *SopStageUpdate) SetSopTaskID(id uint64) *SopStageUpdate {
 	ssu.mutation.SetSopTaskID(id)
@@ -381,6 +399,9 @@ func (ssu *SopStageUpdate) sqlSave(ctx context.Context) (n int, err error) {
 			sqljson.Append(u, sopstage.FieldActionMessage, value)
 		})
 	}
+	if ssu.mutation.ActionMessageCleared() {
+		_spec.ClearField(sopstage.FieldActionMessage, field.TypeJSON)
+	}
 	if value, ok := ssu.mutation.ActionLabel(); ok {
 		_spec.SetField(sopstage.FieldActionLabel, field.TypeJSON, value)
 	}
@@ -389,12 +410,18 @@ func (ssu *SopStageUpdate) sqlSave(ctx context.Context) (n int, err error) {
 			sqljson.Append(u, sopstage.FieldActionLabel, value)
 		})
 	}
+	if ssu.mutation.ActionLabelCleared() {
+		_spec.ClearField(sopstage.FieldActionLabel, field.TypeJSON)
+	}
 	if value, ok := ssu.mutation.IndexSort(); ok {
 		_spec.SetField(sopstage.FieldIndexSort, field.TypeInt, value)
 	}
 	if value, ok := ssu.mutation.AddedIndexSort(); ok {
 		_spec.AddField(sopstage.FieldIndexSort, field.TypeInt, value)
 	}
+	if ssu.mutation.IndexSortCleared() {
+		_spec.ClearField(sopstage.FieldIndexSort, field.TypeInt)
+	}
 	if ssu.mutation.SopTaskCleared() {
 		edge := &sqlgraph.EdgeSpec{
 			Rel:     sqlgraph.M2O,
@@ -636,6 +663,12 @@ func (ssuo *SopStageUpdateOne) AppendActionMessage(ct []custom_types.Action) *So
 	return ssuo
 }
 
+// ClearActionMessage clears the value of the "action_message" field.
+func (ssuo *SopStageUpdateOne) ClearActionMessage() *SopStageUpdateOne {
+	ssuo.mutation.ClearActionMessage()
+	return ssuo
+}
+
 // SetActionLabel sets the "action_label" field.
 func (ssuo *SopStageUpdateOne) SetActionLabel(i []int) *SopStageUpdateOne {
 	ssuo.mutation.SetActionLabel(i)
@@ -648,6 +681,12 @@ func (ssuo *SopStageUpdateOne) AppendActionLabel(i []int) *SopStageUpdateOne {
 	return ssuo
 }
 
+// ClearActionLabel clears the value of the "action_label" field.
+func (ssuo *SopStageUpdateOne) ClearActionLabel() *SopStageUpdateOne {
+	ssuo.mutation.ClearActionLabel()
+	return ssuo
+}
+
 // SetIndexSort sets the "index_sort" field.
 func (ssuo *SopStageUpdateOne) SetIndexSort(i int) *SopStageUpdateOne {
 	ssuo.mutation.ResetIndexSort()
@@ -669,6 +708,12 @@ func (ssuo *SopStageUpdateOne) AddIndexSort(i int) *SopStageUpdateOne {
 	return ssuo
 }
 
+// ClearIndexSort clears the value of the "index_sort" field.
+func (ssuo *SopStageUpdateOne) ClearIndexSort() *SopStageUpdateOne {
+	ssuo.mutation.ClearIndexSort()
+	return ssuo
+}
+
 // SetSopTaskID sets the "sop_task" edge to the SopTask entity by ID.
 func (ssuo *SopStageUpdateOne) SetSopTaskID(id uint64) *SopStageUpdateOne {
 	ssuo.mutation.SetSopTaskID(id)
@@ -868,6 +913,9 @@ func (ssuo *SopStageUpdateOne) sqlSave(ctx context.Context) (_node *SopStage, er
 			sqljson.Append(u, sopstage.FieldActionMessage, value)
 		})
 	}
+	if ssuo.mutation.ActionMessageCleared() {
+		_spec.ClearField(sopstage.FieldActionMessage, field.TypeJSON)
+	}
 	if value, ok := ssuo.mutation.ActionLabel(); ok {
 		_spec.SetField(sopstage.FieldActionLabel, field.TypeJSON, value)
 	}
@@ -876,12 +924,18 @@ func (ssuo *SopStageUpdateOne) sqlSave(ctx context.Context) (_node *SopStage, er
 			sqljson.Append(u, sopstage.FieldActionLabel, value)
 		})
 	}
+	if ssuo.mutation.ActionLabelCleared() {
+		_spec.ClearField(sopstage.FieldActionLabel, field.TypeJSON)
+	}
 	if value, ok := ssuo.mutation.IndexSort(); ok {
 		_spec.SetField(sopstage.FieldIndexSort, field.TypeInt, value)
 	}
 	if value, ok := ssuo.mutation.AddedIndexSort(); ok {
 		_spec.AddField(sopstage.FieldIndexSort, field.TypeInt, value)
 	}
+	if ssuo.mutation.IndexSortCleared() {
+		_spec.ClearField(sopstage.FieldIndexSort, field.TypeInt)
+	}
 	if ssuo.mutation.SopTaskCleared() {
 		edge := &sqlgraph.EdgeSpec{
 			Rel:     sqlgraph.M2O,

+ 15 - 0
internal/handler/routes.go

@@ -319,6 +319,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 					Path:    "/sop_task",
 					Handler: sop_task.GetSopTaskByIdHandler(serverCtx),
 				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/sop_task/detail",
+					Handler: sop_task.GetSopTaskDetailHandler(serverCtx),
+				},
 			}...,
 		),
 		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
@@ -353,6 +358,16 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 					Path:    "/sop_stage",
 					Handler: sop_stage.GetSopStageByIdHandler(serverCtx),
 				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/sop_stage/detail",
+					Handler: sop_stage.GetSopStageDetailHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/sop_stage/move",
+					Handler: sop_stage.MoveSopStageHandler(serverCtx),
+				},
 			}...,
 		),
 		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),

+ 1 - 1
internal/handler/sop_node/delete_sop_node_handler.go

@@ -27,7 +27,7 @@ import (
 
 func DeleteSopNodeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
-		var req types.IDsReq
+		var req types.IDReq
 		if err := httpx.Parse(r, &req, true); err != nil {
 			httpx.ErrorCtx(r.Context(), w, err)
 			return

+ 2 - 2
internal/handler/sop_stage/delete_sop_stage_handler.go

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

+ 44 - 0
internal/handler/sop_stage/get_sop_stage_detail_handler.go

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

+ 44 - 0
internal/handler/sop_stage/move_sop_stage_handler.go

@@ -0,0 +1,44 @@
+package sop_stage
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/sop_stage"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /sop_stage/move sop_stage MoveSopStage
+//
+// Get sop stage move | 移动阶段顺序
+//
+// Get sop stage move | 移动阶段顺序
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: SopStageMoveReq
+//
+// Responses:
+//  200: BaseMsgResp
+
+func MoveSopStageHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.SopStageMoveReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := sop_stage.NewMoveSopStageLogic(r.Context(), svcCtx)
+		resp, err := l.MoveSopStage(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

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

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

+ 14 - 9
internal/logic/sop_node/create_sop_node_logic.go

@@ -3,7 +3,7 @@ package sop_node
 import (
 	"context"
 	"wechat-api/ent/custom_types"
-
+	"wechat-api/ent/sopstage"
 	"wechat-api/internal/svc"
 	"wechat-api/internal/types"
 	"wechat-api/internal/utils/dberrorhandler"
@@ -28,12 +28,17 @@ func NewCreateSopNodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Cre
 }
 
 func (l *CreateSopNodeLogic) CreateSopNode(req *types.SopNodeInfo) (*types.BaseMsgResp, error) {
-	conditionList := make([]custom_types.Condition, len(req.ConditionList))
-	for i, condition := range req.ConditionList {
-		conditionList[i] = custom_types.Condition{
-			Equal:       condition.Equal,
-			LabelIdList: condition.LabelIdList,
-		}
+	// 根据 id 关联查询处 task 信息,并判断 status 是否为 1
+	data, err := l.svcCtx.DB.SopStage.Query().
+		Where(sopstage.ID(*req.StageId)).
+		WithSopTask().
+		Only(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+	task := data.Edges.SopTask
+	if task.Status != 1 {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
 
 	actionMessage := make([]custom_types.Action, len(req.ActionMessage))
@@ -44,13 +49,13 @@ func (l *CreateSopNodeLogic) CreateSopNode(req *types.SopNodeInfo) (*types.BaseM
 		}
 	}
 
-	_, err := l.svcCtx.DB.SopNode.Create().
+	_, err = l.svcCtx.DB.SopNode.Create().
 		SetNotNilStatus(req.Status).
 		SetNotNilStageID(req.StageId).
 		SetNotNilParentID(req.ParentId).
 		SetNotNilName(req.Name).
 		SetNotNilConditionType(req.ConditionType).
-		SetNotNilConditionList(conditionList).
+		SetNotNilConditionList(req.ConditionList).
 		SetNotNilActionMessage(actionMessage).
 		SetNotNilActionLabel(req.ActionLabel).
 		Save(l.ctx)

+ 75 - 10
internal/logic/sop_node/delete_sop_node_logic.go

@@ -2,14 +2,15 @@ package sop_node
 
 import (
 	"context"
+	"wechat-api/ent"
 
-    "wechat-api/ent/sopnode"
-    "wechat-api/internal/svc"
-    "wechat-api/internal/types"
-    "wechat-api/internal/utils/dberrorhandler"
+	"wechat-api/ent/sopnode"
+	"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"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/zeromicro/go-zero/core/logx"
 )
 
 type DeleteSopNodeLogic struct {
@@ -26,12 +27,76 @@ func NewDeleteSopNodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Del
 	}
 }
 
-func (l *DeleteSopNodeLogic) DeleteSopNode(req *types.IDsReq) (*types.BaseMsgResp, error) {
-	_, err := l.svcCtx.DB.SopNode.Delete().Where(sopnode.IDIn(req.Ids...)).Exec(l.ctx)
+func (l *DeleteSopNodeLogic) DeleteSopNode(req *types.IDReq) (*types.BaseMsgResp, error) {
+	// 根据 id 关联查询处 task 信息,并判断 status 是否为 1
+	data, err := l.svcCtx.DB.SopNode.Query().
+		Where(sopnode.ID(req.Id)).
+		WithSopStage(func(query *ent.SopStageQuery) {
+			query.WithSopTask()
+		}).
+		Only(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+	task := data.Edges.SopStage.Edges.SopTask
+	if task.Status != 1 {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	// 开始一个新的事务
+	tx, err := l.svcCtx.DB.Tx(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	// 确保在函数返回时回滚事务,除非提交事务成功
+	defer func() {
+		if err != nil {
+			if rbErr := tx.Rollback(); rbErr != nil {
+				l.Logger.Errorf("tx rollback error: %v", rbErr)
+			}
+		} else {
+			if commitErr := tx.Commit(); commitErr != nil {
+				err = commitErr
+			}
+		}
+	}()
+
+	// 首先删除所有子节点
+	err = l.deleteChildren(tx, req.Id)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
 
-    if err != nil {
+	// 删除节点本身
+	_, err = tx.SopNode.Delete().Where(sopnode.IDIn(req.Id)).Exec(l.ctx)
+	if err != nil {
+		_ = tx.Rollback()
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
 
-    return &types.BaseMsgResp{Msg: errormsg.DeleteSuccess}, nil
+	return &types.BaseMsgResp{Msg: errormsg.DeleteSuccess}, nil
+}
+
+func (l *DeleteSopNodeLogic) deleteChildren(tx *ent.Tx, parentID uint64) error {
+	// 查找所有子节点
+	children, err := tx.SopNode.Query().Where(sopnode.ParentID(parentID)).All(l.ctx)
+	if err != nil {
+		return err
+	}
+
+	// 对每个子节点递归执行删除操作
+	for _, child := range children {
+		err := l.deleteChildren(tx, child.ID)
+		if err != nil {
+			return err
+		}
+
+		_, err = tx.SopNode.Delete().Where(sopnode.ID(child.ID)).Exec(l.ctx)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
 }

+ 1 - 9
internal/logic/sop_node/get_sop_node_by_id_logic.go

@@ -33,14 +33,6 @@ func (l *GetSopNodeByIdLogic) GetSopNodeById(req *types.IDReq) (*types.SopNodeIn
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
 
-	conditionList := make([]types.Condition, len(data.ConditionList))
-	for i, condition := range data.ConditionList {
-		conditionList[i] = types.Condition{
-			Equal:       condition.Equal,
-			LabelIdList: condition.LabelIdList,
-		}
-	}
-
 	actionMessage := make([]types.Action, len(data.ActionMessage))
 	for i, condition := range data.ActionMessage {
 		actionMessage[i] = types.Action{
@@ -65,7 +57,7 @@ func (l *GetSopNodeByIdLogic) GetSopNodeById(req *types.IDReq) (*types.SopNodeIn
 			ParentId:      &data.ParentID,
 			Name:          &data.Name,
 			ConditionType: &data.ConditionType,
-			ConditionList: conditionList,
+			ConditionList: data.ConditionList,
 			ActionMessage: actionMessage,
 			ActionLabel:   data.ActionLabel,
 		},

+ 1 - 9
internal/logic/sop_node/get_sop_node_list_logic.go

@@ -45,14 +45,6 @@ func (l *GetSopNodeListLogic) GetSopNodeList(req *types.SopNodeListReq) (*types.
 	resp.Data.Total = data.PageDetails.Total
 
 	for _, v := range data.List {
-		conditionList := make([]types.Condition, len(v.ConditionList))
-		for i, condition := range v.ConditionList {
-			conditionList[i] = types.Condition{
-				Equal:       condition.Equal,
-				LabelIdList: condition.LabelIdList,
-			}
-		}
-
 		actionMessage := make([]types.Action, len(v.ActionMessage))
 		for i, condition := range v.ActionMessage {
 			actionMessage[i] = types.Action{
@@ -73,7 +65,7 @@ func (l *GetSopNodeListLogic) GetSopNodeList(req *types.SopNodeListReq) (*types.
 				ParentId:      &v.ParentID,
 				Name:          &v.Name,
 				ConditionType: &v.ConditionType,
-				ConditionList: conditionList,
+				ConditionList: v.ConditionList,
 				ActionMessage: actionMessage,
 				ActionLabel:   v.ActionLabel,
 			})

+ 18 - 8
internal/logic/sop_node/update_sop_node_logic.go

@@ -2,7 +2,9 @@ package sop_node
 
 import (
 	"context"
+	"wechat-api/ent"
 	"wechat-api/ent/custom_types"
+	"wechat-api/ent/sopnode"
 
 	"wechat-api/internal/svc"
 	"wechat-api/internal/types"
@@ -27,12 +29,20 @@ func NewUpdateSopNodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Upd
 }
 
 func (l *UpdateSopNodeLogic) UpdateSopNode(req *types.SopNodeInfo) (*types.BaseMsgResp, error) {
-	conditionList := make([]custom_types.Condition, len(req.ConditionList))
-	for i, condition := range req.ConditionList {
-		conditionList[i] = custom_types.Condition{
-			Equal:       condition.Equal,
-			LabelIdList: condition.LabelIdList,
-		}
+	// 根据 id 关联查询处 task 信息,并判断 status 是否为 1
+	data, err := l.svcCtx.DB.SopNode.Query().
+		Where(sopnode.ID(*req.Id)).
+		WithSopStage(func(query *ent.SopStageQuery) {
+			query.WithSopTask()
+		}).
+		Only(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	task := data.Edges.SopStage.Edges.SopTask
+	if task.Status != 1 {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
 
 	actionMessage := make([]custom_types.Action, len(req.ActionMessage))
@@ -43,13 +53,13 @@ func (l *UpdateSopNodeLogic) UpdateSopNode(req *types.SopNodeInfo) (*types.BaseM
 		}
 	}
 
-	err := l.svcCtx.DB.SopNode.UpdateOneID(*req.Id).
+	err = l.svcCtx.DB.SopNode.UpdateOneID(*req.Id).
 		SetNotNilStatus(req.Status).
 		SetNotNilStageID(req.StageId).
 		SetNotNilParentID(req.ParentId).
 		SetNotNilName(req.Name).
 		SetNotNilConditionType(req.ConditionType).
-		SetNotNilConditionList(conditionList).
+		SetNotNilConditionList(req.ConditionList).
 		SetNotNilActionMessage(actionMessage).
 		SetNotNilActionLabel(req.ActionLabel).
 		Exec(l.ctx)

+ 17 - 2
internal/logic/sop_stage/create_sop_stage_logic.go

@@ -3,6 +3,7 @@ package sop_stage
 import (
 	"context"
 	"wechat-api/ent/custom_types"
+	"wechat-api/ent/sopstage"
 
 	"wechat-api/internal/svc"
 	"wechat-api/internal/types"
@@ -28,6 +29,20 @@ func NewCreateSopStageLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Cr
 }
 
 func (l *CreateSopStageLogic) CreateSopStage(req *types.SopStageInfo) (*types.BaseMsgResp, error) {
+	// 根据 task_id 查询 task 是否存在
+	task, err := l.svcCtx.DB.SopTask.Get(l.ctx, *req.TaskId)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+	// 判断 task 的状态是否为 1
+	if task.Status != 1 {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	// 查询某 task_id 下的 stage 的数量
+	count, err := l.svcCtx.DB.SopStage.Query().Where(sopstage.TaskIDEQ(*req.TaskId)).Count(l.ctx)
+	count += 1
+
 	conditionList := make([]custom_types.Condition, len(req.ConditionList))
 	for i, condition := range req.ConditionList {
 		conditionList[i] = custom_types.Condition{
@@ -44,7 +59,7 @@ func (l *CreateSopStageLogic) CreateSopStage(req *types.SopStageInfo) (*types.Ba
 		}
 	}
 
-	_, err := l.svcCtx.DB.SopStage.Create().
+	_, err = l.svcCtx.DB.SopStage.Create().
 		SetNotNilStatus(req.Status).
 		SetNotNilTaskID(req.TaskId).
 		SetNotNilName(req.Name).
@@ -53,7 +68,7 @@ func (l *CreateSopStageLogic) CreateSopStage(req *types.SopStageInfo) (*types.Ba
 		SetNotNilConditionList(conditionList).
 		SetNotNilActionMessage(actionMessage).
 		SetNotNilActionLabel(req.ActionLabel).
-		SetNotNilIndexSort(req.IndexSort).
+		SetNotNilIndexSort(&count).
 		Save(l.ctx)
 
 	if err != nil {

+ 55 - 10
internal/logic/sop_stage/delete_sop_stage_logic.go

@@ -2,14 +2,15 @@ package sop_stage
 
 import (
 	"context"
+	"wechat-api/ent/sopnode"
 
-    "wechat-api/ent/sopstage"
-    "wechat-api/internal/svc"
-    "wechat-api/internal/types"
-    "wechat-api/internal/utils/dberrorhandler"
+	"wechat-api/ent/sopstage"
+	"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"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/zeromicro/go-zero/core/logx"
 )
 
 type DeleteSopStageLogic struct {
@@ -26,12 +27,56 @@ func NewDeleteSopStageLogic(ctx context.Context, svcCtx *svc.ServiceContext) *De
 	}
 }
 
-func (l *DeleteSopStageLogic) DeleteSopStage(req *types.IDsReq) (*types.BaseMsgResp, error) {
-	_, err := l.svcCtx.DB.SopStage.Delete().Where(sopstage.IDIn(req.Ids...)).Exec(l.ctx)
+func (l *DeleteSopStageLogic) DeleteSopStage(req *types.IDReq) (*types.BaseMsgResp, error) {
+	// 根据 id 关联查询 task 信息,并判断 task 的状态是否为 1
+	data, err := l.svcCtx.DB.SopStage.Query().
+		Where(sopstage.ID(req.Id)).
+		WithSopTask().
+		Only(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+	task := data.Edges.SopTask
+	if task.Status != 1 {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	// 开始一个新的事务
+	tx, err := l.svcCtx.DB.Tx(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	// 确保在函数返回时回滚事务,除非提交事务成功
+	defer func() {
+		if err != nil {
+			if rbErr := tx.Rollback(); rbErr != nil {
+				l.Logger.Errorf("tx rollback error: %v", rbErr)
+			}
+		} else {
+			if commitErr := tx.Commit(); commitErr != nil {
+				err = commitErr
+			}
+		}
+	}()
+
+	// 获取阶段信息
+	stage, err := tx.SopStage.Get(l.ctx, req.Id)
+	indexSort := stage.IndexSort
+	taskId := stage.TaskID
+
+	_, err = tx.SopStage.Delete().Where(sopstage.ID(req.Id)).Exec(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	// 将具有同一 task_id 且 index_sort 大于当前阶段的阶段 index_sort 减一
+	err = tx.SopStage.Update().Where(sopstage.TaskIDEQ(taskId), sopstage.IndexSortGT(indexSort)).AddIndexSort(-1).Exec(l.ctx)
 
-    if err != nil {
+	_, err = tx.SopNode.Delete().Where(sopnode.StageID(req.Id)).Exec(l.ctx)
+	if err != nil {
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
 
-    return &types.BaseMsgResp{Msg: errormsg.DeleteSuccess}, nil
+	return &types.BaseMsgResp{Msg: errormsg.DeleteSuccess}, nil
 }

+ 21 - 2
internal/logic/sop_stage/get_sop_stage_by_id_logic.go

@@ -2,7 +2,7 @@ package sop_stage
 
 import (
 	"context"
-
+	"wechat-api/ent/sopstage"
 	"wechat-api/internal/svc"
 	"wechat-api/internal/types"
 	"wechat-api/internal/utils/dberrorhandler"
@@ -28,7 +28,10 @@ func NewGetSopStageByIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *G
 }
 
 func (l *GetSopStageByIdLogic) GetSopStageById(req *types.IDReq) (*types.SopStageInfoResp, error) {
-	data, err := l.svcCtx.DB.SopStage.Get(l.ctx, req.Id)
+	data, err := l.svcCtx.DB.SopStage.Query().
+		Where(sopstage.ID(req.Id)).
+		WithStageNodes().
+		Only(l.ctx)
 	if err != nil {
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
@@ -49,6 +52,21 @@ func (l *GetSopStageByIdLogic) GetSopStageById(req *types.IDReq) (*types.SopStag
 		}
 	}
 
+	nodeList := make([]types.SopNodeInfo, 0)
+	if data.Edges.StageNodes != nil {
+		for _, sn := range data.Edges.StageNodes {
+			nodeList = append(nodeList, types.SopNodeInfo{
+				BaseIDInfo: types.BaseIDInfo{
+					Id: &sn.ID,
+				},
+				Status:        &sn.Status,
+				ParentId:      &sn.ParentID,
+				Name:          &sn.Name,
+				ConditionType: &sn.ConditionType,
+			})
+		}
+	}
+
 	return &types.SopStageInfoResp{
 		BaseDataInfo: types.BaseDataInfo{
 			Code: 0,
@@ -69,6 +87,7 @@ func (l *GetSopStageByIdLogic) GetSopStageById(req *types.IDReq) (*types.SopStag
 			ActionMessage:     actionMessage,
 			ActionLabel:       data.ActionLabel,
 			IndexSort:         &data.IndexSort,
+			NodeList:          nodeList,
 		},
 	}, nil
 }

+ 76 - 0
internal/logic/sop_stage/get_sop_stage_detail_logic.go

@@ -0,0 +1,76 @@
+package sop_stage
+
+import (
+	"context"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/suyuan32/simple-admin-common/utils/pointy"
+	"wechat-api/ent/sopstage"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetSopStageDetailLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewGetSopStageDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetSopStageDetailLogic {
+	return &GetSopStageDetailLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *GetSopStageDetailLogic) GetSopStageDetail(req *types.IDReq) (resp *types.SopStageInfoResp, err error) {
+	data, err := l.svcCtx.DB.SopStage.Query().
+		Where(sopstage.ID(req.Id)).
+		WithStageNodes().
+		Only(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	conditionList := make([]types.Condition, len(data.ConditionList))
+	for i, condition := range data.ConditionList {
+		conditionList[i] = types.Condition{
+			Equal:       condition.Equal,
+			LabelIdList: condition.LabelIdList,
+		}
+	}
+
+	actionMessage := make([]types.Action, len(data.ActionMessage))
+	for i, condition := range data.ActionMessage {
+		actionMessage[i] = types.Action{
+			Type:    condition.Type,
+			Content: condition.Content,
+		}
+	}
+
+	return &types.SopStageInfoResp{
+		BaseDataInfo: types.BaseDataInfo{
+			Code: 0,
+			Msg:  errormsg.Success,
+		},
+		Data: types.SopStageInfo{
+			BaseIDInfo: types.BaseIDInfo{
+				Id:        &data.ID,
+				CreatedAt: pointy.GetPointer(data.CreatedAt.UnixMilli()),
+				UpdatedAt: pointy.GetPointer(data.UpdatedAt.UnixMilli()),
+			},
+			Status:            &data.Status,
+			TaskId:            &data.TaskID,
+			Name:              &data.Name,
+			ConditionType:     &data.ConditionType,
+			ConditionOperator: &data.ConditionOperator,
+			ConditionList:     conditionList,
+			ActionMessage:     actionMessage,
+			ActionLabel:       data.ActionLabel,
+			IndexSort:         &data.IndexSort,
+		},
+	}, nil
+}

+ 83 - 0
internal/logic/sop_stage/move_sop_stage_logic.go

@@ -0,0 +1,83 @@
+package sop_stage
+
+import (
+	"context"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"wechat-api/ent/sopstage"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type MoveSopStageLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewMoveSopStageLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MoveSopStageLogic {
+	return &MoveSopStageLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *MoveSopStageLogic) MoveSopStage(req *types.SopStageMoveReq) (resp *types.BaseMsgResp, err error) {
+	// 获取待移动阶段顺序
+	data, err := l.svcCtx.DB.SopStage.Get(l.ctx, *req.Id)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+	taskId := data.TaskID
+	currentIndexSort := data.IndexSort
+	targetIndexSort := currentIndexSort + *req.Offset
+
+	// 开始一个新的事务
+	tx, err := l.svcCtx.DB.Tx(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	// 确保在函数返回时回滚事务,除非提交事务成功
+	defer func() {
+		if err != nil {
+			if rbErr := tx.Rollback(); rbErr != nil {
+				l.Logger.Errorf("tx rollback error: %v", rbErr)
+			}
+		} else {
+			if commitErr := tx.Commit(); commitErr != nil {
+				err = commitErr
+			}
+		}
+	}()
+
+	// 更改目标阶段顺序
+	affected, err := tx.SopStage.Update().
+		Where(
+			sopstage.TaskID(taskId),
+			sopstage.IndexSort(targetIndexSort),
+		).
+		SetNotNilIndexSort(&currentIndexSort).
+		Save(l.ctx)
+
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	if affected == 0 {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	// 更改待移动阶段顺序
+	err = tx.SopStage.UpdateOneID(*req.Id).
+		SetNotNilIndexSort(&targetIndexSort).
+		Exec(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	return &types.BaseMsgResp{Msg: errormsg.UpdateSuccess}, nil
+}

+ 15 - 1
internal/logic/sop_stage/update_sop_stage_logic.go

@@ -3,6 +3,7 @@ package sop_stage
 import (
 	"context"
 	"wechat-api/ent/custom_types"
+	"wechat-api/ent/sopstage"
 
 	"wechat-api/internal/svc"
 	"wechat-api/internal/types"
@@ -27,6 +28,19 @@ func NewUpdateSopStageLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Up
 }
 
 func (l *UpdateSopStageLogic) UpdateSopStage(req *types.SopStageInfo) (*types.BaseMsgResp, error) {
+	// 根据 id 关联查询 task 信息,并判断 task 的状态是否为 1
+	data, err := l.svcCtx.DB.SopStage.Query().
+		Where(sopstage.ID(*req.Id)).
+		WithSopTask().
+		Only(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+	task := data.Edges.SopTask
+	if task.Status != 1 {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
 	conditionList := make([]custom_types.Condition, len(req.ConditionList))
 	for i, condition := range req.ConditionList {
 		conditionList[i] = custom_types.Condition{
@@ -43,7 +57,7 @@ func (l *UpdateSopStageLogic) UpdateSopStage(req *types.SopStageInfo) (*types.Ba
 		}
 	}
 
-	err := l.svcCtx.DB.SopStage.UpdateOneID(*req.Id).
+	err = l.svcCtx.DB.SopStage.UpdateOneID(*req.Id).
 		SetNotNilStatus(req.Status).
 		SetNotNilTaskID(req.TaskId).
 		SetNotNilName(req.Name).

+ 18 - 0
internal/logic/sop_task/get_sop_task_by_id_logic.go

@@ -37,6 +37,23 @@ func (l *GetSopTaskByIdLogic) GetSopTaskById(req *types.IDReq) (*types.SopTaskIn
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
 
+	stageList := make([]types.SopStageInfo, 0)
+	if data.Edges.TaskStages != nil {
+		for _, ts := range data.Edges.TaskStages {
+			stageList = append(stageList, types.SopStageInfo{
+				BaseIDInfo: types.BaseIDInfo{
+					Id: &ts.ID,
+				},
+				Status:            &ts.Status,
+				TaskId:            &ts.TaskID,
+				Name:              &ts.Name,
+				ConditionType:     &ts.ConditionType,
+				ConditionOperator: &ts.ConditionOperator,
+				IndexSort:         &ts.IndexSort,
+			})
+		}
+	}
+
 	return &types.SopTaskInfoResp{
 		BaseDataInfo: types.BaseDataInfo{
 			Code: 0,
@@ -55,6 +72,7 @@ func (l *GetSopTaskByIdLogic) GetSopTaskById(req *types.IDReq) (*types.SopTaskIn
 			PlanStartTime: pointy.GetUnixMilliPointer(data.PlanStartTime.UnixMilli()),
 			PlanEndTime:   pointy.GetUnixMilliPointer(data.PlanEndTime.UnixMilli()),
 			CreatorId:     &data.CreatorID,
+			StageList:     stageList,
 		},
 	}, nil
 }

+ 58 - 0
internal/logic/sop_task/get_sop_task_detail_logic.go

@@ -0,0 +1,58 @@
+package sop_task
+
+import (
+	"context"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/suyuan32/simple-admin-common/utils/pointy"
+	"wechat-api/ent/soptask"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetSopTaskDetailLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewGetSopTaskDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetSopTaskDetailLogic {
+	return &GetSopTaskDetailLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *GetSopTaskDetailLogic) GetSopTaskDetail(req *types.IDReq) (resp *types.SopTaskInfoResp, err error) {
+	data, err := l.svcCtx.DB.SopTask.Query().
+		Where(soptask.ID(req.Id)).
+		WithTaskStages().
+		Only(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	return &types.SopTaskInfoResp{
+		BaseDataInfo: types.BaseDataInfo{
+			Code: 0,
+			Msg:  errormsg.Success,
+		},
+		Data: types.SopTaskInfo{
+			BaseIDInfo: types.BaseIDInfo{
+				Id:        &data.ID,
+				CreatedAt: pointy.GetPointer(data.CreatedAt.UnixMilli()),
+				UpdatedAt: pointy.GetPointer(data.UpdatedAt.UnixMilli()),
+			},
+			Status:        &data.Status,
+			Name:          &data.Name,
+			BotWxidList:   data.BotWxidList,
+			Type:          &data.Type,
+			PlanStartTime: pointy.GetUnixMilliPointer(data.PlanStartTime.UnixMilli()),
+			PlanEndTime:   pointy.GetUnixMilliPointer(data.PlanEndTime.UnixMilli()),
+			CreatorId:     &data.CreatorID,
+		},
+	}, nil
+}

+ 21 - 14
internal/logic/sop_task/update_sop_task_logic.go

@@ -2,12 +2,10 @@ package sop_task
 
 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"
@@ -28,19 +26,28 @@ func NewUpdateSopTaskLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Upd
 }
 
 func (l *UpdateSopTaskLogic) UpdateSopTask(req *types.SopTaskInfo) (*types.BaseMsgResp, error) {
-    err := l.svcCtx.DB.SopTask.UpdateOneID(*req.Id).
-			SetNotNilStatus(req.Status).
-			SetNotNilName(req.Name).
-			SetNotNilBotWxidList(req.BotWxidList).
-			SetNotNilType(req.Type).
-			SetNotNilPlanStartTime(pointy.GetTimeMilliPointer(req.PlanStartTime)).
-			SetNotNilPlanEndTime(pointy.GetTimeMilliPointer(req.PlanEndTime)).
-			SetNotNilCreatorID(req.CreatorId).
-			Exec(l.ctx)
-
-    if err != nil {
+	// 根据 id 查询 task 信息,如果 Status 的值不为 1,则不允许修改
+	task, err := l.svcCtx.DB.SopTask.Get(l.ctx, *req.Id)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+	if task.Status != 1 {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	err = l.svcCtx.DB.SopTask.UpdateOneID(*req.Id).
+		SetNotNilStatus(req.Status).
+		SetNotNilName(req.Name).
+		SetNotNilBotWxidList(req.BotWxidList).
+		SetNotNilType(req.Type).
+		SetNotNilPlanStartTime(pointy.GetTimeMilliPointer(req.PlanStartTime)).
+		SetNotNilPlanEndTime(pointy.GetTimeMilliPointer(req.PlanEndTime)).
+		SetNotNilCreatorID(req.CreatorId).
+		Exec(l.ctx)
+
+	if err != nil {
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
 
-    return &types.BaseMsgResp{Msg: errormsg.UpdateSuccess}, nil
+	return &types.BaseMsgResp{Msg: errormsg.UpdateSuccess}, nil
 }

+ 57 - 41
internal/types/types.go

@@ -221,8 +221,8 @@ type BaseUUIDInfo struct {
 }
 
 type Condition struct {
-	Equal       int   `json:"equal"`
-	LabelIdList []int `json:"labelIdList"`
+	Equal       int      `json:"equal"`
+	LabelIdList []uint64 `json:"labelIdList"`
 }
 
 type Action struct {
@@ -673,26 +673,6 @@ type LabelSelectListInfo struct {
 	Value *uint64 `json:"value,optional"`
 }
 
-// The response data of sop task information | SopTask信息
-// swagger:model SopTaskInfo
-type SopTaskInfo struct {
-	BaseIDInfo
-	// Status 1: normal 2: ban | 状态 1 正常 2 禁用
-	Status *uint8 `json:"status,optional"`
-	// SOP 任务名称
-	Name *string `json:"name,optional"`
-	// 机器人微信 id 列表
-	BotWxidList []string `json:"botWxidList,optional"`
-	// 标签类型:1好友,2群组,3企业微信联系人
-	Type *int `json:"type,optional"`
-	// 任务计划开始时间
-	PlanStartTime *int64 `json:"planStartTime,optional"`
-	// 任务计划结束时间
-	PlanEndTime *int64 `json:"planEndTime,optional"`
-	// 创建者 id
-	CreatorId *string `json:"creatorId,optional"`
-}
-
 // The response data of sop task list | SopTask列表数据
 // swagger:model SopTaskListResp
 type SopTaskListResp struct {
@@ -749,6 +729,56 @@ type SopStageInfo struct {
 	ActionLabel []int `json:"actionLabel,optional"`
 	// 阶段顺序
 	IndexSort *int `json:"indexSort,optional"`
+	// sop 任务信息
+	TaskInfo *SopTaskInfo `json:"taskInfo,optional"`
+	// node 信息
+	NodeList []SopNodeInfo `json:"nodeList,optional"`
+}
+
+// The response data of sop task information | SopTask信息
+// swagger:model SopTaskInfo
+type SopTaskInfo struct {
+	BaseIDInfo
+	// Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	Status *uint8 `json:"status,optional"`
+	// SOP 任务名称
+	Name *string `json:"name,optional"`
+	// 机器人微信 id 列表
+	BotWxidList []string `json:"botWxidList,optional"`
+	// 标签类型:1好友,2群组,3企业微信联系人
+	Type *int `json:"type,optional"`
+	// 任务计划开始时间
+	PlanStartTime *int64 `json:"planStartTime,optional"`
+	// 任务计划结束时间
+	PlanEndTime *int64 `json:"planEndTime,optional"`
+	// 创建者 id
+	CreatorId *string `json:"creatorId,optional"`
+	// 阶段信息
+	StageList []SopStageInfo `json:"stageList,optional"`
+}
+
+// The response data of sop node information | SopNode信息
+// swagger:model SopNodeInfo
+type SopNodeInfo struct {
+	BaseIDInfo
+	// Status 1: normal 2: ban | 状态 1 正常 2 禁用
+	Status *uint8 `json:"status,optional"`
+	// 阶段 ID
+	StageId *uint64 `json:"stageId,optional"`
+	// 父节点 ID
+	ParentId *uint64 `json:"parentId,optional"`
+	// 节点名称
+	Name *string `json:"name,optional"`
+	// 触发条件类型 1 客户回复后触发 2 超时后触发
+	ConditionType *int `json:"conditionType,optional"`
+	// 触发语义列表 当为空时则代表用户回复任意内容后触发
+	ConditionList []string `json:"conditionList,optional"`
+	// 命中后发送的消息内容
+	ActionMessage []Action `json:"actionMessage,optional"`
+	// 命中后需要打的标签
+	ActionLabel []int `json:"actionLabel,optional"`
+	// 阶段信息
+	StageInfo *SopStageInfo `json:"stageInfo,optional"`
 }
 
 // The response data of sop stage list | SopStage列表数据
@@ -783,26 +813,12 @@ type SopStageInfoResp struct {
 	Data SopStageInfo `json:"data"`
 }
 
-// The response data of sop node information | SopNode信息
-// swagger:model SopNodeInfo
-type SopNodeInfo struct {
+// Move sop stage request params | 移动阶段请求参数
+// swagger:model SopStageMoveReq
+type SopStageMoveReq struct {
 	BaseIDInfo
-	// Status 1: normal 2: ban | 状态 1 正常 2 禁用
-	Status *uint8 `json:"status,optional"`
-	// 阶段 ID
-	StageId *uint64 `json:"stageId,optional"`
-	// 父节点 ID
-	ParentId *int `json:"parentId,optional"`
-	// 节点名称
-	Name *string `json:"name,optional"`
-	// 触发条件类型 1 客户回复后触发 2 超时后触发
-	ConditionType *int `json:"conditionType,optional"`
-	// 触发语义列表 当为空时则代表用户回复任意内容后触发
-	ConditionList []Condition `json:"conditionList,optional"`
-	// 命中后发送的消息内容
-	ActionMessage []Action `json:"actionMessage,optional"`
-	// 命中后需要打的标签
-	ActionLabel []int `json:"actionLabel,optional"`
+	// 阶段名称
+	Offset *int `json:"offset,optional"`
 }
 
 // The response data of sop node list | SopNode列表数据