瀏覽代碼

Merge branch 'dev_suwenjiang' of http://1.94.207.143:3000/xyy/xyy-m into dev_suwenjiang

suwenjiang 2 月之前
父節點
當前提交
a13efe638f
共有 2 個文件被更改,包括 272 次插入0 次删除
  1. 195 0
      src/pages/scan/_index.vue
  2. 77 0
      src/pages/scan/test/index.vue

+ 195 - 0
src/pages/scan/_index.vue

@@ -0,0 +1,195 @@
+<script setup>
+import { Html5QrcodeScanner, Html5Qrcode, Html5QrcodeSupportedFormats, Html5QrcodeScanType } from 'html5-qrcode'
+const router = useRouter()
+definePageMeta({
+  layout: 'scan'
+})
+
+let scanInstance = null; // 扫码实例
+let results = ref(null); // 扫码结果
+
+const initScanInstance = () => {
+  if (!scanInstance) {
+    // reader放置扫码功能的元素ID
+    scanInstance = new Html5Qrcode('qr-reader', {
+      formatsToSupport: [
+        Html5QrcodeSupportedFormats.QR_CODE,
+      ],
+    })
+  }
+}
+const openQrcode = async () => {
+  Html5Qrcode.getCameras()
+      .then(devices => {
+        if (devices && devices.length) {// 当前环境下能识别出摄像头,并且摄像头的数据可能不止一个
+          initScanInstance()
+          scanInstance.start(
+              {facingMode: "environment"},
+              {
+                focusMode: 'continuous',
+                fps: 10, // 可选,每n秒帧扫描一次
+                qrbox: { // 扫描的UI框
+                  width: 250,
+                  height: 250
+                },
+                videoConstraints: {
+                  // width: 375,
+                  // height: (window.visualViewport.height - 50),
+                  aspectRatio: window.visualViewport.height / window.visualViewport.width,
+                  facingMode: "environment",
+                }
+              },
+              (decodedText, decodedResult) => {
+                showToast('识别成功')
+                handleSuccess({decodedText, decodedResult})
+              },
+              (errorMessage, error) => {
+                handleFail(errorMessage)
+              }
+          )
+        }
+      })
+      .catch((err) => {
+        // 错误信息处理仅供参考,具体情况看输出!!!
+        let errorStr = ''
+        if (typeof err === "string") {
+          errorStr = err
+        } else {
+          if (err.name === "NotAllowedError")
+            errorStr = "您需要授予相机访问权限"
+          if (err.name === "NotFoundError") {
+            errorStr = "未检测到摄像头"
+          }
+          if (err.name === "NotSupportedError")
+            errorStr = "摄像头访问只支持在安全的上下文中,如https或localhost"
+          if (err.name === "NotReadableError") errorStr = "摄像头被占用"
+          if (err.name === "OverconstrainedError")
+            errorStr = "安装摄像头不合适"
+          if (err.name === "StreamApiNotSupportedError")
+            errorStr = "此浏览器不支持流API"
+        }
+        showToast(errorStr)
+      })
+}
+const scanLoadImg = (e) => {
+  try {
+    initScanInstance()
+    scanInstance.scanFile(e.file, false)
+        .then(result => {
+          // 二维码结果
+          console.log(result, '上传扫码成功')
+          handleSuccess(result)
+        })
+        .catch(err => {
+          handleFail(err)
+        })
+  } catch (e) {
+    console.error(e, '失败')
+  }
+}
+
+const getResults = (result) => {
+
+  if (!result) {
+    return {success: false, groupId: null, overTime: false}
+  }
+
+  const url = new URL(result);
+  const urlParams = new URLSearchParams(url.search);
+
+  const hasGroupId = urlParams.has('groupId');
+  const hasTime = urlParams.has('time');
+  console.log(url.search, hasGroupId, hasTime, 'hasTime')
+  if (!hasGroupId || !hasTime) {
+    return {success: false, groupId: null, overTime: false}
+  }
+
+  const givenDate = new Date(urlParams.get('time'));
+  const currentDate = new Date();
+  const givenDateCst = new Date(givenDate.getTime() + (8 * 60 * 60 * 1000));
+  const currentDateCst = new Date(currentDate.getTime() + (8 * 60 * 60 * 1000));
+
+  const diffInMilliseconds = currentDateCst - givenDateCst;
+  const sevenDaysInMilliseconds = 7 * 24 * 60 * 60 * 1000;
+
+  return {
+    success: true,
+    groupId: urlParams.get('groupId'),
+    overTime: diffInMilliseconds > sevenDaysInMilliseconds
+  }
+}
+
+const handleSuccess = (result) => {
+  results.value = result
+  router.replace({
+    path: '/chat/qr-results',
+    query: result ? getResults(result) : result
+  })
+}
+
+const handleFail = (err) => {
+  alert(err)
+/*  router.replace({
+    path: '/chat/qr-results',
+    query: {success: false, groupId: null, overTime: false}
+  })*/
+}
+
+const closeQrcode = () => {
+  if (scanInstance && scanInstance.isScanning) scanInstance.stop()
+  router.back()
+}
+
+onMounted(async () => {
+  await nextTick()
+  // initScanInstance()
+  await openQrcode()
+})
+onUnmounted(() => {
+  if (scanInstance && scanInstance.isScanning) scanInstance.stop()
+})
+
+</script>
+
+<template>
+  <div>
+    <div v-if="false" class="h-200">
+      {{ results }}
+    </div>
+    <div class="overlay">
+      <div class="absolute w-full z-30 flex flex-row items-center justify-center p-12">
+        <div class="absolute left-12 font-bold" @click="closeQrcode">
+          <span class="iconfont icon-left text-white"></span>
+        </div>
+        <div class="text-base text-[#fff] font-bold">
+          扫描二维码
+        </div>
+      </div>
+      <div class="relative qr-reader z-20" id="qr-reader"></div>
+      <p class="absolute w-full p-12 text-center bottom-100 z-30 text-sm text-[#fff]">请将二维码对准扫码框中心</p>
+      <div id="qr-code-file"
+           class="absolute w-54 h-54 grid place-items-center bottom-40 z-30 rounded-full bg-[#000]/80 text-white left-1/2 -translate-x-1/2">
+        <van-uploader
+            :preview-image="false"
+            :after-read="scanLoadImg"
+            accept="image/*"
+            :multiple="false"
+            :max-count="1"
+        ><img src="~/assets/img/scan/pic.png" height="32" width="32" alt=""/>
+        </van-uploader>
+      </div>
+    </div>
+  </div>
+</template>
+
+<style scoped lang="scss">
+.overlay {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  z-index: 999999;
+  width: 100%;
+  height: 100%;
+  background: rgba(0, 0, 0, 0.7);
+}
+</style>

+ 77 - 0
src/pages/scan/test/index.vue

@@ -0,0 +1,77 @@
+<template>
+  <div>
+    <div>{{res}}</div>
+    <!-- 扫描仪占位符 -->
+    <div id="reader"></div>
+  </div>
+</template>
+
+<script>
+import { Html5Qrcode } from "html5-qrcode"
+export default {
+  data() {
+    return {
+      res: null,
+      html5QrCode: null,
+    }
+  },
+  mounted() {
+    this.useCamera() // 打开相机
+  },
+  methods: {
+    // 关闭扫一扫页面,返回上一页
+    closed() {
+      this.html5QrCode.stop().finally(() => {
+        this.html5QrCode.clear()
+      })
+    },
+    scanRes(qr, err) {
+      this.res = qr
+    },
+    // 成功回调
+    onScanSuccess(qr) {
+      this.scanRes(qr)
+      this.closed()
+    },
+    useCamera() {
+      alert(1)
+      // 实例化,接收元素id作为参数
+      this.html5QrCode = new Html5Qrcode("reader")
+      // 获取相机设备
+      Html5Qrcode.getCameras()
+          .then(devices => {
+            // 扫码配置
+            const config = {
+              fps: 10, //  二维码扫描每秒帧数
+              qrbox: {
+                width: 300,
+                height: 300,
+              }, // UI框的大小
+              aspectRatio: 1.777778,
+            }
+            if (devices && devices.length) {
+              let cameraId = devices[devices.length - 1].id //后置摄像头,一般最后一个是后置摄像头
+              //let cameraId = devices[0].id //前置摄像头
+              this.html5QrCode
+                  .start({ deviceId: { exact: cameraId, }, }, config, this.onScanSuccess)
+                  .catch(err => {
+                    this.scanRes(undefined, err)
+                  })
+            } else {
+              // 如果没有找到设备,直接启用摄像头
+              //environment:后置摄像头  user:前置摄像头
+              this.html5QrCode
+                  .start( { facingMode: "environment" }, config, this.onScanSuccess )
+                  .catch(err => {
+                    alert('error')
+                    this.scanRes(undefined, err)
+                  })
+            }
+          })
+          .catch(err => {
+            this.scanRes(undefined, err)
+          })
+    },
+  },
+}
+</script>