pie.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. <template>
  2. <div class="pie">
  3. <!-- <div class="pie-percentage no-print" @click="handlePercentage"
  4. >{{ showPercentage ? '隐藏' : '显示' }}百分比</div> -->
  5. <div ref="chartRef" :style="{ height, width }" />
  6. </div>
  7. </template>
  8. <script lang="ts" setup>
  9. import { onMounted, PropType, ref, Ref, watch } from 'vue';
  10. import { useECharts } from '/@/hooks/web/useECharts';
  11. const props = defineProps({
  12. width: {
  13. type: String as PropType<string>,
  14. default: '100%',
  15. },
  16. height: {
  17. type: String as PropType<string>,
  18. default: '400px',
  19. },
  20. data: {
  21. type: Object,
  22. default: () => {},
  23. },
  24. });
  25. // console.log('props', props);
  26. const chartRef = ref<HTMLDivElement | null>(null);
  27. const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
  28. const showPercentage = ref(true);
  29. onMounted(async () => {
  30. setChart();
  31. });
  32. watch(
  33. () => props.data,
  34. _newVal => {
  35. setChart();
  36. },
  37. );
  38. // function handlePercentage() {
  39. // showPercentage.value = !showPercentage.value;
  40. // setChart();
  41. // }
  42. function setChart() {
  43. const data = props.data?.content;
  44. const sum = data?.reduce((pre, cur) => pre + cur.value, 0) || 0;
  45. let legend = {} as any;
  46. legend =
  47. props.data.id != 'bubble' &&
  48. props.data.id != 'jam' &&
  49. props.data.id != 'noBox' &&
  50. props.data.id != 'limit' &&
  51. props.data.id != 'lowBattery' &&
  52. props.data.id != 'outOfControl' &&
  53. props.data.id != 'machine'
  54. ? {
  55. orient: 'vertical',
  56. right: 20,
  57. top: 40,
  58. bottom: 20,
  59. }
  60. : {
  61. orient: 'horizontal',
  62. right: 20,
  63. top: 40,
  64. type: 'scroll',
  65. };
  66. const lableFormatter = showPercentage.value ? '{b} (数量: {c}, 占比: {d}%)' : '{b} ({c})';
  67. setOptions({
  68. title: {
  69. show: false,
  70. text: props.data?.description || '',
  71. left: 'left',
  72. },
  73. tooltip: {
  74. trigger: 'item',
  75. valueFormatter: (value: number) =>
  76. '数量: ' + value + ' 占比: ' + (Number(((value / sum) * 100).toFixed(2)) || 0) + '%',
  77. },
  78. toolbox: {
  79. feature: {
  80. saveAsImage: {
  81. type: 'png',
  82. },
  83. },
  84. },
  85. legend,
  86. series: [
  87. {
  88. type: 'pie',
  89. radius: '50%',
  90. data: props.data?.content || [],
  91. minAngle: 5,
  92. avoidLabelOverlap: true,
  93. label: {
  94. show: true,
  95. formatter: lableFormatter,
  96. overflow: 'break',
  97. },
  98. emphasis: {
  99. itemStyle: {
  100. shadowBlur: 10,
  101. shadowOffsetX: 0,
  102. shadowColor: 'rgba(0, 0, 0, 0.5)',
  103. },
  104. },
  105. },
  106. ],
  107. });
  108. }
  109. </script>
  110. <style lang="less" scoped>
  111. .pie {
  112. position: relative;
  113. &-percentage {
  114. position: absolute;
  115. top: 4px;
  116. right: 35px;
  117. z-index: 99;
  118. border: 1px solid #ccc;
  119. border-radius: 4px;
  120. padding: 2px 4px;
  121. font-size: 12px;
  122. cursor: pointer;
  123. transition: all 0.3s ease-in-out;
  124. &:hover {
  125. box-shadow: 2px 4px 4px rgb(12 12 12 / 10%);
  126. }
  127. }
  128. }
  129. </style>