bookingTabViewComponent.tsx 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import React, { useState, useCallback, useEffect } from 'react';
  2. import { ActivityIndicator, View, RefreshControl } from 'react-native';
  3. import { useQuery, QueryClient, QueryClientProvider } from '@tanstack/react-query';
  4. import TabViewComponent, { TabItem } from './chargingRecord';
  5. import { chargeStationService } from '../../service/chargeStationService';
  6. import { useTranslation } from '../../util/hooks/useTranslation';
  7. const queryClient = new QueryClient();
  8. // 更新 findStationByConnectorId 函数以增加安全性
  9. const findStationByConnectorId = (allStations: any[], targetConnectorId: string) => {
  10. if (!Array.isArray(allStations) || !targetConnectorId) {
  11. return undefined;
  12. }
  13. return allStations.find((station) =>
  14. station?.snapshot?.EquipmentInfos?.some((equipment: any) =>
  15. equipment?.ConnectorInfos?.some((connector: any) => connector?.ConnectorID === targetConnectorId)
  16. )
  17. );
  18. };
  19. const fetchReservationsAndStations = async () => {
  20. try {
  21. const [reservationResponse, allStationsResponse] = await Promise.allSettled([
  22. chargeStationService.fetchReservationHistories(),
  23. chargeStationService.fetchAllChargeStations()
  24. ]);
  25. const reservations = reservationResponse.status === 'fulfilled' ? reservationResponse.value : [];
  26. const stations = allStationsResponse.status === 'fulfilled' ? allStationsResponse.value : [];
  27. return {
  28. reservations: Array.isArray(reservations) ? reservations : [],
  29. stations: Array.isArray(stations) ? stations : []
  30. };
  31. } catch (error) {
  32. return { reservations: [], stations: [] };
  33. }
  34. };
  35. const processReservations = (reservations: any [], allStations: string [], isFuture: boolean, isEn: boolean): TabItem[] => {
  36. // 确保参数是数组类型
  37. const validReservations = Array.isArray(reservations) ? reservations : [];
  38. const validStations = Array.isArray(allStations) ? allStations : [];
  39. const now = Date.now();
  40. return validReservations
  41. .filter((reservation) => {
  42. // 添加安全检查
  43. if (!reservation || !reservation.end_time) return false;
  44. const endTime = Date.parse(reservation.end_time);
  45. if (isNaN(endTime)) return false;
  46. return isFuture ? endTime > now : endTime <= now;
  47. })
  48. .sort((a, b) => {
  49. // 添加安全检查
  50. if (!a?.end_time || !b?.end_time) return 0;
  51. const aTime = Date.parse(a.end_time);
  52. const bTime = Date.parse(b.end_time);
  53. if (isNaN(aTime) || isNaN(bTime)) return 0;
  54. return isFuture ? aTime - bTime : bTime - aTime;
  55. })
  56. .slice(0, 33)
  57. .map((reservation) => {
  58. // 添加对 reservation 的安全检查
  59. if (!reservation) {
  60. return {} as TabItem; // 返回默认对象
  61. }
  62. let snapshot = {} as any;
  63. let snapshot_price = {} as any;
  64. try {
  65. snapshot = reservation.connector.EquipmentID.StationID.snapshot ? JSON.parse(reservation.connector.EquipmentID.StationID.snapshot) : {};
  66. snapshot_price = reservation.snapshot ? JSON.parse(reservation.snapshot) : {};
  67. } catch (e) {
  68. console.warn('Error parsing snapshot:', e);
  69. }
  70. let stationInfo = null;
  71. if (snapshot?.StationID) {
  72. stationInfo = validStations.find((station: any) => station?.id === snapshot.StationID);
  73. } else if (snapshot?.connector) {
  74. stationInfo = findStationByConnectorId(validStations, snapshot.connector);
  75. }
  76. // 确保时间字段存在
  77. const bookTime = reservation.book_time ? new Date(reservation.book_time) : new Date();
  78. const actualEndTime = reservation.actual_end_time ? new Date(reservation.actual_end_time) : new Date();
  79. const img = stationInfo?.image
  80. ? { uri: stationInfo?.image }
  81. : require('../../assets/dummyStationPicture.png');
  82. return {
  83. imgURL: img,
  84. date: `${bookTime.getMonth() + 1}月${bookTime.getDate()}`,
  85. time: bookTime.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit', hour12: false }),
  86. actual_end_time: actualEndTime.toLocaleTimeString('zh-CN', {
  87. hour: '2-digit',
  88. minute: '2-digit',
  89. hour12: false
  90. }),
  91. chargeStationName: (isEn? stationInfo?.snapshoten?.StationName : stationInfo?.snapshot?.StationName) || 'Unknown Station',
  92. chargeStationAddress: stationInfo?.snapshot?.Address || 'Unknown Address',
  93. stationLng: stationInfo?.snapshot?.StationLng || '',
  94. stationLat: stationInfo?.snapshot?.StationLat || '',
  95. distance: '',
  96. format_order_id: reservation.format_order_id || '',
  97. actual_total_power: reservation.actual_total_power || 0,
  98. total_fee: reservation.total_fee || 0,
  99. withdraw_fee: reservation.withdraw_fee || 0,
  100. actual_fee: (reservation.total_fee || 0) - (reservation.withdraw_fee || 0),
  101. current_price: snapshot_price?.current_price || 0,
  102. total_power: reservation.total_power || 0,
  103. id: reservation.id || '',
  104. status: reservation.status || {}
  105. } as TabItem;
  106. });
  107. };
  108. const BookingTabViewComponentInner: React.FC = () => {
  109. const { t, getCurrentLanguageConfig } = useTranslation(); // 使用翻译钩子
  110. const isEn = getCurrentLanguageConfig()?.code === 'en';
  111. const { data, isLoading, error } = useQuery({
  112. queryKey: ['reservationsAndStations'],
  113. queryFn: fetchReservationsAndStations,
  114. staleTime: 0,
  115. gcTime: 0,
  116. refetchOnMount: true,
  117. refetchOnWindowFocus: true
  118. });
  119. if (isLoading) {
  120. return (
  121. <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
  122. <ActivityIndicator size="large" color="#34657b" />
  123. </View>
  124. );
  125. }
  126. if (error) {
  127. console.log('Error fetching data:', error);
  128. return null;
  129. }
  130. if (!data) {
  131. return null;
  132. }
  133. // 确保即使 data 为 undefined 也能安全处理
  134. const reservations = Array.isArray(data?.reservations) ? data.reservations : [];
  135. const stations = Array.isArray(data?.stations) ? data.stations : [];
  136. const futureReservations = processReservations(reservations, stations, true, isEn);
  137. const completedReservations = processReservations(reservations, stations, false, isEn);
  138. const allReservationItems = [...futureReservations, ...completedReservations];
  139. return (
  140. <TabViewComponent
  141. tabItems={allReservationItems}
  142. isLoading={false}
  143. />
  144. );
  145. };
  146. const BookingTabViewComponent: React.FC = (props) => (
  147. <QueryClientProvider client={queryClient}>
  148. <BookingTabViewComponentInner {...props} />
  149. </QueryClientProvider>
  150. );
  151. export default BookingTabViewComponent;