11
This commit is contained in:
parent
63226e5dfe
commit
0ef962e5ba
7
App.tsx
7
App.tsx
|
@ -8,6 +8,7 @@ import 'react-native-gesture-handler';
|
|||
import { enableScreens } from 'react-native-screens';
|
||||
import HomeStackNavigator from './src/views/HomeStackNavigator';
|
||||
import { getFocusedRouteNameFromRoute } from '@react-navigation/native';
|
||||
import { rpx } from './src/utils/rpx';
|
||||
|
||||
enableScreens();
|
||||
|
||||
|
@ -35,7 +36,7 @@ function App() {
|
|||
tabBarIcon: ({ color, size }) => (
|
||||
<Image
|
||||
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/unny4QdTukoNl8fZYtkf' }}
|
||||
style={{ width: size, height: size, tintColor: color }}
|
||||
style={{ width: size, height: size, tintColor: color,paddingBottom:rpx(10) }}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
),
|
||||
|
@ -44,7 +45,7 @@ function App() {
|
|||
}
|
||||
})}
|
||||
/>
|
||||
<Tab.Screen
|
||||
{/* <Tab.Screen
|
||||
name="商城"
|
||||
component={ShopScreens}
|
||||
options={{
|
||||
|
@ -56,7 +57,7 @@ function App() {
|
|||
/>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
/> */}
|
||||
<Tab.Screen
|
||||
name="个人中心"
|
||||
component={ProfileScreens}
|
||||
|
|
19
package-lock.json
generated
19
package-lock.json
generated
|
@ -8,12 +8,14 @@
|
|||
"name": "BikeApp_demo",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"@react-native-community/geolocation": "^3.4.0",
|
||||
"@react-navigation/bottom-tabs": "^6.4.0",
|
||||
"@react-navigation/native": "^6.1.18",
|
||||
"@react-navigation/stack": "^6.3.8",
|
||||
"axios": "^1.7.7",
|
||||
"react": "18.2.0",
|
||||
"react-native": "0.74.5",
|
||||
"react-native-amap-geolocation": "^1.2.3",
|
||||
"react-native-amap3d": "^3.0.7",
|
||||
"react-native-camera": "^4.2.1",
|
||||
"react-native-gesture-handler": "^2.20.2",
|
||||
|
@ -2785,6 +2787,18 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-native-community/geolocation": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/@react-native-community/geolocation/-/geolocation-3.4.0.tgz",
|
||||
"integrity": "sha512-bzZH89/cwmpkPMKKveoC72C4JH0yF4St5Ceg/ZM9pA1SqX9MlRIrIrrOGZ/+yi++xAvFDiYfihtn9TvXWU9/rA==",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-native/assets-registry": {
|
||||
"version": "0.74.87",
|
||||
"license": "MIT",
|
||||
|
@ -9041,6 +9055,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-amap-geolocation": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmmirror.com/react-native-amap-geolocation/-/react-native-amap-geolocation-1.2.3.tgz",
|
||||
"integrity": "sha512-NKQG1eKJGHFnSGAMtsXZYfoKzlDAyK23cuKaIcJaWfa0kNr23pVrxOss3TcNRZTu8Syr9AwRus7I0PLGEcAaNA=="
|
||||
},
|
||||
"node_modules/react-native-amap3d": {
|
||||
"version": "3.2.4",
|
||||
"license": "MIT",
|
||||
|
|
|
@ -10,12 +10,14 @@
|
|||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-native-community/geolocation": "^3.4.0",
|
||||
"@react-navigation/bottom-tabs": "^6.4.0",
|
||||
"@react-navigation/native": "^6.1.18",
|
||||
"@react-navigation/stack": "^6.3.8",
|
||||
"axios": "^1.7.7",
|
||||
"react": "18.2.0",
|
||||
"react-native": "0.74.5",
|
||||
"react-native-amap-geolocation": "^1.2.3",
|
||||
"react-native-amap3d": "^3.0.7",
|
||||
"react-native-camera": "^4.2.1",
|
||||
"react-native-gesture-handler": "^2.20.2",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useRef, useEffect, useState } from 'react';
|
||||
import { View, Text, StyleSheet, Animated, Image, PanResponder } from 'react-native';
|
||||
import { rpx } from '../../utils/rpx'; // 根据需要调整路径
|
||||
import { rpx } from '../utils/rpx'; // 根据需要调整路径
|
||||
|
||||
|
||||
const Slider: React.FC = () => {
|
||||
const translateX = useRef(new Animated.Value(0)).current;
|
|
@ -8,7 +8,7 @@ import NormaIndex from "./NormaIndex";
|
|||
const HomeScreen: React.FC = () => {
|
||||
const [count, setCount] = useState(0);
|
||||
const [data, setData] = useState(null);
|
||||
const [pageIndex, setPageIndex] = useState(1);
|
||||
const [pageIndex, setPageIndex] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
// 发起 GET 请求
|
||||
|
|
|
@ -1,10 +1,22 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { View, StyleSheet, Platform,Text,Image } from 'react-native';
|
||||
import { View, StyleSheet, Platform, Text, Image, TouchableOpacity } from 'react-native';
|
||||
import { AMapSdk, MapView, Marker, MapType } from 'react-native-amap3d';
|
||||
import LinearGradient from 'react-native-linear-gradient';
|
||||
import { rpx } from '../../utils/rpx';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { StackNavigationProp } from '@react-navigation/stack';
|
||||
|
||||
type RootStackParamList = {
|
||||
Home: undefined;
|
||||
DeviceList: undefined;
|
||||
DeviceMap: undefined;
|
||||
};
|
||||
|
||||
type NavigationProp = StackNavigationProp<RootStackParamList>;
|
||||
|
||||
const MiniMap = () => {
|
||||
const navigation = useNavigation<NavigationProp>();
|
||||
|
||||
useEffect(() => {
|
||||
AMapSdk.init(
|
||||
Platform.select({
|
||||
|
@ -13,6 +25,10 @@ const MiniMap = () => {
|
|||
);
|
||||
}, []);
|
||||
|
||||
const handleMapPress = () => {
|
||||
navigation.navigate('DeviceMap');
|
||||
};
|
||||
|
||||
const latitude = 26.95500669;
|
||||
const longitude = 120.32736769;
|
||||
const imageUrl = "https://lxnapi.ccttiot.com/bike/img/static/uRx1B8B8acbquF2TO7Ry";
|
||||
|
@ -23,6 +39,8 @@ const MiniMap = () => {
|
|||
style={styles.map}
|
||||
mapType={MapType.Standard}
|
||||
zoomControlsEnabled={false}
|
||||
scrollEnabled={true}
|
||||
zoomEnabled={true}
|
||||
initialCameraPosition={{
|
||||
target: {
|
||||
latitude,
|
||||
|
@ -39,19 +57,24 @@ const MiniMap = () => {
|
|||
icon={{ uri: imageUrl }}
|
||||
/>
|
||||
</MapView>
|
||||
|
||||
<LinearGradient
|
||||
colors={[
|
||||
'rgba(255,255,255,1)',
|
||||
'rgba(255,255,255,1)',
|
||||
'rgba(255,255,255,0.9)',
|
||||
'rgba(255,255,255,0)',
|
||||
]}
|
||||
locations={[0, 0.8, 1]}
|
||||
locations={[0, 0.6, 1]}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 0, y: 1 }}
|
||||
style={styles.mapTop}
|
||||
pointerEvents="none"
|
||||
pointerEvents="box-none"
|
||||
>
|
||||
<View style={styles.contentContainer}>
|
||||
<TouchableOpacity
|
||||
style={styles.contentContainer}
|
||||
onPress={handleMapPress}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
<View style={styles.cont_left}>
|
||||
<View style={styles.cont_left_top}>
|
||||
<Text style={styles.cont_left_top_txt}>
|
||||
|
@ -66,12 +89,12 @@ const MiniMap = () => {
|
|||
</Text>
|
||||
</View>
|
||||
<View style={styles.cont_right}>
|
||||
<Image
|
||||
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uoWXZvZN5ynoS4CDFM4k' }} // 替换成你的图标URL
|
||||
<Image
|
||||
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uoWXZvZN5ynoS4CDFM4k' }}
|
||||
style={styles.rightIcon}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</LinearGradient>
|
||||
</View>
|
||||
);
|
||||
|
@ -109,7 +132,6 @@ const styles = StyleSheet.create({
|
|||
fontWeight: '400',
|
||||
fontSize: rpx(24),
|
||||
color: '#3D3D3D',
|
||||
lineHeight: rpx(32),
|
||||
},
|
||||
cont_right: {
|
||||
width: rpx(48),
|
||||
|
@ -121,7 +143,6 @@ const styles = StyleSheet.create({
|
|||
width: rpx(32),
|
||||
height: rpx(32),
|
||||
},
|
||||
|
||||
container: {
|
||||
marginTop: rpx(44),
|
||||
width: rpx(688),
|
||||
|
@ -135,7 +156,7 @@ const styles = StyleSheet.create({
|
|||
left: rpx(0),
|
||||
top: rpx(0),
|
||||
width: rpx(688),
|
||||
height: rpx(112),
|
||||
height: rpx(160),
|
||||
zIndex: 999,
|
||||
elevation: 3,
|
||||
},
|
||||
|
|
|
@ -1,24 +1,49 @@
|
|||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { View, Text, StyleSheet, Image, PanResponder, Animated, ScrollView, TouchableOpacity } from 'react-native';
|
||||
import http from '../../utils/http'; // 调整路径
|
||||
import { rpx } from '../../utils/rpx'; // Adjust the path as necessary
|
||||
import Slider from "./slider";
|
||||
import MiniMap from './MiniMap';
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
StyleSheet,
|
||||
Image,
|
||||
PanResponder,
|
||||
Animated,
|
||||
ScrollView,
|
||||
TouchableOpacity,
|
||||
TouchableWithoutFeedback ,
|
||||
StatusBar
|
||||
} from 'react-native';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
const NormaIndex: React.FC = () => {
|
||||
import { StackNavigationProp } from '@react-navigation/stack';
|
||||
import http from '../../utils/http';
|
||||
import { rpx } from '../../utils/rpx';
|
||||
import Slider from '../../components/slider';
|
||||
import MiniMap from './MiniMap';
|
||||
|
||||
// 定义导航参数类型
|
||||
type RootStackParamList = {
|
||||
Home: undefined;
|
||||
DeviceList: undefined;
|
||||
DeviceMap: undefined;
|
||||
// 添加其他页面的路由参数类型
|
||||
};
|
||||
|
||||
// 定义导航类型
|
||||
type NavigationProp = StackNavigationProp<RootStackParamList>;
|
||||
|
||||
const NormaIndex: React.FC = () => {
|
||||
const [count, setCount] = useState(0);
|
||||
const [data, setData] = useState(null);
|
||||
const translateX = useRef(new Animated.Value(0)).current;
|
||||
const bgColor = useRef(new Animated.Value(0)).current;
|
||||
|
||||
const navigation = useNavigation();
|
||||
const navigation = useNavigation<NavigationProp>();
|
||||
|
||||
const handlePress = () => {
|
||||
|
||||
navigation.navigate('DeviceList');
|
||||
// console.log(navigation);
|
||||
};
|
||||
|
||||
const toMap = () => {
|
||||
navigation.navigate('DeviceMap');
|
||||
};
|
||||
|
||||
const panResponder = useRef(
|
||||
PanResponder.create({
|
||||
onStartShouldSetPanResponder: () => true,
|
||||
|
@ -69,10 +94,9 @@ const NormaIndex: React.FC = () => {
|
|||
});
|
||||
|
||||
useEffect(() => {
|
||||
// 发起 GET 请求
|
||||
http.get('/app/article/9') // 替换为你的 API endpoint
|
||||
http.get('/app/article/9')
|
||||
.then(response => {
|
||||
// setData(response); // Uncomment when API response is needed
|
||||
// setData(response);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('请求错误', error);
|
||||
|
@ -80,11 +104,34 @@ const NormaIndex: React.FC = () => {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<ScrollView contentContainerStyle={styles.scrollContent}>
|
||||
<View style={styles.pageContainer}>
|
||||
<StatusBar
|
||||
backgroundColor="#F3FCFF" // 设置为白色
|
||||
barStyle="dark-content" // 状态栏文字为深色
|
||||
translucent={false} // 不透明
|
||||
/>
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.scrollContent}
|
||||
scrollEventThrottle={16}
|
||||
nestedScrollEnabled={true}
|
||||
>
|
||||
<View style={styles.container}>
|
||||
<View style={styles.titBox}>
|
||||
<Text style={styles.titTxt}>朵VFLU-13762</Text>
|
||||
</View>
|
||||
<TouchableOpacity onPress={handlePress}>
|
||||
<View style={styles.titBox}>
|
||||
<Text
|
||||
style={styles.titTxts}
|
||||
numberOfLines={1}
|
||||
ellipsizeMode="tail"
|
||||
>
|
||||
朵VFLU-13762
|
||||
</Text>
|
||||
<Image
|
||||
source={{ uri: 'https://api.ccttiot.com/smartmeter/img/static/uJRIitv0Yn5K7CEVe9qd' }}
|
||||
style={{ width: rpx(24), height: rpx(14), marginLeft: rpx(8) }}
|
||||
/>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={styles.KmBox}>
|
||||
<View style={styles.KmLi}>
|
||||
<View style={styles.KmLi_top}>
|
||||
|
@ -92,8 +139,10 @@ const NormaIndex: React.FC = () => {
|
|||
<Text style={styles.KmLi_tits}>km</Text>
|
||||
</View>
|
||||
<View style={styles.KmLi_bot}>
|
||||
<Image source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uDg93bCzlPFiFBtS71Al' }}
|
||||
style={{ width: rpx(32), height: rpx(32) }} />
|
||||
<Image
|
||||
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uDg93bCzlPFiFBtS71Al' }}
|
||||
style={{ width: rpx(32), height: rpx(32) }}
|
||||
/>
|
||||
<Text style={styles.KmLi_tits1}>剩余里程</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
@ -103,12 +152,15 @@ const NormaIndex: React.FC = () => {
|
|||
<Text style={styles.KmLi_tits}>km</Text>
|
||||
</View>
|
||||
<View style={styles.KmLi_bot}>
|
||||
<Image source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uDg93bCzlPFiFBtS71Al' }}
|
||||
style={{ width: rpx(32), height: rpx(32) }} />
|
||||
<Image
|
||||
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uDg93bCzlPFiFBtS71Al' }}
|
||||
style={{ width: rpx(32), height: rpx(32) }}
|
||||
/>
|
||||
<Text style={styles.KmLi_tits1}>剩余里程</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.infoBox}>
|
||||
<View style={styles.eleBox}>
|
||||
<View style={styles.eleType}>
|
||||
|
@ -116,54 +168,94 @@ const NormaIndex: React.FC = () => {
|
|||
</View>
|
||||
</View>
|
||||
<View style={styles.carBox}>
|
||||
<Image source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uVnIDwcwQP7oo12PeYVJ' }}
|
||||
style={{ width: rpx(440), height: rpx(340) }} />
|
||||
<Image
|
||||
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uVnIDwcwQP7oo12PeYVJ' }}
|
||||
style={{ width: rpx(440), height: rpx(340) }}
|
||||
/>
|
||||
<View style={styles.txtbox}>
|
||||
<View style={styles.yuan}></View>
|
||||
<Text style={styles.txt}>当前车辆状态:锁车</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.Bind_type}>
|
||||
<Image source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uQdjlI2DLfXmABfynycn' }}
|
||||
style={{ width: rpx(32), height: rpx(32) }} />
|
||||
<Image source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uLizPj6UxdjBsiqhxZB8' }}
|
||||
style={{ width: rpx(60), height: rpx(60), marginLeft: 'auto' }} />
|
||||
<Image
|
||||
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uQdjlI2DLfXmABfynycn' }}
|
||||
style={{ width: rpx(32), height: rpx(32) }}
|
||||
/>
|
||||
<Image
|
||||
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uLizPj6UxdjBsiqhxZB8' }}
|
||||
style={{ width: rpx(60), height: rpx(60), marginLeft: 'auto' }}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.car_stause_box}>
|
||||
<View style={styles.car_stause_li}>
|
||||
<Image source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uro1vIU1WydjNWgi7PUg' }}
|
||||
style={{ width: rpx(90), height: rpx(90), marginLeft: rpx(18) }} />
|
||||
<Text style={{ fontSize: rpx(32), color: '#3D3D3D', textAlign: 'center', marginTop: rpx(24) }}>鸣笛寻车</Text>
|
||||
<Image
|
||||
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uro1vIU1WydjNWgi7PUg' }}
|
||||
style={{ width: rpx(90), height: rpx(90), marginLeft: rpx(18) }}
|
||||
/>
|
||||
<Text style={styles.stauseText}>鸣笛寻车</Text>
|
||||
</View>
|
||||
<Slider />
|
||||
<View style={styles.car_stause_li}>
|
||||
<Image source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uVpJNxwWXlyXt4IdHQoe' }}
|
||||
style={{ width: rpx(90), height: rpx(90), marginLeft: rpx(18) }} />
|
||||
<Text style={{ fontSize: rpx(32), color: '#3D3D3D', textAlign: 'center', marginTop: rpx(24) }}>警报已开</Text>
|
||||
<Image
|
||||
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uVpJNxwWXlyXt4IdHQoe' }}
|
||||
style={{ width: rpx(90), height: rpx(90), marginLeft: rpx(18) }}
|
||||
/>
|
||||
<Text style={styles.stauseText}>警报已开</Text>
|
||||
</View>
|
||||
</View>
|
||||
<MiniMap />
|
||||
|
||||
<TouchableWithoutFeedback >
|
||||
|
||||
<View style={styles.mapWrapper}>
|
||||
<MiniMap />
|
||||
</View>
|
||||
|
||||
</TouchableWithoutFeedback>
|
||||
|
||||
<TouchableOpacity onPress={handlePress}>
|
||||
<Image
|
||||
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/ucYQHQ2Ep4odL8JpbtfT' }}
|
||||
style={styles.carSet}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
|
||||
|
||||
<View style={styles.otherSet}>
|
||||
<Image source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/ulDHhC4MrH3FO0AeTqVg' }} style={styles.otherImg} />
|
||||
<Image source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/u849NsNxdtzxhUkUJnfW' }} style={styles.otherImg} />
|
||||
<Image
|
||||
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/ulDHhC4MrH3FO0AeTqVg' }}
|
||||
style={styles.otherImg}
|
||||
/>
|
||||
<Image
|
||||
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/u849NsNxdtzxhUkUJnfW' }}
|
||||
style={styles.otherImg}
|
||||
/>
|
||||
</View>
|
||||
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
scrollContent: {
|
||||
flexGrow: 1, // This ensures the content expands to fill the available space
|
||||
pageContainer: {
|
||||
flex: 1,
|
||||
backgroundColor: '#F3FCFF', // 设置整个页面的背景色为白色
|
||||
},
|
||||
scrollContent: {
|
||||
flexGrow: 1,
|
||||
},
|
||||
mapWrapper: {
|
||||
marginVertical: rpx(20),
|
||||
},
|
||||
stauseText: {
|
||||
fontSize: rpx(32),
|
||||
color: '#3D3D3D',
|
||||
textAlign: 'center',
|
||||
marginTop: rpx(24)
|
||||
},
|
||||
|
||||
otherSet: {
|
||||
marginTop: rpx(30),
|
||||
// display:f,\
|
||||
|
@ -271,10 +363,22 @@ const styles = StyleSheet.create({
|
|||
borderRadius: rpx(16),
|
||||
backgroundColor: 'rgba(89,202,112,0.5)'
|
||||
},
|
||||
titBox: {
|
||||
|
||||
titTxts: {
|
||||
maxWidth: rpx(480),
|
||||
fontSize: rpx(48),
|
||||
fontWeight: '500',
|
||||
color: '#3D3D3D',
|
||||
},
|
||||
titBox: {
|
||||
// width: rpx(750),
|
||||
flexDirection: 'row', // 添加这行
|
||||
alignItems: 'center', // 添加这行
|
||||
// // 移除这些不需要的属性
|
||||
display: 'flex',
|
||||
flexWrap: 'nowrap',
|
||||
// // flex: 1,
|
||||
// justifyContent: 'center',
|
||||
},
|
||||
|
||||
KmLi_bot: {
|
||||
marginTop: rpx(4),
|
||||
flexDirection: 'row', // 保持在一行中
|
||||
|
|
|
@ -6,6 +6,7 @@ import DeviceList from './device/deviceList';
|
|||
import BindIndex from './bind/bind_index';
|
||||
import SnBind from './bind/sn_bind';
|
||||
import ConfirmBind from './bind/ConfirmBind';
|
||||
import DeviceMap from './device/deviceMap';
|
||||
// import BleBind from './bind/ble_bind';
|
||||
import { getFocusedRouteNameFromRoute } from '@react-navigation/native';
|
||||
|
||||
|
@ -15,6 +16,7 @@ type RootStackParamList = {
|
|||
BindIndex: undefined;
|
||||
SnBind: undefined;
|
||||
ConfirmBind: undefined;
|
||||
DeviceMap: undefined;
|
||||
};
|
||||
|
||||
const Stack = createStackNavigator<RootStackParamList>();
|
||||
|
@ -42,7 +44,7 @@ type Props = {
|
|||
export default function HomeStackNavigator({ navigation, route }: Props) {
|
||||
React.useEffect(() => {
|
||||
const routeName = getFocusedRouteNameFromRoute(route) ?? 'Home';
|
||||
const hideTabBarRoutes = ['DeviceList', 'BindIndex', 'SnBind', 'BleBind', 'ConfirmBind']; // 添加新的路由名
|
||||
const hideTabBarRoutes = ['DeviceList', 'BindIndex', 'SnBind', 'BleBind', 'ConfirmBind', 'DeviceMap']; // 添加新的路由名
|
||||
const shouldHideTabBar = hideTabBarRoutes.includes(routeName);
|
||||
|
||||
navigation.getParent()?.setOptions({
|
||||
|
@ -80,6 +82,11 @@ export default function HomeStackNavigator({ navigation, route }: Props) {
|
|||
component={ConfirmBind}
|
||||
options={createScreenOptions('确认绑定')}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="DeviceMap"
|
||||
component={DeviceMap}
|
||||
options={createScreenOptions('设备位置')}
|
||||
/>
|
||||
</Stack.Navigator>
|
||||
);
|
||||
}
|
|
@ -2,10 +2,10 @@
|
|||
import React from 'react';
|
||||
import { View, Text, StyleSheet } from 'react-native';
|
||||
|
||||
const ShopScreen = () => {
|
||||
const ProfileScreen = () => {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text>Shop Screen</Text>
|
||||
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
@ -15,10 +15,11 @@ const styles = StyleSheet.create({
|
|||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#F3FCFF',
|
||||
},
|
||||
});
|
||||
|
||||
export default ShopScreen;
|
||||
export default ProfileScreen;
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
import React from 'react';
|
||||
import { View, Text, StyleSheet } from 'react-native';
|
||||
|
||||
const ProfileScreen = () => {
|
||||
const ShopScreen = () => {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text>Profile Screen</Text>
|
||||
<Text>ShopScreen Screen</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
@ -18,4 +18,4 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
});
|
||||
|
||||
export default ProfileScreen;
|
||||
export default ShopScreen;
|
||||
|
|
|
@ -1,15 +1,101 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { View, Text, StyleSheet, Button } from 'react-native';
|
||||
import React, { useState } from 'react';
|
||||
import { View, Text, StyleSheet, ScrollView, Image, TouchableOpacity } from 'react-native';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { rpx } from '../../utils/rpx';
|
||||
|
||||
type CarItem = {
|
||||
id: number;
|
||||
title: string;
|
||||
model: string;
|
||||
status: string;
|
||||
isShared: boolean;
|
||||
};
|
||||
|
||||
export default function DeviceList() {
|
||||
const navigation = useNavigation();
|
||||
const [selectedItem, setSelectedItem] = useState<number | null>(null);
|
||||
const handlePress = () => {
|
||||
|
||||
navigation.navigate('BindIndex');
|
||||
// console.log(navigation);
|
||||
};
|
||||
|
||||
|
||||
const handleCancel = () => {
|
||||
navigation.goBack();
|
||||
};
|
||||
|
||||
// 示例数据保持不变
|
||||
const carList: CarItem[] = [
|
||||
|
||||
{
|
||||
id: 1,
|
||||
title: '备注1376',
|
||||
model: '车型:飞过的魔毯不须归于温暖',
|
||||
status: '车辆登入X小时出租',
|
||||
isShared: false,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '备注1376',
|
||||
model: '车型:飞过的魔毯不须归于温暖',
|
||||
status: '车辆登入X小时出租',
|
||||
isShared: true,
|
||||
},
|
||||
];
|
||||
|
||||
const toggleSelect = (id: number) => {
|
||||
setSelectedItem(prev => prev === id ? null : id);
|
||||
};
|
||||
|
||||
const renderCarItem = (item: CarItem) => (
|
||||
<View key={item.id} style={[styles.carItem, item.id !== 1 && styles.marginTop]}>
|
||||
<View style={styles.leftContent}>
|
||||
<Text style={styles.title}>{item.title}</Text>
|
||||
<Text style={styles.subTitle}>{item.model}</Text>
|
||||
<Text style={styles.status}>{item.status}</Text>
|
||||
<Text style={[styles.tag, item.isShared && styles.tagShare]}>
|
||||
{item.isShared ? '临时共享' : '车主'}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.rightContent}>
|
||||
<Image
|
||||
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uVnIDwcwQP7oo12PeYVJ' }}
|
||||
style={styles.carImage}
|
||||
/>
|
||||
<View style={styles.checkboxWrapper}>
|
||||
<Text style={styles.checkboxText}>选择车辆</Text>
|
||||
<TouchableOpacity
|
||||
onPress={() => toggleSelect(item.id)}
|
||||
style={styles.checkboxContainer}
|
||||
>
|
||||
<Image
|
||||
source={{
|
||||
uri: selectedItem === item.id
|
||||
? 'https://api.ccttiot.com/smartmeter/img/static/u4alnzo5240dlVnSQK0r'
|
||||
: 'https://api.ccttiot.com/smartmeter/img/static/uj2puOsyrcZY4ygZL6GX'
|
||||
}}
|
||||
style={styles.checkboxImage}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
|
||||
<ScrollView style={styles.scrollContent}>
|
||||
{carList.map(item => renderCarItem(item))}
|
||||
</ScrollView>
|
||||
|
||||
<View style={styles.bottomButtons}>
|
||||
<TouchableOpacity onPress={handlePress} style={styles.addButton}>
|
||||
<Text style={styles.addButtonText}>+ 添加车辆</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={handleCancel} style={styles.cancelButton}>
|
||||
<Text style={styles.cancelButtonText}>取消</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
@ -17,7 +103,123 @@ export default function DeviceList() {
|
|||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '#fff',
|
||||
backgroundColor: '#F3FCFF',
|
||||
},
|
||||
|
||||
});
|
||||
scrollContent: {
|
||||
marginBottom: rpx(300),
|
||||
flex: 1,
|
||||
paddingHorizontal: rpx(20),
|
||||
// marginBottom: rpx(160),
|
||||
},
|
||||
carItem: {
|
||||
flexDirection: 'row',
|
||||
backgroundColor: '#EEF2FD',
|
||||
borderRadius: rpx(20),
|
||||
padding: rpx(30),
|
||||
marginTop: rpx(20),
|
||||
alignItems: 'center',
|
||||
},
|
||||
marginTop: {
|
||||
marginTop: rpx(20),
|
||||
},
|
||||
leftContent: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
rightContent: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginLeft: rpx(20),
|
||||
},
|
||||
title: {
|
||||
fontSize: rpx(40),
|
||||
fontWeight: '500',
|
||||
color: '#3D3D3D',
|
||||
marginBottom: rpx(16),
|
||||
},
|
||||
subTitle: {
|
||||
fontWeight: '500',
|
||||
fontSize: rpx(24),
|
||||
color: '#3D3D3D',
|
||||
marginBottom: rpx(12),
|
||||
},
|
||||
status: {
|
||||
fontSize: rpx(24),
|
||||
color: '#666',
|
||||
marginBottom: rpx(16),
|
||||
},
|
||||
tag: {
|
||||
alignSelf: 'flex-start',
|
||||
paddingVertical: rpx(6),
|
||||
paddingHorizontal: rpx(30),
|
||||
backgroundColor: '#D2E8FF',
|
||||
borderRadius: rpx(29),
|
||||
fontSize: rpx(24),
|
||||
color: '#4297F3',
|
||||
marginTop: rpx(10),
|
||||
fontWeight: '500'
|
||||
},
|
||||
tagShare: {
|
||||
color: '#FF9500',
|
||||
backgroundColor: '#FFEEDE'
|
||||
},
|
||||
carImage: {
|
||||
width: rpx(232),
|
||||
height: rpx(180),
|
||||
marginBottom: rpx(16),
|
||||
},
|
||||
checkboxContainer: {
|
||||
width: rpx(44),
|
||||
height: rpx(44),
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
checkboxWrapper: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
checkboxText: {
|
||||
fontSize: rpx(32),
|
||||
color: '#3D3D3D',
|
||||
marginRight: rpx(8),
|
||||
},
|
||||
checkboxImage: {
|
||||
width: rpx(44),
|
||||
height: rpx(44),
|
||||
resizeMode: 'contain',
|
||||
},
|
||||
bottomButtons: {
|
||||
position: 'absolute',
|
||||
bottom: rpx(30),
|
||||
left: 0,
|
||||
right: 0,
|
||||
padding: rpx(20),
|
||||
backgroundColor: '#F3FCFF',
|
||||
},
|
||||
addButton: {
|
||||
backgroundColor: '#4297F3',
|
||||
height: rpx(92),
|
||||
borderRadius: rpx(20),
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginBottom: rpx(20),
|
||||
},
|
||||
addButtonText: {
|
||||
color: '#FFFFFF',
|
||||
fontSize: rpx(32),
|
||||
},
|
||||
cancelButton: {
|
||||
backgroundColor: '#fff',
|
||||
height: rpx(92),
|
||||
borderRadius: rpx(20),
|
||||
borderWidth: rpx(2),
|
||||
borderColor: '#4297F3',
|
||||
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
cancelButtonText: {
|
||||
color: '#4297F3',
|
||||
fontSize: rpx(32),
|
||||
},
|
||||
});
|
230
src/views/device/deviceMap.tsx
Normal file
230
src/views/device/deviceMap.tsx
Normal file
|
@ -0,0 +1,230 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { View, Text, StyleSheet, TouchableOpacity, Image, StatusBar, Linking, Platform } from 'react-native';
|
||||
import { AMapSdk, MapView, Marker, MapType } from 'react-native-amap3d';
|
||||
import { init, Geolocation } from 'react-native-amap-geolocation';
|
||||
import { rpx } from '../../utils/rpx';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
|
||||
const DeviceMap = () => {
|
||||
const navigation = useNavigation();
|
||||
const latitude = 26.95500669;
|
||||
const longitude = 120.32736769;
|
||||
const imageUrl = "https://lxnapi.ccttiot.com/bike/img/static/uRx1B8B8acbquF2TO7Ry";
|
||||
|
||||
const [userLocation, setUserLocation] = React.useState({
|
||||
latitude: 0,
|
||||
longitude: 0,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// 初始化定位
|
||||
async function initGeolocation() {
|
||||
await init({
|
||||
ios: "812efd3a950ba3675f928630302c6463",
|
||||
android: "812efd3a950ba3675f928630302c6463"
|
||||
});
|
||||
|
||||
Geolocation.getCurrentPosition(
|
||||
({ coords }) => {
|
||||
// console.log('定位错误:', coords);
|
||||
setUserLocation({
|
||||
latitude: coords.latitude,
|
||||
longitude: coords.longitude,
|
||||
});
|
||||
},
|
||||
(error) => {
|
||||
console.log('定位错误:', error);
|
||||
},
|
||||
// {
|
||||
// timeout: 15000,
|
||||
// maximumAge: 10000,
|
||||
// distanceFilter: 100,
|
||||
// }
|
||||
);
|
||||
}
|
||||
|
||||
initGeolocation();
|
||||
|
||||
// 组件卸载时清理
|
||||
return () => {
|
||||
Geolocation.stop();
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 跳转到高德地图
|
||||
const openAMap = async () => {
|
||||
const url = Platform.select({
|
||||
android: `androidamap://navi?sourceApplication=appname&lat=${latitude}&lon=${longitude}&dev=0&style=2`,
|
||||
ios: `iosamap://navi?sourceApplication=appname&lat=${latitude}&lon=${longitude}&dev=0&style=2`,
|
||||
});
|
||||
|
||||
const fallbackUrl = `https://uri.amap.com/navigation?to=${longitude},${latitude},目的地&mode=car&coordinate=gaode`;
|
||||
|
||||
try {
|
||||
// 检查是否安装了高德地图
|
||||
const supported = await Linking.canOpenURL(url);
|
||||
|
||||
if (supported) {
|
||||
await Linking.openURL(url);
|
||||
} else {
|
||||
// 如果没有安装高德地图,则打开网页版
|
||||
await Linking.openURL(fallbackUrl);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('无法打开高德地图:', error);
|
||||
// 打开网页版作为后备方案
|
||||
await Linking.openURL(fallbackUrl);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<StatusBar
|
||||
backgroundColor="#FFFFFF"
|
||||
barStyle="dark-content"
|
||||
translucent={false}
|
||||
/>
|
||||
<MapView
|
||||
style={styles.map}
|
||||
mapType={MapType.Standard}
|
||||
zoomControlsEnabled={false}
|
||||
scrollEnabled={true}
|
||||
zoomEnabled={true}
|
||||
initialCameraPosition={{
|
||||
target: {
|
||||
latitude,
|
||||
longitude,
|
||||
},
|
||||
zoom: 15,
|
||||
}}
|
||||
>
|
||||
{/* 设备位置标记 */}
|
||||
<Marker
|
||||
position={{
|
||||
latitude,
|
||||
longitude,
|
||||
}}
|
||||
icon={{ uri: imageUrl }}
|
||||
/>
|
||||
|
||||
{/* 用户位置标记 */}
|
||||
{userLocation.latitude !== 0 && (
|
||||
<Marker
|
||||
position={{
|
||||
latitude: userLocation.latitude,
|
||||
longitude: userLocation.longitude,
|
||||
}}
|
||||
icon={{ uri: 'imageUrl' }}
|
||||
/>
|
||||
)}
|
||||
</MapView>
|
||||
<View style={styles.bottomCard}>
|
||||
<View style={styles.addressInfo}>
|
||||
<Text style={styles.addressText}>
|
||||
福建省宁德市福鼎市海滨路200号靠近福鼎第四中学
|
||||
</Text>
|
||||
<Image
|
||||
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/voice' }}
|
||||
style={styles.voiceIcon}
|
||||
/>
|
||||
</View>
|
||||
<TouchableOpacity
|
||||
style={styles.navigationButton}
|
||||
onPress={openAMap}
|
||||
>
|
||||
<Text style={styles.buttonText}>导航到车辆</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '#FFFFFF',
|
||||
},
|
||||
map: {
|
||||
flex: 1,
|
||||
width: '100%',
|
||||
},
|
||||
header: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: rpx(88),
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingHorizontal: rpx(32),
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
backButton: {
|
||||
width: rpx(44),
|
||||
height: rpx(44),
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
backIcon: {
|
||||
width: rpx(32),
|
||||
height: rpx(32),
|
||||
},
|
||||
timeContainer: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
},
|
||||
timeText: {
|
||||
fontSize: rpx(28),
|
||||
color: '#333333',
|
||||
},
|
||||
menuButton: {
|
||||
width: rpx(44),
|
||||
height: rpx(44),
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
menuIcon: {
|
||||
width: rpx(32),
|
||||
height: rpx(32),
|
||||
},
|
||||
bottomCard: {
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
backgroundColor: '#FFFFFF',
|
||||
borderTopLeftRadius: rpx(24),
|
||||
borderTopRightRadius: rpx(24),
|
||||
padding: rpx(32),
|
||||
},
|
||||
addressInfo: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginBottom: rpx(32),
|
||||
},
|
||||
addressText: {
|
||||
flex: 1,
|
||||
fontSize: rpx(28),
|
||||
color: '#333333',
|
||||
marginRight: rpx(16),
|
||||
},
|
||||
voiceIcon: {
|
||||
width: rpx(44),
|
||||
height: rpx(44),
|
||||
},
|
||||
navigationButton: {
|
||||
height: rpx(96),
|
||||
backgroundColor: '#2089FF',
|
||||
borderRadius: rpx(48),
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
buttonText: {
|
||||
fontSize: rpx(32),
|
||||
color: '#FFFFFF',
|
||||
fontWeight: '500',
|
||||
},
|
||||
});
|
||||
|
||||
export default DeviceMap;
|
Loading…
Reference in New Issue
Block a user