track_day_detail_view.dart 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. import 'package:flutter/cupertino.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter/src/widgets/framework.dart';
  4. import 'package:flutter_screenutil/flutter_screenutil.dart';
  5. import 'package:get/get.dart';
  6. import 'package:get/get_core/src/get_main.dart';
  7. import 'package:location/base/base_view.dart';
  8. import 'package:location/data/bean/track_days.dart';
  9. import 'package:location/module/track/track_day_detail/time_proportion/track_time_pie_chat.dart';
  10. import 'package:location/module/track/track_day_detail/track_daily_item.dart';
  11. import 'package:location/module/track/track_day_detail/track_day_detail_controller.dart';
  12. import 'package:location/module/track/track_status.dart';
  13. import 'package:location/resource/assets.gen.dart';
  14. import 'package:location/resource/colors.gen.dart';
  15. import 'package:location/resource/string.gen.dart';
  16. import 'package:location/utils/common_expand.dart';
  17. import 'package:location/widget/rich_text_replace.dart';
  18. import 'package:visibility_detector/visibility_detector.dart';
  19. import '../../../data/bean/track_summary.dart';
  20. import '../../../widget/drop_cap_text.dart';
  21. import '../../../widget/gradually_print_text.dart';
  22. class TrackDayDetailView extends BaseView<TrackDayDetailController> {
  23. late final String trackTag;
  24. TrackDayDetailView(TrackDays days, {super.key, bool isExpand = false}) {
  25. trackTag = 'TrackDayDetailView_${days.day}';
  26. Get.lazyPut(() => TrackDayDetailController(days, isExpand),
  27. tag: trackTag, fenix: true);
  28. }
  29. @override
  30. TrackDayDetailController get controller =>
  31. Get.find<TrackDayDetailController>(tag: trackTag);
  32. @override
  33. Widget buildBody(BuildContext context) {
  34. return Obx(() {
  35. return Visibility(
  36. visible: controller.isRequested,
  37. child: _buildTrackDetailView(),
  38. );
  39. });
  40. }
  41. Widget _buildTrackDetailView() {
  42. return Obx(() {
  43. if (controller.trackNoData) {
  44. return _buildTrackNoData();
  45. }
  46. return _buildTrackListView();
  47. });
  48. }
  49. Widget _buildTrackListView() {
  50. return Stack(
  51. children: [
  52. CustomScrollView(
  53. slivers: [
  54. buildSliverHistoryTrack(),
  55. SliverToBoxAdapter(
  56. child: Container(
  57. height: 8.w,
  58. color: '#F8F5FF'.color,
  59. )),
  60. SliverToBoxAdapter(
  61. child: buildProportionDurationView(),
  62. ),
  63. SliverToBoxAdapter(
  64. child: buildTrackDailySummaryView(),
  65. ),
  66. SliverToBoxAdapter(
  67. child: buildTrackExtraBottomView(),
  68. ),
  69. SliverToBoxAdapter(
  70. child: Container(
  71. height: 80.w,
  72. color: '#F8F5FF'.color,
  73. )),
  74. ],
  75. ),
  76. _buildFoldBtn(),
  77. ],
  78. );
  79. }
  80. Widget buildTrackExtraBottomView() {
  81. return Obx(() {
  82. return Container(
  83. height: controller.trackBottomHeight,
  84. color: '#F8F5FF'.color,
  85. );
  86. });
  87. }
  88. Widget buildTrackDailySummaryView() {
  89. return Column(
  90. children: [
  91. buildDailySummaryTitle(),
  92. SizedBox(height: 8.w),
  93. Obx(() {
  94. return _buildSituationItem(StringName.trackDailySummaryPhone,
  95. controller.trackDailySummary?.phoneSituation,
  96. isShowDivider: controller.trackDailySummary?.stayLongest != null);
  97. }),
  98. Obx(() {
  99. return _buildSituationItem(StringName.trackDailySummaryStay,
  100. controller.trackDailySummary?.stayLongest,
  101. isShowDivider:
  102. controller.trackDailySummary?.trackSituation?.isNotEmpty ==
  103. true);
  104. }),
  105. //轨迹情况
  106. Obx(() {
  107. return _buildDailyTrack(
  108. controller.trackDailySummary?.showTrackSituation,
  109. controller.trackDailySummary?.trackSituation);
  110. }),
  111. SizedBox(height: 10.w)
  112. ],
  113. );
  114. }
  115. Widget _buildDailyTrack(bool? isShow, String? trackSituation) {
  116. if (isShow == false) {
  117. return SizedBox.shrink();
  118. }
  119. if (trackSituation != null && trackSituation.isNotEmpty) {
  120. return _buildDailyDoneSituationView(trackSituation);
  121. }
  122. return _buildDailyTrackPrintingView();
  123. }
  124. Widget _buildDailyDoneSituationView(String trackSituation) {
  125. return Container(
  126. width: double.infinity,
  127. padding: EdgeInsets.symmetric(horizontal: 22.w),
  128. child: Column(
  129. crossAxisAlignment: CrossAxisAlignment.start,
  130. children: [
  131. Text(StringName.trackDailySummarytrack,
  132. style: TextStyle(
  133. fontSize: 13.sp,
  134. color: '#333333'.color,
  135. fontWeight: FontWeight.bold)),
  136. SizedBox(height: 8.w),
  137. Obx(() {
  138. if (controller.trackController.userInfo?.isMine == true) {
  139. return Text(
  140. trackSituation,
  141. style: TextStyle(fontSize: 11.sp, color: '#666666'.color),
  142. );
  143. }
  144. return DropCapText(
  145. style: TextStyle(fontSize: 11.sp, color: '#666666'.color),
  146. trackSituation,
  147. dropCapPosition: DropCapPosition.bottomRight,
  148. textAlign: TextAlign.justify,
  149. dropCap: DropCap(
  150. width: 75.w,
  151. height: 36.w,
  152. child: Align(
  153. alignment: Alignment.bottomRight,
  154. child: GestureDetector(
  155. onTap: controller.onPhoneCallClick,
  156. child: Column(
  157. crossAxisAlignment: CrossAxisAlignment.center,
  158. mainAxisAlignment: MainAxisAlignment.end,
  159. children: [
  160. Assets.images.iconCallPhone
  161. .image(width: 15.w, height: 15.w),
  162. Text(
  163. StringName.trackDailyCallPhone,
  164. style: TextStyle(
  165. fontSize: 10.sp,
  166. color: ColorName.colorPrimary,
  167. fontWeight: FontWeight.bold),
  168. )
  169. ],
  170. ),
  171. ),
  172. )),
  173. );
  174. }),
  175. SizedBox(height: 12.w),
  176. ],
  177. ),
  178. );
  179. }
  180. Widget _buildDailyTrackPrintingView() {
  181. return VisibilityDetector(
  182. key: Key('track-summary-print'),
  183. onVisibilityChanged: (VisibilityInfo info) {
  184. final visibleFraction = info.visibleFraction;
  185. controller.checkGraduallyPrintTextVisible(visibleFraction);
  186. },
  187. child: Container(
  188. width: double.infinity,
  189. padding: EdgeInsets.symmetric(horizontal: 22.w),
  190. child: Column(
  191. crossAxisAlignment: CrossAxisAlignment.start,
  192. children: [
  193. Text(StringName.trackDailySummarytrack,
  194. style: TextStyle(
  195. fontSize: 13.sp,
  196. color: '#333333'.color,
  197. fontWeight: FontWeight.bold)),
  198. SizedBox(height: 8.w),
  199. Obx(() {
  200. if (controller.summaryError?.isNotEmpty == true) {
  201. return Text(controller.summaryError!,
  202. style: TextStyle(fontSize: 11.sp, color: '#FF0000'.color));
  203. } else {
  204. return GraduallyPrintText(
  205. graduallyController: controller.graduallyController,
  206. textStyle: TextStyle(fontSize: 11.sp, color: '#666666'.color),
  207. );
  208. }
  209. }),
  210. SizedBox(height: 12.w),
  211. ],
  212. ),
  213. ),
  214. );
  215. }
  216. Widget buildDailySummaryTitle() {
  217. return Row(
  218. children: [
  219. SizedBox(width: 22.w),
  220. Assets.images.iconTrackDailySummary.image(width: 20.w),
  221. SizedBox(width: 5.w),
  222. Text(StringName.trackDetailDailySummary,
  223. style: TextStyle(
  224. fontWeight: FontWeight.bold,
  225. fontSize: 14.sp,
  226. color: '#333333'.color)),
  227. Spacer(),
  228. GestureDetector(
  229. onTap: controller.onShareClick,
  230. child: Container(
  231. padding: EdgeInsets.symmetric(horizontal: 5.w, vertical: 12.w),
  232. child: Row(
  233. children: [
  234. Text(StringName.trackDetailDailySummaryShare,
  235. style: TextStyle(fontSize: 12.sp, color: '#666666'.color)),
  236. Assets.images.iconTrackDailySummaryArrow.image(height: 11.w)
  237. ],
  238. ),
  239. ),
  240. ),
  241. SizedBox(width: 10.w),
  242. ],
  243. );
  244. }
  245. Widget _buildSituationItem(String title, TrackSummary? summary,
  246. {bool isShowDivider = true}) {
  247. if (summary == null) {
  248. return SizedBox.shrink();
  249. }
  250. return Container(
  251. width: double.infinity,
  252. padding: EdgeInsets.symmetric(horizontal: 22.w),
  253. child: Column(
  254. crossAxisAlignment: CrossAxisAlignment.start,
  255. children: [
  256. Text(title,
  257. style: TextStyle(
  258. fontSize: 13.sp,
  259. color: '#333333'.color,
  260. fontWeight: FontWeight.bold)),
  261. SizedBox(height: 8.w),
  262. RichTextReplace(
  263. text: summary.text,
  264. items: summary.items,
  265. defaultStyle: TextStyle(fontSize: 11.sp, color: '#666666'.color),
  266. replacedStyle: TextStyle(
  267. fontWeight: FontWeight.bold,
  268. fontSize: 11.sp,
  269. color: '#333333'.color)),
  270. SizedBox(height: 12.w),
  271. Visibility(
  272. visible: isShowDivider,
  273. child: Container(
  274. width: double.infinity,
  275. height: 1.w,
  276. color: '#EEEEEE'.color,
  277. ),
  278. ),
  279. Visibility(visible: isShowDivider, child: SizedBox(height: 10.w)),
  280. ],
  281. ),
  282. );
  283. }
  284. Widget _buildFoldContentView() {
  285. return Obx(() {
  286. return Column(
  287. crossAxisAlignment: CrossAxisAlignment.start,
  288. children: [
  289. Builder(builder: (context) {
  290. if (controller.expandSituation != null) {
  291. if (controller.expandSituation!.first == TrackExpandType.error ||
  292. controller.expandSituation!.first ==
  293. TrackExpandType.errorNow) {
  294. return buildErrorTrackDailyItem(
  295. controller.expandSituation!.second,
  296. contentPadding: EdgeInsets.only(top: 46.w, bottom: 12.w),
  297. onItemClick: controller.onHistoryTrackItemClick,
  298. onAIAnalyseClick: controller.onAIAnalyseClick);
  299. } else {
  300. return buildStayTrackDailyItem(
  301. controller.expandSituation!.second,
  302. contentPadding: EdgeInsets.only(top: 35.w),
  303. onItemClick: controller.onHistoryTrackItemClick);
  304. }
  305. } else {
  306. return SizedBox.shrink();
  307. }
  308. }),
  309. if (controller.expandSituation != null &&
  310. (controller.expandSituation?.first == TrackExpandType.error ||
  311. controller.expandSituation?.first == TrackExpandType.stay))
  312. buildEndPoint(controller.expandSituation!.second)
  313. ],
  314. );
  315. });
  316. }
  317. Widget _buildTrackNoData() {
  318. return Column(
  319. children: [
  320. SizedBox(height: 0.048.sh),
  321. Assets.images.imgTrackNoData.image(width: 78.5.w),
  322. SizedBox(height: 7.w),
  323. Text(StringName.trackDetailNoData,
  324. style: TextStyle(fontSize: 11.sp, color: ColorName.black60))
  325. ],
  326. );
  327. }
  328. Widget _buildFoldBtn() {
  329. return Obx(() {
  330. return Visibility(
  331. visible: !controller.trackNoData && !controller.isHideExpand,
  332. child: Positioned(
  333. top: 2.w,
  334. right: 5.w,
  335. child: GestureDetector(
  336. behavior: HitTestBehavior.translucent,
  337. onTap: controller.onTrackDetailFoldClick,
  338. child: Container(
  339. padding: EdgeInsets.symmetric(horizontal: 5.w, vertical: 8.w),
  340. child: Obx(() {
  341. return Row(
  342. crossAxisAlignment: controller.isExpanded
  343. ? CrossAxisAlignment.end
  344. : CrossAxisAlignment.center,
  345. children: [
  346. Text(
  347. controller.isExpanded
  348. ? StringName.trackDetailFold
  349. : StringName.trackDetailExpand,
  350. style: TextStyle(fontSize: 10.sp, color: '#666666'.color),
  351. ),
  352. SizedBox(width: 1.w),
  353. Transform.rotate(
  354. angle: controller.isExpanded ? 3.1416 : 0,
  355. child: Assets.images.iconTrackDetailTimeBaseArrow
  356. .image(width: 10.w, height: 10.w),
  357. )
  358. ],
  359. );
  360. }),
  361. ),
  362. ),
  363. ),
  364. );
  365. });
  366. }
  367. Widget buildProportionDurationView() {
  368. return Column(
  369. children: [
  370. Container(
  371. width: double.infinity,
  372. height: 293.w,
  373. padding: EdgeInsets.all(12.w),
  374. child: Stack(
  375. children: [
  376. Text(StringName.trackDetailTimeProportion,
  377. style: TextStyle(
  378. fontSize: 13.sp,
  379. color: '#333333'.color,
  380. fontWeight: FontWeight.bold)),
  381. _buildPieChatView()
  382. ],
  383. ),
  384. ),
  385. Container(
  386. height: 8.w,
  387. width: double.infinity,
  388. color: '#F8F5FF'.color,
  389. )
  390. ],
  391. );
  392. }
  393. Widget _buildPieChatView() {
  394. return Obx(() {
  395. if (controller.pieChatData.isEmpty) {
  396. return SizedBox.shrink();
  397. }
  398. return Align(
  399. alignment: Alignment.center,
  400. child: TrackTimePieChat(pieData: controller.pieChatData));
  401. });
  402. }
  403. Widget buildSliverHistoryTrack() {
  404. return Obx(() {
  405. if (controller.isExpanded) {
  406. return SliverPadding(
  407. padding: EdgeInsets.only(top: 20.w, bottom: 12.w),
  408. sliver: SliverList.builder(
  409. itemBuilder: buildHistoryTrackItem,
  410. itemCount: controller.trackDailyList.length),
  411. );
  412. } else {
  413. return SliverPadding(
  414. padding: EdgeInsets.only(
  415. top: 20.w, bottom: 12.w, left: 12.w, right: 12.w),
  416. sliver: SliverToBoxAdapter(
  417. child: _buildFoldContentView(),
  418. ));
  419. }
  420. });
  421. }
  422. Widget buildHistoryTrackItem(BuildContext context, int index) {
  423. return buildTrackDailyItem(controller.trackDailyList[index],
  424. index == controller.trackDailyList.length - 1,
  425. onItemClick: controller.onHistoryTrackItemClick,
  426. onAIAnalyseClick: controller.onAIAnalyseClick);
  427. }
  428. }