最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue3使用vue-qrcode-reader實現(xiàn)掃碼綁定設(shè)備功能(推薦)

 更新時間:2024年10月21日 10:02:55   作者:魚是一只魚啊  
本文介紹了在Vue3中使用vue-qrcode-reader版本5.5.7來實現(xiàn)移動端的掃碼綁定設(shè)備功能,用戶通過掃描二維碼自動獲取設(shè)備序列號,并填充到添加設(shè)備界面,完成設(shè)備綁定的全過程,包含ScanCode.vue和DeviceAdd.vue兩個主要界面的實現(xiàn)方式

需求描述

移動端進入網(wǎng)站后,登錄網(wǎng)站進入設(shè)備管理界面。點擊添加設(shè)備,可以選擇直接添加或者掃一掃。點擊掃一掃進行掃描二維碼獲取設(shè)備序列號自動填充到添加設(shè)備界面的序列號輸入框中。然后點擊完成進行設(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è)備編號
        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("用戶拒絕相機訪問權(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("相機被占用了)");
      } 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="請輸入設(shè)備序列號"
      />
      <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: "請選擇需要綁定的設(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 = "請選擇設(shè)備類型";
        return;
      }
      if (!deviceInfo.devsn) {
        deviceInfo.devsn_error = "請?zhí)顚懺O(shè)備序列號";
        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實現(xiàn)掃碼綁定設(shè)備功能的文章就介紹到這了,更多相關(guān)Vue3掃碼綁定設(shè)備內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vuejs實現(xiàn)購物車功能

    Vuejs實現(xiàn)購物車功能

    這篇文章主要為大家詳細(xì)介紹了Vuejs實現(xiàn)購物車功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Vue項目接入Paypal實現(xiàn)示例詳解

    Vue項目接入Paypal實現(xiàn)示例詳解

    這篇文章主要介紹了Vue項目接入Paypal實現(xiàn)示例詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • vue子組件設(shè)計provide和inject理解使用

    vue子組件設(shè)計provide和inject理解使用

    這篇文章主要為大家介紹了vue子組件設(shè)計provide和inject理解及使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • vue子組件通過.sync修飾符修改props屬性方式

    vue子組件通過.sync修飾符修改props屬性方式

    這篇文章主要介紹了vue子組件通過.sync修飾符修改props屬性方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • Vue.js 60分鐘輕松入門

    Vue.js 60分鐘輕松入門

    Vue.js提供了簡潔、易于理解的API,幫助大家快速靈活掌握Vue.js。這篇文章主要介紹了如何在60分鐘內(nèi)輕松學(xué)習(xí)Vue.js,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Vue封裝DateRangePicker組件流程詳細(xì)介紹

    Vue封裝DateRangePicker組件流程詳細(xì)介紹

    在后端管理項目中使用vue來進行前端項目的開發(fā),但我們都知道Vue實際上無法監(jiān)聽由第三方插件所引起的數(shù)據(jù)變化。也無法獲得JQuery這樣的js框架對元素值的修改的。而日期控件daterangepicker又基于JQuery來實現(xiàn)的
    2022-11-11
  • vue學(xué)習(xí)筆記之v-if和v-show的區(qū)別

    vue學(xué)習(xí)筆記之v-if和v-show的區(qū)別

    本篇文章主要介紹了vue學(xué)習(xí)筆記之v-if和v-show的區(qū)別,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • 一次前端Vue項目國際化解決方案的實戰(zhàn)記錄

    一次前端Vue項目國際化解決方案的實戰(zhàn)記錄

    這篇文章主要給大家介紹了關(guān)于前端Vue項目國際化解決方案的實戰(zhàn)記錄,以上只是一部分Vue項目開發(fā)中遇到的典型問題和解決方案,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-07-07
  • Vue實現(xiàn)導(dǎo)航欄菜單

    Vue實現(xiàn)導(dǎo)航欄菜單

    這篇文章主要為大家詳細(xì)介紹了Vue實現(xiàn)導(dǎo)航欄菜單,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-08-08
  • 解決父子組件通信的三種Vue插槽

    解決父子組件通信的三種Vue插槽

    這篇文章主要為大家介紹了Vue插槽解決父子組件通信,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11

最新評論

金乡县| 石景山区| 城步| 寿光市| 格尔木市| 石屏县| 澄城县| 廊坊市| 开远市| 永州市| 江北区| 永福县| 额济纳旗| 开远市| 板桥市| 西丰县| 特克斯县| 卓尼县| 永年县| 西畴县| 泰安市| 饶河县| 汉川市| 攀枝花市| 阿图什市| 沛县| 敦化市| 灵璧县| 天长市| 林口县| 扎鲁特旗| 惠来县| 夏邑县| 客服| 正宁县| 淮滨县| 鄱阳县| 保靖县| 吉林省| 将乐县| 玛沁县|