加载系统APIs
This commit is contained in:
parent
4c92fa3015
commit
5a8629f43f
10 changed files with 156 additions and 70 deletions
|
|
@ -31,6 +31,10 @@ type XiangConfig struct {
|
||||||
RootModel string `json:"root_model,omitempty" env:"XIANG_ROOT_MODEL"` // 应用模型文件目录
|
RootModel string `json:"root_model,omitempty" env:"XIANG_ROOT_MODEL"` // 应用模型文件目录
|
||||||
RootFLow string `json:"root_flow,omitempty" env:"XIANG_ROOT_FLOW"` // 应用工作流文件目录
|
RootFLow string `json:"root_flow,omitempty" env:"XIANG_ROOT_FLOW"` // 应用工作流文件目录
|
||||||
RootPlugin string `json:"root_plugin,omitempty" env:"XIANG_ROOT_PLUGIN"` // 应用插件文件目录
|
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 服务配置
|
// ServiceConfig 服务配置
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,24 @@ package global
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/yaoapp/gou"
|
"github.com/yaoapp/gou"
|
||||||
|
"github.com/yaoapp/xiang/table"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cfg Config
|
var cfg Config
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
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
|
// Run test suites
|
||||||
exitVal := m.Run()
|
exitVal := m.Run()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
"github.com/yaoapp/gou"
|
"github.com/yaoapp/gou"
|
||||||
"github.com/yaoapp/kun/exception"
|
"github.com/yaoapp/kun/exception"
|
||||||
|
"github.com/yaoapp/xiang/table"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Script 脚本文件类型
|
// Script 脚本文件类型
|
||||||
|
|
@ -55,7 +56,7 @@ func LoadEngine(from string) {
|
||||||
exception.New("读取文件失败, 未找到任何可执行脚本", 500, from).Throw()
|
exception.New("读取文件失败, 未找到任何可执行脚本", 500, from).Throw()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载 API, Flow, Models
|
// 加载 API, Flow, Models, Table
|
||||||
for _, script := range scripts {
|
for _, script := range scripts {
|
||||||
switch script.Type {
|
switch script.Type {
|
||||||
case "models":
|
case "models":
|
||||||
|
|
@ -67,6 +68,9 @@ func LoadEngine(from string) {
|
||||||
case "apis":
|
case "apis":
|
||||||
gou.LoadAPI(string(script.Content), "xiang."+script.Name)
|
gou.LoadAPI(string(script.Content), "xiang."+script.Name)
|
||||||
break
|
break
|
||||||
|
case "tables":
|
||||||
|
table.Load(string(script.Content), "xiang."+script.Name)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/yaoapp/gou"
|
"github.com/yaoapp/gou"
|
||||||
|
"github.com/yaoapp/kun/any"
|
||||||
|
"github.com/yaoapp/xiang/table"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestProcessPing(t *testing.T) {
|
func TestProcessPing(t *testing.T) {
|
||||||
|
|
@ -13,3 +15,29 @@ func TestProcessPing(t *testing.T) {
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, res["version"], VERSION)
|
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"))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
}
|
|
||||||
|
|
@ -6,19 +6,21 @@ import (
|
||||||
"github.com/yaoapp/gou"
|
"github.com/yaoapp/gou"
|
||||||
"github.com/yaoapp/kun/any"
|
"github.com/yaoapp/kun/any"
|
||||||
"github.com/yaoapp/kun/exception"
|
"github.com/yaoapp/kun/exception"
|
||||||
|
"github.com/yaoapp/kun/str"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// 注册处理器
|
// 注册处理器
|
||||||
gou.RegisterProcessHandler("xiang.table.Search", processSearch)
|
gou.RegisterProcessHandler("xiang.table.Search", ProcessSearch)
|
||||||
}
|
}
|
||||||
|
|
||||||
// processSearch 用户检索
|
// ProcessSearch xiang.table.Search
|
||||||
func processSearch(process *gou.Process) interface{} {
|
// 按条件查询数据记录, 请求成功返回符合查询条件带有分页信息的数据对象
|
||||||
|
func ProcessSearch(process *gou.Process) interface{} {
|
||||||
|
|
||||||
|
// 参数处理
|
||||||
process.ValidateArgNums(4)
|
process.ValidateArgNums(4)
|
||||||
name := any.Of(process.Args[0]).String()
|
name := any.Of(process.Args[0]).String()
|
||||||
page := any.Of(process.Args[2]).CInt()
|
|
||||||
pagesize := any.Of(process.Args[3]).CInt()
|
|
||||||
|
|
||||||
param := gou.QueryParam{}
|
param := gou.QueryParam{}
|
||||||
ok := false
|
ok := false
|
||||||
|
|
@ -29,17 +31,34 @@ func processSearch(process *gou.Process) interface{} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 执行查询器
|
||||||
table := Select(name)
|
table := Select(name)
|
||||||
api := table.APIs["search"]
|
api := table.APIs["search"]
|
||||||
param = mergeQueryParam(param, api, 0)
|
|
||||||
|
|
||||||
|
// 查询校验
|
||||||
if strings.ToLower(api.Process) == "xiang.table.search" {
|
if strings.ToLower(api.Process) == "xiang.table.search" {
|
||||||
exception.New("循环引用 xiang.table.search", 400).Throw()
|
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()
|
return gou.NewProcess(api.Process, param, page, pagesize).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 合并默认查询参数
|
||||||
func mergeQueryParam(param gou.QueryParam, api API, i int) gou.QueryParam {
|
func mergeQueryParam(param gou.QueryParam, api API, i int) gou.QueryParam {
|
||||||
if len(api.Default) > i && api.Default[i] != nil {
|
if len(api.Default) > i && api.Default[i] != nil {
|
||||||
defaults, ok := api.Default[i].(gou.QueryParam)
|
defaults, ok := api.Default[i].(gou.QueryParam)
|
||||||
|
|
|
||||||
|
|
@ -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"))
|
|
||||||
}
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
"guard": "bearer-jwt",
|
"guard": "bearer-jwt",
|
||||||
"paths": [
|
"paths": [
|
||||||
{
|
{
|
||||||
|
"guard": "-",
|
||||||
"path": "/:name/search",
|
"path": "/:name/search",
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"process": "xiang.table.Search",
|
"process": "xiang.table.Search",
|
||||||
|
|
|
||||||
1
xiang/tables/README.md
Normal file
1
xiang/tables/README.md
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
# 数据表格
|
||||||
83
xiang/tables/user.json
Normal file
83
xiang/tables/user.json
Normal file
|
|
@ -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": {}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue