周凯,个人博客

  • 前端
  • 嵌入式
  • 工具
  • 后端
  • 随笔
个人记录
  1. 首页
  2. 前端
  3. vue3
  4. 正文

vue3 h5端扫码

2024年 10月 12日 1048点热度 0人点赞 0条评论
  • 使用到的库

    • html5-qrcode
    • vant
    • vant
  • 实现代码
<template>
  <div>
    <van-dialog
      v-model:show="show"
      title="扫一扫"
      @close="closeDialog"
      :show-cancel-button="true"
      :show-confirm-button="false"
    >
      <div id="render" width="600px"></div>
    </van-dialog>
    <van-action-sheet
      v-model:show="showAction"
      :actions="actions"
      :title="t('comm.toast.selectCamera')"
      @select="onSelect"
      :cancel-text="t('comm.cancel')"
      close-on-click-action
    />
  </div>
</template>
<script lang="ts" setup>
import { useLanguage } from "@/hooks/useLanguage";
import logger from "@/utils/Logger";
import ToastUtil from "@/utils/ToastUtil";
import { Html5Qrcode } from "html5-qrcode";
import { ActionSheetAction } from "vant";
import { nextTick, ref } from "vue";

const { t } = useLanguage();

export interface IScanCodeExpose {
  scan(): void;
}

const emit = defineEmits(["scanTxt"]);

defineExpose<IScanCodeExpose>({
  scan,
});

// 设备列表
const showAction = ref(false);
const actions = ref<ActionSheetAction[]>([]);
const decodeTxt = ref("");

function onSelect(val: any) {
  logger.debug("选择项", val);
  const cameraId = val.value;
  show.value = true;
  nextTick(() => {
    html5QrCode.value = new Html5Qrcode("render", true);
    html5QrCode.value
      .start(
        cameraId,
        {
          fps: 10, // Optional, frame per seconds for qr code scanning
          qrbox: { width: 300, height: 300 }, // Optional, if you want bounded box UI
        },
        (decodedText, decodedResult) => {
          decodeTxt.value = decodedText;
          // do something when code is read
          logger.debug("decodedText", decodedText);
          logger.debug("decodedResult", decodedResult);
          stopCameraScan();
        },
        (errorMessage) => {
          // parse error, ignore it.
          logger.debug("errorMessage", errorMessage);
        },
      )
      .catch((err) => {
        // Start failed, handle it.
        logger.debug("err", err);
      });
  });
}

const show = ref(false);
const html5QrCode = ref<Html5Qrcode>();

function stopCameraScan() {
  // 停止 QR 码扫描
  html5QrCode.value
    ?.stop()
    .then(() => {
      logger.debug("QR Code scanning stopped.");
      show.value = false;
      html5QrCode.value?.clear();
      ToastUtil.successToast("扫码成功");
      emit("scanTxt", decodeTxt.value);
    })
    .catch((err) => {
      logger.debug("Failed to stop scanning:", err);
    });
}

function closeDialog() {
  logger.debug("点击了关闭");
  stopCameraScan();
  show.value = false;
}

function getCameraId() {
  Html5Qrcode.getCameras()
    .then((devices) => {
      /**
       * devices would be an array of objects of type:
       * { id: "id", label: "label" }
       */
      logger.debug("设备列表devices:", devices);
      actions.value = devices.map((item) => {
        return {
          name: item.label,
          value: item.id,
        };
      });
      showAction.value = true;
    })
    .catch((err) => {
      logger.error(err);
    })
    .finally(() => {
      ToastUtil.close();
    });
}

function scan() {
  logger.debug("打开扫码");

  ToastUtil.loading(t("comm.toast.loading"));
  getCameraId();
}
</script>
<style scoped lang="scss">
#reader {
  min-height: 200px;
}
</style>

🎯 拓展阅读提示

本文涉及的内容已同步至公众号后台,我会在那里分享更多深度内容和实用技巧

→ 点击关注:一行梦境

公众号二维码
本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: 暂无
最后更新:2024年 10月 12日

周凯

这个人很懒,什么都没留下

打赏 点赞
< 上一篇

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

COPYRIGHT © 2022-现在 周凯,个人博客. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

蒙ICP备18004897号