mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-02 23:40:24 +08:00
132 lines
3.9 KiB
Go
132 lines
3.9 KiB
Go
package application
|
|
|
|
import (
|
|
"context"
|
|
"mayfly-go/internal/flow/domain/entity"
|
|
"mayfly-go/internal/flow/imsg"
|
|
"mayfly-go/internal/flow/infra/persistence"
|
|
msgdto "mayfly-go/internal/msg/application/dto"
|
|
"mayfly-go/internal/pkg/event"
|
|
"mayfly-go/pkg/errorx"
|
|
"mayfly-go/pkg/global"
|
|
"strings"
|
|
|
|
"github.com/spf13/cast"
|
|
)
|
|
|
|
/******************* 用户任务节点 *******************/
|
|
|
|
const (
|
|
FlowNodeTypeUserTask entity.FlowNodeType = "usertask" // 用户任务
|
|
|
|
NrOfCompleted = "nrOfCompleted" // number of completed
|
|
NrOfAll = "nrOfAll" // 总候选人处理数
|
|
)
|
|
|
|
// UserTaskNode 用户任务节点
|
|
type UserTaskNode struct {
|
|
entity.FlowNode
|
|
|
|
CompletionCondition string `json:"completionCondition" form:"completionCondition"` // 完成条件,如会签{{.nrOfAll == .nrOfCompleted}}
|
|
Candidates []string `json:"candidates" form:"candidates"` // 节点处理候选人
|
|
}
|
|
|
|
// ToUserTaskNode 将标准节点转换成用户任务节点(方便取值)
|
|
func ToUserTaskNode(node *entity.FlowNode) *UserTaskNode {
|
|
return &UserTaskNode{
|
|
FlowNode: *node,
|
|
CompletionCondition: node.GetExtraString("completionCondition"),
|
|
Candidates: node.GetExtraStringSlice("candidates"),
|
|
}
|
|
}
|
|
|
|
type FlowNodeUserTaskApprovalMode string
|
|
|
|
// UserTaskNodeBehavior 用户任务节点行为处理器
|
|
type UserTaskNodeBehavior struct {
|
|
DefaultNodeBehavior
|
|
}
|
|
|
|
var _ NodeBehavior = (*UserTaskNodeBehavior)(nil)
|
|
|
|
func (h *UserTaskNodeBehavior) GetType() entity.FlowNodeType {
|
|
return FlowNodeTypeUserTask
|
|
}
|
|
|
|
func (h *UserTaskNodeBehavior) Validate(ctx context.Context, flowDef *entity.FlowDef, node *entity.FlowNode) error {
|
|
usertaskNode := ToUserTaskNode(node)
|
|
if len(usertaskNode.Candidates) == 0 {
|
|
return errorx.NewBizI(ctx, imsg.ErrUserTaskNodeCandidateNotEmpty, "name", node.Name)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (u *UserTaskNodeBehavior) Execute(ctx *ExecutionCtx) error {
|
|
flowNode := ctx.GetFlowNode()
|
|
usertaskNode := ToUserTaskNode(flowNode)
|
|
|
|
candidates := usertaskNode.Candidates
|
|
if len(candidates) == 0 {
|
|
return errorx.NewBiz("candidates cannot be empty")
|
|
}
|
|
|
|
taskApp := GetProcinstTaskApp()
|
|
task := &entity.ProcinstTask{
|
|
ProcinstId: ctx.GetProcinst().Id,
|
|
ExecutionId: ctx.Execution.Id,
|
|
NodeKey: flowNode.Key,
|
|
NodeName: flowNode.Name,
|
|
NodeType: flowNode.Type,
|
|
Status: entity.ProcinstTaskStatusProcess,
|
|
}
|
|
|
|
// 赋值总的候选人审批数量,会签时需要该值
|
|
task.Vars.Set(NrOfAll, len(candidates))
|
|
procinst := ctx.GetProcinst()
|
|
procinstId := procinst.Id
|
|
|
|
// 创建审批任务与审批候选人
|
|
return taskApp.Tx(ctx, func(c context.Context) error {
|
|
if err := taskApp.Save(c, task); err != nil {
|
|
return err
|
|
}
|
|
|
|
taskCandidates := make([]*entity.ProcinstTaskCandidate, 0, len(usertaskNode.Candidates))
|
|
for _, candidate := range usertaskNode.Candidates {
|
|
taskCandidates = append(taskCandidates, &entity.ProcinstTaskCandidate{
|
|
ProcinstId: procinstId,
|
|
TaskId: task.Id,
|
|
Candidate: candidate,
|
|
Status: entity.ProcinstTaskStatusProcess,
|
|
})
|
|
|
|
// 用户账号类型
|
|
if !strings.Contains(candidate, ":") {
|
|
params := map[string]any{
|
|
"creator": procinst.Creator,
|
|
"procdefName": procinst.ProcdefName,
|
|
"bizKey": procinst.BizKey,
|
|
"taskName": flowNode.Name,
|
|
"procinstRemark": procinst.Remark,
|
|
}
|
|
// 发送通知消息
|
|
global.EventBus.Publish(context.Background(), event.EventTopicBizMsgTmplSend, &msgdto.BizMsgTmplSend{
|
|
BizType: FlowTaskNotifyBizKey,
|
|
BizId: procinst.ProcdefId,
|
|
Params: params,
|
|
ReceiverIds: []uint64{cast.ToUint64(candidate)},
|
|
})
|
|
|
|
global.EventBus.Publish(context.Background(), event.EventTopicMsgTmplSend, &msgdto.MsgTmplSendEvent{
|
|
TmplChannel: msgdto.MsgTmplFlowUserTaskTodo,
|
|
Params: params,
|
|
ReceiverIds: []uint64{cast.ToUint64(candidate)},
|
|
})
|
|
}
|
|
}
|
|
|
|
return persistence.GetProcinstTaskCandidateRepo().BatchInsert(c, taskCandidates)
|
|
})
|
|
}
|