ExamStudentManage.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. <template>
  2. <div class="student-manage">
  3. <div class="part-box part-box-filter">
  4. <el-form ref="FilterForm" label-position="left" label-width="90px" inline>
  5. <secp-select
  6. v-model="filterSe"
  7. defaultSelectExam
  8. @exam-default="search"
  9. ></secp-select>
  10. <el-form-item label="课程(代码):">
  11. <course-common-select
  12. v-model="filter.courseId"
  13. placeholder="课程(代码)"
  14. clearable
  15. ></course-common-select>
  16. </el-form-item>
  17. <el-form-item label="任课老师:">
  18. <el-input
  19. v-model.trim="filter.teacher"
  20. placeholder="任课老师"
  21. clearable
  22. ></el-input>
  23. </el-form-item>
  24. <el-form-item label="学院:">
  25. <el-input
  26. v-model.trim="filter.college"
  27. placeholder="学院"
  28. clearable
  29. ></el-input>
  30. </el-form-item>
  31. <el-form-item label="专业:">
  32. <el-input
  33. v-model.trim="filter.major"
  34. placeholder="专业"
  35. clearable
  36. ></el-input>
  37. </el-form-item>
  38. <el-form-item label="班级:">
  39. <el-input
  40. v-model.trim="filter.teachClazz"
  41. placeholder="班级"
  42. clearable
  43. ></el-input>
  44. </el-form-item>
  45. <el-form-item label="姓名/学号:">
  46. <el-input
  47. v-model.trim="filter.examStudentInfo"
  48. placeholder="姓名/学号"
  49. clearable
  50. ></el-input>
  51. </el-form-item>
  52. <el-form-item>
  53. <el-button
  54. v-if="checkPrivilege('button', 'select')"
  55. type="primary"
  56. @click="toPage(1)"
  57. >查询</el-button
  58. >
  59. </el-form-item>
  60. </el-form>
  61. <div class="box-justify">
  62. <div>
  63. <el-button
  64. v-if="checkPrivilege('button', 'DeleteBatch')"
  65. type="danger"
  66. icon="el-icon-delete"
  67. @click="toBatchDelete"
  68. >批量删除</el-button
  69. >
  70. <el-button
  71. v-if="checkPrivilege('button', 'export')"
  72. type="primary"
  73. icon="el-icon-download"
  74. :loading="loading"
  75. @click="toExportStudent"
  76. >导出</el-button
  77. >
  78. </div>
  79. <div>
  80. <el-button
  81. v-if="checkPrivilege('button', 'ImportTeacher')"
  82. type="success"
  83. icon="el-icon-upload2"
  84. @click="toImportTeacher"
  85. >导入任课老师</el-button
  86. >
  87. <el-button
  88. v-if="checkPrivilege('button', 'import')"
  89. type="success"
  90. icon="el-icon-upload2"
  91. @click="toImport"
  92. >导入</el-button
  93. >
  94. <template
  95. v-if="
  96. checkPrivilege('button', 'import') ||
  97. checkPrivilege('button', 'ImportTeacher')
  98. "
  99. >
  100. <el-button
  101. v-if="taskTypes.length === 1"
  102. type="primary"
  103. icon="el-icon-s-order"
  104. @click="toDataTask"
  105. >
  106. 导入结果查询
  107. </el-button>
  108. <el-dropdown v-if="taskTypes.length > 1" @command="handleTaskType">
  109. <el-button
  110. type="primary"
  111. icon="el-icon-s-order"
  112. style="margin: 0 10px"
  113. >
  114. 导入结果查询 <i class="el-icon-arrow-down el-icon--right"></i>
  115. </el-button>
  116. <el-dropdown-menu slot="dropdown">
  117. <el-dropdown-item command="BASIC_EXAM_STUDENT_IMPORT"
  118. >考生导入</el-dropdown-item
  119. >
  120. <el-dropdown-item command="BASIC_EXAM_STUDENT_TEACHER_IMPORT"
  121. >任课老师导入</el-dropdown-item
  122. >
  123. </el-dropdown-menu>
  124. </el-dropdown>
  125. </template>
  126. <el-button
  127. v-if="checkPrivilege('button', 'add')"
  128. type="primary"
  129. icon="el-icon-circle-plus-outline"
  130. @click="toAdd"
  131. >新增</el-button
  132. >
  133. </div>
  134. </div>
  135. </div>
  136. <div class="part-box part-box-pad">
  137. <el-table
  138. ref="TableList"
  139. :data="dataList"
  140. @selection-change="handleSelectionChange"
  141. >
  142. <el-table-column
  143. type="selection"
  144. fixed="left"
  145. width="55"
  146. align="center"
  147. ></el-table-column>
  148. <el-table-column
  149. prop="studentName"
  150. label="姓名"
  151. min-width="100"
  152. ></el-table-column>
  153. <el-table-column
  154. prop="studentCode"
  155. label="学号"
  156. width="140"
  157. ></el-table-column>
  158. <el-table-column
  159. prop="courseName"
  160. label="课程名称"
  161. min-width="300"
  162. ></el-table-column>
  163. <el-table-column
  164. prop="courseCode"
  165. label="课程代码"
  166. width="120"
  167. ></el-table-column>
  168. <el-table-column
  169. prop="teachingRoomName"
  170. label="开课学院"
  171. min-width="180"
  172. ></el-table-column>
  173. <el-table-column
  174. prop="paperNumber"
  175. label="试卷编号"
  176. width="120"
  177. ></el-table-column>
  178. <el-table-column
  179. prop="paperType"
  180. label="卷型"
  181. width="80"
  182. ></el-table-column>
  183. <el-table-column prop="status" label="状态" width="100">
  184. <template slot-scope="scope">
  185. {{ scope.row.status | studentStatusFilter }}
  186. </template>
  187. </el-table-column>
  188. <el-table-column
  189. prop="teacherName"
  190. label="任课老师"
  191. min-width="100"
  192. ></el-table-column>
  193. <el-table-column
  194. prop="teacherCode"
  195. label="任课老师工号"
  196. width="120"
  197. ></el-table-column>
  198. <el-table-column
  199. prop="collegeName"
  200. label="学院"
  201. min-width="180"
  202. ></el-table-column>
  203. <el-table-column
  204. prop="majorName"
  205. label="专业"
  206. min-width="180"
  207. ></el-table-column>
  208. <el-table-column
  209. prop="teachClassName"
  210. label="教学班"
  211. min-width="180"
  212. ></el-table-column>
  213. <el-table-column
  214. prop="className"
  215. label="行政班"
  216. min-width="180"
  217. ></el-table-column>
  218. <el-table-column
  219. prop="examDate"
  220. label="考试日期"
  221. width="100"
  222. ></el-table-column>
  223. <el-table-column
  224. prop="examTime"
  225. label="考试时间"
  226. width="160"
  227. ></el-table-column>
  228. <el-table-column
  229. prop="examPlace"
  230. label="考点(校区)"
  231. min-width="120"
  232. ></el-table-column>
  233. <el-table-column
  234. prop="examRoom"
  235. label="考场(考试教室)"
  236. width="140"
  237. ></el-table-column>
  238. <el-table-column
  239. class-name="action-column"
  240. label="操作"
  241. width="140"
  242. fixed="right"
  243. >
  244. <template slot-scope="scope">
  245. <el-button
  246. v-if="checkPrivilege('link', 'edit')"
  247. class="btn-primary"
  248. type="text"
  249. @click="toSet(scope.row)"
  250. >设置</el-button
  251. >
  252. <el-button
  253. v-if="checkPrivilege('link', 'edit')"
  254. class="btn-primary"
  255. type="text"
  256. @click="toEdit(scope.row)"
  257. >编辑</el-button
  258. >
  259. <el-button
  260. v-if="checkPrivilege('link', 'delete')"
  261. class="btn-danger"
  262. type="text"
  263. @click="toDelete(scope.row)"
  264. >删除</el-button
  265. >
  266. </template>
  267. </el-table-column>
  268. </el-table>
  269. <div class="part-page">
  270. <el-pagination
  271. background
  272. layout="total, sizes, prev, pager, next, jumper"
  273. :pager-count="5"
  274. :current-page="current"
  275. :total="total"
  276. :page-size="size"
  277. @current-change="toPage"
  278. @size-change="pageSizeChange"
  279. >
  280. </el-pagination>
  281. </div>
  282. </div>
  283. <modify-exam-student
  284. :instance="curRow"
  285. @modified="getList"
  286. ref="ModifyExamStudent"
  287. ></modify-exam-student>
  288. <!-- ModifyExamStudentStatus -->
  289. <modify-exam-student-status
  290. ref="ModifyExamStudentStatus"
  291. :instance="curRow"
  292. @modified="getList"
  293. ></modify-exam-student-status>
  294. <!-- ImportFile -->
  295. <import-file
  296. v-if="checkPrivilege('button', 'import')"
  297. ref="ImportFile"
  298. title="导入考生"
  299. :upload-url="uploadUrl"
  300. :upload-data="{
  301. examId: filterSe.examId,
  302. semesterId: filterSe.semesterId,
  303. }"
  304. :format="['xls', 'xlsx']"
  305. :download-handle="() => downloadHandle(dfilename)"
  306. :download-filename="dfilename"
  307. :auto-upload="false"
  308. @upload-success="uploadSuccess"
  309. ></import-file>
  310. <!-- ImportFileTeacher -->
  311. <import-file
  312. v-if="checkPrivilege('button', 'ImportTeacher')"
  313. ref="ImportFileTeacher"
  314. title="导入任课老师"
  315. :upload-url="uploadTeacherUrl"
  316. :upload-data="{
  317. examId: filterSe.examId,
  318. semesterId: filterSe.semesterId,
  319. }"
  320. :format="['xls', 'xlsx']"
  321. :download-handle="() => downloadHandle(teacherDfilename)"
  322. :download-filename="teacherDfilename"
  323. :auto-upload="false"
  324. @upload-success="uploadSuccess"
  325. ></import-file>
  326. <!-- data-task-dialog -->
  327. <data-task-dialog
  328. v-if="
  329. checkPrivilege('button', 'import') ||
  330. checkPrivilege('button', 'ImportTeacher')
  331. "
  332. ref="DataTaskDialog"
  333. :task-type="curTaskType"
  334. ></data-task-dialog>
  335. </div>
  336. </template>
  337. <script>
  338. import {
  339. examStudentListPage,
  340. deleteExamStudent,
  341. exportExamStudent,
  342. } from "../api";
  343. import { businessTemplateDownload } from "@/modules/print/api";
  344. import ModifyExamStudent from "../components/ModifyExamStudent.vue";
  345. import ModifyExamStudentStatus from "../components/ModifyExamStudentStatus.vue";
  346. import ImportFile from "../../../components/ImportFile.vue";
  347. import { downloadByApi } from "@/plugins/download";
  348. import templateDownload from "@/mixins/templateDownload";
  349. import { getExamDateTime } from "@/plugins/utils";
  350. export default {
  351. name: "exam-student-manage",
  352. components: { ModifyExamStudent, ModifyExamStudentStatus, ImportFile },
  353. mixins: [templateDownload],
  354. data() {
  355. return {
  356. filterSe: {
  357. semesterId: "",
  358. examId: "",
  359. },
  360. filter: {
  361. courseId: "",
  362. teacher: "",
  363. college: "",
  364. major: "",
  365. teachClazz: "",
  366. examStudentInfo: "",
  367. },
  368. current: 1,
  369. size: this.GLOBAL.pageSize,
  370. total: 0,
  371. dataList: [],
  372. multipleSelection: [],
  373. curRow: {},
  374. loading: false,
  375. download: false,
  376. curTaskType: "BASIC_EXAM_STUDENT_IMPORT",
  377. taskTypes: [],
  378. // import
  379. uploadUrl: "/api/admin/basic/exam_student/import",
  380. dfilename: "考生导入模板.xlsx",
  381. // import teacher
  382. uploadTeacherUrl: "/api/admin/basic/exam_student/import_teacher",
  383. teacherDfilename: "任课老师导入模板.xlsx",
  384. };
  385. },
  386. mounted() {
  387. const taskTypes = [];
  388. if (this.checkPrivilege("button", "import")) {
  389. taskTypes.push("BASIC_EXAM_STUDENT_IMPORT");
  390. }
  391. if (this.checkPrivilege("button", "ImportTeacher")) {
  392. taskTypes.push("BASIC_EXAM_STUDENT_TEACHER_IMPORT");
  393. }
  394. if (taskTypes.length === 1) this.curTaskType = taskTypes[0];
  395. this.taskTypes = taskTypes;
  396. },
  397. methods: {
  398. async getList() {
  399. if (!this.checkPrivilege("list", "list")) return;
  400. const datas = {
  401. ...this.filterSe,
  402. ...this.filter,
  403. pageNumber: this.current,
  404. pageSize: this.size,
  405. };
  406. const data = await examStudentListPage(datas);
  407. this.dataList = data.records.map((item) => {
  408. const { examDate, examTime } = getExamDateTime(
  409. item.examStartTime,
  410. item.examEndTime
  411. );
  412. item.examDate = examDate;
  413. item.examTime = examTime;
  414. return item;
  415. });
  416. this.total = data.total;
  417. },
  418. toPage(page) {
  419. this.current = page;
  420. this.getList();
  421. },
  422. search() {
  423. this.toPage(1);
  424. },
  425. handleSelectionChange(val) {
  426. this.multipleSelection = val.map((item) => item.id);
  427. },
  428. async downloadHandle(filename) {
  429. if (this.download) return;
  430. this.download = true;
  431. const res = await downloadByApi(() => {
  432. return businessTemplateDownload();
  433. }, filename).catch((e) => {
  434. this.$message.error(e || "下载失败,请重新尝试!");
  435. });
  436. this.download = false;
  437. if (!res) return;
  438. this.$message.success("下载成功!");
  439. },
  440. toAdd() {
  441. this.curRow = {};
  442. this.$refs.ModifyExamStudent.open();
  443. },
  444. toEdit(row) {
  445. this.curRow = row;
  446. this.$refs.ModifyExamStudent.open();
  447. },
  448. toSet(row) {
  449. this.curRow = row;
  450. this.$refs.ModifyExamStudentStatus.open();
  451. },
  452. async toBatchDelete() {
  453. if (!this.multipleSelection.length) {
  454. this.$message.error("请选择要删除的考生");
  455. return;
  456. }
  457. const confirm = await this.$confirm(
  458. `确定要删除当前选择的所有考生吗?`,
  459. "提示",
  460. {
  461. type: "warning",
  462. }
  463. ).catch(() => {});
  464. if (confirm !== "confirm") return;
  465. await deleteExamStudent(this.multipleSelection);
  466. this.$message.success("删除成功!");
  467. this.deletePageLastItem();
  468. },
  469. toDelete(row) {
  470. this.$confirm(`确定要删除考生【${row.studentName}】吗?`, "提示", {
  471. type: "warning",
  472. })
  473. .then(async () => {
  474. await deleteExamStudent([row.id]);
  475. this.$message.success("删除成功!");
  476. this.deletePageLastItem();
  477. })
  478. .catch(() => {});
  479. },
  480. async toExportStudent() {
  481. if (this.loading) return;
  482. this.loading = true;
  483. const res = await downloadByApi(() => {
  484. return exportExamStudent({ ...this.filterSe, ...this.filter });
  485. }, "").catch((e) => {
  486. this.$message.error(e || "下载失败,请重新尝试!");
  487. });
  488. this.loading = false;
  489. if (!res) return;
  490. this.$message.success("下载成功!");
  491. },
  492. // import
  493. toImport() {
  494. this.$refs.ImportFile.open();
  495. },
  496. toImportTeacher() {
  497. this.$refs.ImportFileTeacher.open();
  498. },
  499. toDataTask() {
  500. this.$refs.DataTaskDialog.open();
  501. },
  502. handleTaskType(val) {
  503. this.curTaskType = val;
  504. this.$refs.DataTaskDialog.open();
  505. },
  506. validError(errorData) {
  507. this.$message.error(errorData.message);
  508. },
  509. uploadSuccess() {
  510. this.$message.success("文件上传成功,后台正在导入!");
  511. this.getList();
  512. },
  513. },
  514. };
  515. </script>