123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912 |
- import 'dart:ui';
- import 'package:flutter/material.dart';
- import 'package:flutter/material.dart' as ui;
- import 'package:flutter/painting.dart';
- import 'package:sport/bean/jog/record.dart';
- import 'package:sport/bean/sport_index.dart';
- import 'package:sport/pages/home/consume_page.dart';
- import 'package:sport/pages/home/plan_page.dart';
- import 'package:sport/pages/run/run_detail_page.dart';
- import 'package:sport/pages/run/run_share_statistics.dart';
- import 'package:sport/provider/lib/provider_widget.dart';
- import 'package:sport/provider/lib/simple_model.dart';
- import 'package:sport/provider/lib/view_state_lifecycle.dart';
- import 'package:sport/router/navigator_util.dart';
- import 'package:sport/services/api/inject_api.dart';
- import 'package:sport/services/api/resp.dart';
- import 'package:sport/utils/DateFormat.dart';
- import 'package:sport/utils/date.dart';
- import 'package:sport/utils/sport_utils.dart';
- import 'package:sport/utils/toast.dart';
- import 'package:sport/widgets/appbar.dart';
- import 'package:sport/widgets/chart.dart';
- import 'package:sport/widgets/dialog/popupmenu.dart' as menu;
- import 'package:sport/widgets/dialog/request_dialog.dart';
- import 'package:sport/widgets/image.dart';
- import 'package:sport/widgets/loading.dart';
- import 'package:sport/widgets/misc.dart';
- import 'package:sport/widgets/popmenu_bg.dart';
- const Color _color = Color(0xffFFC400);
- const List<String> TABS = ["日", "周", "月", "年", "总"];
- class RunStatisticsPage extends StatefulWidget {
- @override
- State<StatefulWidget> createState() => _PageState();
- }
- class _PageState extends State<RunStatisticsPage> with TickerProviderStateMixin, InjectApi, InjectLoginApi {
- ValueNotifier<String> _tab = ValueNotifier<String>("周");
- ValueNotifier<JogRecord?> _valueNotifierSportDetail = ValueNotifier(null);
- ValueNotifier<DateTime> _valueNotifierDate = ValueNotifier(DateTime.now());
- late PageController _pageController;
- @override
- void initState() {
- super.initState();
- _pageController = PageController(initialPage: 0);
- changeTab();
- }
- @override
- void dispose() {
- _pageController.dispose();
- super.dispose();
- _tab.dispose();
- _valueNotifierSportDetail.dispose();
- _valueNotifierDate.dispose();
- }
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- backgroundColor: Colors.white,
- appBar: buildAppBar(context, title: "跑步统计", actions: [
- IconButton(icon: Image.asset("lib/assets/img/bbs_icon_share.png"), onPressed: () => _share()),
- ]),
- body: Container(
- color: Colors.white,
- child: ValueListenableBuilder(
- valueListenable: _tab,
- builder: (BuildContext context, String value, Widget? child) {
- return Column(
- children: <Widget>[
- Padding(
- padding: const EdgeInsets.all(8.0),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: ["周", "/", "月", "/", "年", "/", "总"]
- .map((e) => e == "/"
- ? Container(
- margin: const EdgeInsets.fromLTRB(5, 0, 1, 0),
- color: const Color(0xffdcdcdc),
- width: 0.5,
- height: 14,
- transform: Matrix4.rotationZ(0.35),
- )
- : InkWell(
- onTap: () {
- _tab.value = e;
- _valueNotifierDate.value = DateTime.now();
- _pageController.jumpToPage(0);
- // _pageController= PageController(initialPage: 0);
- changeTab();
- },
- child: Container(
- margin: EdgeInsets.symmetric(horizontal: 12.0),
- padding: EdgeInsets.all(8.0),
- decoration: value == e ? BoxDecoration(color: _color, shape: BoxShape.circle) : null,
- child: Text(
- "$e",
- style: value == e
- ? Theme.of(context).textTheme.subtitle1!.copyWith(color: Colors.white)
- : Theme.of(context).textTheme.subtitle1!,
- ),
- )))
- .toList(),
- ),
- ),
- if (toType() != 4)
- Center(
- child: ValueListenableBuilder<DateTime>(
- valueListenable: _valueNotifierDate,
- builder: (_, time, ___) {
- int type = toType();
- String text = "";
- if (type == 0) {
- text = "${time.year}.${'${time.month}'.padLeft(2, '0')}.${'${time.day}'.padLeft(2, '0')} 6:00 - 24:00 ";
- } else if (type == 1) {
- DateTime start = DateTime(time.year, time.month, time.day - time.weekday + 1);
- DateTime end = DateTime(time.year, time.month, time.day + 6 - time.weekday + 1);
- print("$time ${time.weekday} == $start $end");
- text =
- "${start.year}.${'${start.month}'.padLeft(2, '0')}.${'${start.day}'.padLeft(2, '0')} 至 ${end.year}.${'${end.month}'.padLeft(2, '0')}.${'${end.day}'.padLeft(2, '0')}";
- } else if (type == 2) {
- text = ("${time.year}年${'${time.month}'.padLeft(2, '0')}月");
- } else if (type == 3) {
- text = ("${time.year}年");
- }
- return Row(
- mainAxisSize: MainAxisSize.min,
- children: <Widget>[
- GestureDetector(
- behavior: HitTestBehavior.opaque,
- onTap: () {
- _pageController.nextPage(duration: Duration(milliseconds: 500), curve: Curves.linear);
- },
- child: Padding(
- padding: const EdgeInsets.all(18.0),
- child: arrowLeft(),
- ),
- ),
- Text(
- text,
- style: Theme.of(context).textTheme.bodyText2!.copyWith(color: Color(0xff333333)),
- strutStyle: fixedLine,
- ),
- GestureDetector(
- behavior: HitTestBehavior.opaque,
- onTap: () {
- if (_pageController.page == 0.0) {
- ToastUtil.show("没有数据了");
- return;
- }
- _pageController.previousPage(duration: Duration(milliseconds: 500), curve: Curves.linear);
- },
- child: Padding(
- padding: const EdgeInsets.all(18.0),
- child: arrowRight(),
- ),
- ),
- ],
- );
- }),
- ),
- Expanded(
- child: Center(
- child: PageView.builder(
- key: ValueKey("${toType()}"),
- reverse: true,
- itemCount: toType() != 4 ? 10240 : 1,
- controller: _pageController,
- onPageChanged: (page) {
- rollDate(-page);
- },
- itemBuilder: (context, index) {
- int type = toType();
- DateTime time = offsetDate(type, -index);
- return _PageChild(type: type, time: time, future: createFuture(time));
- },
- ),
- ),
- ),
- ],
- );
- },
- ),
- ));
- }
- int toType() {
- return TABS.indexOf(_tab.value);
- }
- void changeTab() async {
- _valueNotifierSportDetail.value = null;
- try {
- RespData<JogRecord> data = await createFuture(_valueNotifierDate.value);
- _valueNotifierSportDetail.value = data.data;
- } catch (e) {
- print(e);
- }
- }
- Future<RespData<JogRecord>> createQueryFuture(int offset) {
- int type = toType();
- DateTime next = offsetDate(type, offset);
- return createFuture(next);
- }
- Future<RespData<JogRecord>> createFuture(DateTime time) {
- int type = toType();
- Future<RespData<JogRecord>> data;
- switch (type) {
- case 1:
- DateTime start = DateTime(time.year, time.month, time.day - time.weekday + 1);
- DateTime end = DateTime(time.year, time.month, time.day + 6 - time.weekday + 1);
- data = api.jogListByDay('${start.year}-${'${start.month}'.padLeft(2, '0')}-${'${start.day}'.padLeft(2, '0')}',
- '${end.year}-${'${end.month}'.padLeft(2, '0')}-${'${end.day}'.padLeft(2, '0')}');
- break;
- case 2:
- DateTime start = DateTime(time.year, time.month, 1);
- DateTime end = DateTime(time.year, time.month + 1, 0);
- data = api.jogListByDay('${start.year}-${'${start.month}'.padLeft(2, '0')}-${'${start.day}'.padLeft(2, '0')}',
- '${end.year}-${'${end.month}'.padLeft(2, '0')}-${'${end.day}'.padLeft(2, '0')}');
- break;
- case 3:
- data = api.jogListByMonth(time.year);
- break;
- case 4:
- data = api.jogListByYear();
- break;
- default:
- data = api.jogListByDay('${time.year}-${'${time.month}'.padLeft(2, '0')}-${'${time.day}'.padLeft(2, '0')}',
- '${time.year}-${'${time.month}'.padLeft(2, '0')}-${'${time.day}'.padLeft(2, '0')}');
- break;
- }
- return data;
- }
- void rollDate(int offset) {
- if (_valueNotifierSportDetail.value == null) return;
- int type = toType();
- DateTime next = offsetDate(type, offset);
- _valueNotifierDate.value = next;
- changeTab();
- }
- _share() async {
- int type = toType();
- int index = _pageController.page?.toInt() ?? 0;
- DateTime time = offsetDate(type, -index);
- JogRecord? jogRecord = await request(context, () async {
- RespData<JogRecord> resp = await createFuture(time);
- if (resp.code == 0) return resp.data;
- return null;
- });
- if (jogRecord == null) return;
- NavigatorUtil.goPage(context, (context) => RunShareStatistics(record: jogRecord, type: type, time: time));
- }
- }
- class _PageChild extends StatefulWidget {
- final int type;
- final DateTime time;
- final Future<RespData<JogRecord>> future;
- const _PageChild({Key? key, required this.type, required this.time, required this.future}) : super(key: key);
- @override
- State<StatefulWidget> createState() {
- return _PageChildState();
- }
- }
- class _PageChildState extends ViewStateLifecycle<_PageChild, SimpleModel> {
- var contentPadding = const EdgeInsets.symmetric(horizontal: 0.0);
- var flexLeft = 7;
- var flexRight = 3;
- var _labelTextStyle = const TextStyle(fontSize: 16.0, color: Color(0xff333333));
- JogRecord? jogRecord;
- double _dx =0;
- double _dy = 0;
- @override
- SimpleModel createModel() => SimpleModel((page) async {
- RespData<JogRecord> resp = await widget.future;
- jogRecord = resp.data;
- return [];
- });
- int toType() {
- return widget.type;
- }
- String toKm(double km) {
- if (km > 20 && km < 25) {
- return "半程马拉松";
- } else if (km > 40 && km < 43) {
- return "全程马拉松";
- }
- return "${km.toInt()}公里";
- }
- Widget _label(String text, {Widget? right}) {
- return Container(
- color: Color(0xffF1F1F1),
- padding: EdgeInsets.only(left: 13.0),
- margin: EdgeInsets.only(top: 10.0, bottom: 6.0),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Text(
- "$text",
- style: Theme.of(context).textTheme.bodyText2!,
- strutStyle: fixedLine,
- ),
- if (right != null) right,
- ],
- ),
- width: double.infinity,
- height: 25.0,
- );
- }
- Widget _row(BuildContext context, String label, String text, String unit, {Color? color}) {
- return Padding(
- padding: const EdgeInsets.symmetric(horizontal: 11.0),
- child: Row(
- children: [
- Expanded(
- child: Text('$label', style: _labelTextStyle),
- flex: flexLeft,
- ),
- Expanded(
- child: RichText(
- text: TextSpan(style: DefaultTextStyle.of(context).style, children: <InlineSpan>[
- TextSpan(
- text: '$text',
- style: color == null
- ? Theme.of(context).textTheme.headline1!.copyWith(
- fontSize: 20.0,
- fontFamily: "DIN",
- )
- : Theme.of(context).textTheme.subtitle1!.copyWith(fontSize: 15.0, fontFamily: "DIN", color: color)),
- WidgetSpan(
- alignment: PlaceholderAlignment.middle,
- child: Text(' $unit',
- style: Theme.of(context).textTheme.subtitle1!.copyWith(
- fontSize: 12.0,
- )),
- ),
- ]),
- ),
- flex: flexRight,
- ),
- ],
- ),
- );
- }
- @override
- Widget build(BuildContext context) {
- String sportType = widget.type == 1 ? "周" : "周均";
- sportType = "周均";
- DateTime next = offsetDateNext(widget.time, widget.type, 1);
- int day = next.difference(widget.time).inDays;
- return ProviderWidget<SimpleModel>(
- model: model,
- onModelReady: (model) => model.initData(),
- builder: (_, model, __) {
- JogRecord? _value = jogRecord;
- if (_value == null) {
- return RequestLoadingWidget();
- }
- List<double> items = [1, 3, 5, 10, 15, 20, 21.09, 25, 30, 35, 40, 42.19];
- int best = _value.best?.kmDurationList?.length ?? 0;
- List<double> bestFilled = (best < 3 ? items.skip(best).take(3 - best) : items.skip(best).take(1)).toList();
- var _divider = const Divider(
- height: 32,
- );
- var _vDivider = Container(
- height: 42.0,
- width: .5,
- color: const Color(0xffDCDCDC),
- );
- return SingleChildScrollView(
- child: Column(
- children: <Widget>[
- SizedBox(
- height: 10.0,
- ),
- Text(
- "${((_value.sum?.distance ?? 0) / 1000).toStringAsFixed(2)}",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 34.0, color: _color, fontFamily: "DIN"),
- ),
- Text(
- "总里程 (公里)",
- style: Theme.of(context).textTheme.subtitle2!.copyWith(color: Color(0xff333333)),
- ),
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 30.0, vertical: 30.0),
- child: Column(
- children: [
- Row(
- children: [
- Expanded(
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- Text(
- "${DateFormat.toTime(_value.sum?.duration ?? 0)}",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 22.0, fontFamily: "DIN"),
- ),
- Text(
- "总时长",
- style: Theme.of(context).textTheme.bodyText1!,
- ),
- ],
- ),
- ),
- _vDivider,
- Expanded(
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- Text(
- "${SportUtils.pace11(SportUtils.calPace(_value.sum?.kmDurationAvg ?? 0, 1))}",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 22.0, fontFamily: "DIN"),
- ),
- Text(
- "′",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 22.0),
- ),
- Text(
- "${SportUtils.pace12(SportUtils.calPace(_value.sum?.kmDurationAvg ?? 0, 1))}",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 22.0, fontFamily: "DIN"),
- ),
- Text(
- "″",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 22.0),
- ),
- ],
- ),
- Text(
- "配速(每公里用时)",
- style: Theme.of(context).textTheme.bodyText1!,
- ),
- ],
- ),
- ),
- ],
- ),
- Row(
- children: [
- Expanded(
- child: Divider(
- indent: 40,
- endIndent: 40,
- height: 40,
- )),
- Expanded(
- child: Divider(
- indent: 40,
- endIndent: 40,
- height: 40,
- )),
- ],
- ),
- Row(
- children: [
- Expanded(
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- Text(
- "${_value.sum?.times ?? 0}",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 22.0, fontFamily: "DIN"),
- ),
- Text(
- "运动次数(次)",
- style: Theme.of(context).textTheme.bodyText1!,
- ),
- ],
- ),
- ),
- _vDivider,
- Expanded(
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- Text(
- "${_value.sum?.consume ?? 0}",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 22.0, fontFamily: "DIN"),
- ),
- Text(
- "总消耗(大卡)",
- style: Theme.of(context).textTheme.bodyText1!,
- ),
- ],
- ),
- ),
- ],
- ),
- ],
- ),
- ),
- GestureDetector(
- onTapDown: (details){
- // print("${details.globalPosition.dx}");
- // print("${details.globalPosition.dy}");
- // print("${details.localPosition.dx}");
- // print("${details.localPosition.dy}");
- setState(() {
- _dx = details.localPosition.dx;
- _dy= details.localPosition.dy;
- });
- },
- child: CustomPaint(
- painter: Chart(
- type: widget.type,
- decimal: 2,
- dx: _dx,
- dy: _dy,
- records: _value.records
- ?.map((e) => ChartItem(
- widget.type == 4
- ? "${e.year}"
- : widget.type == 3
- ? "${e.month}"
- : e.createdAt ?? "",
- (e.distance ?? 0) / 1000))
- .toList() ??
- [],
- dateTime: widget.time,
- drawMax: true,
- unit: "km")
- ..initData(valueSplit: 5, valueSize: 5),
- child: Container(
- height: 200,
- ),
- ),
- ),
- if (widget.type != 4)
- _label("$sportType运动量",
- right: PopupMenuTheme(
- data: PopupMenuThemeData(
- color: Colors.black.withOpacity(.5),
- shape: PopmenuShape(backgroundColor: Colors.black.withOpacity(.5), borderRadius: BorderRadius.all(Radius.circular(10.0)))),
- child: PopupMenuButton(
- padding: EdgeInsets.symmetric(horizontal: 17.0),
- offset: Offset(0, kToolbarHeight / 2 + 5),
- icon: ui.Image.asset("lib/assets/img/linkpop_icon_modify_1.png"),
- onSelected: (val) {},
- itemBuilder: (context) {
- return [
- menu.PopupMenuItem(
- value: "",
- child: Center(
- child: Padding(
- padding: const EdgeInsets.all(12.0),
- child: Text(
- "周运动量:世界卫生组织WHO建议,成年人每周应进行最少150分钟的中等强度运动或75分钟的高强度运动,可以实现延长寿命的好处。 \n\n运动次数和时长:权威医学杂志《柳叶刀》的研究表明,每次锻炼的最佳时长在45-60分钟之间,少于45分钟效果会减弱,大于60分钟不仅没有更高收益,还容易产生负效应。 每周3--5次。",
- style: Theme.of(context).textTheme.subtitle1!.copyWith(color: Colors.white),
- ),
- )),
- ),
- ];
- },
- ))),
- if (widget.type != 4)
- Padding(
- padding: const EdgeInsets.all(12.0),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: <Widget>[
- GestureDetector(
- behavior: HitTestBehavior.opaque,
- onTap: () => NavigatorUtil.goPage(
- context,
- (context) => PlanPage(
- index: 1,
- )),
- child:
- _row(context, '$sportType强度', '${strengthMetToLabel(_value.avg?.met ?? 0)}', '(${(_value.avg?.met ?? 0).toStringAsFixed(1)}MET)',
- color: Theme.of(context).accentColor), ),
- _divider,
- _row(context, '$sportType时长', '${_value.avg?.durationMin}', '分钟'),
- _divider,
- GestureDetector(
- behavior: HitTestBehavior.opaque,
- onTap: () => NavigatorUtil.goPage(context, (context) => ConsumePage()),
- child: _row(context, '$sportType消耗', '${_value.avg?.consume}', '大卡')),
- ],
- ),
- ),
- _label("运动数据"),
- Padding(
- padding: const EdgeInsets.all(12.0),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: <Widget>[
- _row(context, '平均时速', "${_value.sum?.speed.toStringAsFixed(2)}", '公里/小时'),
- _divider,
- _row(context, '平均步频', "${_value.sum?.stepRateAvg ?? 0}", '步/分钟'),
- _divider,
- _row(context, '平均步幅', "${((_value.sum?.stepDistanceAvg ?? 0) * 100).toInt()}", '厘米'),
- ],
- ),
- ),
- _label("${TABS[toType()]}最佳"),
- Padding(
- padding: const EdgeInsets.all(12.0),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- if (_value.best?.distance != null)
- GestureDetector(
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 11.0),
- child: Row(
- children: [
- Expanded(
- child: Column(
- children: [
- Text('最远距离', style: _labelTextStyle),
- const SizedBox(
- height: 4.0,
- ),
- Text(
- _value.best?.distance?.createdAt?.isNotEmpty == true
- ? '${_value.best?.distance?.createdAt?.substring(0, _value.best?.distance?.createdAt?.indexOf(" ") ?? 0)}'
- : '',
- style: Theme.of(context).textTheme.bodyText1!),
- ],
- crossAxisAlignment: CrossAxisAlignment.start,
- ),
- flex: flexLeft,
- ),
- Expanded(
- child: Row(
- children: [
- Expanded(
- child: RichText(
- text: TextSpan(style: DefaultTextStyle.of(context).style, children: <InlineSpan>[
- TextSpan(
- text: '${((_value.best?.distance?.value ?? 0) / 1000).toStringAsFixed(2)}',
- style: Theme.of(context).textTheme.headline1!.copyWith(
- fontSize: 20.0,
- fontFamily: "DIN",
- )),
- WidgetSpan(
- alignment: PlaceholderAlignment.middle,
- child: Text(' 公里',
- style: Theme.of(context).textTheme.subtitle1!.copyWith(
- fontSize: 12.0,
- )),
- ),
- ]),
- ),
- ),
- arrowRight5()
- ],
- ),
- flex: flexRight,
- ),
- ],
- ),
- ),
- onTap: () {
- int id = _value.best?.distance?.id ?? 0;
- if (id != 0) {
- NavigatorUtil.goPage(
- context,
- (context) => RunDetailPage(
- id: id,
- ));
- } else {
- ToastUtil.show("暂无运动记录");
- }
- },
- behavior: HitTestBehavior.opaque,
- ),
- _divider,
- if (_value.best?.duration != null)
- GestureDetector(
- onTap: () {
- int id = _value.best?.duration?.id ?? 0;
- if (id != 0) {
- NavigatorUtil.goPage(
- context,
- (context) => RunDetailPage(
- id: id,
- ));
- } else {
- ToastUtil.show("暂无运动记录");
- }
- },
- behavior: HitTestBehavior.opaque,
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 11.0),
- child: Row(
- children: [
- Expanded(
- child: Column(
- children: [
- Text('最长时间', style: _labelTextStyle),
- const SizedBox(
- height: 4.0,
- ),
- Text(
- _value.best?.duration?.createdAt?.isNotEmpty == true
- ? '${_value.best?.duration?.createdAt?.substring(0, _value.best?.duration?.createdAt?.indexOf(" ") ?? 0)}'
- : "",
- style: Theme.of(context).textTheme.bodyText1!),
- ],
- crossAxisAlignment: CrossAxisAlignment.start,
- ),
- flex: flexLeft,
- ),
- Expanded(
- child: Row(
- children: [
- Expanded(
- child: Text("${DateFormat.toTime(_value.best?.duration?.value ?? 0)}",
- style: Theme.of(context).textTheme.headline1!.copyWith(
- fontSize: 20.0,
- fontFamily: "DIN",
- ))),
- arrowRight5()
- ],
- ),
- flex: flexRight,
- ),
- ],
- ),
- ),
- ),
- _divider,
- if (_value.best?.kmDuration != null)
- GestureDetector(
- onTap: () {
- int id = _value.best?.kmDuration?.id ?? 0;
- if (id != 0) {
- NavigatorUtil.goPage(
- context,
- (context) => RunDetailPage(
- id: id,
- ));
- } else {
- ToastUtil.show("暂无运动记录");
- }
- },
- behavior: HitTestBehavior.opaque,
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 11.0),
- child: Row(
- children: [
- Expanded(
- child: Column(
- children: [
- Text('最快配速', style: _labelTextStyle),
- const SizedBox(
- height: 4.0,
- ),
- Text(
- _value.best?.kmDuration?.createdAt?.isNotEmpty == true
- ? '${_value.best?.kmDuration?.createdAt?.substring(0, _value.best?.kmDuration?.createdAt?.indexOf(" ") ?? 0)}'
- : "",
- style: Theme.of(context).textTheme.bodyText1!),
- ],
- crossAxisAlignment: CrossAxisAlignment.start,
- ),
- flex: flexLeft,
- ),
- Expanded(
- child: Row(
- children: [
- Expanded(
- child: Text("${SportUtils.pace4(_value.best?.kmDuration?.value ?? 0, 1000)}",
- style: Theme.of(context).textTheme.headline1!.copyWith(
- fontSize: 20.0,
- fontFamily: "DIN",
- ))),
- arrowRight5()
- ],
- ),
- flex: flexRight,
- ),
- ],
- ),
- ),
- ),
- ],
- ),
- ),
- _label("${TABS[toType()]}最快"),
- Padding(
- padding: const EdgeInsets.all(12.0),
- child: Column(
- children: [
- if (_value.best?.kmDurationList?.isNotEmpty == true)
- ListView.separated(
- itemBuilder: (context, index) {
- KmDurationList? e = _value.best?.kmDurationList?[index];
- return GestureDetector(
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 11.0),
- child: Row(
- children: [
- Expanded(
- child: Column(
- children: [
- Text('${toKm((e?.distance ?? 0) / 1000)}最快时间', style: _labelTextStyle),
- const SizedBox(
- height: 4.0,
- ),
- Text('${e?.createdAt?.substring(0, e.createdAt?.indexOf(" ") ?? 0)}', style: Theme.of(context).textTheme.bodyText1!),
- ],
- crossAxisAlignment: CrossAxisAlignment.start,
- ),
- flex: flexLeft,
- ),
- Expanded(
- child: Row(
- children: [
- Expanded(
- child: Text("${DateFormat.toTime(e?.duration ?? 0)}",
- style: Theme.of(context).textTheme.headline1!.copyWith(
- fontSize: 20.0,
- fontFamily: "DIN",
- )),
- ),
- arrowRight5()
- ],
- ),
- flex: flexRight,
- ),
- ],
- ),
- ),
- onTap: () => NavigatorUtil.goPage(
- context,
- (context) => RunDetailPage(
- id: e?.id ?? 0,
- )),
- behavior: HitTestBehavior.opaque,
- );
- },
- separatorBuilder: (context, index) {
- return _divider;
- },
- itemCount: _value.best?.kmDurationList?.length ?? 0,
- shrinkWrap: true,
- physics: NeverScrollableScrollPhysics(),
- ),
- if (_value.best?.kmDurationList?.isNotEmpty == true) _divider,
- ListView.separated(
- itemBuilder: (context, index) {
- var e = bestFilled[index];
- return Padding(
- padding: const EdgeInsets.symmetric(horizontal: 11.0),
- child: Row(
- children: [
- Expanded(
- child: Column(
- children: [
- Text('${toKm(e)}最快时间', style: _labelTextStyle),
- const SizedBox(
- height: 4.0,
- ),
- Text('暂无记录时间', style: Theme.of(context).textTheme.bodyText1!),
- ],
- crossAxisAlignment: CrossAxisAlignment.start,
- ),
- flex: flexLeft,
- ),
- Text("--",
- style: Theme.of(context).textTheme.headline1!.copyWith(
- fontSize: 20.0,
- fontFamily: "DIN",
- )),
- ],
- ),
- );
- },
- separatorBuilder: (context, index) {
- return _divider;
- },
- itemCount: bestFilled.length,
- shrinkWrap: true,
- physics: NeverScrollableScrollPhysics(),
- ),
- ],
- ),
- ),
- const SizedBox(
- height: 50.0,
- ),
- ],
- ),
- );
- });
- }
- }
|