| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- import 'package:flutter/material.dart';
-
- /// 报警推送列表页面
- class AlertPage extends StatefulWidget {
- const AlertPage({super.key});
-
- @override
- State<AlertPage> createState() => _AlertPageState();
- }
-
- class _AlertPageState extends State<AlertPage>
- with AutomaticKeepAliveClientMixin {
- List<Map<String, dynamic>> _alerts = [];
- bool _isLoading = true;
-
- @override
- bool get wantKeepAlive => true;
-
- @override
- void initState() {
- super.initState();
- _loadData();
- }
-
- void _loadData() {
- // 模拟数据加载
- Future.delayed(const Duration(milliseconds: 500), () {
- setState(() {
- _alerts = _generateMockAlerts();
- _isLoading = false;
- });
- });
- }
-
- List<Map<String, dynamic>> _generateMockAlerts() {
- return [
- {
- 'id': 'AL-001',
- 'title': '城东加压站压力异常',
- 'level': 'critical',
- 'station': '城东加压站',
- 'content': '水压达到 3.2 MPa,超过警戒值',
- 'time': '2026-06-17 08:30',
- 'isRead': false,
- },
- {
- 'id': 'AL-002',
- 'title': '城西水厂流量下降',
- 'level': 'warning',
- 'station': '城西水厂',
- 'content': '流量从 450 m³/h 降至 280 m³/h',
- 'time': '2026-06-17 09:15',
- 'isRead': false,
- },
- {
- 'id': 'AL-003',
- 'title': '南区配水站水质异常',
- 'level': 'error',
- 'station': '南区配水站',
- 'content': '浊度指标超标,需立即处理',
- 'time': '2026-06-17 10:20',
- 'isRead': true,
- },
- {
- 'id': 'AL-004',
- 'title': '中心泵站设备维护',
- 'level': 'info',
- 'station': '中心泵站',
- 'content': '计划性维护,预计停机 2 小时',
- 'time': '2026-06-17 11:00',
- 'isRead': true,
- },
- {
- 'id': 'AL-005',
- 'title': '高新区水厂水质恢复',
- 'level': 'normal',
- 'station': '高新区水厂',
- 'content': '水质指标恢复正常,告警已解除',
- 'time': '2026-06-16 15:45',
- 'isRead': true,
- },
- {
- 'id': 'AL-006',
- 'title': '工业园加压站供电异常',
- 'level': 'critical',
- 'station': '工业园加压站',
- 'content': '备用电源已启动,需尽快恢复主供电',
- 'time': '2026-06-17 12:10',
- 'isRead': false,
- },
- ];
- }
-
- Color _getLevelColor(String level) {
- switch (level) {
- case 'critical':
- return Colors.red;
- case 'error':
- return Colors.orange;
- case 'warning':
- return Colors.yellow;
- case 'info':
- return Colors.blue;
- default:
- return Colors.green;
- }
- }
-
- String _getLevelText(String level) {
- switch (level) {
- case 'critical':
- return '严重';
- case 'error':
- return '错误';
- case 'warning':
- return '警告';
- case 'info':
- return '信息';
- default:
- return '正常';
- }
- }
-
- @override
- Widget build(BuildContext context) {
- super.build(context);
- return Scaffold(
- appBar: AppBar(
- title: const Text('报警信息'),
- actions: [
- IconButton(
- icon: const Icon(Icons.filter_list),
- onPressed: () {
- _showFilterDialog();
- },
- ),
- ],
- ),
- body: _isLoading
- ? const Center(child: CircularProgressIndicator())
- : RefreshIndicator(
- onRefresh: () async {
- setState(() {
- _isLoading = true;
- });
- _loadData();
- },
- child: ListView.builder(
- padding: const EdgeInsets.all(12),
- itemCount: _alerts.length,
- itemBuilder: (context, index) {
- final alert = _alerts[index];
- return _buildAlertCard(alert);
- },
- ),
- ),
- floatingActionButton: FloatingActionButton(
- onPressed: () {
- _showAlertDetail();
- },
- child: const Icon(Icons.info),
- ),
- );
- }
-
- Widget _buildAlertCard(Map<String, dynamic> alert) {
- final isUnread = !alert['isRead'];
-
- return Card(
- margin: const EdgeInsets.only(bottom: 12),
- child: Padding(
- padding: const EdgeInsets.all(16),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- children: [
- Container(
- padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
- decoration: BoxDecoration(
- color: _getLevelColor(alert['level']).withOpacity(0.1),
- borderRadius: BorderRadius.circular(12),
- border: Border.all(
- color: _getLevelColor(alert['level']),
- ),
- ),
- child: Text(
- _getLevelText(alert['level']),
- style: TextStyle(
- fontSize: 12,
- color: _getLevelColor(alert['level']),
- fontWeight: FontWeight.bold,
- ),
- ),
- ),
- if (isUnread)
- Container(
- margin: const EdgeInsets.only(left: 8),
- width: 8,
- height: 8,
- decoration: BoxDecoration(
- color: Colors.red,
- shape: BoxShape.circle,
- ),
- ),
- const Spacer(),
- Text(
- alert['time'],
- style: TextStyle(fontSize: 12, color: Colors.grey[500]),
- ),
- ],
- ),
- const SizedBox(height: 12),
- Text(
- alert['title'],
- style: const TextStyle(
- fontSize: 16,
- fontWeight: FontWeight.bold,
- ),
- ),
- const SizedBox(height: 8),
- Row(
- children: [
- const Icon(Icons.location_on, size: 16, color: Colors.grey),
- const SizedBox(width: 4),
- Text(
- alert['station'],
- style: TextStyle(fontSize: 14, color: Colors.grey[600]),
- ),
- ],
- ),
- const SizedBox(height: 8),
- Text(
- alert['content'],
- style: TextStyle(fontSize: 14, color: Colors.grey[700]),
- maxLines: 2,
- overflow: TextOverflow.ellipsis,
- ),
- ],
- ),
- ),
- );
- }
-
- void _showFilterDialog() {
- showDialog(
- context: context,
- builder: (context) => AlertDialog(
- title: const Text('筛选报警'),
- content: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- _buildFilterItem('严重', 'critical'),
- _buildFilterItem('错误', 'error'),
- _buildFilterItem('警告', 'warning'),
- _buildFilterItem('信息', 'info'),
- ],
- ),
- actions: [
- TextButton(
- onPressed: () => Navigator.pop(context),
- child: const Text('取消'),
- ),
- TextButton(
- onPressed: () {
- setState(() {
- _loadData();
- });
- Navigator.pop(context);
- },
- child: const Text('确定'),
- ),
- ],
- ),
- );
- }
-
- Widget _buildFilterItem(String text, String level) {
- return CheckboxListTile(
- title: Text(text),
- value: true,
- onChanged: (value) {},
- );
- }
-
- void _showAlertDetail() {
- // 显示最后一个未读告警详情
- final unreadAlerts = _alerts.where((alert) => !alert['isRead']).toList();
- if (unreadAlerts.isNotEmpty) {
- showDialog(
- context: context,
- builder: (context) => AlertDialog(
- title: Text(unreadAlerts.first['title']),
- content: Column(
- mainAxisSize: MainAxisSize.min,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- _buildDetailRow('地点', unreadAlerts.first['station']),
- _buildDetailRow('时间', unreadAlerts.first['time']),
- _buildDetailRow('级别', _getLevelText(unreadAlerts.first['level'])),
- const SizedBox(height: 16),
- Text(unreadAlerts.first['content']),
- ],
- ),
- actions: [
- TextButton(
- onPressed: () => Navigator.pop(context),
- child: const Text('关闭'),
- ),
- TextButton(
- onPressed: () {
- setState(() {
- unreadAlerts.first['isRead'] = true;
- });
- Navigator.pop(context);
- },
- child: const Text('标记已读'),
- ),
- ],
- ),
- );
- }
- }
-
- Widget _buildDetailRow(String label, String value) {
- return Padding(
- padding: const EdgeInsets.symmetric(vertical: 4),
- child: Row(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- '$label: ',
- style: const TextStyle(
- fontSize: 14,
- fontWeight: FontWeight.bold,
- ),
- ),
- Expanded(
- child: Text(value),
- ),
- ],
- ),
- );
- }
- }
|