Subjects.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import {
  2. PropType,
  3. defineComponent,
  4. nextTick,
  5. onMounted,
  6. ref,
  7. toRefs,
  8. watch
  9. } from 'vue';
  10. import styles from '../index.module.less';
  11. import icons from '../icons.json';
  12. import { Badge, Image, Skeleton, SkeletonParagraph } from 'vant';
  13. import * as echarts from 'echarts';
  14. import { ISubjectDistribution } from '../type';
  15. import icon_2 from '../image/icon_2.png';
  16. type EChartsOption = echarts.EChartsOption;
  17. const colors = [
  18. '#5B8FF9',
  19. '#F6BD16',
  20. '#5AD8A6',
  21. '#E8684A',
  22. '#5D7092',
  23. '#6DC8EC'
  24. ];
  25. export default defineComponent({
  26. name: 'Subjects',
  27. props: {
  28. list: {
  29. type: Array as PropType<ISubjectDistribution[]>,
  30. default: () => []
  31. }
  32. },
  33. setup(props) {
  34. const firstInit = ref(false);
  35. const echratsRef = ref();
  36. const { list } = toRefs(props);
  37. watch(
  38. () => list.value,
  39. () => {
  40. firstInit.value = true;
  41. nextTick(() => {
  42. handleInit();
  43. });
  44. }
  45. );
  46. let myChart: echarts.ECharts;
  47. const handleInit = () => {
  48. if (!list.value.length) return;
  49. if (myChart) {
  50. myChart.dispose();
  51. }
  52. myChart = echarts.init(echratsRef.value);
  53. const option: EChartsOption = {
  54. grid: {
  55. left: 8,
  56. top: 16,
  57. right: 5,
  58. bottom: 5,
  59. containLabel: true
  60. },
  61. xAxis: {
  62. type: 'category',
  63. axisTick: {
  64. show: false
  65. },
  66. axisLabel: {
  67. color: '#333',
  68. fontSize: 10,
  69. rotate: 30
  70. },
  71. axisLine: {
  72. lineStyle: {
  73. color: '#F2F2F2'
  74. }
  75. },
  76. data: list.value.map(item => item.subjectName)
  77. },
  78. yAxis: {
  79. type: 'value'
  80. },
  81. series: [
  82. {
  83. data: list.value.map(item => item.studentNum),
  84. type: 'bar',
  85. label: {
  86. show: true,
  87. position: 'top'
  88. },
  89. itemStyle: {
  90. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  91. { offset: 0, color: '#FFD1A9' },
  92. { offset: 1, color: '#FFCAD0' }
  93. ])
  94. },
  95. barWidth: 20
  96. }
  97. ]
  98. };
  99. option && myChart.setOption(option);
  100. };
  101. return () => (
  102. <div class={styles.item}>
  103. <div class={styles.itemTop}>
  104. <Image class={styles.icon} src={icons[2]} />
  105. <div class={styles.title}>声部分布</div>
  106. <div class={styles.des}>(单位:人)</div>
  107. </div>
  108. {!firstInit.value && (
  109. <div class={[styles.subjectContainer, styles.itemEmtry]}>
  110. <Skeleton loading={true}>
  111. {{
  112. template: () => (
  113. <div class={styles.subjectEcharts}>
  114. <SkeletonParagraph />
  115. <SkeletonParagraph />
  116. <SkeletonParagraph />
  117. <SkeletonParagraph />
  118. <SkeletonParagraph />
  119. <SkeletonParagraph />
  120. </div>
  121. )
  122. }}
  123. </Skeleton>
  124. </div>
  125. )}
  126. <div
  127. style={{ display: list.value.length ? '' : 'none' }}
  128. class={styles.subjectContainer}>
  129. <div class={styles.subjectEcharts} ref={echratsRef}></div>
  130. </div>
  131. {firstInit.value && !list.value.length && (
  132. <div class={[styles.gradeContainer, styles.itemEmtry]}>
  133. <Image src={icon_2} />
  134. </div>
  135. )}
  136. </div>
  137. );
  138. }
  139. });