From d868dacd3adb5d5ed21b8a0794feebc3cbc96fe1 Mon Sep 17 00:00:00 2001 From: shaoying Date: Mon, 2 Sep 2019 09:48:12 +0800 Subject: [PATCH] add storage --- src/contexts/cli/cli.go | 4 +- src/contexts/cli/version.go | 2 +- src/contexts/ssh/ssh.go | 164 +++++++++++++++++++++++++++++++---- src/plugin/favor/index.shy | 18 ---- src/plugin/storage/index.go | 36 ++++++++ src/plugin/storage/index.js | 4 + src/plugin/storage/index.shy | 50 +++++++++++ src/plugin/storage/local.shy | 1 + src/toolkit/misc.go | 66 ++++++++++++++ usr/librarys/chat.js | 4 +- usr/librarys/example.js | 6 ++ 11 files changed, 315 insertions(+), 40 deletions(-) create mode 100644 src/plugin/storage/index.go create mode 100644 src/plugin/storage/index.js create mode 100644 src/plugin/storage/index.shy create mode 100644 src/plugin/storage/local.shy diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go index 48d78428..c92841fc 100644 --- a/src/contexts/cli/cli.go +++ b/src/contexts/cli/cli.go @@ -624,7 +624,9 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", format := kit.Select(m.Conf("time", "format"), m.Option("time_format")) t, stamp := time.Now(), true if len(arg) > 0 { - if i, e := strconv.ParseInt(arg[0], 10, 64); e == nil { + if arg[0] == "show" { + stamp = false + } else if i, e := strconv.ParseInt(arg[0], 10, 64); e == nil { t, stamp, arg = time.Unix(int64(i/int64(m.Confi("time", "unit"))), 0), false, arg[1:] } else if n, e := time.ParseInLocation(format, arg[0], time.Local); e == nil { t, arg = n, arg[1:] diff --git a/src/contexts/cli/version.go b/src/contexts/cli/version.go index 092422fb..bb642e34 100644 --- a/src/contexts/cli/version.go +++ b/src/contexts/cli/version.go @@ -4,5 +4,5 @@ var version = struct { host string self int }{ - "2019-08-31 00:31:59", "mac", 495, + "2019-08-31 02:08:47", "mac", 497, } diff --git a/src/contexts/ssh/ssh.go b/src/contexts/ssh/ssh.go index cc72215f..2fdbb1ab 100644 --- a/src/contexts/ssh/ssh.go +++ b/src/contexts/ssh/ssh.go @@ -5,6 +5,7 @@ import ( "contexts/ctx" "fmt" "os/exec" + "sort" "time" "toolkit" @@ -77,10 +78,10 @@ func (ssh *SSH) Close(m *ctx.Message, arg ...string) bool { var Index = &ctx.Context{Name: "ssh", Help: "集群中心", Caches: map[string]*ctx.Cache{ - "nnode": &ctx.Cache{Name: "nnode", Value: "0", Help: "节点数量"}, + "nnode": {Name: "nnode", Value: "0", Help: "节点数量"}, }, Configs: map[string]*ctx.Config{ - "componet": &ctx.Config{Name: "componet", Value: map[string]interface{}{ + "componet": {Name: "componet", Value: map[string]interface{}{ "index": []interface{}{ map[string]interface{}{"componet_name": "ifconfig", "componet_help": "ifconfig", "componet_tmpl": "componet", "componet_view": "", "componet_init": "", @@ -132,21 +133,21 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", }, }, Help: "组件列表"}, - "flow": &ctx.Config{Name: "flow", Value: map[string]interface{}{}, Help: "聊天群组"}, - "work": &ctx.Config{Name: "work", Value: map[string]interface{}{}, Help: "工作信息"}, - "node": &ctx.Config{Name: "node", Value: map[string]interface{}{}, Help: "节点信息"}, - "timer": &ctx.Config{Name: "timer", Value: map[string]interface{}{"interval": "10s", "timer": ""}, Help: "断线重连"}, - "trust": &ctx.Config{Name: "trust", Value: map[string]interface{}{ + "flow": {Name: "flow", Value: map[string]interface{}{}, Help: "聊天群组"}, + "work": {Name: "work", Value: map[string]interface{}{}, Help: "工作信息"}, + "node": {Name: "node", Value: map[string]interface{}{}, Help: "节点信息"}, + "timer": {Name: "timer", Value: map[string]interface{}{"interval": "10s", "timer": ""}, Help: "断线重连"}, + "trust": {Name: "trust", Value: map[string]interface{}{ "renew": true, "fresh": false, "user": true, "up": true, }, Help: "可信节点"}, - "login": &ctx.Config{Name: "login", Value: map[string]interface{}{ + "login": {Name: "login", Value: map[string]interface{}{ "ticker": "10ms", "count": 100, "delay": "10ms", }, Help: "聊天群组"}, }, Commands: map[string]*ctx.Command{ - "_init": &ctx.Command{Name: "_init", Help: "启动初始化", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + "_init": {Name: "_init", Help: "启动初始化", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if m.Confs("runtime", "boot.ctx_box") { m.Conf("runtime", "node.type", "worker") m.Conf("runtime", "node.name", m.Conf("runtime", "boot.pathname")) @@ -161,7 +162,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", m.Cmd("aaa.role", "tech", "componet", "source", "command", "tool") return }}, - "_node": &ctx.Command{Name: "_node [init|create name type module|delete name]", Help: "节点", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + "_node": {Name: "_node [init|create name type module|delete name]", Help: "节点", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) == 0 { m.Confm("ssh.node", func(key string, value map[string]interface{}) { m.Push("create_time", value["create_time"]) @@ -205,7 +206,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", } return }}, - "user": &ctx.Command{Name: "user [init|create|trust [node]]", Help: "用户管理, init: 用户节点, create: 用户创建, trust: 用户授权", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + "user": {Name: "user [init|create|trust [node]]", Help: "用户管理, init: 用户节点, create: 用户创建, trust: 用户授权", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) == 0 { m.Echo(m.Conf("runtime", "user.route")) return @@ -251,7 +252,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", m.Append("user.route", m.Conf("runtime", "user.route")) return }}, - "work": &ctx.Command{Name: "work [serve|create|search]", Help: "工作管理, serve: 创建组织, create: 创建员工, search: 搜索员工", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + "work": {Name: "work [serve|create|search]", Help: "工作管理, serve: 创建组织, create: 创建员工, search: 搜索员工", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) == 0 { m.Confm("work", func(key string, value map[string]interface{}) { m.Add("append", "key", key) @@ -299,7 +300,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", } return }}, - "tool": &ctx.Command{Name: "tool [group index][run group index chatid arg...]", Help: "工具", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + "tool": {Name: "tool [group index][run group index chatid arg...]", Help: "工具", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) == 0 { m.Confm("componet", func(key string, index int, value map[string]interface{}) { if kit.Format(value["componet_type"]) != "public" && m.Option("userrole") != "root" { @@ -339,6 +340,9 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", } } + msg.Option("river", arg[3]) + msg.Option("storm", arg[1]) + arg = arg[4:] args := []string{} for _, v := range kit.Trans(tool["componet_args"]) { @@ -385,8 +389,130 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", } return }}, + "data": {Name: "data show|save|create|insert", Help: "数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + if len(arg) == 0 { + arg = append(arg, "show") + } - "remote": &ctx.Command{Name: "remote auto|dial|listen args...", Help: "连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + switch arg[0] { + case "show": + switch len(arg) { + case 1: // 数据库 + m.Confm("flow", []string{m.Option("river"), "data"}, func(key string, value map[string]interface{}) { + m.Push("create_time", kit.Chains(value, "meta.create_time")) + m.Push("create_user", kit.Chains(value, "meta.create_user")) + m.Push("table", key) + m.Push("count", len(value["list"].([]interface{}))) + }) + + case 2: // 关系表 + hide := map[string]bool{"create_time": true, "update_time": true, "extra": true} + m.Confm("flow", []string{m.Option("river"), "data", arg[1], "list"}, func(index int, value map[string]interface{}) { + for k := range value { + if !hide[k] { + hide[k] = false + } + } + }) + + keys := []string{} + for k, hide := range hide { + if !hide { + keys = append(keys, k) + } + } + sort.Strings(keys) + + m.Confm("flow", []string{m.Option("river"), "data", arg[1], "list"}, func(index int, value map[string]interface{}) { + for _, k := range keys { + m.Push(k, kit.Format(value[k])) + } + }) + + default: // 记录值 + m.Confm("flow", []string{m.Option("river"), "data", arg[1], "list", arg[2]}, func(key string, value string) { + m.Push("key", key) + m.Push("value", value) + }) + } + m.Table() + + case "save": + if len(arg) == 1 { + m.Confm("flow", []string{m.Option("river"), "data"}, func(key string, value map[string]interface{}) { + arg = append(arg, key) + }) + } + + for _, v := range arg[1:] { + data := m.Confm("flow", []string{m.Option("river"), "data", v}) + kit.Marshal(data["meta"], path.Join("var/data", m.Option("river"), v, "/meta.json")) + kit.Marshal(data["list"], path.Join("var/data", m.Option("river"), v, "/list.csv")) + + l := len(data["list"].([]interface{})) + m.Push("table", v).Push("count", l) + m.Log("info", "save table %s:%s %d", m.Option("river"), v, l) + } + m.Table() + + case "create": + if m.Confs("flow", []string{m.Option("river"), "data", arg[1]}) { + break + } + + tmpl := map[string]interface{}{"create_time": m.Time(), "update_time": m.Time(), "extra": "{}", "id": 0} + for i := 2; i < len(arg)-1; i += 2 { + tmpl[arg[i]] = arg[i+1] + } + + m.Confv("flow", []string{m.Option("river"), "data", arg[1]}, map[string]interface{}{ + "meta": map[string]interface{}{ + "create_user": m.Option("username"), + "create_time": m.Time(), + "create_tmpl": tmpl, + }, + "list": []interface{}{}, + }) + m.Log("info", "create table %s:%s", m.Option("river"), arg[1]) + + case "insert": + if len(arg) == 2 { + m.Cmd("ssh.data", "show", arg[1]) + break + } + if !m.Confs("flow", []string{m.Option("river"), "data", arg[1]}) { + m.Cmd("ssh.data", "create", arg[1:]) + } + + id := m.Confi("flow", []string{m.Option("river"), "data", arg[1], "meta", "count"}) + 1 + m.Confi("flow", []string{m.Option("river"), "data", arg[1], "meta", "count"}, id) + + data := map[string]interface{}{} + extra := map[string]interface{}{} + tmpl := m.Confm("flow", []string{m.Option("river"), "data", arg[1], "meta", "create_tmpl"}) + for k, v := range tmpl { + data[k] = v + } + for i := 2; i < len(arg)-1; i += 2 { + if _, ok := tmpl[arg[i]]; ok { + data[arg[i]] = arg[i+1] + } else { + extra[arg[i]] = arg[i+1] + } + } + data["create_time"] = m.Time() + data["update_time"] = m.Time() + data["extra"] = extra + data["id"] = id + + m.Log("info", "insert %s:%s %s", m.Option("river"), arg[1], kit.Format(data)) + m.Confv("flow", []string{m.Option("river"), "data", arg[1], "list", "-2"}, data) + m.Cmdy("ssh.data", "save", arg[1]) + } + return + }}, + + "remote": {Name: "remote auto|dial|listen args...", Help: "连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) == 0 { m.Cmd("_node") return @@ -506,7 +632,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", } return }}, - "_route": &ctx.Command{Name: "_route", Help: "路由", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + "_route": {Name: "_route", Help: "路由", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { m.Log("time", "exec: %v", m.Format("cost")) if len(arg) == 0 { return @@ -630,7 +756,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", } return }}, - "_right": &ctx.Command{Name: "_right [node|user|work]", Help: []string{"认证", + "_right": {Name: "_right [node|user|work]", Help: []string{"认证", "node [check text|trust node]", "user [create|check text|share role node...|proxy node|trust node]", "work [create node name|check node name]", @@ -821,7 +947,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", } return }}, - "_check": &ctx.Command{Name: "_check node|user|work", Help: []string{"验签", + "_check": {Name: "_check node|user|work", Help: []string{"验签", "node", "user [node text]", "work name [node cert]", }, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { switch arg[0] { @@ -906,7 +1032,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", } return }}, - "_exec": &ctx.Command{Name: "_exec", Help: "命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + "_exec": {Name: "_exec", Help: "命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { access := m.Option("access", kit.Hashs( m.Option("node.route"), m.Option("user.route"), @@ -984,7 +1110,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", return }}, - "login": &ctx.Command{Name: "login address", Help: "网络连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + "login": {Name: "login address", Help: "网络连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) == 0 { arg = append(arg, "shy@shylinux.com") } diff --git a/src/plugin/favor/index.shy b/src/plugin/favor/index.shy index d94d0bd4..08775e92 100644 --- a/src/plugin/favor/index.shy +++ b/src/plugin/favor/index.shy @@ -6,11 +6,6 @@ fun qrcode "二维码" "index.js" public \ append qrcode ($1 || $referer) end -kit clip "粘贴板" public "ssh._route" _ "aaa.clip" \ - text "" name you imports plugin_you action auto \ - text "" name txt view long \ - button "保存" - kit macro "脚本宏" "macro.js" public \ text "" name mac imports plugin_mac action auto \ button "查看" \ @@ -24,19 +19,6 @@ kit sys "命令行" public "nfs.source" \ button "运行" \ exports mac name -fun note "记事本" public \ - text "" name tip imports plugin_tip view long action auto \ - button "创建" action auto \ - exports tip file tip \ - feature display inner - - if $1 == "" || $1 ~ ".*/$" - copy context wiki tree __ - else - copy context wiki text __ - end -end - fun salary "工资单" public \ text "9000" label total \ text "9000" label base \ diff --git a/src/plugin/storage/index.go b/src/plugin/storage/index.go new file mode 100644 index 00000000..82ab5752 --- /dev/null +++ b/src/plugin/storage/index.go @@ -0,0 +1,36 @@ +package main + +import ( + "contexts/cli" + "contexts/ctx" + "toolkit" + + "fmt" + "os" +) + +var Index = &ctx.Context{Name: "test", Help: "测试工具", + Caches: map[string]*ctx.Cache{}, + Configs: map[string]*ctx.Config{ + "_index": &ctx.Config{Name: "index", Value: []interface{}{ + map[string]interface{}{"name": "demo", "help": "demo", + "tmpl": "componet", "view": "componet", "init": "", + "type": "public", "ctx": "demo", "cmd": "demo", + "args": []interface{}{}, "inputs": []interface{}{ + map[string]interface{}{"type": "text", "name": "pod", "value": "hello world"}, + map[string]interface{}{"type": "button", "value": "执行"}, + }, + }, + }}, + }, + Commands: map[string]*ctx.Command{ + "demo": {Name: "demo", Help: "demo", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + m.Echo(kit.Select("hello world", arg, 0)) + return + }}, + }, +} + +func main() { + fmt.Print(cli.Index.Plugin(Index, os.Args[1:])) +} diff --git a/src/plugin/storage/index.js b/src/plugin/storage/index.js new file mode 100644 index 00000000..8c8f3659 --- /dev/null +++ b/src/plugin/storage/index.js @@ -0,0 +1,4 @@ + +{init: function(page, pane, field, option, output) { + kit.Log("hello world") +}} diff --git a/src/plugin/storage/index.shy b/src/plugin/storage/index.shy new file mode 100644 index 00000000..536ae7c3 --- /dev/null +++ b/src/plugin/storage/index.shy @@ -0,0 +1,50 @@ + +kit xiao "数据库" public "ssh.data" show \ + text "" name table imports plugin_table action auto view long \ + text "" name index action auto \ + button "查看" action auto \ + button "返回" click Last \ + exports table table + +fun meet "第一眼" public \ + text "" name table imports plugin_table \ + text "" name when \ + text "" name where \ + button "添加" + + if $2 == "" + return "time miss" + end + if $3 == "" + return "meet miss" + end + copy ssh.data insert _ when _ where __ +end + +fun clip "粘贴板" public \ + text "" name you imports plugin_you action auto \ + text "" name txt view long \ + button "保存" action auto + + if $2 == "" + copy ssh._route _ data show clip + else + copy ssh._route _ data insert clip txt $2 + end +end + +fun note "记事本" public \ + text "" name you imports plugin_you action auto \ + text "" name tip imports plugin_tip view long action auto \ + button "查看" action auto \ + button "返回" click Last \ + exports tip file tip \ + feature display inner + + if $2 == "" || $2 ~ ".*/$" + copy ssh._route _ context wiki tree __ + else + copy ssh._route _ context wiki text __ + end +end + diff --git a/src/plugin/storage/local.shy b/src/plugin/storage/local.shy new file mode 100644 index 00000000..0519ecba --- /dev/null +++ b/src/plugin/storage/local.shy @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/toolkit/misc.go b/src/toolkit/misc.go index 58db9b93..692edc94 100644 --- a/src/toolkit/misc.go +++ b/src/toolkit/misc.go @@ -1,9 +1,13 @@ package kit import ( + "encoding/csv" + "encoding/json" "fmt" + "io/ioutil" "os" "path" + "strings" ) type TERM interface { @@ -89,3 +93,65 @@ func FmtTime(t int64) string { } return fmt.Sprintf("%s%dns", sign, time) } + +func Marshal(data interface{}, arg ...interface{}) string { + if len(arg) > 0 { + switch arg := arg[0].(type) { + case string: + if f, p, e := Create(arg); e == nil { + defer f.Close() + + switch { + case strings.HasSuffix(arg, ".json"): + b, _ := json.MarshalIndent(data, "", " ") + if n, e := f.Write(b); e == nil && n == len(b) { + return p + } + + case strings.HasSuffix(arg, ".csv"): + switch data := data.(type) { + case []interface{}: + w := csv.NewWriter(f) + head := []string{} + for _, v := range data { + switch v := v.(type) { + case map[string]interface{}: + if len(head) == 0 { + for k, _ := range v { + head = append(head, k) + } + w.Write(head) + } + + fields := []string{} + for _, k := range head { + fields = append(fields, Format(v[k])) + } + w.Write(fields) + } + } + w.Flush() + } + } + } + } + } + + b, _ := json.MarshalIndent(data, "", " ") + return string(b) +} +func UnMarshal(data string) interface{} { + var res interface{} + if strings.HasSuffix(data, ".json") { + if b, e := ioutil.ReadFile(data); e == nil { + json.Unmarshal(b, &res) + } + } else { + json.Unmarshal([]byte(data), &res) + } + return res +} +func UnMarshalm(data string) map[string]interface{} { + res, _ := UnMarshal(data).(map[string]interface{}) + return res +} diff --git a/usr/librarys/chat.js b/usr/librarys/chat.js index 29489625..244e5f29 100644 --- a/usr/librarys/chat.js +++ b/usr/librarys/chat.js @@ -231,8 +231,10 @@ var page = Page({ var ui = kit.AppendChild(field, [{"view": ["input", "textarea"], "data": {"onkeyup": function(event){ page.oninput(event), kit.isSpace(event.key) && field.Pane.which.set(event.target.value) event.key == "Enter" && !event.shiftKey && page.target.Pane.Send("text", event.target.value, field.Pane.clear) + event.stopPropagation() }, "onkeydown": function(event) { - event.key == "Enter" && !event.shiftKey && event.preventDefault() + event.key == "Enter" && !event.shiftKey + event.stopPropagation() }}}]) return { Select: function() { diff --git a/usr/librarys/example.js b/usr/librarys/example.js index 639af2f1..b5689dda 100644 --- a/usr/librarys/example.js +++ b/usr/librarys/example.js @@ -700,6 +700,7 @@ function Plugin(page, pane, field, runs) { var feature = JSON.parse(meta.feature||'{}') var exports = JSON.parse(meta.exports||'["",""]') var deal = (feature && feature.display) || "table" + var history = [] var plugin = Meta(field, (field.Script && field.Script.init || function() { })(run, field, option, output)||{}, { @@ -739,6 +740,7 @@ function Plugin(page, pane, field, runs) { (typeof item.imports == "object"? item.imports: typeof item.imports == "string"? [item.imports]: []).forEach(function(imports) { page.Sync(imports).change(function(value) { + history.push({target: action.target, value: action.target.value}); (action.target.value = value) && item.action == "auto" && plugin.Runs(window.event) }) }) @@ -774,6 +776,10 @@ function Plugin(page, pane, field, runs) { run(event, cmds, cbs) }).field.Plugin }, + Last: function() { + var list = history.pop() + list && (list.target.value = list.value, plugin.Check()) + }, Help: function(type, action) { var text = []