index.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. <script setup lang="ts">
  2. import {useUserStore} from "@/store/modules/user";
  3. import {GradeList} from "@/api/grade/types";
  4. import {TrainingItem, TrainingParams} from "@/api/training/types";
  5. import {getGradeSelect} from "@/api/grade";
  6. import {getTrainingLists} from "@/api/training";
  7. import {trimInput} from "@/utils";
  8. import {RouteLocationRaw, useRouter} from "vue-router";
  9. const router = useRouter();
  10. const userStore = useUserStore();
  11. defineOptions({
  12. name: "TrainingIndex",
  13. inheritAttrs: false,
  14. });
  15. const pageParams: TrainingParams = reactive({
  16. school_id: userStore.schoolId,
  17. is_formal: 1, // 1正式,2非正式
  18. grade_id: 0,
  19. page: 1,
  20. page_size: 10,
  21. // 学生名称/手机号
  22. search: "",
  23. });
  24. const isFormal = ref(1);
  25. /**
  26. * 班级数据
  27. */
  28. const gradeData = ref<GradeList[]>();
  29. async function getGradeData(schoolId: number) {
  30. getGradeSelect(schoolId)
  31. .then(({data}) => {
  32. gradeData.value = data;
  33. gradeData.value?.unshift({id: 0, name: "全部班级"});
  34. })
  35. .catch((error) => {
  36. gradeData.value = [];
  37. gradeData.value?.unshift({id: 0, name: "全部班级"});
  38. console.log(error.message);
  39. });
  40. }
  41. const dataMessage = ref("加载中...");
  42. const trainingData = ref<TrainingItem[]>();
  43. const trainingCount = ref(0);
  44. async function getTrainingData(schoolId: number) {
  45. pageParams.school_id = schoolId;
  46. isFormal.value = pageParams.is_formal;
  47. getTrainingLists(pageParams)
  48. .then(({data}) => {
  49. const {count, lists} = data;
  50. trainingData.value = lists;
  51. trainingCount.value = count;
  52. if (!(count && count > 0 && lists.length > 0)) {
  53. dataMessage.value = "没有符合搜索条件的记录!";
  54. if (pageParams.is_formal == 2 && pageParams.search == "") {
  55. dataMessage.value = "还没有任何体验用户训练记录!";
  56. }
  57. if (pageParams.is_formal == 1 && pageParams.grade_id == 0 && pageParams.search == "") {
  58. dataMessage.value = "还没有任何学生训练记录!";
  59. }
  60. }
  61. })
  62. .catch((error) => {
  63. dataMessage.value = error.message;
  64. console.log(error.message);
  65. });
  66. }
  67. function getTrainingSearch() {
  68. getTrainingData(userStore.schoolId);
  69. }
  70. function alertError() {
  71. ElMessage.error("本次训练采集的数据不足,无法分析并生成有效报告!");
  72. }
  73. function pathTo(url: RouteLocationRaw) {
  74. // 记录搜索条件
  75. sessionStorage.setItem("trainingParams", JSON.stringify(pageParams));
  76. // 路由跳转
  77. router.push(url);
  78. }
  79. onMounted(() => {
  80. // 获取记录的搜索条件
  81. let params = sessionStorage.getItem("trainingParams");
  82. if (params && params != "null") {
  83. const parse: TrainingParams = JSON.parse(params);
  84. if (parse.page && parse.page > 0) {
  85. pageParams.page = parse.page;
  86. }
  87. if (parse.page_size && parse.page_size > 0) {
  88. pageParams.page_size = parse.page_size;
  89. }
  90. if (parse.is_formal && parse.is_formal > 0) {
  91. pageParams.is_formal = parse.is_formal;
  92. }
  93. if (parse.grade_id && parse.grade_id > 0) {
  94. pageParams.grade_id = parse.grade_id;
  95. }
  96. if (parse.search) {
  97. pageParams.search = parse.search;
  98. }
  99. }
  100. sessionStorage.removeItem("trainingParams");
  101. getGradeData(userStore.schoolId);
  102. getTrainingData(userStore.schoolId);
  103. });
  104. </script>
  105. <template>
  106. <div class="training-container">
  107. <!-- 学生查找 -->
  108. <div class="training-search">
  109. <el-select v-model="pageParams.is_formal" placeholder="正式学生/体验用户" size="large">
  110. <el-option key="1" :value="Number(1)" label="正式学生" />
  111. <el-option key="2" :value="Number(2)" label="体验用户" />
  112. </el-select>
  113. <el-select v-if="pageParams.is_formal == 1" v-model="pageParams.grade_id" placeholder="请选择班级" size="large">
  114. <el-option v-for="item in gradeData" :key="item.id" :label="item.name" :value="item.id" />
  115. </el-select>
  116. <el-input
  117. v-model="pageParams.search"
  118. placeholder="请输入学生名称或手机号码"
  119. size="large"
  120. @input="(value:string) => (pageParams.search = trimInput(value))" />
  121. <el-button size="large" type="primary" @click="getTrainingSearch()">查找</el-button>
  122. </div>
  123. <!-- 学生数据 -->
  124. <div class="list-table">
  125. <el-table :data="trainingData" style="width: 100%">
  126. <el-table-column align="center" label="序号" max-width="120" type="index" />
  127. <el-table-column prop="name" label="学生名称" align="center" />
  128. <el-table-column v-if="isFormal == 1" prop="phone" label="手机号码" align="center" />
  129. <el-table-column prop="device_name" label="训练方式" align="center" />
  130. <el-table-column prop="create_time" label="训练时间" align="center" />
  131. <el-table-column prop="play_time" label="训练时长" align="center" />
  132. <el-table-column v-if="isFormal == 1" prop="grade_name" label="所在班级" align="center" />
  133. <el-table-column label="操作" align="center" min-width="120">
  134. <template #default="scope">
  135. <template v-if="scope.row.report_status == 1">
  136. <!-- <router-link
  137. :to="
  138. '/training/result?id=' +
  139. scope.row.game_record_id +
  140. '&type=' +
  141. scope.row.device_id +
  142. '&formal=' +
  143. isFormal
  144. "
  145. class="table-btn"
  146. >报告详情</router-link
  147. >-->
  148. <button
  149. class="table-btn"
  150. @click="
  151. pathTo(
  152. '/training/result?id=' +
  153. scope.row.game_record_id +
  154. '&type=' +
  155. scope.row.device_id +
  156. '&formal=' +
  157. isFormal
  158. )
  159. ">
  160. 报告详情
  161. </button>
  162. </template>
  163. <button v-else class="table-btn disabled" @click="alertError()">报告详情</button>
  164. </template>
  165. </el-table-column>
  166. <!-- 无数据插槽 -->
  167. <template #empty>
  168. <div class="empty">
  169. <img src="../../../assets/empty.png" alt="数据为空" />
  170. <p>{{ dataMessage }}</p>
  171. </div>
  172. </template>
  173. </el-table>
  174. </div>
  175. <pagination
  176. v-if="trainingCount > 0"
  177. v-model:total="trainingCount"
  178. v-model:page="pageParams.page"
  179. v-model:limit="pageParams.page_size"
  180. @pagination="getTrainingSearch()" />
  181. </div>
  182. </template>
  183. <style lang="scss" scoped>
  184. .training-container {
  185. position: relative;
  186. padding: 20px 30px;
  187. }
  188. .training-search {
  189. margin-bottom: 20px;
  190. font-size: 16px;
  191. .el-select {
  192. width: 200px;
  193. margin: 0 20px 0 0;
  194. }
  195. .el-input {
  196. width: 250px;
  197. margin: 0;
  198. }
  199. :deep(.el-input__inner) {
  200. font-size: 16px;
  201. }
  202. .el-button {
  203. padding: 0 26px;
  204. margin: 0 20px;
  205. font-size: 16px;
  206. background: #4284f2;
  207. border-radius: 10px;
  208. }
  209. }
  210. :deep(.el-input__wrapper) {
  211. background: #fff;
  212. border-radius: 12px;
  213. box-shadow: none !important;
  214. }
  215. :deep(.el-select) {
  216. --el-select-input-focus-border-color: none !important;
  217. }
  218. :deep(.el-select .el-input__wrapper.is-focus) {
  219. box-shadow: none !important;
  220. }
  221. :deep(.el-select:hover:not(.el-select--disabled) .el-input__wrapper) {
  222. box-shadow: none !important;
  223. }
  224. :deep(.el-table .el-table__header .el-table__cell .cell) {
  225. overflow: visible;
  226. white-space: nowrap;
  227. }
  228. :deep(.el-table th.el-table__cell) {
  229. background: #e9ebee;
  230. }
  231. .list-table {
  232. overflow: hidden;
  233. background: #fff;
  234. border-radius: 25px;
  235. .table-btn {
  236. display: inline-block;
  237. height: 38px;
  238. padding: 0 15px;
  239. line-height: 38px;
  240. color: #fff;
  241. background: #4284f2;
  242. border-radius: 10px;
  243. &.disabled {
  244. background: #bfbfbf;
  245. }
  246. }
  247. }
  248. .empty {
  249. padding: 200px 0;
  250. }
  251. </style>