track_daily_item.dart 13 KB

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