track_daily_item.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. import 'dart:math';
  2. import 'package:flutter/cupertino.dart';
  3. import 'package:flutter_screenutil/flutter_screenutil.dart';
  4. import 'package:location/data/bean/track_daily_bean.dart';
  5. import 'package:location/data/consts/constants.dart';
  6. import 'package:location/dialog/track_error_tips_dialog.dart';
  7. import 'package:location/module/analyse/location_analyse_page.dart';
  8. import 'package:location/module/track/track_util.dart';
  9. import 'package:location/resource/assets.gen.dart';
  10. import 'package:location/resource/colors.gen.dart';
  11. import 'package:location/resource/string.gen.dart';
  12. import 'package:location/utils/common_expand.dart';
  13. import 'package:location/utils/date_util.dart';
  14. import '../track_status.dart';
  15. typedef TrackItemClick = void Function(TrackDailyBean bean);
  16. Widget buildTrackDailyItem(TrackDailyBean bean, bool isEnd,
  17. {TrackItemClick? onItemClick}) {
  18. return Container(
  19. padding: EdgeInsets.symmetric(horizontal: 12.w),
  20. margin: EdgeInsets.only(bottom: 8.w),
  21. child: Column(
  22. crossAxisAlignment: CrossAxisAlignment.start,
  23. children: [
  24. Builder(builder: (context) {
  25. if (bean.status == TrackStatus.moving) {
  26. return _buildMovingTrackDailyItem(bean, onItemClick: onItemClick);
  27. } else if (bean.status == TrackStatus.stay) {
  28. return buildStayTrackDailyItem(bean, onItemClick: onItemClick);
  29. } else if (bean.status == TrackStatus.error) {
  30. return buildErrorTrackDailyItem(bean, onItemClick: onItemClick);
  31. } else {
  32. return SizedBox(height: 50.w, child: Text('未知轨迹,请更新最新应用版本'));
  33. }
  34. }),
  35. if (isEnd) buildEndPoint(bean)
  36. ],
  37. ),
  38. );
  39. }
  40. Widget _buildMovingTrackDailyItem(TrackDailyBean bean,
  41. {TrackItemClick? onItemClick}) {
  42. return Column(
  43. crossAxisAlignment: CrossAxisAlignment.start,
  44. children: [
  45. IntrinsicHeight(
  46. child: Row(
  47. children: [
  48. Column(
  49. crossAxisAlignment: CrossAxisAlignment.center,
  50. children: [
  51. _buildTimeText(bean.start),
  52. SizedBox(height: 4.w),
  53. _buildRingView(),
  54. SizedBox(height: 4.w),
  55. Expanded(
  56. child: Container(
  57. width: 1.w,
  58. decoration: BoxDecoration(
  59. color: '#F0F0F0'.color,
  60. borderRadius: BorderRadius.circular(100.r),
  61. ),
  62. ),
  63. )
  64. ],
  65. ),
  66. Expanded(
  67. child: GestureDetector(
  68. onTap: () {
  69. onItemClick?.call(bean);
  70. },
  71. child: Container(
  72. height: 50.w,
  73. margin: EdgeInsets.only(top: 26.w),
  74. decoration: BoxDecoration(
  75. borderRadius: BorderRadius.circular(8.r),
  76. gradient: LinearGradient(colors: [
  77. '#F8F5FF'.color,
  78. ColorName.transparent,
  79. ])),
  80. padding: EdgeInsets.symmetric(horizontal: 14.w),
  81. child: Row(
  82. children: [
  83. Assets.images.iconTrackMoving.image(width: 16.w),
  84. SizedBox(width: 5.w),
  85. Text(
  86. StringName.trackDetailMoving,
  87. style: TextStyle(
  88. fontSize: 12.sp,
  89. color: '#333333'.color,
  90. fontWeight: FontWeight.bold),
  91. )
  92. ],
  93. ),
  94. ),
  95. ))
  96. ],
  97. ),
  98. ),
  99. SizedBox(height: 8.w),
  100. ],
  101. );
  102. }
  103. Widget buildStayTrackDailyItem(TrackDailyBean bean,
  104. {EdgeInsetsGeometry? contentPadding, TrackItemClick? onItemClick}) {
  105. return Column(
  106. crossAxisAlignment: CrossAxisAlignment.start,
  107. children: [
  108. IntrinsicHeight(
  109. child: Row(
  110. children: [
  111. Column(
  112. crossAxisAlignment: CrossAxisAlignment.center,
  113. children: [
  114. _buildTimeText(bean.start),
  115. SizedBox(height: 4.w),
  116. _buildRingView(),
  117. SizedBox(height: 4.w),
  118. Expanded(
  119. child: Container(
  120. width: 1.w,
  121. decoration: BoxDecoration(
  122. color: '#F0F0F0'.color,
  123. borderRadius: BorderRadius.circular(100.r),
  124. ),
  125. ),
  126. )
  127. ],
  128. ),
  129. Expanded(
  130. child: GestureDetector(
  131. onTap: () {
  132. onItemClick?.call(bean);
  133. },
  134. child: Container(
  135. padding: EdgeInsets.all(10.w),
  136. margin: contentPadding ?? EdgeInsets.only(top: 20.w),
  137. decoration: BoxDecoration(
  138. borderRadius: BorderRadius.circular(8.r),
  139. gradient: LinearGradient(colors: [
  140. '#F8F5FF'.color,
  141. ColorName.transparent,
  142. ])),
  143. child: ConstrainedBox(
  144. constraints: BoxConstraints(minHeight: 60.w),
  145. child: Column(
  146. crossAxisAlignment: CrossAxisAlignment.start,
  147. children: [
  148. Expanded(
  149. child: Text(
  150. bean.addr ?? '',
  151. style: TextStyle(
  152. fontSize: 12.sp,
  153. color: '#333333'.color,
  154. fontWeight: FontWeight.bold),
  155. ),
  156. ),
  157. SizedBox(height: 11.w),
  158. Row(
  159. children: [
  160. _buildStayDesc(bean.duration),
  161. SizedBox(width: 18.w),
  162. _buildLockDesc(bean.highUnlock, bean.totalUnlock),
  163. SizedBox(width: 18.w),
  164. Expanded(child: _buildNetDesc(bean.network))
  165. ],
  166. )
  167. ],
  168. ),
  169. ),
  170. ),
  171. ))
  172. ],
  173. ),
  174. ),
  175. SizedBox(height: 8.w),
  176. ],
  177. );
  178. }
  179. Widget buildErrorTrackDailyItem(TrackDailyBean bean,
  180. {EdgeInsetsGeometry? contentPadding, TrackItemClick? onItemClick}) {
  181. return Column(
  182. crossAxisAlignment: CrossAxisAlignment.start,
  183. children: [
  184. IntrinsicHeight(
  185. child: Row(
  186. children: [
  187. Column(
  188. crossAxisAlignment: CrossAxisAlignment.center,
  189. children: [
  190. _buildTimeText(bean.start),
  191. SizedBox(height: 4.w),
  192. _buildRingView(isError: true),
  193. SizedBox(height: 4.w),
  194. Expanded(
  195. child: Container(
  196. width: 1.w,
  197. decoration: BoxDecoration(
  198. color: '#F0F0F0'.color,
  199. borderRadius: BorderRadius.circular(100.r),
  200. ),
  201. ),
  202. )
  203. ],
  204. ),
  205. Expanded(
  206. child: GestureDetector(
  207. onTap: () {
  208. onItemClick?.call(bean);
  209. },
  210. child: Container(
  211. height: 50.w,
  212. padding: EdgeInsets.all(10.w),
  213. margin:
  214. contentPadding ?? EdgeInsets.only(top: 41.w, bottom: 7.w),
  215. decoration: BoxDecoration(
  216. borderRadius: BorderRadius.circular(8.r),
  217. gradient: LinearGradient(colors: [
  218. '#FFECEC'.color,
  219. ColorName.white,
  220. ])),
  221. child: Row(
  222. children: [
  223. Assets.images.iconTrackError.image(width: 19.4.w),
  224. SizedBox(width: 5.5.w),
  225. Text(StringName.trackDetailError,
  226. style: TextStyle(
  227. fontSize: 12.sp,
  228. color: '#333333'.color,
  229. fontWeight: FontWeight.bold)),
  230. SizedBox(width: 10.w),
  231. GestureDetector(
  232. onTap: () {
  233. TrackErrorTipsDialog.show();
  234. },
  235. child: Text(
  236. StringName.trackDetailSeeError,
  237. style:
  238. TextStyle(fontSize: 11.sp, color: '#4476FF'.color),
  239. ),
  240. ),
  241. Spacer(),
  242. GestureDetector(
  243. onTap: () {
  244. LocationAnalysePage.start();
  245. },
  246. child:
  247. Assets.images.imgTrackAiAnalyse.image(width: 73.w)),
  248. SizedBox(width: 6.w),
  249. ],
  250. ),
  251. ),
  252. ))
  253. ],
  254. ),
  255. ),
  256. SizedBox(height: 8.w),
  257. ],
  258. );
  259. }
  260. Widget _buildRingView({bool isError = false}) {
  261. return Container(
  262. width: 12.w,
  263. height: 12.w,
  264. decoration: BoxDecoration(
  265. shape: BoxShape.circle,
  266. border: Border.all(
  267. color: isError ? '#F24D4D'.color : '#66999999'.color,
  268. width: isError ? 2.w : 1.w,
  269. ),
  270. ),
  271. );
  272. }
  273. Widget _buildTimeText(int time) {
  274. return Text(
  275. DateUtil.fromMillisecondsSinceEpoch('HH:mm', time),
  276. style: TextStyle(
  277. fontSize: 12.sp, color: '#333333'.color, fontWeight: FontWeight.w500),
  278. );
  279. }
  280. Widget buildEndPoint(TrackDailyBean bean) {
  281. return Column(
  282. children: [
  283. SizedBox(height: 4.w),
  284. _buildRingView(),
  285. SizedBox(height: 4.w),
  286. _buildTimeText(bean.end),
  287. ],
  288. );
  289. }
  290. Widget _buildNetDesc(String? network) {
  291. bool isMobile = network == Constants.kMobileNetworkTag;
  292. return IntrinsicWidth(
  293. child: Row(
  294. children: [
  295. isMobile
  296. ? Assets.images.iconNetMobile.image(width: 14.w, height: 14.w)
  297. : Assets.images.iconNetWifi.image(width: 14.w, height: 14.w),
  298. SizedBox(width: 2.w),
  299. Expanded(
  300. child: Text(
  301. isMobile ? StringName.trackDetailMobile : network ?? '',
  302. style:
  303. TextStyle(fontSize: 11.sp, color: '#666666'.color, height: 1),
  304. ),
  305. )
  306. ],
  307. ),
  308. );
  309. }
  310. Widget _buildLockDesc(int? highUnlock, int? totalUnlock) {
  311. if ((highUnlock == null && totalUnlock == null) ||
  312. (highUnlock == 0 && totalUnlock == 0)) {
  313. return Row(
  314. children: [
  315. Assets.images.iconTrackUnlockNoPermission
  316. .image(width: 14.w, height: 14.w),
  317. SizedBox(width: 2.w),
  318. Text(StringName.trackDetailNoAuthorize,
  319. style:
  320. TextStyle(fontSize: 11.sp, color: '#919DBE'.color, height: 1))
  321. ],
  322. );
  323. } else {
  324. return Row(
  325. children: [
  326. Assets.images.iconTrackStay.image(width: 14.w, height: 14.w),
  327. SizedBox(width: 2.w),
  328. if (highUnlock != null && highUnlock == 0)
  329. Text('高频解锁$highUnlock次,共${totalUnlock ?? 0}次',
  330. style:
  331. TextStyle(fontSize: 11.sp, color: '#666666'.color, height: 1))
  332. else
  333. Text('解锁${totalUnlock ?? 0}次',
  334. style:
  335. TextStyle(fontSize: 11.sp, color: '#666666'.color, height: 1))
  336. ],
  337. );
  338. }
  339. }
  340. Widget _buildStayDesc(int duration) {
  341. return Row(
  342. children: [
  343. Assets.images.iconTrackStay.image(width: 14.w, height: 14.w),
  344. SizedBox(width: 2.w),
  345. Text(TrackUtil.formatDurationFromMillis(duration),
  346. style: TextStyle(fontSize: 11.sp, color: '#666666'.color, height: 1))
  347. ],
  348. );
  349. }