This commit is contained in:
IT 老营长 @云轩领航-创始人 2025-03-08 08:39:25 +08:00
parent 9941c35ce4
commit 4f5556781d
11 changed files with 147 additions and 89 deletions

View File

@ -9,7 +9,7 @@ import (
"shylinux.com/x/operation/src/operation/model"
)
type cluster struct {
type Cluster struct {
Table
travel travel.Travel
order string `data:"1"`
@ -19,14 +19,19 @@ type cluster struct {
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, "2025-dev.shylinux.com/x/20250215-cluster", "web.chat.dev.cluster.travel").Table(func(value ice.Maps) {
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.ProcessRefresh()
}
func (s cluster) List(m *ice.Message, arg ...string) {
if s.Select(m); m.Length() == 0 {
func (s Cluster) List(m *ice.Message, arg ...string) {
if len(arg) == 1 {
s.Select(m)
} else {
s.SelectDetail(m, model.UID, arg[1])
}
if m.Length() == 0 {
if m.IsTech() {
m.EchoInfoButton("请扫描集群", s.Scan)
} else {
@ -53,19 +58,20 @@ func (s cluster) List(m *ice.Message, arg ...string) {
m.PushAction().Action()
}
}
if len(arg) == 2 && m.IsTech() {
m.EchoIFrame(web.S(m.Append(web.SPACE)))
}
}
func (s cluster) Payfor(m *ice.Message, arg ...string) {
m.Option(model.CLUSTER_UID, m.Option(model.UID))
m.Cmdy(gateway{}, s.Payfor, arg)
func (s Cluster) Payfor(m *ice.Message, arg ...string) {
m.Cmdy(Gateway{}, s.Payfor, arg, kit.Dict(model.CLUSTER_UID, m.Option(model.UID)))
}
func (s cluster) ScanService(m *ice.Message, arg ...string) {
m.Option(model.CLUSTER_UID, m.Option(model.UID))
m.Cmdy(gateway{}, s.Scan, arg)
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)...)
m.ProcessRefresh()
}
func (s cluster) Modify(m *ice.Message, arg ...string) {
func (s Cluster) Modify(m *ice.Message, arg ...string) {
s.Update(m, s.TransPrice(m, arg), m.OptionSimple(model.UID)...)
s.RecordEventWithName(m, "")
}
func init() { ice.TeamCtxCmd(cluster{}) }
func init() { ice.TeamCtxCmd(Cluster{}) }

View File

@ -4,6 +4,6 @@ Volcanos(chat.ONIMPORT, {
{view: html.TITLE, list: [value.title||value.space, value.price+" 元/月", can.onimport.titleAction(can, value)]},
{view: html.STATUS, list: [value.uid.slice(0, 6), can.onimport.timeView(can, value)]},
{view: html.OUTPUT, list: [value.content]},
] }, function() {})
] })
},
})

View File

@ -6,23 +6,26 @@ import (
"shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits"
"2025-dev.shylinux.com/x/20250211-service/src/gateway"
"2025-dev.shylinux.com/x/20250215-cluster/src/travel"
"shylinux.com/x/operation/src/operation/model"
)
type gateway struct {
type Gateway struct {
Table
cluster cluster
cluster Cluster
travel travel.Travel
gateway gateway.Gateway
order string `data:"2"`
fields string `data:"title,content,space,cluster_uid"`
fields string `data:"title,content,space,cluster_uid,user_uid"`
payfor string `name:"payfor" help:"购买" style:"notice" role:"leader"`
createProject string `name:"createProject name* repos binary" help:"创建" style:"notice" role:"worker"`
scanProject string `name:"scanProject" help:"扫描" role:"worker"`
open string `name:"open" role:"leader"`
modify string `name:"modify title content" style:"danger" role:"leader"`
}
func (s gateway) List(m *ice.Message, arg ...string) {
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) {
@ -30,55 +33,53 @@ func (s gateway) List(m *ice.Message, arg ...string) {
} else {
m.PushAction()
}
s.Fields(m, model.UID, s.KeyAS(s.cluster, model.SPACE)).SelectJoin(m, s.cluster, s.Keys(s.cluster, model.SPACE))
if m.Action(); m.Length() == 0 {
m.Echo("请到「云集群」购买主机")
} else {
s.SelectJoinUser(m).Display("")
m.Display("")
}
if len(arg) == 2 && s.IsLeader(m) {
m.EchoIFrame(web.S(s.space(m.Spawn().Options(model.CLOUD_UID, arg[0], model.UID, arg[1]))))
}
}
func (s gateway) CreateProject(m *ice.Message, arg ...string) {
m.Option(web.SPACE, s.space(m))
m.Cmd(project{}, s.Create, arg, model.GATEWAY_UID, m.Option(model.UID))
m.ProcessRefresh()
func (s Gateway) CreateProject(m *ice.Message, arg ...string) {
m.Cmdy(project{}, s.Create, arg, model.GATEWAY_UID, m.Option(model.UID), kit.Dict(web.SPACE, s.space(m))).ProcessRefresh()
}
func (s gateway) ScanProject(m *ice.Message, arg ...string) {
m.Cmd(web.SPACE, s.space(m.Spawn()), web.DREAM).Table(func(value ice.Maps) {
if value[mdb.TYPE] == web.WORKER {
m.Cmd(project{}, s.InsertIfNeed, mdb.NAME, value[mdb.NAME], model.GATEWAY_UID, m.Option(model.UID), m.OptionSimple(model.CLOUD_UID))
}
})
m.ProcessRefresh()
func (s Gateway) ScanProject(m *ice.Message, arg ...string) {
m.Cmdy(project{}, s.Scan, kit.Dict(model.GATEWAY_UID, m.Option(model.UID), web.SPACE, s.space(m.Spawn()))).ProcessRefresh()
}
func (s gateway) Open(m *ice.Message, arg ...string) {
func (s Gateway) Open(m *ice.Message, arg ...string) {
m.ProcessOpen(m.Options(ice.MSG_USERPOD, "").MergePodCmd(s.space(m), web.ADMIN))
}
func (s gateway) Modify(m *ice.Message, arg ...string) {
func (s Gateway) Modify(m *ice.Message, arg ...string) {
s.Update(m, arg, m.OptionSimple(model.CLOUD_UID, model.UID)...)
s.RecordEventWithName(m, "")
}
func init() { ice.TeamCtxCmd(gateway{}) }
func init() { ice.TeamCtxCmd(Gateway{}) }
func (s gateway) Payfor(m *ice.Message, arg ...string) {
func (s Gateway) Payfor(m *ice.Message, arg ...string) {
s.Transaction(m, func() {
msg := m.Spawn()
if msg = s.Orders(msg, "id").Limit(msg, 1).SelectForUpdate(msg, "(cloud_uid IS NULL OR cloud_uid = '') AND (cluster_uid = ?)", m.Option(model.CLUSTER_UID)); msg.Length() == 0 {
if msg = s.Orders(msg, mdb.ID).Limit(msg, 1).SelectForUpdate(msg, "cluster_uid = ? AND (cloud_uid IS NULL OR cloud_uid = '')", m.Option(model.CLUSTER_UID)); msg.Length() == 0 {
m.Echo("主机不够用啦!请等待管理员添加。")
} else {
s.Update(m, m.OptionSimple(model.CLOUD_UID, model.USER_UID), msg.AppendSimple(model.UID)...)
m.Option(model.TITLE, "我的云主机")
s.Update(m, m.OptionSimple(model.CLOUD_UID, model.USER_UID, model.TITLE), msg.AppendSimple(model.UID)...)
s.RecordEventWithName(m.Options(model.UID, msg.Append(model.UID)), "")
s.SendMessage(s.GetCommandUID(m), "", "")
}
})
}
func (s gateway) Scan(m *ice.Message, arg ...string) {
m.Cmd(web.SPACE, m.Option(web.SPACE), s.travel, s.travel.Concurrent, "2025-dev.shylinux.com/x/20250211-service", "web.chat.dev.service.gateway").Table(func(value ice.Maps) {
func (s Gateway) Scan(m *ice.Message, arg ...string) {
m.Cmd(web.SPACE, m.Option(web.SPACE), s.travel, s.travel.Concurrent, ice.GetTypeMod(s.gateway), ice.GetTypeKey(s.gateway)).Table(func(value ice.Maps) {
s.InsertIfNeed(m, web.SPACE, value[web.SPACE], model.CLUSTER_UID, m.Option(model.CLUSTER_UID))
})
s.Fields(m, "count(*) AS total")
s.Select(m, model.CLUSTER_UID, m.Option(model.CLUSTER_UID))
s.Fields(m, "count(*) AS stock")
s.Select(m, "cluster_uid = ? AND (cloud_uid IS NULL OR cloud_uid = '')", m.Option(model.CLUSTER_UID))
m.Info("hwat %v ", m.FormatMeta())
s.Fields(m, "count(*) AS total").Select(m, model.CLUSTER_UID, m.Option(model.CLUSTER_UID))
s.Fields(m, "count(*) AS stock").Select(m, "cluster_uid = ? AND (cloud_uid IS NULL OR cloud_uid = '')", m.Option(model.CLUSTER_UID))
}
func (s gateway) space(m *ice.Message, arg ...string) string {
func (s Gateway) space(m *ice.Message, arg ...string) string {
s.Tables(m, s.cluster).Fields(m, s.Key(s, web.SPACE), s.KeyAS(s.cluster, web.SPACE))
s.Select(m, kit.Simple(m.OptionSimple(model.CLOUD_UID), s.Key(s, model.UID), m.Option(model.UID))...)
return kit.Keys(m.Append(model.CLUSTER_SPACE), m.Append(web.SPACE))

View File

@ -2,7 +2,7 @@ Volcanos(chat.ONIMPORT, {
_init: function(can, msg) {
can.onimport.myView(can, msg, function(value) { return [
{view: html.TITLE, list: [value.title||value.space, can.onimport.titleAction(can, value)]},
{view: html.STATUS, list: [value.uid.slice(0, 6), can.onimport.timeView(can, value)]},
{view: html.STATUS, list: [value.uid.slice(0, 6), can.onimport.timeView(can, value), value.user_name]},
{view: html.OUTPUT, list: [value.content]},
] })
},

View File

@ -7,9 +7,11 @@ const (
NAME = "name"
INFO = "info"
TYPE = "type"
ROLE = "role"
TOTAL = "total"
STOCK = "stock"
PRICE = "price"
SPACE = "space"
TITLE = "title"
CONTENT = "content"
USER_UID = "user_uid"
@ -34,31 +36,30 @@ type Cloud struct {
}
type Cluster struct {
db.ModelContent
Space string `gorm:"type:varchar(64)"`
Space string `gorm:"type:varchar(64);index"`
Total int
Stock int
Price int
}
type Gateway struct {
db.ModelContent
Space string `gorm:"type:varchar(64)"`
CloudUID string `gorm:"type:char(32);index"`
ClusterUID string `gorm:"type:char(32);index"`
Space string `gorm:"type:varchar(64)"`
}
type Project struct {
db.ModelWithUID
CloudUID string `gorm:"type:char(32);index"`
GatewayUID string `gorm:"type:char(32);index"`
Name string `gorm:"type:varchar(64)"`
db.ModelNameInfo
Repos string `gorm:"type:varchar(255)"`
Binary string `gorm:"type:varchar(255)"`
CloudUID string `gorm:"type:char(32);index"`
GatewayUID string `gorm:"type:char(32);index"`
}
type Product struct {
db.ModelWithUID
db.ModelNameInfo
Icon string `gorm:"type:varchar(255)"`
Index string `gorm:"type:varchar(128)"`
CloudUID string `gorm:"type:char(32);index"`
ProjectUID string `gorm:"type:char(32);index"`
Index string `gorm:"type:varchar(128)"`
Name string `gorm:"type:varchar(64)"`
}
func init() { db.CmdModels("", &UserCloud{}, &Cloud{}, &Cluster{}, &Gateway{}, &Project{}, &Product{}) }

View File

@ -1,6 +1,6 @@
{
"portal": "系统运维",
"cluster": "云集群", "gateway": "云主机", "project": "云项目", "product": "云应用",
"cluster": "云集群", "gateway": "云主机", "project": "云项目", "product": "云服务",
"icons": {
"cluster": "https://img.icons8.com/officel/80/activity-grid.png",
"gateway": "https://img.icons8.com/officel/80/activity-grid.png",
@ -11,7 +11,12 @@
"My Cloud": "我的系统",
"user_cloud_role": "用户角色",
"cloud_name": "系统名称",
"cloud_type": "系统类型"
"cloud_type": "系统类型",
"cloud_space": "集群空间",
"gateway_title": "云主机",
"gateway_space": "主机空间",
"project_name": "项目名称",
"stock": "库存"
},
"value": {
"user_cloud_role": {

View File

@ -5,24 +5,42 @@ import (
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/web"
"shylinux.com/x/operation/src/operation/model"
kit "shylinux.com/x/toolkits"
"shylinux.com/x/community/src/api"
"shylinux.com/x/operation/src/operation/model"
)
type product struct {
Table
cluster cluster
gateway gateway
cluster Cluster
gateway Gateway
project project
order string `data:"4"`
fields string `data:"index,name,project_uid"`
open string `name:"open" role:"void"`
fields string `data:"name,icon,index,project_uid"`
open string `name:"open" style:"notice" role:"void"`
}
func (s product) Scan(m *ice.Message, arg ...string) {
m.Cmd(web.SPACE, m.Option(web.SPACE), api.GONGANXITONG_PORTAL)
m.Cmd(web.SPACE, m.Option(web.SPACE), api.GONGANXITONG_SERVICE).Table(func(value ice.Maps) {
s.InsertIfNeed(m.Options(ctx.INDEX, value[ctx.INDEX]), m.OptionSimple(model.CLOUD_UID, model.PROJECT_UID, ctx.INDEX)...)
s.Update(m, kit.Dict(mdb.NAME, value[mdb.NAME], mdb.ICON, value[mdb.ICON]), m.OptionSimple(model.CLOUD_UID, model.PROJECT_UID, ctx.INDEX)...)
})
}
func (s product) List(m *ice.Message, arg ...string) {
s.ValueList(m, arg).PushAction(s.Open).Display("")
s.Fields(m, model.UID, s.Keys(s.gateway, model.UID)).SelectJoin(m, s.project, s.Keys(s.gateway, model.UID))
s.Fields(m, model.UID, s.KeyAS(s.gateway, model.TITLE)).SelectJoin(m, s.gateway, s.Keys(s.gateway, model.TITLE))
if s.ValueList(m, arg); s.IsWorker(m) {
m.PushAction(s.Open, s.Remove)
} else {
m.PushAction(s.Open)
}
m.Display("")
s.Fields(m, model.UID, s.Keys(s.gateway, model.UID), s.KeyAS(s.project, mdb.NAME)).SelectJoin(m, s.project, s.Keys(s.project, mdb.NAME), s.Keys(s.gateway, model.UID))
s.Fields(m, model.UID, s.Keys(s.cluster, model.UID), s.KeyAS(s.gateway, model.TITLE), s.KeyAS(s.gateway, model.SPACE)).SelectJoin(m, s.gateway, s.Keys(s.cluster, model.UID), s.Keys(s.gateway, model.SPACE), s.Keys(s.gateway, model.TITLE))
s.Fields(m, model.UID, s.KeyAS(s.cluster, model.SPACE)).SelectJoin(m, s.cluster, s.Keys(s.cluster, model.SPACE))
if len(arg) == 2 {
m.EchoIFrame(web.S(kit.Keys(m.Append(model.CLUSTER_SPACE), m.Append(model.GATEWAY_SPACE), m.Append(model.PROJECT_NAME))))
}
}
func (s product) Open(m *ice.Message, arg ...string) {
m.ProcessOpen(m.Options(ice.MSG_USERPOD, "").MergePodCmd(s.space(m.Spawn()), m.Option(ctx.INDEX)))
@ -33,5 +51,5 @@ func init() { ice.TeamCtxCmd(product{}) }
func (s product) space(m *ice.Message, arg ...string) string {
s.Tables(m, s.project, s.gateway, s.cluster).Fields(m, s.Key(s.project, mdb.NAME), s.KeyAS(s.gateway, web.SPACE), s.KeyAS(s.cluster, web.SPACE))
s.Select(m, kit.Simple(s.Key(s, model.CLOUD_UID), m.Option(model.CLOUD_UID), s.Key(s, model.UID), m.Option(model.UID))...)
return kit.Keys(m.Append(model.CLUSTER_SPACE), m.Append(model.GATEWAY_SPACE), m.Append(model.NAME))
return kit.Keys(m.Append(model.CLUSTER_SPACE), m.Append(model.GATEWAY_SPACE), m.Append(mdb.NAME))
}

View File

@ -1,9 +1,12 @@
Volcanos(chat.ONIMPORT, {
_init: function(can, msg) {
can.onimport.myView(can, msg, function(value) { return [
{view: html.TITLE, list: [value.title||value.name||value.user_name, can.onimport.titleAction(can, value)]},
can.onimport.myView(can, msg, function(value) {
value.icon = can.misc.ResourceIcons(can, value.icon, can.core.Keys(value.cluster_space, value.gateway_space, value.project_name))
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), value.gateway_title]},
{view: html.OUTPUT, list: [value.content||value.info]},
] })
{view: html.OUTPUT, list: [value.info]},
]
})
},
})

View File

@ -1,25 +1,25 @@
package operation
import (
"shylinux.com/x/community/src/api"
"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/web"
"shylinux.com/x/operation/src/operation/model"
kit "shylinux.com/x/toolkits"
"shylinux.com/x/operation/src/operation/model"
)
type project struct {
Table
cluster cluster
gateway gateway
cluster Cluster
gateway Gateway
order string `data:"3"`
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"`
open string `name:"name" role:"worker"`
open string `name:"open" role:"worker"`
}
func (s project) Create(m *ice.Message, arg ...string) {
@ -28,20 +28,37 @@ func (s project) Create(m *ice.Message, arg ...string) {
}
msg := m.Cmd(web.SPACE, m.Option(web.SPACE), web.DREAM, mdb.CREATE, arg, kit.Dict(ice.MSG_USERROLE, aaa.TECH))
s.Insert(m, kit.Simple(arg, msg.OptionSimple(model.CLOUD_UID, model.GATEWAY_UID, mdb.NAME))...)
s.SendMessage(s.GetCommandUID(m), "", "", m.Option(model.CLOUD_UID), m.Result())
s.RecordEventWithName(m, "")
}
func (s project) Scan(m *ice.Message, arg ...string) {
m.Cmd(web.SPACE, m.Option(web.SPACE), web.DREAM).Table(func(value ice.Maps) {
if m.Option(mdb.NAME, value[mdb.NAME]); value[mdb.TYPE] == web.WORKER {
s.InsertIfNeed(m, m.OptionSimple(model.CLOUD_UID, model.GATEWAY_UID, mdb.NAME)...)
}
s.Update(m, kit.Dict(nfs.REPOS, value[nfs.REPOS], nfs.BINARY, value[nfs.BINARY]), m.OptionSimple(model.CLOUD_UID, model.GATEWAY_UID, mdb.NAME)...)
})
}
func (s project) List(m *ice.Message, arg ...string) {
s.ValueList(m, arg).PushAction(s.ScanProduct, s.Open).Action().Display("")
if m.Length() == 0 {
m.SetResult().Echo("请到「云主机」创建项目")
if s.ValueList(m, arg); s.IsWorker(m) {
m.PushAction(s.ScanProduct, s.Open, s.Remove)
} else {
m.PushAction()
}
if m.Action(); m.Length() == 0 {
m.SetResult().Echo("请到「云主机」创建项目")
} else {
s.Fields(m, model.UID, s.KeyAS(s.gateway, model.TITLE), s.KeyAS(s.gateway, model.SPACE), s.Keys(s.cluster, model.UID))
s.SelectJoin(m, s.gateway, s.Keys(s.gateway, model.TITLE), s.Keys(s.gateway, model.SPACE), s.Keys(s.cluster, model.UID))
s.Fields(m, model.UID, s.KeyAS(s.cluster, model.SPACE)).SelectJoin(m, s.cluster, s.Keys(s.cluster, model.SPACE))
m.Display("")
}
if len(arg) == 2 && s.IsWorker(m) {
m.EchoIFrame(web.S(s.space(m.Spawn().Options(model.CLOUD_UID, arg[0], model.UID, arg[1]))))
}
s.Fields(m, model.UID, s.KeyAS(s.gateway, model.TITLE)).SelectJoin(m, s.gateway, s.Keys(s.gateway, model.TITLE))
}
func (s project) ScanProduct(m *ice.Message, arg ...string) {
m.Cmd(web.SPACE, s.space(m), api.GONGANXITONG_PORTAL)
m.Cmd(web.SPACE, s.space(m), api.GONGANXITONG_SERVICE).Table(func(value ice.Maps) {
m.Cmd(product{}, s.InsertIfNeed, ctx.INDEX, value[ctx.INDEX], mdb.NAME, value[mdb.NAME], model.PROJECT_UID, m.Option(model.UID), m.OptionSimple(model.CLOUD_UID))
})
m.ProcessRefresh()
m.Cmdy(product{}, s.Scan, kit.Dict(model.PROJECT_UID, m.Option(model.UID), web.SPACE, s.space(m))).ProcessRefresh()
}
func (s project) Open(m *ice.Message, arg ...string) {
m.ProcessOpen(m.Options(ice.MSG_USERPOD, "").MergePodCmd(s.space(m), web.ADMIN))

View File

@ -1,9 +1,9 @@
Volcanos(chat.ONIMPORT, {
_init: function(can, msg) {
can.onimport.myView(can, msg, function(value) { return [
{view: html.TITLE, list: [value.title||value.name, can.onimport.titleAction(can, value)]},
{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), value.gateway_title]},
{view: html.OUTPUT, list: [value.content||value.repos||value.binary]},
{view: html.OUTPUT, list: [value.binary||value.repos]},
] })
},
})

View File

@ -44,9 +44,10 @@
},
"64be90144c205e73b1fc216962d7ad25": {
"meta": {
"auth": "issued",
"icons": "https://img.icons8.com/officel/80/activity-grid.png",
"index": "web.team.operation.product",
"name": "云应用",
"name": "云服务",
"order": "4",
"time": "2025-03-05 10:40:39.748"
}
@ -75,10 +76,12 @@
},
"7abb3b3760a9b686457938511c0ee7df": {
"meta": {
"auth": "issued",
"icons": "https://img.icons8.com/officel/80/activity-grid.png",
"index": "web.team.operation.project",
"name": "云项目",
"order": "3",
"role": "leader,worker",
"time": "2025-03-05 10:40:39.740"
}
},
@ -124,10 +127,12 @@
},
"c8159ab932f400dbafa08fb995e16355": {
"meta": {
"auth": "issued",
"icons": "https://img.icons8.com/officel/80/activity-grid.png",
"index": "web.team.operation.cluster",
"name": "云集群",
"order": "1",
"role": "leader",
"time": "2025-03-05 10:40:39.838"
}
},
@ -162,10 +167,12 @@
},
"d8f6d139d6a5f9b5aa504702e7777eb3": {
"meta": {
"auth": "issued",
"icons": "https://img.icons8.com/officel/80/activity-grid.png",
"index": "web.team.operation.gateway",
"name": "云主机",
"order": "2",
"portal": "true",
"time": "2025-03-05 12:13:06.405"
}
},