双端适配,web端的修改父容器和接口

This commit is contained in:
2026-03-29 02:34:13 +08:00
parent 3c071957ce
commit ebb0c003e3
16 changed files with 1419 additions and 226 deletions

View File

@@ -7,8 +7,8 @@ import {
Alert,
Modal,
Dimensions,
Platform,
} from 'react-native';
import { CameraView, useCameraPermissions } from 'expo-camera';
import { useRouter } from 'expo-router';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import * as hrefs from '../../navigation/hrefs';
@@ -133,22 +133,74 @@ function createQrScannerStyles(colors: AppColors) {
fontSize: fontSizes.md,
fontWeight: '600',
},
webNotSupportedContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: spacing.xl,
backgroundColor: '#000',
},
webNotSupportedText: {
marginTop: spacing.lg,
fontSize: fontSizes.md,
color: 'rgba(255,255,255,0.72)',
textAlign: 'center',
lineHeight: 24,
},
});
}
export const QRCodeScanner: React.FC<QRCodeScannerProps> = ({ visible, onClose }) => {
// Web 端不支持扫码组件
const QRCodeScannerWeb: React.FC<QRCodeScannerProps> = ({ visible, onClose }) => {
const themeColors = useAppColors();
const styles = useMemo(() => createQrScannerStyles(themeColors), [themeColors]);
return (
<Modal visible={visible} animationType="slide" onRequestClose={onClose}>
<View style={styles.container}>
<View style={styles.header}>
<TouchableOpacity onPress={onClose} style={styles.closeButton}>
<MaterialCommunityIcons name="close" size={24} color="#fff" />
</TouchableOpacity>
<Text style={styles.headerTitle}></Text>
<View style={styles.placeholder} />
</View>
<View style={styles.webNotSupportedContainer}>
<MaterialCommunityIcons name="web-off" size={64} color="rgba(255,255,255,0.5)" />
<Text style={styles.webNotSupportedText}>
使{'\n'}
App
</Text>
<TouchableOpacity style={styles.permissionButton} onPress={onClose}>
<Text style={styles.permissionButtonText}></Text>
</TouchableOpacity>
</View>
</View>
</Modal>
);
};
// 原生端扫码组件
const QRCodeScannerNative: React.FC<QRCodeScannerProps> = ({ visible, onClose }) => {
const router = useRouter();
const themeColors = useAppColors();
const styles = useMemo(() => createQrScannerStyles(themeColors), [themeColors]);
const [permission, requestPermission] = useCameraPermissions();
// 动态导入 expo-camera避免 Web 端加载
const [cameraModule, setCameraModule] = useState<typeof import('expo-camera') | null>(null);
const [permission, setPermission] = useState<any>(null);
const [scanned, setScanned] = useState(false);
useEffect(() => {
if (visible) {
setScanned(false);
if (!permission?.granted) {
requestPermission();
}
if (visible && Platform.OS !== 'web') {
import('expo-camera').then((module) => {
setCameraModule(module);
const [perm, requestPerm] = module.useCameraPermissions();
setPermission(perm);
if (!perm?.granted) {
requestPerm();
}
});
}
}, [visible]);
@@ -178,7 +230,7 @@ export const QRCodeScanner: React.FC<QRCodeScannerProps> = ({ visible, onClose }
}
};
if (!permission?.granted) {
if (!cameraModule || !permission?.granted) {
return (
<Modal visible={visible} animationType="slide" onRequestClose={onClose}>
<View style={styles.container}>
@@ -192,7 +244,10 @@ export const QRCodeScanner: React.FC<QRCodeScannerProps> = ({ visible, onClose }
<View style={styles.permissionContainer}>
<MaterialCommunityIcons name="camera-off" size={64} color="rgba(255,255,255,0.5)" />
<Text style={styles.permissionText}></Text>
<TouchableOpacity style={styles.permissionButton} onPress={requestPermission}>
<TouchableOpacity
style={styles.permissionButton}
onPress={() => cameraModule?.useCameraPermissions()[1]()}
>
<Text style={styles.permissionButtonText}></Text>
</TouchableOpacity>
</View>
@@ -201,6 +256,8 @@ export const QRCodeScanner: React.FC<QRCodeScannerProps> = ({ visible, onClose }
);
}
const { CameraView } = cameraModule;
return (
<Modal visible={visible} animationType="slide" onRequestClose={onClose}>
<View style={styles.container}>
@@ -243,4 +300,9 @@ export const QRCodeScanner: React.FC<QRCodeScannerProps> = ({ visible, onClose }
);
};
// 根据平台导出不同组件
export const QRCodeScanner: React.FC<QRCodeScannerProps> = Platform.OS === 'web'
? QRCodeScannerWeb
: QRCodeScannerNative;
export default QRCodeScanner;