|
@@ -0,0 +1,326 @@
|
|
|
|
+<template>
|
|
|
|
+ <div class="group-scan">
|
|
|
|
+ <div class="home-header">
|
|
|
|
+ <div class="head-logo">
|
|
|
|
+ <h1>试卷采集</h1>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="head-back">
|
|
|
|
+ <i-button type="default" @click="goBack"
|
|
|
|
+ ><i class="icon-font icon-left"></i>返回</i-button
|
|
|
|
+ >
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="home-body">
|
|
|
|
+ <div class="home-main home-main-split">
|
|
|
|
+ <div
|
|
|
|
+ class="scan-list student-list"
|
|
|
|
+ id="student-list"
|
|
|
|
+ v-if="studentSerialList.length"
|
|
|
|
+ >
|
|
|
|
+ <div
|
|
|
|
+ v-for="(student, index) in studentSerialList"
|
|
|
|
+ :key="index"
|
|
|
|
+ :class="[
|
|
|
|
+ 'student-item',
|
|
|
|
+ {
|
|
|
|
+ 'student-current': student.isCurrent,
|
|
|
|
+ 'student-over': student.isClient
|
|
|
|
+ }
|
|
|
|
+ ]"
|
|
|
|
+ >
|
|
|
|
+ <span>{{ student.name }}</span>
|
|
|
|
+ <span>{{ student.examNumber }}</span>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="scan-btns">
|
|
|
|
+ <i-button type="primary" @click="scanOver" :disabled="holding"
|
|
|
|
+ >扫描完毕</i-button
|
|
|
|
+ >
|
|
|
|
+ <i-button type="primary" @click="allReScan">整包重扫</i-button>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="scan-image">
|
|
|
|
+ <div class="scan-main scan-waiting" v-if="isWaiting">
|
|
|
|
+ <p class="scan-waiting-icon"></p>
|
|
|
|
+ <p class="scan-waiting-tips">等待采集试卷</p>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="scan-main scan-picture" v-else>
|
|
|
|
+ <img class="img-contain" :src="curImage.url" :alt="curImage.name" />
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <!-- reset current image scan area dialog -->
|
|
|
|
+ <scan-area-dialog
|
|
|
|
+ :cur-image="curImage"
|
|
|
|
+ :cur-collect-config="curCollectConfig"
|
|
|
|
+ @confirm="studentConfigChange"
|
|
|
|
+ ref="ScanAreaDialog"
|
|
|
|
+ ></scan-area-dialog>
|
|
|
|
+ <!-- scan exception dialog -->
|
|
|
|
+ <scan-exception-dialog
|
|
|
|
+ :cur-image="curImage"
|
|
|
|
+ :cur-exception="curException"
|
|
|
|
+ @on-reset="resetConfig"
|
|
|
|
+ @on-rescan="restartInitFile"
|
|
|
|
+ @on-hand-input="examNumberValid"
|
|
|
|
+ ref="ScanExceptionDialog"
|
|
|
|
+ ></scan-exception-dialog>
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script>
|
|
|
|
+const fs = require("fs");
|
|
|
|
+import { getStudentGroupByExamNumber } from "../api";
|
|
|
|
+import {
|
|
|
|
+ decodeImageCode,
|
|
|
|
+ getEarliestFile,
|
|
|
|
+ saveFormalImage
|
|
|
|
+} from "../../../plugins/imageOcr";
|
|
|
|
+import { formatDate } from "../../../plugins/utils";
|
|
|
|
+import ScanAreaDialog from "../components/ScanAreaDialog";
|
|
|
|
+import ScanExceptionDialog from "../components/ScanExceptionDialog";
|
|
|
|
+
|
|
|
|
+export default {
|
|
|
|
+ name: "group-scan",
|
|
|
|
+ components: { ScanAreaDialog, ScanExceptionDialog },
|
|
|
|
+ data() {
|
|
|
|
+ return {
|
|
|
|
+ isWaiting: true,
|
|
|
|
+ students: [],
|
|
|
|
+ curStudent: {},
|
|
|
|
+ curCollectConfig: {},
|
|
|
|
+ curException: {
|
|
|
|
+ showAction: true,
|
|
|
|
+ message: ""
|
|
|
|
+ },
|
|
|
|
+ setT: "",
|
|
|
|
+ holding: false,
|
|
|
|
+ curImage: {
|
|
|
|
+ url: "",
|
|
|
|
+ name: ""
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ },
|
|
|
|
+ computed: {
|
|
|
|
+ user() {
|
|
|
|
+ return this.$store.state.user;
|
|
|
|
+ },
|
|
|
|
+ curSubject() {
|
|
|
|
+ return this.$store.state.curSubject;
|
|
|
|
+ },
|
|
|
|
+ studentSerialList() {
|
|
|
|
+ return this.students.sort((a, b) => {
|
|
|
|
+ if (a.isClient) return -1;
|
|
|
|
+ if (b.isClient) return 1;
|
|
|
|
+ if (a.isCurrent) return -1;
|
|
|
|
+ if (b.isCurrent) return 1;
|
|
|
|
+ return 0;
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ scanNo() {
|
|
|
|
+ return this.students.filter(item => item.isClient).length;
|
|
|
|
+ },
|
|
|
|
+ taskNo() {
|
|
|
|
+ return this.students.length;
|
|
|
|
+ },
|
|
|
|
+ isFinished() {
|
|
|
|
+ return this.taskNo && this.scanNo === this.taskNo;
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ mounted() {
|
|
|
|
+ this.getInitFile();
|
|
|
|
+ // this.curImage = {
|
|
|
|
+ // name: "1901130043.jpg",
|
|
|
|
+ // url: "E:\\newspace\\msyj-client\\in\\1901130043.jpg"
|
|
|
|
+ // };
|
|
|
|
+ },
|
|
|
|
+ methods: {
|
|
|
|
+ getInitFile() {
|
|
|
|
+ if (this.isFinished) {
|
|
|
|
+ this.isWaiting = true;
|
|
|
|
+ if (this.setT) clearTimeout(this.setT);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ this.curImage = getEarliestFile();
|
|
|
|
+
|
|
|
|
+ if (this.curImage.url) {
|
|
|
|
+ if (this.setT) clearTimeout(this.setT);
|
|
|
|
+ this.isWaiting = false;
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
+ this.startDecodeTask(this.curSubject.collectConfig.codeArea);
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ this.setT = setTimeout(() => {
|
|
|
|
+ this.getInitFile();
|
|
|
|
+ }, 1000);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ restartInitFile() {
|
|
|
|
+ this.isWaiting = true;
|
|
|
|
+ this.curStudent = {};
|
|
|
|
+ if (this.setT) clearTimeout(this.setT);
|
|
|
|
+ this.holding = false;
|
|
|
|
+ this.curImage = { url: "", name: "" };
|
|
|
|
+
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
+ this.getInitFile();
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ async startDecodeTask(codeArea) {
|
|
|
|
+ const examNumber = await decodeImageCode(
|
|
|
|
+ this.curImage.url,
|
|
|
|
+ codeArea
|
|
|
|
+ ).catch(error => {
|
|
|
|
+ const content = `图像:${this.curImage.name},解析错误,错误信息:${error}`;
|
|
|
|
+
|
|
|
|
+ this.$Notice.error({ title: "错误提示", desc: content, duration: 0 });
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ if (examNumber) {
|
|
|
|
+ this.examNumberValid(examNumber);
|
|
|
|
+ } else {
|
|
|
|
+ // 未解析到考号异常
|
|
|
|
+ this.curException = {
|
|
|
|
+ showAction: true,
|
|
|
|
+ message: "条形码解析错误!",
|
|
|
|
+ collectConfig: this.getCurCollectConfig()
|
|
|
|
+ };
|
|
|
|
+ this.$refs.ScanExceptionDialog.open();
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ async examNumberValid(examNumber, type = "AUTO") {
|
|
|
|
+ const validRes = await this.checkStudentValid(examNumber);
|
|
|
|
+ if (validRes.valid) {
|
|
|
|
+ // 保存扫描到的试卷
|
|
|
|
+ this.toSaveStudent(examNumber, type);
|
|
|
|
+ } else {
|
|
|
|
+ // 考号不合法异常
|
|
|
|
+ this.curException = {
|
|
|
|
+ showAction: false,
|
|
|
|
+ message: validRes.message
|
|
|
|
+ };
|
|
|
|
+ this.$refs.ScanExceptionDialog.open();
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ async checkStudentValid(examNumber) {
|
|
|
|
+ let validInfo = { valid: true, message: "" };
|
|
|
|
+ if (!this.students.length) {
|
|
|
|
+ const students = await getStudentGroupByExamNumber(examNumber);
|
|
|
|
+ if (students && students.length) {
|
|
|
|
+ this.students = students.map(item => {
|
|
|
|
+ return {
|
|
|
|
+ ...item,
|
|
|
|
+ isClient: false,
|
|
|
|
+ isCurrent: false,
|
|
|
|
+ isManual: false,
|
|
|
|
+ collectConfig: null
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ validInfo = {
|
|
|
|
+ valid: false,
|
|
|
|
+ message: "学生数据没有上传,请重新采集!"
|
|
|
|
+ };
|
|
|
|
+ return validInfo;
|
|
|
|
+ }
|
|
|
|
+ // 请求远程当前学生所在组的所有学生信息。
|
|
|
|
+ // 通过当前学生examNumber获取到的学生列表为空时,抛出异常
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.curStudent = this.students.find(
|
|
|
|
+ item => item.examNumber === examNumber
|
|
|
|
+ );
|
|
|
|
+ if (!this.curStudent) {
|
|
|
|
+ validInfo = {
|
|
|
|
+ valid: false,
|
|
|
|
+ message: "当前考场没有当前学生,请重新采集!"
|
|
|
|
+ };
|
|
|
|
+ } else {
|
|
|
|
+ this.curStudent.isCurrent = true;
|
|
|
|
+ }
|
|
|
|
+ return validInfo;
|
|
|
|
+ },
|
|
|
|
+ async toSaveStudent(examNumber, type) {
|
|
|
|
+ await saveFormalImage(
|
|
|
|
+ this.curImage.url,
|
|
|
|
+ {
|
|
|
|
+ workId: this.user.workId,
|
|
|
|
+ subjectId: this.curSubject.id,
|
|
|
|
+ examNumber
|
|
|
|
+ },
|
|
|
|
+ this.getCurCollectConfig()
|
|
|
|
+ );
|
|
|
|
+ this.curStudent = Object.assign(this.curStudent, {
|
|
|
|
+ isCurrent: false,
|
|
|
|
+ isClient: true,
|
|
|
|
+ isManual: type === "MANUAL"
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // 删除扫描文件,继续开始下一个任务
|
|
|
|
+ fs.unlinkSync(this.curImage.url);
|
|
|
|
+ this.restartInitFile();
|
|
|
|
+ },
|
|
|
|
+ checkAllStudentIsClient() {
|
|
|
|
+ return !this.students.some(item => !item.isClient);
|
|
|
|
+ },
|
|
|
|
+ async scanOver() {
|
|
|
|
+ if (this.holding) return;
|
|
|
|
+ this.holding = true;
|
|
|
|
+ if (!this.checkAllStudentIsClient()) {
|
|
|
|
+ this.$Message.error("当前考场试卷没有扫完!");
|
|
|
|
+ this.holding = false;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ // 添加上传任务
|
|
|
|
+ for (let i = 0, len = this.students.length; i < len; i++) {
|
|
|
|
+ const curStudent = this.students[i];
|
|
|
|
+ await this.$parent.addUploadTask({
|
|
|
|
+ workId: this.user.workId,
|
|
|
|
+ workName: this.user.workName,
|
|
|
|
+ subjectId: this.curSubject.id,
|
|
|
|
+ subjectName: this.curSubject.name,
|
|
|
|
+ examNumber: curStudent.examNumber,
|
|
|
|
+ studentName: curStudent.name,
|
|
|
|
+ siteCode: curStudent.siteCode,
|
|
|
|
+ roomCode: curStudent.roomCode,
|
|
|
|
+ createdTime: formatDate(),
|
|
|
|
+ isManual: curStudent.isManual,
|
|
|
|
+ clientUserId: this.user.id,
|
|
|
|
+ clientUsername: this.user.name,
|
|
|
|
+ clientUserLoginTime: this.user.clientUserLoginTime
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.allReScan();
|
|
|
|
+ },
|
|
|
|
+ allReScan() {
|
|
|
|
+ this.students = [];
|
|
|
|
+ this.restartInitFile();
|
|
|
|
+ },
|
|
|
|
+ getCurCollectConfig() {
|
|
|
|
+ return this.curStudent.collectConfig || this.curSubject.collectConfig;
|
|
|
|
+ },
|
|
|
|
+ // scan-exception
|
|
|
|
+ resetConfig() {
|
|
|
|
+ this.curCollectConfig = this.getCurCollectConfig();
|
|
|
|
+ this.$refs.ScanAreaDialog.open();
|
|
|
|
+ },
|
|
|
|
+ studentConfigChange(setting) {
|
|
|
|
+ this.curStudent.collectConfig = setting;
|
|
|
|
+ this.startDecodeTask(setting.codeArea);
|
|
|
|
+ },
|
|
|
|
+ goBack() {
|
|
|
|
+ this.$confirm({
|
|
|
|
+ content: "当前正处于采集状态,确定要退出吗?",
|
|
|
|
+ onOk: () => {
|
|
|
|
+ this.$router.go(-1);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ beforeDestroy() {
|
|
|
|
+ if (this.setT) clearTimeout(this.setT);
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+</script>
|