|
|
@@ -0,0 +1,154 @@
|
|
|
+<template>
|
|
|
+ <view class="scan-page" :data-theme="'theme-' + (proxy.$settingStore.themeColor?.name || 'rf')">
|
|
|
+ <u-navbar
|
|
|
+ title="扫一扫"
|
|
|
+ :autoBack="true"
|
|
|
+ :placeholder="true"
|
|
|
+ :safeAreaInsetTop="true"
|
|
|
+ :bgColor="proxy.$settingStore.themeColor?.color || '#149eff'"
|
|
|
+ :titleStyle="{ color: '#fff' }"
|
|
|
+ >
|
|
|
+ <template #left>
|
|
|
+ <view class="u-navbar__content__left__item">
|
|
|
+ <u-icon name="arrow-left" size="20" color="#fff"></u-icon>
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
+ </u-navbar>
|
|
|
+
|
|
|
+ <!-- #ifdef H5 -->
|
|
|
+ <view class="scan-body">
|
|
|
+ <view id="reader" class="reader"></view>
|
|
|
+ <view class="tip">将二维码放入框内</view>
|
|
|
+ </view>
|
|
|
+ <!-- #endif -->
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { getCurrentInstance, onMounted, onUnmounted } from "vue";
|
|
|
+import { onShow, onUnload } from "@dcloudio/uni-app";
|
|
|
+// #ifdef H5
|
|
|
+import { Html5Qrcode } from "html5-qrcode";
|
|
|
+import { finishScanSuccess, finishScanFail, cancelScan } from "@/utils/oaScanCode.js";
|
|
|
+// #endif
|
|
|
+
|
|
|
+const { proxy } = getCurrentInstance();
|
|
|
+
|
|
|
+onShow(() => {
|
|
|
+ proxy.$settingStore.systemThemeColor([1]);
|
|
|
+});
|
|
|
+
|
|
|
+// #ifdef H5
|
|
|
+let scanner = null;
|
|
|
+let handled = false;
|
|
|
+
|
|
|
+function deliverResult(result) {
|
|
|
+ if (handled) return;
|
|
|
+ handled = true;
|
|
|
+ finishScanSuccess(result);
|
|
|
+}
|
|
|
+
|
|
|
+async function startScan() {
|
|
|
+ try {
|
|
|
+ scanner = new Html5Qrcode("reader");
|
|
|
+ await scanner.start(
|
|
|
+ { facingMode: "environment" },
|
|
|
+ {
|
|
|
+ fps: 10,
|
|
|
+ qrbox: { width: 250, height: 250 },
|
|
|
+ },
|
|
|
+ (decodedText) => {
|
|
|
+ scanner
|
|
|
+ ?.stop()
|
|
|
+ .then(() => {
|
|
|
+ scanner?.clear();
|
|
|
+ scanner = null;
|
|
|
+ deliverResult(decodedText);
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ deliverResult(decodedText);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ () => {}
|
|
|
+ );
|
|
|
+ } catch (e) {
|
|
|
+ uni.showToast({ title: "摄像头权限被拒", icon: "none" });
|
|
|
+ finishScanFail(e);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ startScan();
|
|
|
+});
|
|
|
+
|
|
|
+onUnload(() => {
|
|
|
+ cancelScan();
|
|
|
+});
|
|
|
+
|
|
|
+onUnmounted(() => {
|
|
|
+ if (scanner) {
|
|
|
+ scanner.stop().catch(() => {});
|
|
|
+ scanner.clear();
|
|
|
+ scanner = null;
|
|
|
+ }
|
|
|
+});
|
|
|
+// #endif
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.scan-page {
|
|
|
+ height: 100vh;
|
|
|
+ overflow: hidden;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ background-color: #000;
|
|
|
+}
|
|
|
+
|
|
|
+.scan-body {
|
|
|
+ position: relative;
|
|
|
+ width: 100%;
|
|
|
+ flex: 1;
|
|
|
+ min-height: 0;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.reader {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+
|
|
|
+ :deep(video) {
|
|
|
+ width: 100% !important;
|
|
|
+ height: 100% !important;
|
|
|
+ object-fit: cover;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(#qr-shaded-region) {
|
|
|
+ border-width: 0 !important;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.tip {
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ top: calc(50% + 137px);
|
|
|
+ z-index: 2;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 28rpx;
|
|
|
+ line-height: 1.5;
|
|
|
+ color: #fff;
|
|
|
+ pointer-events: none;
|
|
|
+ text-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.45);
|
|
|
+ animation: tip-breathe 2.2s ease-in-out infinite;
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes tip-breathe {
|
|
|
+ 0%,
|
|
|
+ 100% {
|
|
|
+ opacity: 0.35;
|
|
|
+ }
|
|
|
+ 50% {
|
|
|
+ opacity: 0.85;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|