# 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> get binds => []; @override List get imports => [AccountConModule(), ClrChargingModule()]; @override List 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(moduleHome.path, child: (_, args) => moduleHome.provider(args).as()), ChildRoute(chargingMapHome.path, child: (_, args) => chargingMapHome.provider(args).as()), ChildRoute(searchHome.path, child: (_, args) => searchHome.provider(args).as()), ChildRoute(cpoCollection.path, child: (_, args) => cpoCollection.provider(args).as()), ChildRoute(stationDetailPage.path, child: (_, args) => stationDetailPage.provider(args).as()), ChildRoute(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 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 createState() => _ChargingMapHomePageState(); } class _ChargingMapHomePageState extends State { AMapController? _mapController; List _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.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 _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 createState() => _ChargingStationDetailPageState(); } class _ChargingStationDetailPageState extends State { 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 createState() => _ChargingSmartPileFindingPageState(); } class _ChargingSmartPileFindingPageState extends State { @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 { final ChargingService _chargingService; ChargingMapHomeBloc(this._chargingService) : super(ChargingMapHomeInitial()) { on(_onLoadChargingStations); on(_onFilterStations); on(_onSearchStations); } Future _onLoadChargingStations( LoadChargingStationsEvent event, Emitter 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 _onFilterStations( FilterStationsEvent event, Emitter emit, ) async { if (state is ChargingMapHomeLoaded) { final currentState = state as ChargingMapHomeLoaded; final filteredStations = _applyFilter(currentState.stations, event.filter); emit(ChargingMapHomeLoaded(filteredStations)); } } List _applyFilter(List 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 stations; ChargingMapHomeLoaded(this.stations); } class ChargingMapHomeError extends ChargingMapHomeState { final String message; ChargingMapHomeError(this.message); } // 过滤器模型 class StationFilter { final bool onlyAvailable; final double? maxDistance; final List? 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. 性能优化 - 地图资源合理加载释放 - 充电站数据分页加载 - 网络请求优化和重试机制