liuqiang 1 год назад
Родитель
Сommit
9945d3120b

Разница между файлами не показана из-за своего большого размера
+ 622 - 18
package-lock.json


+ 2 - 0
package.json

@@ -10,6 +10,8 @@
   },
   "dependencies": {
     "axios": "^1.6.8",
+    "libpag": "^4.2.84",
+    "rollup-plugin-copy": "^3.5.0",
     "vue": "^3.4.21",
     "vue-router": "^4.3.0"
   },

+ 0 - 0
src/assets/img/scaning.pag → public/img/scaning.pag


+ 0 - 0
src/assets/img/扫描成功.pag → public/img/success.pag


BIN
public/libpag.wasm


BIN
src/assets/img/badface.png


BIN
src/assets/img/close.png


BIN
src/assets/img/noface.png


BIN
src/assets/img/scan1.png


BIN
src/assets/img/scan2.png


BIN
src/assets/img/scan3.png


+ 6 - 0
src/router/index.js

@@ -44,6 +44,12 @@ export const constantRoutes = [
 		name: 'scan',
 		hidden: true
 	},
+	{
+		path: '/scanentrance',
+		component: () => import('@/views/ScanEntrance/ScanEntrance.vue'),
+		name: 'scanentrance',
+		hidden: true
+	},
 	// {
 	// 	path: '',
 	// 	component: () => import('@/layout/index.vue'),

+ 177 - 15
src/views/SacnPage/SacnPage.vue

@@ -1,12 +1,33 @@
 <template>
   <div class="page">
     <TopLogoVue></TopLogoVue>
-    <!-- 主页面容器,红色背景,居中显示 -->
-    <div class="bgcBox">
-      <div ref="wrapper" class="camera">
-        <!-- 视频元素容器 -->
-        <video v-if="!takeOver" ref="videoEl" class="camera" />
+    <div class="scanMain">
+      <div class="bgcBox">
+        <div>
+          <canvas class="canvas" id="pag"></canvas>
+        </div>
+        <div ref="wrapper" class="camera wrapper">
+          <!-- 视频元素容器 -->
+          <video v-show="!takeOver && first" ref="videoEl" class="camera" />
+          <canvas v-if="!takeOver && !first" class="success" id="success"></canvas>
+        </div>
       </div>
+      <span v-if="takeOver" class="text">扫描中...</span>
+      <span v-if="!takeOver && !first" class="text">人脸识别成功</span>
+      <div v-if="takeOver" class="loading">
+        <div
+          v-for="item in 16"
+          :key="item"
+          class="oneBox"
+          :class="{ check: item < loadingNum }"
+        ></div>
+      </div>
+    </div>
+    <div v-if="noface" class="noface err">
+      <img src="../../assets/img/close.png" @click="closeErr" alt="" />
+    </div>
+    <div v-if="badface" class="badface err">
+      <img src="../../assets/img/close.png" @click="closeErr" alt="" />
     </div>
   </div>
 </template>
@@ -14,11 +35,16 @@
 <script setup>
 import TopLogoVue from "../../components/TopLogo/TopLogo.vue";
 import { ref, onMounted } from "vue";
+import { PAGInit } from "libpag";
 //使用 ref 对象来获取 DOM 元素
 const wrapper = ref();
 const videoEl = ref();
 const takeOver = ref(false);
-
+const loadingNum = ref(0); //点亮的色块个数
+const first = ref(true); //第一次进入页面
+let timer = null; //定时器
+const noface = ref(false); //未检测到脸
+const badface = ref(false); //未注册的脸
 // 存储拍摄后的图片路径
 const imageUrl = ref(null);
 
@@ -58,6 +84,7 @@ function shoot() {
   // 检查视频元素和页面容器是否存在
   if (!videoEl.value || !wrapper.value) return;
   takeOver.value = true;
+  first.value = false;
   // 创建一个画布元素,设置画布尺寸为视频流的尺寸
   const canvas = document.createElement("canvas");
   canvas.width = videoEl.value.videoWidth;
@@ -82,11 +109,74 @@ function shoot() {
   // 将 Base64 数据设置为图片的 src 属性
   imageElement.src = imageDataUrl;
 
-  console.log(imageElement, "图片路径");
-
   // 将图片元素添加到页面容器中
   wrapper.value.appendChild(imageElement);
+  timer = setInterval(() => {
+    if (loadingNum.value <= 16) {
+      loadingNum.value += 1;
+    } else {
+      loadingNum.value = 1;
+    }
+    // console.log(loadingNum.value, "loadingNum");
+  }, 500);
+  setTimeout(() => {
+    clearInterval(timer);
+    takeOver.value = false;
+    noface.value = true;
+    successInit()
+  }, 4000);
 }
+// 关闭错误提示
+const closeErr = () => {
+  noface.value = false;
+  badface.value = false;
+};
+// 初始化 PAG
+const pagInit = () => {
+  PAGInit().then((PAG) => {
+    //此处特别要注意一点,你得看你的文件路径是否能够获取到你想要的pag格式文件,如果不行就用../的形式
+    //一层一层获取,目前在我的操作来看他目前貌似用不了 @/assets/XXX.pag的形式获取到想要的图片路径
+    //大家可以自行尝试看能否可以获取到对应的pag图片路径
+    const url = "/public/img/scaning.pag";
+    fetch(url)
+      .then((response) => response.blob())
+      .then(async (blob) => {
+        const file = new window.File(
+          [blob],
+          url.replace(/(.*\/)*([^.]+)/i, "$2")
+        );
+        const pagFile = await PAG.PAGFile.load(file);
+        document.getElementById("pag").width = pagFile.width();
+        document.getElementById("pag").height = pagFile.height();
+        const pagView = await PAG.PAGView.init(pagFile, "#pag");
+        pagView.setRepeatCount(0);
+        await pagView.play();
+      });
+  });
+};
+// 识别成功 PAG
+const successInit = () => {
+  PAGInit().then((PAG) => {
+    //此处特别要注意一点,你得看你的文件路径是否能够获取到你想要的pag格式文件,如果不行就用../的形式
+    //一层一层获取,目前在我的操作来看他目前貌似用不了 @/assets/XXX.pag的形式获取到想要的图片路径
+    //大家可以自行尝试看能否可以获取到对应的pag图片路径
+    const url = "/public/img/success.pag";
+    fetch(url)
+      .then((response) => response.blob())
+      .then(async (blob) => {
+        const file = new window.File(
+          [blob],
+          url.replace(/(.*\/)*([^.]+)/i, "$2")
+        );
+        const pagFile = await PAG.PAGFile.load(file);
+        document.getElementById("success").width = pagFile.width();
+        document.getElementById("success").height = pagFile.height();
+        const pagView = await PAG.PAGView.init(pagFile, "#success");
+        pagView.setRepeatCount(0);
+        await pagView.play();
+      });
+  });
+};
 
 // 在组件挂载后执行检查摄像头的操作
 onMounted(() => {
@@ -94,6 +184,7 @@ onMounted(() => {
   setTimeout(() => {
     shoot();
   }, 3000);
+  pagInit();
 });
 </script>
 
@@ -105,21 +196,92 @@ onMounted(() => {
   background-size: cover;
   background-position: center;
   position: relative;
+  .scanMain {
+    width: 500px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    margin: 0 auto;
+    .text {
+      color: #b7beff;
+      font-family: Inter-Medium-8;
+      font-weight: bold;
+      font-size: 24px;
+      margin-bottom: 16px;
+    }
+    .loading {
+      width: 421px;
+      height: 40px;
+      border-radius: 5px 5px 5px 5px;
+      border: 1px solid #b7beff;
+      display: flex;
+      justify-content: space-around;
+      align-items: center;
+      .oneBox {
+        width: 21px;
+        height: 30px;
+        border-radius: 2px 2px 2px 2px;
+        background: #362b5d;
+      }
+      .check {
+        background: #b7beff;
+      }
+    }
+  }
   .camera {
-    position: absolute;
-    top: calc(50% - 140px);
-    left: calc(50% - 140px);
     width: 280px;
     height: 280px;
     border-radius: 50%;
   }
-  .bgcBox{
+  .bgcBox {
     width: 450px;
     height: 450px;
-    position: absolute;
-    top: calc(50% - 225px);
-    left: calc(50% - 225px);
+    position: relative;
+    display: flex;
+    justify-content: center;
+    align-items: center;
     background-image: url("../../assets/img/scaning.pag");
+    .wrapper {
+      position: absolute;
+      // top: 10%;
+      // left: 10%;
+    }
+    .success{
+      position: absolute;
+      top: -100px;
+      left: -100px;
+      width: 480px;
+      height: 480px;
+      z-index: 99999;
+    }
+  }
+  .err {
+    width: 800px;
+    height: 272px;
+    position: absolute;
+    top: calc(50% - 136px);
+    left: calc(50% - 400px);
+    z-index: 99;
+    background-size: cover;
+    background-position: center;
+    img {
+      width: 40px;
+      height: 40px;
+      cursor: pointer;
+      position: absolute;
+      top: 5%;
+      right: 3%;
+    }
+  }
+  .noface {
+    background-image: url("../../assets/img/noface.png");
+  }
+  .badface {
+    background-image: url("../../assets/img/badface.png");
+  }
+  #pag {
+    width: 450px;
+    height: 450px;
   }
 }
 </style>

+ 82 - 0
src/views/ScanEntrance/ScanEntrance.vue

@@ -0,0 +1,82 @@
+<template>
+  <div class="page">
+    <TopLogoVue></TopLogoVue>
+    <div class="entranceMain">
+        <div class="oneBox">
+          <img src="../../assets/img/scan1.png" alt="">
+          <span class="text1">单页扫描</span>
+          <span class="text2">直接点击扫描按钮即可扫描</span>
+          <div class="btn">开始扫描</div>
+        </div>
+        <div class="oneBox">
+          <img src="../../assets/img/scan2.png" alt="">
+          <span class="text1">自动扫描</span>
+          <span class="text2">手动翻页后无需再次点击扫描按钮</span>
+          <div class="btn">开始扫描</div>
+        </div>
+        <div class="oneBox">
+          <img src="../../assets/img/scan3.png" alt="">
+          <span class="text1">文字提取</span>
+          <span class="text2">智能提取图片中的文字</span>
+          <div class="btn">开始扫描</div>
+        </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import TopLogoVue from "../../components/TopLogo/TopLogo.vue";
+</script>
+
+<style lang="scss" scoped>
+.page {
+  width: 100vw;
+  height: 100vh;
+  background-image: url("../../assets/img/bluebgi.png");
+  background-size: cover;
+  background-position: center;
+  position: relative;
+}
+.entranceMain{
+    width: 1067px;
+    height: 324px;
+    position: absolute;
+    top: calc(50% - 162px);
+    left: calc(50% - 533px);
+    display: flex;
+    justify-content: space-between;
+    .oneBox{
+        width: 329px;
+        height: 324px;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        img{
+          width: 150px;
+          height: 150px;
+        }
+        .text1{
+          margin: 24px 0 12px 0;
+          font-family:Inter-Bold ;
+          color: #B7BEFF;
+        }
+        .text2{
+          color: #8989C6;
+          font-family: Inter-Medium;
+          margin-bottom: 40px;
+        }
+        .btn{
+          width: 120px;
+          height: 35px;
+          display: flex;
+          justify-content: center;
+          align-items: center;
+          cursor: pointer;
+          color: #231347;
+          font-family: Inter-Medium;
+          background: #B7BEFF;
+          border-radius: 2px 2px 2px 2px;
+        }
+    }
+}
+</style>

+ 11 - 1
vite.config.js

@@ -2,9 +2,19 @@ import { defineConfig } from 'vite'
 import vue from '@vitejs/plugin-vue'
 import path from 'path'
 
+import copy from 'rollup-plugin-copy'
+
 // https://vitejs.dev/config/
 export default defineConfig({
-  plugins: [vue()],
+  plugins: [
+    vue(),
+    copy({
+      targets: [
+        { src: './node_modules/libpag/lib/libpag.wasm', dest: process.env.NODE_ENV === 'production' ? 'dist/' : 'public/' },
+      ],
+      hook: process.env.NODE_ENV === 'production' ? 'writeBundle' : "buildStart",
+    })
+  ],
   resolve: {
     // https://cn.vitejs.dev/config/#resolve-alias
     alias: {

Некоторые файлы не были показаны из-за большого количества измененных файлов