[remove] workfow table
This commit is contained in:
parent
5878b238c7
commit
f2f43e7f96
9 changed files with 55 additions and 1577 deletions
133
data/bindata.go
133
data/bindata.go
|
|
@ -49,7 +49,6 @@
|
|||
// .tmp/data/yao/models/README.md
|
||||
// .tmp/data/yao/models/menu.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/menu.tab.json
|
||||
// .tmp/data/yao/tables/user.tab.json
|
||||
|
|
@ -231,7 +230,7 @@ func initAppJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -251,7 +250,7 @@ func initChartsDashboardChartJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -271,7 +270,7 @@ func initFlowsAppMenuFlowJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -291,7 +290,7 @@ func initFormsPetFormJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -311,7 +310,7 @@ func initLangsZhCnGlobalYml() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -331,7 +330,7 @@ func initLangsZhHkLangsGlobalYml() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -351,7 +350,7 @@ func initLoginsAdminLoginJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -371,7 +370,7 @@ func initLoginsUserLoginJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -391,7 +390,7 @@ func initModelsPetModJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -411,7 +410,7 @@ func initPublicIndexHtml() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -431,7 +430,7 @@ func initScriptsDemoJs() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -451,7 +450,7 @@ func initScriptsStatJs() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -471,7 +470,7 @@ func initTablesPetTabJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -491,7 +490,7 @@ func publicIndexHtml() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -511,7 +510,7 @@ func uiIndexHtml() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -531,7 +530,7 @@ func xgenSetupIndexHtml() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -551,7 +550,7 @@ func xgenV09IndexHtml() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -571,7 +570,7 @@ func xgenV10IndexHtml() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -591,7 +590,7 @@ func xgenV10Layouts__indexAsyncJs() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -611,7 +610,7 @@ func xgenV10UmiJs() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -631,7 +630,7 @@ func yaoApisReadmeMd() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -651,7 +650,7 @@ func yaoApisChartHttpJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -671,7 +670,7 @@ func yaoApisImportHttpJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -691,7 +690,7 @@ func yaoApisPageHttpJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -711,7 +710,7 @@ func yaoApisStorageHttpJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -731,7 +730,7 @@ func yaoApisTableHttpJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -751,7 +750,7 @@ func yaoApisUserHttpJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -771,7 +770,7 @@ func yaoApisXiangHttpJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -791,7 +790,7 @@ func yaoDataAppJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -811,7 +810,7 @@ func yaoDataIcons404Png() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -831,7 +830,7 @@ func yaoDataIconsIconIcns() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -851,7 +850,7 @@ func yaoDataIconsIconIco() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -871,7 +870,7 @@ func yaoDataIconsIconPng() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -891,7 +890,7 @@ func yaoDataIndexHtml() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -911,7 +910,7 @@ func yaoFieldsModelTransJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -931,7 +930,7 @@ func yaoFlowsReadmeMd() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -951,7 +950,7 @@ func yaoFlowsAdminGuardFlowJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -971,7 +970,7 @@ func yaoFlowsMenuFlowJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -991,7 +990,7 @@ func yaoFlowsUserFindFlowJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -1011,7 +1010,7 @@ func yaoLangsEnUsJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -1031,7 +1030,7 @@ func yaoLangsZhCnGlobalYml() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -1051,7 +1050,7 @@ func yaoLangsZhCnLoginsAdminLoginYml() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -1071,7 +1070,7 @@ func yaoLangsZhCnLoginsUserLoginYml() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -1091,7 +1090,7 @@ func yaoLangsZhHkGlobalYml() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -1111,7 +1110,7 @@ func yaoLangsZhHkLoginsAdminLoginYml() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -1131,7 +1130,7 @@ func yaoLangsZhHkLoginsUserLoginYml() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -1151,7 +1150,7 @@ func yaoModelsReadmeMd() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -1171,7 +1170,7 @@ func yaoModelsMenuModJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -1191,27 +1190,7 @@ func yaoModelsUserModJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/models/user.mod.json", size: 8826, mode: os.FileMode(420), modTime: time.Unix(1668659457, 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)}
|
||||
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
|
||||
}
|
||||
|
|
@ -1231,7 +1210,7 @@ func yaoTablesReadmeMd() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -1251,7 +1230,7 @@ func yaoTablesMenuTabJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -1271,7 +1250,7 @@ func yaoTablesUserTabJson() (*asset, error) {
|
|||
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}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -1377,7 +1356,6 @@ var _bindata = map[string]func() (*asset, error){
|
|||
"yao/models/README.md": yaoModelsReadmeMd,
|
||||
"yao/models/menu.mod.json": yaoModelsMenuModJson,
|
||||
"yao/models/user.mod.json": yaoModelsUserModJson,
|
||||
"yao/models/workflow.mod.json": yaoModelsWorkflowModJson,
|
||||
"yao/tables/README.md": yaoTablesReadmeMd,
|
||||
"yao/tables/menu.tab.json": yaoTablesMenuTabJson,
|
||||
"yao/tables/user.tab.json": yaoTablesUserTabJson,
|
||||
|
|
@ -1538,10 +1516,9 @@ var _bintree = &bintree{nil, map[string]*bintree{
|
|||
}},
|
||||
}},
|
||||
"models": {nil, map[string]*bintree{
|
||||
"README.md": {yaoModelsReadmeMd, map[string]*bintree{}},
|
||||
"menu.mod.json": {yaoModelsMenuModJson, map[string]*bintree{}},
|
||||
"user.mod.json": {yaoModelsUserModJson, map[string]*bintree{}},
|
||||
"workflow.mod.json": {yaoModelsWorkflowModJson, map[string]*bintree{}},
|
||||
"README.md": {yaoModelsReadmeMd, map[string]*bintree{}},
|
||||
"menu.mod.json": {yaoModelsMenuModJson, map[string]*bintree{}},
|
||||
"user.mod.json": {yaoModelsUserModJson, map[string]*bintree{}},
|
||||
}},
|
||||
"tables": {nil, 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