field_control.dart 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. import 'package:application/service/api.dart' as pb;
  2. import 'package:application/widget.dart';
  3. import 'package:common_pub/ui/map_view/map_view.dart';
  4. import 'package:common_pub/ui/map_view/view_map_image.dart';
  5. import 'package:common_pub/ui/map_view/view_map_trace_tail.dart';
  6. import 'package:common_pub/ui/map_view/view_map_touch.dart';
  7. import 'package:common_pub/ui/map_view/view_map_user_point.dart';
  8. import 'package:common_pub/ui/map_view/view_plug_loading.dart';
  9. import 'package:common_pub/utils.dart';
  10. import 'field_control_controller.dart';
  11. class FieldControlPage extends StatelessWidget {
  12. const FieldControlPage({super.key});
  13. @override
  14. Widget build(BuildContext context) {
  15. return GetBuilder(
  16. init: FieldControlController(),
  17. builder: (c) {
  18. return Container(
  19. height: double.infinity,
  20. width: double.infinity,
  21. color: const Color(0xffc9c0c0),
  22. alignment: Alignment.center,
  23. child: Obx(() {
  24. final mapWatch = c.mapWatch;
  25. return mapWatch != null
  26. ? content(context, mapWatch, c)
  27. : noData();
  28. }));
  29. });
  30. }
  31. Widget noData() {
  32. return Center(
  33. child: Column(
  34. mainAxisSize: MainAxisSize.min,
  35. children: [
  36. Image.asset(Assets.imagesIcNoData, height: 64),
  37. const SizedBox(height: 25),
  38. const Text('没有数据, 请选择地图',
  39. style: TextStyle(color: Color(0xff707070), fontSize: 18.5)),
  40. ],
  41. ),
  42. );
  43. }
  44. Widget content(
  45. BuildContext context, MapWatchService map, FieldControlController c) {
  46. return Row(
  47. children: [
  48. Expanded(
  49. child: Column(
  50. children: [
  51. Expanded(
  52. child: ViewMapStack(plug: map.plugMap, children: [
  53. ViewPlugLoading(map.plugMap),
  54. ViewMapImage(map.plugMap),
  55. _ViewTrace(map: map, traceDuration:30.seconds),
  56. ViewMapTouch(map.plugMap)
  57. ])),
  58. _MsgView(),
  59. ],
  60. )),
  61. _ActiveInfoView()
  62. ],
  63. );
  64. }
  65. }
  66. class _ViewTrace extends GetView<FieldControlController> {
  67. const _ViewTrace({required this.map, required this.traceDuration});
  68. final MapWatchService map;
  69. final Duration traceDuration;
  70. @override
  71. Widget build(BuildContext context) {
  72. return Obx(() {
  73. final children = <Widget>[];
  74. for (final act in map.activeList) {
  75. for (final user in act.userList) {
  76. if (user.isHide.value) {
  77. continue;
  78. }
  79. final trace = user.trace.lastOrNull;
  80. final traceTailOnMap = <Offset>[];
  81. final st = user.gameInfo.gameSaveInfo.startAt.toModel();
  82. for(final one in user.trace){
  83. if(DateTime.now().difference(st.add(one.ts)) < traceDuration ){
  84. traceTailOnMap.add(one.onMap);
  85. }
  86. }
  87. if (trace != null) {
  88. children.add(ViewMapTraceTail(plug: map.plugMap, onMapTrace: traceTailOnMap, color: user.flag.value.color,));
  89. children.add(ViewMapUserPoint(map.plugMap, trace,
  90. info: user.name, color: user.flag.value.color));
  91. }
  92. }
  93. }
  94. return Stack(alignment: Alignment.topLeft, children: children);
  95. });
  96. }
  97. }
  98. class _ActiveInfoView extends GetView<FieldControlController> {
  99. @override
  100. Widget build(BuildContext context) {
  101. return Obx(() => Container(
  102. width: 370,
  103. height: double.infinity,
  104. color: Colors.white,
  105. child: ListView(
  106. children: controller.activeList
  107. .map((element) => activeView(element))
  108. .toList(),
  109. ),
  110. ));
  111. }
  112. Widget activeView(ActiveInfo info) {
  113. final children = <Widget>[
  114. Row(children: [
  115. Text('${info.name} (${info.userList.length}人)'),
  116. const Spacer(),
  117. IconButton(
  118. onPressed: () {
  119. info.isHide.value = !info.isHide.value;
  120. },
  121. icon: info.isHide.value
  122. ? const Icon(Icons.arrow_drop_down)
  123. : const Icon(Icons.arrow_drop_up))
  124. ]),
  125. ];
  126. if (!info.isHide.value) {
  127. children.addAll([
  128. Container(
  129. decoration: BoxDecoration(
  130. color: Colors.white, borderRadius: BorderRadius.circular(5)),
  131. padding: const EdgeInsets.fromLTRB(26, 11, 26, 11),
  132. child: Row(
  133. children: [
  134. Text('广播'),
  135. const Spacer(),
  136. Image.asset(Assets.imagesIcCp, height: 20, width: 20),
  137. Text(' ${info.cpAllCount}'),
  138. const Spacer(),
  139. Text('全部隐藏'),
  140. ],
  141. ),
  142. )
  143. ]);
  144. children
  145. .addAll(info.userList.map((e) => _UserInfoView(data: e)).toList());
  146. }
  147. return Container(
  148. decoration: BoxDecoration(
  149. color: const Color(0xffe0e0e0),
  150. borderRadius: BorderRadius.circular(5)),
  151. margin: const EdgeInsets.fromLTRB(9, 12, 9, 12),
  152. padding: const EdgeInsets.all(9),
  153. child: Column(
  154. children: children,
  155. ),
  156. );
  157. }
  158. }
  159. class _UserInfoView extends GetView<FieldControlController> {
  160. const _UserInfoView({required this.data});
  161. final UserInfo data;
  162. @override
  163. Widget build(BuildContext context) {
  164. return Container(
  165. decoration: BoxDecoration(
  166. color: Colors.white, borderRadius: BorderRadius.circular(5)),
  167. padding: const EdgeInsets.fromLTRB(7, 11, 7, 11),
  168. margin: const EdgeInsets.only(top: 5),
  169. child: Row(
  170. crossAxisAlignment: CrossAxisAlignment.start,
  171. children: [
  172. Obx(() => Container(
  173. margin: const EdgeInsets.only(top: 2),
  174. decoration: BoxDecoration(
  175. color: data.flag.value.color,
  176. borderRadius: BorderRadius.circular(4)),
  177. width: 7,
  178. height: 16)),
  179. const SizedBox(
  180. width: 8,
  181. ),
  182. Expanded(
  183. child: Column(
  184. crossAxisAlignment: CrossAxisAlignment.start,
  185. children: [
  186. Text.rich(TextSpan(
  187. text: data.name,
  188. children: [TextSpan(text: ' [${data.routeName}]')])),
  189. const SizedBox(height: 5),
  190. Row(
  191. children: [
  192. container(null, cpInfo, Colors.blue),
  193. container(
  194. const Icon(
  195. Icons.favorite,
  196. size: 13,
  197. color: Colors.white,
  198. ),
  199. ' ${hr == 0 ? '--' : hr}',
  200. (data.gameInfo.otherInfo.hasHeartRatePercent()?data.gameInfo.otherInfo.heartRatePercent: 0)
  201. .toHRPColor()),
  202. container(null, paceInfo, data.pace.color)
  203. ],
  204. ),
  205. const SizedBox(height: 5),
  206. Row(
  207. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  208. children: [
  209. Text('距离 ${data.nextDistance.toString()}'),
  210. Text('时间 ${data.duration.toAppString()}'),
  211. Text('里程 ${data.distance.toString()}'),
  212. ],
  213. )
  214. ],
  215. )),
  216. GestureDetector(
  217. onTap: () {
  218. data.isHide.value = !data.isHide.value;
  219. },
  220. child: Obx(() => Icon(
  221. data.isHide.value ? Icons.visibility_off : Icons.visibility,
  222. color:
  223. data.isHide.value ? Colors.grey : const Color(0xffffbb77),
  224. )),
  225. )
  226. ],
  227. ),
  228. );
  229. }
  230. int get hr {
  231. return data.gameInfo.hrInfo.hrInfo.lastOrNull?.hr ?? 0;
  232. }
  233. String get cpInfo {
  234. final next = data.nextWant;
  235. return next!=null?'${data.nextCPSN}点(${next.sn})': '--';
  236. }
  237. String get paceInfo {
  238. Duration;
  239. return data.pace.toString();
  240. }
  241. Widget container(Widget? icon, String text, Color color) {
  242. final children = <Widget>[];
  243. if (icon != null) {
  244. children.add(icon);
  245. }
  246. children.add(
  247. Text(text, style: const TextStyle(color: Colors.white, fontSize: 14)));
  248. return Container(
  249. height: 18,
  250. padding: const EdgeInsets.fromLTRB(10, 0, 12, 0),
  251. margin: const EdgeInsets.only(right: 6),
  252. alignment: Alignment.center,
  253. decoration:
  254. BoxDecoration(color: color, borderRadius: BorderRadius.circular(9)),
  255. child: Row(
  256. children: children,
  257. ),
  258. );
  259. }
  260. }
  261. class _MsgView extends GetView<FieldControlController> {
  262. @override
  263. Widget build(BuildContext context) {
  264. return Container();
  265. }
  266. }