Vue3使用vue-qrcode-reader实现扫码绑定设备功能

需求描述

移动端进入网站后,登录网站进入设备管理界面。点击添加设备,可以选择直接添加或者扫一扫。点击扫一扫进行扫描二维码获取设备序列号自动填充到添加设备界面的序列号输入框中。然后点击完成进行设备绑定。

  1. 安装vue-qrcode-reader 这里使用的版本是5.5.7
npm install vue-qrcode-reader --save
  1. 扫一扫界面ScanCode.vue
<template>
  <div class="block-main">
    <div class="head-wrap">
      <img
        src="../../assets/images/mobile/icon-arrow-left.png"
        class="btn-back"
        @click="goback"
      />
      <span class="title">扫一扫</span>
    </div>
    <div class="qr-container">
      <qrcode-stream
        @detect="onDecode"
        @camera-on="onCameraReady"
        @error="onError"
      />
    </div>
  </div>
</template>

<script>
import { reactive, ref, onMounted } from "vue";
import { useRouter } from "vue-router";
import { QrcodeStream } from "vue-qrcode-reader";
import { showToast } from "vant";
export default {
  components: {
    QrcodeStream,
    showToast,
  },
  setup() {
    const testVice = reactive([]);
    const router = useRouter();
    // 扫码成功后的回调
    const onDecode = (detectedCodes) => {
      if (detectedCodes.length > 0) {
        // 跳转到添加设备页面并传递设备编号
        let deviceCode = detectedCodes[0].rawValue;
        router.replace({
          path: "/deviceadd",
          query: { deviceCode },
        });
      } else {
        showToast("扫码失败");
      }
    };
    const onCameraReady = (res) => {
      console.log("摄像头准备好了");
    };
    const onError = (error) => {
      if (error.name === "NotAllowedError") {
        // user denied camera access permission
        showToast("用户拒绝相机访问权限");
      } else if (error.name === "NotFoundError") {
        // no suitable camera device installed
        showToast("未安装合适的摄像设备");
      } else if (error.name === "NotSupportedError") {
        // page is not served over HTTPS (or localhost)
         showToast("当前网页没有通过 HTTPS 或 localhost 安全协议提供服务");
      } else if (error.name === "NotReadableError") {
        // maybe camera is already in use
        showToast("相机被占用了)");
      } else if (error.name === "OverconstrainedError") {
        // did you request the front camera although there is none?
         showToast("尝试使用前置摄像头)");
      } else if (error.name === "StreamApiNotSupportedError") {
        showToast("浏览器似乎缺少功能)");
        // browser seems to be lacking features
      }
    };
    onMounted(() => {
      navigator.mediaDevices
        .enumerateDevices()
        .then((devices) => {
          devices.forEach((device) => {
            if (device.kind === "videoinput") {
              console.log(
                "Video input device: ",
                device.label,
                device.deviceId
              );
            }
          });
        })
        .catch((error) => {
          console.error("Error enumerating devices: ", error);
          showToast("Error enumerating devices");
        });
    });
    const goback = () => {
      router.go(-1);
    };
    return {
      testVice,
      onCameraReady,
      goback,
      onDecode,
      onError,
    };
  },
};
</script>

<style lang="scss" scoped>
.block-main {
  height: 100%;
  background: #fff;
  overflow: hidden;
  font-size: 16px;
  .head-wrap {
    height: 0.96rem;
    background: #31be7c;
    font-family: Microsoft YaHei UI;
    font-weight: 400;
    color: #fff;
    display: flex;
    align-items: center;
    position: fixed;
    left: 0;
    right: 0;
    .btn-back {
      margin-left: 0.4rem;
      width: 0.22rem;
      height: 0.38rem;
    }
    .title {
      font-size: 0.36rem;
      text-align: center;
      flex: 1;
    }
  }
  .qr-container {
    display: flex;
    justify-content: center;
    align-items: center;
    height: calc(100vh - 0.96rem); // 减去头部的高度
    margin-top: 0.96rem;
  }
}
</style>
  1. 添加设备界面DeviceAdd.vue
<template>
  <div class="block-main">
    <div class="head-wrap">
      <a href="javascript:void(0)" class="btn-cancel" @click="goBack">取消</a>
      <span class="title"></span>
      <a href="javascript:void(0)" class="btn-sure" @click="deviceReg">完成</a>
    </div>
    <div class="input-wrap" @click="showDeviceType">
      <span class="input">{{ deviceInfo.devtypeName }}</span>
      <img
        src="../../assets/images/mobile/icon-arrow-right.png"
        class="icon-arrow"
      />
    </div>
    <div class="input-wrap">
      <input
        type="text"
        class="input"
        v-model="deviceInfo.devsn"
        placeholder="请输入设备序列号"
      />
      <img
        v-if="deviceInfo.devsn"
        src="../../assets/images/mobile/icon-close-gray.png"
        class="icon-close"
        @click="clearInput"
      />
    </div>
    <div class="error-msg">{{ deviceInfo.devsn_error }}</div>
    <van-popup v-model:show="deviceTypeDialog" position="bottom">
      <van-picker
        :columns="devTypes"
        v-model:value="deviceInfo.devtype"
        @cancel="deviceTypeDialog = false"
        @confirm="onConfirm"
      />
    </van-popup>
  </div>
</template>

<script>
import { ref, reactive, onMounted } from "vue";
import { useRoute,useRouter } from "vue-router";
import {
  Picker,
  Popup,
  showFailToast,
  showSuccessToast,
  showToast,
  showLoadingToast,
} from "vant";
import { device_Reg } from "../../api/auth";
export default {
  components: {
    "van-picker": Picker,
    "van-popup": Popup,
  },
  setup() {
    const route = useRoute();
    const deviceTypeDialog = ref(false);
    const router = useRouter();
    const devTypes = [
      { value: 1, text: "设备类型1" },
      { value: 2, text: "设备类型2" },
      { value: 3, text: "设备类型3" },
    ];
    const deviceInfo = reactive({
      devtype: null,
      devtypeName: "请选择需要绑定的设备",
      devsn: "",
      devsn_error: "",
    });
    const showDeviceType = () => {
      deviceTypeDialog.value = true;
    };
    const clearInput = () => {
      deviceInfo.devsn = "";
      deviceInfo.devsn_error = "";
    };
    const onConfirm = ({ selectedOptions }) => {
      deviceTypeDialog.value = false;
      deviceInfo.devtype = selectedOptions[0].value;
      deviceInfo.devtypeName = selectedOptions[0].text;
    };
    const goBack = () => {
      router.go(-1);
    };

    const deviceReg = async () => {
      if (deviceInfo.devtype == null) {
        deviceInfo.devsn_error = "请选择设备类型";
        return;
      }
      if (!deviceInfo.devsn) {
        deviceInfo.devsn_error = "请填写设备序列号";
        return;
      }
      const toast = showLoadingToast({
        message: "数据提交中...",
        forbidClick: true,
      });
      let response = await device_Reg({
        devsn: deviceInfo.devsn,
        devtype: deviceInfo.devtype,
      });
      if (response.isSuccess == true) {
        toast.close();
        showSuccessToast("设备绑定成功");
        setTimeout(() => {
          router.go(-1);
        }, 2000);
      } else {
        deviceInfo.devsn_error = response.message;
        toast.close();
      }
    };
    onMounted(() => {
      const scannedDeviceSn = route.query.deviceCode;
      if (scannedDeviceSn) {
        deviceInfo.devsn = scannedDeviceSn;
      }
    });
    return {
      devTypes,
      deviceTypeDialog,
      deviceInfo,
      showDeviceType,
      clearInput,
      onConfirm,
      goBack,
      deviceReg,
    };
  },
};
</script>

<style lang="scss" scoped>
.block-main {
  height: auto;
  overflow: hidden;
  .head-wrap {
    height: 0.96rem;
    background: #31be7c;
    font-family: Microsoft YaHei UI;
    font-weight: 400;
    color: #fff;
    display: flex;
    align-items: center;
    .btn-cancel {
      padding-left: 0.4rem;
      padding-right: 0.4rem;
      height: 0.96rem;
      line-height: 0.96rem;
      font-size: 0.36rem;
      color: #fff;
    }
    .title {
      font-size: 0.36rem;
      text-align: center;
      flex: 1;
    }
    .btn-sure {
      width: 1.15rem;
      height: 0.55rem;
      background: #ffffff;
      border-radius: 5px;
      font-size: 0.36rem;
      line-height: 0.55rem;
      margin-right: 0.4rem;
      margin-left: 0.4rem;
      color: #31be7c;
    }
  }
  .input-wrap {
    height: 1.2rem;
    line-height: 1.2rem;
    border-bottom: 1px solid #ced6d2;
    display: flex;
    align-items: center;
    .input {
      flex: 1;
      margin-left: 0.58rem;
      font-size: 0.3rem;
      width: 0px;
      border-style: none;
      outline: none;
      height: 1rem;
      text-align: left;
    }
    .icon-close {
      width: 0.36rem;
      height: 0.36rem;
      margin-right: 0.4rem;
      margin-left: 0.4rem;
    }
    .icon-arrow {
      width: 0.2rem;
      height: 0.3rem;
      margin-left: 0.04rem;
      margin-right: 0.4rem;
      margin-left: 0.4rem;
    }
  }
  .error-msg {
    padding-left: 0.58rem;
    margin-top: 0.19rem;
    font-size: 0.24rem;
    color: #ff6c00;
    padding-right: 0.58rem;
    text-align: left;
    line-height: 0.24rem;
  }
}
</style>

效果图

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: vue-qrcode-reader是一个基于Vue.js的条形码扫描组件。它为用户提供了在网页上扫描条形码的功能使用vue-qrcode-reader,我们需要先安装并导入组件。然后,我们可以在Vue的模板中使用组件,并通过设定相应的参数来调整扫描的设置。 该组件支持从摄像头扫描条形码,并可以将扫描到的条形码数据在网页展示出来。我们可以通过捕获组件的事件来获取扫描到的条形码数据,并进行后续的处理。 在使用vue-qrcode-reader的过程中,我们可以自定义组件的样式、设置摄像头的类型、调整扫描的精度等。此外,组件还提供了一些其他的参数,如自动开始扫描、扫描完成后是否暂停等,以便根据实际需求进行相应的调整。 使用vue-qrcode-reader可以方便地在Vue项目中实现条形码的扫描功能。它简化了扫描条形码的开发过程,提高了用户体验,并可以应用于各种需要条形码扫描的场景,如电商购物车、门禁系统等。 ### 回答2: vue-qrcode-reader是一个用于Vue.js的条形码扫描器插件。它基于QuaggaJS库,并提供简单易用的接口,让我们能够在Vue.js应用程序中轻松地集成条形码扫描功能使用vue-qrcode-reader非常简便。首先,我们需要安装该插件,可以在命令行中运行`npm install vue-qrcode-reader`来进行安装。安装完成后,可以在Vue组件中引入并注册该插件。 在使用vue-qrcode-reader之前,我们需要在页面中准备一个用于显示扫描结果的容器元素。可以使用一个`div`元素,并在其上绑定一个自定义的`class`或`id`,以便在Vue组件中引用。 然后,在Vue组件中,我们需要导入vue-qrcode-reader插件,并在`components`选项中进行注册。然后,我们可以在组件的`template`中使用插件提供的`Scanner`组件,来实现条形码的扫描功能。 在`Scanner`组件中,我们可以使用`@scan-success`事件来监听扫描成功的回调函数,并处理扫描到的条形码数据。我们还可以通过设置`@picker-active-red-line-color`属性来改变扫描框的红色边线颜色,以及使用`@activate-vibrate`属性来设置设备在扫描时是否震动反馈。 最后,在Vue组件中,我们可以使用`this.$refs.scanner.start`方法来启动条形码扫描,使用`this.$refs.scanner.stop`方法来停止条形码扫描。 总结而言,vue-qrcode-reader是一个方便易用的Vue.js条形码扫描器插件,可以轻松地集成到Vue.js应用程序中,实现条形码的扫描功能。 ### 回答3: vue-qrcode-reader 是一款基于 Vue.js 的扫码组件,可以用于扫描条形码。它使用了浏览器的摄像头,通过扫描条形码获取条形码的信息。 使用 vue-qrcode-reader 很简单,只需要在 Vue.js 的项目中导入该组件,并在需要扫描条形码的地方添加该组件即可。通过调用组件的方法,可以解析并获取扫描到的条形码信息。 在使用 vue-qrcode-reader 的时候,可以根据需要进行设置,如配置是否启用闪光灯、设置摄像头的分辨率等。扫描到条形码后,可以通过回调函数获取到扫描到的条形码的内容。 vue-qrcode-reader 提供了一套功能完善的 API,可以方便地进行二维码的扫描和解析。同时,它还支持多种条形码的解析,如 EAN、UPC、Code39 等。 总的来说,vue-qrcode-reader 是一款方便实用的扫码组件,可以在 Vue.js 项目中轻松实现条形码的扫描功能,为用户提供更加便捷的条形码操作体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值