This commit is contained in:
jingganjiaoyu 2024-08-09 00:04:04 +08:00
parent ec06d53508
commit 1e9a95ae42
43 changed files with 1260 additions and 74 deletions

View File

@ -69,7 +69,7 @@ func (s apply) List(m *ice.Message, arg ...string) {
}
})
s.UserPlace.RewriteAppend(m)
s.Display(m)
s.Display(m, "")
}
func (s apply) Cancel(m *ice.Message, arg ...string) {
msg := s.status(m, ApplyCreate, ApplyCancel)

View File

@ -5,7 +5,8 @@ import (
"shylinux.com/x/ice"
icebergs "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits"
@ -15,6 +16,7 @@ import (
type Tabler interface {
Inputs(m *ice.Message, arg ...string)
Select(m *ice.Message, arg ...string) *ice.Message
RewriteAppend(m *ice.Message, arg ...string) *ice.Message
TransValue(m *ice.Message, key string, arg ...string) string
TransRole(m *ice.Message, arg ...string) string
@ -49,11 +51,21 @@ func (s Table) Inputs(m *ice.Message, arg ...string) {
}
}
m.SortInt(arg[0]).DisplayInputKeyNameIconTitle()
case ctx.INDEX:
mdb.HashInputs(m.Message, arg)
default:
s.Table.Inputs(m, arg...)
}
}
func (s Table) List(m *ice.Message, arg ...string) {
func (s Table) List(m *ice.Message, arg ...string) *ice.Message {
if m.IsTech() {
if len(arg) == 0 {
s.Select(m)
} else if len(arg) == 2 {
s.SelectDetail(m, model.UID, arg[1])
}
}
return m
}
func (s Table) TablesWithRole(m *ice.Message, arg []string, target, userPlace, place Tabler, fields ...ice.Any) *ice.Message {
s.Tables(m, kit.JoinWord("LEFT JOIN", s.TableName(kit.TypeName(userPlace)),
@ -62,20 +74,38 @@ func (s Table) TablesWithRole(m *ice.Message, arg []string, target, userPlace, p
)).FieldsWithCreatedAT(m, target, append([]ice.Any{s.Key(target, model.USER_UID), s.AS(s.Key(userPlace, model.ROLE), s.Keys(userPlace, model.ROLE))}, fields...)...)
if len(arg) == 1 {
s.Table.Select(m, s.Key(target, s.Keys(place, model.UID)), arg[0])
m.Action(s.Create)
} else if len(arg) == 2 {
s.Table.Select(m, s.Key(target, s.Keys(place, model.UID)), arg[0], s.Key(target, model.UID), arg[1])
s.Table.SelectDetail(m, s.Key(target, s.Keys(place, model.UID)), arg[0], s.Key(target, model.UID), arg[1])
} else {
return m
}
userPlace.RewriteAppend(m)
return s.SelectJoinUser(m)
}
func (s Table) Select(m *ice.Message, arg ...string) *ice.Message {
defer s.Display(m, "")
defer m.PushAction(s.Delete)
return s.Table.Select(m, arg...)
}
func (s Table) SelectDetail(m *ice.Message, arg ...string) *ice.Message {
defer s.Display(m, "")
defer m.PushAction(s.Delete)
return s.Table.SelectDetail(m, arg...)
}
func (s Table) SelectJoinUser(m *ice.Message) *ice.Message {
return s.SelectJoin(m, user{}, model.NAME, model.AVATAR)
}
func (s Table) SelectJoinCity(m *ice.Message) *ice.Message {
return s.SelectJoin(m, city{}, model.NAME)
}
func (s Table) ChangeStatus(m *ice.Message, uid string, from, to int, arg ...string) *ice.Message {
msg := s.Select(m.Spawn(), model.UID, uid)
if !m.WarnNotValid(kit.Int(msg.Append(mdb.STATUS)) != int(from)) {
s.Update(m, kit.Dict(mdb.STATUS, to, arg), model.UID, uid)
}
return m
}
func (s Table) RewriteAppend(m *ice.Message, arg ...string) *ice.Message {
m.RewriteAppend(func(value, key string, index int) string {
kit.If(key == model.PLACE_TYPE, func() { value = PlaceType(kit.Int(value)).String() })
@ -102,25 +132,40 @@ func (s Table) TransRole(m *ice.Message, arg ...string) string {
role := s.Place.TransValue(m, s.Keys(s.UserPlace, model.ROLE), arg...)
return kit.Format(`<span class="role %s">%s</span>`, value, role)
}
func (s Table) RecordEvent(m *ice.Message, uid, info string, arg ...string) {
event{}.Record(m.Spawn(kit.Dict(model.PLACE_UID, uid)), info, arg...)
}
func (s Table) SendTemplate(m *ice.Message, from, user_uid, title string) {
if !m.IsErr() {
m.Cmd(user{}, user{}.SendTemplate, from, user_uid, Portal{}.Link(m, m.Option(s.Keys(s.Place, model.UID)), m.PrefixKey(), m.Option(model.UID)),
m.Cmd(user{}, s.SendTemplate, from, user_uid, Portal{}.Link(m, m.Option(s.Keys(s.Place, model.UID)), m.PrefixKey(), m.Option(model.UID)),
title, m.Option(s.Keys(s.Place, model.NAME))+" "+s.Place.TransValue(m, s.Keys(s.UserPlace, model.ROLE)), kit.Cut(m.Option(model.UID), 6))
}
}
func (s Table) Display(m *ice.Message) *ice.Message {
m.Option("_place_uid", s.ToLower(kit.TypeName(s.Place))+"_uid")
m.Option("_place_name", s.ToLower(kit.TypeName(s.Place))+"_name")
m.Option("_place_type", s.ToLower(kit.TypeName(s.Place))+"_type")
m.Option("_user_place_role", s.ToLower(kit.TypeName(s.UserPlace))+"_role")
m.Option("_street_name", s.ToLower(kit.TypeName(s.Street))+"_name")
file := ""
kit.If(file == "", func() { file = m.CommandKey() + ".js" })
if !kit.HasPrefix(file, nfs.PS, web.HTTP) {
file = m.Resource(path.Join(path.Dir(kit.FileLine(1, 100)), file))
func (s Table) Display(m *ice.Message, file string) *ice.Message {
if s.Place != nil {
m.Option("_place_uid", s.ToLower(kit.TypeName(s.Place))+"_uid")
m.Option("_place_name", s.ToLower(kit.TypeName(s.Place))+"_name")
m.Option("_place_type", s.ToLower(kit.TypeName(s.Place))+"_type")
m.Option("_user_place_role", s.ToLower(kit.TypeName(s.UserPlace))+"_role")
}
m.Display(file)
return m
if s.Street != nil {
m.Option("_street_name", s.ToLower(kit.TypeName(s.Street))+"_name")
}
base := path.Dir(kit.FileLine(1, 100))
sub := path.Dir(kit.FileLine(-1, 100))
return m.Display(kit.Format(mdb.Cache(m.Message, kit.Keys(m.PrefixKey(), ctx.DISPLAY, file), func() ice.Any {
if file == "" {
file = m.Resource(path.Join(sub, m.CommandKey()+".js"))
}
if m.Template(file) == "" {
if m.CommandKey() == web.PORTAL {
file = m.Resource(path.Join(base, "portal.js"))
} else {
file = m.Resource(path.Join(base, "common.js"))
}
}
return file
})))
}
type Tables struct {
@ -159,12 +204,15 @@ func PortalCmd(portal ice.Any) {
cmd := func(name string, data ice.Any) {
_, cmd := ice.Cmd(kit.Keys(p, name), data)
cmd.RawHand = path.Join(path.Dir(h), name+".go")
h := cmd.Actions["beforeMigrate"].Hand
cmd.Actions["beforeMigrate"].Hand = func(m *icebergs.Message, arg ...string) {
ice.LoadTrans(m.Cmd("web.team.gonganxitong.apply"), cmd)
ice.LoadTrans(m, cmd)
h(m, arg...)
}
cmd.Actions[ice.CTX_INIT].Hand = icebergs.MergeHand(cmd.Actions[ice.CTX_INIT].Hand, func(m *icebergs.Message, arg ...string) {
msg := m.Cmd("web.team.gonganxitong.apply")
ice.LoadTrans(msg, m.CommandKey(), cmd)
ice.LoadTrans(m, m.CommandKey(), cmd)
kit.If(mdb.Config(m, web.PORTAL) == ice.TRUE, func() { Portal{}.Show(&ice.Message{Message: m}, m.PrefixKey()) })
})
cmd.Actions["afterMigrate"].Hand = icebergs.MergeHand(cmd.Actions["afterMigrate"].Hand, func(m *icebergs.Message, arg ...string) {
kit.If(mdb.Config(m, web.PORTAL) == ice.TRUE, func() { Portal{}.Show(&ice.Message{Message: m}, m.PrefixKey()) })
})
}
table := portal.(interface{ getTable() Table }).getTable()
cmd("portal", portal)

View File

@ -0,0 +1,14 @@
Volcanos(chat.ONIMPORT, {
_init: function(can, msg) {
var PLACE_NAME = msg.Option("_place_name"), PLACE_TYPE = msg.Option("_place_type"), USER_PLACE_ROLE = msg.Option("_user_place_role")
can.onimport.itemcards(can, msg, function(value) { value._style = [value[PLACE_TYPE]||"", value[USER_PLACE_ROLE]||""]
return [
{view: html.TITLE, list:[{text: [value.name||value.user_name]},
value[PLACE_TYPE] && {text: [value[PLACE_TYPE]||"", "", [mdb.TYPE, value[PLACE_TYPE]||""]]},
value[USER_PLACE_ROLE] && {text: [value[USER_PLACE_ROLE]||"", "", [aaa.ROLE, value[UESR_PLACE_ROLE]||""]]},
]},
{view: html.STATUS, list: [value.uid && {text: value.uid.slice(0, 6)}, {text: can.base.TimeTrim(value.created_at||value.updated_at)}]},
]
})
},
})

View File

@ -28,7 +28,7 @@ func (s event) List(m *ice.Message, arg ...string) {
return
}
m.PushAction().Action()
s.Display(m)
s.Display(m, "")
}
func init() { ice.TeamCtxCmd(event{Table: newTable()}) }

View File

@ -80,19 +80,6 @@ type City struct {
Name string `gorm:"type:char(32);index"`
}
type Service struct {
db.ModelWithUID
Icon string `gorm:"type:char(32)"`
Name string `gorm:"type:char(32)"`
Index string `gorm:"type:char(32)"`
Hostname string `gorm:"type:char(32)"`
Pathname string `gorm:"type:char(255)"`
Nodename string `gorm:"type:char(32)"`
Nodetype string `gorm:"type:char(32)"`
Domain string `gorm:"type:char(255)"`
Module string `gorm:"type:char(32)"`
Version string `gorm:"type:char(32)"`
}
type Event struct {
db.ModelWithUID
PlaceUID string `gorm:"type:char(32);index"`
@ -119,6 +106,21 @@ type Order struct {
Status uint8
}
type Service struct {
db.ModelWithUID
Icon string `gorm:"type:char(32)"`
Name string `gorm:"type:char(32)"`
Index string `gorm:"type:char(32)"`
Hostname string `gorm:"type:char(32)"`
Pathname string `gorm:"type:char(255)"`
Nodename string `gorm:"type:char(32)"`
Nodetype string `gorm:"type:char(32)"`
Portal string `gorm:"type:char(255)"`
Domain string `gorm:"type:char(255)"`
Module string `gorm:"type:char(32)"`
Version string `gorm:"type:char(32)"`
}
func init() {
db.CmdModels("", &Sess{}, &User{}, &UserPlace{}, &Place{}, &Street{}, &City{}, Event{}, Apply{}, Order{}, Service{})
}

View File

@ -66,7 +66,7 @@ func (s order) List(m *ice.Message, arg ...string) {
}
}).Action()
s.UserPlace.RewriteAppend(m)
s.Display(m)
s.Display(m, "")
}
func init() { ice.TeamCtxCmd(order{Table: newTable()}) }

View File

@ -13,13 +13,21 @@ $output>div.list>div.action div.item { margin-right:5px; }
$output>div.list>div.action div.item input[type=button] { color:var(--notice-bg-color); border:none; }
$output>div.list>div.action div.item i { display:none; }
$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 input { border:none; color:var(--notice-bg-color); min-width:60px; float:left; }
$output>div.action div.item.button input:hover { background-color:var(--hover-bg-color); }
$output>div.action div.item.button i { display:none; }
$output>div.action div.item.button span { display:none; }
$output>fieldset table.content td { box-shadow:none; }
$output span.role { border:var(--box-notice); color:var(--notice-bg-color); padding:2px 5px; }
$output span.role { border:var(--box-notice); color:var(--notice-bg-color); }
$output span.role.creator { border-color:var(--box-danger); color:var(--danger-bg-color); }
$output span.role.landlord { border-color:var(--box-danger); color:var(--danger-bg-color); }
$output span.role.teacher { border-color:var(--box-danger); color:var(--danger-bg-color); }
$output span.role.leader { border-color:var(--box-danger); color:var(--danger-bg-color); }
$output span.role.manager { border-color:var(--box-danger); color:var(--danger-bg-color); }
$output table.content.detail tr.action input.icons { display:unset; }
$output table.content.detail tr.action i { display:none; }
$output table.content td.action i { display:none; }
$output table.content td.action input.icons { display:unset; }
body.en $output>fieldset table.content td:first-child { max-width:180px; width:unset;}
$output>fieldset table.content tr.uid { display:none; }
$output>fieldset table.content tr.order_uid { display:none; }

View File

@ -20,19 +20,24 @@ type Portal struct {
short string `data:"index"`
field string `data:"time,name,icons,index,order,enable,type,role,view"`
list string `name:"list place_uid index uid auto" role:"void"`
create string `name:"create name icons index"`
create string `name:"create index name icons"`
placeCreate string `name:"placeCreate city_name* street_name* place_type*:select name* address*" icon:"bi bi-plus-square-dotted" role:"void"`
placeRemove string `name:"placeRemove uid*" role:"void"`
scanQRCode string `name:"scanQRCode type text" icon:"bi bi-qr-code-scan" role:"void"`
setIcons string `name:"setIcons icons" icon:"bi bi-info-square"`
}
func (s Portal) Init(m *ice.Message, arg ...string) {
s.Hash.Init(m, arg...)
}
func (s Portal) Exit(m *ice.Message, arg ...string) {
s.Hash.Exit(m, arg...)
}
func (s Portal) BeforeMigrate(m *ice.Message, arg ...string) {
}
func (s Portal) AfterMigrate(m *ice.Message, arg ...string) {
m.GoSleep("30ms", func() {
m.Option(ctx.INDEX, m.PrefixKey())
m.Cmdy(s.service, s.Update, m.ConfigSimple(mdb.ICON, mdb.NAME))
m.Cmdy(s.service, s.Update, m.ConfigSimple(mdb.NAME), mdb.ICON, kit.Select(ice.Info.NodeIcon, m.Config(mdb.ICON)), ctx.INDEX, m.PrefixKey())
})
}
func (s Portal) Inputs(m *ice.Message, arg ...string) {
@ -52,7 +57,7 @@ func (s Portal) List(m *ice.Message, arg ...string) {
m.EchoInfoButton(m.Trans("Please Create Your Place", "请添加场所"), s.PlaceCreate, s.ScanQRCode)
})
} else if len(arg) == 2 {
msg := m.Cmd(s.Place, s.Select, model.UID, arg[0])
msg := m.Cmd(s.Place, s.Place.Select, model.UID, arg[0])
m.Option(s.Keys(s.Place, model.NAME), msg.Append(model.NAME))
m.Cmdy(ctx.COMMAND, arg[1]).Push(ctx.ARGS, arg[0])
} else if len(arg) == 1 {
@ -60,14 +65,13 @@ func (s Portal) List(m *ice.Message, arg ...string) {
} else {
m.FieldsSetDetail().Cmdy(arg[1], mdb.SELECT, model.UID, arg[2]).PushAction().Action()
}
s.Display(m).DisplayCSS("")
s.Display(m, "").DisplayCSS("")
}
func (s Portal) PlaceCreate(m *ice.Message, arg ...string) {
defer m.ToastProcess()()
if s.city.FindOrCreateByName(m, arg...); m.IsErr() {
return
}
if s.Street.FindOrCreateByName(m, arg...); m.IsErr() {
} else if s.Street.FindOrCreateByName(m, arg...); m.IsErr() {
return
}
arg = kit.TransArgKeys(arg, s.Keys(s.Place, model.TYPE), model.TYPE)
@ -76,6 +80,7 @@ func (s Portal) PlaceCreate(m *ice.Message, arg ...string) {
}
args := kit.Simple(m.OptionSimple(model.USER_UID), s.Keys(s.Place, model.UID), m.Result(), model.ROLE, UserPlaceCreator)
m.Cmdy(s.UserPlace, s.Create, args).ProcessRefresh()
s.RecordEvent(m, m.Result(), kit.Format(m.Trans("create", "创建")), arg...)
}
func (s Portal) PlaceRemove(m *ice.Message, arg ...string) {
defer m.ToastProcess()()
@ -90,7 +95,7 @@ func (s Portal) ScanQRCode(m *ice.Message, arg ...string) {
} else if m.Option(mdb.TYPE) == web.LINK {
args := m.ParseURL(m.Option(mdb.TEXT))
if len(args) > 1 && args[1] == m.Prefix("apply") {
args := kit.Simple(m.OptionSimple(model.USER_UID), s.Key(s.Place, model.UID), args[0])
args := kit.Simple(m.OptionSimple(model.USER_UID), s.Keys(s.Place, model.UID), args[0])
m.Cmdy(s.UserPlace, s.Create, args, model.ROLE, UserPlaceVisitor)
}
}
@ -105,12 +110,15 @@ type portal struct {
func init() { ice.TeamCtxCmd(portal{Portal: Portal{Table: newTable()}}) }
func (s Portal) Create(m *ice.Message, arg ...string) {
var _cmd *ice.Command
m.Search(m.Option(ctx.INDEX), func(key string, cmd *ice.Command) { _cmd = cmd })
msg := s.Hash.Select(m.Spawn(), m.Option(ctx.INDEX))
s.Hash.Create(m, ctx.INDEX, m.Option(ctx.INDEX), mdb.NAME, _cmd.Help, mdb.ICONS, _cmd.Icon, mdb.TIME, msg.Append(mdb.TIME))
}
func (s Portal) Show(m *ice.Message, arg ...string) {
m.GoSleep("30ms", func() {
cmd := m.GetCommand()
msg := m.Cmd(m.Prefix(web.PORTAL), s.Select, m.PrefixKey())
m.Cmd(m.Prefix(web.PORTAL), s.Create, mdb.NAME, cmd.Help, mdb.ICONS, cmd.Icon, ctx.INDEX, m.PrefixKey(), mdb.TIME, msg.Append(mdb.TIME))
})
key := m.PrefixKey()
m.GoSleep("300ms", func() { m.Cmd(m.Prefix(web.PORTAL), s.Create, ctx.INDEX, key) })
}
func (s Portal) Link(m *ice.Message, arg ...string) string {
return m.MergePodCmd("", m.Prefix(web.PORTAL)) + "?debug=true" +

View File

@ -8,7 +8,7 @@ Volcanos(chat.ONIMPORT, {
return [
{view: html.TITLE, list: [{text: value._name},
{text: [value.__type, "", [mdb.TYPE, value._type]]},
value._role != "creator" && {text: [value.__role, "", [aaa.ROLE, value._role]]},
value._role != "visitor" && {text: [value.__role, "", [aaa.ROLE, value._role]]},
]},
{view: html.STATUS, list: [
{text: value._uid.slice(0, 6)}, {text: value.city_name}, {text: value._street},
@ -53,15 +53,15 @@ Volcanos(chat.ONIMPORT, {
},
myIndex: function(can, msg, target, PLACE_UID) {
var width = (can.ConfWidth()-40)/parseInt((can.ConfWidth()-40)/100), height = width+20; can.user.isMobile && !can.user.isLandscape() && (width = (can.ConfWidth()-40)/4, height = width+20)
can.page.Append(can, target||can._output, msg.Table(function(value) { if (value.enable != ice.TRUE) { return }
can.page.Append(can, target||can._output, msg.Table(function(value) {
// if (value.enable != ice.TRUE) { return }
return {view: [[html.ITEM, ctx.INDEX].concat(
value.type? [mdb.TYPE]: [], can.core.Split(value.type||""),
value.role? [aaa.ROLE]: [], can.core.Split(value.role||""),
)], style: {height: height, width: width}, list: [
{img: can.misc.ResourceIcons(can, value.icons)}, {text: can.user.trans(can, value.index.split(".").pop(), value.name)},
], onclick: function(event) {
can.page.ClassList.del(can, can._fields, "_back")
can.page.ClassList.add(can, can._fields, "_goto")
can.page.ClassList.del(can, can._fields, "_back"), can.page.ClassList.add(can, can._fields, "_goto")
can.Option(PLACE_UID, can.onexport.session(can, PLACE_UID)), can.Option(ctx.INDEX, value.index), can.Update()
}}
}))
@ -89,7 +89,7 @@ Volcanos(chat.ONIMPORT, {
can.core.List(["_trans", "_icons", "_style", "_trans.input", "_trans.value"], function(key) {
var value = sub.Conf(key); value && can.core.Item(can.Conf(key), function(k, v) { value[k] = value[k]||v })
})
can.onexport.title(can, value.help, sub.Conf(PLACE_NAME, msg.Option(PLACE_NAME)))
can.onexport.title(can, sub.Conf(PLACE_NAME, msg.Option(PLACE_NAME)), value.help)
sub.onexport.title = function(sub) { can.onexport.title.apply(can.onexport, [can].concat(can.core.List(arguments).slice(1))) }
sub.onexport._output = function(_sub, msg) {
can.core.Item(can.onimport, function(key, value) { _sub.onimport[key] = _sub.onimport[key]||value })
@ -101,7 +101,7 @@ Volcanos(chat.ONIMPORT, {
}
sub.onexport.output = function(_sub, msg) { can.onappend.style(sub, html.OUTPUT)
can.onexport.hash(can, can.Option(PLACE_UID), value.index, sub.Option(UID))
can.onexport.title(can, sub.ConfHelp(), sub.Conf(PLACE_NAME), msg.Option("_share_title")||"")
can.onexport.title(can, sub.Conf(PLACE_NAME), sub.ConfHelp(), msg.Option("_share_title")||"")
can.user.agent.init(can, msg.Option("_share_content"), msg.Option("_share_icons")||value.icons)
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)
back = function() { can.page.ClassList.add(can, can._fields, "_back")
@ -119,7 +119,7 @@ Volcanos(chat.ONIMPORT, {
Volcanos(chat.ONEXPORT, {
value: function(can, value, PLACE_UID, PLACE_NAME) {
can.page.Select(can, can.ui._target, "div.item.card.uid-"+value._uid, function(item) { can.onmotion.select(can, can.ui._target, html.DIV_ITEM, item) })
can.sup.current = value, can.onimport.selectIndex(can, can.sup.current), can.onexport.title(can, value[PLACE_NAME])
can.sup.current = value, can.onimport.selectIndex(can, can.sup.current), can.onexport.title(can, value[PLACE_NAME], can.ConfHelp())
can.onexport.session(can, PLACE_UID, value[PLACE_UID]), can.onexport.hash(can, value[PLACE_UID]), can.user.agent.init(can)
},
share_title: function(can, msg, title, role) {

View File

@ -13,8 +13,13 @@
"placeUser": "场景用户",
"cancel": "取消",
"submit": "提交",
"finish": "完成",
"reject": "驳回",
"approve": "通过",
"autogen": "生成",
"compile": "编译",
"project": "项目",
"oauth": "授权",
"icons": {
"service": "https://img.icons8.com/officel/80/activity-grid.png",
"qrcode": "https://img.icons8.com/officel/80/qr-code.png",
@ -28,12 +33,17 @@
"placeRemove": "danger"
},
"input": {
"class": "基类",
"table": "应用",
"My Place": "我的场景",
"apply_status": "申请状态",
"order_status": "审批状态",
"begin_time": "起始时间",
"end_time": "结束时间",
"cancel_time": "取消时间",
"finish_time": "完成时间",
"operate": "操作",
"user_uid": "用户",
"user_name": "用户昵称",
"user_avatar": "用户头像",
"user_place_role": "用户角色",
@ -42,6 +52,8 @@
"place_type": "场景类型",
"place_address": "场景地址",
"street_name": "街道名称",
"school_name": "学校名称",
"company_name": "公司名称",
"city_name": "城市名称"
},
"value": {

View File

@ -3,7 +3,7 @@ refer `
ICON https://igoutu.cn/icons/officel
GORM https://gorm.io/docs/indexes.html
`
field web.chat.wx.access
field web.code.mysql.client
field web.code.mysql.query args `mysql gonganxitong`
field web.code.db.database

View File

@ -1,11 +1,17 @@
package gonganxitong
import (
"path"
"strings"
"shylinux.com/x/ice"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb"
"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"
"shylinux.com/x/community/src/gonganxitong/model"
@ -13,26 +19,80 @@ import (
type service struct {
Table
portal string `data:"true"`
domain string `data:"gonganxitong"`
create string `name:"create name help table"`
portal string `data:"true"`
domain string `data:"gonganxitong"`
update string `name:"update name icon index"`
autogen string `name:"autogen name* help* class* table*" icon:"bi bi-plus-square-dotted"`
oauth string `name:"oauth" icon:"bi bi-shield-fill-check"`
open string `name:"open" role:"void"`
conf string `name:"conf" role:"void"`
}
func (s service) Update(m *ice.Message, arg ...string) {
uid := kit.Hashs(ice.Info.Hostname, ice.Info.Pwd, m.Option(ctx.INDEX))
s.Table.Create(m, model.UID, uid, tcp.HOSTNAME, ice.Info.Hostname, nfs.PATHNAME, ice.Info.Pwd, ctx.INDEX, m.Option(ctx.INDEX))
s.Table.Update(m, kit.Dict(arg, web.DOMAIN, ice.Info.Make.Domain,
tcp.NODENAME, ice.Info.NodeName, tcp.NODETYPE, ice.Info.NodeType,
if s.Table.Select(m.Spawn(), model.UID, uid).Length() == 0 {
s.Table.Create(m, kit.Simple(model.UID, uid, m.OptionSimple(mdb.NAME, mdb.ICON), tcp.HOSTNAME, ice.Info.Hostname, nfs.PATHNAME, ice.Info.Pwd, m.OptionSimple(ctx.INDEX))...)
m.Cmd(m.Prefix(web.PORTAL)).Table(func(value ice.Maps) { m.Cmd(m.Prefix(web.PORTAL), mdb.MODIFY, value[ctx.INDEX], mdb.ENABLE, ice.TRUE) })
}
s.Table.Update(m, kit.Dict(arg, m.OptionSimple(mdb.NAME, mdb.ICON),
nfs.MODULE, ice.Info.Make.Module, nfs.VERSION, ice.Info.Make.Versions(),
tcp.NODENAME, ice.Info.NodeName, tcp.NODETYPE, ice.Info.NodeType,
web.DOMAIN, ice.Info.Make.Domain,
web.PORTAL, ctx.GetCmdFile(m.Message, m.Prefix(web.PORTAL)),
), model.UID, uid)
}
func (s service) Autogen(m *ice.Message, arg ...string) {
m.Option("CLASS", strings.ToUpper(m.Option(mdb.CLASS)))
m.Option("Class", kit.Capital(m.Option(mdb.CLASS)))
m.Option("class", kit.LowerCapital(m.Option(mdb.CLASS)))
m.Option("TABLE", strings.ToUpper(m.Option(mdb.TABLE)))
m.Option("Table", kit.Capital(m.Option(mdb.TABLE)))
m.Option("table", kit.LowerCapital(m.Option(mdb.TABLE)))
code.AutogenImport(m.Message, m.Option(mdb.NAME))
m.Option(nfs.MODULE, path.Join(code.AutogenMod(m.Message), nfs.SRC, m.Option(mdb.NAME)))
p, from := path.Join(nfs.SRC, m.Option(mdb.NAME)), "template/"
m.Cmd(nfs.DEFS, path.Join(p, "model/model.go"), m.Template(from+"model/model.go"))
m.Cmd(nfs.DEFS, path.Join(p, "common.go"), m.Template(from+"common.go"))
m.Cmd(nfs.DEFS, path.Join(p, "portal.go"), m.Template(from+"portal.go"))
m.Cmd(nfs.DEFS, path.Join(p, "portal.json"), m.Template(from+"portal.json"))
m.Cmd(nfs.DEFS, path.Join(p, "user"+m.Option("Class")+".go"), m.Template(from+"userClass.go"))
m.Cmd(nfs.DEFS, path.Join(p, m.Option("class")+".go"), m.Template(from+"class.go"))
kit.For(kit.Split(m.Option(mdb.TABLE)), func(table string) {
m.Option(mdb.TABLE, kit.LowerCapital(table))
m.Cmd(nfs.DEFS, path.Join(p, m.Option(mdb.TABLE)+".go"), m.Template(from+"homework.go"))
m.Cmd(nfs.DEFS, path.Join(p, m.Option(mdb.TABLE)+".js"), m.Template(from+"homework.js"))
})
}
func (s service) Compile(m *ice.Message, arg ...string) {
m.Cmdy(code.VIMER, code.COMPILE)
}
func (s service) Oauth(m *ice.Message, arg ...string) {
defer m.ToastProcess()()
m.Options(m.Cmd(web.CHAT_WX_ACCESS).AppendSimple())
m.Option("user_cmd", kit.JoinWord(m.Prefix(aaa.USER), mdb.CREATE))
m.Option("sess_cmd", kit.JoinWord(m.Prefix(aaa.SESS), mdb.CREATE))
m.Cmd(web.CHAT_WX_ACCESS, web.OAUTH)
m.Cmd(web.SPACE, ice.OPS, ctx.CONFIG, web.CHAT_WX_AGENT, web.SPACE, m.Option(ice.MSG_USERPOD))
m.ProcessHold()
}
func (s service) List(m *ice.Message, arg ...string) {
if len(arg) == 2 {
s.Table.SelectDetail(m, model.UID, arg[1])
} else {
s.Orders(m, s.Desc(model.UPDATED_AT)).Select(m)
}
m.PushAction(s.Open, s.Conf).Display("")
list := m.CmdMap(web.SPACE, ice.OPS, web.SPACE, mdb.NAME)
m.Table(func(value ice.Maps) {
if _, ok := list[value[tcp.NODENAME]]; ok && value[ctx.INDEX] != "" {
if m.Cmd(web.SPACE, ice.OPS, web.SPACE, value[tcp.NODENAME], value[ctx.INDEX], kit.Dict(mdb.VIEW, mdb.TABLE)).Length() > 0 {
m.Push(mdb.STATUS, web.ONLINE)
return
}
}
m.Push(mdb.STATUS, "")
})
m.PushAction(s.Open, s.Conf, s.Project).Action(s.Autogen, s.Compile, s.Oauth).Display("")
m.Sort("status,updated_at", []string{web.ONLINE}, ice.STR_R)
}
func (s service) Open(m *ice.Message, arg ...string) {
m.ProcessOpen(web.S(m.Option(tcp.NODENAME)) + web.C(m.Option(ctx.INDEX)))
@ -40,5 +100,8 @@ func (s service) Open(m *ice.Message, arg ...string) {
func (s service) Conf(m *ice.Message, arg ...string) {
m.ProcessOpen(web.S(m.Option(tcp.NODENAME)) + web.C(m.Option(ctx.INDEX)) + "?view=table")
}
func (s service) Project(m *ice.Message, arg ...string) {
m.ProcessOpen(web.S(m.Option(tcp.NODENAME)) + web.C(web.CODE_VIMER) + "?path=src/&file=" + strings.Split(kit.Select("", strings.Split(m.Option(web.PORTAL), "/src/"), 1), "?")[0])
}
func init() { ice.TeamCtxCmd(service{}) }

View File

@ -1,12 +1,12 @@
Volcanos(chat.ONIMPORT, {
_init: function(can, msg) {
can.onimport.itemcards(can, msg, function(value) { value._style = [value.nodetype]
can.onimport.itemcards(can, msg, function(value) { value._style = [value.nodetype, value.status]
return [
{view: html.TITLE, list: [{text: value.name}, {text: [value.nodetype, "", mdb.TYPE]}]},
{view: html.TITLE, list: [{text: value.name}, {text: [value.nodetype, "", mdb.TYPE]}, value.status && {text: [value.status, "", mdb.STATUS]}]},
{view: html.STATUS, list: [{text: value.uid.slice(0, 6)}, {text: can.base.TimeTrim(value.updated_at)}]},
{view: html.STATUS, list: [{text: value.index}]},
{view: html.STATUS, list: [{text: value.module}, {text: value.version}]},
// {view: html.STATUS, list: [{text: value.domain}]},
{view: html.STATUS, list: [{text: value.domain.split("?")[0]}]},
// {view: html.STATUS, list: [{text: value.hostname}, {text: value.pathname}]},
]
})

View File

@ -0,0 +1,25 @@
package {{.Option "name"}}
import "shylinux.com/x/ice"
type {{.Option "class"}} struct{ Table }
func init() { ice.TeamCtxCmd({{.Option "class"}}{}) }
type {{.Option "Class"}}Type int
const (
{{.Option "Class"}}Term {{.Option "Class"}}Type = iota
{{.Option "Class"}}Weekly
{{.Option "Class"}}Step
{{.Option "Class"}}Free
)
var {{.Option "Class"}}TypeList = map[{{.Option "Class"}}Type]string{
{{.Option "Class"}}Term: "term",
{{.Option "Class"}}Weekly: "weekly",
{{.Option "Class"}}Step: "step",
{{.Option "Class"}}Free: "free",
}
func (s {{.Option "Class"}}Type) String() string { return {{.Option "Class"}}TypeList[s] }

View File

@ -0,0 +1,46 @@
package {{.Option "name"}}
import (
"shylinux.com/x/ice"
kit "shylinux.com/x/toolkits"
"shylinux.com/x/enterprise/src/guanlixitong"
"{{.Option "module"}}/model"
)
type Tables struct {
guanlixitong.Tables
list string `name:"list {{.Option "class"}}_uid uid auto" role:"void"`
}
type Table struct {
guanlixitong.Table
list string `name:"list {{.Option "class"}}_uid uid auto" role:"void"`
}
func (s Table) Inputs(m *ice.Message, arg ...string) {
switch arg[0] {
case model.{{.Option "CLASS"}}_TYPE:
for k, v := range {{.Option "Class"}}TypeList {
m.Push(arg[0], k).Push(model.NAME, v)
}
m.SortInt(arg[0]).DisplayInputKeyNameIconTitle()
case model.USER_{{.Option "CLASS"}}_ROLE:
for k, v := range User{{.Option "Class"}}RoleList {
if k != User{{.Option "Class"}}Creator && k != User{{.Option "Class"}}Visitor {
m.Push(arg[0], k).Push(model.NAME, v)
}
}
m.SortInt(arg[0]).DisplayInputKeyNameIconTitle()
default:
s.Table.Inputs(m, arg...)
}
}
func (s Table) RewriteAppend(m *ice.Message, arg ...string) *ice.Message {
m.RewriteAppend(func(value, key string, index int) string {
kit.If(key == model.{{.Option "CLASS"}}_TYPE, func() { value = {{.Option "Class"}}Type(kit.Int(value)).String() })
kit.If(key == model.USER_{{.Option "CLASS"}}_ROLE, func() { value = User{{.Option "Class"}}Role(kit.Int(value)).String() })
return value
})
s.Table.RewriteAppend(m)
return m
}

View File

@ -0,0 +1,25 @@
package {{.Option "name"}}
import (
"shylinux.com/x/ice"
kit "shylinux.com/x/toolkits"
"{{.Option "module"}}/model"
)
type {{.Option "table"}} struct {
Table
{{.Option "class"}} {{.Option "class"}}
user{{.Option "Class"}} user{{.Option "Class"}}
portal string `data:"true"`
create string `name:"create content*" role:"void"`
}
func (s {{.Option "table"}}) Create(m *ice.Message, arg ...string) {
s.Table.Create(m, kit.Simple(arg, m.OptionSimple(model.USER_UID, model.{{.Option "CLASS"}}_UID))...)
}
func (s {{.Option "table"}}) List(m *ice.Message, arg ...string) {
s.TablesWithRole(m, arg, s, s.user{{.Option "Class"}}, s.{{.Option "class"}}, model.CONTENT).Display("")
}
func init() { ice.TeamCtxCmd({{.Option "table"}}{}) }

View File

@ -0,0 +1,11 @@
Volcanos(chat.ONIMPORT, {
_init: function(can, msg) {
can.onimport.itemcards(can, msg, function(value) { return [
{view: html.TITLE, list: [{text: value.user_name},
{text: [can.user.transValue(can, value, "user_{{.Option "class"}}_role"), "", aaa.ROLE]},
]},
{view: html.STATUS, list: [{text: value.uid.slice(0, 6)}, {text: can.base.TimeTrim(value.created_at)},]},
{view: html.OUTPUT, list: [{text: value.content}]},
] })
},
})

View File

@ -0,0 +1,41 @@
package model
import "shylinux.com/x/mysql-story/src/db"
const (
UID = "uid"
NAME = "name"
TYPE = "type"
ROLE = "role"
CONTENT = "content"
USER_UID = "user_uid"
USER_{{.Option "CLASS"}}_ROLE = "user_{{.Option "class"}}_role"
{{.Option "CLASS"}}_UID = "{{.Option "class"}}_uid"
{{.Option "CLASS"}}_NAME = "{{.Option "class"}}_name"
{{.Option "CLASS"}}_TYPE = "{{.Option "class"}}_type"
{{.Option "TABLE"}}_UID = "{{.Option "table"}}_uid"
COMPANY_UID = "company_uid"
CITY_UID = "city_uid"
)
type User{{.Option "Class"}} struct {
db.ModelWithUID
UserUID string `gorm:"type:char(32);index"`
{{.Option "Class"}}UID string `gorm:"type:char(32);index"`
Role uint8
}
type {{.Option "Class"}} struct {
db.ModelWithUID
CompanyUID string `gorm:"type:char(32);index"`
Name string `gorm:"type:varchar(255)"`
Type uint8
}
type {{.Option "Table"}} struct {
db.ModelWithUID
{{.Option "Class"}}UID string `gorm:"type:char(32);index"`
UserUID string `gorm:"type:char(32);index"`
Content string `gorm:"type:varchar(255)"`
}
func init() { db.CmdModels("", &User{{.Option "Class"}}{}, &{{.Option "Class"}}{}, &{{.Option "Table"}}{}) }

View File

@ -0,0 +1,17 @@
package {{.Option "name"}}
import (
"shylinux.com/x/community/src/gonganxitong"
"shylinux.com/x/enterprise/src/guanlixitong"
)
type Portal struct {
gonganxitong.Portal
name string `data:"{{.Option "help"}}"`
list string `name:"list {{.Option "class"}}_uid index uid auto" role:"void"`
placeCreate string `name:"placeCreate city_name* company_name* name*" role:"void"`
}
func init() {
gonganxitong.PortalCmd(Portal{Portal: gonganxitong.NewPortal(user{{.Option "Class"}}{}, {{.Option "class"}}{}, guanlixitong.Company{})})
}

View File

@ -0,0 +1,29 @@
{
"portal": "{{.Option "help"}}",
"placeCreate": "创建场景",
"placeRemove": "删除场景",
"{{.Option "table"}}": "场景应用",
"icons": {
"{{.Option "table"}}": "https://img.icons8.com/officel/80/activity-grid.png",
"service": "https://img.icons8.com/officel/80/activity-grid.png"
},
"input": {
"My {{.Option "Class"}}": "我的场景",
"user_{{.Option "class"}}_role": "用户角色",
"{{.Option "class"}}_uid": "场景",
"{{.Option "class"}}_name": "场景名称",
"{{.Option "class"}}_type": "场景类型"
},
"value": {
"user_{{.Option "class"}}_role": {
"creator": "创建人",
"visitor": "访客"
},
"{{.Option "class"}}_type": {
"term": "学期制",
"weekly": "周期性",
"step": "阶段性",
"free": "自由式"
}
}
}

View File

@ -0,0 +1,57 @@
package {{.Option "name"}}
import (
"shylinux.com/x/ice"
"{{.Option "module"}}/model"
)
type user{{.Option "Class"}} struct {
Table
{{.Option "class"}} {{.Option "class"}}
}
func (s user{{.Option "Class"}}) User(m *ice.Message, arg ...string) {
if len(arg) == 1 {
s.Select(m, model.{{.Option "CLASS"}}_UID, arg[0])
} else if len(arg) == 2 {
s.Select(m, model.{{.Option "CLASS"}}_UID, arg[0], model.UID, arg[1])
} else {
return
}
m.RenameAppend(model.ROLE, model.USER_{{.Option "CLASS"}}_ROLE)
s.SelectJoinUser(m)
s.RewriteAppend(m)
}
func (s user{{.Option "Class"}}) List(m *ice.Message, arg ...string) {
s.Tables(m, s.{{.Option "class"}}).FieldsWithCreatedAT(m, s,
model.{{.Option "CLASS"}}_NAME, model.{{.Option "CLASS"}}_TYPE, model.USER_{{.Option "CLASS"}}_ROLE,
model.{{.Option "CLASS"}}_UID, model.COMPANY_UID,
)
if len(arg) == 1 {
s.Select(m, model.USER_UID, arg[0])
} else if len(arg) == 2 {
s.SelectDetail(m, model.USER_UID, arg[0], s.Key(s.{{.Option "class"}}, model.UID), arg[1])
} else {
return
}
s.SelectJoinCompany(m)
s.SelectJoinCity(m)
s.RewriteAppend(m)
}
func init() { ice.TeamCtxCmd(user{{.Option "Class"}}{}) }
type User{{.Option "Class"}}Role int
const (
User{{.Option "Class"}}Creator User{{.Option "Class"}}Role = iota
User{{.Option "Class"}}Visitor
)
var User{{.Option "Class"}}RoleList = map[User{{.Option "Class"}}Role]string{
User{{.Option "Class"}}Creator: "creator",
User{{.Option "Class"}}Visitor: "visitor",
}
func (s User{{.Option "Class"}}Role) String() string { return User{{.Option "Class"}}RoleList[s] }

View File

@ -30,6 +30,18 @@ func (s user) Create(m *ice.Message, arg ...string) {
func (s user) Email(m *ice.Message, arg ...string) {
s.Table.Update(m, kit.Dict(m.OptionSimple(model.EMAIL)), model.UID, m.Option(model.USER_UID))
}
func (s user) List(m *ice.Message, arg ...string) {
s.Table.List(m, arg...).Table(func(value ice.Maps) {
if value[model.UID] != m.Option(model.USER_UID) {
m.PushButton(s.SetCookie)
} else {
m.PushButton()
}
})
}
func (s user) SetCookie(m *ice.Message, arg ...string) {
m.ProcessCookie(model.USER_UID, m.Option(model.UID))
}
func (s user) SendTemplate(m *ice.Message, arg ...string) { // from uid url type name hash
msg := s.Select(m, model.UID, arg[1])
m.Cmdy("web.chat.wx.template", "", m.Config(nfs.TEMPLATE), msg.Append(model.OPEN_ID), kit.Select("", arg, 2),

View File

@ -5,6 +5,8 @@ import (
_ "shylinux.com/x/community/src/gonganxitong"
_ "shylinux.com/x/community/src/gonganxitong/express"
_ "shylinux.com/x/community/src/yuehaoxitong"
)
func main() { print(ice.Run()) }

View File

@ -0,0 +1,10 @@
Volcanos(chat.ONIMPORT, {
_init: function(can, msg) {
can.onimport.itemcards(can, msg, function(value) {
return [
{view: html.TITLE, list:[{text: [value.name||value.user_name]}]},
{view: html.STATUS, list: [value.uid && {text: value.uid.slice(0, 6)}, {text: can.base.TimeTrim(value.created_at||value.updated_at)}]},
]
})
},
})

55
src/yuehaoxitong/call.go Normal file
View File

@ -0,0 +1,55 @@
package yuehaoxitong
import (
"shylinux.com/x/ice"
kit "shylinux.com/x/toolkits"
"shylinux.com/x/community/src/yuehaoxitong/model"
)
type call struct {
Tables
schedule schedule
reception reception
call string `name:"call" role:"void"`
expire string `name:"expire" role:"void"`
finish string `name:"finish" role:"void"`
list string `name:"list queue_uid uid reception_uid auto"`
}
func (s call) Call(m *ice.Message, arg ...string) {
if !m.WarnNotRight(!s.CheckRole(m, UserQueueCreator, UserQueueServer)) {
m.Cmdy(s.schedule, s.schedule.Call)
m.PushAction(s.Expire, s.Finish)
}
}
func (s call) Expire(m *ice.Message, arg ...string) {
if !m.WarnNotRight(!s.CheckRole(m, UserQueueCreator, UserQueueServer)) {
m.Cmdy(s.schedule, s.schedule.Expire)
m.ProcessRefresh()
}
}
func (s call) Finish(m *ice.Message, arg ...string) {
if !m.WarnNotRight(!s.CheckRole(m, UserQueueCreator, UserQueueServer)) {
m.Cmdy(s.schedule, s.schedule.Finish)
m.ProcessRefresh()
}
}
func (s call) List(m *ice.Message, arg ...string) {
if len(arg) == 1 {
m.Cmdy(s.schedule, s.schedule.SelectByStatus, arg[0], ScheduleTake).PushAction().Action(s.Call)
kit.If(m.Length() == 0, func() { m.Echo(m.Trans("not found order", "没有等待")) })
} else if len(arg) == 2 {
m.Cmdy(s.schedule, arg[0], arg[1]).Table(func(value ice.Maps) {
if value[model.SCHEDULE_STATUS] == ScheduleCall.String() {
m.PushButton(s.Expire, s.Finish)
} else {
m.PushButton()
}
}).Action(s.Call)
} else if len(arg) == 3 {
m.Cmdy(s.schedule, s.Select, model.QUEUE_UID, arg[0], model.STATUS, ScheduleTake, model.RECEPTION_UID, arg[2]).PushAction().Action(s.Call)
}
}
func init() { ice.TeamCtxCmd(call{}) }

View File

@ -0,0 +1,65 @@
package yuehaoxitong
import (
"shylinux.com/x/ice"
kit "shylinux.com/x/toolkits"
"shylinux.com/x/community/src/yuehaoxitong/model"
"shylinux.com/x/enterprise/src/guanlixitong"
)
type Tables struct {
guanlixitong.Tables
list string `name:"list queue_uid uid auto" role:"void"`
}
func (s Tables) CheckRole(m *ice.Message, arg ...UserQueueRole) bool {
return Table{}.CheckRole(m, arg...)
}
func (s Tables) RewriteAppend(m *ice.Message, arg ...string) *ice.Message {
return Table{}.RewriteAppend(m, arg...)
}
type Table struct {
guanlixitong.Table
list string `name:"list queue_uid uid auto" role:"void"`
}
func (s Table) Inputs(m *ice.Message, arg ...string) {
switch arg[0] {
case model.QUEUE_TYPE:
for k, v := range QueueTypeList {
m.Push(arg[0], k).Push(model.NAME, v)
}
m.SortInt(arg[0]).DisplayInputKeyNameIconTitle()
case model.USER_QUEUE_ROLE:
for k, v := range UserQueueRoleList {
if k != UserQueueCreator && k != UserQueueVisitor {
m.Push(arg[0], k).Push(model.NAME, v)
}
}
m.SortInt(arg[0]).DisplayInputKeyNameIconTitle()
default:
s.Table.Inputs(m, arg...)
}
}
func (s Table) CheckRole(m *ice.Message, arg ...UserQueueRole) bool {
kit.If(len(arg) == 0, func() { arg = append(arg, UserQueueCreator, UserQueueManager) })
role := UserQueueRole(kit.Int(m.Cmd(userQueue{}, s.Select, m.OptionSimple(model.QUEUE_UID, model.USER_UID)).Append(model.ROLE)))
for _, v := range arg {
if role == v {
return true
}
}
return false
}
func (s Table) RewriteAppend(m *ice.Message, arg ...string) *ice.Message {
m.RewriteAppend(func(value, key string, index int) string {
kit.If(key == model.QUEUE_TYPE, func() { value = QueueType(kit.Int(value)).String() })
kit.If(key == model.USER_QUEUE_ROLE, func() { value = UserQueueRole(kit.Int(value)).String() })
kit.If(key == model.SCHEDULE_STATUS, func() { value = ScheduleStatus(kit.Int(value)).String() })
return value
})
s.Table.RewriteAppend(m)
return m
}

View File

@ -0,0 +1,16 @@
package yuehaoxitong
import (
"shylinux.com/x/ice"
)
type history struct {
Tables
schedule schedule
}
func (s history) List(m *ice.Message, arg ...string) {
m.Cmdy(s.schedule, arg)
}
func init() { ice.TeamCtxCmd(history{}) }

View File

@ -0,0 +1,74 @@
package model
import "shylinux.com/x/mysql-story/src/db"
const (
UID = "uid"
NAME = "name"
TYPE = "type"
ROLE = "role"
STATUS = "status"
CONTENT = "content"
CREATED_AT = "created_at"
USER_UID = "user_uid"
USER_QUEUE_ROLE = "user_queue_role"
QUEUE_UID = "queue_uid"
QUEUE_NAME = "queue_name"
QUEUE_TYPE = "queue_type"
RECEPTION_UID = "reception_uid"
RECEPTION_NAME = "reception_name"
SCHEDULE_UID = "schedule_uid"
SCHEDULE_STATUS = "schedule_status"
COMPANY_UID = "company_uid"
BEGIN_TIME = "begin_time"
END_TIME = "end_time"
CANCEL_TIME = "cancel_time"
TAKE_TIME = "take_time"
CALL_TIME = "call_time"
FINISH_TIME = "finish_time"
AMOUNT = "amount"
COUNT = "count"
)
type UserQueue struct {
db.ModelWithUID
UserUID string `gorm:"type:char(32);index"`
QueueUID string `gorm:"type:char(32);index"`
Role uint8
}
type Queue struct {
db.ModelWithUID
CompanyUID string `gorm:"type:char(32);index"`
Name string `gorm:"type:varchar(255)"`
Type uint8
}
type Reception struct {
db.ModelWithUID
QueueUID string `gorm:"type:char(32);index"`
Name string `gorm:"type:varchar(255)"`
}
type Volume struct {
db.ModelWithUID
QueueUID string `gorm:"type:char(32);index"`
ReceptionUID string `gorm:"type:char(32)"`
BeginTime db.Time
EndTime db.Time
Amount int
Count int
}
type Schedule struct {
db.ModelWithUID
QueueUID string `gorm:"type:char(32);index:idx_queue"`
ReceptionUID string `gorm:"type:char(32);index:idx_queue"`
VolumeUID string `gorm:"type:char(32);index:idx_queue"`
UserUID string `gorm:"type:char(32);index"`
BeginTime db.Time
EndTime db.Time
CancelTime db.Time
TakeTime db.Time
CallTime db.Time
FinishTime db.Time
Status uint8
}
func init() { db.CmdModels("", &UserQueue{}, &Queue{}, &Reception{}, Volume{}, &Schedule{}) }

32
src/yuehaoxitong/open.go Normal file
View File

@ -0,0 +1,32 @@
package yuehaoxitong
import (
"shylinux.com/x/ice"
"shylinux.com/x/community/src/yuehaoxitong/model"
)
type open struct {
Tables
volume volume
create string `name:"plan reception_uid* amount* begin_time@date end_time@date" role:"void"`
}
func (s open) Create(m *ice.Message, arg ...string) {
if !m.WarnNotRight(!s.CheckRole(m)) {
m.Cmd(s.volume, s.Create, arg, m.OptionSimple(model.QUEUE_UID))
}
}
func (s open) List(m *ice.Message, arg ...string) {
if !m.WarnNotRight(!s.CheckRole(m.Options(model.QUEUE_UID, arg[0]))) {
m.Cmdy(s.volume, arg)
if m.Length() == 0 {
m.SetResult()
m.EchoInfoButton(m.Trans("please create open", "请创建放号"), s.Create)
} else {
m.Action(s.Create)
}
}
}
func init() { ice.TeamCtxCmd(open{}) }

29
src/yuehaoxitong/plan.go Normal file
View File

@ -0,0 +1,29 @@
package yuehaoxitong
import (
"shylinux.com/x/ice"
kit "shylinux.com/x/toolkits"
"shylinux.com/x/community/src/yuehaoxitong/model"
)
type plan struct {
Tables
volume volume
schedule schedule
create string `name:"create reception_uid* volume_uid*" role:"void"`
cancel string `name:"cancel" role:"void"`
}
func (s plan) Create(m *ice.Message, arg ...string) {
m.Cmd(s.schedule, s.Create, arg, m.OptionSimple(model.QUEUE_UID, model.USER_UID), model.STATUS, SchedulePlan)
}
func (s plan) Cancel(m *ice.Message, arg ...string) {
m.Cmd(s.schedule, s.Cancel)
}
func (s plan) List(m *ice.Message, arg ...string) {
m.Cmdy(s.schedule, s.schedule.SelectByStatus, arg[0], SchedulePlan, m.OptionSimple(model.USER_UID)).PushAction(s.Cancel)
kit.If(m.Length() == 0, func() { m.EchoInfoButton(m.Trans("please create schedule", "请创建预约"), s.Create) })
}
func init() { ice.TeamCtxCmd(plan{}) }

View File

@ -0,0 +1,17 @@
package yuehaoxitong
import (
"shylinux.com/x/community/src/gonganxitong"
"shylinux.com/x/enterprise/src/guanlixitong"
)
type Portal struct {
gonganxitong.Portal
name string `data:"约号系统"`
list string `name:"list queue_uid index uid auto" role:"void"`
placeCreate string `name:"placeCreate city_name* company_name* name*" role:"void"`
}
func init() {
gonganxitong.PortalCmd(Portal{Portal: gonganxitong.NewPortal(userQueue{}, queue{}, guanlixitong.Company{})})
}

View File

@ -0,0 +1,64 @@
{
"portal": "约号系统",
"placeCreate": "创建场景",
"placeRemove": "删除场景",
"reception": "服务接待",
"volume": "服务计划",
"schedule": "订单数据",
"history": "我的订单",
"open": "放号",
"plan": "约号",
"take": "取号",
"call": "叫号",
"expire": "过号",
"finish": "完成",
"icons": {
"reception": "https://img.icons8.com/officel/80/meeting-room.png",
"volume": "https://img.icons8.com/officel/80/combo-chart.png",
"schedule": "https://img.icons8.com/officel/80/List-of-parts.png",
"history": "https://img.icons8.com/officel/80/order-history.png",
"open": "https://img.icons8.com/officel/80/open-sign.png",
"plan": "https://img.icons8.com/officel/80/calendar-plus.png",
"take": "https://img.icons8.com/officel/80/receipt.png",
"call": "https://img.icons8.com/officel/80/calling.png"
},
"style": {
"expire": "danger"
},
"input": {
"My Queue": "我的场景",
"user_queue_role": "用户角色",
"queue_uid": "场景",
"queue_name": "场景名称",
"queue_type": "场景类型",
"reception_uid": "服务接待",
"reception_name": "服务接待",
"volume_uid": "服务时间",
"schedule_status": "订单状态",
"amount": "放号总量",
"count": "约号数量",
"take_time": "取号时间",
"call_time": "叫号时间"
},
"value": {
"schedule_status": {
"plan": "已预约",
"cancel": "已取消",
"take": "已取号",
"call": "已叫号",
"expire": "已过号",
"finish": "已完成"
},
"user_queue_role": {
"creator": "创建人",
"visitor": "访客",
"manager": "管理员",
"server": "服务员",
"waiter": "接待员"
},
"queue_type": {
"public": "公开预约",
"private": "会员预约"
}
}
}

View File

@ -0,0 +1,3 @@
chapter "约号系统"
field web.code.mysql.query args `mysql yuehaoxitong`

21
src/yuehaoxitong/queue.go Normal file
View File

@ -0,0 +1,21 @@
package yuehaoxitong
import "shylinux.com/x/ice"
type queue struct{ Table }
func init() { ice.TeamCtxCmd(queue{}) }
type QueueType int
const (
QueuePublic QueueType = iota
QueuePrivate
)
var QueueTypeList = map[QueueType]string{
QueuePublic: "public",
QueuePrivate: "private",
}
func (s QueueType) String() string { return QueueTypeList[s] }

View File

@ -0,0 +1,52 @@
package yuehaoxitong
import (
"shylinux.com/x/ice"
"shylinux.com/x/icebergs/base/mdb"
kit "shylinux.com/x/toolkits"
"shylinux.com/x/community/src/yuehaoxitong/model"
)
type reception struct {
Table
userQueue userQueue
portal string `data:"true"`
create string `name:"create name*" role:"void"`
rename string `name:"rename name*" role:"void"`
delete string `name:"delete" role:"void"`
}
func (s reception) Create(m *ice.Message, arg ...string) {
if !m.WarnNotRight(!s.CheckRole(m)) {
s.Table.Create(m, append(arg, m.OptionSimple(model.QUEUE_UID)...)...)
s.RecordEvent(m, m.Option(model.QUEUE_UID), kit.Format(m.Trans("create reception %s", "创建服务接待 %s"), m.Option(mdb.NAME)), arg...)
}
}
func (s reception) Rename(m *ice.Message, arg ...string) {
if !m.WarnNotRight(!s.CheckRole(m)) {
s.Table.Rename(m.Spawn())
s.RecordEvent(m, m.Option(model.QUEUE_UID), kit.Format(m.Trans("rename reception %s", "重命名服务接待 %s"), m.Option(mdb.NAME)), arg...)
}
}
func (s reception) Delete(m *ice.Message, arg ...string) {
if !m.WarnNotRight(!s.CheckRole(m)) {
s.Table.Delete(m.Spawn(), m.OptionSimple(model.UID)...)
s.RecordEvent(m, m.Option(model.QUEUE_UID), kit.Format(m.Trans("delete reception %s", "删除服务接待 %s"), m.Option(mdb.NAME)), arg...)
}
}
func (s reception) List(m *ice.Message, arg ...string) {
s.Table.Fields(m, model.UID, model.NAME, model.CREATED_AT)
if len(arg) == 0 {
if m.Option(model.QUEUE_UID) != "" {
s.Table.Select(m, m.OptionSimple(model.QUEUE_UID)...)
}
} else if len(arg) == 1 {
s.Table.Select(m, model.QUEUE_UID, arg[0]).Action(s.Create)
} else if len(arg) == 2 {
s.Table.SelectDetail(m, model.QUEUE_UID, arg[0], model.UID, arg[1])
}
m.PushAction(s.Rename, s.Delete)
}
func init() { ice.TeamCtxCmd(reception{}) }

View File

@ -0,0 +1,104 @@
package yuehaoxitong
import (
"shylinux.com/x/ice"
kit "shylinux.com/x/toolkits"
"shylinux.com/x/community/src/yuehaoxitong/model"
)
type schedule struct {
Table
queue queue
userQueue userQueue
volume volume
reception reception
portal string `data:"true"`
plan string `name:"plan begin_time@date end_time@date"`
}
func (s schedule) Plan(m *ice.Message, arg ...string) {
arg = kit.TransArgValueTime(arg, model.BEGIN_TIME, model.END_TIME)
s.Table.Create(m, append(arg, m.OptionSimple(model.QUEUE_UID, model.USER_UID)...)...)
}
func (s schedule) Call(m *ice.Message, arg ...string) {
s.Orders(m, model.TAKE_TIME).Limit(m, 1)
s.SelectByStatus(m, m.Option(model.QUEUE_UID), kit.Format(ScheduleTake))
// s.Select(m, kit.Simple(m.OptionSimple(model.QUEUE_UID, model.RECEPTION_UID), mdb.STATUS, ScheduleTake)...)
if m.WarnNotFound(m.Length() == 0) {
return
}
s.ChangeStatus(m, m.Append(model.UID), "", ScheduleTake, ScheduleCall, arg...)
}
func (s schedule) SelectByStatus(m *ice.Message, arg ...string) {
s.Tables(m, s.volume).FieldsWithCreatedAT(m, s,
model.SCHEDULE_STATUS, s.Key(s.volume, model.BEGIN_TIME), s.Key(s.volume, model.END_TIME), s.Key(s, model.RECEPTION_UID), model.USER_UID,
).Orders(m, s.Desc(model.BEGIN_TIME))
s.Select(m, kit.Simple(s.Key(s, model.QUEUE_UID), arg[0], model.STATUS, arg[1], arg[2:])...)
s.RewriteAppend(m)
s.SelectJoin(m, s.reception)
s.SelectJoinUser(m)
}
func (s schedule) List(m *ice.Message, arg ...string) {
if s.CheckRole(m.Options(model.QUEUE_UID, arg[0]), UserQueueCreator, UserQueueServer) {
if len(arg) == 1 {
s.Select(m, model.QUEUE_UID, arg[0])
} else if len(arg) == 2 {
s.SelectDetail(m, model.QUEUE_UID, arg[0], model.UID, arg[1])
}
} else {
if len(arg) == 1 {
s.Select(m, model.QUEUE_UID, arg[0], model.USER_UID, m.Option(model.USER_UID))
} else if len(arg) == 2 {
s.SelectDetail(m, model.QUEUE_UID, arg[0], model.USER_UID, m.Option(model.USER_UID), model.UID, arg[1])
}
}
m.RenameAppend(model.STATUS, model.SCHEDULE_STATUS)
s.RewriteAppend(m)
s.SelectJoin(m, s.reception)
s.SelectJoinUser(m)
kit.If(m.Length() == 0, func() { m.Echo(m.Trans("not found", "没有预约")) })
m.PushAction().Action()
}
func (s schedule) Take(m *ice.Message, arg ...string) {
s.ChangeStatus(m, m.Option(model.UID), "", SchedulePlan, ScheduleTake, arg...)
}
func (s schedule) Cancel(m *ice.Message, arg ...string) {
s.ChangeStatus(m, m.Option(model.UID), "", SchedulePlan, ScheduleTake, arg...)
}
func (s schedule) Expire(m *ice.Message, arg ...string) {
s.ChangeStatus(m, m.Option(model.UID), "", ScheduleCall, ScheduleExpire, arg...)
}
func (s schedule) Finish(m *ice.Message, arg ...string) {
s.ChangeStatus(m, m.Option(model.UID), "", ScheduleCall, ScheduleFinish, arg...)
}
func init() { ice.TeamCtxCmd(schedule{}) }
func (s schedule) ChangeStatus(m *ice.Message, uid, key string, from, to ScheduleStatus, arg ...string) *ice.Message {
kit.If(key == "", func() { key = m.ActionKey() + "_time" })
s.Table.ChangeStatus(m, uid, int(from), int(to), kit.TransArgValueTime(append(arg, key, m.Time()), key)...)
return m
}
type ScheduleStatus int
const (
SchedulePlan ScheduleStatus = iota
ScheduleCancel
ScheduleTake
ScheduleCall
ScheduleExpire
ScheduleFinish
)
var ScheduleStatusList = map[ScheduleStatus]string{
SchedulePlan: "plan",
ScheduleCancel: "cancel",
ScheduleTake: "take",
ScheduleCall: "call",
ScheduleExpire: "expire",
ScheduleFinish: "finish",
}
func (s ScheduleStatus) String() string { return ScheduleStatusList[s] }

View File

@ -0,0 +1,17 @@
Volcanos(chat.ONIMPORT, {
_init: function(can, msg) {
can.onimport.itemcards(can, msg, function(value) {
return [
{view: html.TITLE, list:[{text: [value.name||value.user_name]}, {text: value.reception_name},
{text: [can.user.transValue(can, value, "schedule_status"), "", [mdb.STATUS, value.schedule_status]]},
]},
{view: html.STATUS, list: [value.uid && {text: value.uid.slice(0, 6)}, {text: can.base.TimeTrim(value.created_at||value.updated_at)}]},
value.begin_time && {view: html.TITLE, list: [{text: "开始时间:"}, {text: value.begin_time}]},
value.end_time && {view: html.TITLE, list: [{text: "结束时间:"}, {text: value.end_time}]},
value.take_time && {view: html.TITLE, list: [{text: "取号时间:"}, {text: value.take_time}]},
value.call_time && {view: html.TITLE, list: [{text: "叫号时间:"}, {text: value.call_time}]},
value.finish_time && {view: html.TITLE, list: [{text: "完成时间:"}, {text: value.finish_time}]},
]
})
},
})

24
src/yuehaoxitong/take.go Normal file
View File

@ -0,0 +1,24 @@
package yuehaoxitong
import (
"shylinux.com/x/ice"
kit "shylinux.com/x/toolkits"
"shylinux.com/x/community/src/yuehaoxitong/model"
)
type take struct {
Tables
schedule schedule
take string `name:"take" role:"void"`
}
func (s take) Take(m *ice.Message, arg ...string) {
m.Cmd(s.schedule, s.schedule.Take)
}
func (s take) List(m *ice.Message, arg ...string) {
m.Cmdy(s.schedule, s.schedule.SelectByStatus, arg[0], SchedulePlan, m.OptionSimple(model.USER_UID)).PushAction(s.Take).Action()
kit.If(m.Length() == 0, func() { m.Echo(m.Trans("not found plan", "没有预约")) })
}
func init() { ice.TeamCtxCmd(take{}) }

View File

@ -0,0 +1,63 @@
package yuehaoxitong
import (
"shylinux.com/x/ice"
"shylinux.com/x/community/src/yuehaoxitong/model"
)
type userQueue struct {
Table
queue queue
}
func (s userQueue) User(m *ice.Message, arg ...string) {
if len(arg) == 1 {
s.Select(m, model.QUEUE_UID, arg[0])
} else if len(arg) == 2 {
s.Select(m, model.QUEUE_UID, arg[0], model.UID, arg[1])
} else {
return
}
m.RenameAppend(model.ROLE, model.USER_QUEUE_ROLE)
s.SelectJoinUser(m)
s.RewriteAppend(m)
}
func (s userQueue) List(m *ice.Message, arg ...string) {
s.Tables(m, s.queue).FieldsWithCreatedAT(m, s,
model.QUEUE_NAME, model.QUEUE_TYPE, model.USER_QUEUE_ROLE,
model.QUEUE_UID, model.COMPANY_UID,
)
if len(arg) == 1 {
s.Select(m, model.USER_UID, arg[0])
} else if len(arg) == 2 {
s.SelectDetail(m, model.USER_UID, arg[0], s.Key(s.queue, model.UID), arg[1])
} else {
return
}
s.SelectJoinCompany(m)
s.SelectJoinCity(m)
s.RewriteAppend(m)
}
func init() { ice.TeamCtxCmd(userQueue{}) }
type UserQueueRole int
const (
UserQueueCreator UserQueueRole = iota
UserQueueVisitor
UserQueueManager
UserQueueServer
UserQueueWaiter
)
var UserQueueRoleList = map[UserQueueRole]string{
UserQueueCreator: "creator",
UserQueueVisitor: "visitor",
UserQueueManager: "manager",
UserQueueServer: "server",
UserQueueWaiter: "waiter",
}
func (s UserQueueRole) String() string { return UserQueueRoleList[s] }

View File

@ -0,0 +1,38 @@
package yuehaoxitong
import (
"shylinux.com/x/ice"
"shylinux.com/x/toolkits"
"shylinux.com/x/community/src/yuehaoxitong/model"
)
type volume struct {
Table
reception reception
portal string `data:"true"`
}
func (s volume) List(m *ice.Message, arg ...string) {
if len(arg) == 0 {
if m.Option(model.RECEPTION_UID) != "" {
s.Fields(m, model.UID, model.BEGIN_TIME)
s.Select(m, m.OptionSimple(model.QUEUE_UID, model.RECEPTION_UID)...)
}
} else {
s.Tables(m, s.reception).FieldsWithCreatedAT(m, s,
model.RECEPTION_NAME,
model.AMOUNT, model.COUNT,
model.BEGIN_TIME, model.END_TIME,
)
if len(arg) == 1 {
s.Select(m, s.Key(s, model.QUEUE_UID), arg[0])
} else if len(arg) == 2 {
s.SelectDetail(m, s.Key(s, model.QUEUE_UID), arg[0], s.Key(s, model.UID), arg[1])
}
kit.If(m.Length() == 0, func() { m.Echo(m.Trans("not found", "没有放号")) })
m.Action()
}
}
func init() { ice.TeamCtxCmd(volume{}) }

View File

@ -0,0 +1,12 @@
Volcanos(chat.ONIMPORT, {
_init: function(can, msg) {
can.onimport.itemcards(can, msg, function(value) {
return [
{view: html.TITLE, list:[{text: value.reception_name}]},
{view: html.STATUS, list:[{text: "放号量: "}, {text: value.amount}, {text: "预约量: "}, {text: value.count||"0"}]},
{view: html.TITLE, list:[{text: "开始时间:"}, {text: value.begin_time}]},
{view: html.TITLE, list:[{text: "结束时间:"}, {text: value.end_time}]},
]
})
},
})

View File

@ -1,4 +1,11 @@
{
"258cd1f28422794acd8081ae19aa2e4c": {
"meta": {
"index": "web.team.yuehaoxitong5.portal",
"time": "2024-08-07 13:12:40.469",
"type": "hash"
}
},
"2f91065050f787e1e3b8aa5338ddd16b": {
"meta": {
"index": "web.chat.email.client",
@ -6,6 +13,13 @@
"type": "hash"
}
},
"4b1e97b62a44419c00caf65e297abd18": {
"meta": {
"index": "web.team.guanlixitong.portal",
"time": "2024-08-07 08:09:09.541",
"type": "hash"
}
},
"63c64bf8b1b104e2db3493f457fd48a7": {
"meta": {
"index": "aaa.asign",
@ -13,11 +27,67 @@
"type": "hash"
}
},
"6460b54238e104a6be50a397439850f7": {
"meta": {
"index": "web.team.yuehaoxitong20.portal",
"time": "2024-08-07 19:38:04.852",
"type": "hash"
}
},
"858d6327b7710c5c11df1d4f8a1eb754": {
"meta": {
"index": "web.team.yuehaoxitong2.portal",
"time": "2024-08-07 12:51:44.501",
"type": "hash"
}
},
"9a78f21b2809d8bf2bd0f4fad444a88f": {
"meta": {
"index": "web.team.yuehaoxitong4.portal",
"time": "2024-08-07 13:09:37.550",
"type": "hash"
}
},
"9da3f877eb2450316371f4edc1c93b26": {
"meta": {
"index": "web.team.gonganxitong.portal",
"time": "2024-07-28 15:51:31.253",
"type": "hash"
}
},
"a6bcf58de9f87b0af0d842a52ba9d89a": {
"meta": {
"index": "web.team.yuehaoxitong11.portal",
"time": "2024-08-07 18:29:15.954",
"type": "hash"
}
},
"a9d7661af8cea7074062565dbd27ff83": {
"meta": {
"index": "web.team.yuehaoxitong.portal",
"time": "2024-08-07 08:09:09.554",
"type": "hash"
}
},
"b71940bd397870fd772e2cbe8ce8f0d3": {
"meta": {
"index": "web.team.yuehaoxitong3.portal",
"time": "2024-08-07 13:05:16.811",
"type": "hash"
}
},
"ea215091c9be95050ec8bcda532e95fe": {
"meta": {
"index": "web.team.yuehaoxitong1.portal",
"time": "2024-08-07 11:44:12.464",
"type": "hash"
}
},
"faed481fec1a5ad8dd3ad44f0577e903": {
"meta": {
"index": "web.team.yuehaoxitong10.portal",
"time": "2024-08-07 18:05:36.247",
"type": "hash"
}
}
}

View File

@ -25,7 +25,7 @@
"index": "web.team.gonganxitong.express.express",
"name": "收发快递",
"order": "6",
"time": "2024-08-06 18:55:46.304"
"time": "2024-08-07 23:29:49.682"
}
},
"58724bdcc3cae3e26700cb3199e0602c": {
@ -36,7 +36,7 @@
"name": "场景用户",
"order": "5",
"role": "creator,landlord",
"time": "2024-08-06 18:55:46.299"
"time": "2024-08-07 19:32:54.758"
}
},
"91dd0e9590d3021944f14f3ec8653beb": {
@ -77,7 +77,7 @@
"icons": "https://img.icons8.com/officel/80/reading-confirmation.png",
"index": "web.team.gonganxitong.email",
"name": "邮箱配置",
"time": "2024-08-06 18:35:38.637"
"time": "2024-08-07 00:38:52.287"
}
}
}