|
@@ -1,19 +1,19 @@
|
|
|
<template>
|
|
|
-
|
|
|
- <div class="gauge">
|
|
|
+ <div :class='["gauge", errorStatus ? "warning-wrap" : ""]'>
|
|
|
<div class="gauge__body"></div>
|
|
|
<svg id="progress-bar" width="100%" height="100%" viewBox="0 0 200 120" preserveAspectRatio="xMidYMid meet">
|
|
|
<defs>
|
|
|
- <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
|
- <stop offset="0%" style="stop-color: #00e3b5; stop-opacity: 1" />
|
|
|
- <stop offset="100%" style="stop-color: #00557f; stop-opacity: 1" />
|
|
|
+ <linearGradient :id="`grad1-${errorStatus}`" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
|
+ <stop offset="0%" :style="`stop-color: ${errorStatus ? '#FF6737' : '#00BAF5'}; stop-opacity: 1`" />
|
|
|
+ <stop offset="100%" :style="`stop-color: ${errorStatus ? '#F5BF00' : '#02E1A2'}; stop-opacity: 1`" />
|
|
|
</linearGradient>
|
|
|
</defs>
|
|
|
<path d="M 20,100 A 80,80 0 0,1 180,100" stroke="#00557f" stroke-width="16" fill="none" stroke-linecap="round" />
|
|
|
- <path id="progress" d="M 20,100 A 80,80 0 0,1 180,100" :stroke="`${progessValue > 0 ? 'url(#grad1)' : '#00557f'}`"
|
|
|
- stroke-width="16" fill="none" :stroke-dasharray="strokeDashArray" stroke-linecap="round" />
|
|
|
+ <path id="progress" d="M 20,100 A 80,80 0 0,1 180,100"
|
|
|
+ :stroke="`${progressValue > 0 ? `url(#grad1-${errorStatus})` : '#00557f'}`" stroke-width="16" fill="none"
|
|
|
+ :stroke-dasharray="strokeDashArray" stroke-linecap="round" />
|
|
|
</svg>
|
|
|
- <span class="img"></span>
|
|
|
+ <span class="img" :style="{ transform: `translate(-50%, 50%) rotate(${angle}deg)` }"></span>
|
|
|
<div class="text">{{ valueNumber }}</div>
|
|
|
</div>
|
|
|
</template>
|
|
@@ -21,88 +21,114 @@
|
|
|
<script setup>
|
|
|
import { computed } from "vue";
|
|
|
|
|
|
-
|
|
|
-
|
|
|
const props = defineProps({
|
|
|
progress: {
|
|
|
type: Number,
|
|
|
default: 0,
|
|
|
},
|
|
|
- value: 0,
|
|
|
- levelVal: 0
|
|
|
-})
|
|
|
+ value: {
|
|
|
+ type: Number,
|
|
|
+ default: 0,
|
|
|
+ },
|
|
|
+ levelVal: {
|
|
|
+ type: Number,
|
|
|
+ default: 0,
|
|
|
+ },
|
|
|
+});
|
|
|
+
|
|
|
+const angle = computed(() => {
|
|
|
+ if (!props.value) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ return props.value / props.levelVal > 1 ? 170 : parseInt((props.value / props.levelVal) * 180);
|
|
|
+});
|
|
|
|
|
|
const strokeDashArray = computed(() => {
|
|
|
const radius = 80;
|
|
|
const circumference = Math.PI * radius;
|
|
|
- const offset = circumference * (1 - progessValue.value / 100);
|
|
|
+ const offset = circumference * (1 - progressValue.value / 100);
|
|
|
return `${circumference - offset}, ${circumference}`;
|
|
|
-})
|
|
|
+});
|
|
|
|
|
|
const valueNumber = computed(() => {
|
|
|
- return Number(props.value).toFixed(2)
|
|
|
-})
|
|
|
+ return props.value ? Number(props.value).toFixed(2) : 0;
|
|
|
+});
|
|
|
|
|
|
-const progessValue = computed(() => {
|
|
|
- return (props.value / props.levelVal) * 100 .toFixed(2)
|
|
|
-})
|
|
|
+const progressValue = computed(() => {
|
|
|
+ return props.value / props.levelVal > 1 ? 100 : parseInt((props.value / props.levelVal) * 100);
|
|
|
+});
|
|
|
|
|
|
+const errorStatus = computed(() => {
|
|
|
+ return parseInt((props.value / props.levelVal) * 100) >= 100;
|
|
|
+});
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
.gauge {
|
|
|
- width: 108px;
|
|
|
- height: 54px;
|
|
|
+ width: 10.8rem;
|
|
|
+ height: 5.4rem;
|
|
|
overflow: hidden;
|
|
|
position: relative;
|
|
|
- z-index: 1;
|
|
|
-
|
|
|
-
|
|
|
+ z-index: 2;
|
|
|
|
|
|
.gauge__body {
|
|
|
- width: 90px;
|
|
|
- height: 90px;
|
|
|
+ width: 9rem;
|
|
|
+ height: 9rem;
|
|
|
border-radius: 50%;
|
|
|
- border: 1px solid rgba(2, 225, 162, 1);
|
|
|
- padding: 3px;
|
|
|
+ border: 0.1rem solid rgba(2, 225, 162, 1);
|
|
|
+ padding: 0.3rem;
|
|
|
position: absolute;
|
|
|
z-index: -1;
|
|
|
- margin-left: 9px;
|
|
|
- margin-top: 4px
|
|
|
+ margin-left: 0.9rem;
|
|
|
+ margin-top: 0.4rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.warning-wrap {
|
|
|
+ .gauge__body {
|
|
|
+ border: 0.1rem solid #FF9237;
|
|
|
+ }
|
|
|
+
|
|
|
+ .text {
|
|
|
+ background: linear-gradient(-180.71deg, #FF9237 30.93%, rgba(50, 128, 255, 0) 80%);
|
|
|
+ }
|
|
|
+
|
|
|
+ .img {
|
|
|
+ background: url('@/assets/images/home/waring_arrow.png') no-repeat;
|
|
|
+ background-size: cover;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
#progress-bar {
|
|
|
- margin-top: 5px;
|
|
|
+ margin-top: 0.5rem;
|
|
|
}
|
|
|
|
|
|
.text {
|
|
|
- width: 45px;
|
|
|
- height: 45px;
|
|
|
+ width: 4.5rem;
|
|
|
+ height: 4.5rem;
|
|
|
border-radius: 50%;
|
|
|
- background: linear-gradient(-180.71deg, #02E1A2 8.93%, rgba(50, 128, 255, 0) 60%);
|
|
|
+ background: linear-gradient(-180.71deg, #02E1A2 8.93%, rgba(50, 128, 255, 0.8) 60%);
|
|
|
position: absolute;
|
|
|
bottom: 0;
|
|
|
left: 50%;
|
|
|
transform: translate(-50%, 50%);
|
|
|
text-align: center;
|
|
|
- font-size: 12px;
|
|
|
+ font-size: 1.2rem;
|
|
|
color: #fff;
|
|
|
font-weight: bold;
|
|
|
- padding-top: 4px;
|
|
|
+ padding-top: 0.4rem;
|
|
|
+ z-index: 4;
|
|
|
}
|
|
|
|
|
|
.img {
|
|
|
- width: 46px;
|
|
|
- height: 36px;
|
|
|
+ width: 6.4rem;
|
|
|
+ height: 4.5rem;
|
|
|
background: url('@/assets/images/home/arrow.png') no-repeat;
|
|
|
background-size: cover;
|
|
|
position: absolute;
|
|
|
left: 50%;
|
|
|
- transform: translate(-50%, 50%) rotate(0deg);
|
|
|
- bottom: 10px;
|
|
|
+ bottom: 0.4rem;
|
|
|
transform-origin: center center;
|
|
|
- // rotate: (180deg);
|
|
|
+ z-index: -1;
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
</style>
|