From 48bedf9b2cd6e7ca51f469a51fb653916c70d213 Mon Sep 17 00:00:00 2001 From: jingganjiaoyu Date: Sun, 28 Jul 2024 23:20:53 +0800 Subject: [PATCH] opt portal --- Makefile | 5 +- README.md | 10 ++-- etc/init.shy | 2 - etc/miss.sh | 4 +- go.mod | 2 +- src/jiaowuxitong/class.go | 10 ++-- src/jiaowuxitong/common.go | 12 +--- src/jiaowuxitong/events.go | 31 ++++++++++ src/jiaowuxitong/model/model.go | 15 +---- src/jiaowuxitong/portal.css | 16 +----- src/jiaowuxitong/portal.go | 46 +++++++++------ src/jiaowuxitong/portal.js | 83 +++++---------------------- src/jiaowuxitong/portal.json | 6 +- src/jiaowuxitong/school.go | 6 +- src/jiaowuxitong/sess.go | 27 --------- src/jiaowuxitong/user.go | 30 ---------- src/main.go | 2 +- src/template/web.code.autogen/demo.go | 13 +++++ 18 files changed, 111 insertions(+), 209 deletions(-) create mode 100644 src/jiaowuxitong/events.go delete mode 100644 src/jiaowuxitong/sess.go delete mode 100644 src/jiaowuxitong/user.go create mode 100644 src/template/web.code.autogen/demo.go diff --git a/Makefile b/Makefile index 5a0c2bb..902290b 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,13 @@ binarys = bin/ice.bin version = src/version.go binpack = src/binpack.go +option = src/option.go flags = -ldflags "-w -s" -v all: def @date +"%Y-%m-%d %H:%M:%S" - go build ${flags} -o ${binarys} src/main.go ${version} ${binpack} && ./${binarys} forever restart &>/dev/null + go build ${flags} -o ${binarys} src/main.go ${option} ${version} ${binpack} && ./${binarys} forever restart &>/dev/null def: @[ -f ${version} ] || echo "package main">${version} - @[ -f ${binpack} ] || echo "package main">${binpack} \ No newline at end of file + @[ -f ${binpack} ] || echo "package main">${binpack} diff --git a/README.md b/README.md index c121437..2879cb2 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -# Contexts -Contexts 通过模块化、集群化、自动化的方式,只用一个 20M 大小的程序文件,就可以在各种设备上,一键启动完整的云计算服务与云研发环境。 +# Education +Education 通过模块化、集群化、自动化的方式,只用一个 20M 大小的程序文件,就可以在各种设备上,一键启动完整的云计算服务与云研发环境。 ## 源码安装 ### 克隆编译 ```sh -git clone https://shylinux.com/x/contexts -cd contexts; source etc/miss.sh +git clone https://shylinux.com/x/education +cd education; source etc/miss.sh ``` ### 启动服务 @@ -16,4 +16,4 @@ ish_miss_serve ### 访问网页 ```sh open http://localhost:9020 -``` \ No newline at end of file +``` diff --git a/etc/init.shy b/etc/init.shy index 04bf329..6de1689 100644 --- a/etc/init.shy +++ b/etc/init.shy @@ -1,4 +1,2 @@ -~web.code.db - config database driver mysql ~ssh source local.shy diff --git a/etc/miss.sh b/etc/miss.sh index 55e537d..80c53f0 100644 --- a/etc/miss.sh +++ b/etc/miss.sh @@ -12,4 +12,6 @@ ish_miss_prepare_project ish_miss_prepare_contexts ish_miss_prepare_resource -ish_miss_make; [ -z "$*" ] || ish_miss_serve "$@" \ No newline at end of file +ish_miss_prepare community + +ish_miss_make; [ -z "$*" ] || ish_miss_serve "$@" diff --git a/go.mod b/go.mod index 61b6f9c..c29774e 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module shylinux.com/x/education -go 1.13 +go 1.20 require ( shylinux.com/x/golang-story v0.0.23 diff --git a/src/jiaowuxitong/class.go b/src/jiaowuxitong/class.go index fa27112..e4e83cd 100644 --- a/src/jiaowuxitong/class.go +++ b/src/jiaowuxitong/class.go @@ -2,17 +2,15 @@ package jiaowuxitong import ( "shylinux.com/x/ice" - "shylinux.com/x/icebergs/base/mdb" + + "shylinux.com/x/education/src/jiaowuxitong/model" ) -type Class struct { - Table - create string `name:"create school_uid* grade* name*"` -} +type Class struct{ Table } func (s Class) Inputs(m *ice.Message, arg ...string) { switch arg[0] { - case mdb.NAME: + case model.NAME: m.Push(arg[0], "高一二班") m.Push(arg[0], "高二三班") m.Push(arg[0], "初一一班") diff --git a/src/jiaowuxitong/common.go b/src/jiaowuxitong/common.go index 3e1310b..95cf9cd 100644 --- a/src/jiaowuxitong/common.go +++ b/src/jiaowuxitong/common.go @@ -1,10 +1,7 @@ package jiaowuxitong import ( - "strings" - "shylinux.com/x/ice" - "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/web" kit "shylinux.com/x/toolkits" @@ -14,7 +11,6 @@ import ( type Table struct { db.Table - create string `name:"create name*"` } func (s Table) Init(m *ice.Message, arg ...string) { @@ -22,16 +18,14 @@ func (s Table) Init(m *ice.Message, arg ...string) { } func (s Table) Inputs(m *ice.Message, arg ...string) { switch arg[0] { - case model.USER_UID, model.CLASS_UID, model.SCHOOL_UID: - m.Optionv(mdb.SELECT, model.UID, model.NAME) - m.Cmdy(m.Prefix(strings.TrimSuffix(arg[0], "_uid"))).RenameAppend(model.UID, arg[0]) - m.DisplayInputKeyNameIconTitle() - case GRADE: + case model.GRADE: y := kit.Int(kit.Split(m.Time(), "-")[0]) for i := 0; i < 10; i++ { m.Push(arg[0], kit.Format("%d级", y)) y-- } + default: + s.Table.Inputs(m, arg...) } } diff --git a/src/jiaowuxitong/events.go b/src/jiaowuxitong/events.go new file mode 100644 index 0000000..16aa96b --- /dev/null +++ b/src/jiaowuxitong/events.go @@ -0,0 +1,31 @@ +package jiaowuxitong + +import ( + "shylinux.com/x/ice" + kit "shylinux.com/x/toolkits" + + "shylinux.com/x/community/src/gonganxitong" + "shylinux.com/x/education/src/jiaowuxitong/model" +) + +const ( + EVENT_CLASS_CREATE = "web.team.education.class.create" + EVENT_CLASS_REMOVE = "web.team.education.class.remove" +) + +type events struct { + user gonganxitong.User + portal portal + classCreate string `name:"classCreate" event:"web.team.education.class.create"` + classRemove string `name:"classRemove" event:"web.team.education.class.remove"` +} + +func (s events) ClassCreate(m *ice.Message, arg ...string) { s.classEvent(m, "班级创建成功") } +func (s events) ClassRemove(m *ice.Message, arg ...string) { s.classEvent(m, "班级删除成功") } + +func init() { ice.Cmd(prefixKey(), events{}) } + +func (s events) classEvent(m *ice.Message, arg ...string) { + m.Cmd(s.user, s.user.SendTemplate, m.MergePodCmd("", ice.GetTypeKey(s.portal))+"#"+m.Option(model.CLASS_UID), + m.Trans(m.ActionKey(), arg[0]), m.Option(model.CLASS_NAME), kit.Cut(m.Option(model.CLASS_UID), 8)) +} diff --git a/src/jiaowuxitong/model/model.go b/src/jiaowuxitong/model/model.go index c814966..2b39657 100644 --- a/src/jiaowuxitong/model/model.go +++ b/src/jiaowuxitong/model/model.go @@ -10,25 +10,12 @@ const ( NAME = "name" GRADE = "grade" USER_UID = "user_uid" - USER_NAME = "user_name" CLASS_UID = "class_uid" CLASS_NAME = "class_name" SCHOOL_UID = "school_uid" SCHOOL_NAME = "school_name" ) -type Sess struct { - db.ModelWithUID - UserUID string `gorm:"type:char(32)"` - IP string `gorm:"type:char(16)"` - Agent string `gorm:"size:char(256)"` -} -type User struct { - db.ModelWithUID - OpenID string `gorm:"type:char(32)"` - Avatar string `gorm:"size:char(256)"` - Name string `gorm:"type:char(32)"` -} type UserClass struct { db.Model UserUID string `gorm:"type:char(32);index"` @@ -55,7 +42,7 @@ type Homework struct { type models struct{ db.Models } func (s models) Init(m *ice.Message, arg ...string) { - s.Models.Register(m, &Sess{}, &User{}, &UserClass{}, &Class{}, &School{}, &Homework{}) + s.Models.Register(m, "jiaowuxitong", &UserClass{}, &Class{}, &School{}, &Homework{}) } func init() { ice.Cmd("web.team.education.jiaowuxitong.models", models{}) } diff --git a/src/jiaowuxitong/portal.css b/src/jiaowuxitong/portal.css index 319fa60..fbeacba 100644 --- a/src/jiaowuxitong/portal.css +++ b/src/jiaowuxitong/portal.css @@ -1,15 +1 @@ -$output { background-color:var(--plugin-bg-color); } -$output>div.list { border-radius:10px; background-color:var(--output-bg-color); padding:10px; margin:10px; } -$output>div.list>div.title { font-weight:bold; display:flex; align-items:center; } -$output>div.list>div.title span:first-child { flex-grow:1; } -$output>div.list>div.item.card { padding:10px 0; display:flex; } -$output>div.list>div.item.card>img { height:36px; } -$output>div.list>div.item.card div.title { font-size:16px; } -$output>div.list>div.item.card div.title span { margin-right:5px; } -$output>div.list>div.item.card div.status { color:var(--disable-fg-color); font-size:12px; } -$output>div.list>div.item.card div.status span { margin-right:5px; } -$output>div.list>div.item.index { padding:10px; display:flex; flex-direction:column; align-items:center; float:left; } -$output>div.list>div.item.index img { width:100%; } -$output>div.action div.item.button { margin-right:5px; } -$output>div.action div.item.button input { border:none; color:var(--notice-bg-color); min-width:80px; float:left; } -$output>div.action div.item.button span { display:none; } \ No newline at end of file +$output { background-color:var(--plugin-bg-color); } \ No newline at end of file diff --git a/src/jiaowuxitong/portal.go b/src/jiaowuxitong/portal.go index 3dda180..85c4cd7 100644 --- a/src/jiaowuxitong/portal.go +++ b/src/jiaowuxitong/portal.go @@ -6,16 +6,16 @@ import ( "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/toolkits" + "shylinux.com/x/community/src/gonganxitong" "shylinux.com/x/education/src/jiaowuxitong/model" ) type portal struct { - ice.Hash - Class Class + gonganxitong.Portal + user gonganxitong.User userClass userClass - export string `data:"true"` - short string `data:"index"` - field string `data:"time,name,icons,index,order,enable"` + Class Class + school school list string `name:"list class_uid index uid auto" role:"void"` classCreate string `name:"classCreate school_uid* grade* name*" role:"void"` classRemove string `name:"classRemove class_uid*" role:"void"` @@ -26,32 +26,40 @@ func (s portal) Inputs(m *ice.Message, arg ...string) { } func (s portal) List(m *ice.Message, arg ...string) { if len(arg) == 0 { - m.Cmdy(s.userClass, s.userClass.MyClass, s.UserUID(m)).Action(s.ClassCreate).PushAction(s.ClassRemove) + m.Cmdy(s.userClass, s.userClass.MyClass, s.user.UserUID(m)).Action(s.ClassCreate).PushAction(s.ClassRemove) kit.If(m.Length() == 0, func() { m.EchoInfoButton(m.Trans("Please Create Your Class", "请创建班级"), s.ClassCreate) }) - } else if len(arg) == 1 { - s.Hash.List(m, arg[1:]...).SortInt(mdb.ORDER) - } else if len(arg) == 2 { - m.Cmdy(ctx.COMMAND, arg[1]).Push(ctx.ARGS, arg[0]) + m.Display("").DisplayCSS("") } else { - m.FieldsSetDetail().Cmdy(arg[1], mdb.SELECT, model.UID, arg[2]).PushAction().Action() + s.Portal.List(m, arg...) } - m.Display("").DisplayCSS("") } func (s portal) ClassCreate(m *ice.Message, arg ...string) { - if !m.Cmdy(s.Class, s.Class.Create, arg).IsErr() { - m.Cmdy(s.userClass, s.userClass.Create, model.USER_UID, s.UserUID(m), model.CLASS_UID, m.Result()) + m.ToastProcess() + msg := m.Cmd(s.school, s.school.Select, model.UID, m.Option(model.SCHOOL_UID)) + if !m.WarnNotFound(msg.Length() == 0, "school") { + if !m.Cmdy(s.Class, s.Class.Create, arg).IsErr() { + args := kit.Simple(model.USER_UID, s.user.UserUID(m), model.CLASS_UID, m.Result()) + m.Cmd(s.userClass, s.userClass.Create, args) + m.Event(EVENT_CLASS_CREATE, args, model.CLASS_NAME, m.Option(mdb.NAME)) + m.ProcessRefresh().ToastSuccess() + } } } func (s portal) ClassRemove(m *ice.Message, arg ...string) { - m.Cmdy(s.Class, s.Class.Delete, model.UID, m.Option(model.CLASS_UID)) - m.Cmdy(s.userClass, s.userClass.Delete, model.USER_UID, s.UserUID(m), model.CLASS_UID, m.Option(model.CLASS_UID)) + m.ToastProcess() + args := kit.Simple(model.USER_UID, s.user.UserUID(m), m.OptionSimple(model.CLASS_UID)) + msg := m.Cmd(s.userClass, s.userClass.Select, args) + if !m.WarnNotFound(msg.Length() == 0, "class") { + m.Cmdy(s.userClass, s.userClass.Delete, args) + m.Cmdy(s.Class, s.Class.Delete, model.UID, m.Option(model.CLASS_UID)) + m.Event(EVENT_CLASS_REMOVE, args) + m.ProcessRefresh().ToastSuccess() + } + } func init() { ice.Cmd(prefixKey(), portal{}) } -func (s portal) UserUID(m *ice.Message) string { - return m.Option(ice.MSG_USERNAME) -} func (s portal) Show(m *ice.Message, arg ...string) { cmd := m.GetCommand() m.Cmd(s, s.Create, mdb.NAME, cmd.Help, mdb.ICONS, cmd.Icon, ctx.INDEX, m.PrefixKey()) diff --git a/src/jiaowuxitong/portal.js b/src/jiaowuxitong/portal.js index 8091163..2b61d82 100644 --- a/src/jiaowuxitong/portal.js +++ b/src/jiaowuxitong/portal.js @@ -1,72 +1,17 @@ -var UID = "uid", CLASS_UID = "class_uid" +var UID = "uid", CLASS_UID = "class_uid", CLASS_NAME = "class_name" Volcanos(chat.ONIMPORT, { - _init: function(can, msg) { can.user.isMobile && can.isCmdMode() && can.onappend.style(can, html.OUTPUT) - if (can.Option(CLASS_UID) == "") { - if (can.db.hash.length > 1 && can.db.hash[0]) { return can.Option(CLASS_UID, can.db.hash[0]), can.Option(ctx.INDEX, can.db.hash[1]), can.Update() } - can.ui = can.page.Append(can, can._output, ["myclass.list", "myindex.list"]) - can.page.Append(can, can.ui.myclass, [{view: html.TITLE, list: [{text: can.user.trans(can, "My Class", "我的班级")}, can.page.button(can, "classCreate")]}]) - can.run({}, [can.onimport.myClass(can, msg, can.ui.myclass)], function(msg) { - can.page.Append(can, can.ui.myindex, [{view: html.TITLE, list: [{text: can.user.trans(can, "My Index", "我的课程")}]}]) - can.onimport.myIndex(can, msg, can.ui.myindex) - can.onimport.myIndex(can, msg, can.ui.myindex) - can.onimport.myIndex(can, msg, can.ui.myindex) - can.onimport.myIndex(can, msg, can.ui.myindex) - can.onimport.myIndex(can, msg, can.ui.myindex) - can.onimport.myIndex(can, msg, can.ui.myindex) - can.onimport.myIndex(can, msg, can.ui.myindex) - }) - } else { - can.onimport.myData(can, msg, can._output) - } - }, - myClass: function(can, msg, target) { var class_uid - can.page.Append(can, target||can._output, msg.Table(function(value) { - class_uid = class_uid||value.class_uid, value.class_uid == can.onexport.session(can, CLASS_UID) && (class_uid = value.class_uid) - class_uid == value.class_uid && can.onexport.title(can, value.class_name) - return {view: [[html.ITEM_CARD]], list: [ - {img: can.misc.ResourceIcons(can, value.icon)}, - {view: ice.INFO, list: [ - {view: html.TITLE, list: [{text: value.class_name}]}, - {view: html.STATUS, list: [{text: value.grade}, {text: value.school_name}]}, - ]}, - ], onclick: function(event) { - can.onexport.hash(can, value.class_uid), can.onexport.session(can, CLASS_UID, value.class_uid) - can.onexport.title(can, value.class_name), can.user.toastSuccess(can, "switch") - can.user.agent.init(can, can.user.info.titles) - }} - })), can.onexport.hash(can, class_uid), can.onexport.session(can, CLASS_UID, class_uid); return class_uid - }, - myIndex: function(can, msg, target) { - can.page.Append(can, target||can._output, msg.Table(function(value) { - var width; can.user.isMobile && !can.user.isLandscape() && (width = (can.ConfWidth()-40)/4) - return {view: [[html.ITEM, ctx.INDEX]], style: {width: width}, list: [ - {img: can.misc.ResourceIcons(can, value.icon)}, {text: can.user.trans(can, value.index.split(".").pop(), value.name)}, - ], onclick: function(event) { - can.Option(CLASS_UID, can.onexport.session(can, CLASS_UID)), can.Option(ctx.INDEX, value.index), can.Update() - }} - })) - }, - myData: function(can, msg, target) { - msg.Table(function(value) { function back() {} function refresh() {} - var list = [can.page.button(can, can.user.trans(can, "goback", "返回"), function(event) { back() }), can.page.button(can, can.user.trans(can, "reload", "刷新"), function(event) { refresh() })] - var ui = can.page.Append(can, can._output, [{view: html.ACTION}]) - if (can.db.hash.length > 2 && can.db.hash[0] && can.db.hash[2]) { value.args = [can.db.hash[0], can.db.hash[2]] } - value.style = html.OUTPUT, value.height = can.ConfHeight()-html.ACTION_HEIGHT - can.onappend.plugin(can, value, function(sub) { refresh = function() { sub.Update() } - sub.onexport.output = function(_sub, msg) { can.user.toastSuccess(can, "load", "", 1000) - can.page.Appends(can, ui.action, list), msg.Option(ice.MSG_ACTION) && can.onappend._action(sub, msg.Option(ice.MSG_ACTION), ui.action, null, true) - can.onexport.hash(can, can.Option(CLASS_UID), value.index, sub.Option(UID)) - back = function() { - if (sub.Option(UID)) { - can.onexport.hash(can, can.Option(CLASS_UID), can.Option(ctx.INDEX)) - sub.Option(UID, ""), sub.Update() - } else { - can.onexport.hash(can, "") - can.Option(CLASS_UID, ""), can.Option(ctx.INDEX, ""), can.Update() - } - } - } - }) + _init: function(can, msg) { + can.require([ + "usr/community/src/gonganxitong/portal.js", + "usr/community/src/gonganxitong/portal.css?render=replace&index="+can.ConfIndex(), + ], function() { + can.onimport.myPortal(can, msg, CLASS_UID, CLASS_NAME, "我的班级") }) }, -}) \ No newline at end of file + myValue: function(can, value) { + return [ + {view: html.TITLE, list: [{text: value.class_name}]}, + {view: html.STATUS, list: [{text: value.class_uid.slice(0, 8)}, {text: value.school_name}, {text: value.grade}]}, + ] + }, +}) diff --git a/src/jiaowuxitong/portal.json b/src/jiaowuxitong/portal.json index 61b2dd7..4a43402 100644 --- a/src/jiaowuxitong/portal.json +++ b/src/jiaowuxitong/portal.json @@ -9,10 +9,10 @@ "icons": { "classCreate": "bi bi-plus-square-dotted" }, + "style": { + "classRemove": "danger" + }, "input": { - "migrate": "迁移", - "uid": "主键", - "info": "信息", "address": "地址", "grade": "入学年份", "open_id": "外键", diff --git a/src/jiaowuxitong/school.go b/src/jiaowuxitong/school.go index cfce6f2..b77588c 100644 --- a/src/jiaowuxitong/school.go +++ b/src/jiaowuxitong/school.go @@ -2,13 +2,9 @@ package jiaowuxitong import "shylinux.com/x/ice" -const ( - GRADE = "grade" -) - type school struct { Table - create string `name:"create name* info address"` + create string `name:"create name* address info"` } func init() { ice.Cmd(prefixKey(), school{}) } diff --git a/src/jiaowuxitong/sess.go b/src/jiaowuxitong/sess.go deleted file mode 100644 index eb26955..0000000 --- a/src/jiaowuxitong/sess.go +++ /dev/null @@ -1,27 +0,0 @@ -package jiaowuxitong - -import ( - "shylinux.com/x/ice" - "shylinux.com/x/icebergs/base/aaa" - "shylinux.com/x/icebergs/base/web" - kit "shylinux.com/x/toolkits" - - "shylinux.com/x/education/src/jiaowuxitong/model" -) - -type sess struct { - Table - create string `name:"create user_uid*"` - check string `name:"check uid*"` -} - -func (s sess) Create(m *ice.Message, arg ...string) { - s.Table.Create(m, model.USER_UID, m.Option(model.USER_UID), aaa.IP, m.Option(ice.MSG_USERIP), web.AGENT, m.Option(ice.MSG_USERUA)) - m.ProcessCookie(ice.MSG_SESSID, kit.JoinWord(web.SPACE, m.Option(ice.MSG_USERPOD), m.PrefixKey(), aaa.CHECK, m.Result()), "-2") -} -func (s sess) Check(m *ice.Message, arg ...string) { - msg := s.Table.Select(m.Spawn(), model.UID, arg[0]) - m.Option(ice.MSG_USERNAME, msg.Append(model.USER_UID)) -} - -func init() { ice.Cmd(prefixKey(), sess{}) } diff --git a/src/jiaowuxitong/user.go b/src/jiaowuxitong/user.go deleted file mode 100644 index 1f08697..0000000 --- a/src/jiaowuxitong/user.go +++ /dev/null @@ -1,30 +0,0 @@ -package jiaowuxitong - -import ( - "shylinux.com/x/ice" - "shylinux.com/x/icebergs/base/mdb" - - "shylinux.com/x/education/src/jiaowuxitong/model" -) - -const ( - OPEN_ID = "open_id" - OPENID = "openid" - AVATAR = "avatar" -) - -type user struct { - Table - create string `name:"create openid*"` -} - -func (s user) Create(m *ice.Message, arg ...string) { - if s.Table.Select(m, OPEN_ID, m.Option(OPENID)).Length() == 0 { - s.Table.Create(m, OPEN_ID, m.Option(OPENID), AVATAR, m.Option("headimgurl"), mdb.NAME, m.Option("nickname")) - m.Option(model.USER_UID, m.Result()) - } else { - m.Option(model.USER_UID, m.Append(model.UID)) - } -} - -func init() { ice.Cmd(prefixKey(), user{}) } diff --git a/src/main.go b/src/main.go index 1ddac81..4dbfca8 100644 --- a/src/main.go +++ b/src/main.go @@ -9,4 +9,4 @@ import ( func main() { print(ice.Run()) } -func init() { ice.Info.Titles = "云教育" } +func init() { ice.Info.Titles = "云教育" } \ No newline at end of file diff --git a/src/template/web.code.autogen/demo.go b/src/template/web.code.autogen/demo.go new file mode 100644 index 0000000..4c052ab --- /dev/null +++ b/src/template/web.code.autogen/demo.go @@ -0,0 +1,13 @@ +package {{.Option "zone"}} + +import "shylinux.com/x/ice" + +type {{.Option "name"}} struct { + Table +} + +func (s {{.Option "name"}}) List(m *ice.Message, arg ...string) { + s.Table.List(m, arg...) +} + +func init() { ice.Cmd(prefixKey(), {{.Option "name"}}{}) }