+ 数据图表载入逻辑
This commit is contained in:
parent
a6f9f1383f
commit
afd781cd86
7 changed files with 146 additions and 14 deletions
1
chart/REAME.md
Normal file
1
chart/REAME.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
# 数据图表
|
||||
49
chart/chart.go
Normal file
49
chart/chart.go
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
package chart
|
||||
|
||||
import (
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xiang/share"
|
||||
"github.com/yaoapp/xiang/xlog"
|
||||
)
|
||||
|
||||
// Charts 已载入图表
|
||||
var Charts = map[string]*Chart{}
|
||||
|
||||
// Load 加载数据表格
|
||||
func Load(cfg config.Config) {
|
||||
LoadFrom(cfg.RootChart, "")
|
||||
}
|
||||
|
||||
// LoadFrom 从特定目录加载
|
||||
func LoadFrom(dir string, prefix string) {
|
||||
|
||||
if share.DirNotExists(dir) {
|
||||
return
|
||||
}
|
||||
|
||||
share.Walk(dir, ".json", func(root, filename string) {
|
||||
name := share.SpecName(root, filename)
|
||||
content := share.ReadFile(filename)
|
||||
chart, err := LoadChart(content, name)
|
||||
if err != nil {
|
||||
exception.New("%s 图表格式错误", 400, name).Ctx(filename).Throw()
|
||||
}
|
||||
Charts[name] = chart
|
||||
})
|
||||
}
|
||||
|
||||
// LoadChart 载入数据表格
|
||||
func LoadChart(source []byte, name string) (*Chart, error) {
|
||||
chart := Chart{}
|
||||
err := jsoniter.Unmarshal(source, &chart)
|
||||
if err != nil {
|
||||
xlog.Println(name)
|
||||
xlog.Println(err.Error())
|
||||
xlog.Println(string(source))
|
||||
return nil, err
|
||||
}
|
||||
chart.Prepare()
|
||||
return &chart, nil
|
||||
}
|
||||
29
chart/chart_test.go
Normal file
29
chart/chart_test.go
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package chart
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xiang/model"
|
||||
"github.com/yaoapp/xiang/query"
|
||||
"github.com/yaoapp/xiang/share"
|
||||
)
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
share.DBConnect(config.Conf.Database)
|
||||
model.Load(config.Conf)
|
||||
query.Load(config.Conf)
|
||||
|
||||
Load(config.Conf)
|
||||
LoadFrom("not a path", "404.")
|
||||
check(t)
|
||||
}
|
||||
|
||||
func check(t *testing.T) {
|
||||
keys := []string{}
|
||||
for key := range Charts {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
assert.Equal(t, 1, len(keys))
|
||||
}
|
||||
21
chart/types.go
Normal file
21
chart/types.go
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package chart
|
||||
|
||||
import (
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/xiang/share"
|
||||
)
|
||||
|
||||
// Chart 图表格式
|
||||
type Chart struct {
|
||||
gou.Flow
|
||||
APIs map[string]API `json:"apis,omitempty"`
|
||||
Filters map[string]share.Filter `json:"filters,omitempty"`
|
||||
Page share.Page `json:"page,omitempty"`
|
||||
}
|
||||
|
||||
// API 图表 API
|
||||
type API struct {
|
||||
Disable bool `json:"disable,omitempty"`
|
||||
Guard string `json:"guard,omitempty"`
|
||||
Default interface{} `json:"default,omitempty"`
|
||||
}
|
||||
1
query/README.md
Normal file
1
query/README.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
# 数据分析查询引擎
|
||||
29
query/query.go
Normal file
29
query/query.go
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package query
|
||||
|
||||
import (
|
||||
"github.com/yaoapp/gou"
|
||||
dsl "github.com/yaoapp/gou/query/gou"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xun/capsule"
|
||||
)
|
||||
|
||||
// Load 加载查询引擎
|
||||
func Load(cfg config.Config) {
|
||||
XiangQuery()
|
||||
}
|
||||
|
||||
// XiangQuery 注册应用引擎象 xiang
|
||||
func XiangQuery() {
|
||||
gou.RegisterEngine("xiang", &dsl.Query{
|
||||
Query: capsule.Query(),
|
||||
GetTableName: func(s string) string {
|
||||
if mod, has := gou.Models[s]; has {
|
||||
return mod.MetaData.Table.Name
|
||||
}
|
||||
exception.New("%s 数据模型尚未加载", 404).Throw()
|
||||
return s
|
||||
},
|
||||
AESKey: config.Conf.Database.AESKey,
|
||||
})
|
||||
}
|
||||
|
|
@ -1,35 +1,37 @@
|
|||
{
|
||||
"engine": "gou",
|
||||
"name": "指标对比",
|
||||
"label": "指标对比",
|
||||
"version": "1.0.0",
|
||||
"decription": "指标对比",
|
||||
"nodes": [
|
||||
{
|
||||
"name": "行业分布",
|
||||
"process": "models.service.get",
|
||||
"engine": "xiang",
|
||||
"query": {
|
||||
"select": ["city", ":COUNT(id) as cnt", "@industries.$ as industry"],
|
||||
"select": ["city", ":COUNT(id) as cnt", "industries[*] as industry"],
|
||||
"from": "$service",
|
||||
"wheres": [
|
||||
{ "column": "created_at", "value": "{{$query.from}}", "op": "ge" },
|
||||
{ "column": "created_at", "value": "{{$query.to}}", "op": "le" }
|
||||
{ "field": "created_at", ">": "?:$in.from" },
|
||||
{ "field": "created_at", "<": "?:$in.to" }
|
||||
],
|
||||
"order": ["cnt.desc"],
|
||||
"order": "cnt desc",
|
||||
"limit": 100,
|
||||
"group": ["@industries.$", "city"]
|
||||
"group": ["industries[*]", "city"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "计费方式",
|
||||
"process": "models.service.get",
|
||||
"engine": "xiang",
|
||||
"query": {
|
||||
"select": ["city", ":COUNT(id) as cnt", "@price_options.$ as option"],
|
||||
"select": ["city", ":COUNT(id) as cnt", "price_options[*] as option"],
|
||||
"from": "$service",
|
||||
"wheres": [
|
||||
{ "column": "created_at", "value": "{{$query.from}}", "op": "ge" },
|
||||
{ "column": "created_at", "value": "{{$query.to}}", "op": "le" }
|
||||
{ "field": "created_at", ">": "?:$in.from" },
|
||||
{ "field": "created_at", "<": "?:$in.to" }
|
||||
],
|
||||
"order": ["cnt.desc"],
|
||||
"order": "cnt desc",
|
||||
"limit": 100,
|
||||
"group": ["@price_options.$", "city"]
|
||||
"group": ["price_options[*]", "city"]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -44,7 +46,7 @@
|
|||
]
|
||||
}
|
||||
],
|
||||
"data": "{{$res.合并结果}}",
|
||||
"output": "{{$res.合并结果}}",
|
||||
"filters": {},
|
||||
"page": {
|
||||
"primary": "城市",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue