DailySeizureChart.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. <template>
  2. <div class="daily-seizure-chart">
  3. <div class="chart-section">
  4. <div class="sub-title">总表</div>
  5. <div class="chart-container" ref="totalChart"></div>
  6. </div>
  7. <div class="chart-section">
  8. <div class="sub-title">{{title}}</div>
  9. <div class="chart-container" ref="deptChart"></div>
  10. </div>
  11. </div>
  12. </template>
  13. <script>
  14. import * as echarts from 'echarts'
  15. export default {
  16. name: 'DailySeizureChart',
  17. props: {
  18. title: {
  19. type: String,
  20. default: '部门对比'
  21. },
  22. chartsData: {
  23. type: Object,
  24. default: () => ({
  25. total: {
  26. labels: ['5/20', '5/21', '5/22', '5/23', '5/24', '5/25', '5/26'],
  27. data: [280, 320, 290, 350, 310, 280, 152]
  28. },
  29. dept: {
  30. labels: ['5/20', '5/21', '5/22', '5/23', '5/24', '5/25', '5/26'],
  31. deptData: [
  32. { name: '旅检一部', data: [90, 100, 95, 110, 100, 95, 52] },
  33. { name: '旅检二部', data: [95, 110, 100, 120, 105, 90, 50] },
  34. { name: '旅检三部', data: [95, 110, 95, 120, 105, 95, 50] }
  35. ]
  36. }
  37. })
  38. }
  39. },
  40. data() {
  41. return {
  42. charts: {}
  43. }
  44. },
  45. mounted() {
  46. this.$nextTick(() => {
  47. this.initCharts()
  48. })
  49. },
  50. watch: {
  51. chartsData: {
  52. deep: true,
  53. handler() {
  54. this.$nextTick(() => {
  55. this.disposeCharts()
  56. this.initCharts()
  57. })
  58. }
  59. }
  60. },
  61. methods: {
  62. disposeCharts() {
  63. Object.values(this.charts).forEach(chart => {
  64. if (chart) chart.dispose()
  65. })
  66. this.charts = {}
  67. },
  68. initCharts() {
  69. this.initTotalChart()
  70. this.initDeptChart()
  71. },
  72. initTotalChart() {
  73. if (!this.$refs.totalChart) return
  74. this.charts.total = echarts.init(this.$refs.totalChart)
  75. const option = {
  76. responsive: true,
  77. maintainAspectRatio: false,
  78. tooltip: {
  79. trigger: 'axis',
  80. axisPointer: { type: 'shadow' }
  81. },
  82. grid: {
  83. left: '10%',
  84. right: '5%',
  85. bottom: '18%',
  86. top: '10%'
  87. },
  88. xAxis: {
  89. type: 'category',
  90. data: this.chartsData.total.labels,
  91. axisLine: {
  92. lineStyle: {
  93. color: 'rgba(0, 0, 0, 0.1)'
  94. }
  95. },
  96. axisLabel: {
  97. color: '#666',
  98. fontSize: 10,
  99. rotate: 30
  100. }
  101. },
  102. yAxis: {
  103. type: 'value',
  104. axisLine: {
  105. show: false
  106. },
  107. axisTick: {
  108. show: false
  109. },
  110. splitLine: {
  111. lineStyle: {
  112. color: 'rgba(0, 0, 0, 0.05)'
  113. }
  114. },
  115. axisLabel: {
  116. color: '#666',
  117. fontSize: 10
  118. }
  119. },
  120. series: [{
  121. type: 'line',
  122. data: this.chartsData.total.data,
  123. smooth: true,
  124. itemStyle: {
  125. color: '#A78BFA'
  126. },
  127. areaStyle: {
  128. color: {
  129. type: 'linear',
  130. x: 0,
  131. y: 0,
  132. x2: 0,
  133. y2: 1,
  134. colorStops: [{
  135. offset: 0, color: '#A78BFA40'
  136. }, {
  137. offset: 1, color: '#A78BFA00'
  138. }]
  139. }
  140. }
  141. }]
  142. }
  143. this.charts.total.setOption(option)
  144. },
  145. initDeptChart() {
  146. if (!this.$refs.deptChart) return
  147. this.charts.dept = echarts.init(this.$refs.deptChart)
  148. const colors = ['#60A5FA', '#A78BFA', '#34D399']
  149. const series = (this.chartsData.dept.deptData || []).map((dept, index) => ({
  150. name: dept.name,
  151. type: 'line',
  152. data: dept.data,
  153. smooth: true,
  154. itemStyle: {
  155. color: colors[index % colors.length]
  156. }
  157. }))
  158. const option = {
  159. responsive: true,
  160. maintainAspectRatio: false,
  161. tooltip: {
  162. trigger: 'axis',
  163. axisPointer: { type: 'shadow' }
  164. },
  165. legend: {
  166. data: (this.chartsData.dept.deptData || []).map(d => d.name),
  167. textStyle: {
  168. color: '#333',
  169. fontSize: 9
  170. },
  171. top: 0
  172. },
  173. grid: {
  174. left: '10%',
  175. right: '5%',
  176. bottom: '14%',
  177. top: '22%'
  178. },
  179. xAxis: {
  180. type: 'category',
  181. data: this.chartsData.dept.labels,
  182. axisLine: {
  183. lineStyle: {
  184. color: 'rgba(255, 255, 255, 0.1)'
  185. }
  186. },
  187. axisLabel: {
  188. color: '#333',
  189. fontSize: 10
  190. }
  191. },
  192. yAxis: {
  193. type: 'value',
  194. axisLine: {
  195. show: false
  196. },
  197. axisTick: {
  198. show: false
  199. },
  200. splitLine: {
  201. lineStyle: {
  202. color: 'rgba(255, 255, 255, 0.05)'
  203. }
  204. },
  205. axisLabel: {
  206. color: '#333',
  207. fontSize: 10
  208. }
  209. },
  210. series: series
  211. }
  212. this.charts.dept.setOption(option)
  213. }
  214. },
  215. beforeDestroy() {
  216. Object.values(this.charts).forEach(chart => {
  217. if (chart) chart.dispose()
  218. })
  219. }
  220. }
  221. </script>
  222. <style lang="scss" scoped>
  223. .daily-seizure-chart {
  224. .chart-section {
  225. margin-bottom: 32rpx;
  226. &:last-child {
  227. margin-bottom: 0;
  228. }
  229. }
  230. .sub-title {
  231. font-size: 24rpx;
  232. color: #666;
  233. margin-bottom: 16rpx;
  234. }
  235. .chart-container {
  236. height:450rpx;
  237. }
  238. }
  239. </style>