diff --git a/base/web/share.go b/base/web/share.go
index 6ac01c00..fb4d7785 100644
--- a/base/web/share.go
+++ b/base/web/share.go
@@ -82,12 +82,12 @@ func init() {
m.EchoQRCode(m.Cmd(SHARE, mdb.CREATE, mdb.TYPE, LOGIN).Option(mdb.LINK)).ProcessInner()
}},
ctx.COMMAND: {Hand: func(m *ice.Message, arg ...string) {
- if msg := mdb.HashSelect(m.Spawn(), m.Option(SHARE)); !IsNotValidFieldShare(m, msg) {
- m.Cmdy(ctx.COMMAND, msg.Append(mdb.NAME))
+ if msg := mdb.HashSelects(m.Spawn(), m.Option(SHARE)); !IsNotValidFieldShare(m, msg) {
+ m.Cmdy(Space(m, msg.Append(SPACE)), ctx.COMMAND, msg.Append(mdb.NAME))
}
}},
ctx.RUN: {Hand: func(m *ice.Message, arg ...string) {
- if msg := mdb.HashSelect(m.Spawn(), m.Option(SHARE)); !IsNotValidFieldShare(m, msg) {
+ if msg := mdb.HashSelects(m.Spawn(), m.Option(SHARE)); !IsNotValidFieldShare(m, msg) {
aaa.SessAuth(m, kit.Dict(msg.AppendSimple(aaa.USERNICK, aaa.USERNAME, aaa.USERROLE)))
m.Cmdy(Space(m, msg.Append(SPACE)), msg.Append(mdb.NAME), arg[1:])
}
diff --git a/conf.go b/conf.go
index 4e4fbc72..ed700944 100644
--- a/conf.go
+++ b/conf.go
@@ -131,6 +131,7 @@ const ( // DIR
USR_INSTALL = "usr/install/"
USR_REQUIRE = "usr/require/"
USR_PUBLISH = "usr/publish/"
+ USR_PROGRAM = "usr/program/"
USR_PORTAL = "usr/portal/"
USR_LOCAL = "usr/local/"
USR_ICONS = "usr/icons/"
diff --git a/misc/wx/access.go b/misc/wx/access.go
index 41505ee3..62565357 100644
--- a/misc/wx/access.go
+++ b/misc/wx/access.go
@@ -137,6 +137,7 @@ func Meta() ice.Map {
SEX, "性别", TAGS, "标签", REMARK, "备注",
"subscribe", "订阅", "subscribe_time", "时间",
"nickname", "昵称", "headimgurl", "头像",
+ "projectname", "项目",
ENV, "环境", PAGES, "页面",
)))
}
diff --git a/misc/wx/ide.go b/misc/wx/ide.go
index 8d125769..07a05eb3 100644
--- a/misc/wx/ide.go
+++ b/misc/wx/ide.go
@@ -4,6 +4,7 @@ import (
"net/url"
"path"
"runtime"
+ "strings"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
@@ -15,17 +16,18 @@ import (
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web"
+ "shylinux.com/x/icebergs/core/code"
kit "shylinux.com/x/toolkits"
)
func _ide_args(m *ice.Message) (args []string) {
- args = append(kit.Split(m.Option(ctx.ARGS), "=&"), kit.Simple(kit.Dict(m.OptionSimple(web.SPACE, ctx.INDEX, log.DEBUG)))...)
+ args = append(kit.SplitQuery(m.Option(ctx.ARGS)), kit.Simple(kit.Dict(m.OptionSimple(web.SPACE, ctx.INDEX, log.DEBUG)))...)
kit.If(m.Option(tcp.WIFI), func(p string) { args = append(args, m.Cmd(tcp.WIFI, p).AppendSimple(tcp.SSID, aaa.PASSWORD)...) })
return
}
func _ide_args_cli(m *ice.Message) []string {
return []string{"--project", kit.Path(mdb.Config(m, PROJECT)), "--compile-condition", kit.Format(kit.Dict(
- "pathName", m.Option(PAGES), "query", kit.JoinKV("=", "&", kit.Simple(kit.Dict(web.SERVE, url.QueryEscape(web.UserHost(m)), _ide_args(m)))...),
+ "pathName", m.Option(PAGES), "query", kit.JoinQuery(kit.Simple(kit.Dict(web.SERVE, url.QueryEscape(web.UserHost(m)), _ide_args(m)))...),
))}
}
func _ide_args_qrcode(m *ice.Message, p string) []string {
@@ -33,7 +35,10 @@ func _ide_args_qrcode(m *ice.Message, p string) []string {
}
const (
- PAGES_ACTION = "pages/action/action"
+ PAGES_RIVER = "pages/river/river"
+ PAGES_ACTION = "pages/action/action"
+ PAGES_INSERT = "pages/insert/insert"
+ PUBLISH_CLIENT_MP = "publish/client/mp"
)
const (
PROJECT = "project"
@@ -55,12 +60,43 @@ func init() {
)
Index.MergeCommands(ice.Commands{
IDE: {Name: "ide hash auto", Help: "集成开发环境", Meta: Meta(), Actions: ice.MergeActions(ice.Actions{
- ice.APP: {Help: "应用", Hand: func(m *ice.Message, arg ...string) {
- IdeCli(m, cli.OPEN, "--project", kit.Path(mdb.Config(m, PROJECT)))
+ code.AUTOGEN: {Name: "autogen projectname*=demo appid*='wxf4e5104d83476ed6' serve*='https://2021.shylinux.com'", Help: "生成", Hand: func(m *ice.Message, arg ...string) {
+ const (
+ CONF_JS = "conf.js"
+ APP_JSON = "app.json"
+ PROJECT_CONFIG_JSON = "project.config.json"
+ PROJECT_PRIVATE_CONFIG_JSON = "project.private.config.json"
+ )
+ p, mp := ice.USR_PROGRAM, ice.USR_VOLCANOS+PUBLISH_CLIENT_MP
+ nfs.DirDeepAll(m, mp, "", func(value ice.Maps) {
+ if !kit.IsIn(value[nfs.PATH], PROJECT_CONFIG_JSON, PROJECT_PRIVATE_CONFIG_JSON) {
+ m.Cmd(nfs.COPY, p+value[nfs.PATH], path.Join(mp, value[nfs.PATH]), ice.Maps{nfs.DIR_ROOT: ""})
+ }
+ })
+ m.Cmd(nfs.SAVE, p+CONF_JS, `module.exports = `+kit.Formats(kit.Dict(
+ m.OptionSimple(APPID, web.SERVE), nfs.MODULE, ice.Info.Make.Module, nfs.VERSION, ice.Info.Make.Versions(),
+ )))
+ m.Cmd(nfs.DEFS, p+PROJECT_CONFIG_JSON, kit.Formats(kit.Dict(m.OptionSimple(APPID, "projectname"))))
+ list := []string{}
+ m.Travel(func(_ *ice.Context, s *ice.Context, key string, cmd *ice.Command) {
+ if h, ok := cmd.Actions[PAGES]; ok {
+ prefix := strings.ReplaceAll(s.Prefix(), nfs.PT, "-")
+ file := strings.TrimPrefix(m.Resource(kit.Select(key+".js", h.Name)), nfs.REQUIRE)
+ list = append(list, path.Join(PAGES, prefix, kit.TrimExt(path.Base(file), nfs.JS)))
+ kit.For([]string{WXML, WXSS, nfs.JS}, func(ext string) {
+ file = kit.ExtChange(file, ext)
+ m.Cmd(nfs.COPY, path.Join(p, PAGES, prefix, path.Base(file)), file)
+ })
+ }
+ })
+ app := kit.UnMarshal(m.Cmdx(nfs.CAT, p+APP_JSON))
+ kit.Value(app, PAGES, kit.AddUniq(kit.Simple(kit.Value(app, PAGES)), list...))
+ m.Cmd(nfs.SAVE, p+APP_JSON, kit.Formats(app))
+ IdeCli(m.Sleep3s(), cli.OPEN, "--project", kit.Path(mdb.Config(m, PROJECT, p)))
}},
aaa.LOGIN: {Help: "登录", Hand: func(m *ice.Message, arg ...string) {
p := nfs.TempName(m)
- m.GoSleep("1s", func() { web.PushNoticeGrow(m, ice.Render(m, ice.RENDER_IMAGES, web.SHARE_LOCAL+p)) })
+ m.GoSleep3s(func() { web.PushNoticeGrow(m, ice.Render(m, ice.RENDER_IMAGES, web.SHARE_LOCAL+p)) })
IdeCli(m, "", _ide_args_cli(m), _ide_args_qrcode(m, p)).ProcessRefresh()
}},
web.ADMIN: {Help: "后台", Hand: func(m *ice.Message, arg ...string) {
@@ -109,14 +145,15 @@ func init() {
}, mdb.ExportHashAction(
mdb.FIELD, "time,hash,name,pages,space,index,args,wifi",
cli.DARWIN, "/Applications/wechatwebdevtools.app/Contents/MacOS/cli",
- PROJECT, "usr/volcanos/publish/client/mp/",
)), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 && tcp.IsLocalHost(m, m.Option(ice.MSG_USERIP)) && kit.Value(kit.UnMarshal(IdeCli(m.Spawn(), ISLOGIN).Append(cli.CMD_OUT)), aaa.LOGIN) != true {
m.EchoInfoButton("请登录: ", aaa.LOGIN)
return
- }
- if mdb.HashSelect(m, arg...); tcp.IsLocalHost(m, m.Option(ice.MSG_USERIP)) {
- m.PushAction(AUTO_PREVIEW, PREVIEW, PUSH, mdb.REMOVE).Action(mdb.CREATE, ice.APP, aaa.LOGIN, web.ADMIN, DOC)
+ } else if !nfs.Exists(m, ice.USR_PROGRAM) {
+ m.EchoInfoButton("请生成项目: ", code.AUTOGEN)
+ return
+ } else if mdb.HashSelect(m, arg...); tcp.IsLocalHost(m, m.Option(ice.MSG_USERIP)) {
+ m.PushAction(AUTO_PREVIEW, PREVIEW, PUSH, mdb.REMOVE).Action(aaa.LOGIN, code.AUTOGEN, mdb.CREATE, web.ADMIN, DOC)
} else {
m.PushAction(PUSH, mdb.REMOVE).Action(mdb.CREATE, web.ADMIN, DOC)
}
@@ -127,6 +164,7 @@ func init() {
}
p := mdb.Config(m, CURRENT)
m.Table(func(value ice.Maps) { m.Push(mdb.STATUS, kit.Select("", CURRENT, value[mdb.HASH] == p)) })
+ m.StatusTimeCount(mdb.ConfigSimple(m, PROJECT))
}},
})
}
diff --git a/misc/wx/pages.go b/misc/wx/pages.go
index 24af1c7b..bff58dd4 100644
--- a/misc/wx/pages.go
+++ b/misc/wx/pages.go
@@ -11,7 +11,7 @@ import (
func init() {
web.Index.MergeCommands(ice.Commands{
- "/pages/": {Actions: aaa.WhiteAction(ctx.ACTION), Hand: func(m *ice.Message, arg ...string) {
+ web.PP(PAGES): {Actions: aaa.WhiteAction(ctx.ACTION), Hand: func(m *ice.Message, arg ...string) {
if len(arg[0]) == 0 || arg[0] == "" || arg[0] == chat.RIVER {
web.RenderMain(m)
} else {
diff --git a/misc/wx/scan.go b/misc/wx/scan.go
index 50de7f5d..84526009 100644
--- a/misc/wx/scan.go
+++ b/misc/wx/scan.go
@@ -71,6 +71,7 @@ func init() {
m.Echo(msg.Result())
}
}},
+ PAGES: {Name: "scan.js"},
}, mdb.ExportHashAction(mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,name,text,icons,space,index,args,type,image,link")), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 {
m.Cmdy(ACCESS).PushAction("").Option(ice.MSG_ACTION, "")
diff --git a/misc/wx/scan.js b/misc/wx/scan.js
new file mode 100644
index 00000000..fbe773e4
--- /dev/null
+++ b/misc/wx/scan.js
@@ -0,0 +1,127 @@
+const {ice, ctx, mdb, web, code, chat, http, html} = require("../../utils/const.js")
+const {shy, Volcanos} = require("../../utils/proto.js")
+Volcanos._page = {}
+Volcanos(chat.ONIMPORT, {
+ _init: function(can, msg) { can.ui.data.list = []
+ msg.Table(function(field, order) { can.ui.data.list.push(field)
+ field.feature = can.base.Obj(field.meta, {})
+ field.inputs = can.base.Obj(field.list, [])
+ field.name = can.core.Split(field.name)[0]
+ if (!field.inputs || field.inputs.length === 0) {
+ return can.core.Timer(30, function() {
+ can.onaction._refresh({}, can, order)
+ })
+ }
+ can.core.List(field.inputs, function(input) {
+ input.action = input.action || input.value
+ input.value == ice.AUTO && (input.value = "")
+ if (input.value && input.value.indexOf("@") == 0) {
+ input.action = input.value.slice(1), input.value = ""
+ }
+ if (input.type == html.SELECT) {
+ input.values = input.values || can.core.Split(input.value)
+ }
+ if (can.base.isIn(input.type, html.TEXT, html.TEXTAREA)) {
+ input.placeholder = can.user.trans(can, input.placeholder||input.name, field, html.INPUT)
+ }
+ if (input.type == html.BUTTON) {
+ input.value = can.user.trans(can, input.value||input.name, field)
+ } else {
+ if (can.db.cmd||can.db.index) { input.value = input.value||can.db[input.name] }
+ }
+ input.type == html.BUTTON && input.action == ice.AUTO && can.core.Timer(30, function() {
+ can.onaction._refresh({}, can, order)
+ })
+ })
+ }), can.page.setData(can), can.user.toast(can, "加载成功")
+ },
+})
+Volcanos(chat.ONACTION, {list: ["刷新", "扫码", "清屏"],
+ "刷新": function(event, can) { can.onaction.refresh(event, can) },
+ "扫码": function(event, can) { can.user.agent.scanQRCode(can) },
+ "清屏": function(event, can) { can.core.List(can.ui.data.list, function(item) { delete(item.msg) }), can.page.setData(can) },
+ _refresh: function(event, can, order) { can.page.setData(can)
+ can.onaction.onAction({}, can, ice.LIST, {order: order, name: ice.LIST})
+ },
+ refresh: function(event, can) { can.onaction._apis = "", can.onaction._cmds = []
+ if (can.db.share) { can.onaction._apis = "/share/"+can.db.share
+ can.run(event, [ctx.ACTION, ctx.COMMAND], function(msg) {
+ can.onaction._cmds = [ctx.ACTION, ctx.RUN], can.onimport._init(can, msg)
+ })
+ } else if (can.db.river && can.db.storm) {
+ can.onaction._cmds = [can.db.river, can.db.storm]
+ can.run(event, [], function(msg) { can.onimport._init(can, msg) })
+ } else {
+ can.run(event, [ctx.ACTION, ctx.COMMAND, can.db.cmd||can.db.index||"cli.qrcode"], function(msg) {
+ can.onaction._cmds = [ctx.ACTION, ctx.RUN], can.onimport._init(can, msg)
+ })
+ }
+ },
+ onaction: function(event, can, button, data) { var name = data.name;
+ (can.onaction[name]||function(event) { can.run(event, [ctx.ACTION, name]) })(event, can)
+ },
+ onInputs: function(event, can, button, data) { var order = data.order, index = data.index
+ var input = can.ui.data.list[order||0].inputs[index||0]
+ input.value = event.detail.value
+ },
+ onChange: function(event, can, button, data) { var order = data.order, index = data.index
+ var input = can.ui.data.list[order||0].inputs[index||0]
+ input.value = input.values[parseInt(event.detail.value)]
+ can.onaction._refresh(event, can, order)
+ },
+ onAction: function(event, can, button, data) { var order = data.order, name = data.name
+ var field = can.ui.data.list[order||0], msg = can.request(event)
+ if (field.feature[name]) { if (can.base.isIn(name, mdb.CREATE, mdb.INSERT)) { msg._method = http.PUT }
+ return can.data.insert = {field: field, name: name, list: field.feature[name], cb: function(res) {
+ can.run(event, can.base.Simple([field.id||field.index, ctx.ACTION, name], res), function(msg) {
+ can.onaction._refresh(event, can, order)
+ })
+ }}, can.user.jumps(chat.PAGES_INSERT)
+ } field._history = field._history||[]
+ switch (name) {
+ case ice.BACK: field._history.pop(); var ls = field._history.pop()||[], i = 0
+ can.core.List(field.inputs, function(input) { if (input.type != html.BUTTON) { input.value = ls[i++]||"" } })
+ can.onaction._refresh(event, can, order); break
+ case ctx.RUN: break
+ case ice.LIST:
+ case web.REFRESH: msg._method = http.GET; break
+ default: msg.Option(ctx.ACTION, name)
+ }
+ var cmd = can.core.List(field.inputs, function(input) { if (input.type != html.BUTTON) { return input.value } })
+ for (var i = cmd.length-1; i > 0; i--) { if (cmd[i] === "") { cmd.pop() } else { break } }
+ function eq(to, from) { if (!to) { return false } if (to.length != from.length) { return false }
+ for (var i = 0; i < to.length; i++) { if (to[i] != from[i]) { return false } } return true
+ } eq(field._history[field._history.length-1], cmd) || field._history.push(cmd)
+ can.run(event, [field.id||field.index].concat(cmd), function(msg) {
+ msg._head = can.core.List(msg.append, function(item) { return can.user.trans(can, item, field, html.INPUT) })
+ can.core.Item(msg._view, function(key, value) { can.core.List(value, function(value) { can.core.List(value, function(input, i) {
+ if (input.type == html.BUTTON) { input.value = can.user.trans(can, input.value||input.name, field) }
+ if (input._type == html.TEXT) { input._text = can.user.trans(can, input._text, field, html.VALUE) }
+ }) }) })
+ msg._status = can.core.List(can.base.Obj(msg.Option(ice.MSG_STATUS)), function(item) { return item })
+ msg._action = can.core.List(can.base.Obj(msg.Option(ice.MSG_ACTION)), function(item) {
+ if (typeof item == code.STRING) { return {type: html.BUTTON, name: item, value: can.user.trans(can, item)} }
+ return item.value = can.user.trans(can, item.value||item.name), item
+ }), field.msg = msg, can.page.setData(can)
+ })
+ },
+ onDetail: function(event, can, button, data) { var order = data.order, name = data.name, value = data.value, input = data.input
+ var field = can.ui.data.list[order||0]
+ if (input && input.type == html.BUTTON) { var msg = can.request(event, field.msg.Table()[data.index])
+ if (can.base.isIn(name, mdb.REMOVE, mdb.DELETE)) { msg._method = http.DELETE }
+ var _input = {}; can.core.List(field.inputs, function(input) { if (input.type != html.BUTTON) { _input[input.name] = input.value } }), can.request(event, _input)
+ if (field.feature[input.name]) {
+ can.onAction(event, can, input.name, {order: order, name: input.name})
+ } else {
+ can.run(event, [field.id||field.index, ctx.ACTION, input.name], function(msg) {
+ can.onaction._refresh(event, can, order)
+ })
+ } return
+ }
+ can.core.List(field.inputs, function(input) {
+ if (input.name == name) { input.value = value, can.onaction._refresh(event, can, order) }
+ })
+ },
+})
+Volcanos._init()
+
diff --git a/misc/wx/scan.wxml b/misc/wx/scan.wxml
new file mode 100644
index 00000000..408f7210
--- /dev/null
+++ b/misc/wx/scan.wxml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+ {{field.name}}({{field.help}})
+
+
+
+
+
+
+
+ {{item.value||item.values[item.index||0]}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.name}}: {{item.value}}
+
+
+
+
+
+
diff --git a/misc/wx/wxml.go b/misc/wx/wxml.go
index 6fc9bd5e..9d0a2e63 100644
--- a/misc/wx/wxml.go
+++ b/misc/wx/wxml.go
@@ -6,9 +6,11 @@ import (
kit "shylinux.com/x/toolkits"
)
+const WXML = "wxml"
+
func init() {
Index.MergeCommands(ice.Commands{
- "wxml": {Actions: code.PlugAction(code.PLUG, kit.Dict(
+ WXML: {Actions: code.PlugAction(code.PLUG, kit.Dict(
code.INCLUDE, code.HTML,
code.KEYWORD, kit.Dict(
"page", code.KEYWORD,
diff --git a/misc/wx/wxss.go b/misc/wx/wxss.go
index 9068c75e..acc918a0 100644
--- a/misc/wx/wxss.go
+++ b/misc/wx/wxss.go
@@ -6,9 +6,11 @@ import (
kit "shylinux.com/x/toolkits"
)
+const WXSS = "wxss"
+
func init() {
Index.MergeCommands(ice.Commands{
- "wxss": {Actions: code.PlugAction(code.PLUG, kit.Dict(
+ WXSS: {Actions: code.PlugAction(code.PLUG, kit.Dict(
code.INCLUDE, code.CSS,
code.KEYWORD, kit.Dict(
"page", code.KEYWORD,