11
This commit is contained in:
parent
a868525bb4
commit
17c5a983e6
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -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",
|
||||||
|
|
|
@ -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);
|
|
@ -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"
|
||||||
|
|
|
@ -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 (
|
||||||
|
|
|
@ -27,6 +27,7 @@ export type HomeStackParamList = {
|
||||||
DeviceShare: undefined;
|
DeviceShare: undefined;
|
||||||
AddShare: undefined;
|
AddShare: undefined;
|
||||||
ShareQrcode: undefined;
|
ShareQrcode: undefined;
|
||||||
|
TestBule: undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 导航属性类型
|
// 导航属性类型
|
||||||
|
|
|
@ -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}`),
|
||||||
};
|
};
|
|
@ -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);
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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;
|
|
@ -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),
|
|
||||||
},
|
},
|
||||||
});
|
});
|
46
src/views/device/test_bule.tsx
Normal file
46
src/views/device/test_bule.tsx
Normal 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;
|
Loading…
Reference in New Issue
Block a user