This commit is contained in:
tx 2024-12-18 16:21:19 +08:00
parent a868525bb4
commit 17c5a983e6
11 changed files with 831 additions and 425 deletions

4
package-lock.json generated
View File

@ -2302,8 +2302,7 @@
"node_modules/@eva-design/eva": { "node_modules/@eva-design/eva": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmmirror.com/@eva-design/eva/-/eva-2.2.0.tgz", "resolved": "https://registry.npmmirror.com/@eva-design/eva/-/eva-2.2.0.tgz",
"integrity": "sha512-Wh98ex5cCK+YYSQNpthX1bT4CA3zDRR1WnJv0YlyvULAkmjaEvqtoGMCXzu5DH8v1fGIggu/OpAokLS7UVPe+A==", "integrity": "sha512-Wh98ex5cCK+YYSQNpthX1bT4CA3zDRR1WnJv0YlyvULAkmjaEvqtoGMCXzu5DH8v1fGIggu/OpAokLS7UVPe+A=="
"license": "MIT"
}, },
"node_modules/@eva-design/processor": { "node_modules/@eva-design/processor": {
"version": "2.2.0", "version": "2.2.0",
@ -4226,7 +4225,6 @@
"version": "5.3.1", "version": "5.3.1",
"resolved": "https://registry.npmmirror.com/@ui-kitten/components/-/components-5.3.1.tgz", "resolved": "https://registry.npmmirror.com/@ui-kitten/components/-/components-5.3.1.tgz",
"integrity": "sha512-Oj1WePUQtpNfH7ftXGdkkFVmJI+JcR3cBryPJV0E+JAUdH2dbJ0oG/VA+UAgk27/u0K0OZSUkdMFuGnkDAVuYA==", "integrity": "sha512-Oj1WePUQtpNfH7ftXGdkkFVmJI+JcR3cBryPJV0E+JAUdH2dbJ0oG/VA+UAgk27/u0K0OZSUkdMFuGnkDAVuYA==",
"license": "MIT",
"dependencies": { "dependencies": {
"@eva-design/dss": "^2.2.0", "@eva-design/dss": "^2.2.0",
"@eva-design/processor": "^2.2.0", "@eva-design/processor": "^2.2.0",

View File

@ -1,39 +1,69 @@
import React, { useRef, useEffect, useState } from 'react'; import React, { useRef, useEffect, useState } from 'react';
import { View, Text, StyleSheet, Animated, Image, PanResponder, Vibration } from 'react-native'; import { View, Text, StyleSheet, Animated, Image, PanResponder, Vibration, Dimensions } from 'react-native';
import { rpx } from '../utils/rpx';
const Slider: React.FC = () => { interface SliderProps {
const translateX = useRef(new Animated.Value(0)).current; lockStatus?: number;
onStatusChange?: (status: boolean) => void;
}
// 添加 rpx 计算函数
const { width: SCREEN_WIDTH } = Dimensions.get('window');
const rpx = (px: number) => {
return (SCREEN_WIDTH / 750) * px;
};
const Slider: React.FC<SliderProps> = ({ lockStatus = 1, onStatusChange }) => {
const translateX = useRef(new Animated.Value(lockStatus === 0 ? rpx(180) : 0)).current;
const maxWidth = rpx(180); const maxWidth = rpx(180);
const buttonWidth = rpx(86); const buttonWidth = rpx(86);
const [iconOpacity, setIconOpacity] = useState(1); const [isRight, setIsRight] = useState(lockStatus === 0);
const [isRight, setIsRight] = useState(false);
const hasVibratedRef = useRef(false); const hasVibratedRef = useRef(false);
const offsetRef = useRef(0);
// 添加监听器
useEffect(() => {
const id = translateX.addListener(({ value }) => {
if (value >= maxWidth * 0.95) {
setIsRight(true);
} else if (value <= maxWidth * 0.05) {
setIsRight(false);
}
});
return () => translateX.removeListener(id);
}, []);
const iconOpacity = translateX.interpolate({
inputRange: [maxWidth * 0.9, maxWidth],
outputRange: [1, 0],
extrapolate: 'clamp'
});
const backgroundWidth = translateX.interpolate({
inputRange: [0, maxWidth],
outputRange: [buttonWidth - rpx(2), maxWidth + buttonWidth - rpx(2)],
extrapolate: 'clamp'
});
const panResponder = useRef( const panResponder = useRef(
PanResponder.create({ PanResponder.create({
onMoveShouldSetPanResponder: (_, gestureState) => { onStartShouldSetPanResponder: () => true,
return Math.abs(gestureState.dx) > 10; onMoveShouldSetPanResponder: () => true,
},
onPanResponderGrant: () => { onPanResponderGrant: () => {
hasVibratedRef.current = false; hasVibratedRef.current = false;
offsetRef.current = translateX._value;
}, },
onPanResponderMove: (_, gestureState) => { onPanResponderMove: (_, gestureState) => {
const currentValue = translateX.__getValue();
let newValue; let newValue;
if (isRight) { if (isRight) {
newValue = maxWidth + gestureState.dx; newValue = offsetRef.current + gestureState.dx;
} else { } else {
newValue = gestureState.dx; newValue = offsetRef.current + gestureState.dx;
} }
newValue = Math.max(0, Math.min(maxWidth, newValue)); newValue = Math.max(0, Math.min(maxWidth, newValue));
translateX.setValue(newValue); translateX.setValue(newValue);
// 根据滑动位置更新状态
setIsRight(newValue > maxWidth / 2);
if (!hasVibratedRef.current) { if (!hasVibratedRef.current) {
if (newValue >= maxWidth * 0.95 || newValue <= maxWidth * 0.05) { if (newValue >= maxWidth * 0.95 || newValue <= maxWidth * 0.05) {
Vibration.vibrate(20); Vibration.vibrate(20);
@ -42,98 +72,86 @@ const Slider: React.FC = () => {
} }
}, },
onPanResponderRelease: (_, gestureState) => { onPanResponderRelease: (_, gestureState) => {
const currentValue = translateX.__getValue(); const currentValue = translateX._value;
let toValue; let toValue;
let finalIsRight;
if (isRight) { if (isRight) {
if (gestureState.dx < -maxWidth / 4) { if (gestureState.dx < -maxWidth / 4) {
toValue = 0; toValue = 0;
setIsRight(false); finalIsRight = false;
} else { } else {
toValue = maxWidth; toValue = maxWidth;
setIsRight(true); finalIsRight = true;
} }
} else { } else {
if (gestureState.dx > maxWidth / 4) { if (gestureState.dx > maxWidth / 4) {
toValue = maxWidth; toValue = maxWidth;
setIsRight(true); finalIsRight = true;
} else { } else {
toValue = 0; toValue = 0;
setIsRight(false); finalIsRight = false;
} }
} }
Animated.spring(translateX, { Animated.timing(translateX, {
toValue, toValue,
tension: 50, duration: 100,
friction: 7,
useNativeDriver: false, useNativeDriver: false,
}).start(() => { }).start(() => {
hasVibratedRef.current = false; hasVibratedRef.current = false;
onStatusChange?.(finalIsRight);
}); });
}, },
}) })
).current; ).current;
const backgroundColorWidth = translateX.interpolate({
inputRange: [0, maxWidth],
outputRange: [0, maxWidth + buttonWidth],
extrapolate: 'clamp',
});
useEffect(() => {
const listenerId = translateX.addListener(({ value }) => {
const newOpacity = value < maxWidth ? (1 - value / maxWidth) : 0;
setIconOpacity(newOpacity);
});
return () => {
translateX.removeListener(listenerId);
};
}, [translateX]);
return ( return (
<View style={styles.container}> <View style={styles.container}>
<View style={styles.car_Opne_box}> <View style={styles.car_Opne_box}>
{/* 默认背景 */}
<View style={styles.defaultBackground} />
{/* 蓝色滑动背景 */}
<Animated.View <Animated.View
style={[ style={[
styles.background, styles.background,
{ {
width: backgroundColorWidth, width: backgroundWidth,
backgroundColor: '#4297F3',
zIndex: 1,
} }
]} ]}
/> />
<View style={[styles.defaultBackground]} />
{/* 滑块 */}
<Animated.View <Animated.View
{...panResponder.panHandlers} {...panResponder.panHandlers}
style={[ style={[
styles.imageContainer, styles.imageContainer,
{ {
transform: [{ transform: [{ translateX }]
translateX
}],
zIndex: 2,
} }
]} ]}
> >
<Image <Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uY9tYXXZztuE1VTLDl5y' }} source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uY9tYXXZztuE1VTLDl5y' }}
style={styles.imageContent} style={styles.imageContent}
resizeMode="contain"
/> />
</Animated.View> </Animated.View>
{/* 箭头图标 */}
<Animated.Image <Animated.Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uEJob4XbADaL9ohOTVTL' }} source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uEJob4XbADaL9ohOTVTL' }}
style={[ style={[
styles.icon, styles.icon,
{ opacity: iconOpacity, zIndex: 2 } { opacity: iconOpacity }
]} ]}
resizeMode="contain"
/> />
</View> </View>
<Text style={styles.text}>{isRight ? '左滑关闭' : '右滑启动'}</Text> <Text style={styles.text}>
{isRight ? '左滑关闭' : '右滑启动'}
</Text>
</View> </View>
); );
}; };
@ -153,17 +171,23 @@ const styles = StyleSheet.create({
overflow: 'hidden', overflow: 'hidden',
}, },
background: { background: {
height: '100%',
borderRadius: rpx(45),
position: 'absolute', position: 'absolute',
left: 0, left: 0,
top: 0, top: 0,
height: '100%',
backgroundColor: '#4297F3',
borderRadius: rpx(45),
zIndex: 1,
}, },
defaultBackground: { defaultBackground: {
width: rpx(268), position: 'absolute',
left: 0,
top: 0,
width: '100%',
height: '100%', height: '100%',
backgroundColor: '#EBEBEB', backgroundColor: '#EBEBEB',
borderRadius: rpx(45), borderRadius: rpx(45),
zIndex: 0,
}, },
imageContainer: { imageContainer: {
width: rpx(86), width: rpx(86),
@ -195,4 +219,4 @@ const styles = StyleSheet.create({
}, },
}); });
export default Slider; export default React.memo(Slider);

View File

@ -14,7 +14,7 @@ import AddShare from '../views/device/AddShare';
import ShareQrcode from '../views/device/shareQrcode'; import ShareQrcode from '../views/device/shareQrcode';
import { getFocusedRouteNameFromRoute } from '@react-navigation/native'; import { getFocusedRouteNameFromRoute } from '@react-navigation/native';
import { HomeStackParamList } from './types'; import { HomeStackParamList } from './types';
import TestBule from '../views/device/test_bule';
const Stack = createStackNavigator<HomeStackParamList>(); const Stack = createStackNavigator<HomeStackParamList>();
const createScreenOptions = (title: string): StackNavigationOptions => { const createScreenOptions = (title: string): StackNavigationOptions => {
@ -50,10 +50,19 @@ export default function HomeStackNavigator({ navigation, route }: Props) {
headerShown: false, headerShown: false,
}} }}
/> />
<Stack.Screen
name="TestBule"
component={TestBule}
options={{
headerShown: false,
}}
/>
<Stack.Screen <Stack.Screen
name="DeviceList" name="DeviceList"
component={DeviceList} component={DeviceList}
options={createScreenOptions('设备列表')} options={{
headerShown: false,
}}
/> />
<Stack.Screen <Stack.Screen
name="BindIndex" name="BindIndex"

View File

@ -7,7 +7,6 @@ import { BottomNavigation, BottomNavigationTab, Icon } from '@ui-kitten/componen
import { getFocusedRouteNameFromRoute } from '@react-navigation/native'; import { getFocusedRouteNameFromRoute } from '@react-navigation/native';
import { useAuth } from '../context/AuthContext'; import { useAuth } from '../context/AuthContext';
// 导入页面组件 // 导入页面组件
import LoginScreen from '../views/Login/Login'; import LoginScreen from '../views/Login/Login';
import ResetPasswordScreen from '../views/Login/ResetPassword'; import ResetPasswordScreen from '../views/Login/ResetPassword';
@ -19,8 +18,8 @@ import { RootStackParamList, MainTabParamList } from './types';
const Stack = createStackNavigator<RootStackParamList>(); const Stack = createStackNavigator<RootStackParamList>();
const Tab = createBottomTabNavigator<MainTabParamList>(); const Tab = createBottomTabNavigator<MainTabParamList>();
// 定义需要显示绑定底部栏的路由名称 // 定义需要显示底部导航栏的路由名称
const bindNavBarRoutes = ['BindIndex', 'SnBind', 'ConfirmBind']; const showTabBarRoutes = ['爱车', '个人中心'];
const MainNavigator = () => { const MainNavigator = () => {
return ( return (
@ -30,8 +29,8 @@ const MainNavigator = () => {
tabBarHideOnKeyboard: true, tabBarHideOnKeyboard: true,
}} }}
tabBar={props => { tabBar={props => {
const routeName = getFocusedRouteNameFromRoute(props.state.routes[props.state.index]) ?? 'Home'; const routeName = getFocusedRouteNameFromRoute(props.state.routes[props.state.index]) ?? '爱车';
if (bindNavBarRoutes.includes(routeName)) { if (!showTabBarRoutes.includes(routeName)) {
return null; return null;
} }
return ( return (

View File

@ -27,6 +27,7 @@ export type HomeStackParamList = {
DeviceShare: undefined; DeviceShare: undefined;
AddShare: undefined; AddShare: undefined;
ShareQrcode: undefined; ShareQrcode: undefined;
TestBule: undefined;
}; };
// 导航属性类型 // 导航属性类型

View File

@ -26,7 +26,7 @@ const api = axios.create({
api.interceptors.request.use( api.interceptors.request.use(
async (config) => { async (config) => {
if (__DEV__) { if (__DEV__) {
console.log('[Request]:', config.url, config.data); // console.log('[Request]:', config.url, config.data);
} }
const token = await auth.getToken(); const token = await auth.getToken();
@ -42,7 +42,7 @@ api.interceptors.request.use(
api.interceptors.response.use( api.interceptors.response.use(
response => { response => {
if (__DEV__) { if (__DEV__) {
console.log('[Response]:', response.config.url, response.data); // console.log('[Response]:', response.config.url, response.data);
} }
const { code, msg, data } = response.data; const { code, msg, data } = response.data;
@ -100,5 +100,7 @@ export const apiService = {
bindSn: (sn: string) => bindSn: (sn: string) =>
api.post('/appVerify/userBandDevice?sn=' + sn), api.post('/appVerify/userBandDevice?sn=' + sn),
getDeviceList: () => api.get('/appVerify/getDeviceListByToken'), getDeviceList: () => api.get('/appVerify/getDeviceListByMerchantToken'),
toggleDefault: (sn: string) => api.put(`/appVerify/toggleDefault?sn=${sn}`),
}; };

View File

@ -37,7 +37,8 @@ const HomeScreen = () => {
const fetchDeviceList = async () => { const fetchDeviceList = async () => {
try { try {
const response = await apiService.getDeviceList(); const response = await apiService.getDeviceList();
if (response && response.data && response.data.length > 1) { console.log(response.data.length,'response');
if (response && response.data && response.data.length > 0) {
setHasMultipleDevices(true); setHasMultipleDevices(true);
} else { } else {
setHasMultipleDevices(false); setHasMultipleDevices(false);

View File

@ -1,14 +1,14 @@
import React, { useEffect, useState, useRef } from 'react'; import React, { useEffect, useState, useRef } from 'react';
import { import {
View, View,
Text, Text,
StyleSheet, StyleSheet,
Image, Image,
PanResponder, PanResponder,
Animated, Animated,
ScrollView, ScrollView,
TouchableOpacity, TouchableOpacity,
TouchableWithoutFeedback , TouchableWithoutFeedback,
StatusBar StatusBar
} from 'react-native'; } from 'react-native';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
@ -17,15 +17,26 @@ import http from '../../utils/http';
import { rpx } from '../../utils/rpx'; import { rpx } from '../../utils/rpx';
import Slider from '../../components/slider'; import Slider from '../../components/slider';
import MiniMap from './MiniMap'; import MiniMap from './MiniMap';
import { apiService } from '../../utils/api';
// 定义导航参数类型 // 定义导航参数类型
type RootStackParamList = { type RootStackParamList = {
Home: undefined; Home: undefined;
DeviceList: undefined; DeviceList: undefined;
DeviceMap: undefined; DeviceMap: undefined;
DeviceSet: undefined; DeviceSet: undefined;
DeviceShare: undefined; DeviceShare: undefined;
// 添加其他页面的路由参数类型 TestBule: undefined;
// 添加其他页面的路由参数类型
};
type DeviceType = {
id: number;
sn: string;
vehicleNum: string;
model: string;
remainingPower: number;
remainingMileage: number;
isDefault: number;
lockStatus: number;
}; };
// 定义导航类型 // 定义导航类型
@ -37,7 +48,7 @@ const NormaIndex: React.FC = () => {
const translateX = useRef(new Animated.Value(0)).current; const translateX = useRef(new Animated.Value(0)).current;
const bgColor = useRef(new Animated.Value(0)).current; const bgColor = useRef(new Animated.Value(0)).current;
const navigation = useNavigation<NavigationProp>(); const navigation = useNavigation<NavigationProp>();
const [defaultDevice, setDefaultDevice] = useState<DeviceType | null>(null);
const handlePress = () => { const handlePress = () => {
navigation.navigate('DeviceList'); navigation.navigate('DeviceList');
}; };
@ -51,7 +62,9 @@ const NormaIndex: React.FC = () => {
const toShare = () => { const toShare = () => {
navigation.navigate('DeviceShare'); navigation.navigate('DeviceShare');
}; };
const toTestBule = () => {
navigation.navigate('TestBule');
};
const panResponder = useRef( const panResponder = useRef(
PanResponder.create({ PanResponder.create({
onStartShouldSetPanResponder: () => true, onStartShouldSetPanResponder: () => true,
@ -102,154 +115,185 @@ const NormaIndex: React.FC = () => {
}); });
useEffect(() => { useEffect(() => {
http.get('/app/article/9') fetchDeviceList();
.then(response => {
// setData(response);
})
.catch(error => {
console.error('请求错误', error);
});
}, []); }, []);
const getPowerColor = (power: number): string => {
if (power >= 60) {
return 'rgba(89, 202, 112, 0.5)'; // 绿色
} else if (power >= 20) {
return 'rgba(255, 149, 0, 0.5)'; // 橙色
} else {
return 'rgba(255, 69, 58, 0.5)'; // 红色
}
};
const fetchDeviceList = async () => {
try {
const response = await apiService.getDeviceList();
if (response?.code === 200 && response.data) {
const defaultDev = response.data.find((device: DeviceType) => device.isDefault == 1);
if (defaultDev) {
console.log(defaultDev, 'defaultDev');
setDefaultDevice(defaultDev);
}
}
} catch (error) {
console.error('获取设备列表失败:', error);
} finally {
}
};
return ( return (
<View style={styles.pageContainer}> <View style={styles.pageContainer}>
<StatusBar <StatusBar
backgroundColor="#F3FCFF" // 设置为白色 backgroundColor="#F3FCFF" // 设置为白色
barStyle="dark-content" // 状态栏文字为深色 barStyle="dark-content" // 状态栏文字为深色
translucent={false} // 不透明 translucent={false} // 不透明
/> />
<ScrollView <ScrollView
contentContainerStyle={styles.scrollContent} contentContainerStyle={styles.scrollContent}
scrollEventThrottle={16} scrollEventThrottle={16}
nestedScrollEnabled={true} nestedScrollEnabled={true}
> >
<View style={styles.container}> <View style={styles.container}>
<TouchableOpacity onPress={handlePress}> <TouchableOpacity onPress={handlePress}>
<View style={styles.titBox}> <View style={styles.titBox}>
<Text <Text
style={styles.titTxts} style={styles.titTxts}
numberOfLines={1} numberOfLines={2}
ellipsizeMode="tail" ellipsizeMode="tail"
> >
VFLU-13762 {defaultDevice?.model || '未选择车辆'}
</Text> </Text>
<Image <Image
source={{ uri: 'https://api.ccttiot.com/smartmeter/img/static/uJRIitv0Yn5K7CEVe9qd' }} source={{ uri: 'https://api.ccttiot.com/smartmeter/img/static/uJRIitv0Yn5K7CEVe9qd' }}
style={{ width: rpx(24), height: rpx(14), marginLeft: rpx(8) }} style={styles.arrowIcon}
/>
</View>
</TouchableOpacity>
<View style={styles.KmBox}>
<View style={styles.KmLi}>
<View style={styles.KmLi_top}>
<Text style={styles.titTxt}>110</Text>
<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) }}
/> />
<Text style={styles.KmLi_tits1}></Text>
</View> </View>
</View>
<View style={styles.KmLi}>
<View style={styles.KmLi_top}>
<Text style={styles.titTxt}>110</Text>
<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) }}
/>
<Text style={styles.KmLi_tits1}></Text>
</View>
</View>
</View>
<View style={styles.infoBox}>
<View style={styles.eleBox}>
<View style={styles.eleType}>
<Text style={styles.eleTypeTxt}>90%</Text>
</View>
</View>
<View style={styles.carBox}>
<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' }}
/>
</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={styles.stauseText}></Text>
</View>
<Slider
onComplete={() => {
console.log('滑动完成');
// 处理滑动完成后的逻辑
}}
/>
<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={styles.stauseText}></Text>
</View>
</View>
<TouchableWithoutFeedback >
<View style={styles.mapWrapper}>
<MiniMap />
</View>
</TouchableWithoutFeedback>
<TouchableOpacity onPress={toSet}>
<Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/ucYQHQ2Ep4odL8JpbtfT' }}
style={styles.carSet}
/>
</TouchableOpacity>
<View style={styles.otherSet}>
<TouchableOpacity onPress={toShare}>
<Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/ulDHhC4MrH3FO0AeTqVg' }}
style={styles.otherImg}
/>
</TouchableOpacity> </TouchableOpacity>
<Image <View style={styles.KmBox}>
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/u849NsNxdtzxhUkUJnfW' }} <View style={styles.KmLi}>
style={styles.otherImg} <View style={styles.KmLi_top}>
/> <Text style={styles.titTxt}>{defaultDevice?.remainingMileage}</Text>
<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) }}
/>
<Text style={styles.KmLi_tits1}></Text>
</View>
</View>
<View style={styles.KmLi}>
<View style={styles.KmLi_top}>
<Text style={styles.titTxt}>110</Text>
<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) }}
/>
<Text style={styles.KmLi_tits1}></Text>
</View>
</View>
</View>
<View style={styles.infoBox}>
<View style={styles.eleBox}>
<View style={[
styles.eleType,
{
height: `${defaultDevice?.remainingPower || 0}%`,
backgroundColor: getPowerColor(defaultDevice?.remainingPower || 0)
}
]}>
<Text style={styles.eleTypeTxt}>{defaultDevice?.remainingPower || 0}%</Text>
</View>
</View>
<View style={styles.carBox}>
<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}> {defaultDevice?.lockStatus == 1 ? '开锁' : '关锁'}</Text>
</View>
</View>
<TouchableOpacity onPress={toTestBule}>
<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' }}
/>
</View>
</TouchableOpacity>
</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={styles.stauseText}></Text>
</View>
<Slider
lockStatus={defaultDevice?.lockStatus}
onStatusChange={(status) => {
// 处理状态改变
console.log('Lock status changed:', status);
}}
/>
<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={styles.stauseText}></Text>
</View>
</View>
<TouchableWithoutFeedback >
<View style={styles.mapWrapper}>
<MiniMap />
</View>
</TouchableWithoutFeedback>
<TouchableOpacity onPress={toSet}>
<Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/ucYQHQ2Ep4odL8JpbtfT' }}
style={styles.carSet}
/>
</TouchableOpacity>
<View style={styles.otherSet}>
<TouchableOpacity onPress={toShare}>
<Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/ulDHhC4MrH3FO0AeTqVg' }}
style={styles.otherImg}
/>
</TouchableOpacity>
<Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/u849NsNxdtzxhUkUJnfW' }}
style={styles.otherImg}
/>
</View>
</View> </View>
</View> </ScrollView>
</ScrollView>
</View> </View>
); );
}; };
@ -266,12 +310,12 @@ const styles = StyleSheet.create({
marginVertical: rpx(20), marginVertical: rpx(20),
}, },
stauseText: { stauseText: {
fontSize: rpx(32), fontSize: rpx(32),
color: '#3D3D3D', color: '#3D3D3D',
textAlign: 'center', textAlign: 'center',
marginTop: rpx(24) marginTop: rpx(24)
}, },
otherSet: { otherSet: {
marginTop: rpx(30), marginTop: rpx(30),
// display:f,\ // display:f,\
@ -355,14 +399,6 @@ const styles = StyleSheet.create({
borderRadius: rpx(11), borderRadius: rpx(11),
backgroundColor: 'rgba(255, 130, 130, 1)', backgroundColor: 'rgba(255, 130, 130, 1)',
}, },
eleTypeTxt: {
position: 'absolute',
top: rpx(16),
left: rpx(6),
fontSize: rpx(32),
color: '#3D3D3D',
fontWeight: 'bold'
},
eleBox: { eleBox: {
paddingTop: rpx(14), paddingTop: rpx(14),
paddingRight: rpx(6), paddingRight: rpx(6),
@ -371,29 +407,59 @@ const styles = StyleSheet.create({
width: rpx(86), width: rpx(86),
height: rpx(166), height: rpx(166),
borderRadius: rpx(16), borderRadius: rpx(16),
backgroundColor: '#fff' backgroundColor: '#FFFFFF',
justifyContent: 'flex-end',
// 添加阴影效果
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 4, // Android 阴影
// 添加边框使其更加醒目
borderWidth: 1,
borderColor: '#E0E0E0',
}, },
eleType: { eleType: {
width: '100%', width: '100%',
height: '100%', minHeight: rpx(30),
borderRadius: rpx(16), borderRadius: rpx(16),
backgroundColor: 'rgba(89,202,112,0.5)' position: 'relative',
},
eleTypeTxt: {
position: 'absolute',
top: rpx(-40),
width: '100%',
textAlign: 'center',
fontSize: rpx(32),
color: '#3D3D3D',
// fontWeight: 'bold',
// 为文字添加阴影效果使其更清晰
textShadowColor: 'rgba(255, 255, 255, 0.5)',
textShadowOffset: { width: 0, height: 1 },
textShadowRadius: 2
},
titBox: {
flexDirection: 'row',
alignItems: 'center',
display: 'flex',
flexWrap: 'nowrap',
maxWidth: rpx(600), // 增加最大宽度
}, },
titTxts: { titTxts: {
maxWidth: rpx(480), width: rpx(250),
fontSize: rpx(48), fontSize: rpx(48),
fontWeight: '500', fontWeight: '500',
color: '#3D3D3D', color: '#3D3D3D',
// flex: 2, // 添加 flex 属性
}, },
titBox: { arrowIcon: {
// width: rpx(750), width: rpx(24),
flexDirection: 'row', // 添加这行 height: rpx(14),
alignItems: 'center', // 添加这行 marginLeft: rpx(8)
// // 移除这些不需要的属性
display: 'flex',
flexWrap: 'nowrap',
// // flex: 1,
// justifyContent: 'center',
}, },
KmLi_bot: { KmLi_bot: {
marginTop: rpx(4), marginTop: rpx(4),

View File

@ -1,63 +1,237 @@
import React from 'react'; import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native'; import {
import { auth } from '../utils/auth'; StyleSheet,
ScrollView,
Image,
View,
TouchableOpacity,
ImageBackground
} from 'react-native';
import { Text } from '@ui-kitten/components';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
import { useAuth } from '../context/AuthContext'; // import axios from 'axios';
import { useAuth } from '../context/AuthContext';
import { rpx } from '../utils/rpx';
import { apiService } from '../utils/api';
const ProfileScreen = () => { const ProfileScreen = () => {
const navigation = useNavigation(); const navigation = useNavigation();
const { setIsLoggedIn } = useAuth(); // const { setIsLoggedIn } = useAuth();
const [userInfo, setUserInfo] = useState({});
const handleLogout = async () => { useEffect(() => {
getUserInfo();
}, []);
const formatName = (name) => {
if (!name) return '';
return name.charAt(0) + '*'.repeat(name.length - 1);
};
const getUserInfo = async () => {
try { try {
await auth.removeToken(); // token const response = await apiService.getUserInfo();
setIsLoggedIn(false); // if (response.code === 200) {
// AppNavigator isLoggedIn setUserInfo(response.user);
}
} catch (error) { } catch (error) {
console.error('退出登录失败:', error); console.error('获取用户信息失败:', error);
} }
}; };
return ( return (
<View style={styles.container}> <ImageBackground
<Text style={styles.title}>个人中心</Text> source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uYRs7Cv2Pbp95w3KjGO3' }}
style={styles.background}
<TouchableOpacity >
style={styles.logoutButton} <ScrollView style={styles.scrollView}>
onPress={handleLogout} <View style={styles.page}>
> {/* 头部区域 */}
<Text style={styles.logoutText}>退出登录</Text> <View style={styles.header}>
</TouchableOpacity> <View style={styles.headerLeft}>
</View> <Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/u3giTY4VkWYpnGWRuFHF' }}
style={styles.avatar}
/>
<View style={styles.userinfo}>
<Text style={styles.username}>
{formatName(userInfo.realName)}
</Text>
<Text style={styles.userphone}>
{userInfo.phonenumber}
</Text>
</View>
</View>
<TouchableOpacity
style={styles.headerRight}
onPress={() => navigation.navigate('QrBind')}
>
<Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uyb0iFo50FJ0MZg3RKkV' }}
style={styles.code}
/>
</TouchableOpacity>
</View>
{/* <Text style={styles.tit}>我的设备</Text> */}
{/* 管理与服务区域 */}
<Text style={styles.tit}>管理与服务</Text>
<View style={styles.content}>
<TouchableOpacity
style={styles.item}
onPress={() => navigation.navigate('OrderList')}
>
<Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uVEbrRDbZXvELwK73KAi' }}
style={styles.itemIcon}
/>
<Text style={styles.itemText}>我的订单</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.item}
onPress={() => navigation.navigate('HelpCenter')}
>
<Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uO1ju1OpuA5jjMR7bLYh' }}
style={styles.itemIcon}
/>
<Text style={styles.itemText}>帮助和客服</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.item}
onPress={() => navigation.navigate('Feedback')}
>
<Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uHNMNwTRw89NhtgZUNXK' }}
style={styles.itemIcon}
/>
<Text style={styles.itemText}>意见和反馈</Text>
</TouchableOpacity>
{userInfo.isAuthentication === false && (
<TouchableOpacity
style={styles.item}
onPress={() => navigation.navigate('IdVerification')}
>
<Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/unrltNyYYRXUutaqtuJY' }}
style={styles.itemIcon}
/>
<Text style={styles.itemText}>实名认证</Text>
</TouchableOpacity>
)}
{userInfo.userType === '02' && (
<TouchableOpacity
style={[styles.item, styles.lastItem]}
onPress={() => navigation.navigate('MerchantPortal')}
>
<Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/u1SsqJYSQ8jTK9PkhFtF' }}
style={styles.itemIcon}
/>
<Text style={styles.itemText}>商户端</Text>
</TouchableOpacity>
)}
</View>
{/* TabBar */}
{/* <View style={styles.tabBarContainer}>
<TabBar indexs={1} />
</View> */}
</View>
</ScrollView>
</ImageBackground>
); );
}; };
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { background: {
flex: 1, flex: 1,
alignItems: 'center', width: '100%',
backgroundColor: '#F3FCFF',
}, },
title: { scrollView: {
fontSize: 20, flex: 1,
fontWeight: 'bold',
marginTop: 20,
}, },
logoutButton: { page: {
position: 'absolute', flex: 1,
bottom: 40, paddingTop: rpx(200),
width: '90%', paddingHorizontal: rpx(32),
height: 44, },
backgroundColor: '#FF4D4F', header: {
borderRadius: 22, flexDirection: 'row',
justifyContent: 'center', justifyContent: 'space-between',
alignItems: 'center', alignItems: 'center',
}, },
logoutText: { headerLeft: {
color: '#FFFFFF', flexDirection: 'row',
fontSize: 16, alignItems: 'center',
fontWeight: '500',
}, },
avatar: {
width: rpx(108),
height: rpx(108),
borderRadius: rpx(54),
},
userinfo: {
marginLeft: rpx(40),
},
username: {
fontWeight: '700',
fontSize: rpx(36),
color: '#3D3D3D',
},
userphone: {
fontWeight: '400',
fontSize: rpx(28),
color: '#3D3D3D',
},
headerRight: {
flexDirection: 'row',
alignItems: 'center',
},
code: {
width: rpx(40),
height: rpx(40),
},
tit: {
marginTop: rpx(40),
fontWeight: '700',
fontSize: rpx(36),
color: '#3D3D3D',
},
content: {
marginTop: rpx(24),
width: rpx(688),
padding: rpx(42),
backgroundColor: '#FFFFFF',
borderRadius: rpx(30),
},
item: {
width: '100%',
paddingVertical: rpx(34),
flexDirection: 'row',
alignItems: 'center',
borderBottomWidth: 1,
borderBottomColor: '#D8D8D8',
},
lastItem: {
borderBottomWidth: 0,
},
itemIcon: {
width: rpx(38),
height: rpx(38),
marginTop: rpx(4),
marginRight: rpx(34),
},
itemText: {
fontWeight: '400',
fontSize: rpx(32),
color: '#3D3D3D',
},
tabBarContainer: {
marginLeft: rpx(-32),
}
}); });
export default ProfileScreen; export default ProfileScreen;

View File

@ -1,225 +1,311 @@
import React, { useState } from 'react'; import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, ScrollView, Image, TouchableOpacity } from 'react-native'; import { View, StyleSheet, ScrollView, Image, TouchableOpacity, SafeAreaView } from 'react-native';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
import {
TopNavigation,
TopNavigationAction,
Icon,
Text,
Layout,
Spinner
} from '@ui-kitten/components';
import { rpx } from '../../utils/rpx'; import { rpx } from '../../utils/rpx';
import { apiService } from '../../utils/api';
type CarItem = { type CarItem = {
id: number; id: number;
title: string; sn: string;
vehicleNum: string;
model: string; model: string;
status: string; remainingPower: number;
isShared: boolean; remainingMileage: number;
isDefault: number;
}; };
const BackIcon = (props: any) => (
<Icon {...props} name='arrow-back-outline'/>
);
export default function DeviceList() { export default function DeviceList() {
const navigation = useNavigation(); const navigation = useNavigation();
const [selectedItem, setSelectedItem] = useState<number | null>(null); const [devices, setDevices] = useState<CarItem[]>([]);
const handlePress = () => { const [loading, setLoading] = useState(true);
navigation.navigate('BindIndex' as never);
// console.log(navigation);
};
const handleCancel = () => { useEffect(() => {
navigation.goBack(); fetchDeviceList();
}; }, []);
// 示例数据保持不变 const fetchDeviceList = async () => {
const carList: CarItem[] = [ try {
setLoading(true);
{ const response = await apiService.getDeviceList();
id: 1, if (response?.code === 200 && response.data) {
title: '备注1376', setDevices(response.data);
model: '车型:飞过的魔毯不须归于温暖', }
status: '车辆登入X小时出租', } catch (error) {
isShared: false, console.error('获取设备列表失败:', error);
}, } finally {
{ setLoading(false);
id: 2, }
title: '备注1376',
model: '车型:飞过的魔毯不须归于温暖',
status: '车辆登入X小时出租',
isShared: true,
},
];
const toggleSelect = (id: number) => {
setSelectedItem(prev => prev === id ? null : id);
}; };
const renderCarItem = (item: CarItem) => ( const handlePress = () => {
<View key={item.id} style={[styles.carItem, item.id !== 1 && styles.marginTop]}> navigation.navigate('BindIndex' as never);
};
const handleCancel = () => {
navigation.goBack();
};
const selectCar = async (item: CarItem) => {
try {
const response = await apiService.toggleDefault(item.sn);
if (response.code === 200) {
console.log(response,'response');
fetchDeviceList();
// TODO: 添加成功提示
}
} catch (error) {
console.error('切换默认车辆失败:', error);
}
};
const renderBackAction = () => (
<TopNavigationAction icon={BackIcon} onPress={handleCancel}/>
);
const renderPowerIcons = (power: number) => {
const icons = [];
const fullPowerIcon = 'https://lxnapi.ccttiot.com/bike/img/static/uhxmJlps8lrRRTmBIFpl';
const emptyPowerIcon = 'https://lxnapi.ccttiot.com/bike/img/static/u1CcbtQydd107cOUEZ1l';
const powerPerGrid = power / 10;
for (let i = 0; i < 10; i++) {
icons.push(
<Image
key={`power-${i}`}
source={{ uri: i < Math.floor(powerPerGrid) ? fullPowerIcon : emptyPowerIcon }}
style={styles.powerIcon}
/>
);
}
return icons;
};
const renderCarItem = (item: CarItem, index: number) => (
<TouchableOpacity
key={`device-${item.sn}-${index}`}
style={[styles.carItem, index !== 0 && styles.marginTop]}
onPress={() => selectCar(item)}
>
<View style={styles.leftContent}> <View style={styles.leftContent}>
<Text style={styles.title}>{item.title}</Text> <View style={styles.carInfo}>
<Text style={styles.subTitle}>{item.model}</Text> <Image
<Text style={styles.status}>{item.status}</Text> source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uUIunSd0CSU3ovogLJHk' }}
<Text style={[styles.tag, item.isShared && styles.tagShare]}> style={styles.titleIcon}
{item.isShared ? '临时共享' : '车主'} />
</Text> <View style={styles.power}>
{renderPowerIcons(item.remainingPower)}
</View>
<Text style={styles.mileage}>{item.remainingMileage}KM</Text>
</View>
<Text style={styles.model}>{item.model}</Text>
<Text style={styles.carNum}>{item.vehicleNum}</Text>
<Text style={styles.status}></Text>
</View> </View>
<View style={styles.rightContent}> <View style={styles.rightContent}>
<Image <Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uVnIDwcwQP7oo12PeYVJ' }} source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uB1F5aibooguILH8uB4F' }}
style={styles.carImage} style={styles.carImage}
/> />
<View style={styles.checkboxWrapper}> <View style={styles.checkboxWrapper}>
<Text style={styles.checkboxText}></Text> <Text style={styles.checkboxText}></Text>
<TouchableOpacity <Image
onPress={() => toggleSelect(item.id)} source={{
style={styles.checkboxContainer} uri: item.isDefault == 1
> ? 'https://lxnapi.ccttiot.com/bike/img/static/uj7bE7GMcCm6g2igeo7k'
<Image : 'https://lxnapi.ccttiot.com/bike/img/static/uN3QtzNuM2CMTLUm3joR'
source={{ }}
uri: selectedItem === item.id style={styles.checkboxImage}
? 'https://api.ccttiot.com/smartmeter/img/static/u4alnzo5240dlVnSQK0r' />
: 'https://api.ccttiot.com/smartmeter/img/static/uj2puOsyrcZY4ygZL6GX'
}}
style={styles.checkboxImage}
/>
</TouchableOpacity>
</View> </View>
</View> </View>
</View> </TouchableOpacity>
); );
return ( return (
<View style={styles.container}> <SafeAreaView style={styles.container}>
<ScrollView style={styles.scrollContent}> <TopNavigation
{carList.map(item => renderCarItem(item))} title="选择车辆"
</ScrollView> alignment="center"
accessoryLeft={renderBackAction}
style={styles.topNav}
/>
{loading ? (
<View style={styles.loadingContainer}>
<Spinner size="large"/>
</View>
) : (
<>
<ScrollView style={styles.scrollContent}>
{devices.length > 0 ? (
devices.map((device, index) => renderCarItem(device, index))
) : (
<View style={styles.noDataContainer}>
<Text category="s1"></Text>
</View>
)}
</ScrollView>
<View style={styles.bottomButtons}> <View style={styles.bottomButtons}>
<TouchableOpacity onPress={handlePress} style={styles.addButton}> <TouchableOpacity onPress={handlePress} style={styles.addButton}>
<Text style={styles.addButtonText}>+ </Text> <Text style={styles.addButtonText}>+ </Text>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity onPress={handleCancel} style={styles.cancelButton}> <TouchableOpacity onPress={handleCancel} style={styles.cancelButton}>
<Text style={styles.cancelButtonText}></Text> <Text style={styles.cancelButtonText}></Text>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
</View> </>
)}
</SafeAreaView>
); );
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
backgroundColor: '#F3FCFF', backgroundColor: '#fff',
},
topNav: {
backgroundColor: '#fff',
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
noDataContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingTop: rpx(100),
}, },
scrollContent: { scrollContent: {
marginBottom: rpx(300),
flex: 1, flex: 1,
paddingHorizontal: rpx(20), paddingHorizontal: rpx(40),
// marginBottom: rpx(160),
}, },
carItem: { carItem: {
flexDirection: 'row', flexDirection: 'row',
backgroundColor: '#EEF2FD', backgroundColor: '#EEF2FD',
borderRadius: rpx(20), borderRadius: rpx(28),
padding: rpx(30), padding: rpx(48),
marginTop: rpx(20), marginTop: rpx(20),
alignItems: 'center',
}, },
marginTop: { marginTop: {
marginTop: rpx(20), marginTop: rpx(20),
}, },
leftContent: { leftContent: {
flex: 1, flex: 1,
justifyContent: 'center',
}, },
rightContent: { carInfo: {
flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
justifyContent: 'center',
marginLeft: rpx(20),
}, },
title: { titleIcon: {
fontSize: rpx(40), width: rpx(30),
fontWeight: '500', height: rpx(30),
color: '#3D3D3D', marginRight: rpx(12),
marginBottom: rpx(16), marginBottom: rpx(8),
}, },
subTitle: { power: {
fontWeight: '500', flexDirection: 'row',
fontSize: rpx(24), alignItems: 'center',
marginRight: rpx(12),
},
powerIcon: {
width: rpx(18),
height: rpx(36),
},
mileage: {
fontSize: rpx(36),
fontWeight: '700',
color: '#3D3D3D',
},
model: {
marginTop: rpx(15),
fontSize: rpx(32),
fontWeight: '700',
color: '#3D3D3D',
},
carNum: {
marginTop: rpx(15),
fontSize: rpx(32),
fontWeight: '700',
color: '#3D3D3D', color: '#3D3D3D',
marginBottom: rpx(12),
}, },
status: { status: {
fontSize: rpx(24), marginTop: rpx(20),
color: '#666', paddingVertical: rpx(8),
marginBottom: rpx(16), paddingHorizontal: rpx(19),
},
tag: {
alignSelf: 'flex-start',
paddingVertical: rpx(6),
paddingHorizontal: rpx(30),
backgroundColor: '#D2E8FF', backgroundColor: '#D2E8FF',
borderRadius: rpx(29), borderRadius: rpx(29),
fontSize: rpx(24), fontSize: rpx(28),
color: '#4297F3', color: '#4297F3',
marginTop: rpx(10), alignSelf: 'flex-start',
fontWeight: '500' fontWeight: '500',
}, },
tagShare: { rightContent: {
color: '#FF9500', marginLeft: 'auto',
backgroundColor: '#FFEEDE' width: rpx(200),
alignItems: 'center',
}, },
carImage: { carImage: {
width: rpx(232), width: rpx(212),
height: rpx(180), height: rpx(164),
marginBottom: rpx(16),
},
checkboxContainer: {
width: rpx(44),
height: rpx(44),
justifyContent: 'center',
alignItems: 'center',
}, },
checkboxWrapper: { checkboxWrapper: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
marginTop: rpx(22),
}, },
checkboxText: { checkboxText: {
fontSize: rpx(32), fontSize: rpx(30),
color: '#3D3D3D', color: '#3D3D3D',
marginRight: rpx(8), marginRight: rpx(12),
}, },
checkboxImage: { checkboxImage: {
width: rpx(44), width: rpx(29),
height: rpx(44), height: rpx(29),
resizeMode: 'contain',
}, },
bottomButtons: { bottomButtons: {
position: 'absolute', padding: rpx(38),
bottom: rpx(30),
left: 0,
right: 0,
padding: rpx(20),
backgroundColor: '#F3FCFF',
}, },
addButton: { addButton: {
backgroundColor: '#4297F3',
height: rpx(92), height: rpx(92),
borderRadius: rpx(20), backgroundColor: '#4297F3',
borderRadius: rpx(16),
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
marginBottom: rpx(20), marginBottom: rpx(20),
}, },
addButtonText: { addButtonText: {
fontSize: rpx(40),
fontWeight: '500',
color: '#FFFFFF', color: '#FFFFFF',
fontSize: rpx(32),
}, },
cancelButton: { cancelButton: {
backgroundColor: '#fff',
height: rpx(92), height: rpx(92),
borderRadius: rpx(20), backgroundColor: '#fff',
borderRadius: rpx(16),
borderWidth: rpx(2), borderWidth: rpx(2),
borderColor: '#4297F3', borderColor: '#4297F3',
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
}, },
cancelButtonText: { cancelButtonText: {
fontSize: rpx(40),
fontWeight: '500',
color: '#4297F3', color: '#4297F3',
fontSize: rpx(32),
}, },
}); });

View File

@ -0,0 +1,46 @@
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { TopNavigation, TopNavigationAction, Icon, Text } from '@ui-kitten/components';
import { useNavigation } from '@react-navigation/native';
const BackIcon = (props) => (
<Icon {...props} name='arrow-back' />
);
const TestBule = () => {
const navigation = useNavigation();
const navigateBack = () => {
navigation.goBack();
};
const BackAction = () => (
<TopNavigationAction icon={BackIcon} onPress={navigateBack} />
);
return (
<View style={styles.container}>
<TopNavigation
title="蓝牙测试"
alignment="center"
accessoryLeft={BackAction}
/>
<View style={styles.content}>
<Text>TestBule</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
content: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
export default TestBule;