From 281d6cff52f9d840c4575fb0642170f66f93ce93 Mon Sep 17 00:00:00 2001 From: shaoying Date: Tue, 21 May 2019 18:07:22 +0800 Subject: [PATCH] add ssh.componet --- src/contexts/ctx/ctx.go | 13 ++- src/contexts/ssh/ssh.go | 33 +++++++ src/examples/chat/chat.go | 46 ++++++++++ src/toolkit/kit.go | 9 ++ usr/librarys/chat.css | 58 +++++++++++- usr/librarys/chat.js | 184 ++++++++++++++++++++++++++++++++------ usr/librarys/context.js | 2 +- usr/librarys/example.js | 38 +++++++- usr/librarys/toolkit.js | 99 ++++++++++++-------- 9 files changed, 406 insertions(+), 76 deletions(-) diff --git a/src/contexts/ctx/ctx.go b/src/contexts/ctx/ctx.go index 7bd5875f..200f0a80 100644 --- a/src/contexts/ctx/ctx.go +++ b/src/contexts/ctx/ctx.go @@ -1427,7 +1427,7 @@ func (m *Message) Match(key string, spawn bool, hand func(m *Message, s *Context } context := []*Context{m.target} - for _, v := range []string{"aaa", "cli"} { + for _, v := range []string{"aaa", "ssh", "cli", "nfs"} { if msg := m.Sess(v, false); msg != nil && msg.target != nil { context = append(context, msg.target) } @@ -1730,6 +1730,17 @@ func (m *Message) Confm(key string, args ...interface{}) map[string]interface{} } } } + case func(string, int, map[string]interface{}): + for k, v := range value { + if val, ok := v.([]interface{}); ok { + for i, v := range val { + if val, ok := v.(map[string]interface{}); ok { + fun(k, i, val) + } + } + } + } + case func(string, map[string]interface{}) bool: for k, v := range value { if val, ok := v.(map[string]interface{}); ok { diff --git a/src/contexts/ssh/ssh.go b/src/contexts/ssh/ssh.go index d0d776fb..d4901563 100644 --- a/src/contexts/ssh/ssh.go +++ b/src/contexts/ssh/ssh.go @@ -37,6 +37,20 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", "cert": &ctx.Config{Name: "cert", Value: map[string]interface{}{}, Help: "用户信息"}, "trust": &ctx.Config{Name: "trust", Value: map[string]interface{}{"fresh": false, "user": true, "up": true}, Help: "可信节点"}, "timer": &ctx.Config{Name: "timer", Value: map[string]interface{}{"interval": "10s", "timer": ""}, Help: "断线重连"}, + "componet": &ctx.Config{Name: "componet", Value: map[string]interface{}{ + "index": []interface{}{ + map[string]interface{}{"componet_name": "pwd", "componet_help": "pwd", "componet_tmpl": "componet", + "componet_view": "FlashList", "componet_init": "initFlashList", + "componet_ctx": "nfs", "componet_cmd": "pwd", + "display_result": "", "display_append": "", + }, + map[string]interface{}{"componet_name": "dir", "componet_help": "dir", "componet_tmpl": "componet", + "componet_view": "FlashList", "componet_init": "initFlashList", + "componet_ctx": "nfs", "componet_cmd": "dir", + "display_result": "", "display_append": "", + }, + }, + }, 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) { @@ -220,6 +234,11 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", m.Echo("true") } } + case "tool": + switch arg[1] { + case "check": // 数字验签 + m.Cmdy("ssh.remote", arg[2], "check", arg[0]) + } } return }}, @@ -264,6 +283,14 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", m.Echo(arg[1]) } } + case "tool": + m.Confm("componet", func(key string, index int, value map[string]interface{}) { + m.Add("append", "key", key) + m.Add("append", "index", index) + m.Add("append", "name", value["componet_name"]) + m.Add("append", "help", value["componet_help"]) + }) + m.Table() } return }}, @@ -338,6 +365,12 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", m.Cmdm(arg) return }}, + "componet": &ctx.Command{Name: "componet", Help: "组件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + tool := m.Confm("componet", []string{arg[0], arg[1]}) + msg := m.Find(kit.Format(tool["componet_ctx"])) + msg.Cmd(tool["componet_cmd"]).CopyTo(m) + return + }}, "remote": &ctx.Command{Name: "remote auto|dial|listen args...", Help: "连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { // 设备证书 if !m.Confs("runtime", "node.cert") || !m.Confs("runtime", "node.key") { diff --git a/src/examples/chat/chat.go b/src/examples/chat/chat.go index 5bdc33bd..12d6bd87 100644 --- a/src/examples/chat/chat.go +++ b/src/examples/chat/chat.go @@ -252,15 +252,61 @@ var Index = &ctx.Context{Name: "chat", Help: "会议中心", "list": list, }) } + case "storm": switch arg[1] { + case "create": + list := []interface{}{} + for i := 4; i < len(arg)-3; i += 4 { + list = append(list, map[string]interface{}{ + "node": arg[i], "group": arg[i+1], "index": arg[i+2], "name": arg[i+3], + }) + } + + m.Conf("flow", []string{arg[2], "tool", arg[3]}, map[string]interface{}{ + "create_user": m.Option("username"), + "create_time": m.Time(), + "list": list, + }) + case "wind": switch arg[2] { case "text": } + + default: + if len(arg) == 2 { + m.Confm("flow", []string{arg[1], "tool"}, func(key string, value map[string]interface{}) { + m.Add("append", "key", key) + m.Add("append", "count", kit.Len(value["list"])) + }) + m.Table() + break + } + if len(arg) == 3 { + m.Confm("flow", []string{arg[1], "tool", arg[2], "list"}, func(index int, value map[string]interface{}) { + m.Add("append", "node", value["node"]) + m.Add("append", "group", value["group"]) + m.Add("append", "index", value["index"]) + m.Add("append", "name", value["name"]) + }) + m.Table() + break + } + + if tool := m.Confm("flow", []string{arg[1], "tool", arg[2], "list", arg[3]}); tool != nil { + m.Option("username", "shy") + m.Cmdy("ssh.remote", tool["node"], "componet", tool["group"], tool["index"]) + break + } } + case "steam": + switch arg[1] { + case "tool": + m.Cmdy("ssh.cert", "tool", "check", arg[2]) + } } return }}, diff --git a/src/toolkit/kit.go b/src/toolkit/kit.go index b1866230..b45010d1 100644 --- a/src/toolkit/kit.go +++ b/src/toolkit/kit.go @@ -35,6 +35,15 @@ func Log(action string, str string, args ...interface{}) { func Width(str string, mul int) int { return len([]rune(str)) + (len(str)-len([]rune(str)))/2/mul } +func Len(arg interface{}) int { + switch arg := arg.(type) { + case []interface{}: + return len(arg) + case map[string]interface{}: + return len(arg) + } + return 0 +} func Int(arg ...interface{}) int { result := 0 for _, v := range arg { diff --git a/usr/librarys/chat.css b/usr/librarys/chat.css index 894ff627..f8d2d4ec 100644 --- a/usr/librarys/chat.css +++ b/usr/librarys/chat.css @@ -2,11 +2,33 @@ fieldset div.output { padding:6px; } fieldset.Ocean { - background-color:red; - padding:0; + background-color:lightgray; + padding:10px; display:none; position:absolute; } +fieldset.Ocean div.action { + margin:10px; +} +fieldset.Ocean div.output { + float:left; + padding:0; +} +fieldset.Ocean div.output table td { + min-width:100px; +} +fieldset.Ocean div.output table th { + min-width:130px; +} +fieldset.Ocean div.create { + padding:10px; + border:solid 2px green; + margin-left:10px; + float:left; +} +fieldset.Ocean div.create pre:hover { + background-color:red; +} fieldset.River { padding:0; min-width:160px; @@ -65,8 +87,36 @@ fieldset.Storm div.output div.item.select { background-color:red; } fieldset.Steam { - background-color:red; - padding:0; + background-color:lightgray; + padding:10px; display:none; position:absolute; } +fieldset.Steam div.action { + margin:10px; +} +fieldset.Steam div.output { + float:left; + padding:0; +} +fieldset.Steam div.output table td { + min-width:100px; +} +fieldset.Steam div.output table th { + min-width:130px; +} +fieldset.Steam table.device { + padding:10px; + border:solid 2px green; + margin-left:10px; + float:left; +} +fieldset.Steam div.create { + padding:10px; + border:solid 2px green; + margin-left:10px; + float:left; +} +fieldset.Steam div.create pre:hover { + background-color:red; +} diff --git a/usr/librarys/chat.js b/usr/librarys/chat.js index ad28436c..8ce12146 100644 --- a/usr/librarys/chat.js +++ b/usr/librarys/chat.js @@ -19,16 +19,93 @@ var page = Page({ page.action.Size(sizes.width, sizes.action) }, + oncontrol: function(event, target, action) { + switch (action) { + case "control": + if (event.ctrlKey) { + switch (event.key) { + case "n": + page.ocean.Show() + break + case "m": + page.steam.Show() + + } + break + } + break + } + }, initOcean: function(page, pane, form, output) { var table = kit.AppendChild(output, "table") + var ui = kit.AppendChild(pane, [{view: ["create ocean"], list: [ + {input: ["name", function(event) { + if (event.ctrlKey) { + switch (event.key) { + case "a": + pane.Action["全选"](event) + break + case "c": + pane.Action["清空"](event) + break + } + return + } + + if (event.key == "Enter") { + ui.name.nextSibling.click() + } + }]}, {button: ["create", function(event) { + if (!ui.name.value) { + ui.name.focus() + return + } + + var cmd = ["river", "create", ui.name.value] + ui.list.querySelectorAll("pre").forEach(function(item) { + cmd.push(item.innerText) + }) + if (cmd.length == 3) { + alert("请添加组员") + return + } + + form.Run(cmd, function(msg) { + page.river.Show() + pane.Show() + }) + }]}, {name: "list", view: ["list"]}, + ]}]) + pane.Show = function() { - pane.ShowDialog() && (table.innerHTML = "", form.Run(["ocean"], function(msg) { - kit.AppendTable(table, ctx.Table(msg), ["key", "user.route"]) + pane.ShowDialog() && (table.innerHTML = "", ui.list.innerHTML = "", ui.name.value = "good", form.Run(["ocean"], function(msg) { + kit.AppendTable(table, ctx.Table(msg), ["key", "user.route"], function(value, key, row, i, tr, event) { + tr.style.display = "none" + var uis = kit.AppendChild(ui.list, [{text: [row.key], click: function(event) { + tr.style.display = "", uis.last.parentNode.removeChild(uis.last) + }}]) + }) })) } - return {"button": ["关闭"], "action": function(event) { - pane.Show() - }} + pane.Action = { + "取消": function(event) { + pane.Show() + }, + "全选": function(event) { + ui.list.innerHTML = "" + table.querySelectorAll("tr").forEach(function(item) { + item.firstChild.click() + }) + }, + "清空": function(event) { + ui.list.innerHTML = "" + table.querySelectorAll("tr").forEach(function(item) { + item.style.display = "" + }) + + }, + } + return {"button": ["取消", "全选", "清空"], "action": pane.Action} }, initRiver: function(page, pane, form, output) { pane.Show = function() { @@ -36,15 +113,11 @@ var page = Page({ } pane.Show() pane.Action = { - "添加": function(event) { - var name = prompt("name") - name && form.Run(["river", "create", name], pane.Show) - }, - "查找": function(event) { + "创建": function(event) { page.ocean.Show() }, } - return {"button": ["添加", "查找"], "action": pane.Action} + return {"button": ["创建"], "action": pane.Action} }, initTarget: function(page, pane, form, output) { var river = "" @@ -105,8 +178,17 @@ var page = Page({ }, } pane.Show = function() { - output.Update(["river", "tool", river, water], "text", ["cmd"], "cmd", false, function(line, index) { - form.Run(["river", "tool", river, water, index], function(msg) { + output.Update(["storm", river, water], "text", ["node", "name"], "index", false, function(line, index) { + if (event.shiftKey) { + page.target.Send("field", JSON.stringify({ + componet_group: "index", + componet_name: "river", + cmds: ["storm", river, water, index], + input: [{type: "input", data: {name: "hi", value: line.cmd}}] + })) + return + } + form.Run(["storm", river, water, index], function(msg) { msg.append && msg.append[0]? page.target.Send("table", JSON.stringify(ctx.Table(msg))): page.target.Send("text", msg.result.join("")) @@ -118,11 +200,8 @@ var page = Page({ var name = prompt("name") name && form.Run(["river", "tool", river, water, "add", name], pane.Show) }, - "查找": function(event) { - page.ocean.Show() - }, } - return {"button": ["添加", "查找"], "action": pane.Action} + return {"button": ["添加"], "action": pane.Action} }, initStorm: function(page, pane, form, output) { var river = "" @@ -132,25 +211,73 @@ var page = Page({ }, } pane.Show = function() { - output.Update(["river", "tool", river], "text", ["key", "count"], "key", true) + output.Update(["storm", river], "text", ["key", "count"], "key", true) } pane.Action = { - "添加": function(event) { - var name = prompt("name") - name && form.Run(["river", "tool", river, name, "pwd"], pane.Show) - }, - "查找": function(event) { + "创建": function(event) { page.steam.Show() }, } - return {"button": ["添加", "查找"], "action": pane.Action} + return {"button": ["创建"], "action": pane.Action} }, initSteam: function(page, pane, form, output) { + var river = "" + pane.Listen = { + river: function(value, old) { + river = value + }, + } + + var table = kit.AppendChild(output, "table") + var device = kit.AppendChild(pane, [{"view": ["device", "table"]}]).last + var ui = kit.AppendChild(pane, [{view: ["create steam"], list: [ + {input: ["name", function(event) { + if (event.key == "Enter") { + ui.name.nextSibling.click() + } + }]}, {button: ["create", function(event) { + if (!ui.name.value) { + ui.name.focus() + return + } + + var cmd = ["storm", "create", river, ui.name.value] + + ui.list.querySelectorAll("tr").forEach(function(item) { + cmd.push(item.dataset.pod) + cmd.push(item.dataset.group) + cmd.push(item.dataset.index) + cmd.push(item.dataset.name) + }) + + if (cmd.length == 4) { + alert("请添加命令") + return + } + + form.Run(cmd, function(msg) { + page.storm.Show() + pane.Show() + }) + }]}, {name: "list", view: ["list", "table"]}, + ]}]) + pane.Show = function() { - pane.ShowDialog() && (table.innerHTML = "", form.Run(["ocean"], function(msg) { - kit.AppendTable(table, ctx.Table(msg), ["key", "user.route"]) + pane.ShowDialog() && (table.innerHTML = "", ui.name.value = "nice", form.Run(["river", "user", river], function(msg) { + kit.AppendTable(table, ctx.Table(msg), ["key", "user.route"], function(value, key, pod, i, tr, event) { + form.Run(["steam", "tool", pod.key], function(msg) { + device.innerHTML = "", kit.AppendTable(device, ctx.Table(msg), ["key", "index", "name", "help"], function(value, key, com, i, tr, event) { + var last = kit.AppendChild(ui.list, [{type: "tr", list: [ + {text: [com.key, "td"]}, {text: [com.index, "td"]}, {text: [com.name, "td"]}, {text: [com.help, "td"]}, + ], dataset: {pod: pod["user.route"], group: com.key, index: com.index, name: com.name}, click: function(event) { + last.parentNode.removeChild(last) + }}]).last + }) + }) + }) })) } + return [{"text": ["steam"]}] }, init: function(page) { @@ -166,11 +293,14 @@ var page = Page({ type = line.type || type var ui = kit.AppendChild(output, page.View(type, line, key, function(event) { output.Select(index), pane.which.set(line[which]) - typeof cb == "function" && cb(line, index) + typeof cb == "function" && cb(line, index, event) })) if (type == "table") { kit.OrderTable(ui.last) } + if (type == "field") { + kit.OrderForm(page, ui.last, ui.form, ui.table, ui.code) + } list.push(ui.last) pane.scrollBy(0, pane.scrollHeight) return ui diff --git a/usr/librarys/context.js b/usr/librarys/context.js index 1cdfb2bb..42ae1da8 100644 --- a/usr/librarys/context.js +++ b/usr/librarys/context.js @@ -2,7 +2,7 @@ ctx = context = { Run: function(page, dataset, cmd, cb) { var option = {"cmds": cmd} for (var k in dataset) { - option[k] = dataset[k] + option[k] = dataset[k].split(",") } this.GET("", option, function(msg) { msg = msg && msg[0] diff --git a/usr/librarys/example.js b/usr/librarys/example.js index b587f3a1..40e228f8 100644 --- a/usr/librarys/example.js +++ b/usr/librarys/example.js @@ -33,16 +33,20 @@ function Page(page) { }, View: function(type, line, key, cb) { switch (type) { + case "icon": + return [{view: ["item", "div"], list: [{type: "img", data: {src: line[key[0]]}}, {}]}] + case "text": switch (key.length) { case 0: - return [{view: ["", "div", "null"], click: cb}] + return [{view: ["item", "div", "null"], click: cb}] case 1: - return [{view: ["", "div", line[key[0]]], click: cb}] + return [{view: ["item", "div", line[key[0]]], click: cb}] default: - return [{view: ["", "div", line[key[0]]+"("+line[key[1]]+")"], click: cb}] + return [{view: ["item", "div", line[key[0]]+"("+line[key[1]]+")"], click: cb}] } break + case "table": var data = JSON.parse(line.text) var list = [] @@ -60,6 +64,25 @@ function Page(page) { } var result = [{view: [""], list: [{view: ["", "table"], list: list}]}] return result + + case "field": + var data = JSON.parse(line.text) + var input = [{type: "input", style: {"display": "none"}}] + for (var i = 0; i < data.input.length; i++) { + input.push(data.input[i]) + } + + var result = [{view: ["", "fieldset"], list: [ + {name: "form", view: ["", "form"], dataset: { + componet_group: data.componet_group, + componet_name: data.componet_name, + cmds: data.cmds, + }, list: input}, + {name: "table", view: ["", "table"]}, + {view: ["", "code"], list: [{name: "code", view: ["", "pre"]}]}, + ]}] + return result + } }, reload: function() { @@ -74,6 +97,9 @@ function Page(page) { break } }, + showToast: function(text) { + + }, initHeader: function(page, field, option, output) { return [{"text": ["shycontext", "div", "title"]}] @@ -130,8 +156,9 @@ function Page(page) { } var conf = cb(page[pane.dataset.init], pane, form) + }) - // pane listen + document.querySelectorAll("body>fieldset").forEach(function(pane) { for (var k in pane.Listen) { page[k].which.change(pane.Listen[k]) } @@ -145,6 +172,9 @@ function Page(page) { document.body.onkeydown = function(event) { page.onscroll && page.onscroll(event, document.body, "scroll") } + document.body.onkeyup = function(event) { + page.oncontrol && page.oncontrol(event, document.body, "control") + } } return page } diff --git a/usr/librarys/toolkit.js b/usr/librarys/toolkit.js index 866aeb42..2efa929a 100644 --- a/usr/librarys/toolkit.js +++ b/usr/librarys/toolkit.js @@ -149,13 +149,18 @@ kit = toolkit = { return elm } - // include require styles // 加载文件 // name - // click + // value + // inner // style - // button + // dataset + // click + // + // button input // tree, fork, leaf // 树状结构 - // code, text, view // 普通视图 + // view, text, code // 普通视图 + // include require styles // 加载文件 + // // type, data, list // 基本结构 var kit = this @@ -165,6 +170,12 @@ kit = toolkit = { child.data = child.data || {} child.type = child.type || "div" + if (child.value) { + child.data["value"] = child.value + } + if (child.inner) { + child.data["innerHTML"] = child.inner + } if (typeof(child.style) == "object") { var str = [] for (var k in child.style) { @@ -175,43 +186,24 @@ kit = toolkit = { } child.data["style"] = str.join("") } + if (child.dataset) { + child.data["dataset"] = child.dataset + } if (child.click) { child.data["onclick"] = child.click } - if (child.include) { - child.data["src"] = child.include[0] - child.data["type"] = "text/javascript" - child.include.length > 1 && (child.data["onload"] = child.include[1]) - child.type = "script" - - } else if (child.require) { - child.data["href"] = child.require[0] - child.data["rel"] = child.require.length > 1? child.require[1]: "stylesheet" - child.data["type"] = child.require.length > 2? child.require[2]: "text/css" - child.type = "link" - - } else if (child.styles) { - var str = [] - for (var key in child.styles) { - str.push(key) - str.push(" {") - for (var k in child.styles[key]) { - str.push(k) - str.push(":") - str.push(child.styles[key][k] + (typeof child.styles[key][k] == "number"? "px": "")) - str.push(";") - } - str.push("}\n") - } - child.data["innerHTML"] = str.join("") - child.data["type"] = "text/css" - child.type = "style" - - } else if (child.button) { + if (child.button) { child.type = "button" - child.data["innerText"] = child.button[0] child.data["onclick"] = child.button[1] + child.data["innerText"] = child.button[0] + child.name = child.name || child.button[0] + + } else if (child.input) { + child.type = "input" + child.data["onkeyup"] = child.input[1] + child.data["name"] = child.input[0] + child.name = child.name || child.input[0] } else if (child.tree) { child.type = "ul" @@ -248,6 +240,35 @@ kit = toolkit = { child.type = "code" child.list = [{"type": "pre" ,"data": {"innerText": child.code[0]}, "name": child.code[1]}] child.code.length > 2 && (child.data["className"] = child.code[2]) + } else if (child.include) { + child.data["src"] = child.include[0] + child.data["type"] = "text/javascript" + child.include.length > 1 && (child.data["onload"] = child.include[1]) + child.type = "script" + + } else if (child.require) { + child.data["href"] = child.require[0] + child.data["rel"] = child.require.length > 1? child.require[1]: "stylesheet" + child.data["type"] = child.require.length > 2? child.require[2]: "text/css" + child.type = "link" + + } else if (child.styles) { + var str = [] + for (var key in child.styles) { + str.push(key) + str.push(" {") + for (var k in child.styles[key]) { + str.push(k) + str.push(":") + str.push(child.styles[key][k] + (typeof child.styles[key][k] == "number"? "px": "")) + str.push(";") + } + str.push("}\n") + } + child.data["innerHTML"] = str.join("") + child.data["type"] = "text/css" + child.type = "style" + } var node = kit.CreateNode(child.type, child.data) @@ -280,7 +301,7 @@ kit = toolkit = { var td = kit.AppendChild(tr, "td", row[key]) if (typeof cb == "function") { td.onclick = function(event) { - cb(row[key], key, row, i, event) + cb(row[key], key, row, i, tr, event) } } }) @@ -389,7 +410,7 @@ kit = toolkit = { option.querySelectorAll("select").forEach(function(select, index, array) { select.onchange = select.onchange || function(event) { if (index == array.length-1) { - page.Runs(page, option) + ctx.Runs(page, option) return } if (array[index+1].type == "button") { @@ -415,7 +436,7 @@ kit = toolkit = { return } - page.Runs(page, option) + ctx.Runs(page, option) return } if (array[index+1].type == "button") { @@ -430,7 +451,7 @@ kit = toolkit = { return } if (index == array.length-1) { - page.Runs(page, option) + ctx.Runs(page, option) return } if (array[index+1].type == "button") {