[remove] workfow table
This commit is contained in:
parent
5878b238c7
commit
f2f43e7f96
9 changed files with 55 additions and 1577 deletions
127
data/bindata.go
127
data/bindata.go
|
|
@ -49,7 +49,6 @@
|
||||||
// .tmp/data/yao/models/README.md
|
// .tmp/data/yao/models/README.md
|
||||||
// .tmp/data/yao/models/menu.mod.json
|
// .tmp/data/yao/models/menu.mod.json
|
||||||
// .tmp/data/yao/models/user.mod.json
|
// .tmp/data/yao/models/user.mod.json
|
||||||
// .tmp/data/yao/models/workflow.mod.json
|
|
||||||
// .tmp/data/yao/tables/README.md
|
// .tmp/data/yao/tables/README.md
|
||||||
// .tmp/data/yao/tables/menu.tab.json
|
// .tmp/data/yao/tables/menu.tab.json
|
||||||
// .tmp/data/yao/tables/user.tab.json
|
// .tmp/data/yao/tables/user.tab.json
|
||||||
|
|
@ -231,7 +230,7 @@ func initAppJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "init/app.json", size: 325, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "init/app.json", size: 325, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -251,7 +250,7 @@ func initChartsDashboardChartJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "init/charts/dashboard.chart.json", size: 8471, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "init/charts/dashboard.chart.json", size: 8471, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -271,7 +270,7 @@ func initFlowsAppMenuFlowJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "init/flows/app/menu.flow.json", size: 1327, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "init/flows/app/menu.flow.json", size: 1327, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -291,7 +290,7 @@ func initFormsPetFormJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "init/forms/pet.form.json", size: 87, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "init/forms/pet.form.json", size: 87, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -311,7 +310,7 @@ func initLangsZhCnGlobalYml() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "init/langs/zh-cn/global.yml", size: 90, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "init/langs/zh-cn/global.yml", size: 90, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -331,7 +330,7 @@ func initLangsZhHkLangsGlobalYml() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "init/langs/zh-hk/langs/global.yml", size: 88, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "init/langs/zh-hk/langs/global.yml", size: 88, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -351,7 +350,7 @@ func initLoginsAdminLoginJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "init/logins/admin.login.json", size: 277, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "init/logins/admin.login.json", size: 277, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -371,7 +370,7 @@ func initLoginsUserLoginJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "init/logins/user.login.json", size: 272, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "init/logins/user.login.json", size: 272, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -391,7 +390,7 @@ func initModelsPetModJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "init/models/pet.mod.json", size: 1418, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "init/models/pet.mod.json", size: 1418, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -411,7 +410,7 @@ func initPublicIndexHtml() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "init/public/index.html", size: 1373, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "init/public/index.html", size: 1373, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -431,7 +430,7 @@ func initScriptsDemoJs() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "init/scripts/demo.js", size: 334, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "init/scripts/demo.js", size: 334, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -451,7 +450,7 @@ func initScriptsStatJs() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "init/scripts/stat.js", size: 2235, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "init/scripts/stat.js", size: 2235, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -471,7 +470,7 @@ func initTablesPetTabJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "init/tables/pet.tab.json", size: 118, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "init/tables/pet.tab.json", size: 118, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -491,7 +490,7 @@ func publicIndexHtml() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "public/index.html", size: 11, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "public/index.html", size: 11, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -511,7 +510,7 @@ func uiIndexHtml() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "ui/index.html", size: 11, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "ui/index.html", size: 11, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -531,7 +530,7 @@ func xgenSetupIndexHtml() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "xgen/setup/index.html", size: 11, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "xgen/setup/index.html", size: 11, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -551,7 +550,7 @@ func xgenV09IndexHtml() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "xgen/v0.9/index.html", size: 14, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "xgen/v0.9/index.html", size: 14, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -571,7 +570,7 @@ func xgenV10IndexHtml() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "xgen/v1.0/index.html", size: 50, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "xgen/v1.0/index.html", size: 50, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -591,7 +590,7 @@ func xgenV10Layouts__indexAsyncJs() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "xgen/v1.0/layouts__index.async.js", size: 71, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "xgen/v1.0/layouts__index.async.js", size: 71, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -611,7 +610,7 @@ func xgenV10UmiJs() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "xgen/v1.0/umi.js", size: 71, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "xgen/v1.0/umi.js", size: 71, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -631,7 +630,7 @@ func yaoApisReadmeMd() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/apis/README.md", size: 13, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/apis/README.md", size: 13, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -651,7 +650,7 @@ func yaoApisChartHttpJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/apis/chart.http.json", size: 624, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/apis/chart.http.json", size: 624, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -671,7 +670,7 @@ func yaoApisImportHttpJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/apis/import.http.json", size: 1676, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/apis/import.http.json", size: 1676, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -691,7 +690,7 @@ func yaoApisPageHttpJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/apis/page.http.json", size: 609, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/apis/page.http.json", size: 609, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -711,7 +710,7 @@ func yaoApisStorageHttpJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/apis/storage.http.json", size: 1026, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/apis/storage.http.json", size: 1026, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -731,7 +730,7 @@ func yaoApisTableHttpJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/apis/table.http.json", size: 3213, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/apis/table.http.json", size: 3213, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -751,7 +750,7 @@ func yaoApisUserHttpJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/apis/user.http.json", size: 1453, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/apis/user.http.json", size: 1453, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -771,7 +770,7 @@ func yaoApisXiangHttpJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/apis/xiang.http.json", size: 1239, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/apis/xiang.http.json", size: 1239, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -791,7 +790,7 @@ func yaoDataAppJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/data/app.json", size: 277, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/data/app.json", size: 277, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -811,7 +810,7 @@ func yaoDataIcons404Png() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/data/icons/404.png", size: 9342, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/data/icons/404.png", size: 9342, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -831,7 +830,7 @@ func yaoDataIconsIconIcns() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/data/icons/icon.icns", size: 67465, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/data/icons/icon.icns", size: 67465, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -851,7 +850,7 @@ func yaoDataIconsIconIco() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/data/icons/icon.ico", size: 54993, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/data/icons/icon.ico", size: 54993, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -871,7 +870,7 @@ func yaoDataIconsIconPng() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/data/icons/icon.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/data/icons/icon.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -891,7 +890,7 @@ func yaoDataIndexHtml() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/data/index.html", size: 282, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/data/index.html", size: 282, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -911,7 +910,7 @@ func yaoFieldsModelTransJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/fields/model.trans.json", size: 14959, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/fields/model.trans.json", size: 14959, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -931,7 +930,7 @@ func yaoFlowsReadmeMd() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/flows/README.md", size: 12, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/flows/README.md", size: 12, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -951,7 +950,7 @@ func yaoFlowsAdminGuardFlowJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/flows/admin/guard.flow.json", size: 559, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/flows/admin/guard.flow.json", size: 559, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -971,7 +970,7 @@ func yaoFlowsMenuFlowJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/flows/menu.flow.json", size: 1045, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/flows/menu.flow.json", size: 1045, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -991,7 +990,7 @@ func yaoFlowsUserFindFlowJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/flows/user/find.flow.json", size: 328, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/flows/user/find.flow.json", size: 328, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1011,7 +1010,7 @@ func yaoLangsEnUsJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/langs/en-US.json", size: 66, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/langs/en-US.json", size: 66, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1031,7 +1030,7 @@ func yaoLangsZhCnGlobalYml() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/langs/zh-cn/global.yml", size: 1629, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/langs/zh-cn/global.yml", size: 1629, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1051,7 +1050,7 @@ func yaoLangsZhCnLoginsAdminLoginYml() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/langs/zh-cn/logins/admin.login.yml", size: 94, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/langs/zh-cn/logins/admin.login.yml", size: 94, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1071,7 +1070,7 @@ func yaoLangsZhCnLoginsUserLoginYml() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/langs/zh-cn/logins/user.login.yml", size: 90, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/langs/zh-cn/logins/user.login.yml", size: 90, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1091,7 +1090,7 @@ func yaoLangsZhHkGlobalYml() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/langs/zh-hk/global.yml", size: 1629, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/langs/zh-hk/global.yml", size: 1629, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1111,7 +1110,7 @@ func yaoLangsZhHkLoginsAdminLoginYml() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/langs/zh-hk/logins/admin.login.yml", size: 94, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/langs/zh-hk/logins/admin.login.yml", size: 94, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1131,7 +1130,7 @@ func yaoLangsZhHkLoginsUserLoginYml() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/langs/zh-hk/logins/user.login.yml", size: 90, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/langs/zh-hk/logins/user.login.yml", size: 90, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1151,7 +1150,7 @@ func yaoModelsReadmeMd() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/models/README.md", size: 15, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/models/README.md", size: 15, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1171,7 +1170,7 @@ func yaoModelsMenuModJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/models/menu.mod.json", size: 2378, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/models/menu.mod.json", size: 2378, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1191,27 +1190,7 @@ func yaoModelsUserModJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/models/user.mod.json", size: 8826, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/models/user.mod.json", size: 8826, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
|
||||||
return a, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var _yaoModelsWorkflowModJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x55\xcd\x4e\xdb\x4c\x14\xdd\xe7\x29\x46\xb3\xe2\x93\xf2\x09\xa9\x12\x9b\x2c\x2b\x36\xa8\xfb\x6e\x2a\x14\x19\x3c\x31\x6e\xed\x71\x14\x8f\x0b\x28\xb2\x44\x28\xa1\x94\x90\x36\x52\x82\x50\x45\x84\x48\x5b\x4a\x54\x95\x84\xf2\x53\xd2\x40\xda\x97\xf1\xd8\xe6\x2d\x2a\x8f\x63\xc7\x49\x6d\x23\x68\x44\x55\xa9\xab\xc4\x77\xce\xcc\x39\xf7\xde\x33\x73\xf3\x09\x00\x20\xe6\x64\x04\x53\x00\xd2\x8b\x03\xa3\x57\x37\xcf\x0b\x30\xe9\x84\x09\x37\x27\x39\x71\x07\x13\x40\x2d\x89\x1c\x16\xd2\x8b\x4a\xee\x59\x46\x52\x16\x19\x14\x00\x38\xaf\xc8\x32\xc2\x64\xe8\x18\x73\xfb\xd8\x2c\xb7\xec\x46\xd3\x03\x21\x2c\x88\x98\x1d\x32\x83\xb1\x32\xfd\x10\x26\x00\xd0\x19\xd7\xbc\x22\x69\x32\x56\x61\x0a\x3c\x61\xd0\x3c\x80\x12\x37\x87\x24\x86\x9d\x86\xc9\x01\xbd\xc8\x3b\x5f\x64\x39\x8b\xfa\x6b\xee\x09\xa0\x2f\x13\x04\x36\xd2\x4a\xd9\x3a\x3c\xee\x93\x47\x68\x1c\xc5\x78\x34\xec\xd7\x8f\x7a\x74\x2a\xc9\x89\x58\x18\xc4\x25\x84\x05\xb2\x00\x53\xe0\xc1\xd4\x94\x1f\x14\x31\x8f\x96\x60\x0a\x90\x9c\x86\xfc\xe0\x73\x4e\x12\x79\x8e\x88\x4a\x20\xc9\xa0\x6a\x06\x92\x11\x59\x50\x78\x87\xc8\x21\x54\x32\x3e\x11\x5b\xe5\x72\x02\xdb\xeb\xa9\x98\x4d\x0e\xef\x55\x55\x4e\x60\x2a\xf3\x79\x11\x67\x35\xa2\xeb\xd6\x97\x4b\xba\x57\xba\xae\xbd\xb5\xdb\xed\x24\xc8\xe7\x59\x65\x74\x9d\x76\x6b\x76\xfb\xc0\xe8\x74\xe9\xd1\x8e\xf5\xf9\xa3\xd1\x39\x81\xfe\x49\x7a\xff\xdf\x2c\xfb\x8d\x2c\xad\xdb\x5a\x73\xff\xa5\xdd\x5e\x0f\x2f\x70\xf1\xd4\x2e\xd4\x82\xb0\x24\x18\x8a\x35\x1b\x74\xaf\x64\x37\x9a\xe6\xfe\x95\xd3\xe0\xd1\xfa\xf3\x1c\xe1\xd2\x4e\xaf\x47\x5b\x30\x27\x0a\x33\x98\x20\x01\xe5\x60\x7c\xc5\xb1\x26\x49\x7d\x07\x3b\xf1\xf8\x7c\xec\xcd\x55\x6b\xf5\x5b\x78\x26\xbd\x2a\x7d\x55\x76\x01\x91\x6e\x51\x78\x94\x1e\xb7\x65\xee\x90\x80\xb5\xf9\xd5\x5c\x29\xdc\x98\xc6\x28\x6c\x28\x0d\x95\x70\x44\x53\x7f\x4d\x04\x61\x4d\x1e\x44\x79\x94\xe1\x34\x89\x9d\x6c\xd6\x3f\xd1\xab\x15\x7a\x58\x1a\xac\x2a\x59\xc7\xe9\xcc\xac\x81\x55\x00\xed\x1f\xbb\x76\x63\xcb\xe8\x1c\x39\x1f\xf4\xe2\x84\xb6\xb6\xcc\x8d\xca\xc0\xc9\x7f\xf9\xdd\x49\xde\x24\x6d\xa8\x86\xc3\xc2\x6e\x55\xa7\x48\xd5\x46\xa7\x4c\xeb\x4d\xbb\xd5\xa1\x6f\xda\xf6\xd6\x0b\xba\x7b\x16\xa6\x1d\xf8\x64\x93\x3e\xd3\xe4\x80\xe6\xb6\x8f\x81\x6b\x2d\xfa\x61\xcd\xaa\xac\x1b\xdd\x6e\x8c\xfd\x42\x30\x9e\xf7\x34\x15\xe5\xee\xf1\xc2\xfb\x4a\x66\xa6\xd5\x50\xc1\xd6\x6e\x87\x16\x4f\x03\x30\xba\xb1\x63\x37\x9a\x13\x56\xad\x69\x74\x5f\x9b\xef\x57\xac\xb3\x77\xff\x45\xa6\x11\x72\x7f\xee\xe9\x21\x88\x6f\xc3\x48\x56\xe1\xfa\x43\xc4\x3f\x55\x15\x0c\xef\x26\xc8\x7d\xef\xc3\x4d\x51\x59\x73\x1f\x24\xfb\x7b\x95\x16\x0f\x5c\xe4\xc4\x23\xb4\xfc\xff\x63\x4e\xd2\x50\x48\x79\x99\xcd\xc7\x2a\xcf\xad\x85\x75\x59\x35\xf7\xea\xf1\x22\x83\xc8\x58\x91\x8a\x46\xc6\xad\xd2\xac\x96\x8d\x5e\xdd\x6e\x1d\xd3\xde\x76\xa8\xca\x70\x80\xa7\x68\x41\x54\x89\x92\x5b\xbe\xa3\xa4\x08\x4d\x31\xc3\xc6\x3c\x2f\x58\xcd\x52\xd4\x98\xf9\x03\x13\xa6\xff\x51\x3c\xbd\xde\x39\xfa\x37\x6e\x7e\xab\x68\x91\x29\x8c\x63\xf6\x4c\x0e\x08\xa3\xa6\x50\x02\x00\xa6\xc5\x6d\x1e\x62\xe9\xb8\x01\xdf\x13\x79\x00\x89\x28\x23\x95\x70\x72\x56\xf5\xda\x0b\xa0\xaa\x64\x48\x9a\x47\x12\x22\xc8\x8b\x02\x3d\xa1\x27\x7e\x06\x00\x00\xff\xff\x85\x12\x29\x3f\x05\x0d\x00\x00")
|
|
||||||
|
|
||||||
func yaoModelsWorkflowModJsonBytes() ([]byte, error) {
|
|
||||||
return bindataRead(
|
|
||||||
_yaoModelsWorkflowModJson,
|
|
||||||
"yao/models/workflow.mod.json",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func yaoModelsWorkflowModJson() (*asset, error) {
|
|
||||||
bytes, err := yaoModelsWorkflowModJsonBytes()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/models/workflow.mod.json", size: 3333, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1231,7 +1210,7 @@ func yaoTablesReadmeMd() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/tables/README.md", size: 15, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/tables/README.md", size: 15, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1251,7 +1230,7 @@ func yaoTablesMenuTabJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/tables/menu.tab.json", size: 10471, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/tables/menu.tab.json", size: 10471, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1271,7 +1250,7 @@ func yaoTablesUserTabJson() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "yao/tables/user.tab.json", size: 2357, mode: os.FileMode(420), modTime: time.Unix(1668659457, 0)}
|
info := bindataFileInfo{name: "yao/tables/user.tab.json", size: 2357, mode: os.FileMode(420), modTime: time.Unix(1668660458, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1377,7 +1356,6 @@ var _bindata = map[string]func() (*asset, error){
|
||||||
"yao/models/README.md": yaoModelsReadmeMd,
|
"yao/models/README.md": yaoModelsReadmeMd,
|
||||||
"yao/models/menu.mod.json": yaoModelsMenuModJson,
|
"yao/models/menu.mod.json": yaoModelsMenuModJson,
|
||||||
"yao/models/user.mod.json": yaoModelsUserModJson,
|
"yao/models/user.mod.json": yaoModelsUserModJson,
|
||||||
"yao/models/workflow.mod.json": yaoModelsWorkflowModJson,
|
|
||||||
"yao/tables/README.md": yaoTablesReadmeMd,
|
"yao/tables/README.md": yaoTablesReadmeMd,
|
||||||
"yao/tables/menu.tab.json": yaoTablesMenuTabJson,
|
"yao/tables/menu.tab.json": yaoTablesMenuTabJson,
|
||||||
"yao/tables/user.tab.json": yaoTablesUserTabJson,
|
"yao/tables/user.tab.json": yaoTablesUserTabJson,
|
||||||
|
|
@ -1541,7 +1519,6 @@ var _bintree = &bintree{nil, map[string]*bintree{
|
||||||
"README.md": {yaoModelsReadmeMd, map[string]*bintree{}},
|
"README.md": {yaoModelsReadmeMd, map[string]*bintree{}},
|
||||||
"menu.mod.json": {yaoModelsMenuModJson, map[string]*bintree{}},
|
"menu.mod.json": {yaoModelsMenuModJson, map[string]*bintree{}},
|
||||||
"user.mod.json": {yaoModelsUserModJson, map[string]*bintree{}},
|
"user.mod.json": {yaoModelsUserModJson, map[string]*bintree{}},
|
||||||
"workflow.mod.json": {yaoModelsWorkflowModJson, map[string]*bintree{}},
|
|
||||||
}},
|
}},
|
||||||
"tables": {nil, map[string]*bintree{
|
"tables": {nil, map[string]*bintree{
|
||||||
"README.md": {yaoTablesReadmeMd, map[string]*bintree{}},
|
"README.md": {yaoTablesReadmeMd, map[string]*bintree{}},
|
||||||
|
|
|
||||||
107
workflow/api.go
107
workflow/api.go
|
|
@ -1,107 +0,0 @@
|
||||||
package workflow
|
|
||||||
|
|
||||||
import (
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
jsoniter "github.com/json-iterator/go"
|
|
||||||
"github.com/yaoapp/gou"
|
|
||||||
)
|
|
||||||
|
|
||||||
// API:
|
|
||||||
// 读取工作流 GET /api/xiang/workflow/<工作流名称>/find/:id
|
|
||||||
// 读取工作流 GET /api/xiang/workflow/<工作流名称>/open/:data_id
|
|
||||||
// 读取工作流配置 GET /api/xiang/workflow/<工作流名称>/setting/:data_id
|
|
||||||
// 调用自定义API POST /api/xiang/workflow/<工作流名称>/<自定义API路由>
|
|
||||||
|
|
||||||
// SetupAPIs 注册API
|
|
||||||
func (workflow *WorkFlow) SetupAPIs() error {
|
|
||||||
api := &gou.HTTP{
|
|
||||||
Name: "工作流接口",
|
|
||||||
Version: "1.0.0",
|
|
||||||
Description: "工作流接口 API",
|
|
||||||
Group: "xiang/workflow",
|
|
||||||
Guard: "bearer-jwt",
|
|
||||||
Paths: []gou.Path{},
|
|
||||||
}
|
|
||||||
|
|
||||||
workflow.AddAPI(api, workflow.apiFind())
|
|
||||||
workflow.AddAPI(api, workflow.apiOpen())
|
|
||||||
workflow.AddAPI(api, workflow.apiSetting())
|
|
||||||
|
|
||||||
for name, custAPI := range workflow.APIs {
|
|
||||||
workflow.AddAPI(api, gou.Path{
|
|
||||||
Label: custAPI.Label,
|
|
||||||
Description: custAPI.Description,
|
|
||||||
Path: filepath.Join("/", workflow.Name, name),
|
|
||||||
Method: "POST",
|
|
||||||
Process: custAPI.Process,
|
|
||||||
In: []string{workflow.Name, "$session.user_id", "$query.data_id", ":payload"},
|
|
||||||
Out: gou.Out{
|
|
||||||
Status: 200,
|
|
||||||
Type: "application/json",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 注册API
|
|
||||||
source, err := jsoniter.Marshal(api)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
gou.LoadAPI(string(source), "xiang.workflow."+workflow.Name)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddAPI 添加API
|
|
||||||
func (workflow *WorkFlow) AddAPI(api *gou.HTTP, path gou.Path) {
|
|
||||||
api.Paths = append(api.Paths, path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// apiFind 使用ID读取工作流
|
|
||||||
func (workflow *WorkFlow) apiFind() gou.Path {
|
|
||||||
return gou.Path{
|
|
||||||
Label: "读取工作流",
|
|
||||||
Description: "使用工作流ID读取工作流",
|
|
||||||
Path: filepath.Join("/", workflow.Name, "find", ":id"),
|
|
||||||
Method: "GET",
|
|
||||||
Process: "xiang.workflow.Find",
|
|
||||||
In: []string{workflow.Name, "$param.id"},
|
|
||||||
Out: gou.Out{
|
|
||||||
Status: 200,
|
|
||||||
Type: "application/json",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// apiOpen 使用用户ID和数据ID 读取工作流
|
|
||||||
func (workflow *WorkFlow) apiOpen() gou.Path {
|
|
||||||
return gou.Path{
|
|
||||||
Label: "读取工作流",
|
|
||||||
Description: "使用数据ID读取工作流",
|
|
||||||
Path: filepath.Join("/", workflow.Name, "open", ":data_id"),
|
|
||||||
Method: "GET",
|
|
||||||
Process: "xiang.workflow.Open",
|
|
||||||
In: []string{workflow.Name, "$session.user_id", "$param.data_id"},
|
|
||||||
Out: gou.Out{
|
|
||||||
Status: 200,
|
|
||||||
Type: "application/json",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// apiSetting 读取工作流配置
|
|
||||||
func (workflow *WorkFlow) apiSetting() gou.Path {
|
|
||||||
return gou.Path{
|
|
||||||
Label: "读取工作流配置",
|
|
||||||
Description: "使用数据ID读取工作流配置",
|
|
||||||
Path: filepath.Join("/", workflow.Name, "setting", ":data_id"),
|
|
||||||
Method: "GET",
|
|
||||||
Process: "xiang.workflow.Setting",
|
|
||||||
In: []string{workflow.Name, "$session.user_id", "$param.data_id"},
|
|
||||||
Out: gou.Out{
|
|
||||||
Status: 200,
|
|
||||||
Type: "application/json",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
package workflow
|
|
||||||
|
|
||||||
// Workflow will be removed from engine
|
|
||||||
|
|
||||||
// func TestSetupAPIs(t *testing.T) {
|
|
||||||
// assignFlow := Select("assign")
|
|
||||||
// assignFlow.SetupAPIs()
|
|
||||||
|
|
||||||
// api := gou.SelectAPI("xiang.workflow.assign")
|
|
||||||
// assert.Equal(t, "xiang.workflow.assign", api.Name)
|
|
||||||
// assert.Equal(t, 10, len(api.HTTP.Paths))
|
|
||||||
// }
|
|
||||||
|
|
@ -1,151 +0,0 @@
|
||||||
package workflow
|
|
||||||
|
|
||||||
import "github.com/yaoapp/gou"
|
|
||||||
|
|
||||||
// WARNING: the Workflow widget will be removed from yao engine
|
|
||||||
|
|
||||||
// Process
|
|
||||||
// 读取工作流 xiang.workflow.Find(name, workflow_id)
|
|
||||||
// 读取工作流 xiang.workflow.Open(name, uid, data_id)
|
|
||||||
// 保存工作流 xiang.workflow.Save(name, uid, node_name, data_id, input, ...output)
|
|
||||||
// 进入下一个节点 xiang.workflow.Next(name, uid, workflow_id, output)
|
|
||||||
// 跳转到指定节点 xiang.workflow.Goto(name, uid, workflow_id, node_name, output)
|
|
||||||
// 更新工作流状态 xiang.workflow.Status(name, uid, workflow_id, status_name, output)
|
|
||||||
// 标记结束流程 xiang.workflow.Done(name, uid, workflow_id, output)
|
|
||||||
// 标记关闭流程 xiang.workflow.Close(name, uid, workflow_id, output)
|
|
||||||
// 标记重置流程 xiang.workflow.Reset(name, uid, workflow_id, output)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// 注册处理器
|
|
||||||
gou.RegisterProcessHandler("xiang.workflow.Find", ProcessFind)
|
|
||||||
gou.RegisterProcessHandler("xiang.workflow.Setting", ProcessSetting)
|
|
||||||
gou.RegisterProcessHandler("xiang.workflow.Open", ProcessOpen)
|
|
||||||
gou.RegisterProcessHandler("xiang.workflow.Save", ProcessSave)
|
|
||||||
gou.RegisterProcessHandler("xiang.workflow.Next", ProcessNext)
|
|
||||||
gou.RegisterProcessHandler("xiang.workflow.Goto", ProcessGoto)
|
|
||||||
gou.RegisterProcessHandler("xiang.workflow.Status", ProcessStatus)
|
|
||||||
gou.RegisterProcessHandler("xiang.workflow.Done", ProcessDone)
|
|
||||||
gou.RegisterProcessHandler("xiang.workflow.Close", ProcessClose)
|
|
||||||
gou.RegisterProcessHandler("xiang.workflow.Reset", ProcessReset)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessFind xiang.workflow.Find 读取工作流
|
|
||||||
//
|
|
||||||
// args: [工作流名称*, 工作流ID*]
|
|
||||||
//
|
|
||||||
// return: map[string]interface{} 工作流数据记录
|
|
||||||
func ProcessFind(process *gou.Process) interface{} {
|
|
||||||
process.ValidateArgNums(2)
|
|
||||||
wflow := Select(process.ArgsString(0))
|
|
||||||
return wflow.Find(process.ArgsInt(1))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessOpen xiang.workflow.Open 读取工作流
|
|
||||||
//
|
|
||||||
// args: [工作流名称*, 当前用户ID*, 关联数据ID*]
|
|
||||||
//
|
|
||||||
// return: map[string]interface{} 工作流数据记录
|
|
||||||
func ProcessOpen(process *gou.Process) interface{} {
|
|
||||||
process.ValidateArgNums(3)
|
|
||||||
wflow := Select(process.ArgsString(0))
|
|
||||||
return wflow.Open(process.ArgsInt(1), process.Args[2])
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessSetting xiang.workflow.Setting 读取工作流配置
|
|
||||||
//
|
|
||||||
// args: [工作流名称*, 当前用户ID*, 关联数据ID*]
|
|
||||||
//
|
|
||||||
// return: map[string]interface{} 工作流配置
|
|
||||||
func ProcessSetting(process *gou.Process) interface{} {
|
|
||||||
process.ValidateArgNums(3)
|
|
||||||
wflow := Select(process.ArgsString(0))
|
|
||||||
return wflow.Setting(process.ArgsInt(1), process.Args[2])
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessSave xiang.workflow.Save 保存工作流节点信息
|
|
||||||
//
|
|
||||||
// args: [工作流名称*, 当前用户ID*, 节点名称*, 关联数据ID*, 输入数据*, 输出数据] (输入数据: {"data":{}, "form":{}} data 关联数据记录信息, form 工作流body表单信息, 输出数据: {"foo":"bar"} )
|
|
||||||
//
|
|
||||||
// return: map[string]interface{} 工作流数据记录
|
|
||||||
func ProcessSave(process *gou.Process) interface{} {
|
|
||||||
process.ValidateArgNums(5)
|
|
||||||
wflow := Select(process.ArgsString(0))
|
|
||||||
input := InputOf(process.ArgsMap(4))
|
|
||||||
output := map[string]interface{}{}
|
|
||||||
if process.NumOfArgsIs(6) {
|
|
||||||
output = process.ArgsMap(5)
|
|
||||||
}
|
|
||||||
return wflow.Save(process.ArgsInt(1), process.ArgsString(2), process.Args[3], input, output)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessNext xiang.workflow.Next 进入下一个节点
|
|
||||||
//
|
|
||||||
// args: [工作流名称*, 当前用户ID*, 工作流ID*, 输出数据*] (输出数据: {"foo":"bar"} )
|
|
||||||
//
|
|
||||||
// return: map[string]interface{} 工作流数据记录
|
|
||||||
func ProcessNext(process *gou.Process) interface{} {
|
|
||||||
process.ValidateArgNums(4)
|
|
||||||
wflow := Select(process.ArgsString(0))
|
|
||||||
output := process.ArgsMap(3)
|
|
||||||
return wflow.Next(process.ArgsInt(1), process.ArgsInt(2), output)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessGoto xiang.workflow.Goto 跳转到指定节点
|
|
||||||
//
|
|
||||||
// args: [工作流名称*, 当前用户ID*, 工作流ID*, 节点名称*, 输出数据*] (输出数据: {"foo":"bar"} )
|
|
||||||
//
|
|
||||||
// return: map[string]interface{} 工作流数据记录
|
|
||||||
func ProcessGoto(process *gou.Process) interface{} {
|
|
||||||
process.ValidateArgNums(5)
|
|
||||||
wflow := Select(process.ArgsString(0))
|
|
||||||
output := process.ArgsMap(4)
|
|
||||||
return wflow.Goto(process.ArgsInt(1), process.ArgsInt(2), process.ArgsString(3), output)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessStatus xiang.workflow.Status 更新工作流状态
|
|
||||||
//
|
|
||||||
// args: [工作流名称*, 当前用户ID*, 工作流ID*, 状态名称*, 输出数据*] (输出数据: {"foo":"bar"} )
|
|
||||||
//
|
|
||||||
// return: map[string]interface{} 工作流数据记录
|
|
||||||
func ProcessStatus(process *gou.Process) interface{} {
|
|
||||||
process.ValidateArgNums(5)
|
|
||||||
wflow := Select(process.ArgsString(0))
|
|
||||||
output := process.ArgsMap(4)
|
|
||||||
return wflow.Status(process.ArgsInt(1), process.ArgsInt(2), process.ArgsString(3), output)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessDone xiang.workflow.Done 标记结束流程
|
|
||||||
//
|
|
||||||
// args: [工作流名称*, 当前用户ID*, 工作流ID*, 输出数据*] (输出数据: {"foo":"bar"} )
|
|
||||||
//
|
|
||||||
// return: map[string]interface{} 工作流数据记录
|
|
||||||
func ProcessDone(process *gou.Process) interface{} {
|
|
||||||
process.ValidateArgNums(4)
|
|
||||||
wflow := Select(process.ArgsString(0))
|
|
||||||
output := process.ArgsMap(3)
|
|
||||||
return wflow.Done(process.ArgsInt(1), process.ArgsInt(2), output)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessClose xiang.workflow.Close 标记关闭流程
|
|
||||||
//
|
|
||||||
// args: [工作流名称*, 当前用户ID*, 工作流ID*, 输出数据*] (输出数据: {"foo":"bar"} )
|
|
||||||
//
|
|
||||||
// return: map[string]interface{} 工作流数据记录
|
|
||||||
func ProcessClose(process *gou.Process) interface{} {
|
|
||||||
process.ValidateArgNums(4)
|
|
||||||
wflow := Select(process.ArgsString(0))
|
|
||||||
output := process.ArgsMap(3)
|
|
||||||
return wflow.Close(process.ArgsInt(1), process.ArgsInt(2), output)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessReset xiang.workflow.Reset 标记重置流程
|
|
||||||
//
|
|
||||||
// args: [工作流名称*, 当前用户ID*, 工作流ID*, 输出数据*] (输出数据: {"foo":"bar"} )
|
|
||||||
//
|
|
||||||
// return: map[string]interface{} 工作流数据记录
|
|
||||||
func ProcessReset(process *gou.Process) interface{} {
|
|
||||||
process.ValidateArgNums(4)
|
|
||||||
wflow := Select(process.ArgsString(0))
|
|
||||||
output := process.ArgsMap(3)
|
|
||||||
return wflow.Reset(process.ArgsInt(1), process.ArgsInt(2), output)
|
|
||||||
}
|
|
||||||
|
|
@ -1,233 +0,0 @@
|
||||||
package workflow
|
|
||||||
|
|
||||||
// WARNING: the Workflow widget will be removed from yao engine
|
|
||||||
|
|
||||||
// func init() {
|
|
||||||
// share.DBConnect(config.Conf.DB)
|
|
||||||
// share.Load(config.Conf)
|
|
||||||
// model.Load(config.Conf)
|
|
||||||
// engineModels := path.Join(os.Getenv("YAO_DEV"), "yao", "models")
|
|
||||||
// model.LoadFrom(engineModels, "xiang.")
|
|
||||||
// query.Load(config.Conf)
|
|
||||||
// flow.Load(config.Conf)
|
|
||||||
// Load(config.Conf)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestProcessFind(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": "张良明"},
|
|
||||||
// })
|
|
||||||
|
|
||||||
// args := []interface{}{"assign", wflow["id"]}
|
|
||||||
// res := gou.NewProcess("xiang.workflow.Find", args...).Run()
|
|
||||||
|
|
||||||
// data := any.Of(res).Map().MapStrAny.Dot()
|
|
||||||
// assert.Equal(t, wflow["id"], data.Get("id"))
|
|
||||||
|
|
||||||
// // 清理数据
|
|
||||||
// capsule.Query().From("xiang_workflow").Truncate()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestProcessSetting(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{}{
|
|
||||||
// "项目名称": "测试项目",
|
|
||||||
// "商务负责人名称": "林明波",
|
|
||||||
// })
|
|
||||||
|
|
||||||
// args := []interface{}{"assign", 1, 1}
|
|
||||||
// res := gou.NewProcess("xiang.workflow.Setting", args...).Run()
|
|
||||||
// data := any.Of(res).Map().MapStrAny.Dot()
|
|
||||||
// assert.Equal(t, 2, data.Get("nodes.2.source"))
|
|
||||||
// assert.Equal(t, 2, data.Get("nodes.3.source"))
|
|
||||||
// assert.Equal(t, "assign", data.Get("name"))
|
|
||||||
// assert.Equal(t, "指派商务负责人", data.Get("label"))
|
|
||||||
|
|
||||||
// // 清理数据
|
|
||||||
// capsule.Query().From("xiang_workflow").Truncate()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestProcessOpen(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": "张良明"},
|
|
||||||
// })
|
|
||||||
|
|
||||||
// args := []interface{}{"assign", 1, 1}
|
|
||||||
// res := gou.NewProcess("xiang.workflow.Open", args...).Run()
|
|
||||||
|
|
||||||
// data := any.Of(res).Map().MapStrAny.Dot()
|
|
||||||
// assert.Equal(t, wflow["id"], data.Get("id"))
|
|
||||||
|
|
||||||
// // 清理数据
|
|
||||||
// capsule.Query().From("xiang_workflow").Truncate()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestProcessSave(t *testing.T) {
|
|
||||||
// args := []interface{}{"assign",
|
|
||||||
// 1, "选择商务负责人", 1,
|
|
||||||
// map[string]interface{}{
|
|
||||||
// "data": map[string]interface{}{"id": 1, "name": "云主机"},
|
|
||||||
// "form": map[string]interface{}{"biz_id": 1, "name": "张良明"},
|
|
||||||
// },
|
|
||||||
// map[string]interface{}{"foo": "bar"},
|
|
||||||
// }
|
|
||||||
// res := gou.NewProcess("xiang.workflow.Save", args...).Run()
|
|
||||||
// data := any.Of(res).Map().MapStrAny.Dot()
|
|
||||||
// assert.Equal(t, int64(1), data.Get("id"))
|
|
||||||
|
|
||||||
// // 清理数据
|
|
||||||
// capsule.Query().From("xiang_workflow").Truncate()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestProcessNext(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": "张良明"},
|
|
||||||
// })
|
|
||||||
|
|
||||||
// args := []interface{}{"assign",
|
|
||||||
// 1, wflow["id"], map[string]interface{}{
|
|
||||||
// "项目名称": "测试项目",
|
|
||||||
// "商务负责人名称": "林明波",
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
// res := gou.NewProcess("xiang.workflow.Next", args...).Run()
|
|
||||||
// data := any.Of(res).Map().MapStrAny.Dot()
|
|
||||||
// assert.Equal(t, wflow["id"], data.Get("id"))
|
|
||||||
// assert.Equal(t, "项目负责人审批", data.Get("node_name"))
|
|
||||||
|
|
||||||
// // 清理数据
|
|
||||||
// capsule.Query().From("xiang_workflow").Truncate()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestProcessGoto(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{}{
|
|
||||||
// "项目名称": "测试项目",
|
|
||||||
// "商务负责人名称": "林明波",
|
|
||||||
// })
|
|
||||||
|
|
||||||
// args := []interface{}{"assign",
|
|
||||||
// 2, id, "选择商务负责人",
|
|
||||||
// map[string]interface{}{"审批结果": "驳回"},
|
|
||||||
// }
|
|
||||||
// res := gou.NewProcess("xiang.workflow.Goto", args...).Run()
|
|
||||||
// data := any.Of(res).Map().MapStrAny.Dot()
|
|
||||||
// assert.Equal(t, wflow["id"], data.Get("id"))
|
|
||||||
// assert.Equal(t, "选择商务负责人", data.Get("node_name"))
|
|
||||||
|
|
||||||
// // 清理数据
|
|
||||||
// capsule.Query().From("xiang_workflow").Truncate()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestProcessStatus(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{}{
|
|
||||||
// "项目名称": "测试项目",
|
|
||||||
// "商务负责人名称": "林明波",
|
|
||||||
// })
|
|
||||||
|
|
||||||
// args := []interface{}{"assign",
|
|
||||||
// 2, id, "已完成", map[string]interface{}{"关闭原因": "测试完成"},
|
|
||||||
// }
|
|
||||||
// res := gou.NewProcess("xiang.workflow.Status", args...).Run()
|
|
||||||
// data := any.Of(res).Map().MapStrAny.Dot()
|
|
||||||
// assert.Equal(t, wflow["id"], data.Get("id"))
|
|
||||||
// assert.Equal(t, "已完成", data.Get("status"))
|
|
||||||
|
|
||||||
// // 清理数据
|
|
||||||
// capsule.Query().From("xiang_workflow").Truncate()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestProcessDone(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{}{
|
|
||||||
// "项目名称": "测试项目",
|
|
||||||
// "商务负责人名称": "林明波",
|
|
||||||
// })
|
|
||||||
|
|
||||||
// args := []interface{}{"assign",
|
|
||||||
// 2, id, map[string]interface{}{"关闭原因": "测试完成"},
|
|
||||||
// }
|
|
||||||
// res := gou.NewProcess("xiang.workflow.Done", args...).Run()
|
|
||||||
// data := any.Of(res).Map().MapStrAny.Dot()
|
|
||||||
// assert.Equal(t, wflow["id"], data.Get("id"))
|
|
||||||
// assert.Equal(t, "已完成", data.Get("status"))
|
|
||||||
|
|
||||||
// // 清理数据
|
|
||||||
// capsule.Query().From("xiang_workflow").Truncate()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestProcessClose(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{}{
|
|
||||||
// "项目名称": "测试项目",
|
|
||||||
// "商务负责人名称": "林明波",
|
|
||||||
// })
|
|
||||||
|
|
||||||
// args := []interface{}{"assign",
|
|
||||||
// 2, id, map[string]interface{}{"关闭原因": "测试关闭"},
|
|
||||||
// }
|
|
||||||
// res := gou.NewProcess("xiang.workflow.Close", args...).Run()
|
|
||||||
// data := any.Of(res).Map().MapStrAny.Dot()
|
|
||||||
// assert.Equal(t, wflow["id"], data.Get("id"))
|
|
||||||
// assert.Equal(t, "已关闭", data.Get("status"))
|
|
||||||
|
|
||||||
// // 清理数据
|
|
||||||
// capsule.Query().From("xiang_workflow").Truncate()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestProcessReset(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{}{
|
|
||||||
// "项目名称": "测试项目",
|
|
||||||
// "商务负责人名称": "林明波",
|
|
||||||
// })
|
|
||||||
|
|
||||||
// args := []interface{}{"assign",
|
|
||||||
// 2, id, map[string]interface{}{"驳回原因": "字段填写错误"},
|
|
||||||
// }
|
|
||||||
// res := gou.NewProcess("xiang.workflow.Reset", args...).Run()
|
|
||||||
// data := any.Of(res).Map().MapStrAny.Dot()
|
|
||||||
// assert.Equal(t, wflow["id"], data.Get("id"))
|
|
||||||
// assert.Equal(t, "进行中", data.Get("status"))
|
|
||||||
// assert.Equal(t, "选择商务负责人", data.Get("node_name"))
|
|
||||||
|
|
||||||
// // 清理数据
|
|
||||||
// capsule.Query().From("xiang_workflow").Truncate()
|
|
||||||
// }
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
package workflow
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/yaoapp/yao/helper"
|
|
||||||
"github.com/yaoapp/yao/share"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WorkFlow 工作流配置结构
|
|
||||||
type WorkFlow struct {
|
|
||||||
Name string `json:"-"`
|
|
||||||
Source []byte `json:"-"`
|
|
||||||
Version string `json:"version"`
|
|
||||||
Label string `json:"label,omitempty"`
|
|
||||||
Decription string `json:"decription,omitempty"`
|
|
||||||
Nodes []Node `json:"nodes"`
|
|
||||||
APIs map[string]API `json:"apis"`
|
|
||||||
Actions map[string]share.Render `json:"actions"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Node 工作流节点
|
|
||||||
type Node struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Body share.Render `json:"body,omitempty"`
|
|
||||||
Actions []string `json:"actions,omitempty"`
|
|
||||||
User User `json:"user,omitempty"`
|
|
||||||
Next []Next `json:"next,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next 下一个节点描述
|
|
||||||
type Next struct {
|
|
||||||
Conditions []helper.Condition `json:"when,omitempty"`
|
|
||||||
Goto string `json:"goto,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// User 工作流相关用户读取条件
|
|
||||||
type User struct {
|
|
||||||
Process string `json:"process"`
|
|
||||||
Args []interface{} `json:"args"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// API 工作相关API
|
|
||||||
type API struct {
|
|
||||||
Label string `json:"label,omitempty"`
|
|
||||||
Description string `json:"description,omitempty"`
|
|
||||||
Process string `json:"process"`
|
|
||||||
Args []interface{} `json:"args"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Input 用户输入数据
|
|
||||||
type Input struct {
|
|
||||||
Data map[string]interface{} `json:"data"` // 记录数据
|
|
||||||
Form map[string]interface{} `json:"form"` // 表单数据
|
|
||||||
}
|
|
||||||
|
|
@ -1,514 +0,0 @@
|
||||||
package workflow
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
jsoniter "github.com/json-iterator/go"
|
|
||||||
"github.com/yaoapp/gou"
|
|
||||||
gshare "github.com/yaoapp/gou/query/share"
|
|
||||||
"github.com/yaoapp/kun/any"
|
|
||||||
"github.com/yaoapp/kun/exception"
|
|
||||||
"github.com/yaoapp/kun/log"
|
|
||||||
"github.com/yaoapp/kun/maps"
|
|
||||||
"github.com/yaoapp/kun/str"
|
|
||||||
"github.com/yaoapp/yao/config"
|
|
||||||
"github.com/yaoapp/yao/helper"
|
|
||||||
"github.com/yaoapp/yao/share"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WARNING: the Workflow widget will be removed from yao engine
|
|
||||||
|
|
||||||
// Process
|
|
||||||
// 读取工作流 xiang.workflow.Find(name, workflow_id)
|
|
||||||
// 读取工作流 xiang.workflow.Open(name, uid, data_id)
|
|
||||||
// 保存工作流 xiang.workflow.Save(name, uid, node_name, data_id, input, ...output)
|
|
||||||
// 进入下一个节点 xiang.workflow.Next(name, uid, workflow_id, output)
|
|
||||||
// 跳转到指定节点 xiang.workflow.Goto(name, uid, workflow_id, node_name, output)
|
|
||||||
// 更新工作流状态 xiang.workflow.Status(name, uid, workflow_id, status_name, output)
|
|
||||||
// 标记结束流程 xiang.workflow.Done(name, uid, workflow_id, output)
|
|
||||||
// 标记关闭流程 xiang.workflow.Close(name, uid, workflow_id, output)
|
|
||||||
// 标记重置流程 xiang.workflow.Reset(name, uid, workflow_id, output)
|
|
||||||
|
|
||||||
// API:
|
|
||||||
// 读取工作流 GET /api/xiang/workflow/<工作流名称>/find/:id
|
|
||||||
// 读取工作流 GET /api/xiang/workflow/<工作流名称>/open
|
|
||||||
// 读取工作流配置 GET /api/xiang/workflow/<工作流名称>/setting
|
|
||||||
// 调用自定义API POST /api/xiang/workflow/<工作流名称>/<自定义API路由>
|
|
||||||
|
|
||||||
// WorkFlows 工作流列表
|
|
||||||
var WorkFlows = map[string]*WorkFlow{}
|
|
||||||
|
|
||||||
// Load 加载数据表格
|
|
||||||
func Load(cfg config.Config) {
|
|
||||||
LoadFrom(filepath.Join(cfg.Root, "workflows"), "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadFrom 从特定目录加载
|
|
||||||
func LoadFrom(dir string, prefix string) {
|
|
||||||
if share.DirNotExists(dir) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
share.Walk(dir, ".json", func(root, filename string) {
|
|
||||||
name := prefix + share.SpecName(root, filename)
|
|
||||||
content := share.ReadFile(filename)
|
|
||||||
_, err := LoadWorkFlow(content, name)
|
|
||||||
if err != nil {
|
|
||||||
log.With(log.F{"root": root, "filename": filename}).Error(err.Error())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadWorkFlow 载入工作流
|
|
||||||
func LoadWorkFlow(source []byte, name string) (*WorkFlow, error) {
|
|
||||||
workflow := WorkFlow{Name: name, Source: source}
|
|
||||||
err := jsoniter.Unmarshal(source, &workflow)
|
|
||||||
if err != nil {
|
|
||||||
log.With(log.F{"name": name, "source": source}).Error("LoadWorkFlow: %s", err.Error())
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
workflow.SetupAPIs()
|
|
||||||
WorkFlows[workflow.Name] = &workflow
|
|
||||||
return WorkFlows[workflow.Name], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Select 读取已加载图表
|
|
||||||
func Select(name string) *WorkFlow {
|
|
||||||
workflow, has := WorkFlows[name]
|
|
||||||
if !has {
|
|
||||||
exception.New(
|
|
||||||
fmt.Sprintf("工作流:%s; 尚未加载", name),
|
|
||||||
400,
|
|
||||||
).Throw()
|
|
||||||
}
|
|
||||||
return workflow
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reload 重新载入工作流
|
|
||||||
func (workflow *WorkFlow) Reload() *WorkFlow {
|
|
||||||
new, err := LoadWorkFlow(workflow.Source, workflow.Name)
|
|
||||||
if err != nil {
|
|
||||||
exception.New(
|
|
||||||
fmt.Sprintf("工作流:%s; 加载失败", workflow.Name),
|
|
||||||
400,
|
|
||||||
).Throw()
|
|
||||||
}
|
|
||||||
WorkFlows[workflow.Name] = new
|
|
||||||
return new
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find 读取给定ID的工作流
|
|
||||||
// uid 当前处理人ID, id 数据ID
|
|
||||||
func (workflow *WorkFlow) Find(id int) map[string]interface{} {
|
|
||||||
wflow := gou.Select("xiang.workflow")
|
|
||||||
res := wflow.MustFind(id, gou.QueryParam{
|
|
||||||
Select: []interface{}{
|
|
||||||
"data_id", "id", "input", "output", "name",
|
|
||||||
"user_id", "users",
|
|
||||||
"node_name", "node_status",
|
|
||||||
"status",
|
|
||||||
"updated_at", "created_at",
|
|
||||||
}})
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open 读取当前工作流(未完成的)
|
|
||||||
// uid 当前处理人ID, id 数据ID
|
|
||||||
func (workflow *WorkFlow) Open(uid int, id interface{}) map[string]interface{} {
|
|
||||||
wflow := gou.Select("xiang.workflow")
|
|
||||||
params := gou.QueryParam{
|
|
||||||
Select: []interface{}{
|
|
||||||
"data_id", "id", "input", "output", "name",
|
|
||||||
"user_id", "users",
|
|
||||||
"node_name", "node_status",
|
|
||||||
"status",
|
|
||||||
"updated_at", "created_at",
|
|
||||||
},
|
|
||||||
Wheres: []gou.QueryWhere{
|
|
||||||
{Column: "name", Value: workflow.Name},
|
|
||||||
{Column: "data_id", Value: id},
|
|
||||||
{Column: "user_ids", OP: "like", Value: fmt.Sprintf("%%|%d|%%", uid)},
|
|
||||||
{Column: "status", Value: "进行中"},
|
|
||||||
},
|
|
||||||
Limit: 1,
|
|
||||||
}
|
|
||||||
rows := wflow.MustGet(params)
|
|
||||||
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": users,
|
|
||||||
"status": "进行中",
|
|
||||||
"node_status": "进行中",
|
|
||||||
"input": map[string]interface{}{},
|
|
||||||
"output": map[string]interface{}{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setting 返回配置信息
|
|
||||||
// uid 当前处理人ID, id 数据ID
|
|
||||||
func (workflow *WorkFlow) Setting(uid int, id interface{}) map[string]interface{} {
|
|
||||||
wflow := workflow.Open(1, 1)
|
|
||||||
data := maps.MapStr{
|
|
||||||
"$in": wflow["input"],
|
|
||||||
"$input": wflow["input"],
|
|
||||||
"$out": wflow["output"],
|
|
||||||
"$outupt": wflow["output"],
|
|
||||||
"$data": wflow["output"],
|
|
||||||
}
|
|
||||||
|
|
||||||
nodes := workflow.FlowNodes(data.Dot())
|
|
||||||
_, idx := workflow.pickNode(string(str.Of(wflow["node_name"])))
|
|
||||||
return map[string]interface{}{
|
|
||||||
"nodes": nodes,
|
|
||||||
"node": nodes[idx],
|
|
||||||
"node_index": idx,
|
|
||||||
"read": true,
|
|
||||||
"write": any.Of(wflow["user_id"]).CInt() == uid,
|
|
||||||
"actions": workflow.Actions,
|
|
||||||
"name": workflow.Name,
|
|
||||||
"version": workflow.Version,
|
|
||||||
"label": workflow.Label,
|
|
||||||
"decription": workflow.Decription,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save 保存工作流节点数据 此版本使用Like实现
|
|
||||||
// uid 当前处理人ID, id 数据ID
|
|
||||||
func (workflow *WorkFlow) Save(uid int, name string, id interface{}, input Input, outputs ...map[string]interface{}) map[string]interface{} {
|
|
||||||
wflow := gou.Select("xiang.workflow")
|
|
||||||
params := gou.QueryParam{
|
|
||||||
Select: []interface{}{"id", "input", "output", "users"},
|
|
||||||
Wheres: []gou.QueryWhere{
|
|
||||||
{Column: "name", Value: workflow.Name},
|
|
||||||
{Column: "data_id", Value: id},
|
|
||||||
{Column: "user_ids", OP: "like", Value: fmt.Sprintf("%%|%d|%%", uid)},
|
|
||||||
{Column: "status", Value: "进行中"},
|
|
||||||
},
|
|
||||||
Limit: 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
rows := wflow.MustGet(params)
|
|
||||||
data := map[string]interface{}{
|
|
||||||
"name": workflow.Name,
|
|
||||||
"data_id": id,
|
|
||||||
"node_name": name,
|
|
||||||
"user_id": uid,
|
|
||||||
}
|
|
||||||
users := map[string]interface{}{}
|
|
||||||
users[name] = uid
|
|
||||||
output := map[string]interface{}{}
|
|
||||||
nodeInput := map[string]interface{}{}
|
|
||||||
nodeInput[name] = input
|
|
||||||
if len(outputs) > 0 {
|
|
||||||
output = outputs[0]
|
|
||||||
}
|
|
||||||
if len(rows) > 0 {
|
|
||||||
data["id"] = rows[0].Get("id")
|
|
||||||
nodeInput = workflow.MergeData(rows[0].Get("input"), nodeInput)
|
|
||||||
users = workflow.MergeUsers(rows[0].Get("users"), users)
|
|
||||||
output = workflow.MergeData(rows[0].Get("output"), output)
|
|
||||||
} else {
|
|
||||||
data["status"] = "进行中"
|
|
||||||
data["node_status"] = "进行中"
|
|
||||||
}
|
|
||||||
data["users"] = users
|
|
||||||
data["user_ids"] = workflow.UserIDs(users)
|
|
||||||
data["input"] = nodeInput
|
|
||||||
data["output"] = output
|
|
||||||
id = wflow.MustSave(data)
|
|
||||||
return wflow.MustFind(id, gou.QueryParam{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Done 标记完成
|
|
||||||
// uid 当前处理人ID, id 工作流ID
|
|
||||||
func (workflow *WorkFlow) Done(uid int, id int, output map[string]interface{}) map[string]interface{} {
|
|
||||||
return workflow.Status(uid, id, "已完成", output)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close 标记关闭
|
|
||||||
// uid 当前处理人ID, id 工作流ID
|
|
||||||
func (workflow *WorkFlow) Close(uid int, id int, output map[string]interface{}) map[string]interface{} {
|
|
||||||
return workflow.Status(uid, id, "已关闭", output)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status 设定状态
|
|
||||||
// uid 当前处理人ID, id 工作流ID
|
|
||||||
func (workflow *WorkFlow) Status(uid int, id int, status string, output map[string]interface{}) map[string]interface{} {
|
|
||||||
wflow := workflow.Find(id)
|
|
||||||
mod := gou.Select("xiang.workflow")
|
|
||||||
output = workflow.MergeData(wflow["output"], output)
|
|
||||||
mod.Save(map[string]interface{}{
|
|
||||||
"id": wflow["id"],
|
|
||||||
"output": output,
|
|
||||||
"status": status,
|
|
||||||
})
|
|
||||||
return workflow.Find(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset 重新开始
|
|
||||||
// uid 当前处理人ID, id 工作流ID
|
|
||||||
func (workflow *WorkFlow) Reset(uid int, id int, output map[string]interface{}) map[string]interface{} {
|
|
||||||
return workflow.Goto(uid, id, workflow.Nodes[0].Name, output)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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{} {
|
|
||||||
wflow := workflow.Find(id)
|
|
||||||
currNode, ok := wflow["node_name"].(string)
|
|
||||||
if !ok {
|
|
||||||
exception.New("流程数据异常: 当前节点信息错误", 500).Ctx(currNode).Throw()
|
|
||||||
}
|
|
||||||
|
|
||||||
users := map[string]interface{}{}
|
|
||||||
users[currNode] = uid
|
|
||||||
output = workflow.MergeData(wflow["output"], output)
|
|
||||||
|
|
||||||
// 读取下一个节点
|
|
||||||
data := map[string]interface{}{
|
|
||||||
"$in": wflow["input"],
|
|
||||||
"$input": wflow["input"],
|
|
||||||
"$out": output,
|
|
||||||
"$outupt": output,
|
|
||||||
"$data": output,
|
|
||||||
}
|
|
||||||
nextNode := workflow.nextNode(currNode, data)
|
|
||||||
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": output,
|
|
||||||
"node_name": nextNode.Name,
|
|
||||||
"node_status": "进行中",
|
|
||||||
"user_id": nextUID,
|
|
||||||
"users": users,
|
|
||||||
"user_ids": workflow.UserIDs(users),
|
|
||||||
})
|
|
||||||
return workflow.Find(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (workflow *WorkFlow) pickNode(name string) (*Node, int) {
|
|
||||||
for i, node := range workflow.Nodes {
|
|
||||||
if node.Name == name {
|
|
||||||
return &node, i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 未声明 Next 节点, 转到下一个节点
|
|
||||||
if curr.Next == nil {
|
|
||||||
return &workflow.Nodes[nextIndex]
|
|
||||||
}
|
|
||||||
|
|
||||||
// 声明 Next 节点, 按条件到指定节点
|
|
||||||
data = maps.Of(data).Dot()
|
|
||||||
for _, next := range curr.Next {
|
|
||||||
node := workflow.GetNodeWhen(next, data)
|
|
||||||
if node != nil {
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exception.New("流程数据异常: 未找到符合条件的工作流节点", 500).Ctx(map[string]interface{}{"current": currentNode, "data": data}).Throw()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetNodeWhen 读取节点
|
|
||||||
func (workflow *WorkFlow) GetNodeWhen(next Next, data map[string]interface{}) *Node {
|
|
||||||
nextNode := ""
|
|
||||||
conditions := workflow.Conditions(next.Conditions, data)
|
|
||||||
if helper.When(conditions) {
|
|
||||||
nextNode = next.Goto
|
|
||||||
for i := 0; i < workflow.Len(); i++ {
|
|
||||||
node := workflow.Nodes[i]
|
|
||||||
if node.Name == nextNode {
|
|
||||||
return &node
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Conditions 处理绑定参数
|
|
||||||
func (workflow *WorkFlow) Conditions(conds []helper.Condition, data map[string]interface{}) []helper.Condition {
|
|
||||||
conditions := []helper.Condition{}
|
|
||||||
for _, cond := range conds {
|
|
||||||
if left, ok := cond.Left.(string); ok {
|
|
||||||
cond.Left = gshare.Bind(left, data)
|
|
||||||
}
|
|
||||||
if right, ok := cond.Right.(string); ok {
|
|
||||||
cond.Right = gshare.Bind(right, data)
|
|
||||||
}
|
|
||||||
conditions = append(conditions, cond)
|
|
||||||
}
|
|
||||||
return conditions
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserIDs 读取用户ID
|
|
||||||
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{}) map[string]interface{} {
|
|
||||||
res, ok := data.(map[string]interface{})
|
|
||||||
if !ok {
|
|
||||||
return map[string]interface{}{}
|
|
||||||
}
|
|
||||||
if new, ok := new.(map[string]interface{}); ok {
|
|
||||||
for name, value := range new {
|
|
||||||
res[name] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if new, ok := new.(map[string]interface{}); ok {
|
|
||||||
for key, value := range new {
|
|
||||||
res[key] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsLastNode 检查是否为最后一个节点
|
|
||||||
func (workflow *WorkFlow) IsLastNode(name string) bool {
|
|
||||||
length := workflow.Len()
|
|
||||||
return workflow.Nodes[length-1].Name == name
|
|
||||||
}
|
|
||||||
|
|
||||||
// FlowNodes 转换为 flow
|
|
||||||
func (workflow *WorkFlow) FlowNodes(data map[string]interface{}) []map[string]interface{} {
|
|
||||||
res := []map[string]interface{}{}
|
|
||||||
nodes, err := jsoniter.Marshal(workflow.Nodes)
|
|
||||||
if err != nil {
|
|
||||||
exception.New("JSON解析错误 %s", 500, nodes).Throw()
|
|
||||||
}
|
|
||||||
|
|
||||||
err = jsoniter.Unmarshal(nodes, &res)
|
|
||||||
if err != nil {
|
|
||||||
exception.New("JSON解析错误 %s", 500, nodes).Throw()
|
|
||||||
}
|
|
||||||
|
|
||||||
nameMaps := map[string]int{}
|
|
||||||
for i, node := range workflow.Nodes {
|
|
||||||
nameMaps[node.Name] = i
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, node := range res {
|
|
||||||
v := gshare.Bind(node, data)
|
|
||||||
if v, ok := v.(map[string]interface{}); ok {
|
|
||||||
res[i] = v
|
|
||||||
}
|
|
||||||
res[i]["id"] = i + 1
|
|
||||||
res[i]["label"] = res[i]["name"]
|
|
||||||
delete(res[i], "user")
|
|
||||||
delete(res[i], "next")
|
|
||||||
if workflow.Nodes[i].Next != nil {
|
|
||||||
for _, next := range workflow.Nodes[i].Next {
|
|
||||||
name := next.Goto
|
|
||||||
if id, has := nameMaps[name]; has {
|
|
||||||
res[id]["source"] = i + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// Len 节点数量
|
|
||||||
func (workflow *WorkFlow) Len() int {
|
|
||||||
return len(workflow.Nodes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InputOf 映射表转换为Input
|
|
||||||
func InputOf(in map[string]interface{}) Input {
|
|
||||||
input := Input{Data: map[string]interface{}{}, Form: map[string]interface{}{}}
|
|
||||||
if data, ok := in["data"].(map[string]interface{}); ok {
|
|
||||||
input.Data = data
|
|
||||||
}
|
|
||||||
if form, ok := in["form"].(map[string]interface{}); ok {
|
|
||||||
input.Form = form
|
|
||||||
}
|
|
||||||
return input
|
|
||||||
}
|
|
||||||
|
|
@ -1,296 +0,0 @@
|
||||||
package workflow
|
|
||||||
|
|
||||||
// WARNING: the Workflow widget will be removed from yao engine
|
|
||||||
|
|
||||||
// func init() {
|
|
||||||
// share.DBConnect(config.Conf.DB)
|
|
||||||
// share.Load(config.Conf)
|
|
||||||
// model.Load(config.Conf)
|
|
||||||
// engineModels := path.Join(os.Getenv("YAO_DEV"), "xiang", "models")
|
|
||||||
// model.LoadFrom(engineModels, "xiang.")
|
|
||||||
// query.Load(config.Conf)
|
|
||||||
// flow.Load(config.Conf)
|
|
||||||
// Load(config.Conf)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestLoad(t *testing.T) {
|
|
||||||
// share.DBConnect(config.Conf.DB)
|
|
||||||
// share.Load(config.Conf)
|
|
||||||
// model.Load(config.Conf)
|
|
||||||
// query.Load(config.Conf)
|
|
||||||
// Load(config.Conf)
|
|
||||||
// LoadFrom("not a path", "404.")
|
|
||||||
// check(t)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestSave(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": "张良明"},
|
|
||||||
// })
|
|
||||||
|
|
||||||
// data := maps.Of(wflow).Dot()
|
|
||||||
// assert.Equal(t, int64(1), data.Get("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, float64(1), data.Get("input.选择商务负责人.data.id"))
|
|
||||||
// assert.Equal(t, "云主机", data.Get("input.选择商务负责人.data.name"))
|
|
||||||
// assert.Equal(t, float64(1), data.Get("input.选择商务负责人.form.biz_id"))
|
|
||||||
// assert.Equal(t, "张良明", data.Get("input.选择商务负责人.form.name"))
|
|
||||||
// // 清理数据
|
|
||||||
// capsule.Query().From("xiang_workflow").Truncate()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestSaveUpdate(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": "张良明"},
|
|
||||||
// })
|
|
||||||
|
|
||||||
// wflow = assignFlow.Save(1, "选择商务负责人", 1, Input{
|
|
||||||
// Data: map[string]interface{}{"id": 1, "name": "云存储"},
|
|
||||||
// Form: map[string]interface{}{"biz_id": 1, "name": "李明博"},
|
|
||||||
// })
|
|
||||||
|
|
||||||
// data := maps.Of(wflow).Dot()
|
|
||||||
// assert.Equal(t, int64(1), data.Get("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, float64(1), data.Get("input.选择商务负责人.data.id"))
|
|
||||||
// assert.Equal(t, "云存储", data.Get("input.选择商务负责人.data.name"))
|
|
||||||
// assert.Equal(t, float64(1), data.Get("input.选择商务负责人.form.biz_id"))
|
|
||||||
// assert.Equal(t, "李明博", data.Get("input.选择商务负责人.form.name"))
|
|
||||||
|
|
||||||
// // 清理数据
|
|
||||||
// capsule.Query().From("xiang_workflow").Truncate()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestOpen(t *testing.T) {
|
|
||||||
// assignFlow := Select("assign")
|
|
||||||
// assignFlow.Save(1, "选择商务负责人", 1, Input{
|
|
||||||
// Data: map[string]interface{}{"id": 1, "name": "云主机"},
|
|
||||||
// Form: map[string]interface{}{"biz_id": 1, "name": "张良明"},
|
|
||||||
// })
|
|
||||||
// wflow := assignFlow.Open(1, 1)
|
|
||||||
// data := maps.Of(wflow).Dot()
|
|
||||||
// assert.Equal(t, int64(1), data.Get("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.选择商务负责人"))
|
|
||||||
|
|
||||||
// // 清理数据
|
|
||||||
// capsule.Query().From("xiang_workflow").Truncate()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestOpenEmpty(t *testing.T) {
|
|
||||||
// assignFlow := Select("assign")
|
|
||||||
// wflow := assignFlow.Open(1, 1)
|
|
||||||
// data := maps.Of(wflow).Dot()
|
|
||||||
// assert.Equal(t, false, 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, 1, data.Get("user_id"))
|
|
||||||
// assert.Equal(t, 1, data.Get("users.选择商务负责人"))
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestNext(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": "张良明"},
|
|
||||||
// })
|
|
||||||
// wflow = assignFlow.Next(1, any.Of(wflow["id"]).CInt(), map[string]interface{}{
|
|
||||||
// "项目名称": "测试项目",
|
|
||||||
// "商务负责人名称": "林明波",
|
|
||||||
// })
|
|
||||||
// data := maps.Of(wflow).Dot()
|
|
||||||
// assert.Equal(t, int64(1), data.Get("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(2), data.Get("user_id"))
|
|
||||||
// assert.Equal(t, true, data.Has("users"))
|
|
||||||
// assert.Equal(t, "测试项目", data.Get("output.项目名称"))
|
|
||||||
// assert.Equal(t, "林明波", data.Get("output.商务负责人名称"))
|
|
||||||
|
|
||||||
// // 清理数据
|
|
||||||
// capsule.Query().From("xiang_workflow").Truncate()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestNextWhen(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{}{
|
|
||||||
// "项目名称": "测试项目",
|
|
||||||
// "商务负责人名称": "林明波",
|
|
||||||
// })
|
|
||||||
|
|
||||||
// // Next When
|
|
||||||
// wflow = assignFlow.Next(2, id, map[string]interface{}{"审批结果": "通过"})
|
|
||||||
// data := maps.Of(wflow).Dot()
|
|
||||||
// assert.Equal(t, int64(1), data.Get("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, true, data.Has("users"))
|
|
||||||
// assert.Equal(t, "测试项目", data.Get("output.项目名称"))
|
|
||||||
// assert.Equal(t, "林明波", data.Get("output.商务负责人名称"))
|
|
||||||
// assert.Equal(t, "通过", data.Get("output.审批结果"))
|
|
||||||
|
|
||||||
// // 清理数据
|
|
||||||
// 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 TestReset(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.Reset(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 TestDone(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.Done(2, id, map[string]interface{}{"关闭原因": "测试完成"})
|
|
||||||
// data := maps.Of(wflow).Dot()
|
|
||||||
// assert.Equal(t, "已完成", data.Get("status"))
|
|
||||||
// assert.Equal(t, "测试完成", data.Get("output.关闭原因"))
|
|
||||||
// // 清理数据
|
|
||||||
// capsule.Query().From("xiang_workflow").Truncate()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestClose(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.Close(2, id, map[string]interface{}{"关闭原因": "测试关闭"})
|
|
||||||
// data := maps.Of(wflow).Dot()
|
|
||||||
// assert.Equal(t, "已关闭", data.Get("status"))
|
|
||||||
// assert.Equal(t, "测试关闭", data.Get("output.关闭原因"))
|
|
||||||
// // 清理数据
|
|
||||||
// capsule.Query().From("xiang_workflow").Truncate()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestSetting(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": "张良明"},
|
|
||||||
// })
|
|
||||||
|
|
||||||
// setting := assignFlow.Setting(1, 1)
|
|
||||||
// data := maps.Of(setting).Dot()
|
|
||||||
// assert.Equal(t, true, data.Get("read"))
|
|
||||||
// assert.Equal(t, "选择商务负责人", data.Get("node.label"))
|
|
||||||
// assert.Equal(t, true, data.Get("write"))
|
|
||||||
|
|
||||||
// id := any.Of(wflow["id"]).CInt()
|
|
||||||
// assignFlow.Next(1, id, map[string]interface{}{
|
|
||||||
// "项目名称": "测试项目",
|
|
||||||
// "商务负责人名称": "林明波",
|
|
||||||
// })
|
|
||||||
|
|
||||||
// setting = assignFlow.Setting(1, 1)
|
|
||||||
// data = maps.Of(setting).Dot()
|
|
||||||
// assert.Equal(t, true, data.Get("read"))
|
|
||||||
// assert.Equal(t, false, data.Get("write"))
|
|
||||||
// assert.Equal(t, "项目负责人审批", data.Get("node.label"))
|
|
||||||
// assert.Equal(t, 2, data.Get("nodes.2.source"))
|
|
||||||
// assert.Equal(t, 2, data.Get("nodes.3.source"))
|
|
||||||
// assert.Equal(t, "assign", data.Get("name"))
|
|
||||||
// assert.Equal(t, "指派商务负责人", data.Get("label"))
|
|
||||||
|
|
||||||
// // 清理数据
|
|
||||||
// capsule.Query().From("xiang_workflow").Truncate()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func check(t *testing.T) {
|
|
||||||
// keys := []string{}
|
|
||||||
// for key, workflow := range WorkFlows {
|
|
||||||
// keys = append(keys, key)
|
|
||||||
// workflow.Reload()
|
|
||||||
// }
|
|
||||||
// assert.Equal(t, 1, len(keys))
|
|
||||||
// }
|
|
||||||
|
|
@ -1,133 +0,0 @@
|
||||||
{
|
|
||||||
"name": "工作流",
|
|
||||||
"table": {
|
|
||||||
"name": "xiang_workflow",
|
|
||||||
"comment": "工作流数据表",
|
|
||||||
"engine": "InnoDB"
|
|
||||||
},
|
|
||||||
"columns": [
|
|
||||||
{ "label": "ID", "name": "id", "type": "ID" },
|
|
||||||
{
|
|
||||||
"label": "名称",
|
|
||||||
"comment": "工作流名称",
|
|
||||||
"name": "name",
|
|
||||||
"type": "string",
|
|
||||||
"length": 255,
|
|
||||||
"index": true,
|
|
||||||
"validations": [
|
|
||||||
{
|
|
||||||
"method": "typeof",
|
|
||||||
"args": ["string"],
|
|
||||||
"message": "{{input}}类型错误, {{label}}应该为字符串"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "数据标识",
|
|
||||||
"comment": "关联数据标识, 关联数据模型表格ID",
|
|
||||||
"name": "data_id",
|
|
||||||
"type": "bigInteger",
|
|
||||||
"index": true,
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "节点",
|
|
||||||
"comment": "当前节点名称",
|
|
||||||
"name": "node_name",
|
|
||||||
"type": "string",
|
|
||||||
"length": 255,
|
|
||||||
"index": true,
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "节点状态",
|
|
||||||
"comment": "当前节点状态",
|
|
||||||
"name": "node_status",
|
|
||||||
"type": "enum",
|
|
||||||
"default": "未开始",
|
|
||||||
"option": ["未开始", "进行中", "已完成"],
|
|
||||||
"index": true,
|
|
||||||
"validations": [
|
|
||||||
{
|
|
||||||
"method": "typeof",
|
|
||||||
"args": ["string"],
|
|
||||||
"message": "{{input}}类型错误, {{label}}应该为字符串"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"method": "enum",
|
|
||||||
"args": ["未开始", "进行中", "已完成"],
|
|
||||||
"message": "{{input}}不在许可范围, {{label}}应该为 未开始/进行中/已完成"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "当前处理人",
|
|
||||||
"comment": "当前处理人",
|
|
||||||
"name": "user_id",
|
|
||||||
"type": "bigInteger",
|
|
||||||
"index": true,
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "处理人IDs",
|
|
||||||
"comment": "相关处理人ID列表(用于检索)",
|
|
||||||
"name": "user_ids",
|
|
||||||
"type": "string",
|
|
||||||
"length": 255,
|
|
||||||
"index": true,
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "处理人",
|
|
||||||
"comment": "相关处理人",
|
|
||||||
"name": "users",
|
|
||||||
"type": "json",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "数据",
|
|
||||||
"comment": "各节点输入数据(Key-Value)",
|
|
||||||
"name": "input",
|
|
||||||
"type": "json",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "处理结果",
|
|
||||||
"comment": "各节点处理结果(Key-Value)",
|
|
||||||
"name": "output",
|
|
||||||
"type": "json",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "操作记录",
|
|
||||||
"comment": "操作记录",
|
|
||||||
"name": "history",
|
|
||||||
"type": "json",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"label": "状态",
|
|
||||||
"comment": "流程状态",
|
|
||||||
"name": "status",
|
|
||||||
"type": "enum",
|
|
||||||
"default": "未开始",
|
|
||||||
"option": ["未开始", "进行中", "已完成", "已关闭"],
|
|
||||||
"index": true,
|
|
||||||
"validations": [
|
|
||||||
{
|
|
||||||
"method": "typeof",
|
|
||||||
"args": ["string"],
|
|
||||||
"message": "{{input}}类型错误, {{label}}应该为字符串"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"method": "enum",
|
|
||||||
"args": ["未开始", "进行中", "已完成", "已关闭"],
|
|
||||||
"message": "{{input}}不在许可范围, {{label}}应该为 未开始/进行中/已完成/已关闭"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"indexes": [],
|
|
||||||
"option": { "timestamps": true, "soft_deletes": true }
|
|
||||||
}
|
|
||||||
Loading…
Add table
Reference in a new issue