|
@@ -1,15 +1,339 @@
|
|
<template>
|
|
<template>
|
|
- <div class="line-scan">
|
|
|
|
- line-scan
|
|
|
|
|
|
+ <div class="line-scan scan">
|
|
|
|
+ <div class="scan-task task-list">
|
|
|
|
+ <div
|
|
|
|
+ :class="[
|
|
|
|
+ 'task-item',
|
|
|
|
+ {
|
|
|
|
+ 'task-current': curStudent.isCurrent,
|
|
|
|
+ 'task-over': curStudent.isClient
|
|
|
|
+ }
|
|
|
|
+ ]"
|
|
|
|
+ >
|
|
|
|
+ <span>{{ curStudent.name }}</span>
|
|
|
|
+ <span>{{ curStudent.examNumber }}</span>
|
|
|
|
+ </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 class="scan-history">
|
|
|
|
+ <div
|
|
|
|
+ class="history-item"
|
|
|
|
+ v-for="(task, tindex) in historyList"
|
|
|
|
+ :key="tindex"
|
|
|
|
+ >
|
|
|
|
+ <p class="history-item-title">
|
|
|
|
+ <span>{{ task.name }}</span
|
|
|
|
+ ><span>{{ task.examNumber }}</span>
|
|
|
|
+ </p>
|
|
|
|
+ <div class="history-item-body">
|
|
|
|
+ <img :src="task.url" :alt="task.name" />
|
|
|
|
+ </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"
|
|
|
|
+ @confirm="examNumberValid"
|
|
|
|
+ ref="ScanExceptionDialog"
|
|
|
|
+ ></scan-exception-dialog>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
|
+const fs = require("fs");
|
|
|
|
+import { getStudentByExamNumber } from "../api";
|
|
|
|
+import {
|
|
|
|
+ decodeImageCode,
|
|
|
|
+ getEarliestFile,
|
|
|
|
+ saveOutputImage
|
|
|
|
+} from "../../../plugins/imageOcr";
|
|
|
|
+import { deepCopy } from "../../../plugins/utils";
|
|
|
|
+import ScanAreaDialog from "../components/ScanAreaDialog";
|
|
|
|
+import ScanExceptionDialog from "../components/ScanExceptionDialog";
|
|
|
|
+import { mapState } from "vuex";
|
|
|
|
+
|
|
export default {
|
|
export default {
|
|
name: "line-scan",
|
|
name: "line-scan",
|
|
|
|
+ components: { ScanAreaDialog, ScanExceptionDialog },
|
|
data() {
|
|
data() {
|
|
- return {};
|
|
|
|
|
|
+ return {
|
|
|
|
+ isWaiting: true,
|
|
|
|
+ students: [],
|
|
|
|
+ curStudent: {},
|
|
|
|
+ curCollectConfig: {},
|
|
|
|
+ curException: {
|
|
|
|
+ showAction: true,
|
|
|
|
+ message: ""
|
|
|
|
+ },
|
|
|
|
+ historyLimit: 30,
|
|
|
|
+ historyList: [
|
|
|
|
+ {
|
|
|
|
+ name: "张一二三",
|
|
|
|
+ examNumber: "1901040084",
|
|
|
|
+ url:
|
|
|
|
+ "http://127.0.0.1:9000/api/file/image/download/31/1/734/1?random=676176fc-24cd-407a-a7bc-fabc49bd2dbc"
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ name: "张一二三",
|
|
|
|
+ examNumber: "1901040084",
|
|
|
|
+ url:
|
|
|
|
+ "http://127.0.0.1:9000/api/file/image/download/31/1/733/1?random=e2966291-ffba-4b19-985d-0cad9ae1b75b"
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ name: "张一二三",
|
|
|
|
+ examNumber: "1901040084",
|
|
|
|
+ url:
|
|
|
|
+ "http://127.0.0.1:9000/api/file/image/download/31/1/731/1?random=b305c27c-76d0-4477-a1ef-c9b8554a4671"
|
|
|
|
+ }
|
|
|
|
+ ],
|
|
|
|
+ setT: "",
|
|
|
|
+ holding: false,
|
|
|
|
+ curImage: {
|
|
|
|
+ url: "",
|
|
|
|
+ name: ""
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ },
|
|
|
|
+ computed: {
|
|
|
|
+ ...mapState("client", ["curSubject", "clientConfig", "curLevel"]),
|
|
|
|
+ user() {
|
|
|
|
+ return this.$store.state.user;
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ mounted() {
|
|
|
|
+ if (!this.curSubject || !this.curSubject.collectConfig) {
|
|
|
|
+ this.$Message.error("请先完成采集设置!");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ // this.getInitFile();
|
|
|
|
+ // this.test();
|
|
|
|
+ },
|
|
|
|
+ methods: {
|
|
|
|
+ async test() {
|
|
|
|
+ this.curImage = getEarliestFile();
|
|
|
|
+ const codeAreas = {
|
|
|
|
+ codeArea: {
|
|
|
|
+ x: 0,
|
|
|
|
+ y: 0,
|
|
|
|
+ width: 717.12,
|
|
|
|
+ height: 673.92,
|
|
|
|
+ rotate: 0,
|
|
|
|
+ scaleX: 1,
|
|
|
|
+ scaleY: 1,
|
|
|
|
+ codeRotate: 90
|
|
|
|
+ },
|
|
|
|
+ coverArea: {
|
|
|
|
+ x: 518.4,
|
|
|
|
+ y: 345.6,
|
|
|
|
+ width: 4147.2,
|
|
|
|
+ height: 2764.8,
|
|
|
|
+ rotate: 0,
|
|
|
|
+ scaleX: 1,
|
|
|
|
+ scaleY: 1
|
|
|
|
+ },
|
|
|
|
+ tailorArea: {
|
|
|
|
+ x: 518.4,
|
|
|
|
+ y: 345.6,
|
|
|
|
+ width: 4147.2,
|
|
|
|
+ height: 2764.8,
|
|
|
|
+ rotate: 0,
|
|
|
|
+ scaleX: 1,
|
|
|
|
+ scaleY: 1
|
|
|
|
+ },
|
|
|
|
+ imageRotate: 0
|
|
|
|
+ };
|
|
|
|
+ const examNumber = await decodeImageCode(
|
|
|
|
+ this.curImage.url,
|
|
|
|
+ codeAreas.codeArea
|
|
|
|
+ ).catch(error => {
|
|
|
|
+ const content = `图像:${this.curImage.name},解析错误,错误信息:${error}`;
|
|
|
|
+
|
|
|
|
+ this.$Notice.error({ title: "错误提示", desc: content, duration: 0 });
|
|
|
|
+ });
|
|
|
|
+ console.log(examNumber);
|
|
|
|
+ },
|
|
|
|
+ getInitFile() {
|
|
|
|
+ this.curImage = getEarliestFile(this.GLOBAL.input);
|
|
|
|
+
|
|
|
|
+ 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.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: "" };
|
|
|
|
+ const curStudent = await getStudentByExamNumber(
|
|
|
|
+ examNumber
|
|
|
|
+ ).catch(() => {});
|
|
|
|
+
|
|
|
|
+ if (!curStudent) {
|
|
|
|
+ validInfo = {
|
|
|
|
+ valid: false,
|
|
|
|
+ message: "无该考生,请处理!"
|
|
|
|
+ };
|
|
|
|
+ } else {
|
|
|
|
+ this.curStudent = {
|
|
|
|
+ ...curStudent,
|
|
|
|
+ imgPath: this.curImage.url,
|
|
|
|
+ isClient: false,
|
|
|
|
+ isCurrent: true,
|
|
|
|
+ isManual: false,
|
|
|
|
+ collectConfig: null
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ return validInfo;
|
|
|
|
+ },
|
|
|
|
+ async toSaveStudent(examNumber, type) {
|
|
|
|
+ const result = await saveOutputImage(
|
|
|
|
+ this.curImage.url,
|
|
|
|
+ {
|
|
|
|
+ workId: this.user.workId,
|
|
|
|
+ subjectId: this.curSubject.id,
|
|
|
|
+ examNumber
|
|
|
|
+ },
|
|
|
|
+ this.getCurCollectConfig()
|
|
|
|
+ ).catch(error => {
|
|
|
|
+ const content = `${this.curStudent.name}的试卷保存失败,请重新扫描!`;
|
|
|
|
+ this.$Notice.error({ title: "错误提示", desc: content, duration: 0 });
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ if (result) {
|
|
|
|
+ this.curStudent = Object.assign(this.curStudent, {
|
|
|
|
+ isClient: true,
|
|
|
|
+ formalImgPath: result.outputFormalPath,
|
|
|
|
+ sliceImgPath: result.outputSlicelPath,
|
|
|
|
+ isManual: type === "MANUAL"
|
|
|
|
+ });
|
|
|
|
+ await this.appendUploadTask();
|
|
|
|
+ this.updateHistory(this.curStudent);
|
|
|
|
+ }
|
|
|
|
+ // 删除扫描文件,继续开始下一个任务
|
|
|
|
+ fs.unlinkSync(this.curImage.url);
|
|
|
|
+ this.restartInitFile();
|
|
|
|
+ },
|
|
|
|
+ async appendUploadTask() {
|
|
|
|
+ await this.$parent.addUploadTask({
|
|
|
|
+ id: null,
|
|
|
|
+ examId: this.user.examId,
|
|
|
|
+ examName: this.user.examName,
|
|
|
|
+ subjectId: this.curSubject.id,
|
|
|
|
+ subjectName: this.curSubject.name,
|
|
|
|
+ examNumber: this.curStudent.examNumber,
|
|
|
|
+ studentName: this.curStudent.name,
|
|
|
|
+ siteCode: this.curStudent.siteCode,
|
|
|
|
+ roomCode: this.curStudent.roomCode,
|
|
|
|
+ formalImgPath: this.curStudent.formalImgPath,
|
|
|
|
+ sliceImgPath: this.curStudent.sliceImgPath,
|
|
|
|
+ isManual: this.curStudent.isManual,
|
|
|
|
+ imageEnc: this.clientConfig.imageEnc,
|
|
|
|
+ level: this.curLevel,
|
|
|
|
+ clientUserId: this.user.id,
|
|
|
|
+ clientUsername: this.user.name,
|
|
|
|
+ clientUserLoginTime: this.user.loginTime
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ getCurCollectConfig() {
|
|
|
|
+ return this.curStudent.collectConfig || this.curSubject.collectConfig;
|
|
|
|
+ },
|
|
|
|
+ // history
|
|
|
|
+ updateHistory(curStudent) {
|
|
|
|
+ const student = deepCopy(curStudent);
|
|
|
|
+ if (this.historyList.length >= this.historyLimit) {
|
|
|
|
+ this.historyList.pop();
|
|
|
|
+ }
|
|
|
|
+ this.historyList.unshift(student);
|
|
|
|
+ },
|
|
|
|
+ // 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);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
},
|
|
},
|
|
- methods: {}
|
|
|
|
|
|
+ beforeDestroy() {
|
|
|
|
+ if (this.setT) clearTimeout(this.setT);
|
|
|
|
+ }
|
|
};
|
|
};
|
|
</script>
|
|
</script>
|