智慧水务管理系统 - 精河县供水工程综合管理平台

water_supply_tab.dart 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. import 'package:flutter/material.dart';
  2. /// 供水管理 Tab
  3. class WaterSupplyTab extends StatelessWidget {
  4. const WaterSupplyTab({super.key});
  5. @override
  6. Widget build(BuildContext context) {
  7. final theme = Theme.of(context);
  8. final colorScheme = theme.colorScheme;
  9. return RefreshIndicator(
  10. onRefresh: () async {
  11. // TODO: 刷新数据
  12. await Future.delayed(const Duration(seconds: 1));
  13. },
  14. child: ListView(
  15. padding: const EdgeInsets.all(16),
  16. children: [
  17. // ---------- 概览卡片 ----------
  18. _OverviewCard(
  19. title: '今日供水量',
  20. value: '12,580 m³',
  21. subtitle: '较昨日 ↑ 3.2%',
  22. icon: Icons.water_drop,
  23. color: colorScheme.primary,
  24. ),
  25. const SizedBox(height: 16),
  26. // ---------- 快捷操作 ----------
  27. Text('快捷操作', style: theme.textTheme.titleMedium),
  28. const SizedBox(height: 12),
  29. Wrap(
  30. spacing: 12,
  31. runSpacing: 12,
  32. children: [
  33. _ActionChip(
  34. icon: Icons.sensors,
  35. label: '实时监测',
  36. onTap: () => Navigator.pushNamed(context, '/water/monitor'),
  37. ),
  38. _ActionChip(
  39. icon: Icons.warning_amber,
  40. label: '报警推送',
  41. onTap: () => Navigator.pushNamed(context, '/water/alert'),
  42. ),
  43. _ActionChip(
  44. icon: Icons.assignment_ind,
  45. label: '今日值班',
  46. onTap: () => Navigator.pushNamed(context, '/water/dispatch'),
  47. ),
  48. _ActionChip(
  49. icon: Icons.science,
  50. label: '水质查看',
  51. onTap: () => Navigator.pushNamed(context, '/water/quality'),
  52. ),
  53. ],
  54. ),
  55. const SizedBox(height: 24),
  56. // ---------- 实时数据 ----------
  57. Text('实时监测', style: theme.textTheme.titleMedium),
  58. const SizedBox(height: 12),
  59. _MonitorTile(
  60. name: '1号泵站',
  61. status: '运行中',
  62. pressure: '0.35 MPa',
  63. flow: '120 m³/h',
  64. isOnline: true,
  65. ),
  66. _MonitorTile(
  67. name: '2号泵站',
  68. status: '运行中',
  69. pressure: '0.32 MPa',
  70. flow: '98 m³/h',
  71. isOnline: true,
  72. ),
  73. _MonitorTile(
  74. name: '3号泵站',
  75. status: '维护中',
  76. pressure: '—',
  77. flow: '—',
  78. isOnline: false,
  79. ),
  80. _MonitorTile(
  81. name: '清水池',
  82. status: '正常',
  83. pressure: '—',
  84. flow: '水位 4.2m',
  85. isOnline: true,
  86. ),
  87. ],
  88. ),
  89. );
  90. }
  91. }
  92. class _OverviewCard extends StatelessWidget {
  93. final String title;
  94. final String value;
  95. final String subtitle;
  96. final IconData icon;
  97. final Color color;
  98. const _OverviewCard({
  99. required this.title,
  100. required this.value,
  101. required this.subtitle,
  102. required this.icon,
  103. required this.color,
  104. });
  105. @override
  106. Widget build(BuildContext context) {
  107. return Card(
  108. elevation: 0,
  109. color: color.withAlpha(25),
  110. shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
  111. child: Padding(
  112. padding: const EdgeInsets.all(20),
  113. child: Row(
  114. children: [
  115. Container(
  116. width: 56,
  117. height: 56,
  118. decoration: BoxDecoration(
  119. color: color.withAlpha(50),
  120. shape: BoxShape.circle,
  121. ),
  122. child: Icon(icon, color: color, size: 28),
  123. ),
  124. const SizedBox(width: 16),
  125. Expanded(
  126. child: Column(
  127. crossAxisAlignment: CrossAxisAlignment.start,
  128. children: [
  129. Text(title, style: const TextStyle(fontSize: 14, color: Colors.grey)),
  130. const SizedBox(height: 4),
  131. Text(value, style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold, color: color)),
  132. const SizedBox(height: 4),
  133. Text(subtitle, style: const TextStyle(fontSize: 12, color: Colors.grey)),
  134. ],
  135. ),
  136. ),
  137. ],
  138. ),
  139. ),
  140. );
  141. }
  142. }
  143. class _ActionChip extends StatelessWidget {
  144. final IconData icon;
  145. final String label;
  146. final VoidCallback onTap;
  147. const _ActionChip({required this.icon, required this.label, required this.onTap});
  148. @override
  149. Widget build(BuildContext context) {
  150. return InkWell(
  151. onTap: onTap,
  152. borderRadius: BorderRadius.circular(12),
  153. child: Container(
  154. width: 80,
  155. padding: const EdgeInsets.symmetric(vertical: 12),
  156. decoration: BoxDecoration(
  157. color: Colors.grey.shade100,
  158. borderRadius: BorderRadius.circular(12),
  159. ),
  160. child: Column(
  161. mainAxisSize: MainAxisSize.min,
  162. children: [
  163. Icon(icon, color: Colors.blue.shade700),
  164. const SizedBox(height: 6),
  165. Text(label, style: const TextStyle(fontSize: 12)),
  166. ],
  167. ),
  168. ),
  169. );
  170. }
  171. }
  172. class _MonitorTile extends StatelessWidget {
  173. final String name;
  174. final String status;
  175. final String pressure;
  176. final String flow;
  177. final bool isOnline;
  178. const _MonitorTile({
  179. required this.name,
  180. required this.status,
  181. required this.pressure,
  182. required this.flow,
  183. required this.isOnline,
  184. });
  185. @override
  186. Widget build(BuildContext context) {
  187. return Card(
  188. margin: const EdgeInsets.only(bottom: 8),
  189. child: ListTile(
  190. leading: CircleAvatar(
  191. backgroundColor: isOnline ? Colors.green.shade100 : Colors.grey.shade200,
  192. child: Icon(
  193. Icons.sensors,
  194. color: isOnline ? Colors.green : Colors.grey,
  195. ),
  196. ),
  197. title: Text(name),
  198. subtitle: Text('压力: $pressure | 流量: $flow'),
  199. trailing: Container(
  200. padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
  201. decoration: BoxDecoration(
  202. color: isOnline ? Colors.green.shade100 : Colors.orange.shade100,
  203. borderRadius: BorderRadius.circular(8),
  204. ),
  205. child: Text(
  206. status,
  207. style: TextStyle(
  208. fontSize: 12,
  209. color: isOnline ? Colors.green.shade800 : Colors.orange.shade800,
  210. ),
  211. ),
  212. ),
  213. ),
  214. );
  215. }
  216. }