[add] Goto & 修复一些BUG

This commit is contained in:
Max 2021-11-27 15:33:53 +08:00
parent 9b59d3188e
commit d6268c41af
3 changed files with 114 additions and 32 deletions

View file

@ -128,6 +128,19 @@ func ArrayUnique(columns []interface{}) []interface{} {
return res
}
// ArrayStringUnique 数组排重
func ArrayStringUnique(columns []string) []string {
res := []string{}
m := make(map[string]bool)
for _, key := range columns {
if _, ok := m[key]; !ok {
m[key] = true
res = append(res, key)
}
}
return res
}
// OfArrayPluckValue Any 转 ArrayPluckValue
func OfArrayPluckValue(any interface{}) ArrayPluckValue {
content, err := jsoniter.Marshal(any)

View file

@ -136,12 +136,19 @@ func (workflow *WorkFlow) Open(uid int, id interface{}) map[string]interface{} {
if len(rows) > 0 {
return rows[0]
}
if workflow.Len() == 0 {
exception.New("工作流没有任何节点", 400).Throw()
}
users := map[string]interface{}{}
users[workflow.Nodes[0].Name] = uid
return map[string]interface{}{
"name": workflow.Name,
"data_id": id,
"node_name": workflow.Nodes[0].Name,
"user_id": uid,
"users": []interface{}{uid},
"users": users,
"status": "进行中",
"node_status": "进行中",
"input": map[string]interface{}{},
@ -171,7 +178,8 @@ func (workflow *WorkFlow) Save(uid int, name string, id interface{}, input Input
"node_name": name,
"user_id": uid,
}
users := []interface{}{uid}
users := map[string]interface{}{}
users[name] = uid
output := map[string]interface{}{}
nodeInput := map[string]interface{}{}
nodeInput[name] = input
@ -200,6 +208,29 @@ func (workflow *WorkFlow) Save(uid int, name string, id interface{}, input Input
func (workflow *WorkFlow) Status(uid int, id int, output map[string]interface{}) {
}
// Goto 工作流跳转
func (workflow *WorkFlow) Goto(uid int, id int, name string, output map[string]interface{}) map[string]interface{} {
wflow := workflow.Find(id)
users := map[string]interface{}{}
curr, _ := workflow.pickNode(wflow["node_name"].(string))
users[curr.Name] = uid
node, _ := workflow.pickNode(name)
output = workflow.MergeData(wflow["output"], output)
users = workflow.MergeUsers(wflow["users"], users)
nodeUID := node.GetUID(users)
mod := gou.Select("xiang.workflow")
mod.Save(map[string]interface{}{
"id": wflow["id"],
"output": output,
"node_name": name,
"node_status": "进行中",
"user_id": nodeUID,
"users": users,
"user_ids": workflow.UserIDs(users),
})
return workflow.Find(id)
}
// Next 下一个工作流
// uid 当前处理人ID, id 工作流ID
func (workflow *WorkFlow) Next(uid int, id int, output map[string]interface{}) map[string]interface{} {
@ -209,8 +240,10 @@ func (workflow *WorkFlow) Next(uid int, id int, output map[string]interface{}) m
exception.New("流程数据异常: 当前节点信息错误", 500).Ctx(currNode).Throw()
}
users := map[string]interface{}{}
users[currNode] = uid
output = workflow.MergeData(wflow["output"], output)
users := workflow.MergeUsers(wflow["users"], []interface{}{uid})
// 读取下一个节点
data := map[string]interface{}{
"$in": wflow["input"],
@ -220,13 +253,15 @@ func (workflow *WorkFlow) Next(uid int, id int, output map[string]interface{}) m
"$data": output,
}
nextNode := workflow.nextNode(currNode, data)
nextUID := nextNode.GetUID()
nextUID := nextNode.MakeUID()
users[nextNode.Name] = nextUID
// 更新数据
users = workflow.MergeUsers(wflow["users"], users)
mod := gou.Select("xiang.workflow")
mod.Save(map[string]interface{}{
"id": wflow["id"],
"output": wflow["output"],
"output": output,
"node_name": nextNode.Name,
"node_status": "进行中",
"user_id": nextUID,
@ -236,27 +271,36 @@ func (workflow *WorkFlow) Next(uid int, id int, output map[string]interface{}) m
return workflow.Find(id)
}
// GetUID 根据条件选择节点处理人
func (node *Node) GetUID() int {
// GetUID 读取节点相关人
func (node *Node) GetUID(users interface{}) int {
if users, ok := users.(map[string]interface{}); ok {
if uid, has := users[node.Name]; has {
return any.Of(uid).CInt()
}
}
return node.MakeUID()
}
// MakeUID 根据条件选择节点处理人
func (node *Node) MakeUID() int {
res := gou.NewProcess(node.User.Process, node.User.Args...).Run()
return any.Of(res).CInt()
}
// nextNode 查找下一个节点
func (workflow *WorkFlow) nextNode(currentNode string, data map[string]interface{}) *Node {
var curr *Node
nextIndex := -1
func (workflow *WorkFlow) pickNode(name string) (*Node, int) {
for i, node := range workflow.Nodes {
if node.Name == currentNode {
nextIndex = i + 1
curr = &node
break
if node.Name == name {
return &node, i
}
}
if nextIndex < 0 {
exception.New("流程数据异常: 未找到工作流节点", 500).Ctx(currentNode).Throw()
}
exception.New("流程数据异常: 未找到节点 %s", 500, name).Throw()
return nil, 0
}
// nextNode 查找下一个节点
func (workflow *WorkFlow) nextNode(currentNode string, data map[string]interface{}) *Node {
curr, index := workflow.pickNode(currentNode)
nextIndex := index + 1
if nextIndex == workflow.Len() {
exception.New("流程数据异常: 当前节点为最后一个节点", 500).Ctx(currentNode).Throw()
}
@ -311,30 +355,32 @@ func (workflow *WorkFlow) Conditions(conds []helper.Condition, data map[string]i
}
// UserIDs 读取用户ID
func (workflow *WorkFlow) UserIDs(users []interface{}) string {
func (workflow *WorkFlow) UserIDs(users map[string]interface{}) string {
userIDs := []string{}
for _, u := range users {
userIDs = append(userIDs, fmt.Sprintf("|%d|", u))
}
userIDs = helper.ArrayStringUnique(userIDs)
return strings.Join(userIDs, ",")
}
// MergeUsers 合并数据
func (workflow *WorkFlow) MergeUsers(data interface{}, new interface{}) []interface{} {
res, ok := data.([]interface{})
func (workflow *WorkFlow) MergeUsers(data interface{}, new interface{}) map[string]interface{} {
res, ok := data.(map[string]interface{})
if !ok {
return []interface{}{}
return map[string]interface{}{}
}
if new, ok := new.([]interface{}); ok {
for _, value := range new {
data = append(res, value)
if new, ok := new.(map[string]interface{}); ok {
for name, value := range new {
res[name] = value
}
}
return helper.ArrayUnique(res)
return res
}
// MergeData 合并数据
func (workflow *WorkFlow) MergeData(data interface{}, new interface{}) map[string]interface{} {
res, ok := data.(map[string]interface{})
if !ok {
return map[string]interface{}{}
@ -344,7 +390,6 @@ func (workflow *WorkFlow) MergeData(data interface{}, new interface{}) map[strin
for key, value := range new {
res[key] = value
}
res = new
}
return res
}
@ -355,9 +400,6 @@ func (workflow *WorkFlow) IsLastNode(name string) bool {
return workflow.Nodes[length-1].Name == name
}
// Goto 工作流跳转
func (workflow *WorkFlow) Goto(uid int, id int, node string, output map[string]interface{}) {}
// Len 节点数量
func (workflow *WorkFlow) Len() int {
return len(workflow.Nodes)

View file

@ -101,7 +101,7 @@ func TestOpen(t *testing.T) {
assert.Equal(t, "进行中", data.Get("node_status"))
assert.Equal(t, "进行中", data.Get("status"))
assert.Equal(t, int64(1), data.Get("user_id"))
assert.Equal(t, []interface{}{float64(1)}, data.Get("users"))
assert.Equal(t, float64(1), data.Get("users.选择商务负责人"))
// 清理数据
capsule.Query().From("xiang_workflow").Truncate()
@ -117,7 +117,7 @@ func TestOpenEmpty(t *testing.T) {
assert.Equal(t, "进行中", data.Get("node_status"))
assert.Equal(t, "进行中", data.Get("status"))
assert.Equal(t, 1, data.Get("user_id"))
assert.Equal(t, []interface{}{1}, data.Get("users"))
assert.Equal(t, 1, data.Get("users.选择商务负责人"))
}
func TestNext(t *testing.T) {
@ -175,6 +175,33 @@ func TestNextWhen(t *testing.T) {
capsule.Query().From("xiang_workflow").Truncate()
}
func TestGoto(t *testing.T) {
assignFlow := Select("assign")
wflow := assignFlow.Save(1, "选择商务负责人", 1, Input{
Data: map[string]interface{}{"id": 1, "name": "云主机"},
Form: map[string]interface{}{"biz_id": 1, "name": "张良明"},
})
id := any.Of(wflow["id"]).CInt()
assignFlow.Next(1, id, map[string]interface{}{
"项目名称": "测试项目",
"商务负责人名称": "林明波",
})
wflow = assignFlow.Goto(2, id, "选择商务负责人", map[string]interface{}{"审批结果": "驳回"})
data := maps.Of(wflow).Dot()
assert.Equal(t, true, data.Has("id"))
assert.Equal(t, "assign", data.Get("name"))
assert.Equal(t, "选择商务负责人", data.Get("node_name"))
assert.Equal(t, "进行中", data.Get("node_status"))
assert.Equal(t, "进行中", data.Get("status"))
assert.Equal(t, int64(1), data.Get("user_id"))
assert.Equal(t, float64(1), data.Get("users.选择商务负责人"))
assert.Equal(t, float64(2), data.Get("users.项目负责人审批"))
// 清理数据
capsule.Query().From("xiang_workflow").Truncate()
}
func check(t *testing.T) {
keys := []string{}
for key, workflow := range WorkFlows {