From 5a8629f43f40e98f5bc017a7aec6ecf0c9bc9747 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 28 Sep 2021 16:12:55 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E7=B3=BB=E7=BB=9FAPIs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- global/config.go | 4 ++ global/init_test.go | 9 +++++ global/load.go | 6 ++- global/process_test.go | 28 +++++++++++++ table/init_test.go | 28 ------------- table/process.go | 31 +++++++++++--- table/process_test.go | 35 ---------------- xiang/apis/table.http.json | 1 + xiang/tables/README.md | 1 + xiang/tables/user.json | 83 ++++++++++++++++++++++++++++++++++++++ 10 files changed, 156 insertions(+), 70 deletions(-) delete mode 100644 table/init_test.go delete mode 100644 table/process_test.go create mode 100644 xiang/tables/README.md create mode 100644 xiang/tables/user.json diff --git a/global/config.go b/global/config.go index fc407232..4205b67a 100644 --- a/global/config.go +++ b/global/config.go @@ -31,6 +31,10 @@ type XiangConfig struct { RootModel string `json:"root_model,omitempty" env:"XIANG_ROOT_MODEL"` // 应用模型文件目录 RootFLow string `json:"root_flow,omitempty" env:"XIANG_ROOT_FLOW"` // 应用工作流文件目录 RootPlugin string `json:"root_plugin,omitempty" env:"XIANG_ROOT_PLUGIN"` // 应用插件文件目录 + RootTable string `json:"root_table,omitempty" env:"XIANG_ROOT_TABLE"` // 应用表格文件目录 + RootChart string `json:"root_chart,omitempty" env:"XIANG_ROOT_CHART"` // 应用图表文件目录 + RootKanban string `json:"root_kanban,omitempty" env:"XIANG_ROOT_KANBAN"` // 应用看板文件目录 + RootScreen string `json:"root_screen,omitempty" env:"XIANG_ROOT_SCREEN"` // 应用大屏文件目录 } // ServiceConfig 服务配置 diff --git a/global/init_test.go b/global/init_test.go index f0aec264..6b7fcf55 100644 --- a/global/init_test.go +++ b/global/init_test.go @@ -2,15 +2,24 @@ package global import ( "os" + "path" "testing" "github.com/yaoapp/gou" + "github.com/yaoapp/xiang/table" ) var cfg Config func TestMain(m *testing.M) { + // 加载模型等 + Load(Conf) + + // 加载表格(临时) + root := "fs://" + path.Join(Conf.Source, "/app/tables/service.json") + table.Load(root, "service").Reload() + // Run test suites exitVal := m.Run() diff --git a/global/load.go b/global/load.go index 73ceb039..9b927f07 100644 --- a/global/load.go +++ b/global/load.go @@ -10,6 +10,7 @@ import ( "github.com/yaoapp/gou" "github.com/yaoapp/kun/exception" + "github.com/yaoapp/xiang/table" ) // Script 脚本文件类型 @@ -55,7 +56,7 @@ func LoadEngine(from string) { exception.New("读取文件失败, 未找到任何可执行脚本", 500, from).Throw() } - // 加载 API, Flow, Models + // 加载 API, Flow, Models, Table for _, script := range scripts { switch script.Type { case "models": @@ -67,6 +68,9 @@ func LoadEngine(from string) { case "apis": gou.LoadAPI(string(script.Content), "xiang."+script.Name) break + case "tables": + table.Load(string(script.Content), "xiang."+script.Name) + break } } } diff --git a/global/process_test.go b/global/process_test.go index ed2bbca8..36986abc 100644 --- a/global/process_test.go +++ b/global/process_test.go @@ -5,6 +5,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/yaoapp/gou" + "github.com/yaoapp/kun/any" + "github.com/yaoapp/xiang/table" ) func TestProcessPing(t *testing.T) { @@ -13,3 +15,29 @@ func TestProcessPing(t *testing.T) { assert.True(t, ok) assert.Equal(t, res["version"], VERSION) } + +func TestProcessSearch(t *testing.T) { + args := []interface{}{ + "service", + gou.QueryParam{ + Wheres: []gou.QueryWhere{ + {Column: "status", Value: "enabled"}, + }, + }, + 1, + 2, + } + process := gou.NewProcess("xiang.table.Search", args...) + response := table.ProcessSearch(process) + assert.NotNil(t, response) + res := any.Of(response).Map() + assert.True(t, res.Has("data")) + assert.True(t, res.Has("next")) + assert.True(t, res.Has("page")) + assert.True(t, res.Has("pagecnt")) + assert.True(t, res.Has("pagesize")) + assert.True(t, res.Has("prev")) + assert.True(t, res.Has("total")) + assert.Equal(t, 1, res.Get("page")) + assert.Equal(t, 2, res.Get("pagesize")) +} diff --git a/table/init_test.go b/table/init_test.go deleted file mode 100644 index 6470466b..00000000 --- a/table/init_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package table - -import ( - "os" - "path" - "testing" - - "github.com/yaoapp/gou" - "github.com/yaoapp/xiang/global" -) - -func TestMain(m *testing.M) { - - // 加载模型等 - global.Load(global.Conf) - - // 加载表格(临时) - root := "fs://" + path.Join(global.Conf.Source, "/app/tables/service.json") - Load(root, "service").Reload() - - // Run test suites - exitVal := m.Run() - - // we can do clean up code here - gou.KillPlugins() - - os.Exit(exitVal) -} diff --git a/table/process.go b/table/process.go index 8032b835..aa1da01d 100644 --- a/table/process.go +++ b/table/process.go @@ -6,19 +6,21 @@ import ( "github.com/yaoapp/gou" "github.com/yaoapp/kun/any" "github.com/yaoapp/kun/exception" + "github.com/yaoapp/kun/str" ) func init() { // 注册处理器 - gou.RegisterProcessHandler("xiang.table.Search", processSearch) + gou.RegisterProcessHandler("xiang.table.Search", ProcessSearch) } -// processSearch 用户检索 -func processSearch(process *gou.Process) interface{} { +// ProcessSearch xiang.table.Search +// 按条件查询数据记录, 请求成功返回符合查询条件带有分页信息的数据对象 +func ProcessSearch(process *gou.Process) interface{} { + + // 参数处理 process.ValidateArgNums(4) name := any.Of(process.Args[0]).String() - page := any.Of(process.Args[2]).CInt() - pagesize := any.Of(process.Args[3]).CInt() param := gou.QueryParam{} ok := false @@ -29,17 +31,34 @@ func processSearch(process *gou.Process) interface{} { } } + // 执行查询器 table := Select(name) api := table.APIs["search"] - param = mergeQueryParam(param, api, 0) + // 查询校验 if strings.ToLower(api.Process) == "xiang.table.search" { exception.New("循环引用 xiang.table.search", 400).Throw() } + param = mergeQueryParam(param, api, 0) + page := 1 + if str.Of(api.Default[1]) != "" { + page = any.Of(api.Default[1]).CInt() + } + if str.Of(process.Args[2]) != "" { + page = any.Of(process.Args[2]).CInt() + } + pagesize := 15 + if str.Of(api.Default[2]) != "" { + pagesize = any.Of(api.Default[2]).CInt() + } + if str.Of(process.Args[3]) != "" { + pagesize = any.Of(process.Args[3]).CInt() + } return gou.NewProcess(api.Process, param, page, pagesize).Run() } +// 合并默认查询参数 func mergeQueryParam(param gou.QueryParam, api API, i int) gou.QueryParam { if len(api.Default) > i && api.Default[i] != nil { defaults, ok := api.Default[i].(gou.QueryParam) diff --git a/table/process_test.go b/table/process_test.go deleted file mode 100644 index a089971e..00000000 --- a/table/process_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package table - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/yaoapp/gou" - "github.com/yaoapp/kun/any" -) - -func TestProcessSearch(t *testing.T) { - args := []interface{}{ - "service", - gou.QueryParam{ - Wheres: []gou.QueryWhere{ - {Column: "status", Value: "enabled"}, - }, - }, - 1, - 2, - } - process := gou.NewProcess("xiang.table.Search", args...) - response := processSearch(process) - assert.NotNil(t, response) - res := any.Of(response).Map() - assert.True(t, res.Has("data")) - assert.True(t, res.Has("next")) - assert.True(t, res.Has("page")) - assert.True(t, res.Has("pagecnt")) - assert.True(t, res.Has("pagesize")) - assert.True(t, res.Has("prev")) - assert.True(t, res.Has("total")) - assert.Equal(t, 1, res.Get("page")) - assert.Equal(t, 2, res.Get("pagesize")) -} diff --git a/xiang/apis/table.http.json b/xiang/apis/table.http.json index d1e379af..2d581510 100644 --- a/xiang/apis/table.http.json +++ b/xiang/apis/table.http.json @@ -6,6 +6,7 @@ "guard": "bearer-jwt", "paths": [ { + "guard": "-", "path": "/:name/search", "method": "GET", "process": "xiang.table.Search", diff --git a/xiang/tables/README.md b/xiang/tables/README.md new file mode 100644 index 00000000..c39e643d --- /dev/null +++ b/xiang/tables/README.md @@ -0,0 +1 @@ +# 数据表格 diff --git a/xiang/tables/user.json b/xiang/tables/user.json new file mode 100644 index 00000000..5b7ef06b --- /dev/null +++ b/xiang/tables/user.json @@ -0,0 +1,83 @@ +{ + "name": "用户", + "version": "1.0.0", + "decription": "象传用户", + "bind": { + "model": "xiang.user", + "withs": { + "manu": { + "query": { + "select": ["id", "name", "short_name", "status"] + } + }, + "kind": { + "query": { + "select": ["id", "name"] + } + } + } + }, + "apis": {}, + "columns": {}, + "filters": {}, + "list": { + "primary": "id", + "layout": { + "columns": [ + { "name": "姓名", "width": 6 }, + { "name": "类型", "width": 6 }, + { "name": "手机号", "width": 4 } + ], + "filters": [{ "name": "手机号", "width": 6 }] + }, + "actions": { + "create": { + "type": "button", + "props": { + "label": "新建用户", + "icon": "fas fa-plus" + } + }, + "view": {}, + "edit": {}, + "import": {}, + "update": {}, + "delete": {}, + "insert": {}, + "updateWhere": {}, + "deleteWhere": {}, + "updateSelect": {}, + "deleteSelect": {}, + "pagination": {}, + "setting": {} + } + }, + "edit": { + "primary": "id", + "layout": { + "fieldset": [ + { + "title": "基础信息", + "description": "", + "columns": [ + { "name": "姓名", "width": 6 }, + { "name": "类型", "width": 6 }, + { "name": "手机号", "width": 6 } + ] + } + ] + }, + "actions": { + "cancel": {}, + "save": { + "type": "button", + "props": { + "label": "保存" + } + }, + "delete": {} + } + }, + "insert": {}, + "view": {} +}