+ 数据图表载入逻辑
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",
|
"engine": "gou",
|
||||||
"name": "指标对比",
|
"label": "指标对比",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"decription": "指标对比",
|
"decription": "指标对比",
|
||||||
"nodes": [
|
"nodes": [
|
||||||
{
|
{
|
||||||
"name": "行业分布",
|
"name": "行业分布",
|
||||||
"process": "models.service.get",
|
"engine": "xiang",
|
||||||
"query": {
|
"query": {
|
||||||
"select": ["city", ":COUNT(id) as cnt", "@industries.$ as industry"],
|
"select": ["city", ":COUNT(id) as cnt", "industries[*] as industry"],
|
||||||
|
"from": "$service",
|
||||||
"wheres": [
|
"wheres": [
|
||||||
{ "column": "created_at", "value": "{{$query.from}}", "op": "ge" },
|
{ "field": "created_at", ">": "?:$in.from" },
|
||||||
{ "column": "created_at", "value": "{{$query.to}}", "op": "le" }
|
{ "field": "created_at", "<": "?:$in.to" }
|
||||||
],
|
],
|
||||||
"order": ["cnt.desc"],
|
"order": "cnt desc",
|
||||||
"limit": 100,
|
"limit": 100,
|
||||||
"group": ["@industries.$", "city"]
|
"group": ["industries[*]", "city"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "计费方式",
|
"name": "计费方式",
|
||||||
"process": "models.service.get",
|
"engine": "xiang",
|
||||||
"query": {
|
"query": {
|
||||||
"select": ["city", ":COUNT(id) as cnt", "@price_options.$ as option"],
|
"select": ["city", ":COUNT(id) as cnt", "price_options[*] as option"],
|
||||||
|
"from": "$service",
|
||||||
"wheres": [
|
"wheres": [
|
||||||
{ "column": "created_at", "value": "{{$query.from}}", "op": "ge" },
|
{ "field": "created_at", ">": "?:$in.from" },
|
||||||
{ "column": "created_at", "value": "{{$query.to}}", "op": "le" }
|
{ "field": "created_at", "<": "?:$in.to" }
|
||||||
],
|
],
|
||||||
"order": ["cnt.desc"],
|
"order": "cnt desc",
|
||||||
"limit": 100,
|
"limit": 100,
|
||||||
"group": ["@price_options.$", "city"]
|
"group": ["price_options[*]", "city"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -44,7 +46,7 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"data": "{{$res.合并结果}}",
|
"output": "{{$res.合并结果}}",
|
||||||
"filters": {},
|
"filters": {},
|
||||||
"page": {
|
"page": {
|
||||||
"primary": "城市",
|
"primary": "城市",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue