index.vue 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. <script setup lang="ts">
  2. import { watch } from "vue";
  3. import { useUserStore } from "@/store/modules/user";
  4. import { getGradeList, getGradeStudents } from "@/api/grade";
  5. import { GradeItem } from "@/api/grade/types";
  6. const userStore = useUserStore();
  7. defineOptions({
  8. name: "ClassIndex",
  9. inheritAttrs: false,
  10. });
  11. /**
  12. * 班级数据
  13. */
  14. const gradeData = ref<GradeItem[]>();
  15. // 0加载中,1数据正常,2数据为空
  16. const dataStatus = ref(0);
  17. // 班级status: 0全部1未结课2已结课
  18. const gradeType = ref(0);
  19. async function getGradeItems(schoolId: number, status: number) {
  20. getGradeList(schoolId, status)
  21. .then(({ data }) => {
  22. gradeData.value = data;
  23. dataStatus.value = 1;
  24. })
  25. .catch((error) => {
  26. dataStatus.value = 2;
  27. console.log(error);
  28. });
  29. }
  30. // 请求班级学生数据
  31. async function getStudentList(grade: GradeItem) {
  32. getGradeStudents(grade.id)
  33. .then(({ data }) => {
  34. grade.students = data;
  35. })
  36. .catch((error) => {
  37. console.log(error);
  38. });
  39. }
  40. // 改变班级状态
  41. function changeGradeType() {
  42. getGradeItems(userStore.schoolId, gradeType.value);
  43. }
  44. // 打开班级请求学生
  45. function collapseGrade(grade: GradeItem) {
  46. if (grade.count > 0) {
  47. if (!grade.students || grade.students.length === 0) {
  48. getStudentList(grade);
  49. }
  50. }
  51. }
  52. onMounted(() => {
  53. // 获取班级
  54. getGradeItems(userStore.schoolId, gradeType.value);
  55. });
  56. watch(
  57. () => userStore.schoolId,
  58. (newValue, oldValue) => {
  59. console.log("userStore.schoolId", newValue, oldValue);
  60. // 学校切换后重新加载数据
  61. getGradeItems(newValue, gradeType.value);
  62. }
  63. );
  64. </script>
  65. <template>
  66. <div class="class-container">
  67. <!-- 班级选择 -->
  68. <div class="class-select">
  69. <el-select
  70. v-model="gradeType"
  71. placeholder="全部班级"
  72. size="large"
  73. @change="changeGradeType()"
  74. >
  75. <el-option key="0" label="全部班级" :value="Number(0)" />
  76. <el-option key="1" label="未结课班级" :value="Number(1)" />
  77. <el-option key="1" label="已结课班级" :value="Number(2)" />
  78. </el-select>
  79. </div>
  80. <!-- 班级折叠面板-->
  81. <template v-if="dataStatus == 1">
  82. <div v-for="grade in gradeData" :key="grade.id" class="list-collapse">
  83. <el-collapse v-model="grade.active" @change="collapseGrade(grade)">
  84. <el-collapse-item :name="grade.id" class="testtt">
  85. <template #title>
  86. <div class="title">
  87. <span class="blue mr-10">{{ grade.name }}</span>
  88. <span class="mr-10">教师:{{ grade.teacher_name }}</span>
  89. <span class="mr-10">班级号:{{ grade.num }}</span>
  90. <span v-if="grade.grade_status == 1" class="red"
  91. >结课时间:{{ grade.grade_time }}</span
  92. >
  93. <span class="blue fr"
  94. >学生:{{ grade.count }}人
  95. <el-icon
  96. :class="
  97. grade.active && grade.active.includes(grade.id)
  98. ? 'is-active'
  99. : ''
  100. "
  101. ><CaretBottom
  102. /></el-icon>
  103. </span>
  104. </div>
  105. </template>
  106. <div>
  107. <el-table
  108. :data="grade.students"
  109. max-height="400"
  110. style="width: 100%"
  111. >
  112. <el-table-column
  113. type="index"
  114. label="序号"
  115. width="80"
  116. align="center"
  117. />
  118. <el-table-column
  119. prop="name"
  120. label="学生名称"
  121. width="180"
  122. align="center"
  123. />
  124. <el-table-column
  125. prop="phone"
  126. label="手机号"
  127. width="180"
  128. align="center"
  129. />
  130. <el-table-column
  131. prop="count"
  132. label="训练次数"
  133. width="180"
  134. align="center"
  135. />
  136. <el-table-column />
  137. <!-- 无数据插槽 -->
  138. <template #empty>
  139. <div class="empty">
  140. <img src="../../assets/empty.png" alt="数据为空" />
  141. <p>该班级还未绑定任何学生!</p>
  142. </div>
  143. </template>
  144. </el-table>
  145. </div>
  146. </el-collapse-item>
  147. </el-collapse>
  148. </div>
  149. </template>
  150. <template v-else>
  151. <div class="empty page-empty">
  152. <img src="../../assets/empty.png" alt="数据为空" />
  153. <p v-if="dataStatus == 0">加载中...</p>
  154. <template v-if="dataStatus == 2">
  155. <p v-if="gradeType == 0">您的学校还未创建任何班级!</p>
  156. <p v-if="gradeType == 1">您的学校还没有任何未结课班级!</p>
  157. <p v-if="gradeType == 2">您的学校还没有任何已结课班级!</p>
  158. </template>
  159. </div>
  160. </template>
  161. </div>
  162. </template>
  163. <style lang="scss" scoped>
  164. .class-container {
  165. position: relative;
  166. padding: 20px 30px;
  167. }
  168. .class-select {
  169. margin-bottom: 20px;
  170. .el-select {
  171. width: 160px;
  172. margin: 0;
  173. }
  174. }
  175. :deep(.el-input__wrapper) {
  176. background: #fff;
  177. border-radius: 12px;
  178. box-shadow: none !important;
  179. }
  180. /* el-select 各种边框线隐藏 **/
  181. :deep(.el-select) {
  182. --el-select-input-focus-border-color: none !important;
  183. }
  184. :deep(.el-select .el-input__wrapper.is-focus) {
  185. box-shadow: none !important;
  186. }
  187. :deep(.el-select:hover:not(.el-select--disabled) .el-input__wrapper) {
  188. box-shadow: none !important;
  189. }
  190. .page-empty {
  191. padding: 240px 0;
  192. }
  193. .list-collapse {
  194. padding: 0 32px;
  195. margin-bottom: 10px;
  196. background: #fff;
  197. border-radius: 25px;
  198. .empty {
  199. padding: 20px 0;
  200. }
  201. .title {
  202. width: 100%;
  203. font-size: 18px;
  204. span {
  205. display: inline-block;
  206. }
  207. .blue {
  208. color: #4284f2;
  209. }
  210. .red {
  211. color: #e04962;
  212. }
  213. .fr {
  214. float: right;
  215. }
  216. .el-icon {
  217. vertical-align: middle;
  218. &.is-active {
  219. transform: rotate(180deg);
  220. }
  221. }
  222. }
  223. :deep(.el-collapse),
  224. :deep(.el-collapse-item__header),
  225. :deep(.el-collapse-item__wrap) {
  226. border: none;
  227. }
  228. :deep(.el-collapse-item__arrow) {
  229. display: none;
  230. }
  231. }
  232. :deep(.el-table th.el-table__cell) {
  233. background: #e9ebee;
  234. }
  235. .mobile .list-collapse {
  236. :deep(.el-collapse-item__header) {
  237. height: auto;
  238. }
  239. }
  240. </style>