dashboard增加Jsite服务器菜单并实现列表页功能
This commit is contained in:
parent
2087285c00
commit
ad2929e2fa
@ -109,6 +109,16 @@ export default {
|
|||||||
condition: onboardingComplete && !isSaasUser && this.$team.pg.is_pro,
|
condition: onboardingComplete && !isSaasUser && this.$team.pg.is_pro,
|
||||||
disabled: enforce2FA,
|
disabled: enforce2FA,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Jsite服务器',
|
||||||
|
icon: () => h(Server),
|
||||||
|
route: '/jsite-servers',
|
||||||
|
isActive:
|
||||||
|
['Jsite Servers', 'New Jsite Server'].includes(routeName) ||
|
||||||
|
routeName.startsWith('Jsite Server'),
|
||||||
|
condition: onboardingComplete && !isSaasUser && this.$team.pg.is_pro,
|
||||||
|
disabled: enforce2FA,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: '应用市场',
|
name: '应用市场',
|
||||||
icon: () => h(App),
|
icon: () => h(App),
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import group from './group';
|
|||||||
import bench from './bench';
|
import bench from './bench';
|
||||||
import marketplace from './marketplace';
|
import marketplace from './marketplace';
|
||||||
import server from './server';
|
import server from './server';
|
||||||
|
import jsite_server from './jsite_server';
|
||||||
import notification from './notification';
|
import notification from './notification';
|
||||||
|
|
||||||
let objects = {
|
let objects = {
|
||||||
@ -11,6 +12,7 @@ let objects = {
|
|||||||
Bench: bench,
|
Bench: bench,
|
||||||
Marketplace: marketplace,
|
Marketplace: marketplace,
|
||||||
Server: server,
|
Server: server,
|
||||||
|
'Jsite Server': jsite_server,
|
||||||
Notification: notification
|
Notification: notification
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
275
dashboard/src2/objects/jsite_server.js
Normal file
275
dashboard/src2/objects/jsite_server.js
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
import { defineAsyncComponent, h } from 'vue';
|
||||||
|
import LucideServer from '~icons/lucide/server';
|
||||||
|
import { getTeam } from '../data/team';
|
||||||
|
import router from '../router';
|
||||||
|
import { icon } from '../utils/components';
|
||||||
|
import { duration, planTitle, userCurrency } from '../utils/format';
|
||||||
|
import { trialDays } from '../utils/site';
|
||||||
|
import { getJobsTab } from './common/jobs';
|
||||||
|
import { tagTab } from './common/tags';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
pagetype: 'Jsite Server',
|
||||||
|
whitelistedMethods: {
|
||||||
|
reboot: 'reboot',
|
||||||
|
rename: 'rename',
|
||||||
|
dropServer: 'drop_server',
|
||||||
|
addTag: 'add_resource_tag',
|
||||||
|
removeTag: 'remove_resource_tag'
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
route: '/jsite-servers',
|
||||||
|
title: 'Jsite服务器',
|
||||||
|
fields: [
|
||||||
|
'name',
|
||||||
|
'title',
|
||||||
|
'status',
|
||||||
|
'region',
|
||||||
|
'cpu',
|
||||||
|
'memory',
|
||||||
|
'disk_size',
|
||||||
|
'public_ip',
|
||||||
|
'end_date',
|
||||||
|
'bandwidth',
|
||||||
|
'team',
|
||||||
|
'instance_id',
|
||||||
|
'order_id',
|
||||||
|
'planid',
|
||||||
|
'image_id',
|
||||||
|
'system'
|
||||||
|
],
|
||||||
|
filterControls() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '状态',
|
||||||
|
fieldname: 'status',
|
||||||
|
options: [
|
||||||
|
{ label: '', value: '' },
|
||||||
|
{ label: '待定', value: 'Pending' },
|
||||||
|
{ label: '启动中', value: 'Starting' },
|
||||||
|
{ label: '运行中', value: 'Running' },
|
||||||
|
{ label: '停止中', value: 'Stopping' },
|
||||||
|
{ label: '已停止', value: 'Stopped' },
|
||||||
|
{ label: '重置中', value: 'Resetting' },
|
||||||
|
{ label: '升级中', value: 'Upgrading' },
|
||||||
|
{ label: '已禁用', value: 'Disabled' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '区域',
|
||||||
|
fieldname: 'region',
|
||||||
|
options: [
|
||||||
|
{ label: '', value: '' },
|
||||||
|
{ label: '中国大陆', value: '中国大陆' },
|
||||||
|
{ label: '中国香港', value: '中国香港' },
|
||||||
|
{ label: '美国-洛杉矶', value: '美国-洛杉矶' },
|
||||||
|
{ label: '新加坡', value: '新加坡' },
|
||||||
|
{ label: '英国-伦敦', value: '英国-伦敦' },
|
||||||
|
{ label: '德国-法兰克福', value: '德国-法兰克福' },
|
||||||
|
{ label: '阿联酋-迪拜', value: '阿联酋-迪拜' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
},
|
||||||
|
orderBy: 'creation desc',
|
||||||
|
searchField: 'title',
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
label: '服务器',
|
||||||
|
fieldname: 'name',
|
||||||
|
width: 1.5,
|
||||||
|
class: 'font-medium',
|
||||||
|
format(value, row) {
|
||||||
|
return row.title || value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '状态',
|
||||||
|
fieldname: 'status',
|
||||||
|
type: 'Badge',
|
||||||
|
width: 0.8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '配置',
|
||||||
|
fieldname: 'cpu',
|
||||||
|
format(value, row) {
|
||||||
|
const cpu = row.cpu || '未知';
|
||||||
|
const memory = row.memory || '未知';
|
||||||
|
const disk = row.disk_size || '未知';
|
||||||
|
return `${cpu}核/${memory}GB/${disk}GB`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '公网IP',
|
||||||
|
fieldname: 'public_ip',
|
||||||
|
format(value) {
|
||||||
|
return value || '-';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '区域',
|
||||||
|
fieldname: 'region',
|
||||||
|
format(value) {
|
||||||
|
return value || '-';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '到期时间',
|
||||||
|
fieldname: 'end_date',
|
||||||
|
format(value) {
|
||||||
|
if (!value) return '-';
|
||||||
|
return new Date(value).toLocaleDateString('zh-CN');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
primaryAction({ listResource: jsiteServers }) {
|
||||||
|
return {
|
||||||
|
label: '新建Jsite服务器',
|
||||||
|
icon: 'plus',
|
||||||
|
onClick() {
|
||||||
|
router.push('/jsite-servers/new');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
statusBadge({ documentResource: jsiteServer }) {
|
||||||
|
const status = jsiteServer.pg?.status;
|
||||||
|
const statusConfig = {
|
||||||
|
Pending: { label: '待定', color: 'gray' },
|
||||||
|
Starting: { label: '启动中', color: 'yellow' },
|
||||||
|
Running: { label: '运行中', color: 'green' },
|
||||||
|
Stopping: { label: '停止中', color: 'orange' },
|
||||||
|
Stopped: { label: '已停止', color: 'red' },
|
||||||
|
Resetting: { label: '重置中', color: 'blue' },
|
||||||
|
Upgrading: { label: '升级中', color: 'purple' },
|
||||||
|
Disabled: { label: '已禁用', color: 'gray' }
|
||||||
|
};
|
||||||
|
return statusConfig[status] || { label: status, color: 'gray' };
|
||||||
|
},
|
||||||
|
breadcrumbs({ documentResource: jsiteServer }) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
label: 'Jsite服务器',
|
||||||
|
route: '/jsite-servers'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: jsiteServer.pg?.title || jsiteServer.pg?.name,
|
||||||
|
route: `/jsite-servers/${jsiteServer.pg?.name}`
|
||||||
|
}
|
||||||
|
];
|
||||||
|
},
|
||||||
|
actions({ documentResource: jsiteServer }) {
|
||||||
|
if (!jsiteServer) return [];
|
||||||
|
|
||||||
|
const actions = [
|
||||||
|
{
|
||||||
|
label: '重启',
|
||||||
|
icon: 'refresh-cw',
|
||||||
|
onClick() {
|
||||||
|
jsiteServer.reboot.submit();
|
||||||
|
},
|
||||||
|
condition: () => jsiteServer.pg?.status === 'Running'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '重命名',
|
||||||
|
icon: 'edit-3',
|
||||||
|
onClick() {
|
||||||
|
jsiteServer.rename.submit();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '删除',
|
||||||
|
icon: 'trash-2',
|
||||||
|
onClick() {
|
||||||
|
jsiteServer.dropServer.submit();
|
||||||
|
},
|
||||||
|
condition: () => jsiteServer.pg?.status !== 'Running'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
return actions.filter(action => !action.condition || action.condition());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
route: '/jsite-servers/:name',
|
||||||
|
title: 'Jsite服务器详情',
|
||||||
|
tabs: [
|
||||||
|
{
|
||||||
|
label: '概览',
|
||||||
|
route: '',
|
||||||
|
type: 'fields'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
label: '基本信息',
|
||||||
|
fields: [
|
||||||
|
'title',
|
||||||
|
'status',
|
||||||
|
'region',
|
||||||
|
'instance_id',
|
||||||
|
'order_id'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '服务器配置',
|
||||||
|
fields: [
|
||||||
|
'cpu',
|
||||||
|
'memory',
|
||||||
|
'disk_size',
|
||||||
|
'bandwidth',
|
||||||
|
'public_ip',
|
||||||
|
'image_id',
|
||||||
|
'planid',
|
||||||
|
'system'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'SSH连接',
|
||||||
|
fields: [
|
||||||
|
'ssh_user',
|
||||||
|
'ssh_port',
|
||||||
|
'password',
|
||||||
|
'key_pair_name',
|
||||||
|
'private_key'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '其他信息',
|
||||||
|
fields: [
|
||||||
|
'end_date',
|
||||||
|
'period'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
actions({ documentResource: jsiteServer }) {
|
||||||
|
if (!jsiteServer) return [];
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
label: '重启',
|
||||||
|
icon: 'refresh-cw',
|
||||||
|
onClick() {
|
||||||
|
jsiteServer.reboot.submit();
|
||||||
|
},
|
||||||
|
condition: () => jsiteServer.pg?.status === 'Running'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '重命名',
|
||||||
|
icon: 'edit-3',
|
||||||
|
onClick() {
|
||||||
|
jsiteServer.rename.submit();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '删除',
|
||||||
|
icon: 'trash-2',
|
||||||
|
onClick() {
|
||||||
|
jsiteServer.dropServer.submit();
|
||||||
|
},
|
||||||
|
condition: () => jsiteServer.pg?.status !== 'Running'
|
||||||
|
}
|
||||||
|
].filter(action => !action.condition || action.condition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -110,6 +110,27 @@ let router = createRouter({
|
|||||||
path: '/servers/new',
|
path: '/servers/new',
|
||||||
component: () => import('./pages/NewJsiteServer.vue'),
|
component: () => import('./pages/NewJsiteServer.vue'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Jsite Servers',
|
||||||
|
path: '/jsite-servers',
|
||||||
|
component: () => import('./pages/ListPage.vue'),
|
||||||
|
props: route => {
|
||||||
|
return { objectType: 'Jsite Server', ...route.params };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'New Jsite Server',
|
||||||
|
path: '/jsite-servers/new',
|
||||||
|
component: () => import('./pages/NewJsiteServer.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Jsite Server Detail',
|
||||||
|
path: '/jsite-servers/:name',
|
||||||
|
component: () => import('./pages/DetailPage.vue'),
|
||||||
|
props: route => {
|
||||||
|
return { objectType: 'Jsite Server', ...route.params };
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Billing',
|
name: 'Billing',
|
||||||
path: '/billing',
|
path: '/billing',
|
||||||
|
|||||||
@ -77,6 +77,7 @@ ALLOWED_PAGETYPES = [
|
|||||||
"Site Database User",
|
"Site Database User",
|
||||||
"Jcloud Settings",
|
"Jcloud Settings",
|
||||||
"Mpesa Payment Record",
|
"Mpesa Payment Record",
|
||||||
|
"Jsite Server",
|
||||||
]
|
]
|
||||||
|
|
||||||
ALLOWED_PAGETYPES_FOR_SUPPORT = [
|
ALLOWED_PAGETYPES_FOR_SUPPORT = [
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# Copyright (c) 2025, Jingrow and contributors
|
# Copyright (c) 2025, Jingrow and contributors
|
||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
# import jingrow
|
import jingrow
|
||||||
from jingrow.model.document import Document
|
from jingrow.model.document import Document
|
||||||
|
|
||||||
|
|
||||||
@ -36,4 +36,30 @@ class JsiteServer(Document):
|
|||||||
team: DF.Link | None
|
team: DF.Link | None
|
||||||
title: DF.Data | None
|
title: DF.Data | None
|
||||||
# end: auto-generated types
|
# end: auto-generated types
|
||||||
pass
|
|
||||||
|
dashboard_fields = (
|
||||||
|
"title",
|
||||||
|
"status",
|
||||||
|
"region",
|
||||||
|
"cpu",
|
||||||
|
"memory",
|
||||||
|
"disk_size",
|
||||||
|
"public_ip",
|
||||||
|
"end_date",
|
||||||
|
"bandwidth",
|
||||||
|
"team",
|
||||||
|
"instance_id",
|
||||||
|
"order_id",
|
||||||
|
"planid",
|
||||||
|
"image_id",
|
||||||
|
"system"
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_list_query(query):
|
||||||
|
JsiteServer = jingrow.qb.PageType("Jsite Server")
|
||||||
|
query = query.where(JsiteServer.team == jingrow.local.team().name)
|
||||||
|
return query.run(as_dict=True)
|
||||||
|
|
||||||
|
def get_pg(self, pg):
|
||||||
|
return pg
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user