BarChart.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. <template>
  2. <div class="bar-chart-container">
  3. <div class="chart-wrapper">
  4. <v-chart
  5. class="chart"
  6. :option="chartOption"
  7. :autoresize="true"
  8. style="height: 244px;"
  9. />
  10. </div>
  11. <div class="title">历史卸载次数</div>
  12. </div>
  13. </template>
  14. <script lang="ts" setup>
  15. import { ref, computed, onMounted, watch } from 'vue'
  16. import { use } from 'echarts/core'
  17. import { CanvasRenderer } from 'echarts/renderers'
  18. import { BarChart } from 'echarts/charts'
  19. import {
  20. TitleComponent,
  21. TooltipComponent,
  22. LegendComponent,
  23. GridComponent
  24. } from 'echarts/components'
  25. import VChart from 'vue-echarts'
  26. use([
  27. CanvasRenderer,
  28. BarChart,
  29. TitleComponent,
  30. TooltipComponent,
  31. LegendComponent,
  32. GridComponent
  33. ])
  34. interface BarItem {
  35. name: string
  36. value: number
  37. percentage: string
  38. }
  39. const props = withDefaults(defineProps<{
  40. data?: BarItem[]
  41. }>(), {
  42. data: () => []
  43. })
  44. // 默认数据
  45. const defaultData: BarItem[] = [
  46. { name: '6次以上', value: 45, percentage: '45.0%' },
  47. { name: '5次', value: 23, percentage: '23.0%' },
  48. { name: '4次', value: 15, percentage: '15.0%' },
  49. { name: '3次', value: 8, percentage: '8.0%' },
  50. { name: '2次', value: 6, percentage: '6.0%' },
  51. { name: '1次', value: 3, percentage: '3.0%' }
  52. ]
  53. const displayData = computed(() => {
  54. return props.data && props.data.length > 0 ? props.data : defaultData
  55. })
  56. const chartOption = computed(() => {
  57. return {
  58. tooltip: {
  59. trigger: 'axis',
  60. axisPointer: {
  61. type: 'shadow'
  62. },
  63. formatter: function(params: any) {
  64. const data = params[0]
  65. return `${data.name}<br/>设备数:${data.value} (${data.data.percentage})`
  66. },
  67. backgroundColor: 'rgba(255, 255, 255, 0.9)',
  68. borderColor: '#e6e6e6',
  69. borderWidth: 1,
  70. textStyle: {
  71. color: '#333'
  72. }
  73. },
  74. grid: {
  75. left: '0',
  76. right: '0',
  77. bottom: '0',
  78. top: '3%',
  79. containLabel: true
  80. },
  81. xAxis: {
  82. type: 'category',
  83. data: displayData.value.map(item => item.name),
  84. axisLine: {
  85. lineStyle: {
  86. color: '#e6e6e6'
  87. }
  88. },
  89. axisTick: {
  90. show: false
  91. },
  92. axisLabel: {
  93. color: '#666',
  94. fontSize: 12
  95. }
  96. },
  97. yAxis: {
  98. type: 'value',
  99. name: '次数',
  100. nameTextStyle: {
  101. color: '#666',
  102. fontSize: 12
  103. },
  104. axisLine: {
  105. show: false
  106. },
  107. axisTick: {
  108. show: false
  109. },
  110. axisLabel: {
  111. color: '#666',
  112. fontSize: 12
  113. },
  114. splitLine: {
  115. lineStyle: {
  116. color: '#f0f0f0',
  117. type: 'dashed'
  118. }
  119. }
  120. },
  121. series: [
  122. {
  123. name: '卸载次数',
  124. type: 'bar',
  125. data: displayData.value.map(item => ({
  126. value: item.value,
  127. percentage: item.percentage
  128. })),
  129. itemStyle: {
  130. color: {
  131. type: 'linear',
  132. x: 0,
  133. y: 0,
  134. x2: 0,
  135. y2: 1,
  136. colorStops: [
  137. { offset: 0, color: 'rgba(109, 173, 249, 1)' },
  138. { offset: 1, color: 'rgba(109, 173, 249, 1)' }
  139. ]
  140. },
  141. borderRadius: [0, 0, 0, 0]
  142. },
  143. emphasis: {
  144. itemStyle: {
  145. color: {
  146. type: 'linear',
  147. x: 0,
  148. y: 0,
  149. x2: 0,
  150. y2: 1,
  151. colorStops: [
  152. { offset: 0, color: 'rgba(109, 173, 249, 1)' },
  153. { offset: 1, color: 'rgba(109, 173, 249, 1)' }
  154. ]
  155. }
  156. }
  157. },
  158. barWidth: '60%'
  159. }
  160. ]
  161. }
  162. })
  163. onMounted(() => {
  164. // 组件挂载后的初始化逻辑
  165. })
  166. // 监听数据变化
  167. watch(displayData, (newData) => {
  168. console.log('Bar chart data updated:', newData)
  169. }, { deep: true })
  170. </script>
  171. <style scoped lang="scss">
  172. .bar-chart-container {
  173. width: 100%;
  174. height: 100%;
  175. text-align: center;
  176. }
  177. .chart-wrapper {
  178. width: 100%;
  179. height: 100%;
  180. display: flex;
  181. align-items: center;
  182. justify-content: center;
  183. }
  184. .chart {
  185. width: 100%;
  186. height: 100%;
  187. }
  188. .title {
  189. display: inline-block;
  190. color: rgba(18, 18, 18, 1);
  191. font-family: Source Han Sans SC;
  192. font-weight: 400;
  193. font-style: Regular;
  194. font-size: 14px;
  195. padding-left: 14px;
  196. position: relative;
  197. margin-top: 30px;
  198. &::before {
  199. content: '';
  200. position: absolute;
  201. left: 0;
  202. top: 50%;
  203. transform: translateY(-50%);
  204. width: 8px;
  205. height: 8px;
  206. background-color: rgba(109, 173, 249, 1);
  207. }
  208. }
  209. </style>