首页、学情、任务绑定接口
This commit is contained in:
+43
-32
@@ -16,11 +16,6 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// #ifdef WEB
|
||||
import { BrowserQRCodeReader } from '@zxing/browser'
|
||||
import type { IScannerControls } from '@zxing/browser'
|
||||
// #endif
|
||||
|
||||
type Props = {
|
||||
cooldown?: number
|
||||
active?: boolean
|
||||
@@ -39,10 +34,10 @@
|
||||
let lastScannedAt = 0
|
||||
// #ifdef WEB
|
||||
const videoContainerId = `qr-scanner-${Date.now()}`
|
||||
let scannerControls: IScannerControls | null = null
|
||||
let scanVideo: HTMLVideoElement | null = null
|
||||
let scanStream: MediaStream | null = null
|
||||
let isPageActive = false
|
||||
let restartTimer: number | null = null
|
||||
let scanTimer: number | null = null
|
||||
// #endif
|
||||
|
||||
function emitScan(result: string) {
|
||||
@@ -77,7 +72,7 @@
|
||||
}
|
||||
|
||||
async function startWebScanner() {
|
||||
if (!isPageActive || !props.active || scannerControls != null) return
|
||||
if (!isPageActive || !props.active || scanStream != null) return
|
||||
const video = getScanVideo()
|
||||
if (video == null) {
|
||||
handleCameraError()
|
||||
@@ -85,39 +80,55 @@
|
||||
}
|
||||
|
||||
try {
|
||||
const reader = new BrowserQRCodeReader()
|
||||
scannerControls = await reader.decodeFromConstraints(
|
||||
{ video: { facingMode: 'environment' } },
|
||||
video,
|
||||
(result, _error, controls) => {
|
||||
if (!result) return
|
||||
controls.stop()
|
||||
scannerControls = null
|
||||
emitScan(result.getText())
|
||||
scheduleRestart()
|
||||
}
|
||||
)
|
||||
const BarcodeDetectorClass = (window as any).BarcodeDetector
|
||||
if (BarcodeDetectorClass == null || navigator.mediaDevices == null) {
|
||||
handleCameraError()
|
||||
return
|
||||
}
|
||||
|
||||
scanStream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' } })
|
||||
video.srcObject = scanStream
|
||||
await video.play()
|
||||
const detector = new BarcodeDetectorClass({ formats: ['qr_code'] })
|
||||
void scanWebFrame(detector)
|
||||
} catch (_error) {
|
||||
stopWebScanner()
|
||||
handleCameraError()
|
||||
}
|
||||
}
|
||||
|
||||
function scheduleRestart() {
|
||||
if (!isPageActive || !props.active || restartTimer != null) return
|
||||
restartTimer = setTimeout(() => {
|
||||
restartTimer = null
|
||||
void startWebScanner()
|
||||
}, props.cooldown)
|
||||
async function scanWebFrame(detector: any) {
|
||||
if (!isPageActive || !props.active || scanVideo == null || scanStream == null) return
|
||||
|
||||
try {
|
||||
const results = await detector.detect(scanVideo)
|
||||
if (results.length > 0) {
|
||||
emitScan(results[0].rawValue as string)
|
||||
}
|
||||
} catch (_error) {
|
||||
handleCameraError()
|
||||
return
|
||||
}
|
||||
|
||||
scanTimer = setTimeout(() => {
|
||||
scanTimer = null
|
||||
void scanWebFrame(detector)
|
||||
}, 250)
|
||||
}
|
||||
|
||||
function stopWebScanner() {
|
||||
if (restartTimer != null) {
|
||||
clearTimeout(restartTimer)
|
||||
restartTimer = null
|
||||
if (scanTimer != null) {
|
||||
clearTimeout(scanTimer)
|
||||
scanTimer = null
|
||||
}
|
||||
if (scannerControls != null) {
|
||||
scannerControls.stop()
|
||||
scannerControls = null
|
||||
if (scanStream != null) {
|
||||
scanStream.getTracks().forEach((track) => {
|
||||
track.stop()
|
||||
})
|
||||
scanStream = null
|
||||
}
|
||||
if (scanVideo != null) {
|
||||
scanVideo.srcObject = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user