diff --git a/base/nfs/nfs.go b/base/nfs/nfs.go index 02e31f68..a53d4a34 100644 --- a/base/nfs/nfs.go +++ b/base/nfs/nfs.go @@ -156,7 +156,7 @@ var Index = &ice.Context{Name: "nfs", Help: "存储模块", "cat": {Name: "cat path", Help: "保存", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if f, e := os.OpenFile(arg[0], os.O_RDONLY, 0777); m.Assert(e) { defer f.Close() - buf := make([]byte, 1024) + buf := make([]byte, 4096000) if n, e := f.Read(buf); m.Assert(e) { m.Log(ice.LOG_IMPORT, "%d: %s", n, arg[0]) m.Echo(string(buf[:n])) diff --git a/base/ssh/ssh.go b/base/ssh/ssh.go index 51ff2f98..8d51eae0 100644 --- a/base/ssh/ssh.go +++ b/base/ssh/ssh.go @@ -5,6 +5,7 @@ import ( "github.com/shylinux/toolkits" "bufio" + "bytes" "fmt" "io" "os" @@ -13,60 +14,55 @@ import ( type Frame struct { in io.ReadCloser - out io.WriteCloser + out io.Writer target *ice.Context count int } -func (f *Frame) prompt(m *ice.Message) *ice.Message { - prompt := "[15:04:05]%s> " - fmt.Fprintf(f.out, kit.Format("%d", f.count)) - fmt.Fprintf(f.out, m.Time(prompt, f.target.Name)) - return m -} -func (f *Frame) printf(m *ice.Message, res string) *ice.Message { - fmt.Fprint(f.out, res) - if !strings.HasSuffix(res, "\n") { - fmt.Fprint(f.out, "\n") - } - return m -} - -func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server { - return &Frame{} -} -func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server { - return f -} -func (f *Frame) Start(m *ice.Message, arg ...string) bool { - switch kit.Select("stdio", arg, 0) { - case "stdio": - f.in = os.Stdin - f.out = os.Stdout - m.Cap(ice.CTX_STREAM, "stdio") - default: - if n, e := os.Open(arg[0]); m.Warn(e != nil, "%s", e) { - return true - } else { - f.in = n - f.out = os.Stderr - m.Cap(ice.CTX_STREAM, arg[0]) +func (f *Frame) prompt(m *ice.Message) *Frame { + if f.out == os.Stdout { + for _, v := range kit.Simple(m.Optionv(ice.MSG_PROMPT)) { + switch v { + case "count": + fmt.Fprintf(f.out, kit.Format("%d", f.count)) + case "time": + fmt.Fprintf(f.out, m.Time("15:04:05")) + case "target": + fmt.Fprintf(f.out, f.target.Name) + default: + fmt.Fprintf(f.out, v) + } } } + return f +} +func (f *Frame) printf(m *ice.Message, res string, arg ...interface{}) *Frame { + if len(arg) > 0 { + fmt.Fprintf(f.out, res, arg) + } else { + fmt.Fprint(f.out, res) + } + // if !strings.HasSuffix(res, "\n") { + // fmt.Fprint(f.out, "\n") + // } + return f +} +func (f *Frame) parse(m *ice.Message, line string) *Frame { + for _, one := range kit.Split(line, ";") { + ls := kit.Split(one) + m.Log(ice.LOG_IMPORT, "stdin: %d %v", len(ls), ls) - f.count = 0 - f.target = m.Target() - bio := bufio.NewScanner(f.in) - for f.prompt(m); bio.Scan(); f.prompt(m) { - ls := kit.Split(bio.Text()) - m.Log(ice.LOG_IMPORT, "stdin: %v", ls) - - if len(ls) > 0 && strings.HasPrefix(ls[0], "~") { + if len(ls) == 1 && ls[0] == "~" { + ls = []string{"context"} + } else if len(ls) > 0 && strings.HasPrefix(ls[0], "~") { // 切换模块 target := ls[0][1:] if ls = ls[1:]; len(target) == 0 && len(ls) > 0 { target, ls = ls[0], ls[1:] } + if target == "~" { + target = "" + } m.Spawn(f.target).Search(target+".", func(p *ice.Context, s *ice.Context, key string) { m.Info("choice: %s", s.Name) f.target = s @@ -75,23 +71,95 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool { if len(ls) == 0 { continue } - msg := m.Spawns(f.target) + + // 命令替换 + if alias, ok := m.Optionv(ice.MSG_ALIAS).(map[string]interface{}); ok { + if a := kit.Simple(alias[ls[0]]); len(a) > 0 { + ls = append(append([]string{}, a...), ls[1:]...) + } + } // 执行命令 - if msg.Cmdy(ls); !msg.Hand { + msg := m.Spawns(f.target) + if msg.Cmdy(ls[0], ls[1:]); !msg.Hand { + // 系统命令 msg = msg.Set("result").Cmdy(ice.CLI_SYSTEM, ls) } - // 生成结果 + // 转换结果 res := msg.Result() if res == "" { res = msg.Table().Result() } // 输出结果 - msg.Cost("stdin:%v", ls) - f.printf(msg, res) + if f.printf(msg, res); !strings.HasSuffix(res, "\n") { + f.printf(msg, "\n") + } + } + return f +} + +func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server { + return &Frame{} +} +func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server { + m.Target().Configs["history"] = &ice.Config{Name: "history", Help: "历史", Value: kit.Data()} + return f +} +func (f *Frame) Start(m *ice.Message, arg ...string) bool { + m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS1")) + f.count, f.target = kit.Int(m.Conf("history", "meta.count"))+1, m.Source() + + switch kit.Select("stdio", arg, 0) { + case "stdio": + // 解析终端 + f.in, f.out = os.Stdin, os.Stdout + m.Cap(ice.CTX_STREAM, "stdio") + f.target = m.Target() + default: + // 解析脚本 + if s, e := os.Open(arg[0]); m.Warn(e != nil, "%s", e) { + return true + } else { + defer s.Close() + if f.in, f.out = s, os.Stdout; m.Optionv(ice.MSG_STDOUT) != nil { + f.out = m.Optionv(ice.MSG_STDOUT).(io.Writer) + } + m.Cap(ice.CTX_STREAM, arg[0]) + } + } + + line := "" + bio := bufio.NewScanner(f.in) + for f.prompt(m); bio.Scan(); f.prompt(m) { + if len(bio.Text()) == 0 { + // 空行 + continue + } + if strings.HasSuffix(bio.Text(), "\\") { + // 续行 + m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS2")) + line += bio.Text()[:len(bio.Text())-1] + continue + } + if line += bio.Text(); strings.Count(line, "`")%2 == 1 { + // 多行 + m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS2")) + line += "\n" + continue + } + m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS1")) + m.Log(ice.LOG_IMPORT, "stdin: %v", line) + m.Grow("history", nil, kit.Dict("line", line)) + + if f.out == os.Stdout { + f.printf(m, "\033[0m") + } + f.parse(m, line) + m.Cost("stdin: %v", line) f.count++ + line = "" } return true } @@ -100,27 +168,68 @@ func (f *Frame) Close(m *ice.Message, arg ...string) bool { } var Index = &ice.Context{Name: "ssh", Help: "终端模块", - Caches: map[string]*ice.Cache{}, - Configs: map[string]*ice.Config{}, + Caches: map[string]*ice.Cache{}, + Configs: map[string]*ice.Config{ + "prompt": {Name: "prompt", Help: "prompt", Value: kit.Data( + "PS1", []interface{}{"\033[33;44m", "count", "[", "time", "]", "\033[5m", "target", "\033[0m", "\033[44m", ">", "\033[0m ", "\033[?25h", "\033[32m"}, + "PS2", []interface{}{"count", " ", "target", "> "}, + )}, + }, Commands: map[string]*ice.Command{ ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Cmd(ice.CTX_CONFIG, "load", kit.Keys(m.Cap(ice.CTX_FOLLOW), "json")) }}, ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Cmd(ice.CTX_CONFIG, "save", kit.Keys(m.Cap(ice.CTX_FOLLOW), "json"), kit.Keys(m.Cap(ice.CTX_FOLLOW), "history")) + if f, ok := m.Target().Server().(*Frame); ok { // 关闭终端 f.in.Close() m.Done() } }}, + "history": {Name: "history", Help: "历史", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) == 0 { + m.Grows("history", nil, "", "", func(index int, value map[string]interface{}) { + m.Push("", value, []string{"id", "time", "line"}) + }) + return + } + + f := m.Target().Server().(*Frame) + m.Grows("history", nil, "id", arg[0], func(index int, value map[string]interface{}) { + f.parse(m, kit.Format(value["line"])) + }) + }}, "scan": {Name: "scan", Help: "解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Starts(arg[0], arg[1], arg[2:]...) + buf := bytes.NewBuffer(make([]byte, 4096)) + m.Optionv(ice.MSG_STDOUT, buf) + + m.Starts(strings.Replace(arg[0], ".", "_", -1), arg[1], arg[2:]...) + m.Echo(buf.String()) + }}, + "print": {Name: "print", Help: "解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + f := m.Target().Server().(*Frame) + f.printf(m, arg[0]) + f.printf(m, arg[0]) + f.printf(m, arg[0]) + f.printf(m, arg[0]) + }}, + "prompt": {Name: "print", Help: "解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS1")) + f := m.Target().Server().(*Frame) + f.prompt(m) }}, "show": {Name: "show", Help: "解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - msg := m.Spawn() - msg.Option("title", "疫情分布") - msg.Info("what %v", msg.Format("meta")) - m.Copy(msg) - msg.Info("what %v", m.Format("meta")) + f, e := os.Open("usr/local/what/hi.shy") + m.Assert(e) + + bio := bufio.NewScanner(f) + for bio.Scan() { + ls := kit.Split(bio.Text()) + m.Echo("%d: %v\n", len(ls), ls) + m.Info("%v", ls) + } }}, }, } diff --git a/base/web/web.go b/base/web/web.go index f205ea44..2cc48a65 100644 --- a/base/web/web.go +++ b/base/web/web.go @@ -161,8 +161,10 @@ func (web *Frame) HandleCGI(m *ice.Message, alias map[string]interface{}, which tmpl = tmpl.Funcs(cgi) // tmpl = template.Must(tmpl.ParseGlob(path.Join(m.Conf(ice.WEB_SERVE, ice.Meta("template", "path")), "/*.tmpl"))) // tmpl = template.Must(tmpl.ParseGlob(path.Join(m.Conf(ice.WEB_SERVE, ice.Meta("template", "path")), m.Target().Name, "/*.tmpl"))) - tmpl = template.Must(tmpl.ParseFiles(which)) - m.Confm(ice.WEB_SERVE, ice.Meta("template", "list"), func(index int, value string) { tmpl = template.Must(tmpl.Parse(value)) }) + tmpl, e := tmpl.ParseFiles(which) + if e != nil { + } + // m.Confm(ice.WEB_SERVE, ice.Meta("template", "list"), func(index int, value string) { tmpl = template.Must(tmpl.Parse(value)) }) return tmpl } func (web *Frame) HandleCmd(m *ice.Message, key string, cmd *ice.Command) { @@ -761,8 +763,11 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", id := kit.Format(c.ID()) m.Optionv(ice.MSG_SOURCE, []string{id}) m.Optionv(ice.MSG_TARGET, target[1:]) - m.Option("hot", m.Option("hot")) - m.Option("top", m.Option("top")) + for _, k := range []string{"top", "hot"} { + if m.Options(k) { + m.Option(k, m.Option(k)) + } + } m.Set(ice.MSG_DETAIL, arg[1:]...) m.Info("send %s %s", id, m.Format("meta")) @@ -923,6 +928,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", } if len(arg) == 1 { + m.Option("cache.limit", 30) // 收藏列表 m.Grows(ice.WEB_FAVOR, kit.Keys(kit.MDB_HASH, favor), "", "", func(index int, value map[string]interface{}) { m.Push(kit.Format(index), value, []string{kit.MDB_TIME, kit.MDB_ID, kit.MDB_TYPE, kit.MDB_NAME, kit.MDB_TEXT}) @@ -950,7 +956,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", kit.MDB_TYPE, arg[1], kit.MDB_NAME, arg[2], kit.MDB_TEXT, kit.Select("", arg, 3), "extra", extra, )) - m.Log(ice.LOG_INSERT, "favor: %s index: %d name: %s", favor, index, arg[2]) + m.Log(ice.LOG_INSERT, "favor: %s index: %d name: %s text: %s", favor, index, arg[2], kit.Select("", arg, 3)) m.Echo("%d", index) }}, ice.WEB_CACHE: {Name: "cache", Help: "缓存池", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { diff --git a/conf.go b/conf.go index 83736714..b23d8f95 100644 --- a/conf.go +++ b/conf.go @@ -25,9 +25,14 @@ const ( // MSG MSG_APPEND = "append" MSG_RESULT = "result" + MSG_ACTION = "_action" + MSG_SOURCE = "_source" MSG_TARGET = "_target" MSG_HANDLE = "_handle" + MSG_STDOUT = "_stdout" + MSG_PROMPT = "_prompt" + MSG_ALIAS = "_alias" MSG_SESSID = "sessid" MSG_USERIP = "user.ip" diff --git a/core/chat/chat.go b/core/chat/chat.go index eef9132e..306af112 100644 --- a/core/chat/chat.go +++ b/core/chat/chat.go @@ -16,27 +16,37 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心", ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Cap(ice.CTX_STATUS, "start") m.Cap(ice.CTX_STREAM, "volcanos") - m.Cmd(ice.CTX_CONFIG, "load", "chat.json") m.Watch(ice.SYSTEM_INIT, "web.chat.init") m.Watch(ice.USER_CREATE, "web.chat./tutor", "init") + m.Cmd(ice.CTX_CONFIG, "load", kit.Keys(m.Cap(ice.CTX_FOLLOW), "json")) }}, ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmd(ice.CTX_CONFIG, "save", "chat.json", ice.CHAT_RIVER) + m.Cmd(ice.CTX_CONFIG, "save", kit.Keys(m.Cap(ice.CTX_FOLLOW), "json"), kit.Keys(m.Cap(ice.CTX_FOLLOW), "river")) }}, "init": {Name: "init", Help: "初始化", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(m.Confm(ice.CHAT_RIVER, "hash")) == 0 { // 系统群组 if m.Richs(ice.WEB_FAVOR, nil, "river.root", nil) == nil { - m.Cmd(ice.WEB_FAVOR, "river.root", "storm", "miss") - m.Cmd(ice.WEB_FAVOR, "river.root", "field", "spide") - m.Cmd(ice.WEB_FAVOR, "river.root", "field", "space") - m.Cmd(ice.WEB_FAVOR, "river.root", "field", "dream") - m.Cmd(ice.WEB_FAVOR, "river.root", "field", "favor") - m.Cmd(ice.WEB_FAVOR, "river.root", "field", "story") - m.Cmd(ice.WEB_FAVOR, "river.root", "field", "share") + m.Cmd(ice.WEB_FAVOR, "river.root", "storm", "mall", "mall") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "asset", "web.mall") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "bonus", "web.mall") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "trans", "web.mall") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "spend", "web.mall") - m.Cmd(ice.WEB_FAVOR, "river.root", "storm", "misc") + m.Cmd(ice.WEB_FAVOR, "river.root", "storm", "team", "team") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "miss", "web.team") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "stat", "web.team") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "plan", "web.team") + + m.Cmd(ice.WEB_FAVOR, "river.root", "storm", "wiki", "wiki") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "mind", "web.wiki") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "word", "web.wiki") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "data", "web.wiki") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "feel", "web.wiki") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "walk", "web.wiki") + + m.Cmd(ice.WEB_FAVOR, "river.root", "storm", "code", "code") m.Cmd(ice.WEB_FAVOR, "river.root", "field", "buffer", "web.code.tmux") m.Cmd(ice.WEB_FAVOR, "river.root", "field", "session", "web.code.tmux") m.Cmd(ice.WEB_FAVOR, "river.root", "field", "image", "web.code.docker") @@ -47,12 +57,13 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心", m.Cmd(ice.WEB_FAVOR, "river.root", "field", "branch", "web.code.git") m.Cmd(ice.WEB_FAVOR, "river.root", "field", "status", "web.code.git") - m.Cmd(ice.WEB_FAVOR, "river.root", "storm", "note") - m.Cmd(ice.WEB_FAVOR, "river.root", "field", "total", "web.code.git") - m.Cmd(ice.WEB_FAVOR, "river.root", "field", "date", "web.team") - m.Cmd(ice.WEB_FAVOR, "river.root", "field", "miss", "web.team") - m.Cmd(ice.WEB_FAVOR, "river.root", "field", "progress", "web.team") - m.Cmd(ice.WEB_FAVOR, "river.root", "field", "note", "web.wiki") + m.Cmd(ice.WEB_FAVOR, "river.root", "storm", "root") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "spide") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "space") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "dream") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "favor") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "story") + m.Cmd(ice.WEB_FAVOR, "river.root", "field", "share") } // 用户权限 @@ -279,7 +290,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心", m.Push("index", meta["cmd"]) msg := m.Cmd(m.Space(meta["pod"]), ice.CTX_COMMAND, meta["ctx"], meta["cmd"]) - m.Push("name", meta["cmd"]) + m.Push("name", kit.Select(kit.Format(meta["key"]), meta["cmd"])) m.Push("help", msg.Append("help")) m.Push("inputs", msg.Append("list")) m.Push("feature", msg.Append("meta")) @@ -288,6 +299,18 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心", return } + switch arg[2] { + case "save": + m.Conf(ice.CHAT_RIVER, kit.Keys(prefix), "") + for i := 3; i < len(arg)-3; i += 4 { + id := m.Grow(ice.CHAT_RIVER, kit.Keys(prefix), kit.Data( + "pod", arg[i], "ctx", arg[i+1], "cmd", arg[i+2], "key", arg[i+3], + )) + m.Log("insert", "storm: %s %d: %v", arg[1], id, arg[i:i+4]) + } + return + } + // 查询命令 cmds := []string{} m.Grows(ice.CHAT_RIVER, prefix, kit.MDB_ID, kit.Format(kit.Int(arg[2])+1), func(index int, value map[string]interface{}) { diff --git a/core/mall/mall.go b/core/mall/mall.go index ca3d5897..cf1e61e2 100644 --- a/core/mall/mall.go +++ b/core/mall/mall.go @@ -6,7 +6,9 @@ import ( "github.com/shylinux/icebergs/base/web" "github.com/shylinux/toolkits" + "encoding/csv" "fmt" + "strconv" "strings" "time" ) @@ -15,16 +17,388 @@ var Index = &ice.Context{Name: "mall", Help: "贸易中心", Caches: map[string]*ice.Cache{}, Configs: map[string]*ice.Config{ "railway": {Name: "railway", Help: "12306", Value: kit.Data()}, + "asset": {Name: "asset", Help: "资产", Value: kit.Data( + kit.MDB_SHORT, "account", "limit", "5000", + "site", kit.Dict( + "个税", "https://its.beijing.chinatax.gov.cn:8443/zmsqjl.html", + "社保", "http://fuwu.rsj.beijing.gov.cn/csibiz/indinfo/index.jsp", + "公积金", "https://grwsyw.gjj.beijing.gov.cn/ish/flow/menu/PPLGRZH0102?_r=0.6644871172745264", + ), + )}, }, Commands: map[string]*ice.Command{ ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmd(ice.CTX_CONFIG, "load", "mall.json") - if m.Richs(ice.WEB_SPIDE, nil, "12306", nil) == nil { - m.Cmd(ice.WEB_SPIDE, "add", "12306", "https://kyfw.12306.cn") - } + m.Cmd(ice.CTX_CONFIG, "load", kit.Keys(m.Cap(ice.CTX_FOLLOW), "json")) + + // m.Cmd(ice.CTX_CONFIG, "load", "mall.json") + // if m.Richs(ice.WEB_SPIDE, nil, "12306", nil) == nil { + // m.Cmd(ice.WEB_SPIDE, "add", "12306", "https://kyfw.12306.cn") + // } }}, ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmd(ice.CTX_CONFIG, "save", "mall.json", "web.mall.railway") + m.Cmd(ice.CTX_CONFIG, "save", kit.Keys(m.Cap(ice.CTX_FOLLOW), "json"), kit.Keys(m.Cap(ice.CTX_FOLLOW), "asset")) + + // m.Cmd(ice.CTX_CONFIG, "save", "mall.json", "web.mall.railway") + }}, + + "spend": {Name: "spend", Help: "支出", List: kit.List( + kit.MDB_INPUT, "text", "name", "account", + kit.MDB_INPUT, "text", "name", "name", + kit.MDB_INPUT, "text", "name", "text", + kit.MDB_INPUT, "text", "name", "value", + kit.MDB_INPUT, "button", "name", "记录", + ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) < 2 { + m.Cmdy("asset", arg) + return + } + amount := kit.Int(arg[3]) + m.Cmdy("asset", arg[0], "", "支出", arg[1], arg[2], -amount, arg[4:]) + m.Cmdy("asset", "流水", "", "支出", arg[1], arg[2], -amount, arg[4:]) + }}, + "trans": {Name: "trans", Help: "转账", List: kit.List( + kit.MDB_INPUT, "text", "name", "account", + kit.MDB_INPUT, "text", "name", "to", + kit.MDB_INPUT, "text", "name", "name", + kit.MDB_INPUT, "text", "name", "text", + kit.MDB_INPUT, "text", "name", "value", + kit.MDB_INPUT, "button", "name", "记录", + ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) < 2 { + m.Cmdy("asset", arg) + return + } + amount := kit.Int(arg[4]) + m.Cmdy("asset", arg[0], "", "转出", arg[2], arg[3], -amount, arg[5:]) + m.Cmd("asset", arg[1], "", "转入", arg[2], arg[3], amount, arg[5:]) + m.Cmd("asset", "流水", "", "转出", arg[2], arg[3], -amount, arg[5:]) + m.Cmd("asset", "流水", "", "转入", arg[2], arg[3], amount, arg[5:]) + }}, + "bonus": {Name: "bonus", Help: "收入", List: kit.List( + kit.MDB_INPUT, "text", "name", "account", + kit.MDB_INPUT, "text", "name", "name", + kit.MDB_INPUT, "text", "name", "text", + kit.MDB_INPUT, "text", "name", "value", + kit.MDB_INPUT, "button", "name", "记录", + ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) < 2 { + m.Cmdy("asset", arg) + return + } + m.Cmdy("asset", arg[0], "", "收入", arg[1:]) + m.Cmdy("asset", "流水", "", "收入", arg[1:]) + }}, + "month": {Name: "month", Help: "工资", List: kit.List( + kit.MDB_INPUT, "text", "name", "month", + kit.MDB_INPUT, "text", "name", "value", + kit.MDB_INPUT, "button", "name", "计算", + kit.MDB_INPUT, "button", "name", "记录", + ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + data := map[string]int{"个税方案": 6, "基本工资": 0, "个税": 0, + "公积金比例": 1200, "养老保险比例": 800, "医疗保险比例": 200, "失业保险比例": 20, "工伤保险比例": 2, "生育保险比例": 0, + "公积金金额": 0, "养老保险金额": 0, "医疗保险金额": 0, "失业保险金额": 0, "工伤保险金额": 0, "生育保险金额": 0, + + "企业公积金比例": 1200, "企业养老保险比例": 2000, "企业医疗保险比例": 1000, "企业失业保险比例": 100, "企业工伤保险比例": 30, "企业生育保险比例": 80, + "企业公积金金额": 0, "企业养老保险金额": 0, "企业医疗保险金额": 0, "企业失业保险金额": 0, "企业工伤保险金额": 0, "企业生育保险金额": 0, + } + + for i := 2; i < len(arg)-1; i += 2 { + if _, ok := data[arg[i]]; ok { + data[arg[i]] = kit.Int(arg[i+1]) + arg[i] = "" + } + } + + // data["养老保险比例"] = 725 + // data["失业保险比例"] = 20 + // + salary := kit.Int(arg[1]) + base := data["基本工资"] + if base == 0 { + base = salary + } + + // 五险一金 + amount := 0 + for _, k := range []string{"公积金", "养老保险", "医疗保险", "失业保险", "工伤保险"} { + m.Push("名目", k) + value := -base * kit.Int(data[k+"比例"]) / 10000 + if m.Push("比例", data[k+"比例"]); data[k+"金额"] == 0 { + data[k+"金额"] = value + } else { + value = data[k+"金额"] + } + amount += value + m.Push("金额", data[k+"金额"]) + } + + // 企业五险一金 + company := 0 + for _, k := range []string{"企业公积金", "企业养老保险", "企业医疗保险", "企业失业保险", "企业工伤保险", "企业生育保险"} { + m.Push("名目", k) + value := -base * kit.Int(data[k+"比例"]) / 10000 + if m.Push("比例", data[k+"比例"]); data[k+"金额"] == 0 { + data[k+"金额"] = value + } + company += -value + m.Push("金额", data[k+"金额"]) + } + m.Push("名目", "企业承担") + m.Push("比例", "") + m.Push("金额", company) + + // 其它津贴 + for i := 2; i < len(arg)-1; i += 2 { + if arg[i] != "" && data[arg[i]] == 0 { + m.Push("名目", arg[i]) + m.Push("比例", "") + m.Push("金额", arg[i+1]) + amount += kit.Int(arg[i+1]) + } + } + salary += amount + + m.Push("名目", "税前收入") + m.Push("比例", "") + m.Push("金额", salary) + + tax, amount := 0, salary + if data["个税方案"] == 6 { + // 2011年个税法案 + month := []int{ + 8350000, 4500, + 5850000, 3500, + 3850000, 3000, + 1250000, 2500, + 800000, 2000, + 500000, 1000, + 350000, 300, + } + + for i := 0; i < len(month); i += 2 { + if amount > month[i] { + tax, amount = tax+(amount-month[i])*month[i+1]/10000, month[i] + } + } + if data["个税"] != 0 { + tax = data["个税"] + } + m.Push("名目", "个税") + m.Push("比例", "") + m.Push("金额", tax) + + m.Push("名目", "税后收入") + m.Push("比例", "") + m.Push("金额", salary-tax) + } else { + // 2019年个税法案 + // year := []int{ + // 96000000, 4500, + // 66000000, 3500, + // 42000000, 3000, + // 30000000, 2500, + // 14400000, 2000, + // 3600000, 1000, + // 0, 300, + // } + } + + switch m.Option(ice.MSG_ACTION) { + case "计算": + case "记录": + // 收入 + m.Cmd("bonus", "工资", "企业承担", arg[0], company) + m.Cmd("bonus", "工资", "基本工资", arg[0], arg[1]) + for i := 2; i < len(arg)-1; i += 2 { + if arg[i] != "" { + m.Cmd("bonus", "工资", arg[i], arg[0], arg[i+1]) + } + } + + // 转账 + m.Cmd("trans", "工资", "公积金", "企业公积金", arg[0], -data["企业公积金金额"]) + for _, k := range []string{"企业养老保险", "企业医疗保险", "企业失业保险", "企业工伤保险", "企业生育保险"} { + m.Cmd("trans", "工资", "社保", k, arg[0], -data[k+"金额"]) + } + m.Cmd("trans", "工资", "公积金", "个人公积金", arg[0], -data["公积金金额"]) + for _, k := range []string{"养老保险", "医疗保险", "失业保险"} { + m.Cmd("trans", "工资", "社保", k, arg[0], -data[k+"金额"]) + } + + // 个税 + m.Cmd("trans", "工资", "个税", "工资个税", arg[0], tax) + } + }}, + "asset": {Name: "asset account type name value", Help: []string{"资产", + "action save file [account [key value]]", + "action load file [account]", + }, List: kit.List( + kit.MDB_INPUT, "text", "name", "account", "action", "auto", + kit.MDB_INPUT, "text", "name", "id", "action", "auto", + kit.MDB_INPUT, "button", "name", "查看", + kit.MDB_INPUT, "button", "name", "返回", "cb", "Last", + ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Option("cache.limit", "10000") + if len(arg) == 0 { + // 账户列表 + m.Richs("asset", nil, "*", func(key string, value map[string]interface{}) { + m.Push(key, value["meta"], []string{"account", "count", "amount", "bonus", "spend"}) + }) + m.Sort("amount", "int_r") + return + } + + if len(arg) > 0 && arg[0] == "action" { + switch arg[1] { + case "modify": + m.Richs("asset", nil, m.Option("account"), func(key string, account map[string]interface{}) { + m.Grows("asset", kit.Keys("hash", key), "id", arg[5], func(index int, current map[string]interface{}) { + kit.Value(current, arg[2], arg[3]) + }) + }) + + case "save": + m.Option("cache.limit", "10000") + if f, p, e := kit.Create(arg[2]); m.Assert(e) { + defer f.Close() + + w := csv.NewWriter(f) + defer w.Flush() + + w.Write([]string{"时间", "收支类型", "账目分类", "备注", "金额", "账户"}) + m.Richs("asset", nil, kit.Select("*", arg, 3), func(key string, account map[string]interface{}) { + if kit.Format(kit.Value(account, "meta.account")) == "流水" { + return + } + m.Grows("asset", kit.Keys("hash", key), kit.Select("", arg, 4), kit.Select("", arg, 5), func(index int, current map[string]interface{}) { + w.Write([]string{ + kit.Format(current["time"]), + kit.Format(current["type"]), + kit.Format(current["name"]), + kit.Format(current["text"]), + kit.Format(current["value"]), + kit.Format(kit.Value(account, "meta.account")), + }) + }) + }) + m.Log(ice.LOG_EXPORT, "%s", p) + } + + case "load": + m.Option("cache.limit", "10000") + m.CSV(m.Cmdx("nfs.cat", arg[2])).Table(func(index int, data map[string]string, head []string) { + v, _ := strconv.ParseFloat(data["金额"], 64) + for _, account := range []string{kit.Select(data["账户"], arg, 3), "流水"} { + // amount := kit.Int(v * 100) + item := kit.Dict( + "type", data["收支类型"], "name", data["账目分类"], "text", data["备注"], "value", kit.Int(v), + "time", data["时间"], "extra", kit.UnMarshal(data["extra"]), + ) + + if m.Richs("asset", nil, account, nil) == nil { + // 添加账户 + m.Log(ice.LOG_CREATE, "account: %s", account) + m.Rich("asset", nil, kit.Data("account", account, "amount", "0", "bonus", "0", "spend", "0")) + } + + m.Richs("asset", nil, account, func(key string, value map[string]interface{}) { + // 账户流水 + m.Grow("asset", kit.Keys("hash", key), item) + + // 账户结余 + amount := kit.Int(kit.Value(value, "meta.amount")) + kit.Int(v) + m.Log(ice.LOG_INSERT, "%s: %v", key, amount) + kit.Value(value, "meta.amount", amount) + + switch data["收支类型"] { + case "收入": + bonus := kit.Int(kit.Value(value, "meta.bonus")) + kit.Int(v) + kit.Value(value, "meta.bonus", bonus) + case "支出": + spend := kit.Int(kit.Value(value, "meta.spend")) + kit.Int(v) + kit.Value(value, "meta.spend", spend) + } + }) + } + }) + } + return + } + + if m.Richs("asset", nil, arg[0], nil) == nil { + // 添加账户 + m.Rich("asset", nil, kit.Data("account", arg[0], "amount", "0", "bonus", "0", "spend", "0")) + m.Log(ice.LOG_CREATE, "account: %s", arg[0]) + } + + m.Richs("asset", nil, arg[0], func(key string, value map[string]interface{}) { + field := []string{"time", "id", "value", "type", "name", "text"} + if len(arg) == 1 { + // 消费流水 + m.Grows("asset", kit.Keys("hash", key), "", "", func(index int, value map[string]interface{}) { + m.Push("", value, field) + }) + m.Sort("time", "time_r") + return + } + if len(arg) == 2 { + // 消费详情 + m.Grows("asset", kit.Keys("hash", key), "id", arg[1], func(index int, value map[string]interface{}) { + m.Push("detail", value) + }) + m.Sort("time", "time_r") + return + } + if len(arg) < 6 { + name, value := "type", arg[2] + switch len(arg) { + case 3: + // 消费分类 + name, value = "type", arg[2] + case 4: + // 消费对象 + name, value = "name", arg[3] + case 5: + // 消费备注 + name, value = "text", arg[4] + } + m.Grows("asset", kit.Keys("hash", key), name, value, func(index int, value map[string]interface{}) { + m.Push("", value, field) + }) + m.Sort("time", "time_r") + return + } + + // 添加流水 + amount := kit.Int(arg[5]) + extra := map[string]interface{}{} + data := kit.Dict( + "type", arg[2], "name", arg[3], "text", arg[4], "value", amount, "extra", extra, + ) + for i := 6; i < len(arg); i += 2 { + if arg[i] == "time" { + kit.Value(data, arg[i], arg[i+1]) + } else { + kit.Value(extra, arg[i], arg[i+1]) + } + } + m.Grow("asset", kit.Keys("hash", key), data) + + // 账户结余 + amount = kit.Int(kit.Value(value, "meta.amount")) + amount + m.Log(ice.LOG_INSERT, "%s: %v", key, amount) + kit.Value(value, "meta.amount", amount) + m.Echo("%d", amount) + + switch data["type"] { + case "收入": + bonus := kit.Int(kit.Value(value, "meta.bonus")) + amount + kit.Value(value, "meta.bonus", bonus) + case "支出": + spend := kit.Int(kit.Value(value, "meta.spend")) + amount + kit.Value(value, "meta.spend", spend) + } + }) }}, "passcode": &ice.Command{Name: "passcode", Help: "passcode", Meta: kit.Dict("active", "mall/input"), Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { diff --git a/core/team/team.go b/core/team/team.go index a663b0b3..8ade92e1 100644 --- a/core/team/team.go +++ b/core/team/team.go @@ -1,18 +1,20 @@ package team import ( - "fmt" "github.com/shylinux/icebergs" _ "github.com/shylinux/icebergs/base" "github.com/shylinux/icebergs/base/web" "github.com/shylinux/toolkits" + + "fmt" + "strings" "time" ) var Index = &ice.Context{Name: "team", Help: "团队中心", Caches: map[string]*ice.Cache{}, Configs: map[string]*ice.Config{ - ice.APP_MISS: {Name: "miss", Help: "任务", Value: kit.Data( + ice.APP_MISS: {Name: "miss", Help: "任务", Value: kit.Data(kit.MDB_SHORT, "miss", "mis", []interface{}{"已取消", "准备中", "开发中", "测试中", "发布中", "已完成"}, "fsm", kit.Dict( "准备中", kit.Dict("next", "开发中"), "开发中", kit.Dict("next", "测试中", "prev", "准备中"), @@ -22,60 +24,249 @@ var Index = &ice.Context{Name: "team", Help: "团队中心", "已取消", kit.Dict(), ), )}, + "plan": {Name: "plan", Help: "计划", Value: kit.Data()}, }, Commands: map[string]*ice.Command{ ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Watch(ice.MISS_CREATE, ice.APP_MISS) - m.Cmd(ice.CTX_CONFIG, "load", "team.json") + // m.Watch(ice.MISS_CREATE, ice.APP_MISS) + m.Cmd(ice.CTX_CONFIG, "load", kit.Keys(m.Cap(ice.CTX_FOLLOW), "json")) }}, ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmd(ice.CTX_CONFIG, "save", "team.json", "web.team.miss") + m.Cmd(ice.CTX_CONFIG, "save", kit.Keys(m.Cap(ice.CTX_FOLLOW), "json"), kit.Keys(m.Cap(ice.CTX_FOLLOW), ice.APP_MISS)) }}, ice.APP_MISS: {Name: "miss", Help: "任务", Meta: kit.Dict("remote", "you"), List: kit.List( - kit.MDB_INPUT, "text", "name", "id", - kit.MDB_INPUT, "button", "name", "执行", + kit.MDB_INPUT, "text", "name", "miss", "action", "auto", + kit.MDB_INPUT, "text", "name", "id", "action", "auto", + kit.MDB_INPUT, "button", "name", "查看", kit.MDB_INPUT, "button", "name", "返回", "cb", "Last", - ), Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { - hot := kit.Select(ice.FAVOR_MISS, m.Option("hot")) - if len(arg) > 1 { + ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Option("cache.limit", "10000") + + if len(arg) > 0 && arg[0] == "action" { switch arg[1] { case "modify": - // 修改任务 - m.Richs(ice.WEB_FAVOR, nil, hot, func(key string, value map[string]interface{}) { - m.Grows(ice.WEB_FAVOR, kit.Keys("hash", key), "id", arg[0], func(index int, value map[string]interface{}) { - m.Log(ice.LOG_MODIFY, "%s: %s->%s", arg[2], arg[4], arg[3]) - kit.Value(value, arg[2], arg[3]) + m.Richs(cmd, nil, m.Option("miss"), func(key string, account map[string]interface{}) { + m.Grows(cmd, kit.Keys("hash", key), "id", arg[5], func(index int, current map[string]interface{}) { + kit.Value(current, arg[2], arg[3]) }) }) - arg = arg[:0] } + return } if len(arg) == 0 { // 任务列表 - m.Richs(ice.WEB_FAVOR, nil, hot, func(key string, value map[string]interface{}) { - m.Grows(ice.WEB_FAVOR, kit.Keys("hash", key), "", "", func(index int, value map[string]interface{}) { - m.Push(kit.Format(index), value, []string{"extra.begin_time", "extra.close_time", "extra.status", "id", "type", "name", "text"}) - }) - }) - return - } - if len(arg) == 1 { - // 任务详情 - m.Richs(ice.WEB_FAVOR, nil, hot, func(key string, value map[string]interface{}) { - m.Grows(ice.WEB_FAVOR, kit.Keys("hash", key), "id", arg[0], func(index int, value map[string]interface{}) { - m.Push("detail", value) - }) + m.Richs(cmd, nil, "*", func(key string, value map[string]interface{}) { + m.Push(key, value["meta"]) }) return } - // 添加任务 - m.Cmdy(ice.WEB_FAVOR, hot, ice.TYPE_DRIVE, arg[0], arg[1], - "begin_time", m.Time(), "close_time", m.Time(), - "status", kit.Select("准备中", arg, 2), - ) + if m.Richs(cmd, nil, arg[0], nil) == nil { + // 添加任务 + m.Rich(cmd, nil, kit.Data("miss", arg[0])) + m.Log(ice.LOG_CREATE, "miss: %s", arg[0]) + } + + m.Richs(cmd, nil, arg[0], func(key string, value map[string]interface{}) { + field := []string{"begin_time", "id", "status", "type", "name", "text"} + if len(arg) == 1 { + // 任务列表 + m.Grows(cmd, kit.Keys("hash", key), "", "", func(index int, value map[string]interface{}) { + m.Push("", value, field) + }) + m.Sort("time", "time_r") + return + } + if len(arg) == 2 { + // 消费详情 + m.Grows(cmd, kit.Keys("hash", key), "id", arg[1], func(index int, value map[string]interface{}) { + m.Push("detail", value) + }) + m.Sort("time", "time_r") + return + } + if len(arg) < 5 { + name, value := "type", arg[2] + switch len(arg) { + case 3: + // 消费分类 + name, value = "type", arg[2] + case 4: + // 消费对象 + name, value = "name", arg[3] + } + m.Grows(cmd, kit.Keys("hash", key), name, value, func(index int, value map[string]interface{}) { + m.Push("", value, []string{"time", "id", "status", "type", "name", "text"}) + }) + m.Sort("time", "time_r") + return + } + + // 添加任务 + extra := kit.Dict() + data := kit.Dict("type", arg[2], "name", arg[3], "text", arg[4], + "begin_time", m.Time(), "close_time", m.Time(), + "status", "prepare", "extra", extra, + ) + for i := 5; i < len(arg); i += 2 { + if arg[i] == "time" { + kit.Value(data, arg[i], arg[i+1]) + } else { + kit.Value(extra, arg[i], arg[i+1]) + } + } + n := m.Grow(cmd, kit.Keys("hash", key), data) + m.Echo("%s: %d", key, n) + }) + }}, + "plan": {Name: "plan day|week|month|year", Help: "计划", Meta: kit.Dict("display", "team/plan"), List: kit.List( + kit.MDB_INPUT, "select", "name", "scale", "values", []string{"day", "week", "month"}, "action", "auto", + kit.MDB_INPUT, "text", "name", "begin_time", "action", "auto", "figure", "date", + kit.MDB_INPUT, "button", "name", "查看", + ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + // 起始日期 + first := time.Now() + if len(arg) > 1 { + first = time.Unix(int64(kit.Time(arg[1])), 0) + } + + // 结束日期 + last := time.Now() + if len(arg) > 2 { + last = time.Unix(int64(kit.Time(arg[2])), 0) + } + + meta := map[int]string{0: "周日", 1: "周一", 2: "周二", 3: "周三", 4: "周四", 5: "周五", 6: "周六"} + + switch arg[0] { + case "action": + switch arg[1] { + case "modify": + switch arg[2] { + case "begin_time": + m.Richs(ice.APP_MISS, nil, arg[6], func(key string, value map[string]interface{}) { + m.Grows(ice.APP_MISS, kit.Keys("hash", key), "id", arg[5], func(index int, value map[string]interface{}) { + m.Log(ice.LOG_MODIFY, "%s: %s begin_time: %s", arg[6], arg[5], arg[3]) + value["begin_time"] = arg[3] + }) + }) + } + } + + case "day": + for i := 6; i < 24; i++ { + m.Push("hour", i) + m.Push("miss", "") + } + + match := first.Format("2006-01-02") + m.Richs(ice.APP_MISS, nil, "*", func(key string, value map[string]interface{}) { + m.Grows(ice.APP_MISS, kit.Keys("hash", key), "", "", func(index int, value map[string]interface{}) { + if now := kit.Format(value["begin_time"]); strings.Split(now, " ")[0] == match { + m.Push("hour", strings.Split(now, " ")[1][:2]) + m.Push("miss", kit.Format(`
%s: %s
`, + key, kit.Int(value["id"]), value["begin_time"], value["name"], value["text"])) + } + }) + }) + m.Sort("hour", "int") + + case "week": + one := first.AddDate(0, 0, -int(first.Weekday())) + end := first.AddDate(0, 0, 7-int(first.Weekday())) + + list := map[int][]map[string]interface{}{} + name := map[int][]string{} + m.Richs(ice.APP_MISS, nil, "*", func(key string, value map[string]interface{}) { + m.Grows(ice.APP_MISS, kit.Keys("hash", key), "", "", func(index int, value map[string]interface{}) { + if t, e := time.ParseInLocation(ice.ICE_TIME, kit.Format(value["begin_time"]), time.Local); e == nil { + if t.After(one) && t.Before(end) { + index := t.Hour()*10 + int(t.Weekday()) + list[index] = append(list[index], value) + name[index] = append(name[index], key) + } + } + }) + }) + + for i := 6; i < 24; i++ { + m.Push("hour", i) + for t := one; t.Before(end); t = t.AddDate(0, 0, 1) { + index := i*10 + int(t.Weekday()) + note := []string{} + for i, v := range list[index] { + note = append(note, kit.Format(`
%s
`, + name[index][i], kit.Int(v["id"]), v["begin_time"], v["text"], v["name"])) + } + m.Push(meta[int(t.Weekday())], strings.Join(note, "")) + } + } + + case "month": + // 本月日期 + one := first.AddDate(0, 0, -first.Day()+1) + end := last.AddDate(0, 1, -last.Day()+1) + + list := map[string][]map[string]interface{}{} + m.Richs(ice.APP_MISS, nil, "*", func(key string, value map[string]interface{}) { + m.Grows(ice.APP_MISS, kit.Keys("hash", key), "", "", func(index int, value map[string]interface{}) { + if t, e := time.ParseInLocation(ice.ICE_TIME, kit.Format(value["begin_time"]), time.Local); e == nil { + if t.After(one) && t.Before(end) { + index := t.Format("2006-01-02") + list[index] = append(list[index], value) + } + } + }) + }) + + // 上月结尾 + head := one.AddDate(0, 0, -int(one.Weekday())) + for day := head; day.Before(one); day = day.AddDate(0, 0, 1) { + m.Push(meta[int(day.Weekday())], day.Day()) + } + // 本月日期 + for day := one; day.Before(end); day = day.AddDate(0, 0, 1) { + note := []string{} + if day.Day() == 1 { + note = append(note, kit.Format("%d月", day.Month())) + } else { + note = append(note, kit.Format("%d", day.Day())) + } + + index := day.Format("2006-01-02") + for _, v := range list[index] { + note = append(note, kit.Format(`%s: %s`, v["name"], v["text"])) + } + if len(note) > 1 { + note[0] = kit.Format(`
%s%d
`, strings.Join(note[1:], "\n"), note[0], len(note)-1) + } else { + note[0] = kit.Format(`%s%s`, note[0], "") + } + m.Push(meta[int(day.Weekday())], note[0]) + + } + // 下月开头 + tail := end.AddDate(0, 0, 6-int(end.Weekday())+1) + for day := end; end.Weekday() != 0 && day.Before(tail); day = day.AddDate(0, 0, 1) { + m.Push(meta[int(day.Weekday())], day.Day()) + } + + case "year": + } + }}, + "stat": {Name: "stat", Help: "统计", Meta: kit.Dict(), Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { + m.Richs(ice.APP_MISS, nil, kit.Select("*", arg, 0), func(key string, value map[string]interface{}) { + stat := map[string]int{} + m.Grows(ice.APP_MISS, kit.Keys("hash", key), "", "", func(index int, value map[string]interface{}) { + stat[kit.Format(value["status"])] += 1 + }) + m.Push("miss", kit.Value(value, "meta.miss")) + for _, k := range []string{"prepare", "process", "cancel", "finish"} { + m.Push(k, stat[k]) + } + }) }}, "date": {Name: "date", Help: "日历", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { show := map[int]string{0: "周日", 1: "周一", 2: "周二", 3: "周三", 4: "周四", 5: "周五", 6: "周六"} @@ -119,19 +310,6 @@ var Index = &ice.Context{Name: "team", Help: "团队中心", } } }}, - "stat": {Name: "stat", Help: "统计", Meta: kit.Dict(), Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { - hot := kit.Select(ice.FAVOR_MISS, m.Option("hot")) - stat := map[string]int{} - m.Option("cache.limit", "1000") - m.Richs(ice.WEB_FAVOR, nil, hot, func(key string, value map[string]interface{}) { - m.Grows(ice.WEB_FAVOR, kit.Keys("hash", key), "", "", func(index int, value map[string]interface{}) { - stat[kit.Format(kit.Value(value, "extra.status"))] += 1 - }) - }) - for k, v := range stat { - m.Push(k, v) - } - }}, "progress": {Name: "progress", Help: "进度", Meta: kit.Dict( "remote", "you", "display", "team/miss", "detail", []string{"回退", "前进", "取消", "完成"}, diff --git a/core/wiki/chart.go b/core/wiki/chart.go index 08de4114..b736847f 100644 --- a/core/wiki/chart.go +++ b/core/wiki/chart.go @@ -45,7 +45,7 @@ func (b *Block) Draw(m *ice.Message, x, y int) Chart { m.Echo(``, x+b.Margin/2, y+b.Margin/2, b.GetWidth(), b.GetHeight(), b.BackGround, b.RectData) m.Echo("\n") - m.Echo(`%v`, + m.Echo(`%v`, x+b.GetWidths()/2, y+b.GetHeights()/2, b.FontSize, b.FontColor, b.TextData, b.Text) m.Echo("\n") return b @@ -64,13 +64,16 @@ func (b *Block) GetWidth(str ...string) int { if b.Width != 0 { return b.Width } - return len(kit.Select(b.Text, str, 0))*b.FontSize*6/10 + b.Padding + s := kit.Select(b.Text, str, 0) + cn := (len(s) - len([]rune(s))) / 2 + en := len([]rune(s)) - cn + return cn*b.FontSize + en*b.FontSize*10/16 + b.Padding } func (b *Block) GetHeight(str ...string) int { if b.Height != 0 { return b.Height } - return b.FontSize*b.LineSize/10 + b.Padding + return b.FontSize + b.Padding } func (b *Block) GetWidths(str ...string) int { return b.GetWidth(str...) + b.Margin @@ -79,6 +82,74 @@ func (b *Block) GetHeights(str ...string) int { return b.GetHeight() + b.Margin } +// 框 +type Label struct { + data [][]string + max map[int]int + Block +} + +func (b *Label) Init(m *ice.Message, arg ...string) Chart { + b.FontSize = kit.Int(kit.Select("24", arg, 1)) + b.Padding = kit.Int(kit.Select("16", arg, 6)) + b.Margin = kit.Int(kit.Select("8", arg, 7)) + + // 解析数据 + b.max = map[int]int{} + for _, v := range kit.Split(arg[0], "\n") { + l := kit.Split(v) + for i, v := range l { + switch data := kit.Parse(nil, "", kit.Split(v)...).(type) { + case map[string]interface{}: + v = kit.Select("", data["text"]) + } + + if w := b.GetWidth(v); w > b.max[i] { + b.max[i] = w + } + } + b.data = append(b.data, l) + } + + // 计算尺寸 + width := 0 + for _, v := range b.max { + width += v + b.Margin + } + b.Width = width + b.Height = len(b.data) * b.GetHeights() + return b +} +func (b *Label) Draw(m *ice.Message, x, y int) Chart { + b.Width, b.Height = 0, 0 + top := y + for _, line := range b.data { + left := x + for i, text := range line { + switch data := kit.Parse(nil, "", kit.Split(text)...).(type) { + case map[string]interface{}: + text = kit.Select(text, data["text"]) + } + b.Text = text + + width := b.max[i] + if m.Option("compact") == "true" { + width = b.GetWidth() + } + + m.Echo(``, + left, top, width, b.GetHeight()) + m.Echo("\n") + m.Echo(`%v`, + left+width/2, top+b.GetHeight()/2, m.Option("stroke"), text) + m.Echo("\n") + left += width + b.Margin + } + top += b.GetHeights() + } + return b +} + // 树 type Chain struct { data map[string]interface{} @@ -204,78 +275,7 @@ func (b *Chain) draw(m *ice.Message, root map[string]interface{}, depth int, wid return b } -// 表 -type Table struct { - data [][]string - max map[int]int - Block -} - -func (b *Table) Init(m *ice.Message, arg ...string) Chart { - // 解析数据 - b.max = map[int]int{} - for _, v := range kit.Split(arg[0], "\n") { - l := kit.Split(v) - for i, v := range l { - switch data := kit.Parse(nil, "", kit.Split(v)...).(type) { - case map[string]interface{}: - v = kit.Select("", data["text"]) - } - if len(v) > b.max[i] { - b.max[i] = len(v) - } - } - b.data = append(b.data, l) - } - b.FontColor = kit.Select("white", arg, 1) - b.BackGround = kit.Select("red", arg, 2) - b.FontSize = kit.Int(kit.Select("24", arg, 3)) - b.LineSize = kit.Int(kit.Select("12", arg, 4)) - b.Padding = kit.Int(kit.Select("8", arg, 5)) - b.Margin = kit.Int(kit.Select("8", arg, 6)) - - // 计算尺寸 - width := 0 - for _, v := range b.max { - width += b.GetWidths(strings.Repeat(" ", v)) - } - b.Width = width - b.Height = len(b.data) * b.GetHeights() - - // m.Log("info", "data %v", kit.Formats(b.data)) - return b -} -func (b *Table) Draw(m *ice.Message, x, y int) Chart { - b.Width, b.Height = 0, 0 - for n, line := range b.data { - for i, text := range line { - l := 0 - for j := 0; j < i; j++ { - l += b.GetWidths(strings.Repeat(" ", b.max[i])) - } - block := &Block{ - BackGround: kit.Select(b.BackGround), - FontColor: kit.Select(b.FontColor), - FontSize: b.FontSize, - LineSize: b.LineSize, - Padding: b.Padding, - Margin: b.Margin, - Width: b.GetWidth(strings.Repeat(" ", b.max[i])), - } - - switch data := kit.Parse(nil, "", kit.Split(text)...).(type) { - case map[string]interface{}: - text = kit.Select(text, data["text"]) - block.Data(data) - } - block.Init(m, text).Draw(m, x+l, y+n*b.GetHeights()) - } - } - return b -} - -func stack(m *ice.Message, name string, level int, data interface{}) { - l, ok := kit.Value(data, "list").([]interface{}) +func Stack(m *ice.Message, name string, level int, data interface{}) { style := []string{} kit.Fetch(kit.Value(data, "meta"), func(key string, value string) { switch key { @@ -285,6 +285,8 @@ func stack(m *ice.Message, name string, level int, data interface{}) { style = append(style, "color:"+value) } }) + + l, ok := kit.Value(data, "list").([]interface{}) if !ok || len(l) == 0 { m.Echo(`
o %s
`, name, strings.Join(style, ";"), kit.Value(data, "meta.text")) return @@ -295,7 +297,7 @@ func stack(m *ice.Message, name string, level int, data interface{}) { m.Echo("
    ", name, kit.Select("", `style="display:none"`, level > 2)) kit.Fetch(kit.Value(data, "list"), func(index int, value map[string]interface{}) { m.Echo("
  • ") - stack(m, name, level+1, value) + Stack(m, name, level+1, value) m.Echo("
  • ") }) m.Echo("
") diff --git a/core/wiki/template.go b/core/wiki/template.go index f1c8c52a..96320716 100644 --- a/core/wiki/template.go +++ b/core/wiki/template.go @@ -1,16 +1,19 @@ package wiki -var title = `<{{.Option "level"}} class="story" data-type="{{.Option "type"}}" data-name="{{.Option "prefix"}}" data-text="{{.Option "text"}}">{{.Option "prefix"}}{{.Option "content"}}` +var title = `<{{.Option "level"}} class="story" data-type="{{.Option "type"}}" data-name="{{.Option "prefix"}}" data-text="{{.Option "text"}}">{{.Option "prefix"}} {{.Option "content"}}` var brief = `

{{.Option "text"}}

` var refer = `
    {{range $index, $value := .Optionv "list"}}
  • {{index $value 0}}: {{index $value 1}}
  • {{end}}
` -var spark = `

{{.}}

` +var spark = `

{{.Option "text"}}

` -var shell = `
$ {{.Option "input"}} -{{.Option "output"}}
+var local = `
+{{range $index, $value := .Optionv "input"}}{{$value}}{{end}}
` + +var shell = `$ {{.Option "input"}} # {{.Option "name"}} +{{.Option "output"}} ` - var order = `
    {{range $index, $value := .Optionv "list"}}
  • {{$value}}
  • {{end}}
` @@ -23,15 +26,20 @@ data-type="{{.Option "type"}}" data-name="{{.Option "name"}}" data-text="{{.Opti {{end}} ` +var stack = `
` + var prefix = `` -var premenu = `
    ` -var endmenu = `
      -{{$menu := .Optionv "menu"}} -{{range $index, $value := Value $menu "list"}} -
    • {{Value $value "prefix"}} {{Value $value "content"}}
    • -{{end}} +var premenu = `
        ` +var endmenu = `
          {{$menu := .Optionv "menu"}}{{range $index, $value := Value $menu "list"}} +
        • {{Value $value "prefix"}} {{Value $value "content"}}
        • {{end}}
        ` diff --git a/core/wiki/wiki.go b/core/wiki/wiki.go index 21430bd8..50b3a2b1 100644 --- a/core/wiki/wiki.go +++ b/core/wiki/wiki.go @@ -22,11 +22,13 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", "path", "", "head", "time size line path", "alias", map[string]interface{}{ - "label": []interface{}{"chart", "block"}, + "label": []interface{}{"chart", "label"}, "chain": []interface{}{"chart", "chain"}, - "chapter": []interface{}{"title", "chapter"}, "section": []interface{}{"title", "section"}, + "chapter": []interface{}{"title", "chapter"}, + "endmenu": []interface{}{"title", "endmenu"}, + "premenu": []interface{}{"title", "premenu"}, }, )}, "title": {Name: "title", Help: "标题", Value: kit.Data("template", title)}, @@ -34,15 +36,17 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", "refer": {Name: "refer", Help: "参考", Value: kit.Data("template", refer)}, "spark": {Name: "spark", Help: "段落", Value: kit.Data("template", spark)}, + "local": {Name: "local", Help: "文件", Value: kit.Data("template", local)}, "shell": {Name: "shell", Help: "命令", Value: kit.Data("template", shell)}, "order": {Name: "order", Help: "列表", Value: kit.Data("template", order)}, "table": {Name: "table", Help: "表格", Value: kit.Data("template", table)}, + "stack": {Name: "stack", Help: "结构", Value: kit.Data("template", stack)}, "chart": {Name: "chart", Help: "绘图", Value: kit.Data("prefix", prefix, "suffix", ``)}, "mind": {Name: "mind", Help: "思维导图", Value: kit.Data(kit.MDB_SHORT, "name", "path", "usr/local", "regs", ".*\\.svg", "prefix", ``, "suffix", ``)}, "word": {Name: "word", Help: "语言文字", Value: kit.Data(kit.MDB_SHORT, "name", "path", "usr/local", "regs", ".*\\.shy")}, "data": {Name: "data", Help: "数据表格", Value: kit.Data(kit.MDB_SHORT, "name", "path", "usr/local", "regs", ".*\\.csv")}, - "feel": {Name: "feel", Help: "影音媒体", Value: kit.Data(kit.MDB_SHORT, "name", "path", "usr/local", "regs", ".*\\.(JPG|MOV|m4v)")}, + "feel": {Name: "feel", Help: "影音媒体", Value: kit.Data(kit.MDB_SHORT, "name", "path", "usr/local", "regs", ".*\\.(png|JPG|MOV|m4v)")}, "walk": {Name: "walk", Help: "走遍世界", Value: kit.Data(kit.MDB_SHORT, "name", "path", "usr/local", "regs", ".*\\.csv")}, }, Commands: map[string]*ice.Command{ @@ -53,7 +57,8 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Cmd(ice.CTX_CONFIG, "save", kit.Keys(m.Cap(ice.CTX_FOLLOW), "json"), kit.Keys(m.Cap(ice.CTX_FOLLOW), "feel")) }}, - "chart": {Name: "chart block|chain|table name text [fg bg fs ls p m]", Help: "绘图", Meta: map[string]interface{}{ + + "chart": {Name: "chart label|chain|table name text [fg bg fs ls p m]", Help: "绘图", Meta: map[string]interface{}{ "display": "inner", }, List: kit.List( kit.MDB_INPUT, "select", "value", "chain", "values", "block chain table", @@ -63,8 +68,8 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", // 创建类型 var chart Chart switch arg[0] { - case "block": - chart = &Table{} + case "label": + chart = &Label{} case "chain": chart = &Chain{} } @@ -72,29 +77,47 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", arg[2] = strings.TrimSpace(arg[2]) // 构造数据 - m.Option("type", arg[0]) - m.Option("name", arg[1]) - m.Option("text", arg[2]) + m.Option(kit.MDB_TYPE, arg[0]) + m.Option(kit.MDB_NAME, arg[1]) + m.Option(kit.MDB_TEXT, arg[2]) + m.Option("font-size", kit.Select("16", arg, 3)) + m.Option("stroke", kit.Select("yellow", arg, 4)) + m.Option("fill", kit.Select("purple", arg, 5)) + + m.Option("style", "") + m.Option("compact", "false") + m.Option("stroke-width", "2") + m.Option("font-family", kit.Select("", "monospace", len(arg[2]) == len([]rune(arg[2])))) + for i := 6; i < len(arg)-1; i++ { + m.Option(arg[i], arg[i+1]) + } + chart.Init(m, arg[2:]...) m.Option("width", chart.GetWidth()) m.Option("height", chart.GetHeight()) // 生成网页 m.Render(m.Conf("chart", ice.Meta("prefix"))) - chart.Draw(m, 0, 0) + chart.Draw(m, 4, 4) m.Render(m.Conf("chart", ice.Meta("suffix"))) }}, - "stack": {Name: "stack name text", Help: "堆栈", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + "stack": {Name: "stack name text", Help: "结构", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Option(kit.MDB_TYPE, cmd) + m.Option(kit.MDB_NAME, arg[0]) + m.Option(kit.MDB_TEXT, arg[1]) + chain := &Chain{} - m.Render(m.Conf("spark", ice.Meta("template")), arg[0]) - stack(m, "stack", 0, kit.Parse(nil, "", chain.show(m, arg[1])...)) + m.Render(m.Conf(cmd, "meta.template")) + Stack(m, cmd, 0, kit.Parse(nil, "", chain.show(m, arg[1])...)) + m.Echo("
      ") }}, "table": {Name: "table name text", Help: "表格", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Option("type", "table") - m.Option("name", arg[0]) - m.Option("text", arg[1]) + m.Option(kit.MDB_TYPE, cmd) + m.Option(kit.MDB_NAME, arg[0]) + m.Option(kit.MDB_TEXT, arg[1]) + head, list := []string{}, [][]string{} - for i, v := range kit.Split(arg[1], "\n") { + for i, v := range kit.Split(strings.TrimSpace(arg[1]), "\n") { if i == 0 { head = kit.Split(v) } else { @@ -103,18 +126,18 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", } m.Optionv("head", head) m.Optionv("list", list) - m.Render(m.Conf("table", ice.Meta("template"))) + m.Render(m.Conf(cmd, "meta.template")) }}, - "order": {Name: "order name text", Help: "列表", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { - m.Option("type", "order") - m.Option("name", arg[0]) - m.Option("text", arg[1]) - m.Optionv("list", kit.Split(arg[1], "\n")) - m.Render(m.Conf("order", ice.Meta("template"))) + "order": {Name: "order name text", Help: "列表", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Option(kit.MDB_TYPE, cmd) + m.Option(kit.MDB_NAME, arg[0]) + m.Option(kit.MDB_TEXT, arg[1]) + m.Optionv("list", kit.Split(strings.TrimSpace(arg[1]), "\n")) + m.Render(m.Conf(cmd, "meta.template")) }}, - "shell": {Name: "shell name dir cmd", Help: "命令", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { - m.Option("type", "shell") - m.Option("name", arg[0]) + "shell": {Name: "shell name dir cmd", Help: "命令", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Option(kit.MDB_TYPE, cmd) + m.Option(kit.MDB_NAME, arg[0]) m.Option("cmd_dir", arg[1]) input, output := "", "" @@ -123,86 +146,123 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", input = strings.Join(arg[1:], " ") default: input = strings.Join(arg, " ") - output = m.Cmdx("cli.system", "sh", "-c", strings.Join(arg, " ")) + output = m.Cmdx(ice.CLI_SYSTEM, "sh", "-c", input) } m.Option("input", input) m.Option("output", output) - m.Render(m.Conf("spark", ice.Meta("template")), m.Option("name")) - m.Render(m.Conf("shell", ice.Meta("template"))) + m.Render(m.Conf(cmd, "meta.template")) }}, - "index": {Name: "index hash", Help: "索引", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { - m.Cmd(ice.WEB_STORY, "index", arg) + "local": {Name: "local name text", Help: "文件", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Option(kit.MDB_TYPE, cmd) + m.Option(kit.MDB_NAME, arg[0]) + m.Option(kit.MDB_TEXT, arg[1]) + m.Option("input", m.Cmdx("nfs.cat", arg[1])) + + switch ls := strings.Split(arg[1], "."); ls[len(ls)-1] { + case "csv": + list := []string{""} + m.Spawn().CSV(m.Option("input")).Table(func(index int, value map[string]string, head []string) { + if index == 0 { + list = append(list, "") + for _, k := range head { + list = append(list, "") + } + list = append(list, "") + } + + list = append(list, "") + for _, k := range head { + list = append(list, "") + } + list = append(list, "") + }) + list = append(list, "
      ", k, "
      ", value[k], "
      ") + m.Optionv("input", list) + } + m.Render(m.Conf(cmd, "meta.template")) }}, - "spark": {Name: "spark name text", Help: "参考", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { - m.Option("type", "refer") - m.Option("name", arg[0]) - m.Option("text", arg[1]) + "spark": {Name: "spark name text", Help: "感悟", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Option(kit.MDB_TYPE, cmd) + m.Option(kit.MDB_NAME, arg[0]) + m.Option(kit.MDB_TEXT, arg[1]) m.Optionv("list", kit.Split(arg[1], "\n")) - m.Render(m.Conf("order", ice.Meta("template"))) + m.Render(m.Conf(cmd, "meta.template")) }}, - "refer": {Name: "refer name text", Help: "参考", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { - m.Option("type", "refer") - m.Option("name", arg[0]) - m.Option("text", arg[1]) + "refer": {Name: "refer name text", Help: "参考", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Option(kit.MDB_TYPE, cmd) + m.Option(kit.MDB_NAME, arg[0]) + m.Option(kit.MDB_TEXT, arg[1]) + list := [][]string{} - for _, v := range kit.Split(arg[1], "\n") { + for _, v := range kit.Split(strings.TrimSpace(arg[1]), "\n") { list = append(list, kit.Split(v, " ")) } m.Optionv("list", list) - m.Render(m.Conf("refer", ice.Meta("template"))) + m.Render(m.Conf(cmd, "meta.template")) }}, "brief": {Name: "brief name text", Help: "摘要", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Option("type", "brief") - m.Option("name", arg[0]) - m.Option("text", arg[1]) - m.Render(m.Conf("brief", ice.Meta("template"))) + m.Option(kit.MDB_TYPE, cmd) + m.Option(kit.MDB_NAME, arg[0]) + m.Option(kit.MDB_TEXT, arg[1]) + m.Render(m.Conf(cmd, "meta.template")) }}, - "title": {Name: "title text", Help: "标题", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - // 生成序号 - m.Option("level", "h1") + "title": {Name: "title [chapter|section|endmenu|premenu] text", Help: "标题", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { title, _ := m.Optionv("title").(map[string]int) switch arg[0] { case "endmenu": + // 后置目录 m.Render(endmenu) return case "premenu": + // 前置目录 m.Render(premenu) return case "section": - m.Option("level", "h3") arg = arg[1:] title["section"]++ - m.Option("prefix", fmt.Sprintf("%d.%d ", title["chapter"], title["section"])) + m.Option("level", "h3") + m.Option("prefix", fmt.Sprintf("%d.%d", title["chapter"], title["section"])) case "chapter": - m.Option("level", "h2") arg = arg[1:] title["chapter"]++ title["section"] = 0 - m.Option("prefix", fmt.Sprintf("%d ", title["chapter"])) + m.Option("level", "h2") + m.Option("prefix", fmt.Sprintf("%d", title["chapter"])) default: + m.Option("level", "h1") m.Option("prefix", "") } - m.Option("type", "title") - m.Option("text", arg[0]) + m.Option(kit.MDB_TYPE, cmd) + m.Option(kit.MDB_NAME, arg[0]) + m.Option(kit.MDB_TEXT, arg[0]) - // 生成菜单 + // 添加目录 ns := strings.Split(m.Conf("runtime", "node.name"), "-") menu, _ := m.Optionv("menu").(map[string]interface{}) menu["list"] = append(menu["list"].([]interface{}), map[string]interface{}{ "content": m.Option("content", kit.Select(ns[len(ns)-1], arg, 0)), "prefix": m.Option("prefix"), + "level": m.Option("level"), }) // 生成网页 - m.Render(m.Conf("title", ice.Meta("template"))) + m.Render(m.Conf("title", "meta.template")) }}, - "_text": {Name: "_text file", Help: "文章", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { + "index": {Name: "index hash", Help: "索引", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Cmd(ice.WEB_STORY, "index", arg) + }}, + "_text": {Name: "_text file", Help: "文章", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Option(ice.WEB_TMPL, "raw") m.Optionv("title", map[string]int{}) m.Optionv("menu", map[string]interface{}{"list": []interface{}{}}) + if strings.HasSuffix(arg[0], ".shy") { + m.Optionv(ice.MSG_ALIAS, m.Confv("note", "meta.alias")) + m.Cmdy("ssh.scan", arg[0], arg[0], arg[0]) + return + } // 生成文章 buffer := bytes.NewBuffer([]byte{}) @@ -225,7 +285,7 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", // } m.Echo(string(data)) }}, - "_tree": {Name: "_tree path", Help: "文库", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { + "_tree": {Name: "_tree path", Help: "文库", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Option("dir_deep", "true") m.Option("dir_reg", ".*\\.md") m.Cmdy("nfs.dir", kit.Select(m.Conf("note", "meta.path"), arg, 0), m.Conf("note", "meta.head")) @@ -234,7 +294,7 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", kit.MDB_INPUT, "text", "name", "path", "value", "README.md", kit.MDB_INPUT, "button", "name", "执行", "action", "auto", kit.MDB_INPUT, "button", "name", "返回", "cb", "Last", - ), Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { + ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) > 1 { switch arg[1] { case "运行": @@ -259,8 +319,8 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", }}, "mind": {Name: "mind", Help: "思维导图", Meta: kit.Dict("display", "wiki/mind"), List: kit.List( - kit.MDB_INPUT, "text", "name", "name", - kit.MDB_INPUT, "button", "name", "执行", + kit.MDB_INPUT, "text", "name", "name", "value", "what/he.svg", + kit.MDB_INPUT, "button", "name", "执行", "action", "auto", kit.MDB_INPUT, "button", "name", "返回", "cb", "Last", ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) > 0 && arg[0] == "action" { @@ -276,6 +336,7 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", m.Option("dir_reg", m.Conf(cmd, "meta.regs")) m.Cmdy("nfs.dir", kit.Select("./", arg, 0)) m.Sort("time", "time_r") + if len(arg) == 0 || strings.HasSuffix(arg[0], "/") { // 目录列表 m.Option("dir_reg", "") @@ -284,6 +345,39 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", } }}, "word": {Name: "word", Help: "语言文字", Meta: kit.Dict("display", "wiki/word"), List: kit.List( + kit.MDB_INPUT, "text", "name", "name", "value", "what/hi.shy", + kit.MDB_INPUT, "button", "name", "执行", "action", "auto", + kit.MDB_INPUT, "button", "name", "返回", "cb", "Last", + ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) > 0 && arg[0] == "action" { + switch arg[1] { + case "保存": + m.Cmd("nfs.save", path.Join(m.Conf(cmd, "meta.path"), arg[2]), arg[3]) + } + return + } + + // 文件列表 + m.Option("dir_root", m.Conf(cmd, "meta.path")) + m.Option("dir_reg", m.Conf(cmd, "meta.regs")) + m.Cmdy("nfs.dir", kit.Select("./", arg, 0)) + m.Sort("time", "time_r") + if len(arg) == 0 || strings.HasSuffix(arg[0], "/") { + // 目录列表 + m.Option("dir_reg", "") + m.Option("dir_type", "dir") + m.Cmdy("nfs.dir", kit.Select("./", arg, 0)) + return + } + + // 解析脚本 + m.Option(ice.WEB_TMPL, "raw") + m.Optionv("title", map[string]int{}) + m.Optionv("menu", map[string]interface{}{"list": []interface{}{}}) + m.Optionv(ice.MSG_ALIAS, m.Confv("note", "meta.alias")) + m.Set("result").Cmdy("ssh.scan", arg[0], arg[0], path.Join(m.Conf(cmd, "meta.path"), arg[0])) + }}, + "data": {Name: "data", Help: "数据表格", Meta: kit.Dict("display", "wiki/data"), List: kit.List( kit.MDB_INPUT, "text", "name", "name", kit.MDB_INPUT, "button", "name", "执行", kit.MDB_INPUT, "button", "name", "返回", "cb", "Last", @@ -296,33 +390,6 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", return } - // 文件列表 - m.Option("dir_root", m.Conf(cmd, "meta.path")) - m.Option("dir_reg", m.Conf(cmd, "meta.regs")) - m.Cmdy("nfs.dir", kit.Select("./", arg, 0)) - m.Sort("time", "time_r") - if len(arg) == 0 || strings.HasSuffix(arg[0], "/") { - // 目录列表 - m.Option("dir_reg", "") - m.Option("dir_type", "dir") - m.Cmdy("nfs.dir", kit.Select("./", arg, 0)) - return - } - m.Option("preview", m.Cmdx("_text", path.Join(m.Conf(cmd, "meta.path"), arg[0]))) - }}, - "data": {Name: "data", Help: "数据表格", Meta: kit.Dict("display", "wiki/data"), List: kit.List( - kit.MDB_INPUT, "text", "name", "name", - kit.MDB_INPUT, "button", "name", "执行", - kit.MDB_INPUT, "button", "name", "返回", "cb", "Last", - ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - if len(arg) > 0 && arg[0] == "action" { - switch arg[1] { - case "保存": - m.Cmd("nfs.save", path.Join(m.Conf("mind", "meta.path"), arg[2]), arg[3]) - } - return - } - // 文件列表 m.Option("dir_root", m.Conf(cmd, "meta.path")) m.Option("dir_reg", m.Conf(cmd, "meta.regs")) @@ -337,17 +404,19 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", } m.CSV(m.Result()) }}, - "feel": {Name: "feel", Help: "影音媒体", Meta: kit.Dict("display", "wiki/feel"), List: kit.List( + "feel": {Name: "feel", Help: "影音媒体", Meta: kit.Dict("display", "wiki/feel", "detail", []string{"标签", "删除"}), List: kit.List( kit.MDB_INPUT, "text", "name", "name", kit.MDB_INPUT, "button", "name", "执行", kit.MDB_INPUT, "button", "name", "返回", "cb", "Last", ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) > 0 && arg[0] == "action" { switch arg[1] { + case "删除": + m.Assert(os.Remove(path.Join(m.Conf(cmd, "meta.path"), m.Option("path")))) case "保存": - m.Cmd("nfs.save", path.Join(m.Conf("mind", "meta.path"), arg[2]), arg[3]) + m.Cmd("nfs.save", path.Join(m.Conf(cmd, "meta.path"), arg[2]), arg[3]) case "标签": - m.Conf("feel", kit.Keys(path.Base(arg[2]), "-2"), arg[3]) + m.Conf(cmd, kit.Keys(path.Base(arg[2]), "-2"), arg[3]) p := path.Join(m.Conf(cmd, "meta.path"), arg[2]) q := path.Join(m.Conf(cmd, "meta.path"), arg[3]) os.MkdirAll(q, 0777) @@ -361,7 +430,7 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", m.Option("dir_root", m.Conf(cmd, "meta.path")) m.Option("dir_reg", m.Conf(cmd, "meta.regs")) m.Cmdy("nfs.dir", kit.Select("./", arg, 0), "time size path").Table(func(index int, value map[string]string, head []string) { - m.Push("label", m.Conf("feel", path.Base(value["path"]))) + m.Push("label", m.Conf(cmd, path.Base(value["path"]))) }) // 目录列表 @@ -387,7 +456,7 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", if len(arg) > 0 && arg[0] == "action" { switch arg[1] { case "保存": - m.Cmd("nfs.save", path.Join(m.Conf("mind", "meta.path"), arg[2]), arg[3]) + m.Cmd("nfs.save", path.Join(m.Conf(cmd, "meta.path"), arg[2]), arg[3]) } return } diff --git a/misc/alpha/alpha.go b/misc/alpha/alpha.go index 4c75b720..cda7697e 100644 --- a/misc/alpha/alpha.go +++ b/misc/alpha/alpha.go @@ -20,10 +20,10 @@ var Index = &ice.Context{Name: "alpha", Help: "英汉词典", }, Commands: map[string]*ice.Command{ ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmd(ice.CTX_CONFIG, "load", "alpha.json") + m.Cmd(ice.CTX_CONFIG, "load", kit.Keys(m.Cap(ice.CTX_FOLLOW), "json")) }}, ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmd(ice.CTX_CONFIG, "save", "alpha.json", "alpha") + m.Cmd(ice.CTX_CONFIG, "save", kit.Keys(m.Cap(ice.CTX_FOLLOW), "json"), kit.Keys(m.Cap(ice.CTX_FOLLOW), "alpha")) }}, "alpha": {Name: "alpha [load|list]", Help: "英汉词典", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { @@ -35,7 +35,7 @@ var Index = &ice.Context{Name: "alpha", Help: "英汉词典", switch arg[0] { case "load": // 加载词库 - m.Cmd(ice.MDB_IMPORT, "web.wiki.alpha.alpha", "", "list", + m.Cmd(ice.MDB_IMPORT, "alpha", "", "list", m.Cmd(ice.WEB_CACHE, "catch", "csv", arg[1]).Append("data")) case "list": // 词汇列表 diff --git a/misc/chrome/chrome.go b/misc/chrome/chrome.go new file mode 100644 index 00000000..cd7e86b0 --- /dev/null +++ b/misc/chrome/chrome.go @@ -0,0 +1,110 @@ +package crx + +import ( + "github.com/shylinux/icebergs" + "github.com/shylinux/icebergs/base/web" + "github.com/shylinux/icebergs/core/chat" + "github.com/shylinux/toolkits" +) + +var Index = &ice.Context{Name: "chrome", Help: "chrome", + Caches: map[string]*ice.Cache{}, + Configs: map[string]*ice.Config{ + "chrome": {Name: "chrome", Help: "chrome", Value: kit.Data(kit.MDB_SHORT, "name")}, + "history": {Name: "history", Help: "history", Value: kit.Data(kit.MDB_SHORT, "name")}, + }, + Commands: map[string]*ice.Command{ + ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Cmd(ice.CTX_CONFIG, "load", kit.Keys(m.Cap(ice.CTX_FOLLOW), "json")) + }}, + ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Cmd(ice.CTX_CONFIG, "save", kit.Keys(m.Cap(ice.CTX_FOLLOW), "json"), kit.Keys(m.Cap(ice.CTX_FOLLOW), "history")) + }}, + + "/crx": {Name: "/crx", Help: "/crx", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + switch arg[0] { + case "history": + m.Cmdy("history", arg[1:]) + } + }}, + "chrome": {Name: "chrome", Help: "标签", List: kit.List( + kit.MDB_INPUT, "text", "name", "name", "action", "auto", + kit.MDB_INPUT, "text", "name", "wid", "action", "auto", + kit.MDB_INPUT, "text", "name", "url", + kit.MDB_INPUT, "button", "name", "查看", + kit.MDB_INPUT, "button", "name", "返回", "cb", "Last", + ), Meta: kit.Dict("detail", []string{"编辑", "goBack", "goForward", "duplicate", "reload", "remove"}), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) == 0 { + m.Richs(ice.WEB_SPACE, nil, "*", func(key string, value map[string]interface{}) { + if kit.Format(value["type"]) == "chrome" { + m.Push(key, value, []string{"time", "name"}) + } + }) + return + } + + if arg[0] == "action" { + m.Cmdy(ice.WEB_SPACE, m.Option("name"), "tabs", m.Option("tid"), arg[1]) + arg = []string{m.Option("name"), m.Option("wid")} + } + + m.Cmdy(ice.WEB_SPACE, arg[0], "wins", arg[1:]) + }}, + "cookie": {Name: "cookie", Help: "数据", List: kit.List( + kit.MDB_INPUT, "text", "name", "name", "action", "auto", + kit.MDB_INPUT, "text", "name", "id", "action", "auto", + kit.MDB_INPUT, "button", "name", "查看", + kit.MDB_INPUT, "button", "name", "返回", "cb", "Last", + ), Meta: kit.Dict("detail", []string{"编辑", "删除"}), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) == 0 { + m.Richs(ice.WEB_SPACE, nil, "*", func(key string, value map[string]interface{}) { + if kit.Format(value["type"]) == "chrome" { + m.Push(key, value, []string{"time", "name"}) + } + }) + return + } + + if arg[0] == "action" { + m.Cmdy(ice.WEB_SPACE, m.Option("name"), "cookie", arg[1:]) + arg = []string{m.Option("name"), m.Option("id")} + } + + m.Cmdy(ice.WEB_SPACE, arg[0], "cookie", arg[1:]) + }}, + "history": {Name: "history id url title", Help: "历史", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) == 0 { + m.Grows("history", nil, "", "", func(index int, value map[string]interface{}) { + m.Push("", value) + }) + m.Sort("id", "int_r") + return + } + m.Grow("history", nil, kit.Dict("hid", arg[0], "url", arg[1], "title", arg[2])) + }}, + "bookmark": {Name: "bookmark", Help: "书签", List: kit.List( + kit.MDB_INPUT, "text", "name", "name", "action", "auto", + kit.MDB_INPUT, "text", "name", "id", "action", "auto", + kit.MDB_INPUT, "button", "name", "查看", + kit.MDB_INPUT, "button", "name", "返回", "cb", "Last", + ), Meta: kit.Dict("detail", []string{"编辑", "删除"}), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) == 0 { + m.Richs(ice.WEB_SPACE, nil, "*", func(key string, value map[string]interface{}) { + if kit.Format(value["type"]) == "chrome" { + m.Push(key, value, []string{"time", "name"}) + } + }) + return + } + + if arg[0] == "action" { + m.Cmdy(ice.WEB_SPACE, m.Option("name"), "bookmark", arg[1:]) + arg = []string{m.Option("name"), m.Option("id")} + } + + m.Cmdy(ice.WEB_SPACE, arg[0], "bookmark", arg[1:]) + }}, + }, +} + +func init() { chat.Index.Register(Index, &web.Frame{}) } diff --git a/misc/chrome/chrome.md b/misc/chrome/chrome.md new file mode 100644 index 00000000..bced8432 --- /dev/null +++ b/misc/chrome/chrome.md @@ -0,0 +1 @@ +# {{title "crx"}} diff --git a/misc/chrome/shy.log b/misc/chrome/shy.log new file mode 100644 index 00000000..84636502 --- /dev/null +++ b/misc/chrome/shy.log @@ -0,0 +1,140 @@ +2020-02-05 02:22:41 input v 21 53 +2020-02-05 02:22:41 input o 21 54 +2020-02-05 02:22:41 input l 21 55 +2020-02-05 02:22:41 input c 21 56 +2020-02-05 02:22:41 input a 21 57 +2020-02-05 02:22:42 input n 21 58 +2020-02-05 02:22:42 input o 21 59 +2020-02-05 02:22:42 input s 21 60 +2020-02-05 02:22:50 input l 22 46 +2020-02-05 02:22:50 input o 22 47 +2020-02-05 02:22:50 input c 22 48 +2020-02-05 02:22:50 input a 22 49 +2020-02-05 02:22:50 input l 22 50 +2020-02-05 02:22:50 input h 22 51 +2020-02-05 02:22:50 input o 22 52 +2020-02-05 02:22:51 input s 22 53 +2020-02-05 02:22:51 input t 22 54 +2020-02-05 02:22:51 input : 22 55 +2020-02-05 02:22:52 input 9 22 56 +2020-02-05 02:22:52 input 0 22 57 +2020-02-05 02:22:52 input 2 22 58 +2020-02-05 02:22:52 input 0 22 59 +2020-02-05 10:48:58 input c 10 33 +2020-02-05 10:48:58 input r 10 34 +2020-02-05 10:48:59 input h 10 35 +2020-02-05 10:48:59 input o 10 36 +2020-02-05 10:48:59 input m 10 37 +2020-02-05 10:48:59 input e 10 38 +2020-02-05 10:49:00 input c 10 33 +2020-02-05 10:49:00 input h 10 34 +2020-02-05 10:49:01 input r 10 35 +2020-02-05 10:49:01 input o 10 36 +2020-02-05 10:49:01 input m 10 37 +2020-02-05 10:49:01 input e 10 38 +2020-02-05 10:49:02 input c 10 49 +2020-02-05 10:49:02 input r 10 50 +2020-02-05 10:49:02 input h 10 51 +2020-02-05 10:49:02 input o 10 52 +2020-02-05 10:49:02 input m 10 53 +2020-02-05 10:49:02 input e 10 54 +2020-02-05 10:49:02 input c 10 49 +2020-02-05 10:49:02 input h 10 50 +2020-02-05 10:49:02 input r 10 51 +2020-02-05 10:49:02 input o 10 52 +2020-02-05 10:49:02 input m 10 53 +2020-02-05 10:49:02 input e 10 54 +2020-02-05 10:49:04 input c 13 4 +2020-02-05 10:49:04 input r 13 5 +2020-02-05 10:49:04 input h 13 6 +2020-02-05 10:49:04 input o 13 7 +2020-02-05 10:49:04 input m 13 8 +2020-02-05 10:49:04 input e 13 9 +2020-02-05 10:49:04 input c 13 4 +2020-02-05 10:49:04 input h 13 5 +2020-02-05 10:49:04 input r 13 6 +2020-02-05 10:49:04 input o 13 7 +2020-02-05 10:49:04 input m 13 8 +2020-02-05 10:49:04 input e 13 9 +2020-02-05 10:49:05 input c 13 21 +2020-02-05 10:49:05 input r 13 22 +2020-02-05 10:49:05 input h 13 23 +2020-02-05 10:49:05 input o 13 24 +2020-02-05 10:49:05 input m 13 25 +2020-02-05 10:49:05 input e 13 26 +2020-02-05 10:49:05 input c 13 21 +2020-02-05 10:49:05 input h 13 22 +2020-02-05 10:49:05 input r 13 23 +2020-02-05 10:49:05 input o 13 24 +2020-02-05 10:49:05 input m 13 25 +2020-02-05 10:49:05 input e 13 26 +2020-02-05 10:49:05 input c 13 37 +2020-02-05 10:49:05 input r 13 38 +2020-02-05 10:49:05 input h 13 39 +2020-02-05 10:49:05 input o 13 40 +2020-02-05 10:49:05 input m 13 41 +2020-02-05 10:49:05 input e 13 42 +2020-02-05 10:49:05 input c 13 37 +2020-02-05 10:49:05 input h 13 38 +2020-02-05 10:49:05 input r 13 39 +2020-02-05 10:49:05 input o 13 40 +2020-02-05 10:49:05 input m 13 41 +2020-02-05 10:49:05 input e 13 42 +2020-02-05 10:49:06 input c 19 31 +2020-02-05 10:49:06 input r 19 32 +2020-02-05 10:49:06 input h 19 33 +2020-02-05 10:49:06 input o 19 34 +2020-02-05 10:49:06 input m 19 35 +2020-02-05 10:49:06 input e 19 36 +2020-02-05 10:49:06 input c 19 31 +2020-02-05 10:49:06 input h 19 32 +2020-02-05 10:49:06 input r 19 33 +2020-02-05 10:49:06 input o 19 34 +2020-02-05 10:49:06 input m 19 35 +2020-02-05 10:49:06 input e 19 36 +2020-02-05 10:49:07 input c 22 4 +2020-02-05 10:49:07 input r 22 5 +2020-02-05 10:49:07 input h 22 6 +2020-02-05 10:49:07 input o 22 7 +2020-02-05 10:49:07 input m 22 8 +2020-02-05 10:49:07 input e 22 9 +2020-02-05 10:49:07 input c 22 4 +2020-02-05 10:49:07 input h 22 5 +2020-02-05 10:49:07 input r 22 6 +2020-02-05 10:49:07 input o 22 7 +2020-02-05 10:49:07 input m 22 8 +2020-02-05 10:49:07 input e 22 9 +2020-02-05 10:49:07 input c 22 21 +2020-02-05 10:49:07 input r 22 22 +2020-02-05 10:49:07 input h 22 23 +2020-02-05 10:49:07 input o 22 24 +2020-02-05 10:49:07 input m 22 25 +2020-02-05 10:49:07 input e 22 26 +2020-02-05 10:49:07 input c 22 21 +2020-02-05 10:49:07 input h 22 22 +2020-02-05 10:49:07 input r 22 23 +2020-02-05 10:49:07 input o 22 24 +2020-02-05 10:49:07 input m 22 25 +2020-02-05 10:49:07 input e 22 26 +2020-02-05 10:49:08 input c 22 37 +2020-02-05 10:49:08 input r 22 38 +2020-02-05 10:49:08 input h 22 39 +2020-02-05 10:49:08 input o 22 40 +2020-02-05 10:49:08 input m 22 41 +2020-02-05 10:49:08 input e 22 42 +2020-02-05 10:49:08 input c 22 37 +2020-02-05 10:49:08 input h 22 38 +2020-02-05 10:49:08 input r 22 39 +2020-02-05 10:49:08 input o 22 40 +2020-02-05 10:49:08 input m 22 41 +2020-02-05 10:49:08 input e 22 42 +2020-02-05 10:49:13 input c 19 5 +2020-02-05 10:49:14 input r 19 6 +2020-02-05 10:49:14 input x 19 7 +2020-02-05 10:49:17 input c 19 20 +2020-02-05 10:49:17 input r 19 21 +2020-02-05 10:49:18 input x 19 22 +2020-02-05 10:49:22 input / 19 33 +2020-02-05 10:49:22 input c 19 34 +2020-02-05 10:49:22 input r 19 35 +2020-02-05 10:49:23 input x 19 36 diff --git a/type.go b/type.go index c6e81b6e..f6cc7f54 100644 --- a/type.go +++ b/type.go @@ -102,7 +102,7 @@ func (c *Context) Register(s *Context, x Server) *Context { } func (c *Context) Spawn(m *Message, name string, help string, arg ...string) *Context { - s := &Context{Name: name, Help: help, Caches: map[string]*Cache{}} + s := &Context{Name: name, Help: help, Caches: map[string]*Cache{}, Configs: map[string]*Config{}} if m.target.Server != nil { c.Register(s, m.target.server.Spawn(m, s, arg...)) } else { @@ -141,7 +141,9 @@ func (c *Context) Start(m *Message, arg ...string) bool { wait <- true c.server.Start(m, arg...) c.Cap(CTX_STATUS, "close") - m.Done() + if m.Done(); m.wait != nil { + m.wait <- true + } }) <-wait return true @@ -169,9 +171,10 @@ type Message struct { source *Context target *Context - cb func(*Message) *Message - W http.ResponseWriter - R *http.Request + cb func(*Message) *Message + W http.ResponseWriter + R *http.Request + wait chan bool } func (m *Message) Time(args ...interface{}) string { @@ -362,7 +365,9 @@ func (m *Message) Set(key string, arg ...string) *Message { delete(m.meta, key) case MSG_OPTION, MSG_APPEND: if len(arg) > 0 { - delete(m.meta, arg[0]) + if delete(m.meta, arg[0]); len(arg) == 1 { + return m + } } else { for _, k := range m.meta[key] { delete(m.meta, k) @@ -538,8 +543,8 @@ func (m *Message) Table(cbs ...interface{}) *Message { } // 回调函数 - rows := kit.Select(" ", m.Option("table.row_sep")) - cols := kit.Select("\n", m.Option("table.col_sep")) + rows := kit.Select("\n", m.Option("table.row_sep")) + cols := kit.Select(" ", m.Option("table.col_sep")) compact := kit.Select(m.Conf("table", "compact"), m.Option("table.compact")) == "true" cb := func(maps map[string]string, lists []string, line int) bool { for i, v := range lists { @@ -822,8 +827,11 @@ func (m *Message) Start(key string, arg ...string) *Message { }) return m } + func (m *Message) Starts(name string, help string, arg ...string) *Message { + m.wait = make(chan bool) m.target.Spawn(m, name, help, arg...).Begin(m, arg...).Start(m, arg...) + <-m.wait return m } func (m *Message) Call(sync bool, cb func(*Message) *Message) *Message { @@ -925,17 +933,21 @@ func (m *Message) Search(key interface{}, cb interface{}) *Message { switch cb := cb.(type) { case func(p *Context, s *Context, key string, cmd *Command): - for c := p; c != nil; c = c.context { - if cmd, ok := c.Commands[key]; ok { - cb(c.context, c, key, cmd) - break + for _, p = range []*Context{p, m.target, m.source} { + for c := p; c != nil; c = c.context { + if cmd, ok := c.Commands[key]; ok { + cb(c, p, key, cmd) + return m + } } } case func(p *Context, s *Context, key string, conf *Config): - for c := p; c != nil; c = c.context { - if cmd, ok := c.Configs[key]; ok { - cb(c.context, c, key, cmd) - break + for _, p = range []*Context{p, m.target, m.source} { + for c := p; c != nil; c = c.context { + if cmd, ok := c.Configs[key]; ok { + cb(c.context, c, key, cmd) + break + } } } case func(p *Context, s *Context, key string): @@ -1069,8 +1081,9 @@ func (m *Message) Grow(key string, chain interface{}, data interface{}) int { // 通用数据 id := kit.Int(meta["count"]) + 1 prefix := kit.Select("", "meta.", kit.Value(data, "meta") != nil) - kit.Value(data, prefix+kit.MDB_TIME, m.Time()) - kit.Value(data, prefix+kit.MDB_ID, id) + if kit.Value(data, prefix+kit.MDB_ID, id); kit.Value(data, prefix+kit.MDB_TIME) == nil { + kit.Value(data, prefix+kit.MDB_TIME, m.Time()) + } // 添加数据 list = append(list, data) @@ -1298,7 +1311,7 @@ func (m *Message) Cmd(arg ...interface{}) *Message { if you := m.Option(kit.Format(kit.Value(cmd.Meta, "remote"))); you != "" { msg.Copy(msg.Spawns(c).Cmd(WEB_SPACE, you, list[0], list[1:])) } else { - c.Run(msg, cmd, key, list[1:]...) + p.Run(msg, cmd, key, list[1:]...) } m.Hand, msg.Hand = true, true })