import 'dart:math'; import 'package:flutter/cupertino.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:location/data/bean/track_daily_bean.dart'; import 'package:location/data/bean/user_info.dart'; import 'package:location/data/consts/constants.dart'; import 'package:location/dialog/track_error_tips_dialog.dart'; import 'package:location/module/analyse/location_analyse_page.dart'; import 'package:location/module/track/track_util.dart'; import 'package:location/resource/assets.gen.dart'; import 'package:location/resource/colors.gen.dart'; import 'package:location/resource/string.gen.dart'; import 'package:location/utils/common_expand.dart'; import 'package:location/utils/date_util.dart'; import '../track_status.dart'; typedef TrackItemClick = void Function(TrackDailyBean bean); typedef TrackAIAnalyseClick = void Function(TrackDailyBean bean); Widget buildTrackDailyItem(TrackDailyBean bean, bool isEnd, {TrackItemClick? onItemClick, TrackAIAnalyseClick? onAIAnalyseClick}) { return Container( padding: EdgeInsets.symmetric(horizontal: 12.w), margin: EdgeInsets.only(bottom: 8.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Builder(builder: (context) { if (bean.status == TrackStatus.moving) { return _buildMovingTrackDailyItem(bean, onItemClick: onItemClick); } else if (bean.status == TrackStatus.stay) { return buildStayTrackDailyItem(bean, onItemClick: onItemClick); } else if (bean.status == TrackStatus.error) { return buildErrorTrackDailyItem(bean, onItemClick: onItemClick, onAIAnalyseClick: onAIAnalyseClick); } else { return SizedBox(height: 50.w, child: Text('未知轨迹,请更新最新应用版本')); } }), if (isEnd) buildEndPoint(bean) ], ), ); } Widget _buildMovingTrackDailyItem(TrackDailyBean bean, {TrackItemClick? onItemClick}) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ IntrinsicHeight( child: Row( children: [ Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ _buildTimeText(bean.start), SizedBox(height: 4.w), _buildRingView(), SizedBox(height: 4.w), Expanded( child: Container( width: 1.w, decoration: BoxDecoration( color: '#F0F0F0'.color, borderRadius: BorderRadius.circular(100.r), ), ), ) ], ), Expanded( child: GestureDetector( onTap: () { onItemClick?.call(bean); }, child: Container( height: 50.w, margin: EdgeInsets.only(top: 26.w), decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.r), gradient: LinearGradient(colors: [ '#F8F5FF'.color, ColorName.transparent, ])), padding: EdgeInsets.symmetric(horizontal: 14.w), child: Row( children: [ Assets.images.iconTrackMoving.image(width: 16.w), SizedBox(width: 5.w), Text( StringName.trackDetailMoving, style: TextStyle( fontSize: 12.sp, color: '#333333'.color, fontWeight: FontWeight.bold), ) ], ), ), )) ], ), ), SizedBox(height: 8.w), ], ); } Widget buildStayTrackDailyItem(TrackDailyBean bean, {EdgeInsetsGeometry? contentPadding, TrackItemClick? onItemClick}) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ IntrinsicHeight( child: Row( children: [ Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ _buildTimeText(bean.start), SizedBox(height: 4.w), _buildRingView(), SizedBox(height: 4.w), Expanded( child: Container( width: 1.w, decoration: BoxDecoration( color: '#F0F0F0'.color, borderRadius: BorderRadius.circular(100.r), ), ), ) ], ), Expanded( child: GestureDetector( onTap: () { onItemClick?.call(bean); }, child: Container( padding: EdgeInsets.all(10.w), margin: contentPadding ?? EdgeInsets.only(top: 20.w), decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.r), gradient: LinearGradient(colors: [ '#F8F5FF'.color, ColorName.transparent, ])), child: ConstrainedBox( constraints: BoxConstraints(minHeight: 60.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Text( bean.addr ?? '', style: TextStyle( fontSize: 12.sp, color: '#333333'.color, fontWeight: FontWeight.bold), ), ), SizedBox(height: 11.w), Row( children: [ _buildStayDesc(bean.duration), SizedBox(width: 18.w), _buildLockDesc(bean.highUnlock, bean.totalUnlock), SizedBox(width: 18.w), Expanded(child: _buildNetDesc(bean.network)) ], ) ], ), ), ), )) ], ), ), SizedBox(height: 8.w), ], ); } Widget buildErrorTrackDailyItem(TrackDailyBean bean, {EdgeInsetsGeometry? contentPadding, TrackItemClick? onItemClick, TrackAIAnalyseClick? onAIAnalyseClick}) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ IntrinsicHeight( child: Row( children: [ Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ _buildTimeText(bean.start), SizedBox(height: 4.w), _buildRingView(isError: true), SizedBox(height: 4.w), Expanded( child: Container( width: 1.w, decoration: BoxDecoration( color: '#F0F0F0'.color, borderRadius: BorderRadius.circular(100.r), ), ), ) ], ), Expanded( child: GestureDetector( onTap: () { onItemClick?.call(bean); }, child: Container( height: 50.w, padding: EdgeInsets.all(10.w), margin: contentPadding ?? EdgeInsets.only(top: 41.w, bottom: 7.w), decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.r), gradient: LinearGradient(colors: [ '#FFECEC'.color, ColorName.white, ])), child: Row( children: [ Assets.images.iconTrackError.image(width: 19.4.w), SizedBox(width: 5.5.w), Text(StringName.trackDetailError, style: TextStyle( fontSize: 12.sp, color: '#333333'.color, fontWeight: FontWeight.bold)), SizedBox(width: 10.w), GestureDetector( onTap: () { TrackErrorTipsDialog.show(); }, child: Text( StringName.trackDetailSeeError, style: TextStyle(fontSize: 11.sp, color: '#4476FF'.color), ), ), Spacer(), GestureDetector( onTap: () { onAIAnalyseClick?.call(bean); }, child: Assets.images.imgTrackAiAnalyse.image(width: 73.w)), SizedBox(width: 6.w), ], ), ), )) ], ), ), SizedBox(height: 8.w), ], ); } Widget _buildRingView({bool isError = false}) { return Container( width: 12.w, height: 12.w, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: isError ? '#F24D4D'.color : '#66999999'.color, width: isError ? 2.w : 1.w, ), ), ); } Widget _buildTimeText(int time) { return Text( DateUtil.fromMillisecondsSinceEpoch('HH:mm', time), style: TextStyle( fontSize: 12.sp, color: '#333333'.color, fontWeight: FontWeight.w500), ); } Widget buildEndPoint(TrackDailyBean bean) { return Column( children: [ SizedBox(height: 4.w), _buildRingView(), SizedBox(height: 4.w), _buildTimeText(bean.end), ], ); } Widget _buildNetDesc(String? network) { bool isMobile = network == Constants.kMobileNetworkTag; return IntrinsicWidth( child: Row( children: [ isMobile ? Assets.images.iconNetMobile.image(width: 14.w, height: 14.w) : Assets.images.iconNetWifi.image(width: 14.w, height: 14.w), SizedBox(width: 2.w), Expanded( child: Text( isMobile ? StringName.trackDetailMobile : network ?? '', style: TextStyle(fontSize: 11.sp, color: '#666666'.color, height: 1), ), ) ], ), ); } Widget _buildLockDesc(int? highUnlock, int? totalUnlock) { if ((highUnlock == null && totalUnlock == null) || (highUnlock == 0 && totalUnlock == 0)) { return Row( children: [ Assets.images.iconTrackUnlockNoPermission .image(width: 14.w, height: 14.w), SizedBox(width: 2.w), Text(StringName.trackDetailNoAuthorize, style: TextStyle(fontSize: 11.sp, color: '#919DBE'.color, height: 1)) ], ); } else { return Row( children: [ Assets.images.iconTrackStay.image(width: 14.w, height: 14.w), SizedBox(width: 2.w), if (highUnlock != null && highUnlock == 0) Text('高频解锁$highUnlock次,共${totalUnlock ?? 0}次', style: TextStyle(fontSize: 11.sp, color: '#666666'.color, height: 1)) else Text('解锁${totalUnlock ?? 0}次', style: TextStyle(fontSize: 11.sp, color: '#666666'.color, height: 1)) ], ); } } Widget _buildStayDesc(int duration) { return Row( children: [ Assets.images.iconTrackStay.image(width: 14.w, height: 14.w), SizedBox(width: 2.w), Text(TrackUtil.formatDurationFromMillis(duration), style: TextStyle(fontSize: 11.sp, color: '#666666'.color, height: 1)) ], ); }