BarChart.vue 4.5 KB

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