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

inspection_tab.dart 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. import 'package:flutter/material.dart';
  2. /// 巡检管理 Tab
  3. class InspectionTab extends StatelessWidget {
  4. const InspectionTab({super.key});
  5. @override
  6. Widget build(BuildContext context) {
  7. final theme = Theme.of(context);
  8. return DefaultTabController(
  9. length: 3,
  10. child: Column(
  11. children: [
  12. // ---------- 子 Tab ----------
  13. Material(
  14. color: theme.colorScheme.surface,
  15. child: TabBar(
  16. labelColor: theme.colorScheme.primary,
  17. unselectedLabelColor: Colors.grey,
  18. indicatorColor: theme.colorScheme.primary,
  19. tabs: const [
  20. Tab(text: '待执行', icon: Icon(Icons.pending_actions, size: 18)),
  21. Tab(text: '进行中', icon: Icon(Icons.play_circle, size: 18)),
  22. Tab(text: '已完成', icon: Icon(Icons.check_circle, size: 18)),
  23. ],
  24. ),
  25. ),
  26. // ---------- 内容 ----------
  27. Expanded(
  28. child: TabBarView(
  29. children: [
  30. _InspectionList(status: 'pending'),
  31. _InspectionList(status: 'ongoing'),
  32. _InspectionList(status: 'done'),
  33. ],
  34. ),
  35. ),
  36. ],
  37. ),
  38. );
  39. }
  40. }
  41. class _InspectionList extends StatelessWidget {
  42. final String status;
  43. const _InspectionList({required this.status});
  44. List<Map<String, dynamic>> get _mockData {
  45. switch (status) {
  46. case 'pending':
  47. return [
  48. {'id': 'XJ-2024-001', 'route': '城东片区巡检路线', 'date': '2024-06-14', 'points': 8, 'priority': '高'},
  49. {'id': 'XJ-2024-002', 'route': '城北加压站巡检', 'date': '2024-06-14', 'points': 4, 'priority': '中'},
  50. {'id': 'XJ-2024-003', 'route': '水厂设备日检', 'date': '2024-06-15', 'points': 12, 'priority': '高'},
  51. ];
  52. case 'ongoing':
  53. return [
  54. {'id': 'XJ-2024-004', 'route': '城西管网巡检', 'date': '2024-06-14', 'points': 6, 'progress': '3/6'},
  55. ];
  56. default:
  57. return [
  58. {'id': 'XJ-2024-005', 'route': '城南片区周检', 'date': '2024-06-13', 'points': 10, 'result': '正常'},
  59. {'id': 'XJ-2024-006', 'route': '水厂设备周检', 'date': '2024-06-13', 'points': 12, 'result': '发现1处隐患'},
  60. ];
  61. }
  62. }
  63. @override
  64. Widget build(BuildContext context) {
  65. final data = _mockData;
  66. if (data.isEmpty) {
  67. return const Center(child: Text('暂无数据', style: TextStyle(color: Colors.grey)));
  68. }
  69. return ListView.builder(
  70. padding: const EdgeInsets.all(12),
  71. itemCount: data.length,
  72. itemBuilder: (ctx, i) => _InspectionCard(item: data[i], status: status),
  73. );
  74. }
  75. }
  76. class _InspectionCard extends StatelessWidget {
  77. final Map<String, dynamic> item;
  78. final String status;
  79. const _InspectionCard({required this.item, required this.status});
  80. @override
  81. Widget build(BuildContext context) {
  82. return Card(
  83. margin: const EdgeInsets.only(bottom: 12),
  84. shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
  85. child: Padding(
  86. padding: const EdgeInsets.all(16),
  87. child: Column(
  88. crossAxisAlignment: CrossAxisAlignment.start,
  89. children: [
  90. Row(
  91. children: [
  92. Expanded(
  93. child: Text(
  94. item['route'] as String,
  95. style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 15),
  96. ),
  97. ),
  98. if (status == 'pending' && item.containsKey('priority'))
  99. Container(
  100. padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
  101. decoration: BoxDecoration(
  102. color: item['priority'] == '高' ? Colors.red.shade100 : Colors.orange.shade100,
  103. borderRadius: BorderRadius.circular(4),
  104. ),
  105. child: Text(
  106. '${item['priority']}优先',
  107. style: TextStyle(
  108. fontSize: 11,
  109. color: item['priority'] == '高' ? Colors.red.shade800 : Colors.orange.shade800,
  110. ),
  111. ),
  112. ),
  113. ],
  114. ),
  115. const SizedBox(height: 8),
  116. Row(
  117. children: [
  118. _InfoChip(icon: Icons.tag, text: item['id'] as String),
  119. const SizedBox(width: 8),
  120. _InfoChip(icon: Icons.calendar_today, text: item['date'] as String, size: 12),
  121. const SizedBox(width: 8),
  122. _InfoChip(icon: Icons.location_on, text: '${item['points']}个巡检点'),
  123. ],
  124. ),
  125. if (status == 'ongoing') ...[
  126. const SizedBox(height: 8),
  127. LinearProgressIndicator(
  128. value: 0.5,
  129. backgroundColor: Colors.grey.shade200,
  130. ),
  131. const SizedBox(height: 4),
  132. Text('进度: ${item['progress']}', style: const TextStyle(fontSize: 12, color: Colors.grey)),
  133. ],
  134. if (status == 'done') ...[
  135. const SizedBox(height: 8),
  136. Text('巡检结果: ${item['result']}', style: const TextStyle(fontSize: 13, color: Colors.green)),
  137. ],
  138. const SizedBox(height: 12),
  139. Row(
  140. mainAxisAlignment: MainAxisAlignment.end,
  141. children: [
  142. if (status == 'pending')
  143. FilledButton.icon(
  144. onPressed: () {},
  145. icon: const Icon(Icons.play_arrow, size: 18),
  146. label: const Text('开始巡检'),
  147. ),
  148. if (status == 'ongoing')
  149. FilledButton.icon(
  150. onPressed: () {},
  151. icon: const Icon(Icons.continue, size: 18),
  152. label: const Text('继续'),
  153. ),
  154. if (status == 'done')
  155. OutlinedButton.icon(
  156. onPressed: () {},
  157. icon: const Icon(Icons.visibility, size: 18),
  158. label: const Text('查看详情'),
  159. ),
  160. ],
  161. ),
  162. ],
  163. ),
  164. ),
  165. );
  166. }
  167. }
  168. class _InfoChip extends StatelessWidget {
  169. final IconData icon;
  170. final String text;
  171. final double size;
  172. const _InfoChip({required this.icon, required this.text, this.size = 14});
  173. @override
  174. Widget build(BuildContext context) {
  175. return Row(
  176. mainAxisSize: MainAxisSize.min,
  177. children: [
  178. Icon(icon, size: size, color: Colors.grey),
  179. const SizedBox(width: 2),
  180. Text(text, style: TextStyle(fontSize: 12, color: Colors.grey.shade700)),
  181. ],
  182. );
  183. }
  184. }