track_daily_item.dart 12 KB

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