mirror of
https://github.com/hi2shark/nazhua.git
synced 2026-01-16 17:20:42 +08:00
✨ ServerStatus风格的表格模式
This commit is contained in:
parent
33f1625ab1
commit
69ab11babc
@ -11,7 +11,8 @@ window.$$nazhuaConfig = {
|
|||||||
// showLantern: true, // 是否显示灯笼
|
// showLantern: true, // 是否显示灯笼
|
||||||
enableInnerSearch: true, // 启用内部搜索
|
enableInnerSearch: true, // 启用内部搜索
|
||||||
// listServerItemTypeToggle: true, // 服务器列表项类型切换
|
// listServerItemTypeToggle: true, // 服务器列表项类型切换
|
||||||
// listServerItemType: 'row', // 服务器列表项类型 card/row row列表模式移动端自动切换至card
|
listServerItemType: 'row', // 服务器列表项类型 card/row/status row列表模式移动端自动切换至card
|
||||||
|
// serverStatusColumnsTpl: null, // 服务器状态列配置模板
|
||||||
// listServerStatusType: 'progress', // 服务器状态类型--列表
|
// listServerStatusType: 'progress', // 服务器状态类型--列表
|
||||||
// listServerRealTimeShowLoad: true, // 列表显示服务器实时负载
|
// listServerRealTimeShowLoad: true, // 列表显示服务器实时负载
|
||||||
// detailServerStatusType: 'progress', // 服务器状态类型--详情页
|
// detailServerStatusType: 'progress', // 服务器状态类型--详情页
|
||||||
|
|||||||
122
src/views/components/server-list-by-server-status/main.vue
Normal file
122
src/views/components/server-list-by-server-status/main.vue
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<template>
|
||||||
|
<dot-dot-box
|
||||||
|
v-if="tableData"
|
||||||
|
class="server-status"
|
||||||
|
>
|
||||||
|
<table class="server-status-table">
|
||||||
|
<thead class="server-status-table-header">
|
||||||
|
<tr class="server-status-table-header-row">
|
||||||
|
<template
|
||||||
|
v-for="column in tableData.columnProps"
|
||||||
|
:key="`th_${column.prop}`"
|
||||||
|
>
|
||||||
|
<template v-if="['billing', 'remainingTime'].includes(column.prop)">
|
||||||
|
<server-status-th
|
||||||
|
v-if="tableData.showBilling && column.prop === 'billing'"
|
||||||
|
:column="column"
|
||||||
|
/>
|
||||||
|
<server-status-th
|
||||||
|
v-if="tableData.showRemainingTime && column.prop === 'remainingTime'"
|
||||||
|
:column="column"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<server-status-th
|
||||||
|
:column="column"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="server-status-table-body">
|
||||||
|
<tr
|
||||||
|
v-for="itemData in tableData.list"
|
||||||
|
:key="itemData.info.ID"
|
||||||
|
class="server-status-table-body-row"
|
||||||
|
:class="{
|
||||||
|
'server-status-table-body-row--offline': itemData.info?.Online === -1,
|
||||||
|
'server-status-table-body-row--online': itemData.info?.Online === 1,
|
||||||
|
[`server-item--${itemData.info?.ID}`]: true,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
v-for="column in itemData.columnData"
|
||||||
|
:key="`td_${itemData.info?.ID}_${column.prop}`"
|
||||||
|
>
|
||||||
|
<template v-if="['billing', 'remainingTime'].includes(column.prop)">
|
||||||
|
<server-status-td
|
||||||
|
v-if="tableData.showBilling && column.prop === 'billing'"
|
||||||
|
:column="column"
|
||||||
|
/>
|
||||||
|
<server-status-td
|
||||||
|
v-if="tableData.showRemainingTime && column.prop === 'remainingTime'"
|
||||||
|
:column="column"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<server-status-td
|
||||||
|
:column="column"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dot-dot-box>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
/**
|
||||||
|
* ServerStatus风格的列表
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
computed,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
import config from '@/config';
|
||||||
|
|
||||||
|
import {
|
||||||
|
handleServerListColumn,
|
||||||
|
} from './server-status';
|
||||||
|
|
||||||
|
import ServerStatusTh from './table/th.vue';
|
||||||
|
import ServerStatusTd from './table/td.vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
serverList: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const tableData = computed(() => {
|
||||||
|
const result = handleServerListColumn(props.serverList, config.nazhua.serverStatusColumnsTpl);
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.server-status {
|
||||||
|
--server-status-cell-padding: 0 5px;
|
||||||
|
--server-status-td-height: 32px;
|
||||||
|
|
||||||
|
--progress-bar-height: 18px;
|
||||||
|
|
||||||
|
@media screen and (max-width: 350px) {
|
||||||
|
--progress-bar-height: 16px;
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.server-status-table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
|
||||||
|
.server-status-table-body-row {
|
||||||
|
&--offline {
|
||||||
|
filter: grayscale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
<template>
|
||||||
|
<div class="conn-group">
|
||||||
|
<div class="conn--tcp">
|
||||||
|
{{ tcpConnCount }}
|
||||||
|
</div>
|
||||||
|
<div class="split-line">
|
||||||
|
|
|
||||||
|
</div>
|
||||||
|
<div class="conn--udp">
|
||||||
|
{{ udpConnCount }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
/**
|
||||||
|
* 连接信息
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
computed,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
realTimeData: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const tcpConnCount = computed(() => {
|
||||||
|
const { item } = props.realTimeData?.conns || {};
|
||||||
|
const { value } = item?.data?.tcp || {};
|
||||||
|
return value || '-';
|
||||||
|
});
|
||||||
|
const udpConnCount = computed(() => {
|
||||||
|
const { item } = props.realTimeData?.conns || {};
|
||||||
|
const { value } = item?.data?.udp || {};
|
||||||
|
return value || '-';
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.conn-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 5px;
|
||||||
|
width: 100%;
|
||||||
|
.conn--tcp {
|
||||||
|
flex: 1;
|
||||||
|
text-align: right;
|
||||||
|
color: var(--conn-tcp-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.conn--udp {
|
||||||
|
flex: 1;
|
||||||
|
text-align: left;
|
||||||
|
color: var(--conn-udp-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-line {
|
||||||
|
width: 4px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
<template>
|
||||||
|
<div class="country-content">
|
||||||
|
<server-flag :info="info" />
|
||||||
|
<span class="country-label">
|
||||||
|
{{ countryLabel }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
/**
|
||||||
|
* 地区信息
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
computed,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
info: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const countryLabel = computed(() => props.info?.Host?.CountryCode?.toUpperCase() || 'UN');
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.country-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
<template>
|
||||||
|
<div class="net-speed-group">
|
||||||
|
<div class="net-speed--in">
|
||||||
|
{{ inSpeed }}
|
||||||
|
</div>
|
||||||
|
<div class="split-line">
|
||||||
|
|
|
||||||
|
</div>
|
||||||
|
<div class="net-speed--out">
|
||||||
|
{{ outSpeed }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
/**
|
||||||
|
* 网速信息
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
computed,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
realTimeData: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const inSpeed = computed(() => {
|
||||||
|
const { item } = props.realTimeData?.speeds || {};
|
||||||
|
if (item?.data?.in) {
|
||||||
|
const { value, unit } = item.data.in;
|
||||||
|
return `${value}${unit}`;
|
||||||
|
}
|
||||||
|
return '-';
|
||||||
|
});
|
||||||
|
const outSpeed = computed(() => {
|
||||||
|
const { item } = props.realTimeData?.speeds || {};
|
||||||
|
if (item?.data?.out) {
|
||||||
|
const { value, unit } = item.data.out;
|
||||||
|
return `${value}${unit}`;
|
||||||
|
}
|
||||||
|
return '-';
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.net-speed-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 5px;
|
||||||
|
width: 100%;
|
||||||
|
.net-speed--in {
|
||||||
|
flex: 1;
|
||||||
|
text-align: right;
|
||||||
|
color: var(--net-speed-in-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.net-speed--out {
|
||||||
|
flex: 1;
|
||||||
|
text-align: left;
|
||||||
|
color: var(--net-speed-out-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-line {
|
||||||
|
width: 4px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
<template>
|
||||||
|
<div class="status-icon-box">
|
||||||
|
<div
|
||||||
|
class="status-icon"
|
||||||
|
:class="{
|
||||||
|
online: info.online === 1,
|
||||||
|
offline: info.online === -1,
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
/**
|
||||||
|
* 状态图标
|
||||||
|
*/
|
||||||
|
defineProps({
|
||||||
|
info: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.status-icon-box {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-icon {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-icon.online {
|
||||||
|
background-image: linear-gradient(rgba(77, 133, 58, 1) 0, rgba(54, 126, 54, 1) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-icon.offline {
|
||||||
|
background-image: linear-gradient(rgba(155, 37, 34, 1) 0, rgba(161, 38, 35, 1) 100%);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
<template>
|
||||||
|
<div class="system-os-content">
|
||||||
|
<span class="system-icon">
|
||||||
|
<span :class="platformLogoIconClassName" />
|
||||||
|
</span>
|
||||||
|
<span class="system-label">
|
||||||
|
{{ systemOSLabel }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
/**
|
||||||
|
* 系统信息
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
computed,
|
||||||
|
} from 'vue';
|
||||||
|
import * as hostUtils from '@/utils/host';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
info: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const platformLogoIconClassName = computed(() => hostUtils.getPlatformLogoIconClassName(props.info?.Host?.Platform));
|
||||||
|
const systemOSLabel = computed(() => hostUtils.getSystemOSLabel(props.info?.Host?.Platform, true));
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.system-os-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
<template>
|
||||||
|
<div class="transfer-group">
|
||||||
|
<div class="transfer--in">
|
||||||
|
{{ transferIn }}
|
||||||
|
</div>
|
||||||
|
<div class="split-line">
|
||||||
|
|
|
||||||
|
</div>
|
||||||
|
<div class="transfer--out">
|
||||||
|
{{ transferOut }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
/**
|
||||||
|
* 流量信息
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
computed,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
realTimeData: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const transferIn = computed(() => {
|
||||||
|
const { item } = props.realTimeData?.transfer || {};
|
||||||
|
if (item?.data?.in) {
|
||||||
|
const { value, unit } = item.data.in;
|
||||||
|
return `${value}${unit}`;
|
||||||
|
}
|
||||||
|
return '-';
|
||||||
|
});
|
||||||
|
const transferOut = computed(() => {
|
||||||
|
const { item } = props.realTimeData?.transfer || {};
|
||||||
|
if (item?.data?.out) {
|
||||||
|
const { value, unit } = item.data.out;
|
||||||
|
return `${value}${unit}`;
|
||||||
|
}
|
||||||
|
return '-';
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.transfer-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 5px;
|
||||||
|
width: 100%;
|
||||||
|
.transfer--in {
|
||||||
|
flex: 1;
|
||||||
|
text-align: right;
|
||||||
|
color: var(--transfer-in-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.transfer--out {
|
||||||
|
flex: 1;
|
||||||
|
text-align: left;
|
||||||
|
color: var(--transfer-out-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-line {
|
||||||
|
width: 4px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,438 @@
|
|||||||
|
/**
|
||||||
|
* ServerStatus风格的列表列配置
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
h,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
// import * as hostUtils from '@/utils/host';
|
||||||
|
import handleServerStatus from '@/views/composable/server-status';
|
||||||
|
import handleServerInfo from '@/views/composable/server-info';
|
||||||
|
import handleServerRealTime from '@/views/composable/server-real-time';
|
||||||
|
import handleServerBillAndPlan from '@/views/composable/server-bill-and-plan';
|
||||||
|
|
||||||
|
import ServerStatusProgress from '@/views/components/server/server-status-progress.vue';
|
||||||
|
import StatusIcon from '@/views/components/server-list-by-server-status/server-info/status-icon.vue';
|
||||||
|
import SystemOS from '@/views/components/server-list-by-server-status/server-info/system-os.vue';
|
||||||
|
import Country from '@/views/components/server-list-by-server-status/server-info/country.vue';
|
||||||
|
import NetSpeed from '@/views/components/server-list-by-server-status/server-info/net-speed.vue';
|
||||||
|
import Transfer from '@/views/components/server-list-by-server-status/server-info/transfer.vue';
|
||||||
|
import Conns from '@/views/components/server-list-by-server-status/server-info/conns.vue';
|
||||||
|
|
||||||
|
const COLUMN_MAP = Object.freeze({
|
||||||
|
status: {
|
||||||
|
label: '状态',
|
||||||
|
width: 40,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
label: '名称',
|
||||||
|
minWidth: 100,
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
config: {
|
||||||
|
label: '规格',
|
||||||
|
width: 80,
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
system: {
|
||||||
|
label: '系统',
|
||||||
|
width: 90,
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
country: {
|
||||||
|
label: '地区',
|
||||||
|
width: 60,
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
duration: {
|
||||||
|
label: '在线',
|
||||||
|
width: 60,
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
load: {
|
||||||
|
label: '负载',
|
||||||
|
width: 45,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
speeds: {
|
||||||
|
label: '网速',
|
||||||
|
width: 112,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
inSpeed: {
|
||||||
|
label: '入网',
|
||||||
|
width: 60,
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
outSpeed: {
|
||||||
|
label: '出网',
|
||||||
|
width: 60,
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
transfer: {
|
||||||
|
label: '流量',
|
||||||
|
width: 112,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
inTransfer: {
|
||||||
|
label: '入网流量',
|
||||||
|
width: 60,
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
outTransfer: {
|
||||||
|
label: '出网流量',
|
||||||
|
width: 60,
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
conns: {
|
||||||
|
label: '连接',
|
||||||
|
width: 72,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
tcp: {
|
||||||
|
label: 'TCP',
|
||||||
|
width: 40,
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
udp: {
|
||||||
|
label: 'UDP',
|
||||||
|
width: 40,
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
cpu: {
|
||||||
|
label: 'CPU',
|
||||||
|
width: 80,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
cpuText: {
|
||||||
|
valProp: 'cpu',
|
||||||
|
label: 'CPU',
|
||||||
|
width: 40,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
mem: {
|
||||||
|
label: '内存',
|
||||||
|
width: 80,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
memText: {
|
||||||
|
valProp: 'mem',
|
||||||
|
label: '内存',
|
||||||
|
width: 40,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
swap: {
|
||||||
|
label: '交换',
|
||||||
|
width: 80,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
swapText: {
|
||||||
|
valProp: 'swap',
|
||||||
|
label: '交换',
|
||||||
|
width: 40,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
disk: {
|
||||||
|
label: '硬盘',
|
||||||
|
width: 80,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
diskText: {
|
||||||
|
valProp: 'disk',
|
||||||
|
label: '硬盘',
|
||||||
|
width: 40,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
billing: {
|
||||||
|
label: '价格',
|
||||||
|
width: 110,
|
||||||
|
align: 'right',
|
||||||
|
},
|
||||||
|
remainingTime: {
|
||||||
|
label: '剩余',
|
||||||
|
width: 70,
|
||||||
|
align: 'right',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认列配置
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line max-len, vue/max-len
|
||||||
|
const DEFAULT_COLUMNS = 'status,name,country,system,config,duration,speeds,transfer,conns,load,cpuText,memText,diskText,billing,remainingTime';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 需要实时更新的数据
|
||||||
|
*/
|
||||||
|
const RELD_TIME_DATA = [
|
||||||
|
'speeds', 'inSpeed', 'outSpeed',
|
||||||
|
'transfer', 'inTransfer', 'outTransfer',
|
||||||
|
'conns', 'tcp', 'udp',
|
||||||
|
'duration', 'load',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取列配置
|
||||||
|
* @param {string} columnsTpls 列配置模板
|
||||||
|
* @returns {Object} 列配置
|
||||||
|
* @property {Array} columns 列配置
|
||||||
|
*/
|
||||||
|
export const getColumnPropsConfig = (tpls = DEFAULT_COLUMNS) => {
|
||||||
|
const tplList = tpls.split(',');
|
||||||
|
const columnList = [];
|
||||||
|
tplList.forEach((tpl) => {
|
||||||
|
if (COLUMN_MAP[tpl]) {
|
||||||
|
columnList.push({
|
||||||
|
prop: tpl,
|
||||||
|
...COLUMN_MAP[tpl],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return columnList;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将服务器数据转换为表格数据
|
||||||
|
* @param {Object} server 服务器数据
|
||||||
|
* @returns {Object} 表格数据
|
||||||
|
*/
|
||||||
|
export const handleServerItemData = (params) => {
|
||||||
|
const {
|
||||||
|
column,
|
||||||
|
server,
|
||||||
|
realTimeData,
|
||||||
|
progressData,
|
||||||
|
billAndPlan,
|
||||||
|
} = params || {};
|
||||||
|
switch (column.prop) {
|
||||||
|
case 'status':
|
||||||
|
return {
|
||||||
|
type: 'component',
|
||||||
|
component: h(StatusIcon, { info: server }),
|
||||||
|
originalData: params,
|
||||||
|
};
|
||||||
|
case 'name':
|
||||||
|
return {
|
||||||
|
type: 'text',
|
||||||
|
value: server.Name,
|
||||||
|
originalData: params,
|
||||||
|
};
|
||||||
|
case 'config':
|
||||||
|
{
|
||||||
|
const { cpuAndMemAndDisk } = handleServerInfo({
|
||||||
|
props: {
|
||||||
|
info: server,
|
||||||
|
},
|
||||||
|
originalData: params,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
type: 'text',
|
||||||
|
value: cpuAndMemAndDisk,
|
||||||
|
originalData: params,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case 'system':
|
||||||
|
return {
|
||||||
|
type: 'component',
|
||||||
|
component: h(SystemOS, { info: server }),
|
||||||
|
originalData: params,
|
||||||
|
};
|
||||||
|
case 'country':
|
||||||
|
return {
|
||||||
|
type: 'component',
|
||||||
|
component: h(Country, { info: server }),
|
||||||
|
originalData: params,
|
||||||
|
};
|
||||||
|
case 'speeds':
|
||||||
|
return {
|
||||||
|
type: 'component',
|
||||||
|
component: h(NetSpeed, { realTimeData }),
|
||||||
|
originalData: params,
|
||||||
|
};
|
||||||
|
case 'transfer':
|
||||||
|
return {
|
||||||
|
type: 'component',
|
||||||
|
component: h(Transfer, { realTimeData }),
|
||||||
|
originalData: params,
|
||||||
|
};
|
||||||
|
case 'conns':
|
||||||
|
return {
|
||||||
|
type: 'component',
|
||||||
|
component: h(Conns, { realTimeData }),
|
||||||
|
originalData: params,
|
||||||
|
};
|
||||||
|
case 'cpu':
|
||||||
|
case 'mem':
|
||||||
|
case 'disk':
|
||||||
|
case 'swap':
|
||||||
|
{
|
||||||
|
const progressItem = progressData[column.prop];
|
||||||
|
return {
|
||||||
|
type: 'component',
|
||||||
|
component: h(ServerStatusProgress, {
|
||||||
|
type: column.prop,
|
||||||
|
used: progressItem?.used || 0,
|
||||||
|
colors: progressItem?.colors || {},
|
||||||
|
valText: progressItem?.valPercent || '',
|
||||||
|
}),
|
||||||
|
originalData: params,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case 'cpuText':
|
||||||
|
case 'memText':
|
||||||
|
case 'diskText':
|
||||||
|
case 'swapText':
|
||||||
|
{
|
||||||
|
const progressItem = progressData[column.valProp];
|
||||||
|
return {
|
||||||
|
prop: column.prop,
|
||||||
|
type: 'text',
|
||||||
|
value: parseFloat(progressItem?.used || 0).toFixed(1),
|
||||||
|
unit: '%',
|
||||||
|
text: progressItem?.valPercent || '',
|
||||||
|
originalData: params,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case 'billing':
|
||||||
|
case 'remainingTime':
|
||||||
|
{
|
||||||
|
const item = billAndPlan?.value?.[column.prop];
|
||||||
|
const texts = [];
|
||||||
|
if (item?.value) {
|
||||||
|
texts.push(item.value || '-');
|
||||||
|
}
|
||||||
|
if (item?.cycleLabel) {
|
||||||
|
texts.push(item.cycleLabel);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
prop: column.prop,
|
||||||
|
type: 'text',
|
||||||
|
text: texts.join('/'),
|
||||||
|
originalData: params,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
if (RELD_TIME_DATA.includes(column.prop) && realTimeData[column.prop]) {
|
||||||
|
const item = realTimeData[column.prop];
|
||||||
|
return {
|
||||||
|
prop: column.prop,
|
||||||
|
type: 'text',
|
||||||
|
text: item?.text,
|
||||||
|
value: item?.value,
|
||||||
|
unit: item?.unit,
|
||||||
|
originalData: params,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
prop: column.prop,
|
||||||
|
type: 'text',
|
||||||
|
value: '-',
|
||||||
|
originalData: params,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将服务器数据转换为表格数据
|
||||||
|
* @param {Object} server 服务器数据
|
||||||
|
* @param {Array} columns 列配置
|
||||||
|
* @returns {Array} 表格数据
|
||||||
|
*/
|
||||||
|
export const handleServerListColumn = (serverList, columnTpls = DEFAULT_COLUMNS) => {
|
||||||
|
const columnProps = getColumnPropsConfig(columnTpls);
|
||||||
|
const tpls = columnProps.map((column) => column.valProp || column.prop).join(',');
|
||||||
|
const hasBilling = columnTpls.includes('billing');
|
||||||
|
const hasRemainingTime = columnTpls.includes('remainingTime');
|
||||||
|
let showBilling = false;
|
||||||
|
let showRemainingTime = false;
|
||||||
|
const list = serverList.map((server) => {
|
||||||
|
// 负载\网速\流量\在线等
|
||||||
|
const realTimeResult = handleServerRealTime({
|
||||||
|
props: {
|
||||||
|
info: server,
|
||||||
|
},
|
||||||
|
serverRealTimeListTpls: tpls,
|
||||||
|
});
|
||||||
|
const realTimeData = {};
|
||||||
|
realTimeResult?.serverRealTimeList?.value?.forEach?.((item) => {
|
||||||
|
if (item.show) {
|
||||||
|
const text = [item.value];
|
||||||
|
if (item.unit) {
|
||||||
|
text.push(item.unit);
|
||||||
|
}
|
||||||
|
realTimeData[item.key] = {
|
||||||
|
value: item.value,
|
||||||
|
unit: item.unit,
|
||||||
|
text: text.join(''),
|
||||||
|
item,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
realTimeData[item.key] = {
|
||||||
|
text: '-',
|
||||||
|
item,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// CPU\内存\硬盘\交换 进度条
|
||||||
|
const {
|
||||||
|
serverStatusList,
|
||||||
|
} = handleServerStatus({
|
||||||
|
props: {
|
||||||
|
info: server,
|
||||||
|
},
|
||||||
|
statusListTpl: tpls,
|
||||||
|
statusListItemContent: false,
|
||||||
|
});
|
||||||
|
const progressData = {};
|
||||||
|
serverStatusList.value?.forEach?.((item) => {
|
||||||
|
progressData[item.type] = item;
|
||||||
|
});
|
||||||
|
let billAndPlan = null;
|
||||||
|
if (hasBilling || hasRemainingTime) {
|
||||||
|
const result = handleServerBillAndPlan({
|
||||||
|
props: {
|
||||||
|
info: server,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
billAndPlan = result.billAndPlan;
|
||||||
|
if (billAndPlan?.value?.billing) {
|
||||||
|
showBilling = true;
|
||||||
|
}
|
||||||
|
if (billAndPlan?.value?.remainingTime) {
|
||||||
|
console.log('remainingTime', billAndPlan.value.remainingTime);
|
||||||
|
showRemainingTime = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const columnData = [];
|
||||||
|
columnProps.forEach((columnItem) => {
|
||||||
|
columnData.push({
|
||||||
|
...columnItem,
|
||||||
|
data: handleServerItemData({
|
||||||
|
column: columnItem,
|
||||||
|
server,
|
||||||
|
realTimeData,
|
||||||
|
progressData,
|
||||||
|
billAndPlan,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
info: server,
|
||||||
|
columnData,
|
||||||
|
computedData: {
|
||||||
|
realTimeData,
|
||||||
|
progressData,
|
||||||
|
billAndPlan,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
list,
|
||||||
|
columnProps,
|
||||||
|
showBilling,
|
||||||
|
showRemainingTime,
|
||||||
|
};
|
||||||
|
};
|
||||||
186
src/views/components/server-list-by-server-status/table/td.vue
Normal file
186
src/views/components/server-list-by-server-status/table/td.vue
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
<template>
|
||||||
|
<td
|
||||||
|
class="server-status-td server-status-body-td"
|
||||||
|
:class="columnClass"
|
||||||
|
:style="columnStyle"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="server-status-td-content"
|
||||||
|
:class="'server-status-td-content--' + tdContent.prop"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
v-if="tdContent.type === 'text'"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-if="isSet(tdContent.value)"
|
||||||
|
class="text--value"
|
||||||
|
>
|
||||||
|
{{ tdContent.value }}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-if="isSet(tdContent.unit)"
|
||||||
|
class="text--unit"
|
||||||
|
>
|
||||||
|
{{ tdContent.unit }}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-if="!isSet(tdContent.value) && isSet(tdContent.text)"
|
||||||
|
class="text"
|
||||||
|
>
|
||||||
|
{{ tdContent.text }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template
|
||||||
|
v-if="tdContent.type === 'component'"
|
||||||
|
>
|
||||||
|
<component :is="tdContent.component" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
/**
|
||||||
|
* 自定义TD组件
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
computed,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
column: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 计算css的长度单位
|
||||||
|
const getCssLengthUnit = (value) => {
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
return `${value}px`;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const columnClass = computed(() => {
|
||||||
|
const className = {};
|
||||||
|
if (props.column.align) {
|
||||||
|
className[`server-status-td--align-${props.column.align}`] = true;
|
||||||
|
}
|
||||||
|
return className;
|
||||||
|
});
|
||||||
|
|
||||||
|
const columnStyle = computed(() => {
|
||||||
|
const style = {};
|
||||||
|
if (props.column.width) {
|
||||||
|
style.width = getCssLengthUnit(props.column.width);
|
||||||
|
}
|
||||||
|
if (props.column.minWidth) {
|
||||||
|
style.minWidth = getCssLengthUnit(props.column.minWidth);
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
});
|
||||||
|
|
||||||
|
const tdContent = computed(() => {
|
||||||
|
if (['text', 'component'].includes(props.column.data.type)) {
|
||||||
|
return props.column.data;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
});
|
||||||
|
|
||||||
|
function isSet(value) {
|
||||||
|
return value !== undefined && value !== null && value !== '';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.server-status-td {
|
||||||
|
height: var(--server-status-td-height);
|
||||||
|
padding: var(--server-status-cell-padding);
|
||||||
|
|
||||||
|
--td-content-justify-content: center;
|
||||||
|
|
||||||
|
&--align-center {
|
||||||
|
--td-content-justify-content: center;
|
||||||
|
}
|
||||||
|
&--align-right {
|
||||||
|
--td-content-justify-content: flex-end;
|
||||||
|
}
|
||||||
|
&--align-left {
|
||||||
|
--td-content-justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.server-status-td-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: var(--td-content-justify-content);
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&--transfer {
|
||||||
|
.text--value {
|
||||||
|
color: var(--transfer-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--inTransfer {
|
||||||
|
.text--value {
|
||||||
|
color: var(--transfer-in-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&--outTransfer {
|
||||||
|
.text--value {
|
||||||
|
color: var(--transfer-out-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--inSpeed {
|
||||||
|
.text--value {
|
||||||
|
color: var(--net-speed-in-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--outSpeed {
|
||||||
|
.text--value {
|
||||||
|
color: var(--net-speed-out-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--load {
|
||||||
|
.text--value {
|
||||||
|
color: var(--load-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--duration {
|
||||||
|
.text--value {
|
||||||
|
color: var(--duration-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--cpu {
|
||||||
|
.text--value {
|
||||||
|
color: var(--cpu-text-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--mem {
|
||||||
|
.text--value {
|
||||||
|
color: var(--mem-text-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--swap {
|
||||||
|
.text--value {
|
||||||
|
color: var(--swap-text-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--disk {
|
||||||
|
.text--value {
|
||||||
|
color: var(--disk-text-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
<template>
|
||||||
|
<th
|
||||||
|
class="server-status-th"
|
||||||
|
:class="columnClass"
|
||||||
|
:style="columnStyle"
|
||||||
|
>
|
||||||
|
{{ column.label }}
|
||||||
|
</th>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
/**
|
||||||
|
* 自定义TH组件
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
computed,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
column: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 计算css的长度单位
|
||||||
|
const getCssLengthUnit = (value) => {
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
return `${value}px`;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const columnClass = computed(() => {
|
||||||
|
const className = {};
|
||||||
|
if (props.column.align) {
|
||||||
|
className[`server-status-th--align-${props.column.align}`] = true;
|
||||||
|
}
|
||||||
|
return className;
|
||||||
|
});
|
||||||
|
|
||||||
|
const columnStyle = computed(() => {
|
||||||
|
const style = {};
|
||||||
|
if (props.column.width) {
|
||||||
|
style.width = getCssLengthUnit(props.column.width);
|
||||||
|
}
|
||||||
|
if (props.column.minWidth) {
|
||||||
|
style.minWidth = getCssLengthUnit(props.column.minWidth);
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.server-status-th {
|
||||||
|
padding: var(--server-status-cell-padding);
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&--align-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
&--align-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
&--align-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -7,6 +7,7 @@
|
|||||||
:class="{
|
:class="{
|
||||||
'server-list--row': showListRow,
|
'server-list--row': showListRow,
|
||||||
'server-list--card': showListCard,
|
'server-list--card': showListCard,
|
||||||
|
'server-list--status': showListByServerStatus,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
@ -17,6 +18,7 @@
|
|||||||
:class="{
|
:class="{
|
||||||
'server-list--row': showListRow,
|
'server-list--row': showListRow,
|
||||||
'server-list--card': showListCard,
|
'server-list--card': showListCard,
|
||||||
|
'server-list--status': showListByServerStatus,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
@ -41,6 +43,10 @@ defineProps({
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
showListByServerStatus: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -94,6 +100,18 @@ defineProps({
|
|||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.server-list-container.server-list--status {
|
||||||
|
--list-padding: 20px;
|
||||||
|
--list-gap-size: 12px;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--list-gap-size);
|
||||||
|
width: var(--list-container-width);
|
||||||
|
padding: 0 var(--list-padding);
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.list-move,
|
.list-move,
|
||||||
.list-enter-active,
|
.list-enter-active,
|
||||||
.list-leave-active {
|
.list-leave-active {
|
||||||
|
|||||||
@ -12,7 +12,10 @@
|
|||||||
class="progress-bar-label"
|
class="progress-bar-label"
|
||||||
:title="label + '使用' + used + '%'"
|
:title="label + '使用' + used + '%'"
|
||||||
>
|
>
|
||||||
<span class="server-status-label">
|
<span
|
||||||
|
v-if="label"
|
||||||
|
class="server-status-label"
|
||||||
|
>
|
||||||
{{ label }}:
|
{{ label }}:
|
||||||
</span>
|
</span>
|
||||||
<span class="server-status-val-text">
|
<span class="server-status-val-text">
|
||||||
|
|||||||
@ -221,6 +221,18 @@ export default (params) => {
|
|||||||
value: transfer.value?.value,
|
value: transfer.value?.value,
|
||||||
unit: transfer.value?.unit,
|
unit: transfer.value?.unit,
|
||||||
show: validate.isSet(transfer.value?.value),
|
show: validate.isSet(transfer.value?.value),
|
||||||
|
data: {
|
||||||
|
in: {
|
||||||
|
value: inTransfer.value?.value,
|
||||||
|
unit: inTransfer.value?.unit,
|
||||||
|
show: validate.isSet(inTransfer.value?.value),
|
||||||
|
},
|
||||||
|
out: {
|
||||||
|
value: outTransfer.value?.value,
|
||||||
|
unit: outTransfer.value?.unit,
|
||||||
|
show: validate.isSet(outTransfer.value?.value),
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
case 'inTransfer':
|
case 'inTransfer':
|
||||||
return {
|
return {
|
||||||
@ -263,6 +275,18 @@ export default (params) => {
|
|||||||
`${netOutSpeed.value?.value}${netOutSpeed.value?.unit}`,
|
`${netOutSpeed.value?.value}${netOutSpeed.value?.unit}`,
|
||||||
].join('|'),
|
].join('|'),
|
||||||
show: validate.isSet(netInSpeed.value?.value) && validate.isSet(netOutSpeed.value?.value),
|
show: validate.isSet(netInSpeed.value?.value) && validate.isSet(netOutSpeed.value?.value),
|
||||||
|
data: {
|
||||||
|
in: {
|
||||||
|
value: netInSpeed.value?.value,
|
||||||
|
unit: netInSpeed.value?.unit,
|
||||||
|
show: validate.isSet(netInSpeed.value?.value),
|
||||||
|
},
|
||||||
|
out: {
|
||||||
|
value: netOutSpeed.value?.value,
|
||||||
|
unit: netOutSpeed.value?.unit,
|
||||||
|
show: validate.isSet(netOutSpeed.value?.value),
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
case 'load':
|
case 'load':
|
||||||
return {
|
return {
|
||||||
@ -271,12 +295,49 @@ export default (params) => {
|
|||||||
value: (props.info.State?.Load1 || 0).toFixed(2),
|
value: (props.info.State?.Load1 || 0).toFixed(2),
|
||||||
show: validate.isSet(props.info.State?.Load1),
|
show: validate.isSet(props.info.State?.Load1),
|
||||||
};
|
};
|
||||||
|
case 'loads':
|
||||||
|
{
|
||||||
|
const loads = [];
|
||||||
|
loads.push((props.info.State?.Load1 || 0).toFixed(2));
|
||||||
|
loads.push((props.info.State?.Load5 || 0).toFixed(2));
|
||||||
|
loads.push((props.info.State?.Load15 || 0).toFixed(2));
|
||||||
|
return {
|
||||||
|
key,
|
||||||
|
label: '负载',
|
||||||
|
value: loads.join(','),
|
||||||
|
show: loads.some((load) => validate.isSet(load)),
|
||||||
|
data: {
|
||||||
|
load1: {
|
||||||
|
value: (props.info.State?.Load1 || 0).toFixed(2),
|
||||||
|
show: validate.isSet(props.info.State?.Load1),
|
||||||
|
},
|
||||||
|
load5: {
|
||||||
|
value: (props.info.State?.Load5 || 0).toFixed(2),
|
||||||
|
show: validate.isSet(props.info.State?.Load5),
|
||||||
|
},
|
||||||
|
load15: {
|
||||||
|
value: (props.info.State?.Load15 || 0).toFixed(2),
|
||||||
|
show: validate.isSet(props.info.State?.Load15),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
case 'conns':
|
case 'conns':
|
||||||
return {
|
return {
|
||||||
key,
|
key,
|
||||||
label: '连接',
|
label: '连接',
|
||||||
value: `${props.info.State?.TcpConnCount || 0}|${props.info.State?.UdpConnCount || 0}`,
|
value: `${props.info.State?.TcpConnCount || 0}|${props.info.State?.UdpConnCount || 0}`,
|
||||||
show: true,
|
show: true,
|
||||||
|
data: {
|
||||||
|
tcp: {
|
||||||
|
value: props.info.State?.TcpConnCount || 0,
|
||||||
|
show: validate.isSet(props.info.State?.TcpConnCount),
|
||||||
|
},
|
||||||
|
udp: {
|
||||||
|
value: props.info.State?.UdpConnCount || 0,
|
||||||
|
show: validate.isSet(props.info.State?.UdpConnCount),
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
case 'tcp':
|
case 'tcp':
|
||||||
return {
|
return {
|
||||||
@ -292,6 +353,7 @@ export default (params) => {
|
|||||||
value: props.info.State?.UdpConnCount || 0,
|
value: props.info.State?.UdpConnCount || 0,
|
||||||
show: validate.isSet(props.info.State?.UdpConnCount),
|
show: validate.isSet(props.info.State?.UdpConnCount),
|
||||||
};
|
};
|
||||||
|
// 入网和出网
|
||||||
case 'I-A-O':
|
case 'I-A-O':
|
||||||
return {
|
return {
|
||||||
key,
|
key,
|
||||||
@ -314,6 +376,7 @@ export default (params) => {
|
|||||||
],
|
],
|
||||||
show: validate.isSet(netInSpeed.value?.value) && validate.isSet(netOutSpeed.value?.value),
|
show: validate.isSet(netInSpeed.value?.value) && validate.isSet(netOutSpeed.value?.value),
|
||||||
};
|
};
|
||||||
|
// 负载和进程
|
||||||
case 'L-A-P':
|
case 'L-A-P':
|
||||||
return {
|
return {
|
||||||
key,
|
key,
|
||||||
@ -334,6 +397,7 @@ export default (params) => {
|
|||||||
],
|
],
|
||||||
show: validate.isSet(props.info.State?.Load1) || validate.isSet(props.info.State?.ProcessCount),
|
show: validate.isSet(props.info.State?.Load1) || validate.isSet(props.info.State?.ProcessCount),
|
||||||
};
|
};
|
||||||
|
// 连接 TCP和UDP
|
||||||
case 'T-A-U':
|
case 'T-A-U':
|
||||||
return {
|
return {
|
||||||
key,
|
key,
|
||||||
@ -354,6 +418,7 @@ export default (params) => {
|
|||||||
],
|
],
|
||||||
show: validate.isSet(props.info.State?.TcpConnCount) || validate.isSet(props.info.State?.UdpConnCount),
|
show: validate.isSet(props.info.State?.TcpConnCount) || validate.isSet(props.info.State?.UdpConnCount),
|
||||||
};
|
};
|
||||||
|
// 在线和流量
|
||||||
case 'D-A-T':
|
case 'D-A-T':
|
||||||
return {
|
return {
|
||||||
key,
|
key,
|
||||||
|
|||||||
@ -40,6 +40,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 列表模式 -->
|
||||||
<server-list-warp
|
<server-list-warp
|
||||||
v-if="showListRow"
|
v-if="showListRow"
|
||||||
:show-transition="showTransition"
|
:show-transition="showTransition"
|
||||||
@ -51,6 +52,17 @@
|
|||||||
:info="item"
|
:info="item"
|
||||||
/>
|
/>
|
||||||
</server-list-warp>
|
</server-list-warp>
|
||||||
|
<!-- ServerStatus模式 -->
|
||||||
|
<server-list-warp
|
||||||
|
v-if="showListByServerStatus"
|
||||||
|
:show-transition="showTransition"
|
||||||
|
:show-list-by-server-status="showListByServerStatus"
|
||||||
|
>
|
||||||
|
<server-list-by-server-status
|
||||||
|
:server-list="filterServerList.list"
|
||||||
|
/>
|
||||||
|
</server-list-warp>
|
||||||
|
<!-- 卡片模式 -->
|
||||||
<server-list-warp
|
<server-list-warp
|
||||||
v-if="showListCard"
|
v-if="showListCard"
|
||||||
:show-transition="showTransition"
|
:show-transition="showTransition"
|
||||||
@ -109,6 +121,7 @@ import ServerOptionBox from './components/server-list/server-option-box.vue';
|
|||||||
import ServerListWarp from './components/server-list/server-list-warp.vue';
|
import ServerListWarp from './components/server-list/server-list-warp.vue';
|
||||||
import ServerCardItem from './components/server-list/card/server-list-item.vue';
|
import ServerCardItem from './components/server-list/card/server-list-item.vue';
|
||||||
import ServerRowItem from './components/server-list/row/server-list-item.vue';
|
import ServerRowItem from './components/server-list/row/server-list-item.vue';
|
||||||
|
import ServerListByServerStatus from './components/server-list-by-server-status/main.vue';
|
||||||
|
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
const worldMapWidth = ref();
|
const worldMapWidth = ref();
|
||||||
@ -140,12 +153,21 @@ const showListRow = computed(() => {
|
|||||||
const showListCard = computed(() => {
|
const showListCard = computed(() => {
|
||||||
if (windowWidth.value > 1024) {
|
if (windowWidth.value > 1024) {
|
||||||
if (config.nazhua.listServerItemTypeToggle) {
|
if (config.nazhua.listServerItemTypeToggle) {
|
||||||
return listType.value !== 'row';
|
return listType.value === 'card';
|
||||||
}
|
}
|
||||||
return config.nazhua.listServerItemType !== 'row';
|
return config.nazhua.listServerItemType === 'card';
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
const showListByServerStatus = computed(() => {
|
||||||
|
if (windowWidth.value > 1024) {
|
||||||
|
if (config.nazhua.listServerItemTypeToggle) {
|
||||||
|
return listType.value === 'status';
|
||||||
|
}
|
||||||
|
return config.nazhua.listServerItemType === 'status';
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
const showFilter = computed(() => config.nazhua.hideFilter !== true);
|
const showFilter = computed(() => config.nazhua.hideFilter !== true);
|
||||||
const filterFormData = ref({
|
const filterFormData = ref({
|
||||||
@ -217,14 +239,19 @@ watch(() => serverCount.value, () => {
|
|||||||
|
|
||||||
const listTypeOptions = computed(() => [{
|
const listTypeOptions = computed(() => [{
|
||||||
key: 'card',
|
key: 'card',
|
||||||
label: '卡片',
|
label: '卡片模式',
|
||||||
value: 'card',
|
value: 'card',
|
||||||
icon: 'ri-gallery-view-2',
|
icon: 'ri-gallery-view-2',
|
||||||
}, {
|
}, {
|
||||||
key: 'row',
|
key: 'row',
|
||||||
label: '列表',
|
label: '列表模式',
|
||||||
value: 'row',
|
value: 'row',
|
||||||
icon: 'ri-list-view',
|
icon: 'ri-list-view',
|
||||||
|
}, {
|
||||||
|
key: 'status',
|
||||||
|
label: 'ServerStatus模式',
|
||||||
|
value: 'status',
|
||||||
|
icon: 'ri-server-line',
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const filterServerList = computed(() => {
|
const filterServerList = computed(() => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user