LockerDaily.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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 { getDayLoanStatistics } from '@/api/material/statistics/index'
  8. import * as echarts from 'echarts'
  9. defineOptions({ name: 'LockerDaily' })
  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. onMounted(()=>{
  39. queryParams.startTime = props.startTime
  40. queryParams.endTime = props.endTime
  41. getList()
  42. })
  43. /** 获取数据 */
  44. const getList = async () => {
  45. try {
  46. const response = await getDayLoanStatistics(queryParams)
  47. // 按日期排序
  48. const sortData = response.sort((a, b) => {
  49. const dateA = new Date(a.day)
  50. const dateB = new Date(b.day)
  51. return dateA.getTime() - dateB.getTime()
  52. })
  53. cabinetData.value = sortData
  54. renderChart()
  55. } catch (error) {
  56. console.error('获取每日领取归还统计数据失败:', error)
  57. }
  58. }
  59. /** 渲染图表 */
  60. const renderChart = () => {
  61. if (!cabinetData.value.length || !barChart.value) return
  62. // 初始化图表实例
  63. chartInstance.value = echarts.init(barChart.value)
  64. // 提取数据
  65. const day = cabinetData.value.map(item => item.day)
  66. const allCount = cabinetData.value.map(item => item.allCount)
  67. const returnCount = cabinetData.value.map(item => item.returnCount)
  68. const timeoutCount = cabinetData.value.map(item => item.timeoutCount)
  69. // 配置图表选项
  70. const options = {
  71. title: {
  72. text: '每日领取归还统计',
  73. left: 'center',
  74. top: '0%'
  75. },
  76. tooltip: {
  77. trigger: 'axis',
  78. axisPointer: {
  79. type: 'cross',
  80. crossStyle: {
  81. color: '#999'
  82. }
  83. }
  84. },
  85. legend: {
  86. data: ['累计领取次数', '累计正常归还次数', '累计超时归还次数'],
  87. top: '6%',
  88. left: 'center'
  89. },
  90. xAxis: [
  91. {
  92. type: 'category',
  93. data: day,
  94. axisPointer: {
  95. type: 'shadow'
  96. }
  97. }
  98. ],
  99. dataZoom: {
  100. show: true,
  101. start: 0,
  102. end: 100,
  103. maxSpan: 100
  104. },
  105. yAxis: [
  106. {
  107. type: 'value',
  108. name: '次数',
  109. axisLabel: {
  110. formatter: '{value} 次'
  111. },
  112. splitLine: {
  113. show: false
  114. }
  115. }
  116. ],
  117. series: [
  118. {
  119. name: '累计领取次数',
  120. type: 'bar',
  121. barWidth: '40%',
  122. tooltip: {
  123. valueFormatter: (value: number) => value + ' 次'
  124. },
  125. data: allCount,
  126. itemStyle: {
  127. color: '#5470c6'
  128. }
  129. },
  130. {
  131. name: '累计正常归还次数',
  132. type: 'bar',
  133. barWidth: '40%',
  134. stack: 'total',
  135. tooltip: {
  136. valueFormatter: (value: number) => value + ' 次'
  137. },
  138. data: returnCount,
  139. itemStyle: {
  140. color: '#a6d58f'
  141. }
  142. },
  143. {
  144. name: '累计超时归还次数',
  145. type: 'bar',
  146. barWidth: '40%',
  147. stack: 'total',
  148. tooltip: {
  149. valueFormatter: (value: number) => value + ' 次'
  150. },
  151. data: timeoutCount,
  152. itemStyle: {
  153. color: '#fac85a'
  154. }
  155. }
  156. ]
  157. }
  158. // 设置图表配置
  159. chartInstance.value.setOption(options)
  160. }
  161. /** 组件销毁前清理图表实例 */
  162. onBeforeUnmount(() => {
  163. if (chartInstance.value) {
  164. chartInstance.value.dispose()
  165. }
  166. })
  167. /** 初始化 */
  168. onMounted(() => {
  169. if (props.startTime && props.endTime) {
  170. queryParams.startTime = props.startTime
  171. queryParams.endTime = props.endTime
  172. getList()
  173. }
  174. })
  175. </script>
  176. <style lang="scss" scoped>
  177. .h-350px {
  178. height: 350px;
  179. }
  180. .mt-3 {
  181. margin-top: 3%;
  182. }
  183. </style>