171 lines
4.3 KiB
Vue
Executable File
171 lines
4.3 KiB
Vue
Executable File
<script lang="ts" setup>
|
|
import {useDataStore} from "~/strores/DataStore";
|
|
import {useMainLayoutStore} from "~/strores/UseMainLayoutStore";
|
|
|
|
const {$gsap} = useNuxtApp()
|
|
const props = defineProps({
|
|
title: {
|
|
type: String,
|
|
default: "CPU使用率"
|
|
},
|
|
unit: {
|
|
type: String,
|
|
default: "%"
|
|
},
|
|
watcher: {
|
|
type: String,
|
|
default: "cpuTotalUsage"
|
|
},
|
|
reverse: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
})
|
|
const value = ref("0");
|
|
const trueValue = ref("0");
|
|
const dataStore = useDataStore()
|
|
const mainStore = useMainLayoutStore()
|
|
//监听dataStore变更
|
|
dataStore.$subscribe((_, state) => {
|
|
//获得d3YT#cpuUserUsage的key的value
|
|
const data = state.data[props.watcher]
|
|
//如果data为空则不更新
|
|
if (!data) {
|
|
value.value = "0"
|
|
updateProgress(0)
|
|
if (props.reverse) {
|
|
value.value = "100"
|
|
updateProgress(100)
|
|
}
|
|
|
|
return
|
|
}
|
|
//如果与data.value 不一致则更新
|
|
const newValue = (Math.floor(Number(data) * 100) / 100).toFixed(2)
|
|
|
|
if (newValue !== value.value) {
|
|
value.value = newValue
|
|
trueValue.value = data.toString()
|
|
//转换为数值
|
|
updateProgress(parseFloat(value.value))
|
|
}
|
|
})
|
|
watch(() => mainStore.SelectServer, () => {
|
|
//立即更新
|
|
value.value = "0"
|
|
updateProgress(0)
|
|
})
|
|
const circumference = 2 * Math.PI * 36;
|
|
const updateProgress = (value: number) => {
|
|
let progress = (100 - value) / 100;
|
|
if (props.reverse) {
|
|
progress = 1 - progress
|
|
}
|
|
$gsap.to("#" + props.title, {
|
|
duration: 0.5,
|
|
ease: 'power1.out',
|
|
strokeDashoffset: circumference * progress,
|
|
})
|
|
$gsap.to("#" + props.title + "Arrow", {
|
|
duration: 0.4,
|
|
ease: 'bounce.inOut',
|
|
rotation: 360 * (value / 100) - 30,
|
|
transformOrigin: "center center"
|
|
})
|
|
let color;
|
|
if (value >= 0 && value < 20) {
|
|
color = "#00C853"; // 绿色
|
|
} else if (value >= 20 && value < 40) {
|
|
color = "#3A57E8"; // 蓝色
|
|
} else if (value >= 40 && value < 60) {
|
|
color = "#FBBD08"; // 黄色
|
|
} else if (value >= 60 && value < 80) {
|
|
color = "#FF5722"; // 红色
|
|
} else if (value >= 80 && value <= 100) {
|
|
color = "#FF0000"; // 假设80-100是深红色
|
|
}
|
|
|
|
if (color) {
|
|
$gsap.to("#" + props.title, {
|
|
duration: 0.5,
|
|
ease: 'power1.out',
|
|
stroke: color,
|
|
});
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="mini-card-box">
|
|
<svg fill="none" viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg">
|
|
<circle cx="36" cy="36" r="32" stroke="#E9ECEF" stroke-width="2"/>
|
|
<circle :id="title" :stroke-dasharray="circumference" cx="36"
|
|
cy="36" r="32" stroke="red"
|
|
stroke-linecap="round"
|
|
stroke-width="4" transform="rotate(-90, 36, 36)"/>
|
|
<path
|
|
:id="title+'Arrow'"
|
|
d="M26.1904 44.784C25.8209 45.1944 25.854 45.8267 26.2645 46.1963C26.6749 46.5658 27.3072 46.5327 27.6767 46.1223L26.1904 44.784ZM43.7763 27.8042C43.7474 27.2527 43.2768 26.829 42.7253 26.8579L33.7376 27.3289C33.1861 27.3578 32.7624 27.8284 32.7913 28.3799C32.8202 28.9314 33.2908 29.3551 33.8423 29.3262L41.8313 28.9075L42.25 36.8965C42.2789 37.4481 42.7495 37.8717 43.301 37.8428C43.8525 37.8139 44.2762 37.3434 44.2473 36.7919L43.7763 27.8042ZM27.6767 46.1223L43.5208 28.5257L42.0345 27.1874L26.1904 44.784L27.6767 46.1223Z"
|
|
fill="#ADB5BD"/>
|
|
</svg>
|
|
<div class="text">
|
|
<h3>
|
|
{{ title }}
|
|
</h3>
|
|
|
|
<h2>
|
|
<span v-if="props.reverse" v-tooltip="`${100-trueValue}${unit}`">{{ 100 - value }}{{ unit }}</span>
|
|
<span v-else v-tooltip="`${trueValue}${unit}`">{{ value }}{{ unit }}</span>
|
|
</h2>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
@import "../../base";
|
|
|
|
.mini-card-box {
|
|
display: flex;
|
|
align-items: center;
|
|
background: $light-bg-color;
|
|
padding: $padding*1.5;
|
|
border-radius: $radius*2;
|
|
box-shadow: 0 10px 30px 0 rgba(17, 38, 146, 0.05);
|
|
gap: $gap*3;
|
|
|
|
> svg {
|
|
width: 68px;
|
|
height: 68px;
|
|
}
|
|
|
|
.dark-mode & {
|
|
background: $dark-bg-color;
|
|
}
|
|
}
|
|
|
|
.text {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: $gap;
|
|
|
|
h2, h3 {
|
|
color: $light-unfocused-color;
|
|
font-size: 16px;
|
|
font-style: normal;
|
|
font-weight: 400;
|
|
line-height: 175%; /* 28px */
|
|
//不允许换行
|
|
text-wrap: nowrap;
|
|
}
|
|
|
|
h2 {
|
|
font-size: 19px;
|
|
font-weight: 500;
|
|
color: $light-text-color;
|
|
|
|
.dark-mode & {
|
|
color: $dark-text-color;
|
|
}
|
|
}
|
|
}
|
|
</style> |