Houjie
2025-04-18 ae3855638dba0c927236c1a1b1a85d5b048c40e2
pages/spare/spare.vue
@@ -1,182 +1,145 @@
<template>
   <view class="container">
      <button class="scan" @click="openQrcode">点击扫码</button>
      <view class="reader-box" v-if="isScaning">
         <view class="reader" id="reader"></view>
   <view>
      <cu-custom :bgColor="NavBarColor" :isBack="true" backRouterName="index">
         <block slot="backText">返回</block>
         <block slot="content">扫一扫</block>
      </cu-custom>
      <view class="scanCode">
         <mumu-get-qrcode :continue="true" @success='qrcodeSucess' @error="qrcodeError"
            :definition="true"></mumu-get-qrcode>
      </view>
      <view>扫码内容:{{scanVal}}</view>
   </view>
</template>
<script>
   import {
      Html5Qrcode
   } from "html5-qrcode";
   import mumuGetQrcode from '@/uni_modules/mumu-getQrcode/components/mumu-getQrcode/mumu-getQrcode.vue';
   export default {
      components: {
         mumuGetQrcode // 注册
      },
      name: 'spare',
      watch: {
         cur: {
            immediate: true,
            handler() {
               console.log('watch', this.cur)
            },
         },
      },
      data() {
         return {
            html5QrCode: null,
            isScaning: false,
            cameraId: null,
            scanVal: ''
         }
            NavBarColor: this.NavBarColor,
            hasNavigated: false // 标记是否已经跳转
         };
      },
      methods: {
         isValidURL(url) {
            const pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
               '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
               '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
               '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
               '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
               '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
            return !!pattern.test(url);
         },
         checkURL() {
            const url = this.scanVal;
            if (this.isValidURL(url)) {
               uni.openURL({
                  url: url
               })
            } else {
               uni.showToast({
                  title: 'url地址错误,请重试',
                  icon: 'none',
                  duration: 2000
               });
            }
         },
      openQrcode() {
         this.isScaning = true;
         Html5Qrcode.getCameras().then((devices) => {
            if (devices && devices.length) {
               if (devices.length > 1) {
                  this.cameraId = devices[1].id;
               } else {
                  this.cameraId = devices[0].id;
               }
               this.html5QrCode = new Html5Qrcode('reader');
               this.startInit();
            }
         });
      },
      startInit() {
         const that = this;
         this.html5QrCode.start(
               this.cameraId, // retreived in the previous step.
               // {
               //    facingMode: "environment" //  environment后置摄像头 user前置摄像头
      // mounted() {
      //    window.addEventListener('hashchange', this.handleHashChange);
      //    // 初始解析 hash
      //    this.handleHashChange();
               // }, 
               {
                  fps: 10, // sets the framerate to 10 frame per second
                  qrbox: 250 // sets only 250 X 250 region of viewfinder to
      // beforeDestroy() {
      //    window.removeEventListener('hashchange', this.handleHashChange);
      // },
      methods: {
         // handleHashChange() {
         //    if (this.hasNavigated) {
         //       console.log('Already navigated, skipping hash change handling');
         //       return;
         //    }
         //    const hash = window.location.hash;
         //    console.log('Hash changed:', hash); // 添加日志
         //    if (!hash || hash.length === 0) {
         //       console.warn('Hash is empty or undefined');
         //       return;
         //    }
         //    const params = new URLSearchParams(hash.split('?')[1]);
         //    const equipmentId = params.get('equipmentId');
         //    console.log('Parsed equipmentId:', equipmentId); // 添加日志
         //    if (equipmentId) {
         //       this.navigateToDeviceDetails(equipmentId);
         //    } else {
         //       console.warn('No equipmentId found in hash');
         //    }
         // },
         navigateToDeviceDetails(equipmentId) {
            this.hasNavigated = true; // 标记已经跳转
            uni.navigateTo({
               url: `/pages/device/deviceWebDeils/deviceWebDeils?equipmentId=${encodeURIComponent(equipmentId)}`,
               success: () => {
                  console.log('Navigated to device details');
               },
               qrCodeMessage => {
               fail: (err) => {
                  console.error('Navigation failed:', err);
               }
            });
         },
         qrcodeSucess(data) { // 扫码成功
            setTimeout(() => {
               let equipmentId;
               try {
                  // 兼容性处理:优先使用URL和URLSearchParams,如果不可用则使用字符串解析
                  if ('URL' in window && 'URLSearchParams' in window) {
                     const url = new URL(data);
                     const params = new URLSearchParams(url.hash.slice(1).split('?')[1]);
                     equipmentId = params.get('equipmentId');
                  } else {
                     // 字符串解析方式
                     const hashIndex = data.indexOf('#');
                     if (hashIndex !== -1) {
                        const hashPart = data.substring(hashIndex + 1);
                        const paramIndex = hashPart.indexOf('?');
                        if (paramIndex !== -1) {
                           const paramStr = hashPart.substring(paramIndex + 1);
                           const pairs = paramStr.split('&');
                           for (let pair of pairs) {
                              const [key, value] = pair.split('=');
                              if (key === 'equipmentId') {
                                 equipmentId = value;
                                 break;
                              }
                           }
                        }
                     }
                  }
                  if (equipmentId) {
                     // 登录成功且获取到equipmentId,跳转到设备详情页面
                     this.navigateToDeviceDetails(equipmentId);
                  } else {
                  uni.showModal({
                     title: 'success',
                     content: JSON.stringify(qrCodeMessage),
                        title: '提示',
                        content: "二维码中未找到有效的equipmentId",
                     showCancel: false
                  });
                  // do something when code is read. For example:
                  if (qrCodeMessage) {
                     //成功扫出码qrCodeMessage为扫码内容
                     //扫码成功记得关掉摄像
                     that.action(qrCodeMessage) //对二维码逻辑处理
                     that.stopScan(); //关闭扫码功能
                  }
               } catch (error) {
                  uni.showModal({
                     title: '错误',
                     content: "解析URL出错,请检查二维码内容",
                     showCancel: false
                  });
               }
            }, 200); // 增加100毫秒的延迟
               },
               errorMessage => {
                  console.log('errorMessage', errorMessage);
                  if (errorMessage.includes('NotFoundException')) {
                     uni.showToast({
                        title: '未找到二维码,请重新对准',
                        icon: 'none',
                        duration: 2000
                     });
                  } else {
                     uni.showToast({
                        title: '扫码失败,请重试',
                        icon: 'none',
                        duration: 2000
         qrcodeError(err) { // 扫码失败
            uni.showModal({
               title: '摄像头授权失败',
               content: '摄像头授权失败,请检测当前浏览器是否有摄像头权限。',
               success: () => {
                  uni.navigateBack({}); // 返回到上一页
               }
                     });
                  }
               }
            )
            .catch((err) => {
               // 扫码错误信息
               let message = "";
               if (typeof err == "string") {
                  message = "识别失败";
               } else {
                  if (err.name == "NotAllowedError") {
                     message = "您需要授予相机访问权限!";
                  }
                  if (err.name == "NotFoundError") {
                     message = "这个设备上没有摄像头!";
                  }
                  if (err.name == "NotSupportedError") {
                     message =
                        "摄像头访问只支持在安全的上下文中,如https或localhost!";
                  }
                  if (err.name == "NotReadableError") {
                     message = "相机被占用!";
                  }
                  if (err.name == "OverconstrainedError") {
                     message = "安装摄像头不合适!";
                  }
                  if (err.name == "StreamApiNotSupportedError") {
                     message = "此浏览器不支持流API!";
                  }
               }
               uni.showToast({
                  title: message,
                  icon: 'none',
                  duration: 2000
               });
            });
      },
      action(val) {
         this.scanVal = val;
         const url = this.scanVal;
         this.checkURL(url)
         // plus.runtime.openURL(this.scanVal, function(res) {
         //    console.log(res);
         // });
      },
      stopScan() {
         console.log('停止扫码')
         this.isScaning = false;
         if (this.html5QrCode) {
            this.html5QrCode.stop()
               .then((ignore) => {
                  console.log("停止扫码", ignore);
               })
               .catch((err) => {
                  console.log(err);
                  showToast("停止扫码失败");
               });
         }
      },
   }
   }
   };
</script>
<style>
   .container {
   .scanCode {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      z-index: 99;
      height: 100%;
      width: 100%;
      background-color: rgba(0, 0, 0, 0.7);
   }
   .reader-box {