| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406 |
- import 'package:flutter/material.dart';
- import 'package:water_management_system/models/water_data_model.dart';
- import 'package:water_management_system/services/water_service.dart';
- import 'package:water_management_system/utils/constants.dart';
- import 'package:water_management_system/widgets/custom_card.dart';
- import 'package:water_management_system/widgets/custom_button.dart';
- import 'package:fl_chart/fl_chart.dart';
- import 'package:intl/intl.dart';
-
- class WaterMonitoringPage extends StatefulWidget {
- const WaterMonitoringPage({super.key});
-
- @override
- State<WaterMonitoringPage> createState() => _WaterMonitoringPageState();
- }
-
- class _WaterMonitoringPageState extends State<WaterMonitoringPage> {
- final WaterService _waterService = WaterService();
- bool _isLoading = true;
- List<WaterDataModel> _waterData = [];
- String _selectedArea = '全部区域';
- DateTime _selectedDate = DateTime.now();
-
- @override
- void initState() {
- super.initState();
- _loadWaterData();
- }
-
- Future<void> _loadWaterData() async {
- setState(() {
- _isLoading = true;
- });
-
- try {
- final data = await _waterService.getWaterData(
- area: _selectedArea,
- date: _selectedDate,
- );
- setState(() {
- _waterData = data;
- _isLoading = false;
- });
- } catch (e) {
- setState(() {
- _isLoading = false;
- });
- if (mounted) {
- ScaffoldMessenger.of(context).showSnackBar(
- SnackBar(
- content: Text('加载供水数据失败: $e'),
- backgroundColor: AppConstants.errorColor,
- ),
- );
- }
- }
- }
-
- @override
- Widget build(BuildContext context) {
- return RefreshIndicator(
- onRefresh: _loadWaterData,
- child: Scaffold(
- body: _isLoading
- ? const Center(child: CircularProgressIndicator())
- : Column(
- children: [
- // 搜索和筛选区域
- _buildFilterSection(),
- // 统计卡片
- _buildStatisticsCards(),
- // 图表区域
- _buildChartSection(),
- // 数据列表
- Expanded(
- child: _buildWaterDataList(),
- ),
- ],
- ),
- );
- }
-
- Widget _buildFilterSection() {
- return Container(
- padding: const EdgeInsets.all(16),
- decoration: BoxDecoration(
- color: Colors.white,
- boxShadow: [
- BoxShadow(
- color: Colors.grey.withOpacity(0.1),
- blurRadius: 4,
- offset: const Offset(0, 2),
- ),
- ],
- ),
- child: Column(
- children: [
- Row(
- children: [
- Expanded(
- child: DropdownButtonFormField<String>(
- value: _selectedArea,
- decoration: const InputDecoration(
- labelText: '区域选择',
- border: OutlineInputBorder(),
- ),
- items: const [
- DropdownMenuItem(value: '全部区域', child: Text('全部区域')),
- DropdownMenuItem(value: '东区', child: Text('东区')),
- DropdownMenuItem(value: '西区', child: Text('西区')),
- DropdownMenuItem(value: '南区', child: Text('南区')),
- DropdownMenuItem(value: '北区', child: Text('北区')),
- ],
- onChanged: (value) {
- setState(() {
- _selectedArea = value!;
- });
- },
- ),
- ),
- const SizedBox(width: 16),
- Expanded(
- child: InkWell(
- onTap: _showDatePicker,
- child: Container(
- padding: const EdgeInsets.symmetric(
- horizontal: 16,
- vertical: 12,
- ),
- decoration: BoxDecoration(
- border: Border.all(color: Colors.grey[300]!),
- borderRadius: BorderRadius.circular(8),
- ),
- child: Row(
- children: [
- const Icon(Icons.calendar_today),
- const SizedBox(width: 8),
- Text(
- DateFormat('yyyy-MM-dd').format(_selectedDate),
- style: const TextStyle(fontSize: 14),
- ),
- ],
- ),
- ),
- ),
- ),
- const SizedBox(width: 16),
- CustomButton(
- text: '查询',
- width: 80,
- onPressed: _loadWaterData,
- ),
- ],
- ),
- ],
- ),
- );
- }
-
- Widget _buildStatisticsCards() {
- final totalDevices = _waterData.length;
- final normalDevices = _waterData.where((data) => data.status == 'normal').length;
- const warningDevices = 0; // 假设暂无警告
- const errorDevices = 0; // 假设暂无错误
-
- return Container(
- padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
- child: Row(
- children: [
- Expanded(
- child: CustomCard(
- title: '设备总数',
- value: totalDevices.toString(),
- color: AppConstants.primaryColor,
- icon: Icons.device_thermostat,
- ),
- ),
- const SizedBox(width: 12),
- Expanded(
- child: CustomCard(
- title: '正常设备',
- value: normalDevices.toString(),
- color: AppConstants.successColor,
- icon: Icons.check_circle,
- ),
- ),
- const SizedBox(width: 12),
- Expanded(
- child: CustomCard(
- title: '警告设备',
- value: warningDevices.toString(),
- color: AppConstants.warningColor,
- icon: Icons.warning,
- ),
- ),
- const SizedBox(width: 12),
- Expanded(
- child: CustomCard(
- title: '故障设备',
- value: errorDevices.toString(),
- color: AppConstants.errorColor,
- icon: Icons.error,
- ),
- ),
- ],
- ),
- );
- }
-
- Widget _buildChartSection() {
- if (_waterData.isEmpty) {
- return const SizedBox.shrink();
- }
-
- // 准备图表数据
- final pressureData = _waterData.map((data) => data.pressure).toList();
- final flowData = _waterData.map((data) => data.flowRate).toList();
-
- return Container(
- height: 200,
- margin: const EdgeInsets.all(16),
- padding: const EdgeInsets.all(16),
- decoration: BoxDecoration(
- color: Colors.white,
- borderRadius: BorderRadius.circular(8),
- boxShadow: [
- BoxShadow(
- color: Colors.grey.withOpacity(0.1),
- blurRadius: 4,
- offset: const Offset(0, 2),
- ),
- ],
- ),
- child: Column(
- children: [
- const Row(
- children: [
- Icon(Icons.show_chart),
- SizedBox(width: 8),
- Text('压力和流量趋势'),
- ],
- ),
- const SizedBox(height: 16),
- Expanded(
- child: LineChart(
- LineChartData(
- gridData: const FlGridData(show: false),
- titlesData: const FlTitlesData(show: false),
- borderData: FlBorderData(show: false),
- minX: 0,
- maxX: _waterData.length.toDouble() - 1,
- minY: 0,
- maxY: (_waterData.fold(0, (max, data) =>
- data.pressure > max ? data.pressure : max) * 1.2).toDouble(),
- lineBarsData: [
- LineChartBarData(
- spots: List.generate(_waterData.length, (index) {
- return FlSpot(
- index.toDouble(),
- _waterData[index].pressure.toDouble(),
- );
- }),
- isCurved: true,
- color: AppConstants.primaryColor,
- barWidth: 2,
- isStrokeCapRound: true,
- dotData: const FlDotData(show: false),
- ),
- LineChartBarData(
- spots: List.generate(_waterData.length, (index) {
- return FlSpot(
- index.toDouble(),
- _waterData[index].flowRate.toDouble(),
- );
- }),
- isCurved: true,
- color: AppConstants.accentColor,
- barWidth: 2,
- isStrokeCapRound: true,
- dotData: const FlDotData(show: false),
- ),
- ],
- ),
- ),
- ),
- ],
- ),
- );
- }
-
- Widget _buildWaterDataList() {
- if (_waterData.isEmpty) {
- return const Center(
- child: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Icon(Icons.water_drop, size: 64, color: Colors.grey),
- SizedBox(height: 16),
- Text('暂无供水数据', style: TextStyle(color: Colors.grey)),
- ],
- ),
- );
- }
-
- return ListView.separated(
- padding: const EdgeInsets.all(16),
- itemCount: _waterData.length,
- separatorBuilder: (context, index) => const Divider(height: 1),
- itemBuilder: (context, index) {
- final data = _waterData[index];
- return WaterDataCard(data: data);
- },
- );
- }
-
- void _showDatePicker() {
- showDatePicker(
- context: context,
- initialDate: _selectedDate,
- firstDate: DateTime(2024, 1, 1),
- lastDate: DateTime.now(),
- ).then((date) {
- if (date != null) {
- setState(() {
- _selectedDate = date;
- });
- }
- });
- }
- }
-
- class WaterDataCard extends StatelessWidget {
- final WaterDataModel data;
-
- const WaterDataCard({
- super.key,
- required this.data,
- });
-
- @override
- Widget build(BuildContext context) {
- Color statusColor;
- String statusText;
- IconData statusIcon;
-
- switch (data.status) {
- case 'normal':
- statusColor = AppConstants.successColor;
- statusText = '正常';
- statusIcon = Icons.check_circle;
- break;
- case 'warning':
- statusColor = AppConstants.warningColor;
- statusText = '警告';
- statusIcon = Icons.warning;
- break;
- case 'error':
- statusColor = AppConstants.errorColor;
- statusText = '故障';
- statusIcon = Icons.error;
- break;
- default:
- statusColor = Colors.grey;
- statusText = '未知';
- statusIcon = Icons.help;
- }
-
- return CustomCard(
- title: '${data.area} - ${data.deviceName}',
- subtitle: '设备ID: ${data.deviceId}',
- trailing: Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- Icon(statusIcon, color: statusColor),
- const SizedBox(width: 4),
- Text(
- statusText,
- style: TextStyle(
- color: statusColor,
- fontWeight: FontWeight.bold,
- ),
- ),
- ],
- ),
- children: [
- _buildDataRow('压力', '${data.pressure} MPa'),
- _buildDataRow('流量', '${data.flowRate} m³/h'),
- _buildDataRow('温度', '${data.temperature} °C'),
- _buildDataRow('更新时间', DateFormat('yyyy-MM-dd HH:mm:ss').format(data.updateTime)),
- ],
- );
- }
-
- Widget _buildDataRow(String label, String value) {
- return Padding(
- padding: const EdgeInsets.symmetric(vertical: 4),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Text(label, style: const TextStyle(color: Colors.grey)),
- Text(value, style: const TextStyle(fontWeight: FontWeight.w500)),
- ],
- ),
- );
- }
- }
|