Files
dvcp_v2_webapp/project/dvui/layout/AiDvSummary/components/Summary7.vue
2022-03-25 11:09:26 +08:00

267 lines
6.3 KiB
Vue

<template>
<div class="summary7">
<div class="left">
<div class="el-progress-circle" :style="{height: width + 'px', width: width + 'px'}">
<svg viewBox="0 0 100 100">
<defs>
<linearGradient id="blue" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#243D93;stop-opacity:1" />
<stop offset="100%" style="stop-color:#4EFFDC;stop-opacity:1" />
</linearGradient>
</defs>
<path
class="el-progress-circle__track"
:d="trackPath"
stroke="#464C63"
:stroke-width="relativeStrokeWidth"
fill="none"
:style="trailPathStyle"></path>
<path
class="el-progress-circle__path"
:d="trackPath"
:stroke="stroke"
fill="none"
stroke-linecap="butt"
:stroke-width="percentage ? relativeStrokeWidth : 0"
:style="circlePathStyle"></path>
</svg>
<div class="pointer">
<div class="pointer-round"></div>
<div class="pointer-circle"></div>
<div class="pointer-line" :style="{transform: `rotate(${rotateDeg}deg)`}"></div>
</div>
</div>
</div>
<div class="middle">
<p><span>{{ data[0][value] }}</span></p>
<h2>{{ data[0][keys] }}</h2>
</div>
<div class="right">
<div class="summary7-item" v-for="(item, index) in data" :key="index" v-if="index < 4 && index !== 0">
<h2>{{ item[keys] }}</h2>
<p>{{ item[value] }}</p>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Summary7',
props: {
data: {
type: Array,
default: () => []
},
keys: {
type: String,
default: 'key'
},
value: {
type: String,
default: 'value'
},
},
data () {
return {
width: 70,
strokeWidth: 8
}
},
computed: {
rotateDeg () {
return this.percentage / 100 * 270 + (360 * 0.25) / 2 + 90
},
relativeStrokeWidth() {
return (this.strokeWidth / this.width * 100).toFixed(1);
},
percentage () {
if (this.data.length) {
return typeof this.data[0][this.value] === 'string' ? Number(this.data[0][this.value].replace('%', '')) : this.data[0][this.value]
}
return 0
},
radius() {
return parseInt(50 - parseFloat(this.relativeStrokeWidth) / 2, 10);
},
perimeter() {
return 2 * Math.PI * this.radius;
},
trackPath() {
const radius = this.radius;
const isDashboard = true
return `
M 50 50
m 0 ${isDashboard ? '' : '-'}${radius}
a ${radius} ${radius} 0 1 1 0 ${isDashboard ? '-' : ''}${radius * 2}
a ${radius} ${radius} 0 1 1 0 ${isDashboard ? '' : '-'}${radius * 2}
`;
},
strokeDashoffset() {
const offset = -1 * this.perimeter * (1 - this.rate) / 2;
return `${offset}px`;
},
trailPathStyle() {
return {
strokeDasharray: `${(this.perimeter * this.rate)}px, ${this.perimeter}px`,
strokeDashoffset: this.strokeDashoffset
};
},
circlePathStyle() {
return {
strokeDasharray: `${this.perimeter * this.rate * (this.percentage / 100) }px, ${this.perimeter}px`,
strokeDashoffset: this.strokeDashoffset,
transition: 'stroke-dasharray 0.6s ease 0s, stroke 0.6s ease'
};
},
stroke() {
return 'url(#blue)';
},
rate() {
return 0.75
},
},
methods: {
getCurrentColor(percentage) {
if (typeof this.color === 'function') {
return this.color(percentage);
} else if (typeof this.color === 'string') {
return this.color;
} else {
return this.getLevelColor(percentage);
}
},
}
}
</script>
<style lang="scss" scoped>
.summary7 {
display: flex;
align-items: center;
justify-content: space-between;
width: 380px;
height: 124px;
padding: 0 44px;
background: url(../asset/summary6-bg.svg);
background-size: 100% 100%;
.el-progress-circle {
position: relative;
.pointer-round {
position: absolute;
left: 50%;
top: 50%;
z-index: 1;
width: 20px;
height: 20px;
border: 1px solid #2E69FF;
border-radius: 50%;
transform: translate(-50%, -50%);
}
.pointer-circle {
position: absolute;
left: 50%;
top: 50%;
z-index: 1;
width: 8px;
height: 8px;
background: #FDDD60;
border-radius: 50%;
transform: translate(-50%, -50%);
}
.pointer-line {
position: absolute;
left: 50%;
top: 50%;
z-index: 1;
width: 35px;
height: 1px;
background: #FDDD60;
transform: rotate(90deg);
transform-origin: 0 0 0;
}
}
div {
box-sizing: border-box;
}
.left {
position: relative;
top: 5px;
}
.middle {
margin: 0 16px;
p {
display: flex;
align-items: baseline;
justify-content: center;
font-size: 36px;
font-weight: bold;
color: #FFFFFF;
line-height: 32px;
text-align: center;
background-image: linear-gradient(180deg, #FFFFFF 0%, #FFDD8C 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
i {
font-size: 16px;
}
}
h2 {
display: flex;
align-items: baseline;
font-size: 14px;
font-weight: bold;
color: #FFFFFF;
text-align: center;
background-image: linear-gradient(180deg, #FFFFFF 0%, #C7C7C7 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
.right {
}
.summary7-item {
display: flex;
position: relative;
align-items: center;
h2 {
flex: 1;
line-height: 24px;
margin-right: 8px;
color: #A8D7F3;
font-size: 12px;
font-weight: normal;
text-align: right;
}
p {
font-weight: 700;
font-size: 15px;
color: #fff;
}
}
}
</style>