黄陂项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
5.5 KiB

1 day ago
1 day ago
1 day ago
1 day ago
1 day ago
1 day ago
1 day ago
1 day ago
1 day ago
1 day ago
1 day ago
1 day ago
1 day ago
1 day ago
  1. <template>
  2. <div ref="chartRef" :style="{ height: height, width: width }" />
  3. </template>
  4. <script>
  5. import * as echarts from 'echarts'
  6. import resize from '@/views/dashboard/mixins/resize'
  7. export default {
  8. name: 'CatePie',
  9. mixins: [resize],
  10. props: {
  11. cateData: {
  12. type: Array,
  13. required: true,
  14. default: () => []
  15. },
  16. width: {
  17. type: String,
  18. default: '100%'
  19. },
  20. height: {
  21. type: String,
  22. default: '100%'
  23. },
  24. refreshtime: {
  25. type: Number,
  26. default: null
  27. }
  28. },
  29. data() {
  30. return {
  31. chart: null,
  32. timer: null // 新增:定时器统一管理
  33. }
  34. },
  35. watch: {
  36. cateData: {
  37. handler() {
  38. this.$nextTick(() => {
  39. this.drawChart()
  40. })
  41. },
  42. immediate: true,
  43. deep: true
  44. }
  45. },
  46. mounted() {
  47. this.refreshEchart()
  48. },
  49. beforeDestroy() {
  50. clearInterval(this.timer) // 新增:清除定时器
  51. if (this.chart) {
  52. this.chart.dispose()
  53. this.chart = null
  54. }
  55. },
  56. methods: {
  57. refreshEchart() {
  58. if (this.refreshtime) {
  59. this.timer = setInterval(() => {
  60. this.drawChart() // 优化:直接重绘而非重新初始化
  61. }, this.refreshtime)
  62. } else {
  63. this.initChart()
  64. }
  65. },
  66. initChart() {
  67. if (this.chart) return
  68. const chartDom = this.$refs.chartRef
  69. if (!chartDom) return
  70. this.chart = echarts.init(chartDom)
  71. this.drawChart()
  72. },
  73. drawChart() {
  74. if (!this.chart) this.initChart()
  75. if (!this.chart) return
  76. // 处理无数据情况
  77. const chartData = this.cateData.length
  78. ? this.cateData
  79. : [{ name: '无告警数据', value: 1, itemStyle: { color: '#666666' }}]
  80. // ========== 核心修改:0值项分配极小占比,实现视觉分离 ==========
  81. const processedData = chartData.map(item => {
  82. // 0值替换为极小值(0.01),非0值保持原样
  83. const displayValue = item.value === 0 ? 0.01 : item.value
  84. return {
  85. ...item,
  86. value: displayValue,
  87. // 新增:存储原始值,用于tooltip/label显示
  88. rawValue: item.value
  89. }
  90. })
  91. const option = {
  92. backgroundColor: 'transparent',
  93. tooltip: {
  94. trigger: 'item',
  95. textStyle: { fontSize: 12 },
  96. // 优化:显示原始0值,而非极小值
  97. formatter: (params) => `${params.name}: ${params.data.rawValue} 次 (0%)`
  98. },
  99. legend: {
  100. bottom: 10,
  101. left: 'center',
  102. icon: 'circle',
  103. itemHeight: 8,
  104. itemWidth: 8,
  105. itemGap: 15,
  106. textStyle: {
  107. color: '#ffffff',
  108. fontSize: 11
  109. },
  110. formatter: function(name) {
  111. if (name.length > 6) {
  112. return name.substring(0, 6) + '\n' + name.substring(6)
  113. }
  114. return name
  115. }
  116. },
  117. series: [
  118. {
  119. name: '当日告警统计',
  120. type: 'pie',
  121. radius: ['30%', '60%'],
  122. center: ['50%', '44%'],
  123. avoidLabelOverlap: true, // 优化:开启标签防重叠
  124. // 优化:调整标签线样式,强制分开0值项标签
  125. labelLine: {
  126. show: true,
  127. length: 10, // 增加基础长度
  128. length2: 15, // 增加二级长度
  129. smooth: 0.2, // 轻微平滑,避免线条重叠
  130. lineStyle: (params) => ({
  131. color: params.data.rawValue === 0
  132. ? 'rgba(255,255,255,0.3)'
  133. : '#ffffff',
  134. width: 1
  135. })
  136. },
  137. label: {
  138. show: true,
  139. fontSize: 11,
  140. color: '#ffffff',
  141. // 优化:显示原始0值
  142. formatter: (params) => `${params.data.rawValue}`,
  143. // 新增:调整标签位置,强制分开
  144. position: 'outer',
  145. distance: 20 // 标签离饼图的距离
  146. },
  147. emphasis: {
  148. label: {
  149. show: true,
  150. fontSize: 12,
  151. fontWeight: 'bold'
  152. },
  153. itemStyle: {
  154. shadowBlur: 10,
  155. shadowOffsetX: 0,
  156. shadowColor: 'rgba(0, 0, 0, 0.5)'
  157. }
  158. },
  159. data: processedData,
  160. animationDuration: 1000,
  161. animationEasing: 'cubicOut',
  162. // 新增:饼图扇区之间增加间隙,进一步分开
  163. itemStyle: {
  164. borderColor: 'transparent',
  165. borderWidth: 1
  166. }
  167. }
  168. ]
  169. }
  170. this.chart.setOption(option, true)
  171. },
  172. resize() {
  173. if (this.chart) {
  174. this.chart.resize()
  175. }
  176. }
  177. }
  178. }
  179. </script>
  180. <style lang="scss" scoped>
  181. :deep(.ec-legend) {
  182. padding-bottom: 5px !important;
  183. }
  184. :deep(.ec-tooltip) {
  185. background: rgba(0, 20, 53, 0.9) !important;
  186. border: 1px solid #339cff !important;
  187. border-radius: 4px !important;
  188. }
  189. // 0值项标签半透明区分
  190. :deep(.ec-label) {
  191. &[style*="0 次"] {
  192. fill: rgba(255,255,255,0.5) !important;
  193. }
  194. }
  195. // 新增:给饼图扇区加间隙,视觉上更易区分
  196. :deep(.ec-pie) {
  197. g > path {
  198. stroke: transparent !important;
  199. stroke-width: 1px !important;
  200. }
  201. }
  202. </style>