钟铮锁App web部分 需要打包放进对应的安卓项目 生成apk 才能正常使用功能
he wei
2024-12-20 552a8341d159e463e2946074e21deddb185c90ee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
<script setup>
import { onMounted, ref } from "vue";
import { QrcodeStream, setZXingModuleOverrides } from "vue-qrcode-reader";
import { ElMessage } from "element-plus";
 
const error = ref("");
const cameraIsReady = ref(false);
const isSupportTorch = ref(false); // 是否支持闪光灯
const torch = ref(false); // 闪光灯状态
// 相机配置选项: 'user'|'environment' (默认:environment)
const selectedConstraints = ref({ facingMode: "environment" });
 
// 检测到二维码后绘制画布类型
function paintBoundingBox(detectedCodes, ctx) {
  for (const detectedCode of detectedCodes) {
    const {
      boundingBox: { x, y, width, height },
    } = detectedCode;
 
    ctx.lineWidth = 2;
    ctx.strokeStyle = "#007bff";
    // 绘制边框矩形
    ctx.strokeRect(x, y, width, height);
  }
}
 
async function onCameraReady(capabilities) {
  // NOTE: on iOS we can't invoke `enumerateDevices` before the user has given
  // camera access permission. `QrcodeStream` internally takes care of
  // requesting the permissions. The `camera-on` event should guarantee that this
  // has happened..
  console.log('camera ready', '=============');
  
  try {
    isSupportTorch.value = !!capabilities.torch;
    cameraIsReady.value = true;
    error.value = "";
  } catch (error) {
    onError(error);
    cameraIsReady.value = false;
  }
}
// 错误提示
function onError(err) {
  error.value = `[${err.name}]: `;
  if (err.name === "NotAllowedError") {
    error.value += "you need to grant camera access permission";
  } else if (err.name === "NotFoundError") {
    error.value += "no camera on this device";
  } else if (err.name === "NotSupportedError") {
    error.value += "secure context required (HTTPS, localhost)";
  } else if (err.name === "NotReadableError") {
    error.value += "is the camera already in use?";
  } else if (err.name === "OverconstrainedError") {
    error.value += "installed cameras are not suitable";
  } else if (err.name === "StreamApiNotSupportedError") {
    error.value += "Stream API is not supported in this browser";
  } else if (err.name === "InsecureContextError") {
    error.value +=
      "Camera access is only permitted in secure context. Use HTTPS or localhost rather than HTTP.";
  } else {
    error.value += err.message;
  }
  console.log('error', error.value, '=============');
  
  ElMessage.warning(error.value);
}
// 用户摄像头的流后
function onDetect(detectedCodes) {
  console.log('detectedCodes', detectedCodes, '=============');
  
  if (detectedCodes.length > 0) {
    onDecode(detectedCodes[0]?.rawValue);
  }
}
 
const emit = defineEmits(["on-success"]);
 
// 解码(交给父组件处理:进行网络请求)
function onDecode(text) {
  console.log('text', text, '=============');
  
  emit("on-success", text);
}
// 文件转成base64
const processFile = async (file) => {
    let reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = (e) => {
      let base64String = e.target?.result ||'';
      // 此处可对该base64进行获取赋值传入后端
      onDecode(base64String)
    };
};
</script>
 
<template>
  <div class="qrcode-scanner">
    <qrcode-stream
      class="qrcode-wrap"
      :torch="torch"
      v-memo="[torch]"
      :constraints="selectedConstraints"
      :track="paintBoundingBox"
      @error="onError"
      @detect="onDetect"
      @camera-on="onCameraReady"
    >
      <div v-if="isSupportTorch" class="torch-wrap">
        <div class="torch" @click="() => (torch = !torch)">
          <div class="flash-light" v-if="torch">
            灯灭了
          </div>
          <div class="flash-light" v-else>
           灯开了
          </div>
          {{ torch ? "关闭闪光灯" : "打开闪光灯" }}
        </div>
      </div>
    </qrcode-stream>
  </div>
</template>
 
<style scoped lang="less">
.qrcode-wrap {
  position: fixed !important;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: 1 !important;
  background: rgba(0, 0, 0, 0.5);
}
.torch-wrap {
  width: 18.75rem;
  height: 12.5rem;
  position: fixed !important;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -30%);
  z-index: 20;
}
 
.torch {
  position: fixed;
  bottom: -6.25rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 20;
  color: #fff;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.photo-wrap {
  position: fixed;
  bottom: 2.875rem;
  left: 2.875rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}
 
.photo {
  height: 3.125rem;
  width: 3.125rem;
  background-color: rgba(250, 250, 250, 0.8);
  border-radius: 50%;
  display: grid;
  place-items: center;
  cursor: pointer;
}
</style>