BorrowTrendsChart.vue 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. <template>
  2. <div class="chart-container">
  3. <h3>整体设备借用次数趋势</h3>
  4. <div class="filter-bar">
  5. <button
  6. v-for="range in ranges"
  7. :key="range.value"
  8. :class="{ active: selectedRange === range.value }"
  9. @click="selectedRange = range.value"
  10. >
  11. {{ range.label }}
  12. </button>
  13. </div>
  14. <div v-if="hasData">
  15. <v-chart :option="chartOption" autoresize style="height: 300px;" />
  16. </div>
  17. <div v-else class="empty-tip">暂无数据</div>
  18. </div>
  19. </template>
  20. <script setup lang="ts">
  21. import { ref, computed, watch, onMounted } from 'vue'
  22. import VChart from 'vue-echarts'
  23. import { use } from 'echarts/core'
  24. import {
  25. CanvasRenderer
  26. } from 'echarts/renderers'
  27. import {
  28. LineChart
  29. } from 'echarts/charts'
  30. import {
  31. TitleComponent,
  32. TooltipComponent,
  33. GridComponent,
  34. LegendComponent
  35. } from 'echarts/components'
  36. import * as api from '../api'
  37. use([
  38. CanvasRenderer,
  39. LineChart,
  40. TitleComponent,
  41. TooltipComponent,
  42. GridComponent,
  43. LegendComponent
  44. ])
  45. interface BorrowTrend {
  46. date: string
  47. borrow_count: number
  48. total_duration: number
  49. }
  50. const ranges = [
  51. { label: '近一周', value: 'week' },
  52. { label: '近一个月', value: 'month' },
  53. { label: '近一年', value: 'year' }
  54. ]
  55. const selectedRange = ref('week')
  56. const rawData = ref<BorrowTrend[]>([])
  57. const fetchData = async () => {
  58. // const res = await api.GetBorrowTrends(selectedRange.value)
  59. const res = await api.GetBorrowTrends()
  60. if (res.code === 2000) {
  61. rawData.value = res.data.trends
  62. } else {
  63. rawData.value = []
  64. }
  65. }
  66. watch(selectedRange, fetchData)
  67. onMounted(fetchData)
  68. const hasData = computed(() => rawData.value.length > 0)
  69. const chartOption = computed(() => {
  70. const dates = rawData.value.map(item => item.date)
  71. const borrowCounts = rawData.value.map(item => item.borrow_count)
  72. const durations = rawData.value.map(item => item.total_duration)
  73. return {
  74. tooltip: {
  75. trigger: 'axis'
  76. },
  77. legend: {
  78. data: ['借用次数', '使用时长']
  79. },
  80. xAxis: {
  81. type: 'category',
  82. data: dates
  83. },
  84. yAxis: {
  85. type: 'value',
  86. name: '数量'
  87. },
  88. series: [
  89. {
  90. name: '借用次数',
  91. type: 'line',
  92. data: borrowCounts,
  93. smooth: true
  94. },
  95. {
  96. name: '使用时长',
  97. type: 'line',
  98. data: durations,
  99. smooth: true
  100. }
  101. ]
  102. }
  103. })
  104. </script>
  105. <style scoped>
  106. .chart-container {
  107. width: 100%;
  108. margin: 0 auto;
  109. }
  110. .filter-bar {
  111. margin-bottom: 10px;
  112. }
  113. .filter-bar button {
  114. margin-right: 8px;
  115. padding: 6px 12px;
  116. border: none;
  117. background: #eee;
  118. cursor: pointer;
  119. }
  120. .filter-bar button.active {
  121. background: #409eff;
  122. color: white;
  123. }
  124. .empty-tip {
  125. text-align: center;
  126. color: #999;
  127. padding: 20px;
  128. }
  129. </style>