Files
CloudHome-Ops/lib/screens/alerts/alerts_page.dart

141 lines
4.2 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../models/alert.dart';
import '../../app/theme.dart';
import '../../providers/devices_provider.dart';
import '../../utils/formatters.dart';
/// 告警列表页(底部导航第 2 个 tab)。
class AlertsPage extends ConsumerWidget {
const AlertsPage({super.key});
Color _levelColor(BuildContext context, AlertLevel level) {
final semantic = Theme.of(context).extension<AppSemanticColors>();
switch (level) {
case AlertLevel.critical:
return Colors.red;
case AlertLevel.warning:
return Colors.orange;
case AlertLevel.info:
return semantic?.info ?? Theme.of(context).colorScheme.primary;
}
}
IconData _levelIcon(AlertLevel level) {
switch (level) {
case AlertLevel.critical:
return Icons.error;
case AlertLevel.warning:
return Icons.warning_amber;
case AlertLevel.info:
return Icons.info_outline;
}
}
@override
Widget build(BuildContext context, WidgetRef ref) {
final alertsAsync = ref.watch(alertsProvider);
return Scaffold(
appBar: AppBar(title: const Text('告警中心')),
body: alertsAsync.when(
loading: () => const Center(child: CircularProgressIndicator()),
error: (error, _) => Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text('告警列表加载失败'),
const SizedBox(height: 8),
FilledButton.tonal(
onPressed: () => ref.refresh(alertsProvider),
child: const Text('重试'),
),
],
),
),
data: (alerts) {
if (alerts.isEmpty) {
return const Center(child: Text('暂无告警'));
}
return RefreshIndicator(
onRefresh: () async => ref.refresh(alertsProvider.future),
child: ListView.builder(
physics: const AlwaysScrollableScrollPhysics(),
itemCount: alerts.length,
itemBuilder: (context, index) =>
_buildAlertCard(context, alerts[index]),
),
);
},
),
);
}
Widget _buildAlertCard(BuildContext context, Alert alert) {
final color = _levelColor(context, alert.level);
return Card(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(_levelIcon(alert.level), color: color, size: 20),
const SizedBox(width: 8),
Expanded(
child: Text(
alert.title,
style: const TextStyle(fontWeight: FontWeight.w600),
),
),
_buildLevelTag(alert, color),
],
),
const SizedBox(height: 8),
Text(
alert.message,
style: Theme.of(context).textTheme.bodyMedium,
),
const SizedBox(height: 8),
Row(
children: [
Expanded(
child: Text(
alert.deviceName,
style: Theme.of(context).textTheme.bodySmall,
),
),
Text(
Formatters.formatDateTime(alert.occurredAt),
style: Theme.of(context).textTheme.bodySmall,
),
],
),
],
),
),
);
}
Widget _buildLevelTag(Alert alert, Color color) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
decoration: BoxDecoration(
color: color.withOpacity(0.15),
borderRadius: BorderRadius.circular(999),
),
child: Text(
alert.acknowledged ? '${alert.level.label}·已确认' : alert.level.label,
style: TextStyle(
color: color,
fontSize: 12,
fontWeight: FontWeight.w600,
),
),
);
}
}