/** * QR码扫描器 * @邠心vbe on 2026/04/21 */ import React, { useEffect, useState } from 'react'; import { Pressable, StyleSheet, View } from 'react-native'; import TextView from '../../components/TextView'; import { Camera, useCameraDevice, useCodeScanner } from 'react-native-vision-camera'; import { check, PERMISSIONS, RESULTS } from 'react-native-permissions'; import utils from '../../utils/utils'; const checkPermission = (back) => { if (isIOS) { back(true); } else { check(PERMISSIONS.ANDROID.CAMERA).then(res => { console.log('checkPermission', res); switch (res) { case RESULTS.DENIED://权限未被请求/被拒绝,但可以请求 back(false); break; case RESULTS.LIMITED://权限是有限的:有些操作是可能的 back(true); break; case RESULTS.GRANTED://许可被授予 back(true); break; case RESULTS.BLOCKED://权限被拒绝,不再可请求 back(false); break; default: back(false); break; } }).catch(err => { back(false); }) } } const QRScanner = ({ onResult, isActive }) => { const [flashOn, switchFlash] = useState(false); const [hasPermission, setHasPermission] = useState(false); const [permissionStr, setPermissionStr] = useState(""); const device = useCameraDevice('back'); useEffect(() => { console.log("相机设备", device); checkPermission(result => { setHasPermission(result); }) Camera.requestCameraPermission().then(res => { setPermissionStr(res); utils.logEventTracking("scan_camera_permission", res) if (!hasPermission) { setHasPermission(res == 'granted'); } }).catch(err => { console.warn("相机权限请求错误", err); utils.logEventTracking("scan_camera_permission_error", err) }); }, []); const codeScanner = useCodeScanner({ codeTypes: ['qr'], onCodeScanned: (codes) => { if (codes && codes.length > 0) { onResult(codes) } }, }); if (!device || !hasPermission) { return ( {!hasPermission ? "Camera access has been denied. Please enable it in your device settings.(E0)" : "Can not find camera device.(E1)"} ) } return ( <> { isActive && switchFlash(!flashOn)}> {permissionStr} } ); }; export default QRScanner; const styles = StyleSheet.create({ tipsScreen: { top: 0, left: 0, right: 0, bottom: 0, position: 'absolute', alignItems: "center", justifyContent: "center", backgroundColor: '#111', }, tipsText: { color: textLight, fontSize: 14, textAlign: "center" }, flashLight: { bottom: 120, zIndex: 2, opacity: 0.7, padding: 8, position: 'absolute' } })