Przeglądaj źródła

feat: 扫描结果实施显示

zhangjie 1 rok temu
rodzic
commit
dd8daf283e

+ 3 - 2
config.sample.json

@@ -1,3 +1,4 @@
 {
-  "input": ""
-}
+  "input": "",
+  "delayMode": 0
+}

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "paper-library-client",
-  "version": "1.0.4",
+  "version": "1.0.5",
   "description": "paper-library client",
   "scripts": {
     "start": "npm run e:serve",

+ 99 - 14
src/modules/client/components/ScanTaskProcessDialog.vue

@@ -101,11 +101,14 @@ import {
   saveOutputImage,
   clearDir,
   decodeImageCode,
+  getDirScanFile,
+  deleteFiles,
 } from "../../../plugins/imageOcr";
 import db from "../../../plugins/db";
 import { evokeScanner } from "../../../plugins/scanner";
 import SimpleImagePreview from "@/components/SimpleImagePreview.vue";
 import HandleInputDialog from "./HandleInputDialog.vue";
+import timeMixins from "@/mixins/setTimeMixins";
 import log4js from "@/plugins/logger";
 const logger = log4js.getLogger("scan");
 
@@ -115,6 +118,7 @@ export default {
     SimpleImagePreview,
     HandleInputDialog,
   },
+  mixins: [timeMixins],
   props: {
     task: {
       type: Object,
@@ -139,6 +143,8 @@ export default {
       saving: false,
       maxCacheCount: 120,
       lastStudentCode: "",
+      // 非等待模式:delayMode:0
+      looping: false,
     };
   },
   computed: {
@@ -152,6 +158,12 @@ export default {
     hasSelectedData() {
       return this.scanStageList.some((item) => item.selected);
     },
+    IS_DELAY_MODE() {
+      return this.GLOBAL.delayMode === 1;
+    },
+  },
+  beforeDestroy() {
+    this.stopLoopScaningFile();
   },
   methods: {
     initData() {
@@ -200,12 +212,15 @@ export default {
     startTask() {
       logger.info(`01开始扫描`);
       this.scanStageList = [];
-      this.scanStatus = "SCAN";
-      this.evokeScanExe();
+      this.continueTask();
     },
     continueTask() {
       this.scanStatus = "SCAN";
-      this.evokeScanExe();
+      if (this.IS_DELAY_MODE) {
+        this.evokeScanExe();
+      } else {
+        this.evokeScanExeNotDelay();
+      }
     },
     async evokeScanExe() {
       logger.info("02唤起扫描仪");
@@ -232,7 +247,47 @@ export default {
         this.$refs.HandleInputDialog.open();
       }
     },
-    async stageScanImage(imageList) {
+    async evokeScanExeNotDelay() {
+      logger.info("02唤起扫描仪");
+      this.looping = true;
+      this.loopScaningFile();
+
+      await evokeScanner(this.GLOBAL.input).catch((error) => {
+        console.error(error);
+      });
+      this.stopLoopScaningFile();
+      await this.getScaningFile();
+
+      const scanCount = this.scanStageList.filter(
+        (item) => item.isStage
+      ).length;
+      this.updateScanImageStage();
+
+      // 已扫描的数据
+      const res = getPreUploadFiles(this.GLOBAL.input);
+      if (!res.succeed) {
+        logger.error(
+          `03扫描仪停止,扫描数:${scanCount},故障:${res.errorMsg}`
+        );
+        this.$message.error(res.errorMsg);
+        this.scanStatus = "FINISH";
+        renamePreUploadJsonFile(this.GLOBAL.input);
+        return;
+      }
+      logger.info(`03扫描仪停止,扫描数:${scanCount}`);
+      this.scanStatus = "FINISH";
+      renamePreUploadJsonFile(this.GLOBAL.input);
+
+      if (this.task.isFormal && !this.scanStageList[0].studentCode) {
+        this.$refs.HandleInputDialog.open();
+      }
+    },
+    updateScanImageStage() {
+      this.scanStageList.forEach((item) => {
+        item.isStage = true;
+      });
+    },
+    async stageScanImage(imageList, isStage = false) {
       const ocrAreaContent = JSON.stringify(this.ocrArea);
       for (let i = 0, len = imageList.length; i < len; i++) {
         const fileInfo = {
@@ -244,6 +299,7 @@ export default {
           courseName: this.task.courseName,
           frontOriginImgPath: imageList[i].frontFile,
           versoOriginImgPath: imageList[i].versoFile,
+          basename: imageList[i].basename,
           isFormal: this.task.isFormal ? 1 : 0,
           studentCode: "",
           ocrArea: "",
@@ -251,6 +307,7 @@ export default {
           clientUsername: this.user.loginName,
           clientUserLoginTime: this.user.loginTime,
           selected: false,
+          isStage,
         };
 
         if (this.task.isFormal) {
@@ -295,6 +352,12 @@ export default {
       }).catch(() => {});
       if (res !== "confirm") return;
 
+      const selectedFiles = this.scanStageList
+        .filter((item) => item.selected)
+        .map((item) => [item.frontOriginImgPath, item.versoOriginImgPath])
+        .flat();
+      deleteFiles(selectedFiles);
+
       this.scanStageList = this.scanStageList.filter((item) => !item.selected);
 
       const lastStageItem = this.scanStageList.slice(-1)[0];
@@ -311,6 +374,19 @@ export default {
       logger.info(`99数据清空`);
       this.$message.success("数据已清空!");
     },
+    async saveScanItem(fileInfo) {
+      const ouputImageList = saveOutputImage(
+        [fileInfo.frontOriginImgPath, fileInfo.versoOriginImgPath],
+        {
+          courseCode: this.task.courseCode,
+        }
+      );
+
+      fileInfo.frontOriginImgPath = ouputImageList[0];
+      fileInfo.versoOriginImgPath = ouputImageList[1];
+
+      await db.saveUploadInfo(fileInfo);
+    },
     async toSave() {
       if (!this.scanStageList.length) {
         this.$message.error("当前无要保存的数据!");
@@ -331,18 +407,9 @@ export default {
       logger.info(`04-1开始保存数据`);
       for (let i = 0, len = this.scanStageList.length; i < len; i++) {
         const fileInfo = this.scanStageList[i];
-        const ouputImageList = saveOutputImage(
-          [fileInfo.frontOriginImgPath, fileInfo.versoOriginImgPath],
-          {
-            courseCode: this.task.courseCode,
-          }
-        );
-
-        fileInfo.frontOriginImgPath = ouputImageList[0];
-        fileInfo.versoOriginImgPath = ouputImageList[1];
 
         let res = true;
-        await db.saveUploadInfo(fileInfo).catch((err) => {
+        await this.saveScanItem(fileInfo).catch((err) => {
           res = false;
           console.error(err);
           logger.error(`04-1保存数据错误,${err}`);
@@ -382,6 +449,24 @@ export default {
         });
       });
     },
+    // delay mode
+    // 实时获取扫描图片
+    async loopScaningFile() {
+      this.clearSetTs();
+      if (!this.looping) return;
+      await this.getScaningFile();
+
+      this.addSetTime(this.loopScaningFile, 2 * 1000);
+    },
+    stopLoopScaningFile() {
+      this.clearSetTs();
+      this.looping = false;
+    },
+    async getScaningFile() {
+      const cacheFilenams = this.scanStageList.map((item) => item.basename);
+      const newScanFiles = getDirScanFile(this.GLOBAL.input, cacheFilenams);
+      await this.stageScanImage(newScanFiles, true);
+    },
     // image-preview
     toViewPaper(imgItem) {
       this.setCurPaper(imgItem);

+ 34 - 5
src/plugins/env.js

@@ -1,3 +1,5 @@
+import { objAssign } from "./utils";
+
 const path = window.nodeRequire("path");
 const fs = window.nodeRequire("fs");
 const electron = window.nodeRequire("electron");
@@ -89,17 +91,44 @@ function makeDirSync(pathContent) {
 //   return !num || num > max || num < min ? max : num;
 // }
 
-function initConfigData(data) {
-  let configData = { ...data };
-  if (!configData.input) configData.input = getInputDir();
+const configSets = [
+  {
+    field: "input",
+    validate(val) {
+      return !!val;
+    },
+    default: getInputDir(),
+  },
+  {
+    field: "delayMode",
+    validate(val) {
+      return [0, 1].includes(val);
+    },
+    default: 1,
+  },
+];
+
+function getConfig(datas) {
+  const configData = {};
+  configSets.forEach((config) => {
+    if (config.validate(datas[config.field])) {
+      configData[config.field] = datas[config.field];
+    } else {
+      configData[config.field] = config.default;
+    }
+  });
+  return configData;
+}
 
+function initConfigData(data) {
+  let configData = getConfig(data);
   if (process.env.NODE_ENV === "development") return configData;
-  const homePath = path.dirname(process.execPath);
 
+  const homePath = path.dirname(process.execPath);
   const configPath = path.join(homePath, "config.json");
   if (fs.existsSync(configPath)) {
     configData = JSON.parse(fs.readFileSync(configPath, "utf8"));
-    if (!configData.input) configData.input = getInputDir();
+    configData = getConfig(configData);
   } else {
     fs.writeFileSync(configPath, JSON.stringify(configData), "utf8");
   }

+ 52 - 0
src/plugins/imageOcr.js

@@ -115,6 +115,16 @@ export function clearTaskOriginDir(taskId) {
   clearDir(outputDir);
 }
 
+export function deleteFiles(files) {
+  files.forEach((file) => {
+    fs.unlinkSync(file);
+  });
+}
+
+export function getScanFileBasename(filepath) {
+  return path.basename(filepath, path.extname(filepath)).split("_")[0];
+}
+
 export function getPreUploadFiles(dir) {
   const ddir = dir || getInputDir();
   const files = fs
@@ -135,6 +145,7 @@ export function getPreUploadFiles(dir) {
     return {
       frontFile: item.front,
       versoFile: item.back,
+      basename: getScanFileBasename(item.front),
     };
   });
   if (!imageList.length)
@@ -158,6 +169,47 @@ export function renamePreUploadJsonFile(dir) {
   });
 }
 
+/**
+ * 获取最早添加的文件
+ * @param {String} dir 图片目录
+ */
+export function getDirScanFile(dir, cacheFilenams = []) {
+  const st = Date.now();
+  const ddir = dir || getInputDir();
+  const files = fs
+    .readdirSync(ddir)
+    .filter((fileName) => {
+      const formatValid = fileName.toLowerCase().match(/\.(jpg|png|jpeg)/);
+      const fileBasename = getScanFileBasename(fileName);
+      const nameValid = !cacheFilenams.includes(fileBasename);
+      return formatValid && nameValid;
+    })
+    .map((fileName) => {
+      return {
+        name: fileName,
+        time: fs.statSync(path.join(ddir, fileName)).birthtimeMs,
+      };
+    })
+    .sort((a, b) => a.time - b.time);
+
+  // console.log(files);
+  // 根据时间排序之后,结果一定是[正,反,正,反]结构
+  const nFiles = [];
+  const len = Math.floor(files.length / 2);
+  for (let i = 0; i < len; i++) {
+    const frontUrl = files[2 * i].name;
+    const versoUrl = files[2 * i + 1].name;
+    nFiles[i] = {
+      frontFile: path.join(ddir, frontUrl),
+      versoFile: path.join(ddir, versoUrl),
+      basename: getScanFileBasename(frontUrl),
+    };
+  }
+  // console.log(nFiles);
+  console.log(`getDirScanFile耗时:${Date.now() - st}`);
+  return nFiles;
+}
+
 /**
 扫描仪返回的数据
 {

+ 12 - 3
src/plugins/scanner.js

@@ -8,16 +8,25 @@ const isWindowsPlatform = process.platform === "win32";
 export function setScanner() {
   if (!isWindowsPlatform) return Promise.resolve(true);
   const commandStr = `${getScanExePath()} -settings`;
-  console.log(commandStr);
+  // console.log(commandStr);
   return childProcessExec(commandStr);
 }
 
+function pmiss(time = 1 * 1000) {
+  return new Promise((resolve) => {
+    setTimeout(() => {
+      resolve(true);
+    }, time);
+  });
+}
+
 export function evokeScanner(inputDir) {
-  if (!isWindowsPlatform) return Promise.resolve(true);
+  // if (!isWindowsPlatform) return pmiss(20 * 1000);
+  if (!isWindowsPlatform) return pmiss(1 * 1000);
 
   const commandStr = `${getScanExePath()} -scan -d${inputDir}`;
 
-  console.log(commandStr);
+  // console.log(commandStr);
   return childProcessExec(commandStr);
   // return Promise.resolve({ succeed: true });
 }