mirror of
https://github.com/hi2shark/nazhua.git
synced 2026-01-16 17:20:42 +08:00
✨ 添加服务器状态进度组件,优化样式和交互,调整背景位置,更新状态计算逻辑
This commit is contained in:
parent
5b1a54beeb
commit
5532d48ffb
@ -3,6 +3,8 @@ window.$$nazhuaConfig = {
|
|||||||
// freeAmount: '白嫖', // 免费服务的费用名称
|
// freeAmount: '白嫖', // 免费服务的费用名称
|
||||||
// infinityCycle: '无限', // 无限周期名称
|
// infinityCycle: '无限', // 无限周期名称
|
||||||
// buyBtnText: '购买', // 购买按钮文案
|
// buyBtnText: '购买', // 购买按钮文案
|
||||||
|
// listServerStatusType: 'progress', // 服务器状态类型--列表
|
||||||
|
// detailServerStatusType: 'progress', // 服务器状态类型--详情页
|
||||||
// hideNavbarServerCount: false, // 隐藏服务器数量
|
// hideNavbarServerCount: false, // 隐藏服务器数量
|
||||||
// hideNavbarServerStat: false, // 隐藏服务器统计
|
// hideNavbarServerStat: false, // 隐藏服务器统计
|
||||||
// hideListItemStatusDonut: true, // 隐藏列表项的饼图
|
// hideListItemStatusDonut: true, // 隐藏列表项的饼图
|
||||||
|
|||||||
@ -39,7 +39,7 @@ import LayoutFooter from './components/footer.vue';
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
background: var(--layout-bg-color) url('~@/assets/images/bg.webp') no-repeat 50% 0%;
|
background: var(--layout-bg-color) url('~@/assets/images/bg.webp') no-repeat 50% 100%;
|
||||||
background-size: 100% auto;
|
background-size: 100% auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,10 @@
|
|||||||
<div class="server-status-and-real-time">
|
<div class="server-status-and-real-time">
|
||||||
<div
|
<div
|
||||||
class="server-status-group"
|
class="server-status-group"
|
||||||
:class="'status-list--' + serverStatusList.length"
|
:class="'type--' + componentName + ' status-list--' + serverStatusList.length"
|
||||||
>
|
>
|
||||||
<server-status-item
|
<component
|
||||||
|
:is="componentMaps[componentName]"
|
||||||
v-for="item in serverStatusList"
|
v-for="item in serverStatusList"
|
||||||
:key="item.type"
|
:key="item.type"
|
||||||
:type="item.type"
|
:type="item.type"
|
||||||
@ -23,10 +24,14 @@
|
|||||||
/**
|
/**
|
||||||
* 服务器状态组
|
* 服务器状态组
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import config from '@/config';
|
||||||
|
|
||||||
import handleServerStatus from '@/views/composable/server-status';
|
import handleServerStatus from '@/views/composable/server-status';
|
||||||
|
|
||||||
import ServerStatusItem from '@/views/components/server/server-status.vue';
|
|
||||||
import ServerListItemRealTime from '@/views/components/server/server-real-time.vue';
|
import ServerListItemRealTime from '@/views/components/server/server-real-time.vue';
|
||||||
|
import ServerStatusDonut from '@/views/components/server/server-status-donut.vue';
|
||||||
|
import ServerStatusProgress from '@/views/components/server/server-status-progress.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
info: {
|
info: {
|
||||||
@ -35,6 +40,16 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const componentMaps = {
|
||||||
|
donut: ServerStatusDonut,
|
||||||
|
progress: ServerStatusProgress,
|
||||||
|
};
|
||||||
|
|
||||||
|
const componentName = [
|
||||||
|
'donut',
|
||||||
|
'progress',
|
||||||
|
].includes(config.nazhua.detailServerStatusType) ? config.nazhua.detailServerStatusType : 'donut';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
serverStatusList,
|
serverStatusList,
|
||||||
} = handleServerStatus({
|
} = handleServerStatus({
|
||||||
@ -87,6 +102,7 @@ const {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
&.type--donut {
|
||||||
&.status-list--3 {
|
&.status-list--3 {
|
||||||
--server-status-size: 200px;
|
--server-status-size: 200px;
|
||||||
--server-status-val-text-font-size: 32px;
|
--server-status-val-text-font-size: 32px;
|
||||||
@ -156,4 +172,16 @@ const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.type--progress {
|
||||||
|
padding: 0 5px;
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
--progress-bar-height: 24px;
|
||||||
|
|
||||||
|
@media screen and (max-width: 350px) {
|
||||||
|
--progress-bar-height: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="server-list-item-bill">
|
<div class="server-list-item-bill">
|
||||||
<div class="remaining-time-info">
|
<div class="left-box">
|
||||||
<template
|
<div
|
||||||
v-if="billAndPlan.remainingTime"
|
v-if="billAndPlan.remainingTime"
|
||||||
|
class="remaining-time-info"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<span class="ri-hourglass-fill" />
|
<span class="ri-hourglass-fill" />
|
||||||
@ -20,7 +21,7 @@
|
|||||||
>
|
>
|
||||||
<span class="text-item value-text">{{ billAndPlan.remainingTime.value }}</span>
|
<span class="text-item value-text">{{ billAndPlan.remainingTime.value }}</span>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else-if="tagList"
|
v-else-if="tagList"
|
||||||
class="tag-list"
|
class="tag-list"
|
||||||
@ -116,6 +117,10 @@ const tagList = computed(() => {
|
|||||||
background: rgba(#000, 0.3);
|
background: rgba(#000, 0.3);
|
||||||
box-shadow: 0 -2px 4px rgba(#000, 0.5);
|
box-shadow: 0 -2px 4px rgba(#000, 0.5);
|
||||||
|
|
||||||
|
.left-box {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
.remaining-time-info {
|
.remaining-time-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -147,6 +152,7 @@ const tagList = computed(() => {
|
|||||||
.tag-list {
|
.tag-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
|
padding-left: 15px;
|
||||||
// 折行隐藏
|
// 折行隐藏
|
||||||
height: 18px;
|
height: 18px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -166,7 +172,7 @@ const tagList = computed(() => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
padding: 0 15px;
|
padding-right: 15px;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
|
|
||||||
.billing-info {
|
.billing-info {
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="server-list-item-status">
|
<div
|
||||||
<server-status-item
|
class="server-list-item-status"
|
||||||
|
:class="'type--' + componentName"
|
||||||
|
>
|
||||||
|
<component
|
||||||
|
:is="componentMaps[componentName]"
|
||||||
v-for="item in serverStatusList"
|
v-for="item in serverStatusList"
|
||||||
:key="item.type"
|
:key="item.type"
|
||||||
:type="item.type"
|
:type="item.type"
|
||||||
@ -16,8 +20,12 @@
|
|||||||
/**
|
/**
|
||||||
* 服务器状态盒子
|
* 服务器状态盒子
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import config from '@/config';
|
||||||
|
|
||||||
import handleServerStatus from '@/views/composable/server-status';
|
import handleServerStatus from '@/views/composable/server-status';
|
||||||
import ServerStatusItem from '@/views/components/server/server-status.vue';
|
import ServerStatusDonut from '@/views/components/server/server-status-donut.vue';
|
||||||
|
import ServerStatusProgress from '@/views/components/server/server-status-progress.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
info: {
|
info: {
|
||||||
@ -26,6 +34,16 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const componentMaps = {
|
||||||
|
donut: ServerStatusDonut,
|
||||||
|
progress: ServerStatusProgress,
|
||||||
|
};
|
||||||
|
|
||||||
|
const componentName = [
|
||||||
|
'donut',
|
||||||
|
'progress',
|
||||||
|
].includes(config.nazhua.listServerStatusType) ? config.nazhua.listServerStatusType : 'donut';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
serverStatusList,
|
serverStatusList,
|
||||||
} = handleServerStatus({
|
} = handleServerStatus({
|
||||||
@ -41,6 +59,19 @@ const {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
|
|
||||||
|
&.type--progress {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
--progress-bar-height: 20px;
|
||||||
|
|
||||||
|
@media screen and (max-width: 350px) {
|
||||||
|
--progress-bar-height: 16px;
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.type--donut {
|
||||||
--server-status-size: 120px;
|
--server-status-size: 120px;
|
||||||
--server-status-val-text-font-size: 20px;
|
--server-status-val-text-font-size: 20px;
|
||||||
--server-status-label-font-size: 14px;
|
--server-status-label-font-size: 14px;
|
||||||
@ -78,4 +109,5 @@ const {
|
|||||||
--server-status-label-font-size: 12px;
|
--server-status-label-font-size: 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -4,9 +4,11 @@
|
|||||||
:class="{
|
:class="{
|
||||||
'server-list-item--offline': info.online === -1,
|
'server-list-item--offline': info.online === -1,
|
||||||
}"
|
}"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="server-info-group server-list-item-head"
|
||||||
@click="openDetail"
|
@click="openDetail"
|
||||||
>
|
>
|
||||||
<div class="server-info-group server-list-item-head">
|
|
||||||
<div class="server-name-group left-box">
|
<div class="server-name-group left-box">
|
||||||
<span
|
<span
|
||||||
class="server-flag"
|
class="server-flag"
|
||||||
@ -36,6 +38,7 @@
|
|||||||
<div
|
<div
|
||||||
v-if="showStatus || showStatus"
|
v-if="showStatus || showStatus"
|
||||||
class="server-list-item-main"
|
class="server-list-item-main"
|
||||||
|
@click="openDetail"
|
||||||
>
|
>
|
||||||
<server-list-item-status
|
<server-list-item-status
|
||||||
v-if="showStatus"
|
v-if="showStatus"
|
||||||
@ -128,6 +131,11 @@ const showBill = config.nazhua.hideListItemBill !== true;
|
|||||||
border-top-right-radius: var(--list-item-border-radius);
|
border-top-right-radius: var(--list-item-border-radius);
|
||||||
background: rgba(#000, 0.3);
|
background: rgba(#000, 0.3);
|
||||||
box-shadow: 0 2px 4px rgba(#000, 0.5);
|
box-shadow: 0 2px 4px rgba(#000, 0.5);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
&.server-list-item-head {
|
&.server-list-item-head {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|||||||
@ -54,6 +54,7 @@ const {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
cursor: default;
|
||||||
|
|
||||||
.item-value {
|
.item-value {
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
<div class="server-status-donut">
|
<div class="server-status-donut">
|
||||||
<chart-donut
|
<chart-donut
|
||||||
:size="size"
|
:size="size"
|
||||||
:used="used"
|
:used="Math.min(Math.max(used, 1), 100)"
|
||||||
:item-colors="colors"
|
:item-colors="colors"
|
||||||
>
|
>
|
||||||
<template #default>
|
<template #default>
|
||||||
149
src/views/components/server/server-status-progress.vue
Normal file
149
src/views/components/server/server-status-progress.vue
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="server-status-progress"
|
||||||
|
:class="'server-status--' + type"
|
||||||
|
>
|
||||||
|
<div class="progress-bar-box">
|
||||||
|
<div
|
||||||
|
class="progress-bar-inner"
|
||||||
|
:style="progressStyle"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="progress-bar-label"
|
||||||
|
:title="label + '使用' + used + '%'"
|
||||||
|
>
|
||||||
|
<span class="server-status-label">
|
||||||
|
{{ label }}:
|
||||||
|
</span>
|
||||||
|
<span class="server-status-val-text">
|
||||||
|
{{ valText }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="content"
|
||||||
|
class="server-status-progress-content"
|
||||||
|
>
|
||||||
|
<span>{{ content?.default }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
/**
|
||||||
|
* 服务器状态进度调单项
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
computed,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: Number,
|
||||||
|
default: 100,
|
||||||
|
},
|
||||||
|
used: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 1,
|
||||||
|
},
|
||||||
|
colors: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
valText: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
type: [String, Object],
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const progressStyle = computed(() => {
|
||||||
|
const style = {};
|
||||||
|
style.width = `${Math.min(props.used, 100)}%`;
|
||||||
|
const color = typeof props.colors === 'string' ? props.colors : props.colors?.used;
|
||||||
|
if (color) {
|
||||||
|
style.backgroundColor = color;
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.server-status-progress {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
|
||||||
|
@media screen and (max-width: 480px) {
|
||||||
|
flex: none;
|
||||||
|
width: calc(50% - 5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 350px) {
|
||||||
|
flex: none;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar-box {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: var(--progress-bar-height);
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
border-radius: var(--progress-bar-height);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar-inner {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: #08f;
|
||||||
|
border-radius: var(--progress-bar-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar-label {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
line-height: var(--progress-bar-height);
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
text-shadow: 1px 1px 2px rgba(#000, 0.8), 0 0 1px rgba(#fff, 0.5);
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.server-status-val-text {
|
||||||
|
color: #a1eafb;
|
||||||
|
}
|
||||||
|
.server-status-label {
|
||||||
|
color: #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.server-status-progress-content {
|
||||||
|
color: #eee;
|
||||||
|
@media screen and (max-width: 480px) {
|
||||||
|
line-height: 20px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -63,7 +63,7 @@ export default (params) => {
|
|||||||
case 'cpu':
|
case 'cpu':
|
||||||
return {
|
return {
|
||||||
type: 'cpu',
|
type: 'cpu',
|
||||||
used: Math.max(props.info.State.CPU, 1),
|
used: (props.info.State.CPU).toFixed(1) * 1,
|
||||||
colors: {
|
colors: {
|
||||||
used: '#0088ff',
|
used: '#0088ff',
|
||||||
total: 'rgba(255, 255, 255, 0.2)',
|
total: 'rgba(255, 255, 255, 0.2)',
|
||||||
@ -85,7 +85,7 @@ export default (params) => {
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: 'mem',
|
type: 'mem',
|
||||||
used: Math.max(useMemAndTotalMem.value.usePercent, 1),
|
used: useMemAndTotalMem.value.usePercent,
|
||||||
colors: {
|
colors: {
|
||||||
used: '#0aa344',
|
used: '#0aa344',
|
||||||
total: 'rgba(255, 255, 255, 0.2)',
|
total: 'rgba(255, 255, 255, 0.2)',
|
||||||
@ -111,7 +111,7 @@ export default (params) => {
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: 'swap',
|
type: 'swap',
|
||||||
used: Math.max(useSwapAndTotalSwap.value.usePercent, 1),
|
used: useSwapAndTotalSwap.value.usePercent,
|
||||||
colors: {
|
colors: {
|
||||||
used: '#ff8c00',
|
used: '#ff8c00',
|
||||||
total: 'rgba(255, 255, 255, 0.2)',
|
total: 'rgba(255, 255, 255, 0.2)',
|
||||||
@ -134,7 +134,7 @@ export default (params) => {
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: 'disk',
|
type: 'disk',
|
||||||
used: Math.max(useDiskAndTotalDisk.value.usePercent, 1),
|
used: useDiskAndTotalDisk.value.usePercent,
|
||||||
colors: {
|
colors: {
|
||||||
used: '#70f3ff',
|
used: '#70f3ff',
|
||||||
total: 'rgba(255, 255, 255, 0.2)',
|
total: 'rgba(255, 255, 255, 0.2)',
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user