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

revenue_tab.dart 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. import 'package:flutter/material.dart';
  2. /// 营业收费 Tab
  3. class RevenueTab extends StatelessWidget {
  4. const RevenueTab({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. await Future.delayed(const Duration(seconds: 1));
  12. },
  13. child: ListView(
  14. padding: const EdgeInsets.all(16),
  15. children: [
  16. // ---------- 本月营收概览 ----------
  17. Card(
  18. elevation: 0,
  19. color: colorScheme.primaryContainer.withAlpha(80),
  20. shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
  21. child: Padding(
  22. padding: const EdgeInsets.all(20),
  23. child: Column(
  24. crossAxisAlignment: CrossAxisAlignment.start,
  25. children: [
  26. Text('本月营收', style: TextStyle(fontSize: 14, color: colorScheme.onSurfaceVariant)),
  27. const SizedBox(height: 8),
  28. Row(
  29. crossAxisAlignment: CrossAxisAlignment.end,
  30. children: [
  31. Text(
  32. '¥ 358,620',
  33. style: TextStyle(
  34. fontSize: 32,
  35. fontWeight: FontWeight.bold,
  36. color: colorScheme.primary,
  37. ),
  38. ),
  39. const SizedBox(width: 8),
  40. Padding(
  41. padding: const EdgeInsets.only(bottom: 6),
  42. child: Text(
  43. '较上月 ↑ 5.8%',
  44. style: TextStyle(fontSize: 13, color: Colors.green.shade700),
  45. ),
  46. ),
  47. ],
  48. ),
  49. const SizedBox(height: 16),
  50. Row(
  51. mainAxisAlignment: MainAxisAlignment.spaceAround,
  52. children: [
  53. _StatItem(label: '已收', value: '¥312,450', color: Colors.green),
  54. _StatItem(label: '待收', value: '¥46,170', color: Colors.orange),
  55. _StatItem(label: '欠费', value: '¥12,800', color: Colors.red),
  56. ],
  57. ),
  58. ],
  59. ),
  60. ),
  61. ),
  62. const SizedBox(height: 24),
  63. // ---------- 快捷操作 ----------
  64. Text('快捷操作', style: theme.textTheme.titleMedium),
  65. const SizedBox(height: 12),
  66. Row(
  67. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  68. children: [
  69. _RevenueAction(icon: Icons.receipt, label: '抄表录入', color: Colors.blue, onTap: () {}),
  70. _RevenueAction(icon: Icons.payment, label: '缴费记录', color: Colors.green, onTap: () {}),
  71. _RevenueAction(icon: Icons.notifications_active, label: '催缴通知', color: Colors.orange, onTap: () {}),
  72. _RevenueAction(icon: Icons.analytics, label: '营收报表', color: Colors.purple, onTap: () {}),
  73. ],
  74. ),
  75. const SizedBox(height: 24),
  76. // ---------- 近期账单 ----------
  77. Text('近期账单', style: theme.textTheme.titleMedium),
  78. const SizedBox(height: 12),
  79. _BillTile(
  80. customer: '张三',
  81. address: '阳光小区3-501',
  82. amount: '¥ 85.50',
  83. period: '2024-05',
  84. status: '已缴费',
  85. statusColor: Colors.green,
  86. ),
  87. _BillTile(
  88. customer: '李四',
  89. address: '翠湖花园2-302',
  90. amount: '¥ 120.00',
  91. period: '2024-05',
  92. status: '待缴费',
  93. statusColor: Colors.orange,
  94. ),
  95. _BillTile(
  96. customer: '王五',
  97. address: '东方名城8-101',
  98. amount: '¥ 65.20',
  99. period: '2024-05',
  100. status: '已缴费',
  101. statusColor: Colors.green,
  102. ),
  103. _BillTile(
  104. customer: '赵六',
  105. address: '锦绣家园5-601',
  106. amount: '¥ 98.80',
  107. period: '2024-05',
  108. status: '欠费',
  109. statusColor: Colors.red,
  110. ),
  111. ],
  112. ),
  113. );
  114. }
  115. }
  116. class _StatItem extends StatelessWidget {
  117. final String label;
  118. final String value;
  119. final Color color;
  120. const _StatItem({required this.label, required this.value, required this.color});
  121. @override
  122. Widget build(BuildContext context) {
  123. return Column(
  124. children: [
  125. Text(value, style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: color)),
  126. const SizedBox(height: 4),
  127. Text(label, style: const TextStyle(fontSize: 12, color: Colors.grey)),
  128. ],
  129. );
  130. }
  131. }
  132. class _RevenueAction extends StatelessWidget {
  133. final IconData icon;
  134. final String label;
  135. final Color color;
  136. final VoidCallback onTap;
  137. const _RevenueAction({
  138. required this.icon,
  139. required this.label,
  140. required this.color,
  141. required this.onTap,
  142. });
  143. @override
  144. Widget build(BuildContext context) {
  145. return InkWell(
  146. onTap: onTap,
  147. borderRadius: BorderRadius.circular(12),
  148. child: Column(
  149. mainAxisSize: MainAxisSize.min,
  150. children: [
  151. Container(
  152. width: 48,
  153. height: 48,
  154. decoration: BoxDecoration(
  155. color: color.withAlpha(30),
  156. borderRadius: BorderRadius.circular(12),
  157. ),
  158. child: Icon(icon, color: color, size: 24),
  159. ),
  160. const SizedBox(height: 6),
  161. Text(label, style: const TextStyle(fontSize: 12)),
  162. ],
  163. ),
  164. );
  165. }
  166. }
  167. class _BillTile extends StatelessWidget {
  168. final String customer;
  169. final String address;
  170. final String amount;
  171. final String period;
  172. final String status;
  173. final Color statusColor;
  174. const _BillTile({
  175. required this.customer,
  176. required this.address,
  177. required this.amount,
  178. required this.period,
  179. required this.status,
  180. required this.statusColor,
  181. });
  182. @override
  183. Widget build(BuildContext context) {
  184. return Card(
  185. margin: const EdgeInsets.only(bottom: 8),
  186. child: ListTile(
  187. leading: CircleAvatar(
  188. backgroundColor: Colors.blue.shade50,
  189. child: Text(customer[0], style: TextStyle(color: Colors.blue.shade700)),
  190. ),
  191. title: Text(customer),
  192. subtitle: Text('$address | $period'),
  193. trailing: Column(
  194. mainAxisAlignment: MainAxisAlignment.center,
  195. crossAxisAlignment: CrossAxisAlignment.end,
  196. children: [
  197. Text(amount, style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 15)),
  198. const SizedBox(height: 2),
  199. Text(status, style: TextStyle(fontSize: 12, color: statusColor)),
  200. ],
  201. ),
  202. ),
  203. );
  204. }
  205. }