rd-device-status.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. <script lang="ts" setup>
  2. import * as echarts from 'echarts'
  3. import { ANIMATION, CHART_RENDERER, createTooltip, FONT_FAMILY, THEME } from '@/utils/kb'
  4. interface DeviceStatusItem {
  5. name: string
  6. value: number
  7. }
  8. const chartData: DeviceStatusItem[] = [
  9. {
  10. name: '正常',
  11. value: 269
  12. },
  13. {
  14. name: '带病运行',
  15. value: 1
  16. },
  17. {
  18. name: '故障',
  19. value: 6
  20. }
  21. ]
  22. const chartRef = ref<HTMLDivElement>()
  23. let chart: echarts.ECharts | null = null
  24. function getChartLayout() {
  25. const { clientWidth = 0, clientHeight = 0 } = chartRef.value ?? {}
  26. const compact = clientHeight > 0 && (clientHeight < 210 || clientWidth < 520)
  27. return {
  28. pieRadius: compact ? ['42%', '62%'] : ['48%', '68%'],
  29. pieCenterY: compact ? '50%' : '50%',
  30. legendBottom: compact ? 0 : 8,
  31. legendItemSize: compact ? 9 : 13,
  32. legendGap: compact ? 10 : 18,
  33. legendFontSize: compact ? 10 : 14
  34. }
  35. }
  36. function getChartOption(): echarts.EChartsOption {
  37. const layout = getChartLayout()
  38. return {
  39. ...ANIMATION,
  40. color: [THEME.color.blue.line, THEME.color.orange.line, THEME.color.red.line],
  41. tooltip: createTooltip({
  42. trigger: 'item',
  43. formatter(params: any) {
  44. return `${params.marker}${params.name}<br/>数量:${params.value} 台<br/>占比:${params.percent}%`
  45. }
  46. }),
  47. legend: {
  48. type: 'scroll',
  49. bottom: layout.legendBottom,
  50. left: 'center',
  51. itemWidth: layout.legendItemSize,
  52. itemHeight: layout.legendItemSize,
  53. itemGap: layout.legendGap,
  54. textStyle: {
  55. color: THEME.text.regular,
  56. fontSize: layout.legendFontSize,
  57. fontWeight: 600,
  58. fontFamily: FONT_FAMILY
  59. },
  60. formatter(name: string) {
  61. const item = chartData.find((status) => status.name === name)
  62. return item ? `${name} ${item.value}台` : name
  63. }
  64. },
  65. series: [
  66. {
  67. name: '设备状态',
  68. type: 'pie',
  69. radius: layout.pieRadius,
  70. center: ['50%', layout.pieCenterY],
  71. minAngle: 5,
  72. label: { show: false },
  73. data: chartData
  74. }
  75. ]
  76. }
  77. }
  78. function initChart() {
  79. if (!chartRef.value) return
  80. chart?.dispose()
  81. chart = echarts.init(chartRef.value, undefined, {
  82. renderer: CHART_RENDERER
  83. })
  84. renderChart()
  85. }
  86. function renderChart() {
  87. chart?.setOption(getChartOption(), true)
  88. }
  89. function resizeChart() {
  90. chart?.resize()
  91. renderChart()
  92. }
  93. function destroyChart() {
  94. chart?.dispose()
  95. chart = null
  96. }
  97. onMounted(() => {
  98. initChart()
  99. window.addEventListener('resize', resizeChart)
  100. window.addEventListener('rdkb:resize', resizeChart)
  101. })
  102. onUnmounted(() => {
  103. window.removeEventListener('resize', resizeChart)
  104. window.removeEventListener('rdkb:resize', resizeChart)
  105. destroyChart()
  106. })
  107. </script>
  108. <template>
  109. <div class="panel device-status-panel flex flex-col">
  110. <div class="panel-title">
  111. <div class="icon-decorator">
  112. <span></span>
  113. <span></span>
  114. </div>
  115. 设备状态
  116. </div>
  117. <div class="device-status-body">
  118. <div ref="chartRef" class="device-status-chart"></div>
  119. </div>
  120. </div>
  121. </template>
  122. <style lang="scss" scoped>
  123. @import url('@/styles/kb.scss');
  124. .device-status-panel {
  125. overflow: hidden;
  126. }
  127. .device-status-body {
  128. display: flex;
  129. min-height: 0;
  130. flex: 1;
  131. padding: calc(10px * var(--kb-scale, 1)) calc(16px * var(--kb-scale, 1))
  132. calc(14px * var(--kb-scale, 1));
  133. }
  134. .device-status-chart {
  135. min-height: 0;
  136. flex: 1;
  137. }
  138. </style>