296 lines
6.5 KiB
Vue
296 lines
6.5 KiB
Vue
<template>
|
||
<view class="chart-box">
|
||
<view class="cont-box">
|
||
<view v-for="width in 3" :class="`percent-${width * 25}`"></view>
|
||
<view class="data-box">
|
||
<view class="line-box">
|
||
<view v-for="width in 3" :class="`percent-${width * 25}`"></view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="title" v-if="fromType === 'crs'">
|
||
<image class="title-icon" src="@/static/images/course/edit.png" alt=""> </image>
|
||
改进建议:
|
||
</view>
|
||
<view class="title" v-if="fromType === 'tra'">
|
||
<image class="title-icon icon-tra" src="@/static/images/sparring/den-icon.png" alt=""> </image>
|
||
维度分析:
|
||
</view>
|
||
<view class="total-score" v-if="fromType === 'crs'">
|
||
<view class="score-num">{{ props.score }}</view>分
|
||
<image class="total-score-icon" src="@/static/images/course/score.png" alt=""></image>
|
||
</view>
|
||
<view v-for="item,index in props.dataList" :class="['score-item', 'score-item'+(index+1)]">
|
||
<view class="score-item-name">{{ item.gradeDimensName || item.gradeDimens }}</view>
|
||
<view class="score-item-score">{{ item.anlyGrade }}</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import {
|
||
ref,
|
||
computed
|
||
} from "vue"
|
||
const props = defineProps({
|
||
dataList: {
|
||
default: () => [],
|
||
type: Array
|
||
},
|
||
score: {
|
||
default: 0,
|
||
type: [Number, String]
|
||
},
|
||
size: {
|
||
default: 262,
|
||
type: [Number, String]
|
||
},
|
||
fromType: {
|
||
default: 'crs',
|
||
type: String
|
||
}
|
||
})
|
||
const dataValue = computed(() => {
|
||
// return props.dataList.map(t => t.anlyGrade)
|
||
return props.dataList.map(t => t.anlyGrade / (t.totalGrade || t.pct || 100) * 100)
|
||
})
|
||
const chartWidth = computed(() => props.size + 'rpx')
|
||
const chartHeight = computed(() => props.size + 'rpx')
|
||
const scoreMarginX = computed(() => {
|
||
return props.size / 2 + 'rpx'
|
||
})
|
||
const scoreMarginY = computed(() => {
|
||
return (props.size / 2 + 30) + 'rpx'
|
||
})
|
||
const scoreMarginAbsX = computed(() => {
|
||
return '-' + (props.size / 2) + 'rpx'
|
||
})
|
||
const scoreMarginAbsY = computed(() => {
|
||
return '-' + (props.size / 2 - 25) + 'rpx'
|
||
})
|
||
const styleFour = ref('polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)')
|
||
const styleFourResult = computed(() => {
|
||
let score = dataValue.value
|
||
if (score.length >= 4) {
|
||
let _tx = 50
|
||
let _ty = 50 - Math.floor((score[0] / 100) * 50)
|
||
let _rx = 50 + Math.floor((score[1] / 100) * 50)
|
||
let _ry = 50
|
||
let _bx = 50
|
||
let _by = 50 + Math.floor((score[2] / 100) * 50)
|
||
let _lx = 50 - Math.floor((score[3] / 100) * 50)
|
||
let _ly = 50
|
||
return `polygon(${_tx}% ${_ty}%, ${_rx}% ${_ry}%, ${_bx}% ${_by}%, ${_lx}% ${_ly}%)`
|
||
} else {
|
||
return `polygon(${0}% ${50}%, ${50}% ${100}%, ${100}% ${50}%, ${50}% ${0}%)`
|
||
}
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.chart-box {
|
||
width: 100%;
|
||
height: 580rpx;
|
||
background: linear-gradient(270deg, #4a74ff 0%, #6fa7fe 100%);
|
||
overflow: hidden;
|
||
position: relative;
|
||
border-radius: 16rpx;
|
||
margin-bottom: 20rpx;
|
||
|
||
.cont-box {
|
||
background-color: #87abfe;
|
||
width: v-bind(chartWidth);
|
||
height: v-bind(chartHeight);
|
||
clip-path: v-bind(styleFour);
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
margin-top: 25rpx;
|
||
|
||
&::before {
|
||
content: '';
|
||
display: block;
|
||
width: 100%;
|
||
height: 3rpx;
|
||
background-color: rgba(255, 255, 255, .3);
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
z-index: 20;
|
||
}
|
||
|
||
&::after {
|
||
content: '';
|
||
display: block;
|
||
height: 100%;
|
||
width: 3rpx;
|
||
background-color: rgba(255, 255, 255, .3);
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
z-index: 20;
|
||
}
|
||
|
||
@for $i from 1 through 3 {
|
||
.percent-#{$i*25} {
|
||
width: $i * 25%;
|
||
height: $i * 25%;
|
||
clip-path: v-bind(styleFour);
|
||
background-color: rgba(255, 255, 255, .3);
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
z-index: (4 - $i) * 2;
|
||
|
||
&::before {
|
||
content: '';
|
||
display: block;
|
||
width: calc(100% - 10rpx);
|
||
height: calc(100% - 10rpx);
|
||
background-color: #87abfe;
|
||
clip-path: v-bind(styleFour);
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
}
|
||
}
|
||
}
|
||
|
||
.data-box {
|
||
width: 100%;
|
||
height: 100%;
|
||
clip-path: v-bind(styleFourResult);
|
||
position: absolute;
|
||
background-color: #fff;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
z-index: 12;
|
||
overflow: hidden;
|
||
|
||
.line-box {
|
||
display: block;
|
||
width: calc(100% - 24rpx);
|
||
height: calc(100% - 24rpx);
|
||
// background-color: #6691fe;
|
||
background-color: #6691fe;
|
||
clip-path: v-bind(styleFourResult);
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
z-index: 14;
|
||
}
|
||
|
||
@for $i from 1 through 3 {
|
||
.percent-#{$i*25} {
|
||
background-color: rgba(255, 255, 255, .1);
|
||
z-index: (4 - $i) * 2 + 10;
|
||
|
||
&::before {
|
||
background-color: #6692ff;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.title {
|
||
padding: 24rpx;
|
||
line-height: 46rpx;
|
||
font-size: 32rpx;
|
||
color: #fff;
|
||
position: relative;
|
||
|
||
.title-icon {
|
||
width: 27rpx;
|
||
height: 27rpx;
|
||
|
||
&.icon-tra {
|
||
position: relative;
|
||
top: 4rpx;
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.total-score {
|
||
position: absolute;
|
||
right: 30rpx;
|
||
top: 30rpx;
|
||
width: 100rpx;
|
||
height: 80rpx;
|
||
line-height: 70rpx;
|
||
font-size: 30rpx;
|
||
color: #fff;
|
||
white-space: nowrap;
|
||
text-shadow: 0 4px 12px rgba(0, 0, 0, .33);
|
||
|
||
.score-num {
|
||
display: inline-block;
|
||
font-size: 60rpx;
|
||
line-height: 70rpx;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.total-score-icon {
|
||
width: 100%;
|
||
height: 16rpx;
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 0;
|
||
}
|
||
}
|
||
|
||
.score-item {
|
||
position: absolute;
|
||
color: #fff;
|
||
width: 120rpx;
|
||
text-align: center;
|
||
|
||
.score-item-name {
|
||
font-size: 28rpx;
|
||
line-height: 36rpx;
|
||
margin-bottom: 4rpx;
|
||
}
|
||
|
||
.score-item-score {
|
||
font-size: 38rpx;
|
||
line-height: 46rpx;
|
||
font-weight: bold;
|
||
}
|
||
|
||
&.score-item1 {
|
||
left: 50%;
|
||
margin-left: -60rpx;
|
||
bottom: 50%;
|
||
transform: translateY(v-bind(scoreMarginAbsY));
|
||
}
|
||
|
||
&.score-item2 {
|
||
right: 0%;
|
||
top: 50%;
|
||
transform: translate(calc(v-bind(scoreMarginAbsX) + 60rpx), calc(-50% + 25rpx));
|
||
}
|
||
|
||
&.score-item3 {
|
||
left: 50%;
|
||
margin-left: -60rpx;
|
||
top: 50%;
|
||
transform: translateY(v-bind(scoreMarginY));
|
||
}
|
||
|
||
&.score-item4 {
|
||
left: 0%;
|
||
top: 50%;
|
||
transform: translate(calc(v-bind(scoreMarginX) - 60rpx), calc(-50% + 25rpx));
|
||
}
|
||
}
|
||
}
|
||
</style> |