import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:maibu_satabot_v2/core/di/injection.dart'; import 'package:maibu_satabot_v2/features/v2/home/presentation/bloc/home_v2_bloc.dart'; import 'package:maibu_satabot_v2/features/v2/home/presentation/bloc/home_v2_event.dart'; import 'package:maibu_satabot_v2/features/v2/home/presentation/bloc/home_v2_state.dart'; import 'package:maibu_satabot_v2/features/v2/site/presentation/cubit/site_cubit.dart'; import 'package:maibu_satabot_v2/features/v2/home/presentation/widgets/power_card.dart'; import 'package:maibu_satabot_v2/features/v2/home/presentation/widgets/stats_grid.dart'; import 'package:maibu_satabot_v2/features/v2/home/presentation/widgets/work_order_card.dart'; import 'package:maibu_satabot_v2/features/v2/home/presentation/widgets/quick_entry_card.dart'; import 'package:maibu_satabot_v2/features/v2/home/presentation/widgets/power_trend_chart.dart'; import 'package:maibu_satabot_v2/features/v2/home/presentation/widgets/plant_overview_card.dart'; import 'package:maibu_satabot_v2/features/v2/home/presentation/widgets/tcp_status_indicator.dart'; class HomeV2Page extends StatefulWidget { const HomeV2Page({super.key}); @override State createState() => _HomeV2PageState(); } class _HomeV2PageState extends State { late HomeV2Bloc _bloc; @override void initState() { super.initState(); _bloc = context.read(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFF5F7FA), body: BlocBuilder( builder: (context, state) { if (state is HomeV2Error) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.error_outline, size: 48, color: Color(0xFF86909C)), const SizedBox(height: 16), Text(state.message), const SizedBox(height: 16), ElevatedButton( onPressed: () => _bloc.add(const HomeV2LoadData()), child: const Text('重试'), ), ], ), ); } if (state is HomeV2Loaded) { return RefreshIndicator( onRefresh: () async { _bloc.add(const HomeV2Refresh()); }, child: CustomScrollView( slivers: [ SliverAppBar( pinned: true, backgroundColor: Colors.white, elevation: 0, automaticallyImplyLeading: false, flexibleSpace: FlexibleSpaceBar( background: Container( padding: const EdgeInsets.fromLTRB(16, 40, 16, 16), color: Colors.white, child: Row( children: [ Expanded( child: InkWell( onTap: _showPlantSelector, child: Row( mainAxisSize: MainAxisSize.min, children: [ Flexible( child: StreamBuilder( stream: sl().stream, builder: (context, snapshot) { final siteState = snapshot.data ?? sl().state; return Text( siteState.selectedSite?.siteName ?? '选择电站', maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Color(0xFF1D2129), ), ); }, ), ), const SizedBox(width: 4), const Icon(Icons.arrow_drop_down, size: 20, color: Color(0xFF1D2129)), ], ), ), ), const TcpStatusIndicator(), ], ), ), ), ), SliverPadding( padding: const EdgeInsets.fromLTRB(16, 8, 16, 40), sliver: SliverList( delegate: SliverChildListDelegate([ const SizedBox(height: 16), // 天气和告警 Row( children: [ Expanded( child: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( color: const Color(0xFFF2F3F5), borderRadius: BorderRadius.circular(8), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.cloud_queue, size: 16, color: Color(0xFF165DFF)), const SizedBox(width: 6), const Text( '多云 28°C', style: TextStyle( fontSize: 13, color: Color(0xFF4E5969), ), ), ], ), ), ), const SizedBox(width: 8), Expanded( child: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( color: const Color(0xFFFFF0F0), borderRadius: BorderRadius.circular(8), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.warning_amber_rounded, size: 16, color: Color(0xFFF53F3F)), const SizedBox(width: 6), const Expanded( child: Text( '紧急告警', style: TextStyle( fontSize: 13, color: Color(0xFFF53F3F), ), ), ), const SizedBox(width: 4), const Icon(Icons.arrow_forward_ios, size: 12, color: Color(0xFFF53F3F)), ], ), ), ), ], ), const SizedBox(height: 16), PowerCard(data: state.homeData), const SizedBox(height: 10), StatsGrid(data: state.homeData), const SizedBox(height: 10), PlantOverviewCard(overview: state.homeData.plantOverview), const SizedBox(height: 10), WorkOrderCard(stats: state.homeData.workOrderStats), const SizedBox(height: 10), QuickEntryCard(), const SizedBox(height: 10), PowerTrendChart( data: state.homeData.powerTrendData, trendType: state.trendType, onToggleType: (type) => _bloc.add(HomeV2ToggleTrendType(type)), ), const SizedBox(height: 40), ]), ), ), ], ), ); } return const SizedBox(); }, ), ); } @override void didChangeDependencies() { super.didChangeDependencies(); // 首次进入时自动加载数据,但不显示转圈 if (_bloc.state is HomeV2Initial) { // 延迟 100ms,确保 AppUserCubit 状态已更新 Future.delayed(const Duration(milliseconds: 100), () { if (mounted) { _bloc.add(const HomeV2LoadData()); } }); } } void _showPlantSelector() { if (_bloc.state is! HomeV2Loaded) return; final currentState = _bloc.state as HomeV2Loaded; final sites = currentState.sites; if (sites.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('暂无可用电站')), ); return; } showModalBottomSheet( context: context, backgroundColor: Colors.white, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(16)), ), builder: (context) { return BlocBuilder( bloc: _bloc, builder: (context, state) { if (state is! HomeV2Loaded) return Container(); return Container( padding: const EdgeInsets.all(14), constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.6, ), child: Column( mainAxisSize: MainAxisSize.min, children: [ const Text( '选择电站', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Color(0xFF1D2129), ), ), const SizedBox(height: 14), Expanded( child: ListView.builder( shrinkWrap: true, itemCount: state.sites.length, itemBuilder: (context, index) { final site = state.sites[index]; final isSelected = state.selectedSite?.id == site.id; return ListTile( title: Text(site.siteName), subtitle: site.siteCode != null && site.siteCode!.isNotEmpty ? Text('编号: ${site.siteCode}') : null, trailing: isSelected ? const Icon(Icons.check, color: Color(0xFF165DFF)) : null, onTap: () { // 更新全局选中的场站 sl().selectSite(site); Navigator.pop(context); // 切换场站后,重新加载首页数据 _bloc.add(const HomeV2LoadData()); }, ); }, ), ), ], ), ); }, ); }, ); } }