Files
feature-tenant/lib/features/v2/home/presentation/pages/home_v2_page.dart

253 lines
10 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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/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';
class HomeV2Page extends StatefulWidget {
const HomeV2Page({super.key});
@override
State<HomeV2Page> createState() => _HomeV2PageState();
}
class _HomeV2PageState extends State<HomeV2Page> {
late HomeV2Bloc _bloc;
String _selectedPlant = '示例光伏电站';
final List<String> _plantList = [
'示例光伏电站',
'一号光伏电站',
'二号光伏电站',
'三号光伏电站',
];
@override
void initState() {
super.initState();
_bloc = context.read<HomeV2Bloc>();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFF5F7FA),
body: BlocBuilder<HomeV2Bloc, HomeV2State>(
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: Text(
_selectedPlant,
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)),
],
),
),
),
IconButton(
icon: const Icon(Icons.qr_code_scanner, size: 24, color: Color(0xFF1D2129)),
onPressed: () => print('点击扫码'),
),
],
),
),
),
),
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) {
_bloc.add(const HomeV2LoadData());
}
}
void _showPlantSelector() {
showModalBottomSheet(
context: context,
backgroundColor: Colors.white,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
builder: (context) {
return Container(
padding: const EdgeInsets.all(14),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text(
'选择电站',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Color(0xFF1D2129),
),
),
const SizedBox(height: 14),
..._plantList.map((plant) => ListTile(
title: Text(plant),
trailing: _selectedPlant == plant
? const Icon(Icons.check, color: Color(0xFF165DFF))
: null,
onTap: () {
setState(() {
_selectedPlant = plant;
});
Navigator.pop(context);
},
)),
],
),
);
},
);
}
}