event_manage.dart 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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('手机号'), width: 98),
  82. const LineChartTitle(title: Text('签到时间'), width: 78),
  83. const LineChartTitle(title: Text('手环'), width: 67),
  84. const LineChartTitle(title: Text('路线'), flex: 1),
  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. var optStr = '删除';
  95. var optColor = Colors.red;
  96. VoidCallback? opt;
  97. if (one.isAllowDel) {
  98. opt = () => controller.deleteSignIn(one);
  99. }
  100. switch (one.state) {
  101. case UserState.idle:
  102. stateStr = '未分发';
  103. stateColor = Colors.blue;
  104. break;
  105. case UserState.isStart:
  106. stateStr = '已开始';
  107. stateColor = Colors.green;
  108. optStr = '结束';
  109. opt = () => controller.userStopGame(one);
  110. break;
  111. case UserState.isFinish:
  112. stateStr = '已结束';
  113. stateColor = Colors.orange;
  114. optStr = '重赛';
  115. optColor = Colors.orange;
  116. opt = () => controller.userRestartGame(one);
  117. break;
  118. default:
  119. }
  120. var snStr = '--';
  121. const n = 4;
  122. if (one.bandSN.length > n) {
  123. snStr = '-${one.bandSN.substring(one.bandSN.length - n)}';
  124. } else if (one.bandSN.isNotEmpty) {
  125. snStr = one.bandSN;
  126. }
  127. return LineChartElem([
  128. Checkbox(
  129. value: controller.selectedUser.value.contains(one.checkId),
  130. onChanged: (v) {
  131. controller.selectedUser.update((val) {
  132. if (v == true) {
  133. val?.add(one.checkId);
  134. } else {
  135. val?.remove(one.checkId);
  136. }
  137. });
  138. }),
  139. Text('${i + 1}'),
  140. Text(one.name),
  141. Text(one.phone),
  142. Text(one.checkTime),
  143. Text(snStr),
  144. one.state == UserState.idle
  145. ? button(
  146. color: Colors.blue,
  147. onPressed: () => routeSelect(one),
  148. text: '分发')
  149. : Text(one.routeName, maxLines: 1),
  150. one.state == UserState.hasRoute
  151. ? button(
  152. color: Colors.green,
  153. onPressed: () => controller.userStart(one),
  154. text: '开始')
  155. : Text(stateStr, style: TextStyle(color: stateColor)),
  156. SizedBox(
  157. width: 51.2,
  158. height: 22.76,
  159. child: SmallButton(
  160. color: optColor,
  161. isOutline: true,
  162. onPressed: opt,
  163. child: Text(optStr),
  164. ))
  165. ]);
  166. });
  167. }
  168. Widget button({Color? color, VoidCallback? onPressed, required String text}) {
  169. return SizedBox(
  170. height: 22.78,
  171. width: 51.2,
  172. child: SmallButton(
  173. color: Colors.blue, onPressed: onPressed, child: Text(text)));
  174. }
  175. Future<void> routeSelect(UserInManage user) async {
  176. final list = await controller.routeList(user);
  177. await Get.dialog(_RouteSelectDialog(list: list));
  178. final route = controller.tmpSelectRoute;
  179. if (route != null) {
  180. await controller.routeAlloc(user, route);
  181. }
  182. }
  183. }
  184. class _RouteSelectDialog extends GetView<EventManagerController> {
  185. const _RouteSelectDialog({required this.list});
  186. final Iterable<RouteInfo> list;
  187. @override
  188. Widget build(BuildContext context) {
  189. return AlertDialog(
  190. title: const Center(
  191. child: Text(
  192. '选择路线',
  193. style: TextStyle(fontSize: 17),
  194. )),
  195. backgroundColor: Colors.white,
  196. shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(17.78)),
  197. content: Column(
  198. mainAxisSize: MainAxisSize.min,
  199. crossAxisAlignment: CrossAxisAlignment.center,
  200. children: [
  201. SizedBox(
  202. width: 303.64,
  203. child: DropdownMenu<RouteInfo>(
  204. key: GlobalKey(),
  205. width: 303,
  206. hintText: '请选择路线',
  207. onSelected: (one) {
  208. controller.tmpSelectRoute = one;
  209. },
  210. inputDecorationTheme: InputDecorationTheme(
  211. border: textBorder,
  212. isDense: true,
  213. ),
  214. dropdownMenuEntries: list
  215. .map((e) =>
  216. DropdownMenuEntry<RouteInfo>(value: e, label: e.name))
  217. .toList())),
  218. const SizedBox(height: 30),
  219. Row(
  220. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  221. children: [
  222. SizedBox(
  223. height: 38,
  224. width: 106.67,
  225. child: SmallButton(
  226. onPressed: () {
  227. Get.back();
  228. },
  229. color: Colors.orange,
  230. child: const Text('随机'))),
  231. SizedBox(
  232. height: 38,
  233. width: 106.67,
  234. child: SmallButton(
  235. onPressed: () {
  236. Get.back();
  237. },
  238. color: Colors.blue,
  239. child: const Text('确认'))),
  240. ],
  241. )
  242. ],
  243. ),
  244. );
  245. }
  246. }
  247. class EventTitle extends GetView<EventManagerController> {
  248. final bool selected;
  249. final EventInManage data;
  250. final VoidCallback onTap;
  251. const EventTitle(
  252. {super.key,
  253. required this.selected,
  254. required this.data,
  255. required this.onTap});
  256. @override
  257. Widget build(BuildContext context) {
  258. var children = <Widget>[
  259. AppTitleList(
  260. title: data.name,
  261. tail: Text('${data.userList.length}'),
  262. isSelected: selected,
  263. onTap: onTap,
  264. )
  265. ];
  266. if (selected) {
  267. children.add(const SizedBox(height: 2));
  268. children.add(Container(
  269. decoration: const BoxDecoration(
  270. color: Color(0xfff1f1f1),
  271. borderRadius: BorderRadius.only(
  272. bottomLeft: Radius.circular(14.22),
  273. bottomRight: Radius.circular(14.22))),
  274. padding: const EdgeInsets.all(16.3),
  275. width: 221.87,
  276. child: Column(
  277. mainAxisSize: MainAxisSize.min,
  278. children: [
  279. Row(
  280. children: [
  281. DarkButton(
  282. onPressed: data.isAllowDel
  283. ? () => controller.deleteEvent(data)
  284. : null,
  285. child: const Text('删除')),
  286. const Spacer(),
  287. DarkButton(
  288. color: Colors.blue,
  289. onPressed: data.isAllowEdit
  290. ? () async {
  291. final r = await showEventEditDialog(
  292. controller.mapId!,
  293. EventRegisterInfo()..name = data.name);
  294. if (r != null) {
  295. controller.eventEdit(data.id, r);
  296. }
  297. }
  298. : null,
  299. child: const Text('修改')),
  300. ],
  301. ),
  302. const SizedBox(height: 24),
  303. SizedBox.square(
  304. dimension: 128, child: PrettyQrView.data(data: data.qrCode)),
  305. const SizedBox(height: 12),
  306. const Text(
  307. '用彩图奔跑APP扫码签到',
  308. style: TextStyle(color: Colors.red, fontSize: 14.22),
  309. )
  310. ],
  311. ),
  312. ));
  313. }
  314. return Column(
  315. mainAxisSize: MainAxisSize.min,
  316. children: children,
  317. );
  318. }
  319. }