|
@@ -1,9 +1,281 @@
|
|
<template>
|
|
<template>
|
|
- <div>ImageCheckAudit</div>
|
|
|
|
|
|
+ <div v-if="hasTask" class="audit audit-image-check">
|
|
|
|
+ <div class="audit-head">
|
|
|
|
+ <a-row :gutter="8">
|
|
|
|
+ <a-col :span="3">
|
|
|
|
+ <span class="head-label">姓名:</span>
|
|
|
|
+ <span class="head-cont">{{ curImage.name }}</span>
|
|
|
|
+ </a-col>
|
|
|
|
+ <a-col :span="4">
|
|
|
|
+ <span class="head-label">准考证号:</span>
|
|
|
|
+ <span class="head-cont">{{ curImage.examNumber }}</span>
|
|
|
|
+ </a-col>
|
|
|
|
+ <a-col :span="4">
|
|
|
|
+ <span class="head-label">科目:</span>
|
|
|
|
+ <span class="head-cont">{{ batchInfo.device }}</span>
|
|
|
|
+ </a-col>
|
|
|
|
+ <a-col :span="3">
|
|
|
|
+ <span class="head-label">张数:</span>
|
|
|
|
+ <span class="head-cont">{{ batchInfo.batchId }}</span>
|
|
|
|
+ </a-col>
|
|
|
|
+ <a-col :span="5">
|
|
|
|
+ <span class="head-label">倒计时:</span>
|
|
|
|
+ <span class="head-cont remain-time">{{ remainTime }}秒</span>
|
|
|
|
+ <a-button
|
|
|
|
+ v-if="loopImageStoped"
|
|
|
|
+ type="primary-light"
|
|
|
|
+ @click="startImageLoop"
|
|
|
|
+ >
|
|
|
|
+ <template #icon><PlayCircleOutlined /></template>
|
|
|
|
+ 开始
|
|
|
|
+ </a-button>
|
|
|
|
+ <a-button v-else type="error-light" @click="stopImageLoop">
|
|
|
|
+ <template #icon><PauseCircleOutlined /></template>
|
|
|
|
+ 暂停
|
|
|
|
+ </a-button>
|
|
|
|
+ </a-col>
|
|
|
|
+ <a-col :span="5">
|
|
|
|
+ <a-space>
|
|
|
|
+ <a-button :disabled="!prevEnable" @click="getPrevImage">
|
|
|
|
+ <template #icon><ArrowLeftOutlined /></template>
|
|
|
|
+ 上一个
|
|
|
|
+ </a-button>
|
|
|
|
+ <span>{{ curImageIndex + 1 }} / {{ imageList.length }}</span>
|
|
|
|
+ <a-button @click="getNextImage">
|
|
|
|
+ <template #icon><ArrowRightOutlined /></template>
|
|
|
|
+ 下一个
|
|
|
|
+ </a-button>
|
|
|
|
+ </a-space>
|
|
|
|
+ </a-col>
|
|
|
|
+ </a-row>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="audit-body">
|
|
|
|
+ <!-- <img src="" alt=""> -->
|
|
|
|
+ <img src="../../RecognizeCheck/data/202302040117-1.jpg" />
|
|
|
|
+ </div>
|
|
|
|
+ <div class="audit-topinfo">
|
|
|
|
+ <a-space :size="6">
|
|
|
|
+ <template #split>
|
|
|
|
+ <a-divider type="vertical" style="height: 16px" />
|
|
|
|
+ </template>
|
|
|
|
+ <span>批次ID:{{ batchInfo.batchId }}</span>
|
|
|
|
+ <span>扫描员:{{ batchInfo.deviceName }}</span>
|
|
|
|
+ <span>扫描时间:{{ dateFormat(batchInfo.createTime) }}</span>
|
|
|
|
+ </a-space>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div v-else class="audit is-wait">
|
|
|
|
+ <div>
|
|
|
|
+ <img src="@/assets/imgs/bg-wait.png" alt="等待" />
|
|
|
|
+ <p>等待审核结果…</p>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
</template>
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
|
+import { computed, onBeforeUnmount, onMounted, ref } from "vue";
|
|
|
|
+import {
|
|
|
|
+ ArrowLeftOutlined,
|
|
|
|
+ ArrowRightOutlined,
|
|
|
|
+ PlayCircleOutlined,
|
|
|
|
+ PauseCircleOutlined,
|
|
|
|
+} from "@ant-design/icons-vue";
|
|
|
|
+import { message } from "ant-design-vue";
|
|
|
|
+
|
|
|
|
+import { AuditBatchResult, AuditBatchStudent } from "@/ap/types/audit";
|
|
|
|
+import { imageAuditBatch, imageAuditSave, imageAuditRelease } from "@/ap/audit";
|
|
|
|
+import { useUserStore } from "@/store";
|
|
|
|
+import { dateFormat } from "@/utils/tool";
|
|
|
|
+import useLoop from "@/hooks/useLoop";
|
|
|
|
+
|
|
defineOptions({
|
|
defineOptions({
|
|
name: "ImageCheckAudit",
|
|
name: "ImageCheckAudit",
|
|
});
|
|
});
|
|
|
|
+
|
|
|
|
+interface ImageItem {
|
|
|
|
+ url: string;
|
|
|
|
+ pageName: string;
|
|
|
|
+ name: string;
|
|
|
|
+ examNumber: string;
|
|
|
|
+ subjectName: string;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const userStore = useUserStore();
|
|
|
|
+const imageList = ref<ImageItem[]>([]);
|
|
|
|
+const curImage = ref<ImageItem | null>(null);
|
|
|
|
+const curImageIndex = ref(0);
|
|
|
|
+const batchInfo = ref({} as AuditBatchResult);
|
|
|
|
+const hasTask = ref(false);
|
|
|
|
+
|
|
|
|
+const imageCheckLoopTime = computed(() => {
|
|
|
|
+ return userStore.imageCheckLoopTime || 0;
|
|
|
|
+});
|
|
|
|
+
|
|
|
|
+// 计时
|
|
|
|
+const loopImageStoped = ref(false);
|
|
|
|
+const remainTime = ref(0);
|
|
|
|
+const { start: startLoopRemainTime, stop: stopLoopRemainTime } = useLoop(
|
|
|
|
+ updateRemainTime,
|
|
|
|
+ 1000
|
|
|
|
+);
|
|
|
|
+
|
|
|
|
+function updateRemainTime() {
|
|
|
|
+ remainTime.value--;
|
|
|
|
+
|
|
|
|
+ if (remainTime.value <= 0) {
|
|
|
|
+ stopLoopRemainTime();
|
|
|
|
+ // 跳出loop,再开启新的loop
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ getNextImage();
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function stopImageLoop() {
|
|
|
|
+ loopImageStoped.value = true;
|
|
|
|
+ stopLoopRemainTime();
|
|
|
|
+}
|
|
|
|
+function startImageLoop() {
|
|
|
|
+ loopImageStoped.value = false;
|
|
|
|
+ startLoopRemainTime();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const prevEnable = computed(() => {
|
|
|
|
+ return curImageIndex.value > 0;
|
|
|
|
+});
|
|
|
|
+
|
|
|
|
+// 获取批次数据
|
|
|
|
+const { start: startLoopGetData, stop: stopLoopGetData } = useLoop(
|
|
|
|
+ getData,
|
|
|
|
+ 2000
|
|
|
|
+);
|
|
|
|
+async function getData() {
|
|
|
|
+ const res = await imageAuditBatch({ examId: userStore.curExam.id });
|
|
|
|
+ if (!res) {
|
|
|
|
+ hasTask.value = false;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ stopLoopGetData();
|
|
|
|
+ hasTask.value = true;
|
|
|
|
+ batchInfo.value = res;
|
|
|
|
+
|
|
|
|
+ initImageData();
|
|
|
|
+ setCurImage(0);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function initImageData() {
|
|
|
|
+ if (!hasTask.value) return;
|
|
|
|
+
|
|
|
|
+ const images: ImageItem[] = [];
|
|
|
|
+ batchInfo.value.students.forEach((student) => {
|
|
|
|
+ student.papers.forEach((paper, paperIndex) => {
|
|
|
|
+ paper.pages.forEach((page, pageIndex) => {
|
|
|
|
+ const pageName = `第${paperIndex + 1}张${
|
|
|
|
+ pageIndex === 0 ? "正" : "反"
|
|
|
|
+ }面`;
|
|
|
|
+ images.push({
|
|
|
|
+ url: page,
|
|
|
|
+ pageName,
|
|
|
|
+ name: student.name,
|
|
|
|
+ examNumber: student.examNumber,
|
|
|
|
+ subjectName: student.subjectName,
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ imageList.value = images;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+async function submitBatch() {
|
|
|
|
+ await imageAuditSave({
|
|
|
|
+ examId: userStore.curExam.id,
|
|
|
|
+ batchId: batchInfo.value.batchId,
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+async function releaseBatch() {
|
|
|
|
+ await imageAuditRelease({ examId: userStore.curExam.id });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function setCurImage(index: number) {
|
|
|
|
+ curImageIndex.value = index;
|
|
|
|
+ curImage.value = imageList.value[curImageIndex.value];
|
|
|
|
+ stopLoopRemainTime();
|
|
|
|
+
|
|
|
|
+ remainTime.value = imageCheckLoopTime.value;
|
|
|
|
+ if (!loopImageStoped.value) {
|
|
|
|
+ // 开启loop时会调用一次action,所这里提前加1
|
|
|
|
+ remainTime.value++;
|
|
|
|
+ startLoopRemainTime();
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+async function getNextImage() {
|
|
|
|
+ if (curImageIndex.value >= imageList.value.length - 1) {
|
|
|
|
+ await submitBatch();
|
|
|
|
+ // 获取下一批次
|
|
|
|
+ await startLoopGetData();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ setCurImage(++curImageIndex.value);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function getPrevImage() {
|
|
|
|
+ if (curImageIndex.value <= 0) return;
|
|
|
|
+
|
|
|
|
+ setCurImage(--curImageIndex.value);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// init
|
|
|
|
+// onMounted(async () => {
|
|
|
|
+// await releaseBatch();
|
|
|
|
+// startLoopGetData();
|
|
|
|
+// });
|
|
|
|
+// onBeforeUnmount(async () => {
|
|
|
|
+// stopLoopGetData();
|
|
|
|
+// stopLoopRemainTime();
|
|
|
|
+// await releaseBatch();
|
|
|
|
+// });
|
|
|
|
+
|
|
|
|
+// TODO:测试数据
|
|
|
|
+onMounted(() => {
|
|
|
|
+ const students = "#"
|
|
|
|
+ .repeat(30)
|
|
|
|
+ .split("")
|
|
|
|
+ .map((item, index) => {
|
|
|
|
+ return {
|
|
|
|
+ examNumber: `3600802404012${index}`,
|
|
|
|
+ name: `张三${index + 1}`,
|
|
|
|
+ studentCode: `36008${index + 1}`,
|
|
|
|
+ subjectCode: "sx001",
|
|
|
|
+ subjectName: "数学",
|
|
|
|
+ seatNumber: "11",
|
|
|
|
+ papers: [
|
|
|
|
+ {
|
|
|
|
+ number: 1,
|
|
|
|
+ // 是否本张为人工绑定
|
|
|
|
+ assigned: true,
|
|
|
|
+ // 数组为空表示缺纸
|
|
|
|
+ pages: ["xxx.jpg", "xxx.png"],
|
|
|
|
+ },
|
|
|
|
+ ],
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ batchInfo.value = {
|
|
|
|
+ batchId: 123,
|
|
|
|
+ device: "192.168.0.1",
|
|
|
|
+ deviceName: "scan01",
|
|
|
|
+ createTime: Date.now(),
|
|
|
|
+ // 实时审核批次此字段有值
|
|
|
|
+ packageCode: "ET01245124",
|
|
|
|
+ students,
|
|
|
|
+ };
|
|
|
|
+ hasTask.value = true;
|
|
|
|
+ loopImageStoped.value = true;
|
|
|
|
+
|
|
|
|
+ initImageData();
|
|
|
|
+ setCurImage(0);
|
|
|
|
+});
|
|
</script>
|
|
</script>
|