|
@@ -0,0 +1,170 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div :id="props.id" :style="{ width: '100%' }" class="pieChart"></div>
|
|
|
|
|
+</template>
|
|
|
|
|
+<script setup lang="ts">
|
|
|
|
|
+ import * as echarts from 'echarts/core';
|
|
|
|
|
+ import { TooltipComponent, LegendComponent, GraphicComponent } from 'echarts/components';
|
|
|
|
|
+ import { PieChart } from 'echarts/charts';
|
|
|
|
|
+ import { CanvasRenderer } from 'echarts/renderers';
|
|
|
|
|
+ import { onMounted, ref, watch } from 'vue';
|
|
|
|
|
+ import type { PieChartData } from './types';
|
|
|
|
|
+
|
|
|
|
|
+ const props = defineProps<{
|
|
|
|
|
+ data: PieChartData[];
|
|
|
|
|
+ id: string;
|
|
|
|
|
+ }>();
|
|
|
|
|
+
|
|
|
|
|
+ echarts.use([TooltipComponent, LegendComponent, PieChart, GraphicComponent, CanvasRenderer]);
|
|
|
|
|
+
|
|
|
|
|
+ const sum = ref(props.data.reduce((acc, cur) => acc + cur.value, 0));
|
|
|
|
|
+ let doughnut;
|
|
|
|
|
+
|
|
|
|
|
+ onMounted(() => {
|
|
|
|
|
+ doughnut = echarts.init(document.getElementById(props.id as string)!);
|
|
|
|
|
+ if (doughnut) {
|
|
|
|
|
+ initDoughnut(doughnut);
|
|
|
|
|
+ drawDoughnut(doughnut);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const drawDoughnut = (doughnut) => {
|
|
|
|
|
+ const doughnutOption = {
|
|
|
|
|
+ series: [
|
|
|
|
|
+ {
|
|
|
|
|
+ data: props.data,
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ };
|
|
|
|
|
+ doughnut.setOption(doughnutOption);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const initDoughnut = (doughnut) => {
|
|
|
|
|
+ const doughnutOption = {
|
|
|
|
|
+ graphic: [
|
|
|
|
|
+ {
|
|
|
|
|
+ type: 'group',
|
|
|
|
|
+ width: '60%',
|
|
|
|
|
+ children: [
|
|
|
|
|
+ {
|
|
|
|
|
+ type: 'text',
|
|
|
|
|
+ left: 'center',
|
|
|
|
|
+ top: '90px',
|
|
|
|
|
+ z: 10,
|
|
|
|
|
+ style: {
|
|
|
|
|
+ text: `${sum.value}`,
|
|
|
|
|
+ fill: '#1777ff',
|
|
|
|
|
+ fontSize: 25,
|
|
|
|
|
+ fontWeight: 'bold',
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ type: 'text',
|
|
|
|
|
+ left: 'center',
|
|
|
|
|
+ top: '125px',
|
|
|
|
|
+ z: 10,
|
|
|
|
|
+ style: {
|
|
|
|
|
+ text: '总人数',
|
|
|
|
|
+ fill: '#1777ff',
|
|
|
|
|
+ fontSize: 14,
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ {
|
|
|
|
|
+ type: 'text',
|
|
|
|
|
+ left: '5%',
|
|
|
|
|
+ bottom: '5px',
|
|
|
|
|
+ z: 10,
|
|
|
|
|
+ style: {
|
|
|
|
|
+ text: '说明:常驻外部人员及临时项目报备人员除外',
|
|
|
|
|
+ fill: '#CCCDD0',
|
|
|
|
|
+ fontSize: 14,
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ // legend: {
|
|
|
|
|
+ // orient: 'vertical',
|
|
|
|
|
+ // top: 'center',
|
|
|
|
|
+ // right: '20%',
|
|
|
|
|
+ // icon: 'circle',
|
|
|
|
|
+ // formatter: (name) => {
|
|
|
|
|
+ // const item = props.data.find((item) => item.name === name);
|
|
|
|
|
+ // return `{a|${name}} ` + (item?.id === 1 ? `{b|${item.value}} ` : `{c|${item?.value}} `) + `{a|人}`;
|
|
|
|
|
+ // },
|
|
|
|
|
+ // textStyle: {
|
|
|
|
|
+ // rich: {
|
|
|
|
|
+ // a: {
|
|
|
|
|
+ // fontSize: 14,
|
|
|
|
|
+ // color: '#8B8B8B',
|
|
|
|
|
+ // },
|
|
|
|
|
+ // b: {
|
|
|
|
|
+ // fontSize: 14,
|
|
|
|
|
+ // color: '#3777FD',
|
|
|
|
|
+ // },
|
|
|
|
|
+ // c: {
|
|
|
|
|
+ // fontSize: 14,
|
|
|
|
|
+ // color: '#F1C7A3',
|
|
|
|
|
+ // },
|
|
|
|
|
+ // },
|
|
|
|
|
+ // },
|
|
|
|
|
+ // },
|
|
|
|
|
+ series: [
|
|
|
|
|
+ {
|
|
|
|
|
+ type: 'pie',
|
|
|
|
|
+ radius: ['50%', '70%'],
|
|
|
|
|
+ center: ['30%', '50%'],
|
|
|
|
|
+ clockwise: true,
|
|
|
|
|
+ avoidLabelOverlap: false,
|
|
|
|
|
+ padAngle: 5,
|
|
|
|
|
+ label: {
|
|
|
|
|
+ show: false,
|
|
|
|
|
+ },
|
|
|
|
|
+ emphasis: {
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ borderColor: '#f3f3f3',
|
|
|
|
|
+ borderWidth: 5,
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ data: props.data,
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ normal: {
|
|
|
|
|
+ color: function (params) {
|
|
|
|
|
+ const colorList = [
|
|
|
|
|
+ ['#3777FD', '#52A8FF'],
|
|
|
|
|
+ ['#F1C7A3', '#F19570'],
|
|
|
|
|
+ ];
|
|
|
|
|
+ const index = params.dataIndex;
|
|
|
|
|
+ return new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
|
|
+ {
|
|
|
|
|
+ offset: 0,
|
|
|
|
|
+ color: colorList[index][0],
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ offset: 1,
|
|
|
|
|
+ color: colorList[index][1],
|
|
|
|
|
+ },
|
|
|
|
|
+ ]);
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ };
|
|
|
|
|
+ doughnut.setOption(doughnutOption);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ watch(
|
|
|
|
|
+ () => props.data,
|
|
|
|
|
+ () => {
|
|
|
|
|
+ sum.value = props.data.reduce((acc, cur) => acc + cur.value, 0);
|
|
|
|
|
+ drawDoughnut(doughnut);
|
|
|
|
|
+ },
|
|
|
|
|
+ );
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
|
+ .pieChart {
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ }
|
|
|
|
|
+</style>
|