examScheduling.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. <template>
  2. <el-container>
  3. <el-main v-loading="loading">
  4. <commonFormVue :form="form" :getExamCondition="getExamCondition">
  5. <el-row v-show="showAllCondition">
  6. <el-col :span="6">
  7. <el-form-item label="完成状态">
  8. <el-select
  9. v-if="form.examType == '' || form.examType == 'ONLINE'"
  10. class="form_search_width"
  11. size="small"
  12. v-model="form.finished"
  13. clearable
  14. placeholder="全部"
  15. >
  16. <el-option value="1" label="已完成"></el-option>
  17. <el-option value="0" label="未完成"></el-option>
  18. </el-select>
  19. <el-select
  20. v-if="form.examType == 'OFFLINE'"
  21. class="form_search_width"
  22. size="small"
  23. v-model="form.finished"
  24. clearable
  25. placeholder="全部"
  26. >
  27. <el-option value="0" label="未抽题"></el-option>
  28. <el-option value="1" label="已抽题"></el-option>
  29. <el-option value="2" label="已上传"></el-option>
  30. </el-select>
  31. </el-form-item>
  32. </el-col>
  33. <el-col :span="6">
  34. <el-form-item label="采集人">
  35. <el-input
  36. class="form_search_width"
  37. size="small"
  38. v-model="form.infoCollector"
  39. placeholder="采集人"
  40. >
  41. </el-input>
  42. </el-form-item>
  43. </el-col>
  44. </el-row>
  45. </commonFormVue>
  46. <el-col :span="24">
  47. <el-button
  48. @click="search"
  49. size="small"
  50. type="primary"
  51. icon="el-icon-search"
  52. >查询
  53. </el-button>
  54. <el-button
  55. size="small"
  56. type="primary"
  57. icon="el-icon-more"
  58. v-if="!showAllCondition"
  59. @click="showMoreCondition"
  60. >
  61. 高级查询
  62. </el-button>
  63. <el-button
  64. size="small"
  65. type="primary"
  66. v-if="showAllCondition"
  67. @click="showSimpleCondition"
  68. >
  69. 简单查询
  70. </el-button>
  71. <el-button
  72. size="small"
  73. icon="el-icon-refresh"
  74. @click="resetForm"
  75. class="margin-bottom-10"
  76. >重置</el-button
  77. >
  78. </el-col>
  79. <el-row>
  80. <el-col
  81. :span="24"
  82. v-show="currentPagePrivileges.EXAM_PARTICULARS_EXPORT"
  83. >
  84. <div class="block-seperator"></div>
  85. <span>批量操作:</span>
  86. <commonExportVue
  87. :form="form"
  88. :exportUrl="exportUrl"
  89. :exportFileName="exportFileName"
  90. ></commonExportVue>
  91. </el-col>
  92. </el-row>
  93. <el-row class="margin-top-10">
  94. <el-col :span="24">
  95. <el-table
  96. v-loading="tableLoading"
  97. element-loading-text="数据加载中"
  98. ref="multipleTable"
  99. @selection-change="handleSelectionChange"
  100. :data="tableData"
  101. border
  102. >
  103. <el-table-column sortable label="学习中心" prop="orgName">
  104. </el-table-column>
  105. <el-table-column sortable label="姓名" prop="studentName">
  106. </el-table-column>
  107. <el-table-column sortable label="身份证号" prop="identityNumber">
  108. </el-table-column>
  109. <el-table-column sortable label="学号" prop="studentCode">
  110. </el-table-column>
  111. <el-table-column sortable label="课程" prop="courseName">
  112. </el-table-column>
  113. <el-table-column sortable label="课程层次" prop="courseLevel">
  114. </el-table-column>
  115. <el-table-column sortable label="专业" prop="specialtyName">
  116. </el-table-column>
  117. <el-table-column sortable label="已考次数" prop="normalExamTimes">
  118. </el-table-column>
  119. <el-table-column sortable label="学生电话" prop="phone">
  120. </el-table-column>
  121. <el-table-column sortable label="年级" prop="grade">
  122. </el-table-column>
  123. <el-table-column sortable label="采集人" prop="infoCollector">
  124. </el-table-column>
  125. <el-table-column sortable label="采集人1" prop="canUpload">
  126. </el-table-column>
  127. <el-table-column fixed="right" sortable label="完成状态">
  128. <template slot-scope="scope">
  129. <span>
  130. <el-tag> {{ scope.row.finishedStatus }} </el-tag>
  131. </span>
  132. </template>
  133. </el-table-column>
  134. <el-table-column fixed="right" label="操作" width="120">
  135. <template slot-scope="scope">
  136. <el-row class="operateRow">
  137. <el-col :span="24">
  138. <el-button
  139. plain
  140. type="primary"
  141. size="mini"
  142. icon="el-icon-view"
  143. @click="previewPaper(scope.row.examStudentId)"
  144. v-if="scope.row.examType == 'OFFLINE'"
  145. >查看考题
  146. </el-button>
  147. </el-col>
  148. </el-row>
  149. <el-row class="operateRow">
  150. <el-col :span="24">
  151. <el-button
  152. plain
  153. type="primary"
  154. size="mini"
  155. icon="el-icon-download"
  156. @click="exportPaper(scope.row.examStudentId)"
  157. v-if="scope.row.examType == 'OFFLINE'"
  158. >下载考题
  159. </el-button>
  160. </el-col>
  161. </el-row>
  162. <el-row class="operateRow">
  163. <el-col :span="24">
  164. <el-button
  165. plain
  166. type="primary"
  167. size="mini"
  168. icon="el-icon-upload2"
  169. @click="openUploadAnswerDialog(scope.row.examStudentId)"
  170. v-if="
  171. scope.row.examType == 'OFFLINE' &&
  172. scope.row.canUploadAttachment
  173. "
  174. >上传作答
  175. </el-button>
  176. </el-col>
  177. </el-row>
  178. </template>
  179. </el-table-column>
  180. </el-table>
  181. <div class="page pull-right">
  182. <el-pagination
  183. @size-change="handleSizeChange"
  184. @current-change="handleCurrentChange"
  185. :current-page.sync="form.pageNo"
  186. :page-sizes="[10, 20, 50, 100]"
  187. :page-size="form.pageSize"
  188. layout="total, sizes, prev, pager, next, jumper"
  189. :total="total"
  190. >
  191. </el-pagination></div></el-col
  192. ></el-row>
  193. <div>
  194. <el-dialog
  195. title="上传作答"
  196. v-loading="uploadAnswerDialogLoading"
  197. :visible.sync="uploadAnswerDialogVisible"
  198. @closed="cleanOfflineFile"
  199. >
  200. <el-form>
  201. <el-form-item label="选择文件"
  202. ><input
  203. type="file"
  204. accept="application/pdf,application/zip"
  205. id="importFile"
  206. ref="offlineFileInput"
  207. @change="uploadAnswerChange"
  208. v-bind:class="{ offline_file: offlineAnswerFile }"
  209. />
  210. <div>温馨提示:仅支持pdf和zip文件,文件大小请不要超过30M!</div>
  211. </el-form-item>
  212. <div class="dialog-footer">
  213. <el-button @click="uploadAnswerDialogVisible = false"
  214. >取 消</el-button
  215. >
  216. <el-button
  217. :disabled="!offlineAnswerFile"
  218. type="primary"
  219. @click="doUploadAnswer"
  220. >确 定</el-button
  221. >
  222. </div>
  223. </el-form>
  224. </el-dialog>
  225. </div>
  226. </el-main>
  227. </el-container>
  228. </template>
  229. <script>
  230. import { mapState } from "vuex";
  231. import commonFormVue from "../component/commonForm.vue";
  232. import commonExportVue from "../component/commonExport.vue";
  233. import pagePrivilege from "../mixin/pagePrivilege.js";
  234. export default {
  235. components: { commonFormVue, commonExportVue },
  236. mixins: [pagePrivilege],
  237. data() {
  238. return {
  239. loading: false,
  240. uploadAnswerDialogLoading: false,
  241. uploadAnswerDialogVisible: false,
  242. total: 0,
  243. tableLoading: false,
  244. showAllCondition: false,
  245. form: {
  246. examRecordDataId: null,
  247. hasStranger: null,
  248. courseId: null,
  249. courseLevel: null,
  250. examId: null,
  251. examRecordId: null,
  252. faceSuccessPercentLower: null,
  253. faceSuccessPercentUpper: null,
  254. livenessSuccessPercentLower: null,
  255. livenessSuccessPercentUpper: null,
  256. identityNumber: null,
  257. orgId: null,
  258. studentCode: null,
  259. studentName: null,
  260. isWarn: null,
  261. pageNo: 1,
  262. pageSize: 10,
  263. examType: ""
  264. },
  265. getExamCondition: {
  266. params: {
  267. name: "",
  268. examTypes: "ONLINE#OFFLINE"
  269. },
  270. filterCondition: ""
  271. },
  272. tableData: [],
  273. exportUrl: "/api/ecs_oe_admin/exam/student/examScheduling/list/export",
  274. exportFileName: "考试进度详情",
  275. currentOfflineExamRecordDataId: "",
  276. offlineAnswerFile: "",
  277. currentPagePrivileges: {
  278. EXAM_PARTICULARS_EXPORT: false //导出
  279. }
  280. };
  281. },
  282. computed: {
  283. ...mapState({ user: state => state.user })
  284. },
  285. methods: {
  286. resetForm() {
  287. this.form = {
  288. examRecordDataId: null,
  289. hasStranger: null,
  290. courseId: null,
  291. courseLevel: null,
  292. examId: null,
  293. examRecordId: null,
  294. faceSuccessPercentLower: null,
  295. faceSuccessPercentUpper: null,
  296. livenessSuccessPercentLower: null,
  297. livenessSuccessPercentUpper: null,
  298. identityNumber: null,
  299. orgId: null,
  300. studentCode: null,
  301. studentName: null,
  302. isWarn: null,
  303. pageNo: 1,
  304. pageSize: 10,
  305. examType: ""
  306. };
  307. },
  308. showMoreCondition() {
  309. this.showAllCondition = true;
  310. },
  311. showSimpleCondition() {
  312. this.$notify({
  313. title: "提示",
  314. message: "高级查询条件值已重置",
  315. type: "info",
  316. duration: 2000
  317. });
  318. this.resetForm();
  319. this.showAllCondition = false;
  320. },
  321. search() {
  322. if (!this.form.examId) {
  323. this.$notify({
  324. title: "警告",
  325. message: "请选择考试批次",
  326. type: "warning",
  327. duration: 2000
  328. });
  329. return false;
  330. }
  331. this.tableLoading = true;
  332. this.$http
  333. .post("/api/ecs_oe_admin/exam/student/examScheduling/list", this.form)
  334. .then(response => {
  335. if (response.data) {
  336. var dataList = response.data.content;
  337. this.tableData = dataList;
  338. this.total = response.data.totalElements;
  339. } else {
  340. this.tableData = [];
  341. }
  342. this.tableLoading = false;
  343. });
  344. },
  345. selectable(row) {
  346. return row.isWarn;
  347. },
  348. handleSelectionChange(val) {
  349. this.multipleSelection = val;
  350. },
  351. /**
  352. * pagesize改变时触发
  353. */
  354. handleSizeChange(val) {
  355. this.form.pageSize = val;
  356. this.search();
  357. },
  358. /**
  359. * 当前页改变时触发
  360. */
  361. handleCurrentChange() {
  362. this.search();
  363. },
  364. previewPaper(examStudentId) {
  365. this.$http
  366. .get("/api/ecs_oe_admin/exam/record/select/byExamStudentId", {
  367. params: { examStudentId: examStudentId }
  368. })
  369. .then(response => {
  370. if (response.data) {
  371. var examRecordList = response.data;
  372. if (examRecordList && examRecordList.length > 0) {
  373. window.open(
  374. "/admin/preview_paper/" + examRecordList[0].basePaperId
  375. );
  376. } else {
  377. this.$notify({
  378. title: "提示",
  379. message: "该考生未参加考试",
  380. type: "error",
  381. duration: 2000
  382. });
  383. }
  384. }
  385. });
  386. },
  387. exportPaper(examStudentId) {
  388. this.loading = true;
  389. var currentUser = this.user;
  390. this.$http
  391. .get("/api/ecs_oe_admin/exam/record/select/byExamStudentId", {
  392. params: { examStudentId: examStudentId }
  393. })
  394. .then(response => {
  395. if (response.data) {
  396. var examRecordList = response.data;
  397. if (examRecordList && examRecordList.length > 0) {
  398. var basePaperId = examRecordList[0].basePaperId;
  399. var rootOrgName = currentUser.rootOrgName;
  400. this.$http
  401. .get(
  402. "/api/ecs_ques/paper/export/" +
  403. basePaperId +
  404. "/PAPER/" +
  405. rootOrgName +
  406. "/" +
  407. basePaperId +
  408. "/offLine",
  409. {
  410. responseType: "arraybuffer",
  411. filename: "utf-8"
  412. }
  413. )
  414. .then(response => {
  415. if (response.data) {
  416. var blob = new Blob([response.data], {
  417. type: "application/zip"
  418. });
  419. var url = URL.createObjectURL(blob);
  420. var fileName = response.headers["content-disposition"]
  421. .split(";")[1]
  422. .replace("filename=", "");
  423. var a = document.createElement("a");
  424. a.href = url;
  425. a.download = decodeURI(fileName);
  426. a.target = "_blank";
  427. a.click();
  428. URL.revokeObjectURL(url);
  429. }
  430. this.loading = false;
  431. })
  432. .catch(() => {
  433. this.loading = false;
  434. });
  435. } else {
  436. this.loading = false;
  437. this.$notify({
  438. title: "提示",
  439. message: "该考生未参加考试",
  440. type: "error",
  441. duration: 2000
  442. });
  443. }
  444. }
  445. });
  446. },
  447. openUploadAnswerDialog(examStudentId) {
  448. this.$http
  449. .get("/api/ecs_oe_admin/exam/record/data/findByExamStudentId", {
  450. params: { examStudentId: examStudentId }
  451. })
  452. .then(response => {
  453. var examRecordDataList = response.data;
  454. if (examRecordDataList.length == 0) {
  455. this.$notify({
  456. title: "提示",
  457. message: "该考生未参加考试",
  458. type: "error",
  459. duration: 2000
  460. });
  461. } else {
  462. this.uploadAnswerDialogVisible = true;
  463. this.currentOfflineExamStudentId = examStudentId;
  464. this.currentOfflineExamRecordDataId = examRecordDataList[0].id;
  465. }
  466. });
  467. },
  468. uploadAnswerChange(event) {
  469. if (event.target.files.length > 0) {
  470. this.offlineAnswerFile = event.target.files[0];
  471. } else {
  472. this.offlineAnswerFile = "";
  473. }
  474. },
  475. doUploadAnswer() {
  476. this.uploadAnswerDialogLoading = true;
  477. let config = {
  478. headers: { "Content-Type": "multipart/form-data" }
  479. };
  480. let param = new FormData();
  481. param.append("file", this.offlineAnswerFile);
  482. param.append("examRecordDataId", this.currentOfflineExamRecordDataId);
  483. this.$http
  484. .post("/api/ecs_oe_student/offlineExam/submitPaper", param, config)
  485. .then(() => {
  486. this.$notify({
  487. title: "提示",
  488. message: "上传成功",
  489. type: "success",
  490. duration: 2000
  491. });
  492. this.uploadAnswerDialogVisible = false;
  493. this.uploadAnswerDialogLoading = false;
  494. this.$refs.offlineFileInput.value = "";
  495. this.offlineAnswerFile = "";
  496. })
  497. .catch(() => {
  498. this.$notify({
  499. title: "提示",
  500. message: "上传失败",
  501. type: "error",
  502. duration: 2000
  503. });
  504. this.uploadAnswerDialogLoading = false;
  505. this.$refs.offlineFileInput.value = "";
  506. this.offlineAnswerFile = "";
  507. });
  508. },
  509. cleanOfflineFile() {
  510. this.$refs.offlineFileInput.value = "";
  511. this.offlineAnswerFile = "";
  512. }
  513. },
  514. created() {}
  515. };
  516. </script>
  517. <style scoped>
  518. .el-row {
  519. position: static !important;
  520. }
  521. .operateRow {
  522. margin-top: 2px;
  523. }
  524. .select-type {
  525. font-size: 8px;
  526. cursor: pointer;
  527. color: #409eff;
  528. }
  529. .offline_file {
  530. color: blue;
  531. }
  532. </style>
  533. <style scoped src="../style/common.css"></style>