vue3中,改造环形进度条Progress 组件——显示不同颜色
效果
代码
1、引入页面
index.vue
<template>
<div class="pitDownStatistics-box">
<titleHeader :title="title" />
<div class="pitDownStatistics-data">
<div class="pitDownStatistics-data-left">
<Torus
:color="torusData.color"
:percentage="torusData.percentage"
:width="torusData.width"
:title="torusData.title"
:strokeWidth="torusData.strokeWidth"
@click="handleAttendanceStatistics"
></Torus>
</div>
<div class="pitDownStatistics-data-right">
<ChartList :list="dataList" @click="handleAttendanceStatistics"></ChartList>
</div>
</div>
</div>
</template>
<script setup lang="ts" name="pitDownStatistics">
import { ref } from "vue";
import Torus from "../components/torus.vue";
import titleHeader from "@/components/header/titleHeader.vue";
import ChartList from "../components/chartList.vue";
const title = ref("请假数据统计");
const torusData = ref({
color: "#00F0FF",
percentage: 89,
width: 130,
title: "出勤率",
strokeWidth: 8
});
const dataList = ref([
{
title: "累计休假",
value: 20,
color: "#00F0FF",
unit: "人次"
},
{
title: "累计缺勤",
value: 30,
color: "#FF5D5D",
unit: "人次"
},
{
title: "累计迟到早退",
value: 18,
color: "#0075FF",
unit: "人次"
}
]);
const handleAttendanceStatistics = () => {
console.log("点击事件");
};
</script>
<style scoped lang="scss">
.pitDownStatistics-data {
display: flex;
align-items: center;
height: calc(100% - 54px);
.pitDownStatistics-data-left {
position: relative;
flex: 1;
height: 100%;
justify-content: center;
align-items: center;
display: flex;
}
.pitDownStatistics-data-right {
flex: 1;
}
}
</style>
2、进度条组件页面
src\views\attendance\components\torus.vue
<template>
<div class="torus-box">
<el-progress
type="circle"
:percentage="props.percentage"
:color="props.color"
:stroke-width="props.strokeWidth"
:width="props.width"
>
<template #default="{ percentage }">
<span class="percentage-value">{{ percentage }}%</span>
<span class="percentage-label">{{ props.title }}</span>
</template>
</el-progress>
</div>
</template>
<script setup lang="ts">
const props = defineProps({
color: {
type: String,
required: true,
default: "#00FFBB"
},
title: {
type: String,
required: true,
default: "默认"
},
percentage: {
type: Number,
required: true,
default: 30
},
width: {
type: Number,
required: true,
default: 120
},
strokeWidth: {
type: Number,
required: true,
default: 8
}
});
</script>
<style scoped lang="scss">
.torus-box {
position: relative;
flex: 1;
height: 100%;
justify-content: center;
align-items: center;
display: flex;
.percentage-value {
color: rgba(255, 255, 255, 1);
font-family: PingFang SC;
font-weight: 500;
font-size: 24px;
display: block;
margin-bottom: 2px;
}
.percentage-label {
color: rgba(173, 185, 199, 1);
font-family: PingFang SC;
font-size: 12px;
}
}
</style>
3、title组件
src\components\header\titleHeader.vue
<template>
<div class="header-container">
<div class="title-img">
<!-- title文字 -->
<span>{{ props.title }}</span>
<!-- title单选 -->
<slot name="right"></slot>
<!-- title图片 -->
<img @click="isDialog" class="header" :src="props.src" v-show="props.src != ''" />
</div>
<div class="mark">
<slot name="mark" />
</div>
</div>
</template>
<script lang="ts" setup>
const props = defineProps({
src: {
type: String,
required: false,
default: ""
},
title: {
type: String,
required: true,
default: ""
}
});
// 展示弹框
const emit = defineEmits(["is-dialog"]);
const isDialog = () => {
emit("is-dialog", "");
};
</script>
<style lang="scss" scoped>
.header-container {
padding: 24px 24px 6px;
.title-img {
display: flex;
font-family: "PingFang SC";
font-size: 22px;
color: rgb(255 255 255 / 100%);
align-items: center;
> span {
margin-right: auto;
}
> img {
cursor: pointer;
margin-left: 24px;
height: 20px;
}
}
}
</style>
4、不同颜色显示组件
src\views\attendance\components\chartList.vue
<template>
<div class="chartList-box">
<div class="chartList-item" v-for="(item, index) in props.list" :key="index">
<div :style="{ 'border-color': item.color }"></div>
<p>{{ item.title }}</p>
<span
><b :style="{ color: item.color }">{{ item.value }}</b
>{{ item.unit }}</span
>
</div>
</div>
</template>
<script setup lang="ts">
type listType = {
title: string;
value: number;
color: string;
unit: string;
};
const props = defineProps({
list: {
type: Array<listType>,
required: true,
default: () => {
return [
{
title: "默认",
value: 12,
color: "red",
unit: "个"
}
];
}
}
});
</script>
<style scoped lang="scss">
.chartList-item {
position: relative;
display: flex;
align-items: center;
margin-right: 14%;
margin-bottom: 14px;
> div {
width: 4px;
height: 4px;
border-radius: 50%;
border: 2px solid;
}
> span {
display: block;
width: 100px;
font-family: "PingFang SC";
font-size: 14px;
color: #fff;
text-align: right;
> b {
font-size: 20px;
font-weight: 600;
}
}
> p {
width: 130px;
margin-right: auto;
margin-left: 8px;
font-family: "PingFang SC";
font-size: 16px;
color: #fff;
}
}
.chartList-item:last-of-type {
margin-bottom: 0;
}
.chartList-item::after {
position: absolute;
bottom: -5px;
left: 3px;
width: 100%;
height: 1px;
content: "";
background-color: rgba(219, 223, 241, 0.2);
}
</style>