Vue3使用vue-qrcode-reader實(shí)現(xiàn)掃碼綁定設(shè)備功能(推薦)
需求描述
移動(dòng)端進(jìn)入網(wǎng)站后,登錄網(wǎng)站進(jìn)入設(shè)備管理界面。點(diǎn)擊添加設(shè)備,可以選擇直接添加或者掃一掃。點(diǎn)擊掃一掃進(jìn)行掃描二維碼獲取設(shè)備序列號(hào)自動(dòng)填充到添加設(shè)備界面的序列號(hào)輸入框中。然后點(diǎn)擊完成進(jìn)行設(shè)備綁定。
安裝vue-qrcode-reader 這里使用的版本是5.5.7
npm install vue-qrcode-reader --save
掃一掃界面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(); // 掃碼成功后的回調(diào) const onDecode = (detectedCodes) => { if (detectedCodes.length > 0) { // 跳轉(zhuǎn)到添加設(shè)備頁面并傳遞設(shè)備編號(hào) let deviceCode = detectedCodes[0].rawValue; router.replace({ path: "/deviceadd", query: { deviceCode }, }); } else { showToast("掃碼失敗"); } }; const onCameraReady = (res) => { console.log("攝像頭準(zhǔn)備好了"); }; const onError = (error) => { if (error.name === "NotAllowedError") { // user denied camera access permission showToast("用戶拒絕相機(jī)訪問權(quán)限"); } else if (error.name === "NotFoundError") { // no suitable camera device installed showToast("未安裝合適的攝像設(shè)備"); } else if (error.name === "NotSupportedError") { // page is not served over HTTPS (or localhost) showToast("當(dāng)前網(wǎng)頁沒有通過 HTTPS 或 localhost 安全協(xié)議提供服務(wù)"); } else if (error.name === "NotReadableError") { // maybe camera is already in use showToast("相機(jī)被占用了)"); } 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>
添加設(shè)備界面DeviceAdd.vue
<template> <div class="block-main"> <div class="head-wrap"> <a href="javascript:void(0)" rel="external nofollow" rel="external nofollow" class="btn-cancel" @click="goBack">取消</a> <span class="title"></span> <a href="javascript:void(0)" rel="external nofollow" rel="external nofollow" 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="請(qǐng)輸入設(shè)備序列號(hào)" /> <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: "設(shè)備類型1" }, { value: 2, text: "設(shè)備類型2" }, { value: 3, text: "設(shè)備類型3" }, ]; const deviceInfo = reactive({ devtype: null, devtypeName: "請(qǐng)選擇需要綁定的設(shè)備", 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 = "請(qǐng)選擇設(shè)備類型"; return; } if (!deviceInfo.devsn) { deviceInfo.devsn_error = "請(qǐng)?zhí)顚懺O(shè)備序列號(hào)"; return; } const toast = showLoadingToast({ message: "數(shù)據(jù)提交中...", forbidClick: true, }); let response = await device_Reg({ devsn: deviceInfo.devsn, devtype: deviceInfo.devtype, }); if (response.isSuccess == true) { toast.close(); showSuccessToast("設(shè)備綁定成功"); 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>
效果圖
到此這篇關(guān)于Vue3使用vue-qrcode-reader實(shí)現(xiàn)掃碼綁定設(shè)備功能的文章就介紹到這了,更多相關(guān)Vue3掃碼綁定設(shè)備內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue使用v-viewer實(shí)現(xiàn)圖片預(yù)覽
這篇文章主要為大家詳細(xì)介紹了Vue使用v-viewer實(shí)現(xiàn)圖片預(yù)覽,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10Element-Plus表格實(shí)現(xiàn)Table自定義合并行數(shù)據(jù)
在開發(fā)項(xiàng)目中,我們時(shí)常會(huì)用到表格,許多需求可能會(huì)要求自定義特定的行或列,下面就跟隨小編一起來學(xué)習(xí)一下在實(shí)際開發(fā)中如何實(shí)現(xiàn)這一要求吧2024-12-12vuejs實(shí)現(xiàn)折疊面板展開收縮動(dòng)畫效果
這篇文章主要介紹了vuejs實(shí)現(xiàn)折疊面板展開收縮動(dòng)畫效果,文中通過代碼給大家分享兩種情況介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-09-09解決iView中時(shí)間控件選擇的時(shí)間總是少一天的問題
下面小編就為大家分享一篇解決iView中時(shí)間控件選擇的時(shí)間總是少一天的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-03-03vue3項(xiàng)目打包成apk(android)詳細(xì)圖文教程
Vue本身是一個(gè)構(gòu)建用戶界面的漸進(jìn)式框架,不能直接打包成APK文件,但是你可以使用工具將Vue應(yīng)用打包成一個(gè)可以在Android設(shè)備上安裝的APK文件,這篇文章主要給大家介紹了關(guān)于vue3項(xiàng)目打包成apk(android)的相關(guān)資料,需要的朋友可以參考下2024-05-05