优化储存进度条样式

This commit is contained in:
远野千束 2024-10-05 09:14:16 +08:00
parent 3bff292a6d
commit cbd742a85b
7 changed files with 77 additions and 47 deletions

View File

@ -8,7 +8,7 @@ const year = new Date().getFullYear()
<h1 style="text-align: center">Server Status</h1>
<router-view/>
<footer>
<a href="https://github.com/snowykami/server-status-server">Server Status Dashboard</a><br>
<a href="https://github.com/snowykami/server-status-server">Server status dashboard</a><br>
© Copyright 2024-{{year}} <a href="https://sfkm.me" target="_blank">Snowykami</a> All Rights Reserved
</footer>
</template>

View File

@ -72,7 +72,6 @@ export function formatDate(timestamp: number, timeOnly: boolean = false) {
}
export function getBaseColor(percent: number, disable: boolean = false) {
// 获取基础颜色
// 0~60: green, 60~80: yellow, 80~90: orange, 90~100: red
if (disable) {
return '#9ca3af'
@ -93,8 +92,6 @@ export function getBlankColor(percent: number, disable: boolean = false) {
if (disable) {
return '#e5e7eb'
}
//相比base更浅的颜色
if (percent < 60) {
return '#bbf7d0'
} else if (percent < 80) {
@ -115,4 +112,12 @@ export function formatUptime(uptime: number): string {
const m = Math.floor((seconds % 3600) / 60).toString().padStart(2, '0');
const s = Math.floor(seconds % 60).toString().padStart(2, '0');
return `${d}:${h}:${m}:${s}`;
}
export function formatDuration(duration: number): string {
const d = Math.floor(duration / 86400);
const h = Math.floor((duration % 86400) / 3600);
const m = Math.floor((duration % 3600) / 60);
const s = duration % 60;
return d > 0 ? `${d}d` : h > 0 ? `${h}h` : m > 0 ? `${m}m` : `${s}s`;
}

View File

@ -1,5 +1,5 @@
<script setup lang="ts">
import { format2Size, getBaseColor, getBlankColor } from '../api/utils.ts';
import {format2Size, getBaseColor, getBlankColor} from '../api/utils.ts';
const props = defineProps<{
mountpoint: string;
@ -14,8 +14,8 @@ const colorBlank = getBlankColor(props.used / props.total * 100);
</script>
<template>
<div class="disk" :style="{ backgroundColor: colorBlank }">
<div class="disk-used" :style="{ width: props.used / props.total * 100 + '%', backgroundColor: colorUsed }"></div>
<div class="disk">
<div class="hover-text">
<div class="left-text">
<span class="disk-text">{{ props.mountpoint }}</span>
@ -24,59 +24,67 @@ const colorBlank = getBlankColor(props.used / props.total * 100);
<span class="disk-text">{{ format2Size(props.used, props.total) }} [{{ props.fstype }}]</span>
</div>
</div>
<div class="progress-bar" style="display: flex; align-items: center">
<div class="disk-total" :style="{ backgroundColor: colorBlank }" style="margin-right: 0.5rem;">
<div class="disk-used"
:style="{ width: props.used / props.total * 100 + '%', backgroundColor: colorUsed }"></div>
</div>
<div style="color: var(--text-color-2)">
<div class="percentage" style="text-align: right">{{ (props.used / props.total * 100).toFixed(1) }}%</div>
</div>
</div>
</div>
</template>
<style scoped>
:host {
--text-size: 2px;
}
.disk {
margin-top: 0.5rem;
height: 2rem;
width: 100%;
margin-top: 0.75rem;
}
.disk-total {
height: 0.618rem;
width: 90%;
border-radius: 1rem;
position: relative;
display: flex;
align-items: center;
justify-content: center;
justify-content: flex-start;
overflow: hidden; /* Ensure the used part doesn't overflow */
}
.disk-used {
height: 100%;
position: absolute;
left: 0;
top: 0;
clip-path: inset(0 0 0 0 round var(--border-radius)); /* Apply border-radius using clip-path */
clip-path: inset(0 0 0 0 round 1rem);
}
.hover-text {
position: absolute;
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
text-align: center;
padding: 0 1rem;
}
.left-text {
margin-left: 1rem;
display: flex;
justify-content: flex-start;
}
.right-text {
margin-right: 1rem;
display: flex;
justify-content: flex-end;
}
.disk-text {
font-size: var(--text-size);
font-size: 16px;
color: var(--text-color-2);
}
.percentage{
font-size: 14px;
color: var(--text-color-2);
}
</style>

View File

@ -4,7 +4,7 @@ import {computed, onMounted, ref, watch} from "vue";
import * as echarts from "echarts";
import {
format2Size,
formatDate,
formatDate, formatDuration,
formatSizeByUnit,
formatUptime,
getBaseColor,
@ -63,6 +63,7 @@ const hoverBorderColor = computed(() => {
return statusColor.value
})
const fontFam = 'Josefin Sans'
function onMountedFunc() {
const cpuChart = echarts.init(cpuChartRef.value);
@ -73,15 +74,16 @@ function onMountedFunc() {
// style
const titleStyle = {
color: 'rgba(0, 0, 0, 0.8)',
fontSize: 15,
fontSize: 18,
}
const radius = ['65%', '90%']
const radius = ['65%', '80%']
const netColor = ['#a2d8f4', '#0194e3'] // Tx Rx
const pieLabelPosition = 'center'
const emphasis = {
label: {
show: true,
fontSize: 15,
fontFamily: fontFam,
position: ['50%', '20%'] //
},
}
@ -96,7 +98,7 @@ function onMountedFunc() {
function update() {
const timeDiff = (Date.now()) / 1000 - status.value.meta.observed_at
deltaTime.value = timeDiff.toFixed(1)
deltaTime.value = formatDuration(timeDiff)
// push
if (netStats.length === 0 || netStats[netStats.length - 1][0] !== status.value.meta.observed_at) {
netStats.push([status.value.meta.observed_at, status.value.hardware.net.up, status.value.hardware.net.down]) //
@ -119,6 +121,9 @@ function onMountedFunc() {
top: 'center',
textStyle: titleStyle,
},
textStyle: {
fontFamily: fontFam
},
series: [
{
type: 'pie',
@ -154,6 +159,9 @@ function onMountedFunc() {
top: 'center',
textStyle: titleStyle
},
textStyle: {
fontFamily: fontFam
},
series: [
{
type: 'pie',
@ -187,6 +195,9 @@ function onMountedFunc() {
top: 'center',
textStyle: titleStyle,
},
textStyle: {
fontFamily: fontFam
},
series: [
{
type: 'pie',
@ -215,6 +226,12 @@ function onMountedFunc() {
netChart.setOption(
{
color: netColor,
title: {
textStyle: titleStyle
},
textStyle: {
fontFamily: fontFam
},
tooltip: {
trigger: 'axis',
axisPointer: {
@ -228,7 +245,7 @@ function onMountedFunc() {
} else {
return formatDate(params.value, true);
}
}
},
}
},
formatter: function (params: any) {
@ -237,12 +254,10 @@ function onMountedFunc() {
result += item.marker + (item.seriesName == 'Tx' ? '↑' : '↓') + ': ' + formatSizeByUnit(item.value * 8, null, 'bps') + '<br/>';
});
return result;
}
},
},
toolbox: {
feature: {
saveAsImage: {}
}
feature: {}
},
grid: {
top: '25%',
@ -259,7 +274,7 @@ function onMountedFunc() {
axisLabel: {
formatter: function (value: number) {
return formatDate(value, true)
}
},
}
}
],
@ -269,7 +284,7 @@ function onMountedFunc() {
axisLabel: {
formatter: function (value: number) {
return formatSizeByUnit(value * 8, null, 'b')
}
},
}
}
],
@ -280,7 +295,7 @@ function onMountedFunc() {
stack: 'Total',
areaStyle: {},
emphasis: {
focus: 'series'
focus: 'series',
},
data: netStats.map(item => item[1]),
showSymbol: false,
@ -318,9 +333,9 @@ function onMountedFunc() {
// link.download = `screenshot-${status.value.meta.id}-${formatDate(Date.now(), false)}.svg`;
function downloadScreenshot() {
const hostElement = document.querySelector(".host#"+status.value.meta.id);
const hostElement = document.querySelector(".host#" + status.value.meta.id);
if (hostElement) {
html2canvas(<HTMLElement>hostElement, { scale: 2 }).then((canvas) => {
html2canvas(<HTMLElement>hostElement, {scale: 2}).then((canvas) => {
const dataURL = canvas.toDataURL("image/png");
const link = document.createElement("a");
link.href = dataURL;
@ -335,19 +350,21 @@ onMounted(
onMountedFunc()
}
)
</script>
<template>
<div class="host" :style="[gradientStyle, { '--hover-border-color': hoverBorderColor }]" :id="status.meta.id">
<!-- 主机名-->
<!-- 主机名-->
<div class="host-name">{{ status.meta.name }}</div>
<div class="meta-1" style="display: flex; justify-content: space-between">
<div class="meta1-left" style="display: flex; justify-content: flex-start; align-items: center">
<OutlineAnime class="outline-anime" :color="statusColor" :spreadColor="statusColor2" :is-online="isOnline"/>&nbsp;
<div class="uptime" style="margin-right: 5px"
<div class="uptime time-tag" style="margin-right: 5px"
:style="{backgroundColor: statusColor2, borderColor: statusColor}">{{ uptime }}
</div>
<div class="offline-time time-tag" v-if="!isOnline">
Offline for {{ deltaTime }}
</div>
</div>
<div class="meta1-right" style="display: flex; justify-content: flex-end; align-items: center">
<img @click="downloadScreenshot" src="/svg/screenshots.svg" alt="download" style="width: 20px; height: 20px">
@ -356,7 +373,7 @@ onMounted(
<div class="meta-2">
<div class="section">
<img class="icon" :src="os.icon" alt="system">
<span class="meta2-text">{{ os.name }} {{status.meta.os.release}} · {{status.meta.os.machine}}</span>
<span class="meta2-text">{{ os.name }} {{ status.meta.os.release }} · {{ status.meta.os.machine }}</span>
</div>
<div class="section">
<img class="icon" src="/svg/timezone.svg" alt="location">
@ -366,9 +383,9 @@ onMounted(
<img class="icon" src="/svg/label.svg" alt="labels">
<span><span class="label meta2-text" v-for="label in status.meta.labels" :key="label">{{ label }}</span></span>
</div>
</div>
<hr>
<div class="section-name">
Hardware
</div>
@ -390,7 +407,7 @@ onMounted(
</div>
</div>
<hr>
<!-- -->
<!-- -->
<div class="net">
<div class="section-name">
Network
@ -398,7 +415,7 @@ onMounted(
<div class="net-chart" ref="netChartRef"></div>
</div>
<hr>
<!-- -->
<!-- -->
<div class="disks">
<div class="section-name">
Storage
@ -484,7 +501,7 @@ onMounted(
align-items: center;
}
.uptime {
.time-tag {
padding: 0 0.5rem;
font-size: 0.8rem;
border-radius: 50px;

View File

@ -12,7 +12,7 @@
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
--text-color-1: #000;
--text-color-2: #383838;
--text-color-2: #5f5f5f;
}

View File

@ -49,7 +49,7 @@ onUnmounted(() => {
<style scoped>
.overview {
display: flex;
justify-content: space-between;
justify-content: center;
padding: 10px;
}

View File

@ -1 +1 @@
{"root":["./src/main.ts","./src/vite-env.d.ts","./src/api/index.ts","./src/api/node.ts","./src/api/utils.ts","./src/router/index.ts","./src/app.vue","./src/components/disk.vue","./src/components/helloworld.vue","./src/components/host.vue","./src/components/hostdisks.vue","./src/components/nav.vue","./src/components/outlineanime.vue","./src/views/home.vue","./src/views/test.vue"],"version":"5.6.2"}
{"root":["./src/main.ts","./src/vite-env.d.ts","./src/api/index.ts","./src/api/node.ts","./src/api/utils.ts","./src/router/index.ts","./src/app.vue","./src/components/disk.vue","./src/components/helloworld.vue","./src/components/host.vue","./src/components/nav.vue","./src/components/outlineanime.vue","./src/views/home.vue","./src/views/test.vue"],"version":"5.6.2"}