| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424 |
- import 'package:common_pub/logger.dart';
- import 'package:common_pub/model/distance.dart';
- import 'package:common_pub/model/pace.dart';
- import 'package:common_pub/utils.dart';
- import 'package:flutter/material.dart';
- import 'package:get/get.dart';
- import '../../../widget/title_point.dart';
- import '../../service/map_watch.dart';
- abstract class PersonalRankController extends GetxController {
- @override
- void onInit() {
- super.onInit();
- final now = DateTime.now();
- filterStartAt.value = DateTime(now.year, now.month, now.day);
- workFlushData();
- }
- Future<void> workFlushData() async {
- while (!isClosed) {
- final map = mapWatch;
- if (map == null) {
- activeList.clear();
- await 3.seconds.delay();
- continue;
- }
- try {
- final out = await getRankList(map.id, filterStartAt.value);
- for (final one in out) {
- final oldEvent = map.getEventById(one.id);
- if (oldEvent != null) {
- for (final user in one.userList) {
- final oldUser = oldEvent.getUserById(user.id);
- if (oldUser != null) {
- user.flag = oldUser.flag.value;
- }
- }
- }
- }
- activeList.value = out;
- } catch (_) {}
- await 3.seconds.delay();
- }
- }
- final filterStartAt = DateTime.now().obs;
- final activeList = <RankActiveInfo>[].obs;
- final Rx<RankActiveInfo?> selectActive = Rx(null);
- MapWatch? get mapWatch => Get.find<MapWatchService>().instance;
- Future<List<RankActiveInfo>> getRankList(int mapId, DateTime startAt);
- }
- class PersonalRankPage extends GetView<PersonalRankController> {
- const PersonalRankPage({super.key});
- @override
- Widget build(BuildContext context) {
- return Container(
- width: double.infinity,
- height: double.infinity,
- margin: const EdgeInsets.all(20),
- padding: const EdgeInsets.fromLTRB(12, 17, 12, 17),
- decoration: BoxDecoration(
- color: Colors.transparent, borderRadius: BorderRadius.circular(16)),
- child: DefaultTextStyle(
- style: const TextStyle(color: Colors.white),
- child: Row(
- children: [
- SizedBox(
- width: 260,
- height: double.infinity,
- child: Obx(() => eActiveList(context, controller))),
- const SizedBox(width: 20),
- Expanded(child: Obx(() => eUserList(context, controller)))
- ],
- )),
- );
- }
- Future<void> _pickDate(BuildContext context, PersonalRankController c) async {
- final now = c.filterStartAt.value;
- final time = await showTimePicker(
- context: context, initialTime: TimeOfDay.fromDateTime(now));
- if (time != null) {
- c.filterStartAt.value =
- DateTime(now.year, now.month, now.day, time.hour, time.minute);
- info('time: ${c.filterStartAt.value}');
- c.selectActive.value = null;
- c.activeList.clear();
- }
- // final date = await showDatePicker(
- // context: context,
- // initialDate: c.filterStartAt.value,
- // firstDate: DateTime(now.year - 1),
- // lastDate: DateTime(now.year, now.month, now.day + 1),
- // );
- //
- // if (date != null) {
- // c.filterStartAt.value = DateTime(date.year, date.month, date.day);
- // }
- }
- Widget titlePoint() {
- return const TitlePoint(color: Color(0xff98d8ff));
- }
- Widget eActiveList(BuildContext context, PersonalRankController c) {
- return Column(
- children: [
- Row(
- children: [
- Padding(padding: const EdgeInsets.all(8), child: titlePoint()),
- Text('活动列表',
- style: context.textTheme.titleLarge
- ?.copyWith(color: Colors.white, fontSize: 14.22)),
- const Spacer(),
- GestureDetector(
- onTap: () => _pickDate(context, c),
- child: Container(
- decoration: BoxDecoration(
- border: Border.all(color: const Color(0xffe3e3e3))),
- height: 22.04,
- alignment: Alignment.center,
- padding: const EdgeInsets.symmetric(horizontal: 8),
- child: Text(TimeOfDay.fromDateTime(c.filterStartAt.value)
- .format(context))))
- ],
- ),
- const SizedBox(height: 20),
- Expanded(
- child: Container(
- padding: const EdgeInsets.all(12),
- decoration: BoxDecoration(
- color: const Color(0xff003656),
- borderRadius: BorderRadius.circular(9)),
- child: ListView(
- children: c.activeList
- .map((e) => wActiveCard(
- context, e, c.selectActive.value?.id == e.id, () {
- c.selectActive.value = e;
- }))
- .toList(),
- ))),
- ],
- );
- }
- Widget wActiveCard(BuildContext context, RankActiveInfo active, bool selected,
- VoidCallback onTap) {
- return GestureDetector(
- onTap: onTap,
- child: Container(
- decoration: const BoxDecoration(color: Color(0xff00a0ff), boxShadow: [
- BoxShadow(color: Color(0x4d000000), blurRadius: 3.5)
- ]),
- height: _cardHeight,
- width: double.infinity,
- margin: const EdgeInsets.only(top: 7),
- padding: const EdgeInsets.only(right: 11),
- child: Row(
- children: [
- Container(
- margin: const EdgeInsets.only(right: 10),
- height: double.infinity,
- width: 6.4,
- color: selected ? const Color(0xffff870d) : Colors.transparent,
- ),
- Expanded(child: Text(active.name)),
- const SizedBox(width: 8),
- Text(active.userList.length.toString())
- ],
- ),
- ));
- }
- Widget eUserList(BuildContext context, PersonalRankController c) {
- final active = c.selectActive.value;
- if (active == null) {
- return const SizedBox();
- }
- final userList = c.selectActive.value?.userList ?? <RankUserInfo>[];
- return Column(
- children: [
- Row(
- children: [
- Padding(padding: const EdgeInsets.all(8), child: titlePoint()),
- Text('个人排名',
- style: context.textTheme.titleLarge
- ?.copyWith(color: Colors.white, fontSize: 14.22)),
- Text(' (${active.name})',
- style: context.textTheme.titleLarge?.copyWith(
- color: const Color(0xffffcb00), fontSize: 14.22)),
- ],
- ),
- Expanded(
- child: Padding(
- padding: const EdgeInsets.all(18),
- child: Column(
- children: [
- eUserListTitle(context),
- Expanded(
- child: ListView(
- children: userList.indexed.map<Widget>((t) {
- return eUserCard(context, c, t.$1 + 1, t.$2);
- }).toList(),
- ))
- ],
- )))
- ],
- );
- }
- Widget eUserListTitle(BuildContext context) {
- return DefaultTextStyle(
- style: const TextStyle(
- color: Color(0xff98d8ff),
- fontSize: 14.22,
- fontWeight: FontWeight.w700),
- child: Row(
- children: [
- const SizedBox(
- width: _userIndexWidth,
- child: Text('排名', textAlign: TextAlign.center)),
- const SizedBox(width: 4),
- const SizedBox(
- width: _userNameWidth,
- child: Text('用户名', textAlign: TextAlign.center)),
- verticalDivider(show: false),
- const SizedBox(
- width: _userPhoneWidth,
- child: Text(
- '手机号',
- textAlign: TextAlign.center,
- ),
- ),
- verticalDivider(show: false),
- const Expanded(
- flex: 5, child: Text('路线ID', textAlign: TextAlign.center)),
- verticalDivider(show: false),
- const SizedBox(
- width: _userTimeWidth,
- child: Text('总时间', textAlign: TextAlign.center)),
- verticalDivider(show: false),
- const Expanded(
- flex: 3, child: Text('总里程', textAlign: TextAlign.center)),
- verticalDivider(show: false),
- const Expanded(
- flex: 4, child: Text('配速', textAlign: TextAlign.center)),
- verticalDivider(show: false),
- const SizedBox(
- width: _userResultWidth,
- child: Text('状态', textAlign: TextAlign.center)),
- // verticalDivider(show: false),
- // const SizedBox(
- // width: _userFlagWidth,
- // child: Text('分组', textAlign: TextAlign.center)),
- // verticalDivider(show: false),
- ],
- ));
- }
- Widget eUserCard(BuildContext context, PersonalRankController c, int index,
- RankUserInfo data) {
- return DefaultTextStyle(
- style: context.textTheme.bodyMedium!.copyWith(color: Colors.white),
- child: Container(
- height: _cardHeight,
- width: double.infinity,
- margin: const EdgeInsets.only(top: 3),
- child: Row(
- children: [
- Container(
- width: _userIndexWidth,
- height: double.infinity,
- decoration: const BoxDecoration(
- color: Color(0xffff870d),
- borderRadius: BorderRadius.only(
- topLeft: Radius.circular(6),
- bottomLeft: Radius.circular(6))),
- alignment: Alignment.center,
- child: Text(
- index.toString(),
- textAlign: TextAlign.center,
- style: const TextStyle(
- fontSize: 34,
- fontWeight: FontWeight.w700,
- fontStyle: FontStyle.italic),
- )),
- const SizedBox(width: 4),
- Expanded(
- child: Container(
- height: double.infinity,
- decoration: const BoxDecoration(
- color: Color(0xff003656),
- borderRadius: BorderRadius.only(
- topRight: Radius.circular(6),
- bottomRight: Radius.circular(6))),
- child: Row(
- children: [
- SizedBox(
- width: _userNameWidth,
- child: Text(
- data.name,
- maxLines: 1,
- textAlign: TextAlign.center,
- )),
- verticalDivider(),
- SizedBox(
- width: _userPhoneWidth,
- child: Text(
- data.phone,
- textAlign: TextAlign.center,
- )),
- verticalDivider(),
- Expanded(
- flex: 5,
- child: Text(
- data.routeName,
- textAlign: TextAlign.center,
- )),
- verticalDivider(),
- SizedBox(
- width: _userTimeWidth,
- child: Text(
- data.duration.toMinSecondString(),
- textAlign: TextAlign.center,
- )),
- verticalDivider(),
- Expanded(
- flex: 3,
- child: Text(
- data.distance.toString(),
- textAlign: TextAlign.center,
- )),
- verticalDivider(),
- Expanded(
- flex: 4,
- child: Container(
- margin: const EdgeInsets.only(left: 8, right: 8),
- alignment: Alignment.center,
- height: 18,
- decoration: BoxDecoration(
- color: data.pace.color,
- borderRadius: BorderRadius.circular(9)),
- child: Text(
- data.pace.toString(),
- textAlign: TextAlign.center,
- ))),
- // verticalDivider(),
- verticalDivider(),
- SizedBox(
- width: _userResultWidth,
- child: Text(
- switch (data.state) {
- GameState.processing => '进行中',
- GameState.finish => '完赛',
- GameState.unFinish => '退赛'
- },
- textAlign: TextAlign.center,
- )),
- // Container(
- // alignment: Alignment.center,
- // width: _userFlagWidth,
- // child: Icon(Icons.flag, color: data.flag.color)),
- ],
- ),
- ))
- ],
- )));
- }
- Widget verticalDivider({bool show = true}) {
- return VerticalDivider(
- width: 3,
- indent: 14,
- endIndent: 14,
- color: show ? Colors.white : Colors.transparent,
- );
- }
- static const _userIndexWidth = 56.0;
- static const _userNameWidth = 70.0;
- static const _userPhoneWidth = 94.0;
- static const _userResultWidth = 62.0;
- static const _userTimeWidth = 62.0;
- static const _cardHeight = 45.0;
- // static const _userFlagWidth = 52.0;
- }
- enum GameState {
- processing,
- finish,
- unFinish,
- }
- class RankUserInfo {
- var id = 0;
- var name = '';
- var routeName = '';
- var state = GameState.processing;
- var duration = 0.seconds;
- var distance = 0.meter;
- var startAt = DateTime(2000);
- var phone = '';
- Pace get pace => Pace(distance, duration);
- var flag = Flag.red;
- }
- class RankActiveInfo {
- var id = 0;
- var name = '';
- var userList = <RankUserInfo>[];
- }
|