From f1ab27b59571812bcde393c546c69073b7941feb Mon Sep 17 00:00:00 2001 From: shy Date: Sat, 15 Mar 2025 13:16:15 +0800 Subject: [PATCH] add some --- src/operation/cluster.go | 54 +++++++++++++++++------- src/operation/common.go | 8 ++++ src/operation/gateway.go | 10 ++++- src/operation/model/model.go | 22 +++++++--- src/operation/portal.json | 11 ++++- src/operation/product.go | 2 +- src/operation/project.go | 2 +- src/operation/template.go | 81 ++++++++++++++++++++++++++++++++++++ src/operation/template.js | 9 ++++ 9 files changed, 175 insertions(+), 24 deletions(-) create mode 100644 src/operation/template.go create mode 100644 src/operation/template.js diff --git a/src/operation/cluster.go b/src/operation/cluster.go index 030c3ae..d57a1b0 100644 --- a/src/operation/cluster.go +++ b/src/operation/cluster.go @@ -11,23 +11,27 @@ import ( type Cluster struct { Table - travel travel.Travel - order string `data:"1"` - fields string `data:"title,content,space,total,stock,price"` - payfor string `name:"payfor" help:"购买" style:"notice" role:"leader"` - scanService string `name:"scanService" help:"扫描"` - modify string `name:"modify title content price" style:"danger"` + travel travel.Travel + order string `data:"1"` + fields string `data:"title,content,space,total,stock,price,cluster_status"` + payfor string `name:"payfor" help:"购买" style:"notice" role:"leader"` + modify string `name:"modify title content price" style:"danger"` } func (s Cluster) Scan(m *ice.Message, arg ...string) { m.Cmd(s.travel, s.travel.Concurrent, ice.GetTypeMod(s.travel), ice.GetTypeKey(s.travel)).Table(func(value ice.Maps) { s.InsertIfNeed(m, web.SPACE, value[web.SPACE]) }) + m.Cmd("").Table(func(value ice.Maps) { s.ScanService(m.Options(value)) }) m.ProcessRefresh() } func (s Cluster) List(m *ice.Message, arg ...string) { - if len(arg) == 1 { - s.Select(m) + if len(arg) < 2 { + if m.IsTech() { + s.Select(m) + } else { + s.Select(m, model.STATUS, kit.Format(ClusterOnline)) + } } else { s.SelectDetail(m, model.UID, arg[1]) } @@ -35,20 +39,20 @@ func (s Cluster) List(m *ice.Message, arg ...string) { if m.IsTech() { m.EchoInfoButton("请扫描集群", s.Scan) } else { - m.Echo("请联系平台管理员部署集群").Action() + m.Echo("请联系「平台管理员」部署集群").Action() } } else { if m.Display(""); m.IsTech() { m.Table(func(value ice.Maps) { - if kit.Int(value[model.STOCK]) > 0 { - m.PushButton(s.Payfor, s.ScanService, s.Modify) + if ClusterStatus(kit.Int(value[model.CLUSTER_STATUS])) == ClusterOnline && kit.Int(value[model.STOCK]) > 0 { + m.PushButton(s.Payfor, s.ScanService, s.Offline, s.Modify) } else { - m.PushButton(s.ScanService, s.Modify) + m.PushButton(s.ScanService, s.Online, s.Modify) } }).Action(s.Scan) } else if s.IsLeader(m) { m.Table(func(value ice.Maps) { - if kit.Int(value[model.STOCK]) > 0 { + if ClusterStatus(kit.Int(value[model.CLUSTER_STATUS])) == ClusterOnline && kit.Int(value[model.STOCK]) > 0 { m.PushButton(s.Payfor) } else { m.PushButton() @@ -69,9 +73,31 @@ func (s Cluster) ScanService(m *ice.Message, arg ...string) { m.Cmdy(Gateway{}, s.Scan, arg, kit.Dict(model.CLUSTER_UID, m.Option(model.UID))).ProcessRefresh() s.Update(m, m.AppendSimple(model.TOTAL, model.STOCK), m.OptionSimple(model.UID)...) } +func (s Cluster) Offline(m *ice.Message, arg ...string) { + s.Update(m, []string{model.STATUS, kit.Format(ClusterOffline)}) + s.RecordEventWithName(m, "") +} +func (s Cluster) Online(m *ice.Message, arg ...string) { + s.Update(m, []string{model.STATUS, kit.Format(ClusterOnline)}) + s.RecordEventWithName(m, "") +} func (s Cluster) Modify(m *ice.Message, arg ...string) { - s.Update(m, s.TransPrice(m, arg), m.OptionSimple(model.UID)...) + s.Update(m, s.TransPrice(m, arg)) s.RecordEventWithName(m, "") } func init() { ice.TeamCtxCmd(Cluster{}) } + +type ClusterStatus int + +const ( + ClusterOffline ClusterStatus = iota + ClusterOnline +) + +var ClusterStatusList = map[ClusterStatus]string{ + ClusterOffline: "offline", + ClusterOnline: "online", +} + +func (s ClusterStatus) String() string { return ClusterStatusList[s] } diff --git a/src/operation/common.go b/src/operation/common.go index 462f60f..1214772 100644 --- a/src/operation/common.go +++ b/src/operation/common.go @@ -20,6 +20,10 @@ func (s Table) Inputs(m *ice.Message, arg ...string) { s.InputsListRole(m, UserCloudRoleList, arg...) case model.CLOUD_TYPE: s.InputsList(m, CloudTypeList, arg...) + case model.GATEWAY_UID: + m.Cmdy(Gateway{}, m.Option(model.CLOUD_UID)).Cut(model.UID, model.TITLE) + m.RenameAppend(model.UID, arg[0], model.TITLE, model.NAME) + m.DisplayInputKeyNameIconTitle() default: s.Table.Inputs(m, arg...) } @@ -31,6 +35,10 @@ func (s Table) RewriteAppend(m *ice.Message, arg ...string) *ice.Message { value = UserCloudRole(kit.Int(value)).String() case model.CLOUD_TYPE: value = CloudType(kit.Int(value)).String() + case model.CLUSTER_STATUS: + value = ClusterStatus(kit.Int(value)).String() + case model.TEMPLATE_STATUS: + value = TemplateStatus(kit.Int(value)).String() case model.PRICE: value = kit.Format("%.2f", kit.Float(value)/100) } diff --git a/src/operation/gateway.go b/src/operation/gateway.go index 18aba50..da0a995 100644 --- a/src/operation/gateway.go +++ b/src/operation/gateway.go @@ -29,12 +29,18 @@ func (s Gateway) List(m *ice.Message, arg ...string) { if s.ValueList(m, arg); s.IsLeader(m) { m.PushAction(s.CreateProject, s.ScanProject, s.Open, s.Modify) } else if s.IsWorker(m) { - m.PushAction(s.CreateProject, s.ScanProject) + m.PushAction(s.CreateProject) } else { m.PushAction() } if m.Action(); m.Length() == 0 { - m.Echo("请到「云集群」购买主机") + if m.SetResult(); s.IsLeader(m) { + m.Echo("请到「云集群」购买主机") + } else if s.IsWorker(m) { + m.Echo("请联系「管理员」购买主机") + } else { + m.Echo("请等待「管理员」购买主机") + } } else { s.Fields(m, model.UID, s.KeyAS(s.cluster, model.SPACE)).SelectJoin(m, s.cluster, s.Keys(s.cluster, model.SPACE)).Display("") } diff --git a/src/operation/model/model.go b/src/operation/model/model.go index 6dc4fad..92a822e 100644 --- a/src/operation/model/model.go +++ b/src/operation/model/model.go @@ -8,6 +8,7 @@ const ( INFO = "info" TYPE = "type" ROLE = "role" + STATUS = "status" TOTAL = "total" STOCK = "stock" PRICE = "price" @@ -20,6 +21,8 @@ const ( CLOUD_TYPE = "cloud_type" CLUSTER_UID = "cluster_uid" CLUSTER_SPACE = "cluster_space" + CLUSTER_STATUS = "cluster_status" + TEMPLATE_STATUS = "template_status" GATEWAY_UID = "gateway_uid" GATEWAY_SPACE = "gateway_space" PROJECT_UID = "project_uid" @@ -36,10 +39,11 @@ type Cloud struct { } type Cluster struct { db.ModelContent - Space string `gorm:"type:varchar(64);index"` - Total int - Stock int - Price int + Space string `gorm:"type:varchar(64);index"` + Total int `gorm:"default:0"` + Stock int `gorm:"default:0"` + Price int `gorm:"default:0"` + Status uint8 `gorm:"default:0"` } type Gateway struct { db.ModelContent @@ -47,6 +51,12 @@ type Gateway struct { CloudUID string `gorm:"type:char(32);index"` ClusterUID string `gorm:"type:char(32);index"` } +type Template struct { + db.ModelNameInfo + Repos string `gorm:"type:varchar(255)"` + Binary string `gorm:"type:varchar(255)"` + Status uint8 `gorm:"default:0"` +} type Project struct { db.ModelNameInfo Repos string `gorm:"type:varchar(255)"` @@ -62,4 +72,6 @@ type Product struct { ProjectUID string `gorm:"type:char(32);index"` } -func init() { db.CmdModels("", &UserCloud{}, &Cloud{}, &Cluster{}, &Gateway{}, &Project{}, &Product{}) } +func init() { + db.CmdModels("", &UserCloud{}, &Cloud{}, &Cluster{}, &Gateway{}, &Template{}, &Project{}, &Product{}) +} diff --git a/src/operation/portal.json b/src/operation/portal.json index 35c6167..56e7b2a 100644 --- a/src/operation/portal.json +++ b/src/operation/portal.json @@ -1,9 +1,14 @@ { "portal": "系统运维", - "cluster": "云集群", "gateway": "云主机", "project": "云项目", "product": "云服务", + "cluster": "云集群", "gateway": "云主机", "template": "云模板", "project": "云项目", "product": "云服务", + "scanService": "扫描", "offline": "下架", "online": "上架", + "style": { + "offline": "danger" + }, "icons": { "cluster": "https://img.icons8.com/officel/80/activity-grid.png", "gateway": "https://img.icons8.com/officel/80/activity-grid.png", + "template": "https://img.icons8.com/officel/80/activity-grid.png", "project": "https://img.icons8.com/officel/80/activity-grid.png", "product": "https://img.icons8.com/officel/80/activity-grid.png" }, @@ -13,6 +18,10 @@ "cloud_name": "系统名称", "cloud_type": "系统类型", "cloud_space": "集群空间", + "cluster_status": "集群状态", + "cluster_space": "集群空间", + "template_status": "模板状态", + "gateway_uid": "云主机", "gateway_title": "云主机", "gateway_space": "主机空间", "project_name": "项目名称", diff --git a/src/operation/product.go b/src/operation/product.go index 03174bd..a5e2086 100644 --- a/src/operation/product.go +++ b/src/operation/product.go @@ -16,7 +16,7 @@ type product struct { cluster Cluster gateway Gateway project project - order string `data:"4"` + order string `data:"5"` fields string `data:"name,icon,index,project_uid"` open string `name:"open" style:"notice" role:"void"` } diff --git a/src/operation/project.go b/src/operation/project.go index a6f1bfd..69e87a9 100644 --- a/src/operation/project.go +++ b/src/operation/project.go @@ -15,7 +15,7 @@ type project struct { Table cluster Cluster gateway Gateway - order string `data:"3"` + order string `data:"4"` fields string `data:"name,repos,binary,gateway_uid"` create string `name:"create name* repos binary" style:"notice" role:"worker"` scanProduct string `name:"scanProduct" help:"扫描" role:"worker"` diff --git a/src/operation/template.go b/src/operation/template.go new file mode 100644 index 0000000..38b71bb --- /dev/null +++ b/src/operation/template.go @@ -0,0 +1,81 @@ +package operation + +import ( + "shylinux.com/x/ice" + kit "shylinux.com/x/toolkits" + + "shylinux.com/x/operation/src/operation/model" +) + +type template struct { + Table + order string `data:"3"` + fields string `data:"name,info,repos,binary,template_status"` + create string `name:"create name* info repos* binary*"` + modify string `name:"modify name* info repos* binary*" style:"danger"` + install string `name:"install gateway_uid* name*" style:"notice" role:"worker"` +} + +func (s template) Create(m *ice.Message, arg ...string) { + s.Insert(m, arg...) +} +func (s template) List(m *ice.Message, arg ...string) { + if m.IsTech() { + if len(arg) < 2 { + s.Select(m) + } else { + s.SelectDetail(m, model.UID, arg[1]) + } + m.Table(func(value ice.Maps) { + if TemplateStatus(kit.Int(value[model.TEMPLATE_STATUS])) == TemplateOffline { + m.PushButton(s.Online, s.Modify) + } else { + m.PushButton(s.Install, s.Offline, s.Modify) + } + }) + if m.Length() == 0 { + s.Button(m, "") + } + } else { + if len(arg) < 2 { + s.Select(m, model.STATUS, kit.Format(TemplateOnline)) + } else { + s.SelectDetail(m, model.UID, arg[1]) + } + if m.PushAction(s.Install).Action(); m.Length() == 0 { + m.Echo("请等待「平台管理员」创建模板") + } + } + m.Display("") +} +func (s template) Install(m *ice.Message, arg ...string) { + m.Cmdy(project{}, s.Create, m.OptionSimple("name,repos,binary")) +} +func (s template) Offline(m *ice.Message, arg ...string) { + s.Update(m, []string{model.STATUS, kit.Format(TemplateOffline)}) + s.RecordEventWithName(m, "") +} +func (s template) Online(m *ice.Message, arg ...string) { + s.Update(m, []string{model.STATUS, kit.Format(TemplateOnline)}) + s.RecordEventWithName(m, "") +} +func (s template) Modify(m *ice.Message, arg ...string) { + s.Update(m, arg) + s.RecordEventWithName(m, "") +} + +func init() { ice.TeamCtxCmd(template{}) } + +type TemplateStatus int + +const ( + TemplateOffline TemplateStatus = iota + TemplateOnline +) + +var TemplateStatusList = map[TemplateStatus]string{ + TemplateOffline: "offline", + TemplateOnline: "online", +} + +func (s TemplateStatus) String() string { return TemplateStatusList[s] } diff --git a/src/operation/template.js b/src/operation/template.js new file mode 100644 index 0000000..97495ff --- /dev/null +++ b/src/operation/template.js @@ -0,0 +1,9 @@ +Volcanos(chat.ONIMPORT, { + _init: function(can, msg) { + can.onimport.myView(can, msg, function(value) { return [ + {view: html.TITLE, list: [value.name, can.onimport.titleAction(can, value)]}, + {view: html.STATUS, list: [value.uid.slice(0, 6), can.onimport.timeView(can, value)]}, + {view: html.OUTPUT, list: [value.info||value.binary||value.repos]}, + ] }) + }, +}) \ No newline at end of file