LockerChange.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <template>
  2. <ContentWrap>
  3. <div ref="barChart" class="h-350px mt-3"></div>
  4. </ContentWrap>
  5. </template>
  6. <script lang="ts" setup>
  7. import { getMaterialsChangeStatistics } from '@/api/material/statistics/index'
  8. import * as echarts from 'echarts'
  9. defineOptions({ name: 'LockerChange' })
  10. const props = defineProps({
  11. startTime: {
  12. type: String,
  13. default: ''
  14. },
  15. endTime: {
  16. type: String,
  17. default: ''
  18. }
  19. })
  20. const barChart = ref<HTMLElement>() // 图表容器
  21. const chartInstance = ref<echarts.ECharts>() // 图表实例
  22. const cabinetData = ref([]) // 存储请求到的柜子数据
  23. const queryParams = reactive({
  24. startTime: undefined as string | undefined,
  25. endTime: undefined as string | undefined
  26. })
  27. // 监听日期变化
  28. watch(
  29. () => [props.startTime, props.endTime],
  30. ([newStartTime, newEndTime]) => {
  31. if (newStartTime && newEndTime) {
  32. queryParams.startTime = newStartTime
  33. queryParams.endTime = newEndTime
  34. getList()
  35. }
  36. }
  37. )
  38. /** 获取数据 */
  39. const getList = async () => {
  40. try {
  41. const response = await getMaterialsChangeStatistics(queryParams)
  42. console.log(response,'数据格式')
  43. cabinetData.value = response
  44. renderChart()
  45. } catch (error) {
  46. console.error('获取物资更换统计数据失败:', error)
  47. }
  48. }
  49. /** 渲染图表 */
  50. const renderChart = () => {
  51. if (!cabinetData.value.length || !barChart.value) return
  52. // 初始化图表实例
  53. chartInstance.value = echarts.init(barChart.value)
  54. // 提取数据
  55. const materialTypeName = cabinetData.value.map(item => item.materialsTypeName)
  56. const allCount = cabinetData.value.map(item => item.allCount)
  57. const expireCount = cabinetData.value.map(item => item.expireCount)
  58. const badCount = cabinetData.value.map(item => item.badCount)
  59. // 配置图表选项
  60. const options = {
  61. title: {
  62. text: '物资更换统计',
  63. left: 'center',
  64. top: '0%'
  65. },
  66. tooltip: {
  67. trigger: 'axis',
  68. axisPointer: {
  69. type: 'cross',
  70. crossStyle: {
  71. color: '#999'
  72. }
  73. }
  74. },
  75. legend: {
  76. data: ['正常更换次数', '过期更换次数', '损坏更换次数'],
  77. top: '6%',
  78. left: 'center'
  79. },
  80. xAxis: [
  81. {
  82. type: 'category',
  83. data: materialTypeName,
  84. axisPointer: {
  85. type: 'shadow'
  86. }
  87. }
  88. ],
  89. dataZoom: {
  90. show: true,
  91. start: 0,
  92. end: 100,
  93. maxSpan: 100
  94. },
  95. yAxis: [
  96. {
  97. type: 'value',
  98. name: '次数',
  99. axisLabel: {
  100. formatter: '{value} '
  101. },
  102. splitLine: {
  103. show: false
  104. }
  105. }
  106. ],
  107. series: [
  108. {
  109. name: '正常更换次数',
  110. type: 'bar',
  111. stack: 'Ad',
  112. barWidth: '25%',
  113. tooltip: {
  114. valueFormatter: (value: number) => value + ' 次'
  115. },
  116. data: allCount,
  117. itemStyle: {
  118. color: '#5470c6'
  119. }
  120. },
  121. {
  122. name: '过期更换次数',
  123. type: 'bar',
  124. stack: 'Ad',
  125. emphasis: {
  126. focus: 'series'
  127. },
  128. data: expireCount,
  129. itemStyle: {
  130. color: '#91cc75'
  131. }
  132. },
  133. {
  134. name: '损坏更换次数',
  135. type: 'bar',
  136. stack: 'Ad',
  137. emphasis: {
  138. focus: 'series'
  139. },
  140. data: badCount,
  141. itemStyle: {
  142. color: '#fac858'
  143. }
  144. }
  145. ]
  146. }
  147. // 设置图表配置
  148. chartInstance.value.setOption(options)
  149. }
  150. /** 组件销毁前清理图表实例 */
  151. onBeforeUnmount(() => {
  152. if (chartInstance.value) {
  153. chartInstance.value.dispose()
  154. }
  155. })
  156. /** 初始化 */
  157. onMounted(() => {
  158. getList()
  159. if (props.startTime && props.endTime) {
  160. queryParams.startTime = props.startTime
  161. queryParams.endTime = props.endTime
  162. getList()
  163. }
  164. })
  165. </script>
  166. <style lang="scss" scoped>
  167. .h-350px {
  168. height: 350px;
  169. }
  170. .mt-3 {
  171. margin-top: 3%;
  172. }
  173. </style>