Files
oneapp_docs/app_car/app_charging.md
2025-09-24 14:08:54 +08:00

900 lines
27 KiB
Markdown
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.

# App Charging - 充电管理模块文档
## 模块概述
`app_charging` 是 OneApp 的充电管理核心模块提供完整的电动车充电功能包括充电地图、充电站查找、订单管理、支付结算等全流程充电服务。该模块集成了高德地图服务、BLoC状态管理、路由导航等为用户提供便捷的充电体验。
### 基本信息
- **模块名称**: app_charging
- **路径**: oneapp_app_car/app_charging/
- **依赖**: car_services, car_vehicle, clr_charging, basic_modular
- **主要功能**: 充电地图、充电站搜索、订单管理、智能寻桩
## 目录结构
```
app_charging/
├── lib/
│ ├── app_charging.dart # 主导出文件
│ ├── generated/ # 代码生成文件
│ ├── l10n/ # 国际化文件
│ └── src/ # 源代码目录
│ ├── app_charging_module.dart # 充电模块配置
│ ├── blocs/ # 状态管理BLoC
│ ├── carfinder/ # 车辆查找功能
│ ├── constants/ # 常量定义
│ ├── pages/ # 页面组件
│ │ └── public_charging/ # 公共充电页面
│ │ ├── charging_map_home_page/ # 充电地图首页
│ │ ├── charging_station_detail_page/ # 充电站详情
│ │ ├── charging_query_order_list_page/ # 订单列表
│ │ ├── charging_report_page/ # 充电报告
│ │ ├── charging_smart_pile_finding_page/ # 智能寻桩
│ │ └── ... # 其他充电功能页面
│ ├── utils/ # 工具类
│ ├── route_dp.dart # 路由配置
│ ├── route_export.dart # 路由导出
│ └── switch_vehicle.dart # 车辆切换功能
├── assets/ # 静态资源
└── README.md # 项目说明
```
# App Charging - 充电管理模块文档
## 模块概述
`app_charging` 是 OneApp 的充电管理核心模块提供完整的电动车充电功能包括充电地图、充电站查找、订单管理、支付结算等全流程充电服务。该模块集成了高德地图服务、BLoC状态管理、路由导航等为用户提供便捷的充电体验。
### 基本信息
- **模块名称**: app_charging
- **路径**: oneapp_app_car/app_charging/
- **依赖**: car_services, car_vehicle, clr_charging, basic_modular
- **主要功能**: 充电地图、充电站搜索、订单管理、智能寻桩
## 目录结构
```
app_charging/
├── lib/
│ ├── app_charging.dart # 主导出文件
│ ├── generated/ # 代码生成文件
│ ├── l10n/ # 国际化文件
│ └── src/ # 源代码目录
│ ├── app_charging_module.dart # 充电模块配置
│ ├── blocs/ # 状态管理BLoC
│ ├── carfinder/ # 车辆查找功能
│ ├── constants/ # 常量定义
│ ├── pages/ # 页面组件
│ │ └── public_charging/ # 公共充电页面
│ │ ├── charging_map_home_page/ # 充电地图首页
│ │ ├── charging_station_detail_page/ # 充电站详情
│ │ ├── charging_query_order_list_page/ # 订单列表
│ │ ├── charging_report_page/ # 充电报告
│ │ ├── charging_smart_pile_finding_page/ # 智能寻桩
│ │ ├── charging_coupon_page/ # 充电优惠券
│ │ ├── charging_power_monitor_page/ # 功率监控
│ │ └── ... # 其他充电功能页面
│ ├── utils/ # 工具类
│ ├── route_dp.dart # 路由配置
│ ├── route_export.dart # 路由导出
│ └── switch_vehicle.dart # 车辆切换功能
├── assets/ # 静态资源
└── README.md # 项目说明
```
## 核心实现
### 1. 模块主导出文件
**文件**: `lib/app_charging.dart`
```dart
/// charging pages
library app_charging;
export 'package:car_services/services.dart';
export 'package:car_vehicle/vehicle.dart';
export 'src/app_charging_module.dart';
export 'src/pages/public_charging/charging_map_card/charging_map_card.dart';
export 'src/pages/public_charging/charging_map_home_page/charging_map_home_page.dart';
export 'src/pages/public_charging/charging_query_order_list_page/charging_query_order_list_page.dart';
// 路由键导出
export 'src/route_dp.dart' show ChargingReservationRouteKey;
export 'src/route_dp.dart' show CarChargingCouponRouteKey;
export 'src/route_dp.dart' show ChargingCpoCollectionRouteKey;
export 'src/route_dp.dart' show ChargingDetectiveRouteKey;
export 'src/route_dp.dart' show ChargingMapHomeNonOwnerRouteKey;
export 'src/route_dp.dart' show ChargingMapHomeRouteKey;
export 'src/route_dp.dart' show ChargingPowerMonitorResultRouteKey;
export 'src/route_dp.dart' show ChargingPowerMonitorRouteKey;
export 'src/route_dp.dart' show ChargingPrePaySettingRouteKey;
export 'src/route_dp.dart' show ChargingQueryOrderDetailRouteKey;
export 'src/route_dp.dart' show ChargingQueryOrderListRouteKey;
export 'src/route_dp.dart' show ChargingQueryRatingRouteKey;
export 'src/route_dp.dart' show ChargingReportRouteKey;
export 'src/route_dp.dart' show ChargingSmartPileFindingRouteKey;
export 'src/route_dp.dart' show ChargingStationDetailRouteKey;
export 'src/route_dp.dart' show ChargingStationGuideRouteKey;
export 'src/route_dp.dart' show ChargingVehicleReportRouteKey;
export 'src/route_export.dart';
```
### 2. 模块定义与依赖管理
**文件**: `src/app_charging_module.dart`
```dart
import 'package:basic_logger/basic_logger.dart';
import 'package:basic_modular/modular.dart';
import 'package:basic_modular_route/basic_modular_route.dart';
import 'package:clr_account/account.dart';
import 'package:clr_charging/clr_charging.dart';
import 'package:ui_basic/ui_basic.dart';
import 'constants/module_constant.dart';
import 'route_export.dart';
/// 充电模块定义
class AppChargingModule extends Module with RouteObjProvider, AppLifeCycleListener {
@override
List<Bind<Object>> get binds => [];
@override
List<Module> get imports => [AccountConModule(), ClrChargingModule()];
@override
List<ModularRoute> get routes {
// 模块首页
final moduleHome = RouteCenterAPI.routeMetaBy(AppChargingRouteExport.keyModule);
// 充电地图首页
final chargingMapHome = RouteCenterAPI.routeMetaBy(AppChargingRouteExport.keyChargingMapHome);
// 搜索首页
final searchHome = RouteCenterAPI.routeMetaBy(AppChargingRouteExport.keySearchHome);
// CPO收藏页面
final cpoCollection = RouteCenterAPI.routeMetaBy(AppChargingRouteExport.keyChargingCpoCollection);
// 充电站详情页面
final stationDetailPage = RouteCenterAPI.routeMetaBy(AppChargingRouteExport.keyStationDetailPage);
// 电价页面
final electricPricePage = RouteCenterAPI.routeMetaBy(AppChargingRouteExport.keyStationElectricPricePage);
return [
ChildRoute<dynamic>(moduleHome.path, child: (_, args) => moduleHome.provider(args).as()),
ChildRoute<dynamic>(chargingMapHome.path, child: (_, args) => chargingMapHome.provider(args).as()),
ChildRoute<dynamic>(searchHome.path, child: (_, args) => searchHome.provider(args).as()),
ChildRoute<dynamic>(cpoCollection.path, child: (_, args) => cpoCollection.provider(args).as()),
ChildRoute<dynamic>(stationDetailPage.path, child: (_, args) => stationDetailPage.provider(args).as()),
ChildRoute<dynamic>(electricPricePage.path, child: (_, args) => electricPricePage.provider(args).as()),
// 更多路由配置...
];
}
}
```
### 3. 路由导出管理
**文件**: `src/route_export.dart`
```dart
import 'dart:convert';
import 'package:amap_flutter_base/amap_flutter_base.dart';
import 'package:basic_logger/basic_logger.dart';
import 'package:basic_modular/modular.dart';
import 'package:clr_charging/clr_charging.dart';
import 'package:clr_geo/clr_geo.dart';
import 'app_charging_module.dart';
import 'pages/public_charging/charging_map_home_page/charging_map_home_page.dart';
import 'pages/public_charging/charging_station_detail_page/charging_station_detail_page.dart';
import 'pages/public_charging/charging_query_order_list_page/charging_query_order_list_page.dart';
import 'pages/public_charging/charging_smart_pile_finding_page/charging_smart_pile_finding_page.dart';
// ... 更多页面导入
/// app_charging的路由管理
class AppChargingRouteExport implements RouteExporter {
// 路由键常量定义
static const String keyModule = 'charging';
static const String keyChargingMapHome = 'charging.map_home';
static const String keySearchHome = 'charging.search_home';
static const String keyChargingCpoCollection = 'charging.cpo_collection';
static const String keyStationDetailPage = 'charging.station_detail';
static const String keyStationElectricPricePage = 'charging.electric_price';
static const String keyQueryOrderListPage = 'charging.order_list';
static const String keySmartPileFinding = 'charging.smart_pile_finding';
static const String keyChargingReport = 'charging.report';
static const String keyPowerMonitor = 'charging.power_monitor';
// ... 更多路由键定义
@override
List<RouteMeta> exportRoutes() {
// 模块根路由
final r0 = RouteMeta(keyModule, '/charging', (args) => AppChargingModule(), null);
// 充电地图首页
final r1 = RouteMeta(
keyChargingMapHome,
'/map_home',
(args) => ChargingMapHomePage(args.data['vin'] as String?),
r0,
);
// 充电站详情页面
final r2 = RouteMeta(
keyStationDetailPage,
'/station_detail',
(args) => ChargingStationDetailPage(
stationID: args.data['stationID'] as String,
chargingVin: args.data['chargingVin'] as String?,
),
r0,
);
// 智能寻桩页面
final r3 = RouteMeta(
keySmartPileFinding,
'/smart_pile_finding',
(args) => ChargingSmartPileFindingPage(
vin: args.data['vin'] as String,
),
r0,
);
// 订单列表页面
final r4 = RouteMeta(
keyQueryOrderListPage,
'/order_list',
(args) => ChargingQueryOrderListPage(
vin: args.data['vin'] as String,
),
r0,
);
return [r0, r1, r2, r3, r4];
}
}
```
## 核心功能模块
### 1. 充电地图首页
**文件**: `pages/public_charging/charging_map_home_page/charging_map_home_page.dart`
```dart
import 'package:flutter/material.dart';
import 'package:amap_flutter_map/amap_flutter_map.dart';
import 'package:basic_modular/modular.dart';
/// 充电地图首页
class ChargingMapHomePage extends StatefulWidget {
const ChargingMapHomePage(this.vin, {Key? key}) : super(key: key);
final String? vin;
@override
State<ChargingMapHomePage> createState() => _ChargingMapHomePageState();
}
class _ChargingMapHomePageState extends State<ChargingMapHomePage> {
AMapController? _mapController;
List<ChargingStation> _chargingStations = [];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('充电地图'),
actions: [
IconButton(
icon: Icon(Icons.search),
onPressed: _openSearch,
),
IconButton(
icon: Icon(Icons.filter_list),
onPressed: _openFilter,
),
],
),
body: Stack(
children: [
// 地图组件
AMapWidget(
onMapCreated: _onMapCreated,
markers: Set<Marker>.from(_buildMarkers()),
),
// 功能按钮区域
Positioned(
bottom: 100,
right: 16,
child: Column(
children: [
FloatingActionButton(
heroTag: "locate",
onPressed: _locateUser,
child: Icon(Icons.my_location),
),
SizedBox(height: 10),
FloatingActionButton(
heroTag: "smart_find",
onPressed: _smartPileFinding,
child: Icon(Icons.electric_bolt),
),
],
),
),
// 底部信息卡片
_buildBottomSheet(),
],
),
);
}
void _onMapCreated(AMapController controller) {
_mapController = controller;
_loadChargingStations();
}
List<Marker> _buildMarkers() {
return _chargingStations.map((station) {
return Marker(
markerId: MarkerId(station.id),
position: LatLng(station.latitude, station.longitude),
infoWindow: InfoWindow(title: station.name),
onTap: () => _showStationDetail(station),
);
}).toList();
}
void _loadChargingStations() {
// 加载充电站数据
}
void _openSearch() {
Modular.to.pushNamed('/charging/search_home');
}
void _openFilter() {
Modular.to.pushNamed('/charging/filter');
}
void _locateUser() {
// 定位到用户位置
}
void _smartPileFinding() {
if (widget.vin != null) {
Modular.to.pushNamed('/charging/smart_pile_finding', arguments: {
'vin': widget.vin,
});
}
}
void _showStationDetail(ChargingStation station) {
Modular.to.pushNamed('/charging/station_detail', arguments: {
'stationID': station.id,
'chargingVin': widget.vin,
});
}
Widget _buildBottomSheet() {
return Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
height: 80,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 8,
offset: Offset(0, -2),
),
],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildBottomAction(Icons.list, '订单', _openOrderList),
_buildBottomAction(Icons.assessment, '报告', _openReport),
_buildBottomAction(Icons.settings, '设置', _openSettings),
],
),
),
);
}
Widget _buildBottomAction(IconData icon, String label, VoidCallback onTap) {
return InkWell(
onTap: onTap,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(icon, color: Colors.blue),
SizedBox(height: 4),
Text(label, style: TextStyle(fontSize: 12)),
],
),
);
}
void _openOrderList() {
if (widget.vin != null) {
Modular.to.pushNamed('/charging/order_list', arguments: {
'vin': widget.vin,
});
}
}
void _openReport() {
if (widget.vin != null) {
Modular.to.pushNamed('/charging/report', arguments: {
'vin': widget.vin,
});
}
}
void _openSettings() {
Modular.to.pushNamed('/charging/settings');
}
}
// 充电站数据模型
class ChargingStation {
final String id;
final String name;
final double latitude;
final double longitude;
final int totalPiles;
final int availablePiles;
ChargingStation({
required this.id,
required this.name,
required this.latitude,
required this.longitude,
required this.totalPiles,
required this.availablePiles,
});
}
```
### 2. 充电站详情页面
```dart
/// 充电站详情页面
class ChargingStationDetailPage extends StatefulWidget {
const ChargingStationDetailPage({
Key? key,
required this.stationID,
this.chargingVin,
}) : super(key: key);
final String stationID;
final String? chargingVin;
@override
State<ChargingStationDetailPage> createState() => _ChargingStationDetailPageState();
}
class _ChargingStationDetailPageState extends State<ChargingStationDetailPage> {
ChargingStationDetail? _stationDetail;
bool _isLoading = true;
@override
void initState() {
super.initState();
_loadStationDetail();
}
@override
Widget build(BuildContext context) {
if (_isLoading) {
return Scaffold(
appBar: AppBar(title: Text('充电站详情')),
body: Center(child: CircularProgressIndicator()),
);
}
if (_stationDetail == null) {
return Scaffold(
appBar: AppBar(title: Text('充电站详情')),
body: Center(child: Text('加载失败')),
);
}
return Scaffold(
appBar: AppBar(
title: Text(_stationDetail!.name),
actions: [
IconButton(
icon: Icon(Icons.share),
onPressed: _shareStation,
),
],
),
body: SingleChildScrollView(
child: Column(
children: [
// 充电站基本信息
_buildStationInfo(),
// 充电桩列表
_buildChargingPilesList(),
// 服务设施
_buildFacilities(),
// 电价信息
_buildPriceInfo(),
// 评价与评论
_buildRatingsSection(),
],
),
),
bottomNavigationBar: Container(
padding: EdgeInsets.all(16),
child: Row(
children: [
Expanded(
child: ElevatedButton(
onPressed: _navigateToStation,
child: Text('导航'),
),
),
SizedBox(width: 16),
Expanded(
child: ElevatedButton(
onPressed: _bookChargingPile,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green,
),
child: Text('预约充电'),
),
),
],
),
),
);
}
Widget _buildStationInfo() {
return Container(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(_stationDetail!.name, style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
SizedBox(height: 8),
Text(_stationDetail!.address, style: TextStyle(color: Colors.grey[600])),
SizedBox(height: 16),
Row(
children: [
_buildInfoChip('总桩数', '${_stationDetail!.totalPiles}'),
SizedBox(width: 16),
_buildInfoChip('可用桩数', '${_stationDetail!.availablePiles}'),
],
),
],
),
);
}
Widget _buildInfoChip(String label, String value) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1),
borderRadius: BorderRadius.circular(16),
),
child: Text('$label: $value', style: TextStyle(color: Colors.blue)),
);
}
void _loadStationDetail() {
// 加载充电站详情数据
Future.delayed(Duration(seconds: 1), () {
setState(() {
_stationDetail = ChargingStationDetail(
id: widget.stationID,
name: '示例充电站',
address: '示例地址',
totalPiles: 10,
availablePiles: 6,
);
_isLoading = false;
});
});
}
void _navigateToStation() {
Modular.to.pushNamed('/charging/station_guide', arguments: {
'stationID': widget.stationID,
});
}
void _bookChargingPile() {
Modular.to.pushNamed('/charging/reservation', arguments: {
'stationID': widget.stationID,
'vin': widget.chargingVin,
});
}
}
// 充电站详情数据模型
class ChargingStationDetail {
final String id;
final String name;
final String address;
final int totalPiles;
final int availablePiles;
ChargingStationDetail({
required this.id,
required this.name,
required this.address,
required this.totalPiles,
required this.availablePiles,
});
}
```
### 3. 智能寻桩页面
```dart
/// 智能寻桩页面
class ChargingSmartPileFindingPage extends StatefulWidget {
const ChargingSmartPileFindingPage({
Key? key,
required this.vin,
}) : super(key: key);
final String vin;
@override
State<ChargingSmartPileFindingPage> createState() => _ChargingSmartPileFindingPageState();
}
class _ChargingSmartPileFindingPageState extends State<ChargingSmartPileFindingPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('智能寻桩')),
body: Column(
children: [
// 车辆信息卡片
_buildVehicleInfoCard(),
// 推荐充电站列表
Expanded(
child: ListView.builder(
itemCount: _recommendedStations.length,
itemBuilder: (context, index) {
final station = _recommendedStations[index];
return _buildStationRecommendCard(station);
},
),
),
],
),
);
}
Widget _buildVehicleInfoCard() {
return Container(
margin: EdgeInsets.all(16),
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.1), blurRadius: 4)],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('当前车辆', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
SizedBox(height: 8),
Text('VIN: ${widget.vin}'),
Text('当前电量: 30%'),
Text('续航里程: 120km'),
],
),
);
}
Widget _buildStationRecommendCard(RecommendedStation station) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Card(
child: ListTile(
title: Text(station.name),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('距离: ${station.distance}km'),
Text('可用桩数: ${station.availablePiles}'),
Text('预计费用: ¥${station.estimatedCost}'),
],
),
trailing: ElevatedButton(
onPressed: () => _selectStation(station),
child: Text('选择'),
),
),
),
);
}
void _selectStation(RecommendedStation station) {
Modular.to.pushNamed('/charging/station_detail', arguments: {
'stationID': station.id,
'chargingVin': widget.vin,
});
}
}
// 推荐充电站数据模型
class RecommendedStation {
final String id;
final String name;
final double distance;
final int availablePiles;
final double estimatedCost;
RecommendedStation({
required this.id,
required this.name,
required this.distance,
required this.availablePiles,
required this.estimatedCost,
});
}
```
## 状态管理 (BLoC)
### 充电地图状态管理
```dart
// 充电地图状态管理
class ChargingMapHomeBloc extends Bloc<ChargingMapHomeEvent, ChargingMapHomeState> {
final ChargingService _chargingService;
ChargingMapHomeBloc(this._chargingService) : super(ChargingMapHomeInitial()) {
on<LoadChargingStationsEvent>(_onLoadChargingStations);
on<FilterStationsEvent>(_onFilterStations);
on<SearchStationsEvent>(_onSearchStations);
}
Future<void> _onLoadChargingStations(
LoadChargingStationsEvent event,
Emitter<ChargingMapHomeState> emit,
) async {
emit(ChargingMapHomeLoading());
try {
final stations = await _chargingService.getNearbyStations(
latitude: event.latitude,
longitude: event.longitude,
radius: event.radius,
);
emit(ChargingMapHomeLoaded(stations));
} catch (e) {
emit(ChargingMapHomeError(e.toString()));
}
}
Future<void> _onFilterStations(
FilterStationsEvent event,
Emitter<ChargingMapHomeState> emit,
) async {
if (state is ChargingMapHomeLoaded) {
final currentState = state as ChargingMapHomeLoaded;
final filteredStations = _applyFilter(currentState.stations, event.filter);
emit(ChargingMapHomeLoaded(filteredStations));
}
}
List<ChargingStation> _applyFilter(List<ChargingStation> stations, StationFilter filter) {
return stations.where((station) {
if (filter.onlyAvailable && station.availablePiles == 0) return false;
if (filter.maxDistance != null && station.distance > filter.maxDistance!) return false;
return true;
}).toList();
}
}
// 事件定义
abstract class ChargingMapHomeEvent {}
class LoadChargingStationsEvent extends ChargingMapHomeEvent {
final double latitude;
final double longitude;
final double radius;
LoadChargingStationsEvent(this.latitude, this.longitude, this.radius);
}
class FilterStationsEvent extends ChargingMapHomeEvent {
final StationFilter filter;
FilterStationsEvent(this.filter);
}
// 状态定义
abstract class ChargingMapHomeState {}
class ChargingMapHomeInitial extends ChargingMapHomeState {}
class ChargingMapHomeLoading extends ChargingMapHomeState {}
class ChargingMapHomeLoaded extends ChargingMapHomeState {
final List<ChargingStation> stations;
ChargingMapHomeLoaded(this.stations);
}
class ChargingMapHomeError extends ChargingMapHomeState {
final String message;
ChargingMapHomeError(this.message);
}
// 过滤器模型
class StationFilter {
final bool onlyAvailable;
final double? maxDistance;
final List<String>? supportedConnectors;
StationFilter({
this.onlyAvailable = false,
this.maxDistance,
this.supportedConnectors,
});
}
```
## 依赖管理
### 核心依赖
- **clr_charging**: 充电服务SDK
- **car_services**: 车辆服务
- **car_vehicle**: 车辆管理
- **amap_flutter_map**: 高德地图
### 框架依赖
- **basic_modular**: 模块化框架
- **basic_modular_route**: 路由管理
- **basic_logger**: 日志服务
- **ui_basic**: 基础UI组件
### 账户与支付
- **clr_account**: 账户管理
- **clr_geo**: 地理位置服务
## 最佳实践
### 1. 代码组织
- 按业务功能模块化组织
- 统一的路由管理和页面导航
- 清晰的状态管理模式
### 2. 用户体验
- 地图加载优化和缓存策略
- 实时充电桩状态更新
- 智能推荐算法
### 3. 性能优化
- 地图资源合理加载释放
- 充电站数据分页加载
- 网络请求优化和重试机制