BikeApp_demo/src/views/device/deviceList.tsx
2024-12-18 16:21:19 +08:00

311 lines
7.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState, useEffect } from 'react';
import { View, StyleSheet, ScrollView, Image, TouchableOpacity, SafeAreaView } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import {
TopNavigation,
TopNavigationAction,
Icon,
Text,
Layout,
Spinner
} from '@ui-kitten/components';
import { rpx } from '../../utils/rpx';
import { apiService } from '../../utils/api';
type CarItem = {
id: number;
sn: string;
vehicleNum: string;
model: string;
remainingPower: number;
remainingMileage: number;
isDefault: number;
};
const BackIcon = (props: any) => (
<Icon {...props} name='arrow-back-outline'/>
);
export default function DeviceList() {
const navigation = useNavigation();
const [devices, setDevices] = useState<CarItem[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchDeviceList();
}, []);
const fetchDeviceList = async () => {
try {
setLoading(true);
const response = await apiService.getDeviceList();
if (response?.code === 200 && response.data) {
setDevices(response.data);
}
} catch (error) {
console.error('获取设备列表失败:', error);
} finally {
setLoading(false);
}
};
const handlePress = () => {
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.carInfo}>
<Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uUIunSd0CSU3ovogLJHk' }}
style={styles.titleIcon}
/>
<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 style={styles.rightContent}>
<Image
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uB1F5aibooguILH8uB4F' }}
style={styles.carImage}
/>
<View style={styles.checkboxWrapper}>
<Text style={styles.checkboxText}></Text>
<Image
source={{
uri: item.isDefault == 1
? 'https://lxnapi.ccttiot.com/bike/img/static/uj7bE7GMcCm6g2igeo7k'
: 'https://lxnapi.ccttiot.com/bike/img/static/uN3QtzNuM2CMTLUm3joR'
}}
style={styles.checkboxImage}
/>
</View>
</View>
</TouchableOpacity>
);
return (
<SafeAreaView style={styles.container}>
<TopNavigation
title="选择车辆"
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}>
<TouchableOpacity onPress={handlePress} style={styles.addButton}>
<Text style={styles.addButtonText}>+ </Text>
</TouchableOpacity>
<TouchableOpacity onPress={handleCancel} style={styles.cancelButton}>
<Text style={styles.cancelButtonText}></Text>
</TouchableOpacity>
</View>
</>
)}
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
topNav: {
backgroundColor: '#fff',
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
noDataContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingTop: rpx(100),
},
scrollContent: {
flex: 1,
paddingHorizontal: rpx(40),
},
carItem: {
flexDirection: 'row',
backgroundColor: '#EEF2FD',
borderRadius: rpx(28),
padding: rpx(48),
marginTop: rpx(20),
},
marginTop: {
marginTop: rpx(20),
},
leftContent: {
flex: 1,
},
carInfo: {
flexDirection: 'row',
alignItems: 'center',
},
titleIcon: {
width: rpx(30),
height: rpx(30),
marginRight: rpx(12),
marginBottom: rpx(8),
},
power: {
flexDirection: 'row',
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',
},
status: {
marginTop: rpx(20),
paddingVertical: rpx(8),
paddingHorizontal: rpx(19),
backgroundColor: '#D2E8FF',
borderRadius: rpx(29),
fontSize: rpx(28),
color: '#4297F3',
alignSelf: 'flex-start',
fontWeight: '500',
},
rightContent: {
marginLeft: 'auto',
width: rpx(200),
alignItems: 'center',
},
carImage: {
width: rpx(212),
height: rpx(164),
},
checkboxWrapper: {
flexDirection: 'row',
alignItems: 'center',
marginTop: rpx(22),
},
checkboxText: {
fontSize: rpx(30),
color: '#3D3D3D',
marginRight: rpx(12),
},
checkboxImage: {
width: rpx(29),
height: rpx(29),
},
bottomButtons: {
padding: rpx(38),
},
addButton: {
height: rpx(92),
backgroundColor: '#4297F3',
borderRadius: rpx(16),
justifyContent: 'center',
alignItems: 'center',
marginBottom: rpx(20),
},
addButtonText: {
fontSize: rpx(40),
fontWeight: '500',
color: '#FFFFFF',
},
cancelButton: {
height: rpx(92),
backgroundColor: '#fff',
borderRadius: rpx(16),
borderWidth: rpx(2),
borderColor: '#4297F3',
justifyContent: 'center',
alignItems: 'center',
},
cancelButtonText: {
fontSize: rpx(40),
fontWeight: '500',
color: '#4297F3',
},
});