图片选择

This commit is contained in:
tx 2024-12-27 11:17:51 +08:00
parent c56e54df01
commit 0fd914b3aa
4 changed files with 168 additions and 13 deletions

36
package-lock.json generated
View File

@ -30,8 +30,10 @@
"react-native-contacts": "^8.0.4",
"react-native-fs": "^2.20.0",
"react-native-gesture-handler": "^2.20.2",
"react-native-image-picker": "^7.2.3",
"react-native-linear-gradient": "^2.8.3",
"react-native-permissions": "^5.2.1",
"react-native-qrcode": "^0.2.7",
"react-native-qrcode-scanner": "^1.5.5",
"react-native-qrcode-svg": "^6.3.12",
"react-native-reanimated": "^3.16.1",
@ -7535,6 +7537,15 @@
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/create-react-class": {
"version": "15.7.0",
"resolved": "https://registry.npmmirror.com/create-react-class/-/create-react-class-15.7.0.tgz",
"integrity": "sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng==",
"dependencies": {
"loose-envify": "^1.3.1",
"object-assign": "^4.1.1"
}
},
"node_modules/cross-fetch": {
"version": "3.1.8",
"resolved": "https://registry.npmmirror.com/cross-fetch/-/cross-fetch-3.1.8.tgz",
@ -13964,6 +13975,11 @@
],
"license": "MIT"
},
"node_modules/qr.js": {
"version": "0.0.0",
"resolved": "https://registry.npmmirror.com/qr.js/-/qr.js-0.0.0.tgz",
"integrity": "sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ=="
},
"node_modules/qrcode": {
"version": "1.5.4",
"resolved": "https://registry.npmmirror.com/qrcode/-/qrcode-1.5.4.tgz",
@ -14377,7 +14393,6 @@
"version": "2.20.0",
"resolved": "https://registry.npmmirror.com/react-native-fs/-/react-native-fs-2.20.0.tgz",
"integrity": "sha512-VkTBzs7fIDUiy/XajOSNk0XazFE9l+QlMAce7lGuebZcag5CnjszB+u4BdqzwaQOdcYb5wsJIsqq4kxInIRpJQ==",
"license": "MIT",
"dependencies": {
"base-64": "^0.1.0",
"utf8": "^3.0.0"
@ -14413,6 +14428,15 @@
"react-native": "*"
}
},
"node_modules/react-native-image-picker": {
"version": "7.2.3",
"resolved": "https://registry.npmmirror.com/react-native-image-picker/-/react-native-image-picker-7.2.3.tgz",
"integrity": "sha512-zKIZUlQNU3EtqizsXSH92zPeve4vpUrsqHu2kkpCxWE9TZhJFZBb+irDsBOY8J21k0+Edgt06TMQGJ+iPUIXyA==",
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/react-native-linear-gradient": {
"version": "2.8.3",
"resolved": "https://registry.npmmirror.com/react-native-linear-gradient/-/react-native-linear-gradient-2.8.3.tgz",
@ -14439,6 +14463,16 @@
}
}
},
"node_modules/react-native-qrcode": {
"version": "0.2.7",
"resolved": "https://registry.npmmirror.com/react-native-qrcode/-/react-native-qrcode-0.2.7.tgz",
"integrity": "sha512-Xvc3T1h95zA9tbRxiMkKethDYpPwKcqDPIHe9Cxt7pM+lma9dSzd6yXGGLGeZmFU/SmHMK+4bTnDltUv1s4Jnw==",
"dependencies": {
"create-react-class": "^15.6.0",
"prop-types": "^15.5.10",
"qr.js": "0.0.0"
}
},
"node_modules/react-native-qrcode-scanner": {
"version": "1.5.5",
"resolved": "https://registry.npmmirror.com/react-native-qrcode-scanner/-/react-native-qrcode-scanner-1.5.5.tgz",

View File

@ -32,8 +32,10 @@
"react-native-contacts": "^8.0.4",
"react-native-fs": "^2.20.0",
"react-native-gesture-handler": "^2.20.2",
"react-native-image-picker": "^7.2.3",
"react-native-linear-gradient": "^2.8.3",
"react-native-permissions": "^5.2.1",
"react-native-qrcode": "^0.2.7",
"react-native-qrcode-scanner": "^1.5.5",
"react-native-qrcode-svg": "^6.3.12",
"react-native-reanimated": "^3.16.1",

View File

@ -7,16 +7,28 @@ import {
Keyboard,
Text,
TouchableOpacity,
Modal,
Image
Image,
Modal
} from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { StackNavigationProp } from '@react-navigation/stack';
import { rpx } from '../../utils/rpx';
import QRCodeScanner from 'react-native-qrcode-scanner';
import { RNCamera } from 'react-native-camera';
import { TopNavigation, TopNavigationAction, Icon } from '@ui-kitten/components';
import { TopNavigation, TopNavigationAction, Icon, Popover, Button } from '@ui-kitten/components';
import Toast from 'react-native-toast-message';
import { launchImageLibrary } from 'react-native-image-picker';
// 假设你有一个函数 checkIfImageContainsQRCode 和 decodeQRCodeFromImage
const checkIfImageContainsQRCode = async (imageUri: string): Promise<boolean> => {
// 实现判断图片是否包含二维码的逻辑
return true; // 示例返回值
};
const decodeQRCodeFromImage = async (imageUri: string): Promise<string> => {
// 实现二维码解析的逻辑
return 'example_sn=123456'; // 示例返回值
};
type RootStackParamList = {
Home: undefined;
@ -34,10 +46,15 @@ const BackIcon = (props: any) => (
<Icon {...props} name='arrow-back-outline'/>
);
const MoreIcon = (props: any) => (
<Icon {...props} name='more-vertical'/>
);
const SnBind = () => {
const navigation = useNavigation<NavigationProp>();
const [sn, setSn] = useState('');
const [isScanning, setIsScanning] = useState(false);
const [popoverVisible, setPopoverVisible] = useState(false);
const navigateBack = () => {
navigation.goBack();
@ -47,6 +64,10 @@ const SnBind = () => {
<TopNavigationAction icon={BackIcon} onPress={navigateBack}/>
);
const togglePopover = () => {
setPopoverVisible(!popoverVisible);
};
const handlePress = () => {
if (!sn.trim()) {
Toast.show({
@ -58,8 +79,59 @@ const SnBind = () => {
navigation.navigate('ConfirmBind', { sn: sn.trim() });
};
const handleScan = () => {
setIsScanning(true);
const handleImagePicker = () => {
setPopoverVisible(false);
launchImageLibrary({ mediaType: 'photo' }, (response) => {
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.errorCode) {
console.log('ImagePicker Error: ', response.errorMessage);
} else if (response.assets && response.assets.length > 0) {
const imageUri = response.assets[0].uri;
// 判断图片是否包含二维码
checkIfImageContainsQRCode(imageUri)
.then((containsQRCode) => {
if (!containsQRCode) {
Toast.show({
type: 'error',
text1: '图片不包含二维码',
});
return;
}
// 使用二维码解析库解析图片
decodeQRCodeFromImage(imageUri)
.then((data) => {
console.log('二维码内容:', data);
// 处理解析结果
const snMatch = data.match(/[?&]sn=([^&]+)/);
if (snMatch && snMatch[1]) {
setSn(snMatch[1]);
Toast.show({
type: 'success',
text1: '图片解析成功',
});
} else {
Toast.show({
type: 'error',
text1: '未找到有效的SN码',
});
}
})
.catch((error) => {
Toast.show({
type: 'error',
text1: '图片解析失败或不包含二维码',
});
});
})
.catch((error) => {
Toast.show({
type: 'error',
text1: '无法判断图片内容',
});
});
}
});
};
const onSuccess = (e: { data: string }) => {
@ -113,12 +185,26 @@ const SnBind = () => {
value={sn}
onChangeText={setSn}
/>
<TouchableOpacity onPress={handleScan} style={styles.scanButton}>
<Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uSPtEFPtKlWIAKNrDtiQ' }}
style={styles.scanIcon}
/>
</TouchableOpacity>
<Popover
anchor={() => (
<TouchableOpacity onPress={togglePopover} style={styles.scanButton}>
<Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uSPtEFPtKlWIAKNrDtiQ' }}
style={styles.scanIcon}
/>
</TouchableOpacity>
)}
visible={popoverVisible}
onBackdropPress={togglePopover}
>
<View>
<Button onPress={handleImagePicker}></Button>
<Button onPress={() => {
setPopoverVisible(false);
setIsScanning(true);
}}></Button>
</View>
</Popover>
</View>
{/* 提示文本 */}
@ -245,11 +331,17 @@ const styles = StyleSheet.create({
backgroundColor: '#4297F3',
alignItems: 'center',
justifyContent: 'center',
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.3,
shadowRadius: 4,
elevation: 5,
},
scanIcon: {
width: rpx(88),
height: rpx(88),
resizeMode: 'contain',
tintColor: '#fff',
},
tip: {
marginTop: rpx(40),

View File

@ -3834,6 +3834,14 @@ create-jest@^29.7.0:
jest-util "^29.7.0"
prompts "^2.0.1"
create-react-class@^15.6.0:
version "15.7.0"
resolved "https://registry.npmmirror.com/create-react-class/-/create-react-class-15.7.0.tgz"
integrity sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng==
dependencies:
loose-envify "^1.3.1"
object-assign "^4.1.1"
cross-fetch@^3.1.5:
version "3.1.8"
resolved "https://registry.npmmirror.com/cross-fetch/-/cross-fetch-3.1.8.tgz"
@ -6521,7 +6529,7 @@ logkitty@^0.7.1:
dayjs "^1.8.15"
yargs "^15.1.0"
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.npmmirror.com/loose-envify/-/loose-envify-1.4.0.tgz"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@ -7671,6 +7679,11 @@ pure-rand@^6.0.0:
resolved "https://registry.npmmirror.com/pure-rand/-/pure-rand-6.1.0.tgz"
integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==
qr.js@0.0.0:
version "0.0.0"
resolved "https://registry.npmmirror.com/qr.js/-/qr.js-0.0.0.tgz"
integrity sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==
qrcode-terminal@0.11.0:
version "0.11.0"
resolved "https://registry.npmmirror.com/qrcode-terminal/-/qrcode-terminal-0.11.0.tgz"
@ -7810,6 +7823,11 @@ react-native-gesture-handler@^2.20.2, "react-native-gesture-handler@>= 1.0.0":
invariant "^2.2.4"
prop-types "^15.7.2"
react-native-image-picker@^7.2.3:
version "7.2.3"
resolved "https://registry.npmmirror.com/react-native-image-picker/-/react-native-image-picker-7.2.3.tgz"
integrity sha512-zKIZUlQNU3EtqizsXSH92zPeve4vpUrsqHu2kkpCxWE9TZhJFZBb+irDsBOY8J21k0+Edgt06TMQGJ+iPUIXyA==
react-native-linear-gradient@^2.8.3:
version "2.8.3"
resolved "https://registry.npmmirror.com/react-native-linear-gradient/-/react-native-linear-gradient-2.8.3.tgz"
@ -7843,6 +7861,15 @@ react-native-qrcode-svg@^6.3.12:
qrcode "^1.5.1"
text-encoding "^0.7.0"
react-native-qrcode@^0.2.7:
version "0.2.7"
resolved "https://registry.npmmirror.com/react-native-qrcode/-/react-native-qrcode-0.2.7.tgz"
integrity sha512-Xvc3T1h95zA9tbRxiMkKethDYpPwKcqDPIHe9Cxt7pM+lma9dSzd6yXGGLGeZmFU/SmHMK+4bTnDltUv1s4Jnw==
dependencies:
create-react-class "^15.6.0"
prop-types "^15.5.10"
qr.js "0.0.0"
react-native-reanimated@^3.16.1:
version "3.16.3"
resolved "https://registry.npmmirror.com/react-native-reanimated/-/react-native-reanimated-3.16.3.tgz"