event_manage.dart 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. import 'package:app_business/service/api.dart';
  2. import 'package:app_business/view/home/dialog_event_register.dart';
  3. import 'package:pretty_qr_code/pretty_qr_code.dart';
  4. import 'package:track_common/widget.dart';
  5. import 'package:track_common/widget/prelude.dart';
  6. import 'event_manage_controller.dart';
  7. class EventManage extends GetView<EventManagerController> {
  8. const EventManage({super.key});
  9. @override
  10. Widget build(BuildContext context) {
  11. return Level2View(
  12. level1: level1(),
  13. level2: level2(),
  14. level1Title: '赛事列表',
  15. level1Action: wDate(context),
  16. level2Title: '用户列表',
  17. level2SubTitle: Obx(() => Text(
  18. controller.selected?.name != null
  19. ? '(${controller.selected!.name})'
  20. : '',
  21. style: const TextStyle(color: Colors.grey, fontSize: 14.22),
  22. )));
  23. }
  24. Widget wDate(BuildContext context) {
  25. return GestureDetector(
  26. onTap: () => _onTapDate(context),
  27. child: Obx(() => Container(
  28. height: 22.04,
  29. padding: const EdgeInsets.symmetric(horizontal: 8),
  30. decoration: BoxDecoration(
  31. border:
  32. Border.all(color: const Color(0xffe3e3e3), width: 0.71),
  33. borderRadius: BorderRadius.circular(2.13)),
  34. child: Text(controller.dateStr),
  35. )));
  36. }
  37. Future<void> _onTapDate(BuildContext context) async {
  38. final date = await showDatePicker(
  39. context: context,
  40. initialDate: controller.filterDate.value,
  41. firstDate: DateTime.now(),
  42. lastDate: DateTime.now().add(365.days));
  43. if (date != null) {
  44. controller.filterDate.value = date;
  45. controller.flushList();
  46. }
  47. }
  48. Widget level1() {
  49. return Obx(() => ListView(
  50. children: controller.eventList
  51. .map((e) => EventTitle(
  52. data: e,
  53. selected: controller.selectedId.value == e.id,
  54. onTap: () => controller.selectedId.value = e.id,
  55. ))
  56. .toList()));
  57. }
  58. Widget level2() {
  59. return Column(
  60. children: [
  61. Expanded(
  62. child: Obx(
  63. () => LineChart(titles: rightTitles(), children: rightUsers())))
  64. ],
  65. );
  66. }
  67. Iterable<LineChartTitle> rightTitles() {
  68. return [
  69. LineChartTitle(
  70. title: Checkbox(
  71. value: false,
  72. onChanged: (v) {
  73. controller.selectedUser.update((val) {
  74. final all = controller.userList.map((e) => e.checkId);
  75. val?.assignAll(all);
  76. });
  77. }),
  78. width: 32),
  79. const LineChartTitle(title: Text('序号'), width: 42),
  80. const LineChartTitle(title: Text('用户名'), width: 70),
  81. const LineChartTitle(title: Text('手机号'), flex: 1),
  82. const LineChartTitle(title: Text('签到时间'), width: 78),
  83. const LineChartTitle(title: Text('手环'), width: 67),
  84. const LineChartTitle(title: Text('路线'), width: 90),
  85. const LineChartTitle(title: Text('状态'), width: 67),
  86. const LineChartTitle(title: Text('操作'), width: 67),
  87. ];
  88. }
  89. Iterable<LineChartElem> rightUsers() {
  90. return controller.userList.indexed.map((e) {
  91. final (i, one) = e;
  92. var stateStr = '';
  93. var stateColor = Colors.white;
  94. switch (one.state) {
  95. case UserState.idle:
  96. stateStr = '未分发';
  97. stateColor = Colors.blue;
  98. break;
  99. case UserState.isStart:
  100. stateStr = '已开始';
  101. stateColor = Colors.green;
  102. break;
  103. case UserState.isFinish:
  104. stateStr = '已结束';
  105. stateColor = Colors.orange;
  106. break;
  107. default:
  108. }
  109. var optStr = '';
  110. return LineChartElem([
  111. Checkbox(
  112. value: controller.selectedUser.value.contains(one.checkId),
  113. onChanged: (v) {
  114. controller.selectedUser.update((val) {
  115. if (v == true) {
  116. val?.add(one.checkId);
  117. } else {
  118. val?.remove(one.checkId);
  119. }
  120. });
  121. }),
  122. Text('${i + 1}'),
  123. Text(one.name),
  124. Text(one.phone),
  125. Text(one.checkTime),
  126. Text(one.bandSN),
  127. one.state == UserState.idle
  128. ? SizedBox(
  129. height: 22.78,
  130. width: 51.2,
  131. child: SmallButton(
  132. color: Colors.blue,
  133. onPressed: routeSelect,
  134. child: const Text('分发')))
  135. : Text(one.routeName),
  136. one.state == UserState.hasRoute
  137. ? SmallButton(child: const Text('开始'), onPressed: () {})
  138. : Text(stateStr, style: TextStyle(color: stateColor)),
  139. SizedBox(
  140. width: 51.2,
  141. height: 22.76,
  142. child: SmallButton(
  143. color: const Color(0xffff0000),
  144. isOutline: true,
  145. onPressed: () {
  146. controller.deleteSignIn(one);
  147. },
  148. child: const Text('删除'),
  149. ))
  150. ]);
  151. });
  152. }
  153. Future<void> routeSelect() async {
  154. final list = await controller.routeList();
  155. await Get.dialog(_RouteSelectDialog(list: list));
  156. final id = controller.tmpSelectRoute?.id;
  157. if (id != null) {
  158. await controller.routeSelect([id]);
  159. }
  160. }
  161. }
  162. class _RouteSelectDialog extends GetView<EventManagerController> {
  163. const _RouteSelectDialog({required this.list});
  164. final Iterable<RouteInfo> list;
  165. @override
  166. Widget build(BuildContext context) {
  167. return AlertDialog(
  168. title: const Center(
  169. child: Text(
  170. '选择路线',
  171. style: TextStyle(fontSize: 17),
  172. )),
  173. backgroundColor: Colors.white,
  174. shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(17.78)),
  175. content: Column(
  176. mainAxisSize: MainAxisSize.min,
  177. crossAxisAlignment: CrossAxisAlignment.center,
  178. children: [
  179. SizedBox(
  180. width: 303.64,
  181. child: DropdownMenu<RouteInfo>(
  182. key: GlobalKey(),
  183. width: 303,
  184. hintText: '请选择路线',
  185. onSelected: (one) {
  186. controller.tmpSelectRoute = one;
  187. },
  188. inputDecorationTheme: InputDecorationTheme(
  189. border: textBorder,
  190. isDense: true,
  191. ),
  192. dropdownMenuEntries: list
  193. .map((e) =>
  194. DropdownMenuEntry<RouteInfo>(value: e, label: e.name))
  195. .toList())),
  196. const SizedBox(height: 30),
  197. Row(
  198. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  199. children: [
  200. SizedBox(
  201. height: 38,
  202. width: 106.67,
  203. child: SmallButton(
  204. onPressed: () {
  205. Get.back();
  206. },
  207. color: Colors.orange,
  208. child: const Text('随机'))),
  209. SizedBox(
  210. height: 38,
  211. width: 106.67,
  212. child: SmallButton(
  213. onPressed: () {
  214. Get.back();
  215. },
  216. color: Colors.blue,
  217. child: const Text('确认'))),
  218. ],
  219. )
  220. ],
  221. ),
  222. );
  223. }
  224. }
  225. class EventTitle extends GetView<EventManagerController> {
  226. final bool selected;
  227. final EventInManage data;
  228. final VoidCallback onTap;
  229. const EventTitle(
  230. {super.key,
  231. required this.selected,
  232. required this.data,
  233. required this.onTap});
  234. @override
  235. Widget build(BuildContext context) {
  236. var children = <Widget>[
  237. AppTitleList(
  238. title: data.name,
  239. tail: Text('${data.userList.length}'),
  240. isSelected: selected,
  241. onTap: onTap,
  242. )
  243. ];
  244. if (selected) {
  245. children.add(const SizedBox(height: 2));
  246. children.add(Container(
  247. decoration: const BoxDecoration(
  248. color: Color(0xfff1f1f1),
  249. borderRadius: BorderRadius.only(
  250. bottomLeft: Radius.circular(14.22),
  251. bottomRight: Radius.circular(14.22))),
  252. padding: const EdgeInsets.all(16.3),
  253. width: 221.87,
  254. child: Column(
  255. mainAxisSize: MainAxisSize.min,
  256. children: [
  257. Row(
  258. children: [
  259. DarkButton(
  260. onPressed: data.isAllowDel
  261. ? () => controller.deleteEvent(data)
  262. : null,
  263. child: const Text('删除')),
  264. const Spacer(),
  265. DarkButton(
  266. color: Colors.blue,
  267. onPressed: data.isAllowEdit
  268. ? () async {
  269. final r = await showEventEditDialog(
  270. controller.mapId!,
  271. EventRegisterInfo()..name = data.name);
  272. if (r != null) {
  273. controller.eventEdit(data.id, r);
  274. }
  275. }
  276. : null,
  277. child: const Text('修改')),
  278. ],
  279. ),
  280. const SizedBox(height: 24),
  281. SizedBox.square(
  282. dimension: 128, child: PrettyQrView.data(data: data.qrCode)),
  283. const SizedBox(height: 12),
  284. const Text(
  285. '用彩图奔跑APP扫码签到',
  286. style: TextStyle(color: Colors.red, fontSize: 14.22),
  287. )
  288. ],
  289. ),
  290. ));
  291. }
  292. return Column(
  293. mainAxisSize: MainAxisSize.min,
  294. children: children,
  295. );
  296. }
  297. }