<template>
<div class="container">
<div class="charts-box">
<div class="pie-dec">
<el-tooltip effect="dark" :content="chartTotal" placement="bottom">
<div class="number">
{{ chartTotal }}
<span class="unit">{{ mt('台') }}</span>
</div>
</el-tooltip>
<el-tooltip effect="dark" :content="mt('盘活中资产')" placement="bottom">
<div class="title">
{{ mt('盘活中资产') }}
</div>
</el-tooltip>
</div>
<div id="totalchartBox" class="charts"></div>
</div>
<div class="capacity-label">
<div v-for="(item, index) in aggregatedData" :key="index" class="capacity-label-list">
<div class="type">
<div class="capacity-label-list-dot" :style="{ background: colorList[index] }"></div>
{{ item.type }}
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed, defineProps, onMounted, onUnmounted, ref, watch } from 'vue';
import { getI18n } from '@/util/i18n';
import * as echarts from 'echarts';
const { mt } = getI18n();
const chartOptions = ref({});
const myChart = ref(null);
const props = defineProps({
activeName: {
type: String,
default: () => '',
},
dataList: {
type: Array,
default: () => [],
},
});
// 新增:按 type 聚合数据
const aggregatedData = computed(() => {
const map = new Map<string, number>();
props.dataList.forEach(item => {
const key = item.type;
const value = item.count || 0;
map.set(key, (map.get(key) || 0) + value);
});
return Array.from(map.entries()).map(([type, count]) => ({ type, count }));
});
// 总数量
const chartTotal = computed(() => {
return aggregatedData.value.reduce((sum, item) => sum + item.count, 0);
});
const seriesData = computed(() => {
return aggregatedData.value.map(item => ({
value: item.count,
name: item.type,
}));
});
const colorList = ['#2070F3', '#62B42E', '#715AFB', '#2CB8C9', '#F69E39', '#F3689A'];
const initData = (data: Array) => {
const chartDom = document.getElementById('totalchartBox');
if (myChart.value === null) {
myChart.value = echarts.init(chartDom);
}
chartOptions.value = {
tooltip: {
trigger: 'item',
},
color: colorList,
series: [
{
name: '',
type: 'pie',
radius: ['65%', '80%'],
center: ['50%', '50%'],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 0,
borderColor: '#fff',
borderWidth: 2,
},
label: {
show: true,
position: 'outside',
formatter: '{d}%',
rich: {
name: {
fontSize: 12,
fontWeight: 'bold',
color: '#252b3a',
lineHeight: 20,
},
quantity: {
fontSize: 11,
color: '#666',
lineHeight: 18,
},
percent: {
fontSize: 11,
color: '#999',
lineHeight: 18,
},
},
lineHeight: 20,
},
emphasis: {
label: {
show: true,
fontWeight: 'bold',
},
},
labelLine: {
show: true,
length: 10,
length2: 15,
smooth: false,
lineStyle: {
width: 1,
color: '#ccc',
},
},
data: data,
},
],
};
myChart.value.setOption(chartOptions.value, true);
window.addEventListener('resize', () => {
myChart.value.resize();
});
};
watch(
() => props.dataList,
() => {
initData(seriesData.value);
},
{ deep: true }
);
watch(
() => props.activeName,
() => {
initData(seriesData.value);
},
{ deep: true }
);
onMounted(() => {
window.addEventListener('resize', myChart.value.resize());
});
onUnmounted(() => {
window.removeEventListener('resize', myChart.value.dispose());
});
</script>
<i18n lang="json">
{
"zh": {
"版本": "版本",
"数量": "数量",
"占比": "占比"
},
"en": {
"版本": "version",
"数量": "Quantity",
"占比": "Proportion"
}
}
</i18n>
<style lang="less" scoped>
.dark {
.capacity-label-title {
color: #dfe1e6;
}
.capacity-label-list {
color: #dfe1e6;
}
}
.charts-box {
display: flex;
justify-content: center;
align-items: center;
.pie-dec {
position: absolute;
text-align: center;
z-index: 10;
.number {
font-size: 32px;
font-weight: 600;
color: #191919;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.unit {
font-size: 16px;
font-weight: 400;
}
}
.title {
font-size: 12px;
color: #8a8e99;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 100px;
}
}
}
.dark {
.pie-dec {
.number {
color: #dfe1e6;
}
}
}
.charts {
width: 400px;
height: 190px;
}
.capacity-label {
display: flex;
justify-content: center;
font-size: 14px;
&-title {
margin-bottom: 4px;
display: flex;
justify-content: space-around;
color: #8a8e99;
}
&-list {
display: flex;
justify-content: space-around;
align-items: center;
line-height: 20px;
&-dot {
width: 8px;
height: 8px;
border-radius: 50%;
margin-right: 5px;
}
}
.type {
width: auto;
margin-right: 25px;
display: flex;
flex-wrap: nowrap;
align-items: center;
}
}
</style>
帮我看看代码
最新发布