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"><imgsrc="../../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 permissionshowToast("用户拒绝相机访问权限");} else if (error.name === "NotFoundError") {// no suitable camera device installedshowToast("未安装合适的摄像设备");} 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 useshowToast("相机被占用了)");} 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><imgsrc="../../assets/images/mobile/icon-arrow-right.png"class="icon-arrow"/></div><div class="input-wrap"><inputtype="text"class="input"v-model="deviceInfo.devsn"placeholder="请输入设备序列号"/><imgv-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>
效果图

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/421861.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024.9.11 作业

绘制组件制作时钟 代码&#xff1a; /*******************************************/ 文件名&#xff1a;widget.h /*******************************************/ #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPaintEvent> #include &l…

MAX3483ESA+T具有±15kV ESD保护的+3.3V、低功耗收发器,适用于RS-485和RS-422通信

MAX3483ESAT具有15kV ESD保护的3.3V、低功耗收发器&#xff0c;适用于RS-485和RS-422通信。每个器件包含一个驱动器和一个接收器。MAX3483ESAT具有限摆率驱动器&#xff0c;可充分降低EMI并减少因电缆端接不当引起的反射&#xff0c;从而实现数据速率高达250kbps的无误差数据传…

【中间件】-容器编排平台Kubernetes简介

目录 什么是K8s 为什么需要K8s 什么是容器(Contianer) K8s能做什么&#xff1f; K8s的架构原理 控制平面(Control plane) kube-apiserver etcd kube-scheduler kube-controller-manager cloud-controller-manager 小结 节点组件(Node) container runtime Pod kubelet ku…

AnyChart 数据可视化框架

AnyChart 数据可视化框架 AnyChart 是一个灵活的 JavaScript&#xff08;HTML5、SVG、VML&#xff09;图表框架&#xff0c;适合任何需要数据可视化的解决方案。 目录 下载并安装开始插件将 AnyChart 与 TypeScript 结合使用将 AnyChart 与 ECMAScript 6 结合使用技术集成贡献…

Anolis OS 7.9(龙蜥操作系统)上Oracle12C Release 2 (12.2)打补丁

本文的oracle使用的是单实例环境 一、打补丁前环境准备 1、确保make, ar, ld,和 nm四个可执行命令在$PATH中 export PATH$PATH:/bin2、查看已装的Oracle的OPatch版本 #切换到oracle用户 su - oracle#进入到数据库的安装目录下的opatch目录 cd /ora01/app/oracle/product/12…

JS_函数声明

JS中的方法,多称为函数,函数的声明语法和JAVA中有较大区别 函数说明 函数没有权限控制符不用声明函数的返回值类型,需要返回在函数体中直接return即可,也无需void关键字参数列表中,无需数据类型调用函数时,实参和形参的个数可以不一致声明函数时需要用function关键字函数没有…

github actions CICD简单使用案例

参考&#xff1a; https://developer.aliyun.com/article/1540773 https://github.com/ViggoZ/producthunt-daily-hot/blob/main/.github/workflows/generate_markdown.yml 1、创建github项目 目录&#xff1a; .github/workflows/fetch-news.yml actions执行yaml&#xff08;…

C语言 | Leetcode C语言题解之第397题整数替换

题目&#xff1a; 题解&#xff1a; //第一种动态规划:超时 // class Solution { // public: // int integerReplacement(int n) { // vector<int>dp(n1,0); // dp[1]0; // for(int i2;i<n;i){ // if(i%20){ // …

Vue接入高德地图并实现基本的路线规划功能

目录 一、申请密钥 二、安装依赖 三、代码实现 四、运行截图 五、官方文档 一、申请密钥 登录高德开放平台&#xff0c;点击我的应用&#xff0c;先添加新应用&#xff0c;然后再添加Key。 如图所示填写对应的信息&#xff0c;系统就会自动生成。 二、安装依赖 npm i am…

学生签到系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;学生管理&#xff0c;教师管理&#xff0c;签到信息管理&#xff0c;学生签到管理&#xff0c;班课信息管理&#xff0c;加入班课管理&#xff0c;课程信息管理 微信端账号功能包括&#xff1a;系统首…

C++(三)----内存管理

1.C/C内存分布 看下面这个问题&#xff08;考考你们之前学的咋样&#xff09;&#xff1a; int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] {1, 2, 3, 4};char char2[] "abcd";char* pCh…

JDK 安装及配置教程(Windows)【安装】

文章目录 一、 下载1. 官网下载2. 其它渠道 二、 安装三、 配置四、 验证五、 双 JDK 环境 软件 / 环境安装及配置目录 一、 下载 1. 官网下载 安装地址&#xff1a;https://www.oracle.com/ 打开浏览器输入网址 https://www.oracle.com/index.html&#xff0c;进入 Oracle …

Python——turtle库(海龟绘图)介绍与使用

一、概述 在 Python 中&#xff0c;海龟绘图提供了一个实体“海龟”形象&#xff08;带有画笔的小机器动物&#xff09;&#xff0c;假定它在地板上平铺的纸张上画线。 二、运行环境 本文运行环境&#xff1a;Windows11&#xff0c;Python3.11&#xff0c;Pycharm2023.1.4 使…

哈佛斯坦福大学团队联合发布病理基础模型CHIEF,全面提升癌症诊断的准确性|顶刊精析·24-09-12

小罗碎碎念 今日顶刊&#xff1a;Nature 今天精读的这篇文章于24-09-04发表于Nature&#xff0c;作者来自哈佛大学、斯坦福大学。 作者角色作者姓名单位名称&#xff08;英文&#xff09;单位名称&#xff08;中文&#xff09;第一作者Xiyue WangDepartment of Biomedical Info…

如何快速清理Docker中的停止容器?

如何快速清理Docker中的停止容器? 方法一:使用`docker container prune`方法二:结合`docker ps`和`docker rm`注意(这些命令慎用,确定容器不需要之后再执行)💖The Begin💖点点关注,收藏不迷路💖 Docker容器在停止后可能会占用不必要的磁盘空间。如何清理这些停止的…

k8s以及prometheus

#生成控制器文件并建立控制器 [rootk8s-master ~]# kubectl create deployment bwmis --image timinglee/myapp:v1 --replicas 2 --dry-runclient -o yaml > bwmis.yaml [rootk8s-master ~]# kubectl expose deployment bwmis --port 80 --target-port 80 --dry-runclient…

第 9 章图像分割

图像分割是将一幅图像分割成有意义区域的过程。区域可以是图像的前景与背景或图像中一些单独的对象。这些区域可以利用一些诸如颜色、边界或近邻相似性等特征进行构建。本章中&#xff0c;我们将看到一些不同的分割技术。 9.1 图割&#xff08;Graph Cut&#xff09; 图论中的…

Hive中的分区表与分桶表详解

目录 分区表和分桶表 分区表 分区表基本语法 1. 创建分区表 2. 分区表读写数据 1&#xff09;写数据 &#xff08;1&#xff09;LOAD &#xff08;2&#xff09;INSERT 2&#xff09;读数据 3. 分区表基本操作 1&#xff09;查看所有分区信息 2&#xff09;增加分区 …

iOS 知识点记录

王巍 博客地址&#xff1a;OneVs Den git地址&#xff1a;onevcat (Wei Wang) GitHub 江湖人称喵神&#xff0c;目前就职于line。喵神的博客涉及方面比较广, 有Obejctive-C, Swift, SwiftUI, Unity等等。博客内容很有深度&#xff0c;非常值得关注。 戴铭 博客地址&#xff1…

ctf.show靶场ssrf攻略

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 web351 解析:post传入url参数他就会访问。 解法: hackbar传入url参数写入https://127.0.0.1/flag.php web352 解析:post传入url参数&#xff0c;不能是127.0.0.1和localhost 解法:缩写127.1传入 web353 解析…