From 77b353735cdb37924eb6309febee3dcd82da7e33 Mon Sep 17 00:00:00 2001 From: zhangmeng <494089941@qq.com> Date: Sun, 23 Jan 2022 14:19:20 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E9=A6=96=E9=A1=B5bar=E7=9A=84=E9=A2=9C?= =?UTF-8?q?=E8=89=B2=E9=9A=8F=E8=BD=AE=E6=92=AD=E5=9B=BE=E5=8F=98=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/home/home_page.dart | 702 +++++++++++-------- lib/pages/home/widget/animate_app_bar.dart | 91 ++- lib/pages/home/widget/filter_tool_bar.dart | 592 ---------------- lib/pages/home/widget/home_search.dart | 54 -- lib/ui/community/activity/activity_card.dart | 16 +- pubspec.lock | 7 + pubspec.yaml | 2 + 7 files changed, 469 insertions(+), 995 deletions(-) delete mode 100644 lib/pages/home/widget/filter_tool_bar.dart delete mode 100644 lib/pages/home/widget/home_search.dart diff --git a/lib/pages/home/home_page.dart b/lib/pages/home/home_page.dart index a6e93ff5..e3574593 100644 --- a/lib/pages/home/home_page.dart +++ b/lib/pages/home/home_page.dart @@ -1,13 +1,11 @@ // Dart imports: -import 'package:aku_new_community/const/resource.dart'; import 'package:aku_new_community/constants/api.dart'; import 'package:aku_new_community/constants/application_objects.dart'; import 'package:aku_new_community/model/common/img_model.dart'; import 'package:aku_new_community/model/community/activity_item_model.dart'; import 'package:aku_new_community/model/community/board_model.dart'; import 'package:aku_new_community/model/community/swiper_model.dart'; -import 'package:aku_new_community/pages/home/widget/animate_app_bar.dart'; import 'package:aku_new_community/pages/message_center_page/message_center_page.dart'; import 'package:aku_new_community/pages/one_alarm/widget/alarm_page.dart'; import 'package:aku_new_community/pages/visitor_access_page/visitor_access_page.dart'; @@ -27,18 +25,16 @@ import 'package:aku_new_community/widget/others/rectIndicator.dart'; import 'package:aku_new_community/widget/others/user_tool.dart'; import 'package:badges/badges.dart'; import 'package:bot_toast/bot_toast.dart'; -import 'package:flutter/cupertino.dart'; +import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_easyrefresh/easy_refresh.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_swiper_null_safety/flutter_swiper_null_safety.dart'; import 'package:get/get.dart'; import 'package:jpush_flutter/jpush_flutter.dart'; +import 'package:palette_generator/palette_generator.dart'; import 'package:power_logger/power_logger.dart'; import 'package:provider/provider.dart'; -import 'package:velocity_x/velocity_x.dart'; - -import 'widget/home_search.dart'; class HomePage extends StatefulWidget { HomePage({Key? key}) : super(key: key); @@ -66,6 +62,9 @@ class _HomePageState extends State List _activityItemModels = []; List _boardItemModels = []; List _swiperModels = []; + SwiperController _swiperController = SwiperController(); + + ValueNotifier _barColor = ValueNotifier(Colors.transparent); @override void initState() { @@ -81,12 +80,15 @@ class _HomePageState extends State } _scrollController = ScrollController(); _refreshController = EasyRefreshController(); + SystemChrome.setSystemUIOverlayStyle( + SystemUiOverlayStyle(statusBarColor: Colors.transparent)); } @override void dispose() { _refreshController.dispose(); _scrollController?.dispose(); + _swiperController.dispose(); super.dispose(); } @@ -97,11 +99,51 @@ class _HomePageState extends State commentCount = appProvider.messageCenterModel.commentCount ?? 0; sysCount = appProvider.messageCenterModel.sysCount ?? 0; sum = commentCount + sysCount; - return Scaffold( - extendBodyBehindAppBar: true, - appBar: AnimateAppBar( - scrollController: _scrollController, - actions: [ + var head = ValueListenableBuilder( + valueListenable: _barColor, + builder: (context, Color color, child) { + return Container( + padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top), + decoration: BoxDecoration( + border: Border.all(width: 0, color: color), + color: color, + ), + width: double.infinity, + child: child, + ); + }, + child: Padding( + padding: EdgeInsets.symmetric(vertical: 16.w, horizontal: 16.w), + child: Row(crossAxisAlignment: CrossAxisAlignment.center, children: [ + if (appProvider.location != null) + Padding( + padding: const EdgeInsets.only(right: 5), + child: Image.asset( + R.ASSETS_ICONS_ICON_MAIN_LOCATION_PNG, + width: 32.w, + height: 32.w, + ), + ), + Text( + appProvider.location?['city'] == null + ? '' + : appProvider.location?['city'] as String? ?? '', + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 24.sp, + color: Color(0xff333333), + ), + textAlign: TextAlign.center, + ), + Text( + '(${appProvider.weatherType} ${appProvider.weatherTemp}℃)', + style: TextStyle( + fontSize: 24.sp, + color: Color(0xff999999), + ), + textAlign: TextAlign.center, + ), + Spacer(), GestureDetector( onTap: () { Get.to(() => BeeSearch()); @@ -134,311 +176,303 @@ class _HomePageState extends State height: 40.w, width: 40.w), )), ), - ], + ]), ), - // floatingActionButton: FloatingActionButton( - // - // child: Container( - // decoration: BoxDecoration( - // image: DecorationImage( - // fit: BoxFit.fill, - // image: - // AssetImage(R.ASSETS_ICONS_ICON_MAIN_OPEN_PNG),) - // ), - // ), - // onPressed: (){ - // print('FloatingActionButton'); - // }, - // ), - body: Stack( - children: [ - EasyRefresh( - controller: _refreshController, - header: MaterialHeader(), - firstRefresh: true, - onRefresh: () async { - //_activityItemModel = await CommunityFunc.activity(); - _activityItemModels = await CommunityFunc.activityList(); - _boardItemModels = await CommunityFunc.board(); - _swiperModels = await CommunityFunc.swiper(); - appProvider.getMessageCenter(); - setState(() {}); - }, - child: CustomScrollView( - controller: _scrollController, - slivers: [ - SliverToBoxAdapter( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - HomeSearch(), - - HomeSwiper(), //要做点击事件 - // SizedBox(height: 100.w), - Container( - padding: EdgeInsets.only(top: 24.w, bottom: 32.w), - child: getFunction(), //ApplicationView(), - decoration: BoxDecoration( - color: Colors.white, - boxShadow: const [ - BoxShadow( - color: Color(0x14000000), - blurRadius: 0, - offset: Offset(0.0, 2.0), - spreadRadius: 0.1) - ], - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(28), - bottomRight: Radius.circular(28))), - ) - //ApplicationBox(child: ApplicationView()), - ], - ), - ), - SliverToBoxAdapter( - child: Container( - height: 40, - margin: - EdgeInsets.only(left: 32.w, right: 32.w, top: 24.w), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(8)), - boxShadow: const [ - BoxShadow( - color: Color(0x14000000), - blurRadius: 4, - spreadRadius: 0.5) - ], - ), - child: HomeNotification(items: _boardItemModels)), - ), - SliverToBoxAdapter( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - GestureDetector( - child: Container( - margin: EdgeInsets.only(top: 24.w), - padding: EdgeInsets.only(left: 32.w, top: 24.w), - width: 140, - height: 150, - decoration: BoxDecoration( - image: DecorationImage( - fit: BoxFit.fill, - image: AssetImage(R.ASSETS_IMAGES_CARD_YELLOW_PNG), - )), + ); + return AnnotatedRegion( + value: SystemUiOverlayStyle.dark, + child: Scaffold( + extendBody: true, + extendBodyBehindAppBar: true, + body: Stack( + children: [ + Column( + children: [ + head, + Flexible( + child: EasyRefresh( + controller: _refreshController, + header: BeeBallPauseHeader(bgColor: _barColor), + firstRefresh: true, + onRefresh: () async { + //_activityItemModel = await CommunityFunc.activity(); + _activityItemModels = await CommunityFunc.activityList(); + _boardItemModels = await CommunityFunc.board(); + _swiperModels = await CommunityFunc.swiper(); + appProvider.getMessageCenter(); + setState(() {}); + }, + child: CustomScrollView( + controller: _scrollController, + slivers: [ + SliverToBoxAdapter( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, children: [ - Text( - '访客邀请', - style: TextStyle( - color: Color(0xD9000000), - fontSize: 26.sp, - fontWeight: FontWeight.bold), - ), - 10.hb, - Text( - '一键分享', - style: TextStyle( - color: Color(0x73000000), - fontSize: 20.sp, - ), - ), - Text( - '让拜访不再是难事', - style: TextStyle( - color: Color(0x73000000), - fontSize: 20.sp, - ), - ), - Spacer(), - Image.asset( - R.ASSETS_ICONS_ICON_MAIN_INVITE_PNG, - width: 100.w, - height: 100.w, - ), - 30.hb, + HomeSwiper(), //要做点击事件 + // SizedBox(height: 100.w), + Container( + padding: + EdgeInsets.only(top: 24.w, bottom: 32.w), + child: getFunction(), //ApplicationView(), + decoration: BoxDecoration( + color: Colors.white, + boxShadow: const [ + BoxShadow( + color: Color(0x14000000), + blurRadius: 0, + offset: Offset(0.0, 2.0), + spreadRadius: 0.1) + ], + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(28), + bottomRight: Radius.circular(28))), + ) + //ApplicationBox(child: ApplicationView()), ], ), ), - onTap: () { - Get.to(VisitorAccessPage()); - }, - ), - 25.wb, - Container( - margin: EdgeInsets.only(top: 24.w), - child: Column( - children: [ - GestureDetector( - child: Container( - width: 190, - height: 69, - decoration: BoxDecoration( - image: DecorationImage( - fit: BoxFit.fill, - image: - AssetImage(R.ASSETS_IMAGES_CARD_PINK_PNG), - )), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - 20.wb, - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - 20.hb, - Text( - '一键报警', - style: TextStyle( - color: Color(0xD9000000), - fontSize: 26.sp, - fontWeight: FontWeight.bold), + SliverToBoxAdapter( + child: Container( + height: 40, + margin: EdgeInsets.only( + left: 32.w, right: 32.w, top: 24.w), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: + BorderRadius.all(Radius.circular(8)), + boxShadow: const [ + BoxShadow( + color: Color(0x14000000), + blurRadius: 4, + spreadRadius: 0.5) + ], + ), + child: HomeNotification(items: _boardItemModels)), + ), + SliverToBoxAdapter( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Container( + margin: EdgeInsets.only(top: 24.w), + padding: + EdgeInsets.only(left: 32.w, top: 24.w), + width: 140, + height: 150, + decoration: BoxDecoration( + image: DecorationImage( + fit: BoxFit.fill, + image: AssetImage( + R.ASSETS_IMAGES_CARD_YELLOW_PNG), + )), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + '访客邀请', + style: TextStyle( + color: Color(0xD9000000), + fontSize: 26.sp, + fontWeight: FontWeight.bold), + ), + 10.hb, + Text( + '一键分享', + style: TextStyle( + color: Color(0x73000000), + fontSize: 20.sp, ), - 10.hb, - Text( - '提交报警位置给物业', - style: TextStyle( - color: Color(0x73000000), - fontSize: 20.sp, - ), + ), + Text( + '让拜访不再是难事', + style: TextStyle( + color: Color(0x73000000), + fontSize: 20.sp, ), - ], - ), - Spacer(), - Image.asset( - R.ASSETS_ICONS_ICON_MAIN_POLICE_PNG, - width: 98.w, - height: 98.w, - ), - 20.wb, - ], + ), + Spacer(), + Image.asset( + R.ASSETS_ICONS_ICON_MAIN_INVITE_PNG, + width: 100.w, + height: 100.w, + ), + 30.hb, + ], + ), ), + onTap: () { + Get.to(VisitorAccessPage()); + }, ), - onTap: () { - Get.to(AlarmPage()); - }, - ), - GestureDetector( - child: Container( - margin: EdgeInsets.only(top: 20.w), - width: 190, - height: 69, - decoration: BoxDecoration( - image: DecorationImage( - fit: BoxFit.fill, - image: - AssetImage(R.ASSETS_IMAGES_CARD_BLUE_PNG), - )), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, + 25.wb, + Container( + margin: EdgeInsets.only(top: 24.w), + child: Column( children: [ - 20.wb, - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - 20.hb, - Text( - '建议咨询', - style: TextStyle( - color: Color(0xD9000000), - fontSize: 26.sp, - fontWeight: FontWeight.bold), + GestureDetector( + child: Container( + width: 190, + height: 69, + decoration: BoxDecoration( + image: DecorationImage( + fit: BoxFit.fill, + image: AssetImage( + R.ASSETS_IMAGES_CARD_PINK_PNG), + )), + child: Row( + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + 20.wb, + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + 20.hb, + Text( + '一键报警', + style: TextStyle( + color: Color(0xD9000000), + fontSize: 26.sp, + fontWeight: + FontWeight.bold), + ), + 10.hb, + Text( + '提交报警位置给物业', + style: TextStyle( + color: Color(0x73000000), + fontSize: 20.sp, + ), + ), + ], + ), + Spacer(), + Image.asset( + R.ASSETS_ICONS_ICON_MAIN_POLICE_PNG, + width: 98.w, + height: 98.w, + ), + 20.wb, + ], ), - 10.hb, - Text( - '欢迎给我们提供服务意见', - style: TextStyle( - color: Color(0x73000000), - fontSize: 20.sp, - ), - ), - ], - ), - Spacer(), - Image.asset( - R.ASSETS_ICONS_ICON_MAIN_CONSULT_PNG, - width: 98.w, - height: 98.w, + ), + onTap: () { + Get.to(AlarmPage()); + }, ), - 20.wb, + GestureDetector( + child: Container( + margin: EdgeInsets.only(top: 20.w), + width: 190, + height: 69, + decoration: BoxDecoration( + image: DecorationImage( + fit: BoxFit.fill, + image: AssetImage( + R.ASSETS_IMAGES_CARD_BLUE_PNG), + )), + child: Row( + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + 20.wb, + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + 20.hb, + Text( + '建议咨询', + style: TextStyle( + color: Color(0xD9000000), + fontSize: 26.sp, + fontWeight: + FontWeight.bold), + ), + 10.hb, + Text( + '欢迎给我们提供服务意见', + style: TextStyle( + color: Color(0x73000000), + fontSize: 20.sp, + ), + ), + ], + ), + Spacer(), + Image.asset( + R.ASSETS_ICONS_ICON_MAIN_CONSULT_PNG, + width: 98.w, + height: 98.w, + ), + 20.wb, + ], + ), + ), + onTap: () { + Get.to(AdvicePage( + type: AdviceType.SUGGESTION)); + }, + ) ], ), - ), - onTap: () { - Get.to(AdvicePage(type: AdviceType.SUGGESTION)); - }, - ) - ], + ) + ], + ), ), - ) - ], + SliverToBoxAdapter( + child: Column( + children: [ + HomeTitle( + title: '社区活动', + suffixTitle: '查看全部', + onTap: () => Get.to(() => ActivityListPage()), + ), + _activityItemModels == [] + ? SizedBox() + : Container( + height: 400.w, + padding: EdgeInsets.only(left: 32.w), + child: ListView.separated( + padding: EdgeInsets.zero, + separatorBuilder: (context, index) { + return SizedBox( + width: 16.w, + ); + }, + scrollDirection: Axis.horizontal, + itemBuilder: (context, index) { + return Container( + width: 500.w, + child: Builder( + builder: (context) { + return ActivityCard( + model: _activityItemModels[ + index]); + }, + ), + ); + }, + itemCount: _activityItemModels.length, + ), + ), + // : ActivityCard(model: _activityItemModel) + // .pSymmetric(h: 24.w, v: 24.w), + ], + )), + ], + ), ), ), - SliverToBoxAdapter( - child: Column( - children: [ - // HomeTitle( - // title: '公共资讯', - // suffixTitle: '更多资讯', - // onTap: () async { - // final cancel = BotToast.showLoading(); - // BaseModel model = await NetUtil().get(API.news.category); - // List? category; - // if (model.status == true && model.data != null) { - // category = (model.data as List) - // .map((e) => NewsCategoryModel.fromJson(e)) - // .toList(); - // } - // cancel(); - // Get.to( - // () => PublicInfomationPage(models: category ?? [])); - // }, - // ), - HomeTitle( - title: '社区活动', - suffixTitle: '查看全部', - onTap: () => Get.to(() => ActivityListPage()), - ), - _activityItemModels == [] - ? SizedBox() - : Container( - height: 400.w, - padding: EdgeInsets.only(left: 32.w), - child: ListView.separated( - padding: EdgeInsets.zero, - separatorBuilder: (context, index) { - return SizedBox( - width: 16.w, - ); - }, - scrollDirection: Axis.horizontal, - itemBuilder: (context, index) { - return Container( - width: 500.w, - child: Builder( - builder: (context) { - return ActivityCard( - model: _activityItemModels[index]); - }, - ), - ); - }, - itemCount: _activityItemModels.length, - ), - ), - // : ActivityCard(model: _activityItemModel) - // .pSymmetric(h: 24.w, v: 24.w), - ], - )), ], ), - ), - OverlayLivingBtnWidget() - ], + OverlayLivingBtnWidget() + ], + ), ), ); } @@ -447,10 +481,25 @@ class _HomePageState extends State return Container( width: double.infinity, height: 320.w, + decoration: + BoxDecoration(border: Border.all(width: 0, color: _barColor.value)), child: AspectRatio( aspectRatio: 375 / 160, child: Swiper( key: UniqueKey(), + onIndexChanged: (index) async { + if (_swiperModels.isNotEmpty) { + var color = await PaletteGenerator.fromImageProvider( + CachedNetworkImageProvider( + API.image( + ImgModel.first(_swiperModels[index].voResourcesImgList)), + )); + _barColor.value = + color.dominantColor?.color ?? Colors.transparent; + } else { + _barColor.value = Colors.transparent; + } + }, itemBuilder: (BuildContext context, int index) { return getSwiperImage(_swiperModels[index]); }, @@ -562,3 +611,62 @@ class _HomePageState extends State @override bool get wantKeepAlive => true; } + +class BeeBallPauseHeader extends Header { + /// Key + final Key? key; + + final ValueNotifier bgColor; + + final LinkHeaderNotifier linkNotifier = LinkHeaderNotifier(); + + BeeBallPauseHeader({ + this.key, + required this.bgColor, + bool enableHapticFeedback = true, + bool enableInfiniteRefresh = false, + }) : super( + extent: 70.0, + triggerDistance: 70.0, + float: false, + enableHapticFeedback: enableHapticFeedback, + enableInfiniteRefresh: enableInfiniteRefresh, + ); + + @override + Widget contentBuilder( + BuildContext context, + RefreshMode refreshState, + double pulledExtent, + double refreshTriggerPullDistance, + double refreshIndicatorExtent, + AxisDirection axisDirection, + bool float, + Duration? completeDuration, + bool enableInfiniteRefresh, + bool success, + bool noMore) { + linkNotifier.contentBuilder( + context, + refreshState, + pulledExtent, + refreshTriggerPullDistance, + refreshIndicatorExtent, + axisDirection, + float, + completeDuration, + enableInfiniteRefresh, + success, + noMore); + return ValueListenableBuilder( + valueListenable: bgColor, + builder: (context, Color color, child) { + return BallPulseHeaderWidget( + key: key, + color: color.withBlue(128), + backgroundColor: color, + linkNotifier: linkNotifier, + ); + }); + } +} diff --git a/lib/pages/home/widget/animate_app_bar.dart b/lib/pages/home/widget/animate_app_bar.dart index 13e7d18f..e3d997e7 100644 --- a/lib/pages/home/widget/animate_app_bar.dart +++ b/lib/pages/home/widget/animate_app_bar.dart @@ -1,14 +1,17 @@ import 'package:aku_new_community/provider/app_provider.dart'; import 'package:aku_new_community/utils/headers.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:provider/provider.dart'; class AnimateAppBar extends StatefulWidget with PreferredSizeWidget { final ScrollController? scrollController; final List? actions; + final ValueNotifier bgColor; - AnimateAppBar({Key? key, this.scrollController, this.actions}) + AnimateAppBar( + {Key? key, this.scrollController, this.actions, required this.bgColor}) : super(key: key); @override @@ -19,63 +22,57 @@ class AnimateAppBar extends StatefulWidget with PreferredSizeWidget { } class _AnimateAppBarState extends State { - Color _bgColor = Colors.white; - @override void initState() { super.initState(); - widget.scrollController!.addListener(() { - setState(() { - _bgColor = widget.scrollController!.offset > 30 - ? Colors.white - : widget.scrollController!.offset < 0 - ? Colors.transparent - : Colors.white - .withOpacity((widget.scrollController!.offset / 30)); - }); - }); } @override Widget build(BuildContext context) { final appProvider = Provider.of(context); - return Padding( - padding: const EdgeInsets.only(top: 5), - child: AppBar( - titleSpacing: 10.0, - title: Row(crossAxisAlignment: CrossAxisAlignment.center, children: [ - if (appProvider.location != null) - Padding( - padding: const EdgeInsets.only(right: 5), - child: Image.asset( - R.ASSETS_ICONS_ICON_MAIN_LOCATION_PNG, - width: 32.w, - height: 32.w, - ), - ), - Text( - appProvider.location?['city'] == null - ? '' - : appProvider.location?['city'] as String? ?? '', - style: TextStyle( - fontWeight: FontWeight.w600, - fontSize: 24.sp, - color: Color(0xff333333), + return ValueListenableBuilder( + valueListenable: widget.bgColor, + builder: (context, color, child) { + return AppBar( + systemOverlayStyle: SystemUiOverlayStyle( + statusBarColor: widget.bgColor.value, + statusBarIconBrightness: Brightness.light), + titleSpacing: 10.0, + title: child, + backgroundColor: widget.bgColor.value, + actions: widget.actions, + ); + }, + child: Row(crossAxisAlignment: CrossAxisAlignment.center, children: [ + if (appProvider.location != null) + Padding( + padding: const EdgeInsets.only(right: 5), + child: Image.asset( + R.ASSETS_ICONS_ICON_MAIN_LOCATION_PNG, + width: 32.w, + height: 32.w, ), - textAlign: TextAlign.center, ), - Text( - '(${appProvider.weatherType} ${appProvider.weatherTemp}℃)', - style: TextStyle( - fontSize: 24.sp, - color: Color(0xff999999), - ), - textAlign: TextAlign.center, + Text( + appProvider.location?['city'] == null + ? '' + : appProvider.location?['city'] as String? ?? '', + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 24.sp, + color: Color(0xff333333), + ), + textAlign: TextAlign.center, + ), + Text( + '(${appProvider.weatherType} ${appProvider.weatherTemp}℃)', + style: TextStyle( + fontSize: 24.sp, + color: Color(0xff999999), ), - ]), - backgroundColor: _bgColor, - actions: widget.actions, - ), + textAlign: TextAlign.center, + ), + ]), ); } } diff --git a/lib/pages/home/widget/filter_tool_bar.dart b/lib/pages/home/widget/filter_tool_bar.dart deleted file mode 100644 index d7199f2c..00000000 --- a/lib/pages/home/widget/filter_tool_bar.dart +++ /dev/null @@ -1,592 +0,0 @@ -/* - * ==================================================== - * package : widgets - * author : Created by nansi. - * time : 2019/5/13 1:44 PM - * remark : - * ==================================================== - */ - -import 'package:aku_new_community/utils/text_utils.dart'; -import 'package:flutter/material.dart'; - -/// 自筛选列表点击监听 -typedef SelectedListener = Function(int selectedIndex, FilterItemModel item); - -/// 下拉列表状态变更 -typedef PopOptionHandle = Function(OptionListStatus status); - -/// filterBar 标题点击、变更等监听 -typedef FilterToolBarListener = Function(bool update); - -class FilterToolBarController { - late FilterResultContainerHelper helper; - late int selectedIndex; - late FilterItemModel item; - late GlobalKey _containerKey; - late GlobalKey _toolBarKey; - - /// [update] 是否需要通知外层 sublist 点击的index 和上次一致时,不通知外层 - FilterToolBarListener updateToolBarState = (bool update) {}; - - close() { - helper.changeOptionListStatus(OptionListStatus.close); - } - - get toolBarDx { - RenderBox box = _toolBarKey.currentContext?.findRenderObject() - as RenderBox; //_toolBarKey.currentContext.findRenderObject(); - Offset offset = box.localToGlobal(Offset.zero); - return offset.dx; - } - - double get toolBarDy { - /// toolbar 距离top 的间距 - container外层距离top的间距 - RenderBox containerBox = - _containerKey.currentContext?.findRenderObject() as RenderBox; - RenderBox box = _toolBarKey.currentContext?.findRenderObject() as RenderBox; - Offset containerTopOffset = containerBox.localToGlobal(Offset.zero); - Offset toolBarTopOffset = box.localToGlobal(Offset.zero); - return toolBarTopOffset.dy - containerTopOffset.dy; - } - -////获取position -// RenderBox box = _key.currentContext.findRenderObject(); -// Offset offset = box.localToGlobal(Offset.zero); -// -////获取size -// Size size = box.size; - -// print(" ---- $offset ------- $size"); - -} - -enum OptionListStatus { open, close } - -/// 筛选子列表操作 -class FilterResultContainerHelper { - final PopOptionHandle handle; - - /// 字筛选列表弹出状态 - late OptionListStatus status; - - FilterResultContainerHelper({required this.handle}); - - changeOptionListStatus(OptionListStatus status) { - this.status = status; - this.handle(status); - } -} - -/// 筛选下拉列表容器 与 FilterToolBar 一起使用 -class FilterToolBarResultContainer extends StatefulWidget { - final FilterToolBarController? controller; - final Widget? body; - - const FilterToolBarResultContainer( - {GlobalKey? key, this.controller, this.body}) - : assert(controller != null, "controller 不为空"); - - @override - State createState() { - return _FilterToolBarResultContainerState(); - } -} - -class _FilterToolBarResultContainerState - extends State with TickerProviderStateMixin { - /// 子列表行数 - late int _lines; - - int maxLines = 3; - - /// 子列表单行高度 - double _lineHeight = 35.0; - - /// 底部内边距 - double _bottomSpacing = 8.0; - - /// 顶部边距 - double _topSpacing = 8.0; - - /// 未选中颜色 - Color _unselectedColor = Colors.grey[700]!; - - /// toolbar 字体大小 - // double _toolBarTitleFont = 14.0; - - /// 子列表字体大小 - double _subTitleFont = 13.0; - - /// 子列表单行内边距 因为点击要整行选中,所以在row上设置左右边距 - EdgeInsetsGeometry _subtitleRowPadding = EdgeInsets.only(left: 15, right: 15); - - late AnimationController _animationController; - late Animation _animation; - - @override - void initState() { - _animationController = - AnimationController(vsync: this, duration: Duration(milliseconds: 150)); - - _lines = maxLines; - - widget.controller?.helper = FilterResultContainerHelper(handle: (status) { - if (status == OptionListStatus.open) { - _buildAnimation(widget.controller!.item); - _animationController.forward(); - } else { - _animationController.reset(); - } - }); - - if (widget.key == null) { - widget.controller!._containerKey = GlobalKey(); - } else { - widget.controller!._containerKey = widget.key as GlobalKey; - } - - super.initState(); - } - - @override - void dispose() { - _animationController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Container( - key: widget.controller!._containerKey, - child: _buildBody(context), - ); - } - - Stack _buildBody(BuildContext context) { - return Stack( - children: [ - /// body内容 - Container( - height: double.infinity, - child: widget.body, - ), - - /// 蒙版 - _maskView(), - - widget.controller?._toolBarKey == null - ? Container() - : Positioned( - top: widget.controller!.toolBarDy + 40, - left: 0, - right: 0, - bottom: 0, - child: Stack(children: [ - widget.controller!.item.type == FilterItemType.list - ? _buildList(context) - : Container(), - ])) - ], - ); - } - - Widget _maskView() { - double? num = widget.controller?.toolBarDy; - - return widget.controller?._toolBarKey == null - ? Container() - : Positioned( - top: (num as double) + 40, - left: 0, - right: 0, - bottom: 0, - child: Offstage( - child: GestureDetector( - behavior: HitTestBehavior.translucent, - onTap: () { - widget.controller!.helper.changeOptionListStatus( - OptionListStatus.close, - ); - widget.controller!.updateToolBarState(false); - _animationController.reset(); - }, - child: Opacity( - opacity: 0.3, - child: Container( - color: Colors.black, - ), - ), - ), - offstage: _animation == null || - (_animation.status == AnimationStatus.dismissed), - ), - ); - } - - /// 有多个子列表时 因为有设置最大行数,小于最大行数[widget.maxLines]时,以子列表个数为准, - /// 否则以最大行数为准,选中时切换动画, - _buildAnimation(FilterItemModel item) { - _lines = - item.subtitles!.length > maxLines ? maxLines : item.subtitles!.length; - - _animation = new Tween( - begin: 0.0 - _lines * _lineHeight - _bottomSpacing - _topSpacing, - end: 0.0) - .animate(_animationController) - ..addListener(() { - setState(() { - // the state that has changed here is the animation object’s value - }); - }); - } - - /// 筛选子列表 - Positioned _buildList(context) { - FilterItemModel item = widget.controller!.item; - return Positioned( - top: _animation.value, - left: 0, - right: 0, - child: LimitedBox( - maxHeight: _lineHeight * _lines + _topSpacing + _bottomSpacing, - child: Container( - padding: EdgeInsets.only(bottom: _bottomSpacing, top: 5), - height: _lineHeight * item.subtitles!.length + - _bottomSpacing + - _topSpacing, - decoration: BoxDecoration( - color: Color.fromARGB(240, 255, 255, 255), - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(10), - bottomRight: Radius.circular(10))), - child: MediaQuery.removePadding( - context: context, - removeTop: true, - child: ListView.builder( - physics: NeverScrollableScrollPhysics(), - controller: PrimaryScrollController.of(context), - itemCount: item.subtitles!.length, - itemBuilder: (context, index) { - bool subTitleSelected = item.selectedSubIndex == index; - return Container( - height: _lineHeight, - child: RawMaterialButton( - onPressed: () { - widget.controller!.helper - .changeOptionListStatus(OptionListStatus.close); - widget.controller!.updateToolBarState(false); - if (item.selectedSubIndex == index) return; - - item.selectedSubIndex = index; - String title = item.subtitleShort == null || - TextUtils.isEmpty(item.subtitleShort![index]) - ? item.subtitles![index] - : item.subtitleShort![index]; - item.title = title; - - widget.controller!.updateToolBarState(true); - }, - child: _sublistItem(index, item, subTitleSelected), - ), - ); - }), - ), - ), - ), - ); - } - - /// 子列表item - Container _sublistItem( - int index, FilterItemModel item, bool subTitleSelected) { - return Container( - padding: _subtitleRowPadding, - child: Row( - children: [ - Offstage( - child: Padding( - padding: EdgeInsets.symmetric(horizontal: 8), - child: Icon( - Icons.check, - size: 17, - color: Colors.red, - ), - ), - offstage: index != item.selectedSubIndex, - ), - Expanded( - child: Text( - item.subtitles![index], - style: TextStyle( - fontSize: _subTitleFont, - color: _unselectedColor, - fontWeight: - (subTitleSelected ? FontWeight.w600 : FontWeight.w400)), - )), - ], - ), - ); - } -} - -class FilterToolBar extends StatefulWidget { - FilterToolBar({ - required this.titles, - required this.listener, - required this.controller, - this.selectedColor, - this.maxLines = 4, - this.trialing, - this.startWidget, - this.fontSize = 15.0, - this.height = 40, - }) : assert(listener != null, "请设置监听事件"), - assert(controller != null, "请设置controller"); - - final List titles; - final Color? selectedColor; - final int maxLines; - final SelectedListener listener; - final Widget? trialing; - final Widget? startWidget; - final FilterToolBarController? controller; - final double fontSize; - final double height; - - @override - State createState() { - return _FilterToolBarState(); - } -} - -class _FilterToolBarState extends State - with TickerProviderStateMixin { - Color _unselectedColor = Colors.grey[700]!; - - GlobalKey _key = GlobalKey(); - - @override - void initState() { - super.initState(); - - widget.controller?.selectedIndex = widget.controller?.selectedIndex ?? 0; - - widget.controller?._toolBarKey = _key; - - widget.controller?.updateToolBarState = (bool update) { -// print("----- ${widget.controller.selectedIndex}"); - if (update) { - widget.listener( - widget.controller!.selectedIndex, widget.controller!.item); - } - setState(() {}); - }; - } - - @override - Widget build(BuildContext context) { - return Container( - width: double.infinity, - height: widget.height, - child: _buildToolBar(), - ); - } - - Container _buildToolBar() { - List items = []; - if (widget.startWidget != null) { - items.add(SizedBox( - width: 60, - )); - items.add(widget.startWidget!); - items.add(SizedBox( - width: 20, - )); - } - items.addAll(_buildToolBarItem()); - if (widget.trialing != null) { - items.add(widget.trialing!); - } - - return Container( - key: _key, - height: 40, - decoration: BoxDecoration( - color: Colors.white, - border: Border( - top: BorderSide(color: Colors.grey[200]!, width: 0.5), - bottom: BorderSide(color: Colors.grey[200]!, width: 0.5))), - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: items, - ), - ); - } - - List _buildToolBarItem() { - return widget.titles.map((item) { - int index = widget.titles.indexOf(item); - bool selected = index == widget.controller?.selectedIndex; - Color color = (selected ? widget.selectedColor : _unselectedColor)!; - return Expanded( - child: GestureDetector( - onTap: () { - widget.controller?.item = item; - - /// 列表弹出后直接点击toolbar上按钮 列表消失 - if (widget.controller?.helper != null && - widget.controller?.helper.status == OptionListStatus.open) { - widget.controller?.helper.changeOptionListStatus( - OptionListStatus.close, - ); - } else { - if (item.type == FilterItemType.list) { - /// 当前已选中,再次点击弹出列表 - if (widget.controller?.selectedIndex == index) { - if (widget.controller?.helper != null) { - widget.controller?.helper.changeOptionListStatus( - OptionListStatus.open, - ); - } else { - FlutterError("列表类型需要与 FilterToolBarResultContainer 一起使用"); - } - } else { - /// 点击其他列表项时,把当前列表项之前选中的状态返回 - widget.listener(index, item); - } - } - } - - /// 上下箭头选项点击 - if (item.type == FilterItemType.double) { - if (widget.controller?.selectedIndex != index) { - item.selectedList![index] = true; - item.topSelected = item.selectedList![index]; - } else { - //print(item.topSelected); - //item.topSelected = !item.topSelected; - // print(widget.titles[index].topSelected); - item.selectedList![index] = !item.selectedList![index]; - item.topSelected = item.selectedList![index]; - } - widget.listener(index, item); - } - - /// 普通 - else if (item.type == FilterItemType.normal) { - if (widget.controller?.selectedIndex == index) return; - widget.listener(index, item); - } - - widget.controller?.selectedIndex = index; - - setState(() {}); - }, - child: Container( - color: Colors.white, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text(item.title, - style: TextStyle( - fontSize: widget.fontSize, - color: color, - fontWeight: FontWeight.w400) - // AppTextStyle.generate(widget.fontSize, - // color: color, fontWeight: FontWeight.w400), - ), - _buildArrow(item, color, selected, index) - ], - ), - ), - ), - ); - }).toList(); - } - - _buildArrow(FilterItemModel item, color, bool selected, int index) { - if (item.type == FilterItemType.list) { - return Icon( - selected - ? (widget.controller?.helper != null && - widget.controller?.helper.status == OptionListStatus.open - ? Icons.arrow_drop_up - : Icons.arrow_drop_down) - : Icons.arrow_drop_down, - color: color, - size: 19, - ); - } else if (item.type == FilterItemType.double) { - if (selected) { - return Padding( - padding: const EdgeInsets.only(left: 2.0), - child: Icon( - item.selectedList![index] - ? IconData(0xe620, fontFamily: "AppIcons") - : IconData(0xe621, fontFamily: "AppIcons"), - size: 7, - color: color, - ), - ); - } else { - return Padding( - padding: const EdgeInsets.only(left: 2.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - IconData(0xe620, fontFamily: "AppIcons"), - size: 7, - color: _unselectedColor, - ), - Icon( - IconData(0xe621, fontFamily: "AppIcons"), - size: 7, - color: _unselectedColor, - ), - ], - ), - ); - } - } else { - return Container(); - } - } -} - -enum FilterItemType { - /// 列表形式 - list, - - /// 价格等上下箭头 - double, - - /// 普通 - normal -} - -class FilterItemModel { - final FilterItemType type; - String title; - final List? subtitles; - - /// 列表下拉时的子标题 - final List? subtitleShort; - List? selectedList; - bool topSelected; - int selectedSubIndex = 0; - - FilterItemModel({ - required this.type, - required this.title, - this.selectedList, - this.subtitles, - this.subtitleShort, - this.topSelected = true, - }) : assert( - type == FilterItemType.list - ? (subtitles != null && subtitles.length > 0) - : true, - "type为list,列表项不能为空"); -} diff --git a/lib/pages/home/widget/home_search.dart b/lib/pages/home/widget/home_search.dart deleted file mode 100644 index 4cb5bbf7..00000000 --- a/lib/pages/home/widget/home_search.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'package:aku_new_community/utils/headers.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; - -class HomeSearch extends StatefulWidget { - HomeSearch({Key? key}) : super(key: key); - - @override - _HomeSearchState createState() => _HomeSearchState(); -} - -class _HomeSearchState extends State { - @override - Widget build(BuildContext context) { - return Container( - // decoration: BoxDecoration( - // gradient: LinearGradient( - // begin: Alignment.centerLeft, - // end: Alignment.centerRight, - // colors: [Color(0xffffd000), Color(0xffffbd00)], - // ), - // ), - color: Colors.white, - padding: EdgeInsets.only( - top: MediaQuery.of(context).padding.top, - left: 32.w, - right: 32.w, - bottom: 16.w, - ), - // child: MaterialButton( - // materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - // height: 72.w, - // shape: StadiumBorder(), - // elevation: 0, - // minWidth: double.infinity, - // color: Color(0xFFF3F3F3), - // onPressed: () { - // Get.to(() => BeeSearch()); - // }, - // child: Row( - // children: [ - // Icon( - // Icons.search, - // size: 32.w, - // color: Color(0xFF666666), - // ), - // 10.wb, - // '搜索应用'.text.size(28.sp).color(ktextSubColor).make().expand(), - // ], - // ), - // ), - ); - } -} diff --git a/lib/ui/community/activity/activity_card.dart b/lib/ui/community/activity/activity_card.dart index f5e0267b..8b59491f 100644 --- a/lib/ui/community/activity/activity_card.dart +++ b/lib/ui/community/activity/activity_card.dart @@ -28,9 +28,9 @@ class ActivityCard extends StatelessWidget { elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(24.w), - side: BorderSide( - color: Colors.grey, - ), + // side: BorderSide( + // color: Colors.grey, + // ), ), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, child: Column( @@ -77,12 +77,18 @@ class ActivityCard extends StatelessWidget { height: 39.w, width: 98.w, decoration: BoxDecoration( - color: outdate ? Color(0xFFABABAB) : Color(0x80FEBF76), + color: outdate + ? Colors.black.withOpacity(0.06) + : Color(0x80FEBF76), borderRadius: BorderRadius.all(Radius.circular(4)), ), child: outdate - ? '已结束'.text.size(22.sp).color(Color(0xFF666666)).make() + ? '已结束' + .text + .size(22.sp) + .color(Colors.black.withOpacity(0.25)) + .make() : '报名中' .text .size(22.sp) diff --git a/pubspec.lock b/pubspec.lock index fdc06e5a..43116429 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -814,6 +814,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.0.3" + palette_generator: + dependency: "direct main" + description: + name: palette_generator + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.3.2" path: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index fe91a73c..b684e7ba 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -109,6 +109,8 @@ dependencies: carousel_slider: ^4.0.0-nullsafety.0 #跳转索引列表 scroll_to_index: ^2.1.1 + #提取图片主色 + palette_generator: ^0.3.2 dev_dependencies: From 2e8615f61000448a4691b1b9c504d6963c5ed18b Mon Sep 17 00:00:00 2001 From: zhangmeng <494089941@qq.com> Date: Sun, 23 Jan 2022 17:27:12 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E7=9B=91=E5=90=AC?= =?UTF-8?q?=E8=BD=AE=E6=92=AD=E5=8F=98=E5=8C=96=EF=BC=8C=E8=A7=A3=E5=86=B3?= =?UTF-8?q?=E8=BD=AE=E6=92=AD=E5=8D=A1=E9=A1=BF=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/home/home_page.dart | 35 +++++++++++++++++++++------------- lib/ui/market/market_page.dart | 4 +--- pubspec.lock | 14 +++++++------- pubspec.yaml | 2 +- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/lib/pages/home/home_page.dart b/lib/pages/home/home_page.dart index e3574593..2136625b 100644 --- a/lib/pages/home/home_page.dart +++ b/lib/pages/home/home_page.dart @@ -26,10 +26,10 @@ import 'package:aku_new_community/widget/others/user_tool.dart'; import 'package:badges/badges.dart'; import 'package:bot_toast/bot_toast.dart'; import 'package:cached_network_image/cached_network_image.dart'; +import 'package:card_swiper/card_swiper.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_easyrefresh/easy_refresh.dart'; -import 'package:flutter_swiper_null_safety/flutter_swiper_null_safety.dart'; import 'package:get/get.dart'; import 'package:jpush_flutter/jpush_flutter.dart'; import 'package:palette_generator/palette_generator.dart'; @@ -58,12 +58,14 @@ class _HomePageState extends State int sysCount = 0; int sum = 0; + int _currentSwiperIndex = 0; + // ActivityItemModel? _activityItemModel; List _activityItemModels = []; List _boardItemModels = []; List _swiperModels = []; - SwiperController _swiperController = SwiperController(); + SwiperController _swiperController = SwiperController(); ValueNotifier _barColor = ValueNotifier(Colors.transparent); @override @@ -80,6 +82,10 @@ class _HomePageState extends State } _scrollController = ScrollController(); _refreshController = EasyRefreshController(); + _swiperController.addListener(() { + //由于先触发监听后,再执行onChangeIndex函数,所以_currentSwiperIndex会比当前index少1,用+1并求余的方式获得真正当前index; + _swiperBarColor((_currentSwiperIndex + 1) % 3); + }); SystemChrome.setSystemUIOverlayStyle( SystemUiOverlayStyle(statusBarColor: Colors.transparent)); } @@ -487,18 +493,9 @@ class _HomePageState extends State aspectRatio: 375 / 160, child: Swiper( key: UniqueKey(), + controller: _swiperController, onIndexChanged: (index) async { - if (_swiperModels.isNotEmpty) { - var color = await PaletteGenerator.fromImageProvider( - CachedNetworkImageProvider( - API.image( - ImgModel.first(_swiperModels[index].voResourcesImgList)), - )); - _barColor.value = - color.dominantColor?.color ?? Colors.transparent; - } else { - _barColor.value = Colors.transparent; - } + _currentSwiperIndex = index; }, itemBuilder: (BuildContext context, int index) { return getSwiperImage(_swiperModels[index]); @@ -536,6 +533,18 @@ class _HomePageState extends State ); } + Future _swiperBarColor(int index) async { + if (_swiperModels.isNotEmpty) { + var color = + await PaletteGenerator.fromImageProvider(CachedNetworkImageProvider( + API.image(ImgModel.first(_swiperModels[index].voResourcesImgList)), + )); + _barColor.value = color.dominantColor?.color ?? Colors.transparent; + } else { + _barColor.value = Colors.transparent; + } + } + Widget getSwiperImage(SwiperModel swiperModel) { return Container( child: FadeInImage.assetNetwork( diff --git a/lib/ui/market/market_page.dart b/lib/ui/market/market_page.dart index 27283089..edbe8983 100644 --- a/lib/ui/market/market_page.dart +++ b/lib/ui/market/market_page.dart @@ -24,14 +24,12 @@ import 'package:aku_new_community/utils/network/base_list_model.dart'; import 'package:aku_new_community/utils/network/net_util.dart'; import 'package:aku_new_community/widget/home/home_sliver_app_bar.dart'; import 'package:aku_new_community/widget/others/rectIndicator.dart'; +import 'package:card_swiper/card_swiper.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_easyrefresh/easy_refresh.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:flutter_swiper_null_safety/flutter_swiper_null_safety.dart'; import 'package:get/get.dart'; import 'package:provider/provider.dart'; -import 'package:velocity_x/velocity_x.dart'; import 'category/new_category_page.dart'; import 'market_home_goods_card.dart'; diff --git a/pubspec.lock b/pubspec.lock index 43116429..d9653a50 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -176,6 +176,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.0.1" + card_swiper: + dependency: "direct main" + description: + name: card_swiper + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.1" carousel_slider: dependency: "direct main" description: @@ -503,13 +510,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.6.0" - flutter_swiper_null_safety: - dependency: "direct main" - description: - name: flutter_swiper_null_safety - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.0.2" flutter_test: dependency: "direct dev" description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index b684e7ba..d75e8ce6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -104,7 +104,7 @@ dependencies: #加载网络图片 cached_network_image: ^3.1.0 #轮播图 - flutter_swiper_null_safety: ^1.0.2 + card_swiper: ^2.0.1 #划动组件 carousel_slider: ^4.0.0-nullsafety.0 #跳转索引列表 From 9a118e2aa0babb54b33968dd91fd17d0fc3f64d0 Mon Sep 17 00:00:00 2001 From: zhangmeng <494089941@qq.com> Date: Sat, 29 Jan 2022 13:38:44 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E5=8F=91=E5=B8=83?= =?UTF-8?q?=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/icons/clock_circle.png | Bin 0 -> 3130 bytes assets/icons/edit.png | Bin 0 -> 478 bytes assets/icons/environment.png | Bin 0 -> 2903 bytes assets/icons/phone_circle.png | Bin 0 -> 1937 bytes assets/icons/reward.png | Bin 0 -> 2308 bytes assets/icons/tag.png | Bin 0 -> 2428 bytes lib/constants/api.dart | 24 + lib/constants/application_objects.dart | 3 +- lib/extensions/color_ext.dart | 11 + lib/gen/assets.gen.dart | 21 + lib/models/task/hall_list_model.dart | 40 ++ lib/models/task/hall_list_model.g.dart | 25 + lib/models/task/my_take_task_list_model.dart | 41 ++ .../task/my_take_task_list_model.g.dart | 25 + lib/models/task/my_task_list_model.dart | 40 ++ lib/models/task/my_task_list_model.g.dart | 25 + lib/ui/service/hall/hall_card.dart | 151 +++++ lib/ui/service/hall/hall_detail_page.dart | 262 ++++++++ lib/ui/service/hall/hall_view.dart | 49 ++ .../my_take_task/my_take_task_card.dart | 165 +++++ .../my_take_task/my_take_task_view.dart | 48 ++ lib/ui/service/my_task/my_task_card.dart | 180 +++++ lib/ui/service/my_task/my_task_view.dart | 47 ++ lib/ui/service/publish_task_page.dart | 614 ++++++++++++++++++ lib/ui/service/task_func.dart | 61 ++ lib/ui/service/task_map.dart | 26 + lib/ui/service/task_page.dart | 91 +++ lib/widget/painter/tab_indicator.dart | 21 + .../painter/tab_indicator_parinter.dart | 27 + 29 files changed, 1996 insertions(+), 1 deletion(-) create mode 100644 assets/icons/clock_circle.png create mode 100644 assets/icons/edit.png create mode 100644 assets/icons/environment.png create mode 100644 assets/icons/phone_circle.png create mode 100644 assets/icons/reward.png create mode 100644 assets/icons/tag.png create mode 100644 lib/extensions/color_ext.dart create mode 100644 lib/models/task/hall_list_model.dart create mode 100644 lib/models/task/hall_list_model.g.dart create mode 100644 lib/models/task/my_take_task_list_model.dart create mode 100644 lib/models/task/my_take_task_list_model.g.dart create mode 100644 lib/models/task/my_task_list_model.dart create mode 100644 lib/models/task/my_task_list_model.g.dart create mode 100644 lib/ui/service/hall/hall_card.dart create mode 100644 lib/ui/service/hall/hall_detail_page.dart create mode 100644 lib/ui/service/hall/hall_view.dart create mode 100644 lib/ui/service/my_take_task/my_take_task_card.dart create mode 100644 lib/ui/service/my_take_task/my_take_task_view.dart create mode 100644 lib/ui/service/my_task/my_task_card.dart create mode 100644 lib/ui/service/my_task/my_task_view.dart create mode 100644 lib/ui/service/publish_task_page.dart create mode 100644 lib/ui/service/task_func.dart create mode 100644 lib/ui/service/task_map.dart create mode 100644 lib/ui/service/task_page.dart create mode 100644 lib/widget/painter/tab_indicator.dart create mode 100644 lib/widget/painter/tab_indicator_parinter.dart diff --git a/assets/icons/clock_circle.png b/assets/icons/clock_circle.png new file mode 100644 index 0000000000000000000000000000000000000000..9d94ffc1fa276744f95182cb086107cc437e3353 GIT binary patch literal 3130 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 literal 0 HcmV?d00001 diff --git a/assets/icons/reward.png b/assets/icons/reward.png new file mode 100644 index 0000000000000000000000000000000000000000..2683a0d1c6040e9dec8dadd99bd042d8a6d02be3 GIT binary patch literal 2308 zcmV+f3H$bmP)fxa&Tdal*# z22)e-Yh$KV7^+Yyqdd=eVQ4}wz#KL)9_FGbG9m84hY39IAZWE-?eFg&EH5t))d}gO z48+sZ(-#9{J_wsl1w;lC2ma7x02^BH9sn!e+cB@c?-#-Z7?OE18%4W&dwZKFVPs+k zn$6~q0rsL+Do|Pr2ufVW1O-Nvy%L|-w9EKcGZM+-+<>SVbYX~w3ly5MB_rQ>cq4D?)%!64K zH=FJ2AAaaRd-39+E+)V3!bYQUDbMo{(lk{nO^r-K%2_FW6;{?#jbIZVB~B^x>c(>a z7NS}W@$Fukc7Olz$MdQt)ncICZeM`mUE=24=rz*p$U5Gc5}-%*5hkhxfE0kU0ZuuF zveJ%ZJjnC8n>TN^)oC$sczAgJHHMVp^0IPw|z{SnlchljJez$$=)~&HN zs?~UE&_$}!V;KijP5>(8mEOc6wvzTre4-LO1-eQLKBS>r#zuTY;$#XoU>b2O&*+s_ zS63##U%!sjd<4BiL+Je7IKy%GfKi zvnrgUQfa9hAtEhu9Io^H61YTMzC%NHn-`TxO!tH&@0-O(k2dP!svU_*Ns{~n zs`ApBvM1iBv;&zKxin`RBlH-a=NN-}{3k{3C^lr(81bzC{di5(1zVr^+@>07tqA3phH z`fn>M$v9xO7=UDdrK6|=HR1;J3>i*imy95-CQyweEucinj8!3~(A4qW$NS6VikD}yD zq!w?ayjQMVi3fv08`xQuMX~3_%Blt!&)Qn&tjfSfvI`fv@)qg-c41*I^}O?V-=}BV z+}U~l=2k|b)0Ylg0pLV+)-E7XJS=OM$ zTkW>E)dqlb9dxbt@ZrN3HjSD`aGl|eqy#p7U^?Iu z2?jDqwWZ5~MpEm9B_)e6g2rM7EUJjB3mka)Kp7|v)M)Uh8sJH_;{Y~%4#^HA8dp*Q zN{uOoY;N;t*NMj|o`9I6eUOA6la)9~{&NqT57Z36g_F2wIX z`shcwF|@a5&OD{KVbziWDQm>Gcn@ z>=5ml-nDDj`p11dq~7U-;e25X_f%VZdtaPJAR9$uIWES5Fl1_t@9*uaQ=qF?uXZk+ zJ9l2kaR)kD&`W_yqg$=h31k5K8(ab#2MU`G8|d=@-0fsq?;ac+9NxKe$K^AxH}Kxv zg2C+R)2A&ogQuZZvv8Y%ivzAE#$Llee){QiHHPX2GWLWnanNM+wL#40N2XEM1JwOq z)NT(Ty@Z7{I&#L8Oc>0?aFISDZ4-vgZsMrjD6K^RXWVcMz%y+vE-r4516G#->>1u* zL1PV6qOP?Ixz~+`OPi%f>bldajIQEws`Y@om+Ta3BfTIy_8W~9;J>H?tZp30;IseA zKxS)S>5@o&%Sc>l7rL?QM6k(gY&~q;oGad~8+Gq6kwa>cA+=tuiEE-6Ov#elYqA|upgLb=NNy*ZZAC`i}#t2tZx*`UsO~aO$QcCifG5s&Mw*ECqAUo0j z1MfAP7xOS=-X6Kemdj9aUufG}7de*_H<48zr}yqTPXm%?g7gaUU{g&<6SdbJ4Nz91 zBHIDbLjY(qB8%i1dD%CIH0_@n5-F=vmu5T*d$!lLPNGKRKivx#UOss6;5&5!I+g#( z=I7^I(D4~Knkg^?N8^XF?`t_7`xg_yX7o;`-|xZE_u9L=-~D-gy|4b436WLvr_Sh% e&ghJOu=HQqUP+w{0)HX^0000`8(synNh8 z&Z+LYYSE-D$)tb)DuCd9-#T4Yr%pF%%(Y$HwO!j^#U4F+6!T-2Xx3b@?eFhrQC01x zX_`&wfVHD2ibgrMBWuT#I3DGbNwu1$qp~QfpN$#6c=2LvE@)Q@jG(Hb*iF(j2cX8J zsmb_FN3yIjlZkwbhFZ^U;6ay?gik`SZ!FcO~YE zOhI*4RytKx)jXC4=bNUnHcguZ-(^_}=*WW>vo^s^2@W(Sip;R8n$OnPS8(QN*83uJ z1x8Rvt39}$7jT*&kcx&wt-}p8O$!v~xLxBq?jk~#5#~pa(EzkF@108rwzIQ?l9}wo z**rmt(P27BKw-pqP9jA^O5z^V?i&|TaTxcOOidUfAI&47r2-=;c)N#B79JNT>AZ1( z7$Jg?ZEuWdmZl#(Q&?o|xP;dq9UaZYury!<#q@*o`MhhGem01TrX?L_#Kw~kd4V;k z13*&g_xstbXDW;OyIv%I999Rah ze0zI)ACZunVm*oD_>>_*AR4-z`1u+Cu^>1AJU-m0Gry!<`$L$=hbQX1_!k%WAx{0LG-GT zyW9f`o|9&oS&ieRup&X-&!VUkzP#;8NTHAhO5-SA8?`cDTGuz{y#O`3%5Ty?$wM17 z$zy_kHnw)*5zBAgx^9J~gPb)5#)DIhkC!;e2bK=RshdO#O0P~V z>PC7M!CAf5%2uz}?QU=bb2dh@y_e6Q)yF~^7TQHqF<)C-`!=fU&g8`76Qc0FNsha3 ztJjH|K+4)c6SjSf4SA|5hal9bRLF`gIeFo{wY9ZkJ^@%~b#?UtC^r)@VO<%Cl0<<= z(*Usb)09(=W1CL3Bw|kV;UoYt?EtSGd(|J#2J)haE(?sHSW~(46%RyRSr>&Dh)M}Sw13RoKimz(*aRksP(0QLQoRD8S3Laz%c1uc>pHrm~o1=|ulRznG zO*Mfa4yQ3{&3J5Q^+8<#5~ZK#!+D_20@i|>p4GA$lL0#?Y$zr`1H$l*&U8?m^UDJ| zwF#Zq{aF)D8kljkzP^4m57azhltt_`65po;oK^5A17`x;7FZFuWbj0V2q1U z>YtT{1LD^?!WuKD#v*kqS=J73^m;#@1?ntdoiI{#+A9gGG;TESedCo)KL@jcsu!{d zqT9+XAGLJK`7-QZ!JLhtqdYHq=KwVi7#ZfU-Gig;^n*3#jy2(n6^wSapm`e`tUSpV z31wR8`@SZ(=s6COKkf&0cwSKRfYE+}!!K2#x6W#TYvHRyj0#!LJ1iXM`=oy2YDfb9?)Ti-Mwkbj<_lcAVn}0LX>Dtf$j?L`WJX zBgv+V{lrHMUP}|M;60<+5HLnQ_o*1ywR0RznAd|4WF5r%Xq8+i!FdwJ_9a1`3z!G@ zM@n$k_C-0kxe(Qbr~!#07j2k2P$9fVR0O9r*pD4}DhaD0QKi8)@6%IKJ*RSkOuGBU z7ncTgZeT4qG)7cVpAjQ4D1;`0Gu+lF%E&X4el?09BPYKMuO)LL#~QwvK=5-zyU)79 z!Q%5TzkK~Epe_VV!6D^_1g8;_#KJavoudc0cswS!5k|YuC?p;jtBZ~^l}h(unRxOAjG}S%C()EOLBC2x0bOA>j0K_M^RK^N z2qo;Qc-Hj2Gf?hEC)NgyDt|B%9u}F;wHG8YilC_*dTGRwm36u z$-^_FFrIG(v1|51CZPP{?|XX-2SxkjwR?i=B66VqzI9+u9_lBVv9BpZ>gRE$C1lb! zdwYk=041+B3oz8&;Kq#`L%`aI9Fe#OhY@mpOqScoe&5``zcf(BEb!MBg6np>{Le<8 z`|M5Bl==cH4MK!CEcTWRinh>y$N0#Nu$bBt5e)j{`iHJ@0NmjA?c0Y>o;+D9DB8mR z_Cs(TfJ1$4U|m79B6}5@@c`QI@Y%CxrMUuI%Kw=N4(pI(L~Vm}wXD+_+`W7E%0SVU u_D3y(+uYic-@O3p^;Lqpwrjh#<=dan!tW&~ROj^o0000 "/user/search/search"; } +class _Task { + ///查询所有的任务发布信息 + String get hallList => '/user/taskRelease/list'; + + ///查询我的任务发布信息 + String get myTask => '/user/taskRelease/myList'; + + ///查询我的任务接单信息 + String get myTakeTask => '/user/taskRelease/myOrder'; + + ///发布任务 + String get publish => '/user/taskRelease/insert'; + + ///取消任务 + String get cancel => '/user/taskRelease/cancel'; + + ///接取任务 + String get take => '/user/taskRelease/access'; + + ///完成任务 + String get finish => '/user/taskRelease/finish'; +} + class _Manager { _Facility facility = _Facility(); + _Task task = _Task(); ///获取业委会列表 String get commiteeStaff => '/ownersCommittee/findAll'; diff --git a/lib/constants/application_objects.dart b/lib/constants/application_objects.dart index 98fb6484..acc2159d 100644 --- a/lib/constants/application_objects.dart +++ b/lib/constants/application_objects.dart @@ -31,6 +31,7 @@ import 'package:aku_new_community/ui/manager/questionnaire/questionnaire_page.da import 'package:aku_new_community/ui/profile/car/car_manage_page.dart'; import 'package:aku_new_community/ui/profile/car_parking/car_parking_page.dart'; import 'package:aku_new_community/ui/profile/house/house_owners_page.dart'; +import 'package:aku_new_community/ui/service/task_page.dart'; import 'package:aku_new_community/widget/others/user_tool.dart'; import 'package:flutter/material.dart'; @@ -100,7 +101,7 @@ List appObjects = [ AO('住房说明', R.ASSETS_ICONS_FUNC_ZFSM_PNG, () => HouseIntroducePage()), AO('智慧养老', Assets.icons.provideAged.path, () => OldAgeSupportPageSimple()), AO('周边服务', Assets.icons.nearbyService.path, null), - AO('小蜜蜂任务', Assets.icons.beeTask.path, null), + AO('小蜜蜂任务', Assets.icons.beeTask.path, () => TaskPage()), AO('自营商城', Assets.icons.shoppingMall.path, null), AO('邻家宠物', Assets.icons.nearbyPet.path, null), AO('共享停车', Assets.icons.sharePark.path, null), diff --git a/lib/extensions/color_ext.dart b/lib/extensions/color_ext.dart new file mode 100644 index 00000000..71ed41b3 --- /dev/null +++ b/lib/extensions/color_ext.dart @@ -0,0 +1,11 @@ +import 'package:flutter/material.dart'; + +extension ColorExt on Color { + ///获得此颜色的互补色 + Color get complementary { + var r = ~this.red; + var g = ~this.green; + var b = ~this.blue; + return Color.fromARGB(this.alpha, r, g, b); + } +} diff --git a/lib/gen/assets.gen.dart b/lib/gen/assets.gen.dart index bf7d1c42..79475669 100644 --- a/lib/gen/assets.gen.dart +++ b/lib/gen/assets.gen.dart @@ -190,6 +190,10 @@ class $AssetsIconsGen { /// File path: assets/icons/change.png AssetGenImage get change => const AssetGenImage('assets/icons/change.png'); + /// File path: assets/icons/clock_circle.png + AssetGenImage get clockCircle => + const AssetGenImage('assets/icons/clock_circle.png'); + /// File path: assets/icons/clock_success.png AssetGenImage get clockSuccess => const AssetGenImage('assets/icons/clock_success.png'); @@ -246,6 +250,13 @@ class $AssetsIconsGen { AssetGenImage get deviceAlarm => const AssetGenImage('assets/icons/device_alarm.png'); + /// File path: assets/icons/edit.png + AssetGenImage get edit => const AssetGenImage('assets/icons/edit.png'); + + /// File path: assets/icons/environment.png + AssetGenImage get environment => + const AssetGenImage('assets/icons/environment.png'); + /// File path: assets/icons/examine.png AssetGenImage get examine => const AssetGenImage('assets/icons/examine.png'); @@ -663,6 +674,10 @@ class $AssetsIconsGen { /// File path: assets/icons/phone.png AssetGenImage get phone => const AssetGenImage('assets/icons/phone.png'); + /// File path: assets/icons/phone_circle.png + AssetGenImage get phoneCircle => + const AssetGenImage('assets/icons/phone_circle.png'); + /// File path: assets/icons/projection_screen.png AssetGenImage get projectionScreen => const AssetGenImage('assets/icons/projection_screen.png'); @@ -682,6 +697,9 @@ class $AssetsIconsGen { /// File path: assets/icons/report.png AssetGenImage get report => const AssetGenImage('assets/icons/report.png'); + /// File path: assets/icons/reward.png + AssetGenImage get reward => const AssetGenImage('assets/icons/reward.png'); + /// File path: assets/icons/second_hand.png AssetGenImage get secondHand => const AssetGenImage('assets/icons/second_hand.png'); @@ -791,6 +809,9 @@ class $AssetsIconsGen { AssetGenImage get tabbarUserNo => const AssetGenImage('assets/icons/tabbar_user_no.png'); + /// File path: assets/icons/tag.png + AssetGenImage get tag => const AssetGenImage('assets/icons/tag.png'); + /// File path: assets/icons/test_kingcion.png AssetGenImage get testKingcion => const AssetGenImage('assets/icons/test_kingcion.png'); diff --git a/lib/models/task/hall_list_model.dart b/lib/models/task/hall_list_model.dart new file mode 100644 index 00000000..f9a0dade --- /dev/null +++ b/lib/models/task/hall_list_model.dart @@ -0,0 +1,40 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'hall_list_model.g.dart'; + +@JsonSerializable() +class HallListModel { + final int id; + final String title; + final int status; + final int type; + final int sex; + final int serviceObject; + final String content; + final String appointmentDate; + final String appointmentAddress; + final int rewardType; + final int reward; + final int createType; + final String? createName; + final String createDate; + factory HallListModel.fromJson(Map json) => + _$HallListModelFromJson(json); + + const HallListModel({ + required this.id, + required this.title, + required this.status, + required this.type, + required this.sex, + required this.serviceObject, + required this.content, + required this.appointmentDate, + required this.appointmentAddress, + required this.rewardType, + required this.reward, + required this.createType, + this.createName, + required this.createDate, + }); +} diff --git a/lib/models/task/hall_list_model.g.dart b/lib/models/task/hall_list_model.g.dart new file mode 100644 index 00000000..2681aa43 --- /dev/null +++ b/lib/models/task/hall_list_model.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'hall_list_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +HallListModel _$HallListModelFromJson(Map json) => + HallListModel( + id: json['id'] as int, + title: json['title'] as String, + status: json['status'] as int, + type: json['type'] as int, + sex: json['sex'] as int, + serviceObject: json['serviceObject'] as int, + content: json['content'] as String, + appointmentDate: json['appointmentDate'] as String, + appointmentAddress: json['appointmentAddress'] as String, + rewardType: json['rewardType'] as int, + reward: json['reward'] as int, + createType: json['createType'] as int, + createName: json['createName'] as String?, + createDate: json['createDate'] as String, + ); diff --git a/lib/models/task/my_take_task_list_model.dart b/lib/models/task/my_take_task_list_model.dart new file mode 100644 index 00000000..db0f61d2 --- /dev/null +++ b/lib/models/task/my_take_task_list_model.dart @@ -0,0 +1,41 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'my_take_task_list_model.g.dart'; + +@JsonSerializable() +class MyTakeTaskListModel { + final int id; + final String title; + final int status; + final int type; + final int sex; + final int serviceObject; + final String content; + final String appointmentDate; + final String appointmentAddress; + final int rewardType; + final int reward; + final int createType; + final String? createName; + final String createDate; + + factory MyTakeTaskListModel.fromJson(Map json) => + _$MyTakeTaskListModelFromJson(json); + + const MyTakeTaskListModel({ + required this.id, + required this.title, + required this.status, + required this.type, + required this.sex, + required this.serviceObject, + required this.content, + required this.appointmentDate, + required this.appointmentAddress, + required this.rewardType, + required this.reward, + required this.createType, + this.createName, + required this.createDate, + }); +} diff --git a/lib/models/task/my_take_task_list_model.g.dart b/lib/models/task/my_take_task_list_model.g.dart new file mode 100644 index 00000000..e49a1b7e --- /dev/null +++ b/lib/models/task/my_take_task_list_model.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'my_take_task_list_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +MyTakeTaskListModel _$MyTakeTaskListModelFromJson(Map json) => + MyTakeTaskListModel( + id: json['id'] as int, + title: json['title'] as String, + status: json['status'] as int, + type: json['type'] as int, + sex: json['sex'] as int, + serviceObject: json['serviceObject'] as int, + content: json['content'] as String, + appointmentDate: json['appointmentDate'] as String, + appointmentAddress: json['appointmentAddress'] as String, + rewardType: json['rewardType'] as int, + reward: json['reward'] as int, + createType: json['createType'] as int, + createName: json['createName'] as String?, + createDate: json['createDate'] as String, + ); diff --git a/lib/models/task/my_task_list_model.dart b/lib/models/task/my_task_list_model.dart new file mode 100644 index 00000000..86e9af60 --- /dev/null +++ b/lib/models/task/my_task_list_model.dart @@ -0,0 +1,40 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'my_task_list_model.g.dart'; + +@JsonSerializable() +class MyTaskListModel { + final int id; + final String title; + final int status; + final int type; + final int sex; + final int serviceObject; + final String content; + final String appointmentDate; + final String appointmentAddress; + final int rewardType; + final int reward; + final int createType; + final String? createName; + final String createDate; + factory MyTaskListModel.fromJson(Map json) => + _$MyTaskListModelFromJson(json); + + const MyTaskListModel({ + required this.id, + required this.title, + required this.status, + required this.type, + required this.sex, + required this.serviceObject, + required this.content, + required this.appointmentDate, + required this.appointmentAddress, + required this.rewardType, + required this.reward, + required this.createType, + this.createName, + required this.createDate, + }); +} diff --git a/lib/models/task/my_task_list_model.g.dart b/lib/models/task/my_task_list_model.g.dart new file mode 100644 index 00000000..9c1b1af3 --- /dev/null +++ b/lib/models/task/my_task_list_model.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'my_task_list_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +MyTaskListModel _$MyTaskListModelFromJson(Map json) => + MyTaskListModel( + id: json['id'] as int, + title: json['title'] as String, + status: json['status'] as int, + type: json['type'] as int, + sex: json['sex'] as int, + serviceObject: json['serviceObject'] as int, + content: json['content'] as String, + appointmentDate: json['appointmentDate'] as String, + appointmentAddress: json['appointmentAddress'] as String, + rewardType: json['rewardType'] as int, + reward: json['reward'] as int, + createType: json['createType'] as int, + createName: json['createName'] as String?, + createDate: json['createDate'] as String, + ); diff --git a/lib/ui/service/hall/hall_card.dart b/lib/ui/service/hall/hall_card.dart new file mode 100644 index 00000000..8e7c31b8 --- /dev/null +++ b/lib/ui/service/hall/hall_card.dart @@ -0,0 +1,151 @@ +import 'package:aku_new_community/gen/assets.gen.dart'; +import 'package:aku_new_community/models/task/hall_list_model.dart'; +import 'package:aku_new_community/ui/service/hall/hall_detail_page.dart'; +import 'package:aku_new_community/ui/service/task_map.dart'; +import 'package:aku_new_community/widget/buttons/card_bottom_button.dart'; +import 'package:flustars/flustars.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:velocity_x/velocity_x.dart'; + +class HallCard extends StatelessWidget { + final HallListModel model; + final VoidCallback refresh; + + const HallCard({Key? key, required this.model, required this.refresh}) + : super(key: key); + + @override + Widget build(BuildContext context) { + var head = Row( + children: [ + Container( + width: 100.w, + height: 50.w, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Color(0xFFFFF7E6), + borderRadius: BorderRadius.circular(8.w), + ), + child: '#${TaskMap.typeToString[model.type]}' + .text + .size(28.sp) + .color(Color(0xFFFA8C16)) + .make(), + ), + Spacer(), + Assets.icons.intergral.image(width: 24.w, height: 24.w), + 8.w.widthBox, + '${model.reward}'.text.size(32.sp).color(Colors.red).make() + ], + ); + return GestureDetector( + onTap: () { + Get.to(() => HallDetailPage(model: model)); + }, + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8.w), + ), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + children: [ + head, + 34.w.heightBox, + Row( + children: [ + Assets.icons.clockCircle.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '${DateUtil.formatDateStr(model.appointmentDate)}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + 20.w.heightBox, + Row( + children: [ + Assets.icons.environment.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '${model.appointmentAddress}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + 34.w.heightBox, + Container( + width: 638.w, + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.03), + borderRadius: BorderRadius.circular(8.w)), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + '#${TaskMap.typeToString[model.type]}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.85)) + .make(), + 16.w.heightBox, + model.content.text + .size(28.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + ), + 40.w.heightBox, + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + 40.w.heightBox, + Row( + children: [ + Spacer(), + CardBottomButton.yellow(text: '领取任务', onPressed: () {}), + ], + ), + ], + ), + ], + ), + ), + ); + } + + Widget _cardBottom(int) { + switch (int) { + case 1: + case 2: + return Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + 40.w.heightBox, + CardBottomButton.white(text: '取消订单', onPressed: () {}), + CardBottomButton.yellow(text: '确认完成', onPressed: () {}), + ], + ); + case 4: + return Column( + children: [ + 32.w.heightBox, + Row( + children: [ + '客户取消:暂不需要该服务'.text.size(24.sp).color(Colors.red).make(), + Spacer(), + ], + ), + ], + ); + default: + return SizedBox.shrink(); + } + } +} diff --git a/lib/ui/service/hall/hall_detail_page.dart b/lib/ui/service/hall/hall_detail_page.dart new file mode 100644 index 00000000..cd9462f4 --- /dev/null +++ b/lib/ui/service/hall/hall_detail_page.dart @@ -0,0 +1,262 @@ +import 'package:aku_new_community/gen/assets.gen.dart'; +import 'package:aku_new_community/models/task/hall_list_model.dart'; +import 'package:aku_new_community/ui/service/task_map.dart'; +import 'package:aku_new_community/widget/bee_divider.dart'; +import 'package:aku_new_community/widget/bee_scaffold.dart'; +import 'package:flustars/flustars.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:velocity_x/velocity_x.dart'; + +class HallDetailPage extends StatefulWidget { + final HallListModel model; + + const HallDetailPage({Key? key, required this.model}) : super(key: key); + + @override + _HallDetailPageState createState() => _HallDetailPageState(); +} + +class _HallDetailPageState extends State { + @override + Widget build(BuildContext context) { + return BeeScaffold( + extendBody: true, + title: '', + body: Stack( + children: [ + Column( + children: [ + Container( + width: double.infinity, + height: 380.w, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: widget.model.status == 4 + ? [ + Colors.white, + Color(0xFFADACAC), + ] + : [ + Color(0xFFFFB737), + Color(0xFFFFD361), + ]), + ), + child: Column( + children: [ + 150.w.heightBox, + Row( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: 32.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + '${TaskMap.detailStatusToString[widget.model.status]}' + .text + .size(40.sp) + .color(Colors.black) + .bold + .make(), + '${TaskMap.subStatus[widget.model.status]}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + ], + ), + ), + Spacer(), + Padding( + padding: EdgeInsets.only(right: 32.w), + child: MaterialButton( + color: Colors.white, + elevation: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.w), + ), + onPressed: () {}, + child: '取消订单' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ), + ) + ], + ), + ], + ), + ), + Flexible( + child: Container( + width: double.infinity, + color: Color(0xFFE5E5E5), + ), + ), + ], + ), + Positioned( + top: 280.w, + left: 32.w, + right: 32.w, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + _content(), + 24.w.heightBox, + _taskInfo(), + ], + )), + ], + ), + ); + } + + Widget _taskInfo() { + return Container( + width: 686.w, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8.w), + ), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + children: [ + Row( + children: [ + '任务信息'.text.size(28.sp).color(Colors.black).bold.make(), + Spacer(), + ], + ), + 24.w.heightBox, + BeeDivider.horizontal(), + 24.w.heightBox, + Row( + children: [ + '创建时间' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + Spacer(), + '${DateUtil.formatDateStr(widget.model.createDate)}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.45)) + .make() + ], + ), + ], + ), + ); + } + + Widget _content() { + var head = Row( + children: [ + Container( + width: 100.w, + height: 50.w, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Color(0xFFFFF7E6), + borderRadius: BorderRadius.circular(8.w), + ), + child: '#${TaskMap.typeToString[widget.model.type]}' + .text + .size(28.sp) + .color(Color(0xFFFA8C16)) + .make(), + ), + Spacer(), + Assets.icons.intergral.image(width: 24.w, height: 24.w), + 8.w.widthBox, + '${widget.model.reward}'.text.size(32.sp).color(Colors.red).make() + ], + ); + return Container( + width: 686.w, + height: 500.w, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8.w), + ), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + children: [ + head, + 34.w.heightBox, + Row( + children: [ + Assets.icons.clockCircle.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '${DateUtil.formatDateStr(widget.model.appointmentDate)}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + 20.w.heightBox, + Row( + children: [ + Assets.icons.environment.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '${widget.model.appointmentAddress}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + 34.w.heightBox, + Container( + width: 638.w, + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.03), + borderRadius: BorderRadius.circular(8.w)), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + '#${TaskMap.typeToString[widget.model.type]}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.85)) + .make(), + 16.w.heightBox, + widget.model.content.text + .size(28.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + ), + 32.w.heightBox, + BeeDivider.horizontal(), + 32.w.heightBox, + Row( + children: [ + Assets.icons.reward.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '报酬' + .text + .size(26.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + Spacer(), + '¥${widget.model.reward}' + .text + .size(32.sp) + .color(Colors.red) + .make(), + ], + ), + ], + ), + ); + } +} diff --git a/lib/ui/service/hall/hall_view.dart b/lib/ui/service/hall/hall_view.dart new file mode 100644 index 00000000..efe39722 --- /dev/null +++ b/lib/ui/service/hall/hall_view.dart @@ -0,0 +1,49 @@ +import 'package:aku_new_community/constants/api.dart'; +import 'package:aku_new_community/models/task/hall_list_model.dart'; +import 'package:aku_new_community/pages/things_page/widget/bee_list_view.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_easyrefresh/easy_refresh.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:velocity_x/src/extensions/num_ext.dart'; + +import 'hall_card.dart'; + +class HallView extends StatefulWidget { + const HallView({Key? key}) : super(key: key); + + @override + _HallViewState createState() => _HallViewState(); +} + +class _HallViewState extends State { + EasyRefreshController _refreshController = EasyRefreshController(); + + @override + void dispose() { + _refreshController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BeeListView( + path: API.manager.task.hallList, + controller: _refreshController, + extraParams: {}, + convert: (json) => + json.tableList!.map((e) => HallListModel.fromJson(e)).toList(), + builder: (models) { + return ListView.separated( + padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 24.w), + itemBuilder: (context, index) { + return HallCard( + model: models[index], + refresh: () => _refreshController.callRefresh()); + }, + separatorBuilder: (_, __) { + return 24.w.heightBox; + }, + itemCount: models.length); + }); + } +} diff --git a/lib/ui/service/my_take_task/my_take_task_card.dart b/lib/ui/service/my_take_task/my_take_task_card.dart new file mode 100644 index 00000000..dbf96c3e --- /dev/null +++ b/lib/ui/service/my_take_task/my_take_task_card.dart @@ -0,0 +1,165 @@ +import 'package:aku_new_community/gen/assets.gen.dart'; +import 'package:aku_new_community/models/task/hall_list_model.dart'; +import 'package:aku_new_community/ui/service/task_map.dart'; +import 'package:aku_new_community/widget/bee_divider.dart'; +import 'package:aku_new_community/widget/buttons/card_bottom_button.dart'; +import 'package:flustars/flustars.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:velocity_x/velocity_x.dart'; + +class MyTakeTaskCard extends StatelessWidget { + final HallListModel model; + final VoidCallback refresh; + + const MyTakeTaskCard({Key? key, required this.model, required this.refresh}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + decoration: BoxDecoration( + color: Color(0xFFFFF7E6), + borderRadius: BorderRadius.circular(8.w), + ), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + children: [ + Row( + children: [ + '接单时间 ${DateUtil.formatDateStr(model.createDate)}' + .text + .size(26.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + Spacer(), + '${TaskMap.statusToString[model.status]}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.85)) + .bold + .make() + ], + ), + 20.w.heightBox, + BeeDivider.horizontal(), + 34.w.heightBox, + Row( + children: [ + Assets.icons.clockCircle.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '${DateUtil.formatDateStr(model.appointmentDate)}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + 20.w.heightBox, + Row( + children: [ + Assets.icons.environment.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '${model.appointmentAddress}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + 34.w.heightBox, + Container( + width: 638.w, + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.03), + borderRadius: BorderRadius.circular(8.w)), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + '#${TaskMap.typeToString[model.type]}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.85)) + .make(), + 16.w.heightBox, + model.content.text + .size(28.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + ), + 40.w.heightBox, + Row( + children: [ + Spacer(), + RichText( + text: TextSpan( + text: '实付 ', + children: model.rewardType == 2 + ? [ + WidgetSpan( + child: Assets.icons.intergral + .image(width: 24.w, height: 24.w), + ), + model.reward + .toString() + .textSpan + .size(32.sp) + .color(Colors.red) + .make(), + ] + : [ + '¥ ${model.reward}' + .toString() + .textSpan + .size(32.sp) + .color(Colors.red) + .make(), + ], + style: TextStyle( + color: Colors.black.withOpacity(0.65), fontSize: 24.sp), + ), + ) + ], + ), + _cardBottom(model.status), + ], + ), + ); + } + + Widget _cardBottom(int) { + switch (int) { + case 1: + case 2: + return Column( + children: [ + 40.w.heightBox, + Row( + children: [ + CardBottomButton.white(text: '取消订单', onPressed: () {}), + CardBottomButton.yellow(text: '确认完成', onPressed: () {}), + ], + ) + ], + ); + case 4: + return Column( + children: [ + 32.w.heightBox, + Row( + children: [ + '客户取消:暂不需要该服务'.text.size(24.sp).color(Colors.red).make(), + Spacer(), + ], + ), + ], + ); + default: + return SizedBox.shrink(); + } + } +} diff --git a/lib/ui/service/my_take_task/my_take_task_view.dart b/lib/ui/service/my_take_task/my_take_task_view.dart new file mode 100644 index 00000000..c9a34867 --- /dev/null +++ b/lib/ui/service/my_take_task/my_take_task_view.dart @@ -0,0 +1,48 @@ +import 'package:aku_new_community/constants/api.dart'; +import 'package:aku_new_community/models/task/my_take_task_list_model.dart'; +import 'package:aku_new_community/pages/things_page/widget/bee_list_view.dart'; +import 'package:aku_new_community/ui/service/my_take_task/my_take_task_card.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_easyrefresh/easy_refresh.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:velocity_x/velocity_x.dart'; + +class MyTakeTaskView extends StatefulWidget { + const MyTakeTaskView({Key? key}) : super(key: key); + + @override + _MyTakeTaskViewState createState() => _MyTakeTaskViewState(); +} + +class _MyTakeTaskViewState extends State { + EasyRefreshController _refreshController = EasyRefreshController(); + + @override + void dispose() { + _refreshController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BeeListView( + path: API.manager.task.myTakeTask, + controller: _refreshController, + convert: (json) => json.tableList! + .map((e) => MyTakeTaskListModel.fromJson(e)) + .toList(), + builder: (models) { + return ListView.separated( + padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 24.w), + itemBuilder: (context, index) { + return MyTakeTaskCard( + model: models[index], + refresh: () => _refreshController.callRefresh()); + }, + separatorBuilder: (_, __) { + return 24.w.heightBox; + }, + itemCount: models.length); + }); + } +} diff --git a/lib/ui/service/my_task/my_task_card.dart b/lib/ui/service/my_task/my_task_card.dart new file mode 100644 index 00000000..5f662aa5 --- /dev/null +++ b/lib/ui/service/my_task/my_task_card.dart @@ -0,0 +1,180 @@ +import 'package:aku_new_community/gen/assets.gen.dart'; +import 'package:aku_new_community/models/task/my_task_list_model.dart'; +import 'package:aku_new_community/ui/service/task_map.dart'; +import 'package:aku_new_community/widget/buttons/card_bottom_button.dart'; +import 'package:flustars/flustars.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:velocity_x/velocity_x.dart'; + +class MyTaskCard extends StatelessWidget { + final MyTaskListModel model; + final VoidCallback refresh; + + const MyTaskCard({Key? key, required this.model, required this.refresh}) + : super(key: key); + + @override + Widget build(BuildContext context) { + var head = Row( + children: [ + Container( + width: 100.w, + height: 50.w, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Color(0xFFFFF7E6), + borderRadius: BorderRadius.circular(8.w), + ), + child: '#${TaskMap.typeToString[model.type]}' + .text + .size(28.sp) + .color(Color(0xFFFA8C16)) + .make(), + ), + Spacer(), + '${TaskMap.statusToString[model.status]}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.85)) + .bold + .make() + ], + ); + return Container( + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8.w), + ), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + children: [ + head, + 34.w.heightBox, + Row( + children: [ + Assets.icons.clockCircle.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '${DateUtil.formatDateStr(model.appointmentDate)}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + 20.w.heightBox, + Row( + children: [ + Assets.icons.environment.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '${model.appointmentAddress}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + 34.w.heightBox, + Container( + width: 638.w, + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.03), + borderRadius: BorderRadius.circular(8.w)), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + '#${TaskMap.typeToString[model.type]}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.85)) + .make(), + 16.w.heightBox, + model.content.text + .size(28.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + ), + 40.w.heightBox, + Row( + children: [ + Spacer(), + RichText( + text: TextSpan( + text: '实付 ', + children: model.rewardType == 2 + ? [ + WidgetSpan( + child: Assets.icons.intergral + .image(width: 24.w, height: 24.w), + ), + model.reward + .toString() + .textSpan + .size(32.sp) + .color(Colors.red) + .make(), + ] + : [ + '¥ ${model.reward}' + .toString() + .textSpan + .size(32.sp) + .color(Colors.red) + .make(), + ], + style: TextStyle( + color: Colors.black.withOpacity(0.65), fontSize: 24.sp), + ), + ) + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + 40.w.heightBox, + Row( + children: [ + Spacer(), + CardBottomButton.yellow(text: '取消订单', onPressed: () {}), + ], + ), + ], + ), + ], + ), + ); + } + + Widget _cardBottom(int) { + switch (int) { + case 1: + case 2: + return Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + 40.w.heightBox, + CardBottomButton.white(text: '取消订单', onPressed: () {}), + CardBottomButton.yellow(text: '确认完成', onPressed: () {}), + ], + ); + case 4: + return Column( + children: [ + 32.w.heightBox, + Row( + children: [ + '客户取消:暂不需要该服务'.text.size(24.sp).color(Colors.red).make(), + Spacer(), + ], + ), + ], + ); + default: + return SizedBox.shrink(); + } + } +} diff --git a/lib/ui/service/my_task/my_task_view.dart b/lib/ui/service/my_task/my_task_view.dart new file mode 100644 index 00000000..056fadb8 --- /dev/null +++ b/lib/ui/service/my_task/my_task_view.dart @@ -0,0 +1,47 @@ +import 'package:aku_new_community/constants/api.dart'; +import 'package:aku_new_community/models/task/my_task_list_model.dart'; +import 'package:aku_new_community/pages/things_page/widget/bee_list_view.dart'; +import 'package:aku_new_community/ui/service/my_task/my_task_card.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_easyrefresh/easy_refresh.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:velocity_x/velocity_x.dart'; + +class MyTaskView extends StatefulWidget { + const MyTaskView({Key? key}) : super(key: key); + + @override + _MyTaskViewState createState() => _MyTaskViewState(); +} + +class _MyTaskViewState extends State { + EasyRefreshController _refreshController = EasyRefreshController(); + + @override + void dispose() { + _refreshController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BeeListView( + path: API.manager.task.myTask, + controller: _refreshController, + convert: (json) => + json.tableList!.map((e) => MyTaskListModel.fromJson(e)).toList(), + builder: (models) { + return ListView.separated( + padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 24.w), + itemBuilder: (context, index) { + return MyTaskCard( + model: models[index], + refresh: () => _refreshController.callRefresh()); + }, + separatorBuilder: (_, __) { + return 24.w.heightBox; + }, + itemCount: models.length); + }); + } +} diff --git a/lib/ui/service/publish_task_page.dart b/lib/ui/service/publish_task_page.dart new file mode 100644 index 00000000..935f3ccf --- /dev/null +++ b/lib/ui/service/publish_task_page.dart @@ -0,0 +1,614 @@ +import 'package:aku_new_community/base/base_style.dart'; +import 'package:aku_new_community/ui/service/task_func.dart'; +import 'package:aku_new_community/utils/headers.dart'; +import 'package:aku_new_community/widget/bee_divider.dart'; +import 'package:aku_new_community/widget/bee_scaffold.dart'; +import 'package:aku_new_community/widget/picker/bee_date_picker.dart'; +import 'package:aku_new_community/widget/picker/bee_picker_box.dart'; +import 'package:bot_toast/bot_toast.dart'; +import 'package:flustars/flustars.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:velocity_x/velocity_x.dart'; + +class PublishTaskPage extends StatefulWidget { + const PublishTaskPage({Key? key}) : super(key: key); + + @override + _PublishTaskPageState createState() => _PublishTaskPageState(); +} + +class _PublishTaskPageState extends State { + List _types = ['跑腿', '代驾', '装修', '陪玩', '家政', '维修', '搬家', '家教', '其他']; + int _type = 0; + List _sexStr = ['男', '女', '不限']; + int _sex = 0; + int _service = 0; + List _serviceObject = ['住户', '物业', '不限']; + List _rewardTypes = ['赏金', '积分']; + int _rewardType = 0; + DateTime? _appointDate = DateTime.now(); + TextEditingController _titleController = TextEditingController(); + TextEditingController _contentController = TextEditingController(); + TextEditingController _addressController = TextEditingController(); + TextEditingController _rewardController = TextEditingController(); + + @override + void dispose() { + _titleController.dispose(); + _contentController.dispose(); + _addressController.dispose(); + _rewardController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BeeScaffold( + title: '发布任务', + body: SafeArea( + child: ListView( + padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 24.w), + children: [ + Container( + width: double.infinity, + padding: EdgeInsets.only(left: 32.w, right: 32.w, bottom: 32.w), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16.w), + ), + child: Column( + children: [ + Row( + children: [ + SizedBox( + width: 170.w, + child: '标题' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + ), + Expanded( + child: TextField( + controller: _titleController, + onChanged: (text) => setState(() {}), + autofocus: false, + decoration: InputDecoration( + hintStyle: TextStyle( + fontSize: 28.sp, + color: Colors.black.withOpacity(0.25), + ), + border: InputBorder.none, + hintText: '请输入', + ), + ), + ), + ], + ), + BeeDivider.horizontal(), + 32.w.heightBox, + GestureDetector( + onTap: () async { + _type = 1; + showModalBottomSheet( + context: context, + builder: (context) { + return BeePickerBox( + onPressed: () { + Get.back(); + print(_type); + setState(() {}); + }, + child: CupertinoPicker.builder( + itemExtent: 60.w, + childCount: _types.length, + onSelectedItemChanged: (index) { + _type = index + 1; + }, + itemBuilder: (context, index) { + return Center( + child: _types[index] + .text + .size(32.sp) + .isIntrinsic + .color(Colors.black.withOpacity(0.25)) + .make(), + ); + })); + }, + ); + }, + child: Material( + color: Colors.transparent, + child: Row( + children: [ + SizedBox( + width: 170.w, + child: '分类' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + ), + '${_type == 0 ? '请选择分类' : _types[_type - 1]}' + .text + .size(28.sp) + .color(Colors.black + .withOpacity(_type == 0 ? 0.25 : 0.85)) + .make(), + Spacer(), + Icon( + CupertinoIcons.chevron_right, + size: 24.w, + ), + ], + ), + ), + ), + 32.w.heightBox, + BeeDivider.horizontal(), + 32.w.heightBox, + GestureDetector( + onTap: () async { + await Get.bottomSheet(CupertinoActionSheet( + cancelButton: CupertinoActionSheetAction( + onPressed: () { + Get.back(); + }, + child: '取消' + .text + .size(28.sp) + .isIntrinsic + .color(Colors.black.withOpacity(0.85)) + .make()), + actions: [ + CupertinoActionSheetAction( + onPressed: () { + _sex = 1; + Get.back(); + setState(() {}); + }, + child: '男' + .text + .size(28.sp) + .isIntrinsic + .color(Colors.black.withOpacity(0.85)) + .make()), + CupertinoActionSheetAction( + onPressed: () { + _sex = 2; + Get.back(); + setState(() {}); + }, + child: '女' + .text + .size(28.sp) + .isIntrinsic + .color(Colors.black.withOpacity(0.85)) + .make()), + CupertinoActionSheetAction( + onPressed: () { + _sex = 3; + Get.back(); + setState(() {}); + }, + child: '不限' + .text + .size(28.sp) + .isIntrinsic + .color(Colors.black.withOpacity(0.85)) + .make()) + ], + )); + }, + child: Material( + color: Colors.transparent, + child: Row( + children: [ + SizedBox( + width: 170.w, + child: '性别' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + ), + '${_sex == 0 ? '请选择性别' : _sexStr[_sex - 1]}' + .text + .size(28.sp) + .color(Colors.black + .withOpacity(_sex == 0 ? 0.25 : 0.85)) + .make(), + Spacer(), + Icon( + CupertinoIcons.chevron_right, + size: 24.w, + ), + ], + ), + ), + ), + 32.w.heightBox, + BeeDivider.horizontal(), + 32.w.heightBox, + GestureDetector( + onTap: () async { + await Get.bottomSheet(CupertinoActionSheet( + cancelButton: CupertinoActionSheetAction( + onPressed: () { + Get.back(); + }, + child: '取消' + .text + .size(28.sp) + .isIntrinsic + .color(Colors.black.withOpacity(0.85)) + .make()), + actions: [ + CupertinoActionSheetAction( + onPressed: () { + _service = 1; + Get.back(); + setState(() {}); + }, + child: '住户' + .text + .size(28.sp) + .isIntrinsic + .color(Colors.black.withOpacity(0.85)) + .make()), + CupertinoActionSheetAction( + onPressed: () { + _service = 2; + Get.back(); + setState(() {}); + }, + child: '业主' + .text + .size(28.sp) + .isIntrinsic + .color(Colors.black.withOpacity(0.85)) + .make()), + CupertinoActionSheetAction( + onPressed: () { + _service = 3; + Get.back(); + setState(() {}); + }, + child: '不限' + .text + .size(28.sp) + .isIntrinsic + .color(Colors.black.withOpacity(0.85)) + .make()) + ], + )); + }, + child: Material( + color: Colors.transparent, + child: Row( + children: [ + SizedBox( + width: 170.w, + child: '服务人员' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + ), + '${_service == 0 ? '请选择服务人员' : _serviceObject[_service - 1]}' + .text + .size(28.sp) + .color(Colors.black + .withOpacity(_service == 0 ? 0.25 : 0.85)) + .make(), + Spacer(), + Icon( + CupertinoIcons.chevron_right, + size: 24.w, + ), + ], + ), + ), + ), + 32.w.heightBox, + BeeDivider.horizontal(), + 32.w.heightBox, + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + '任务内容' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + ], + ), + 32.w.heightBox, + Container( + width: double.infinity, + padding: EdgeInsets.symmetric(horizontal: 24.w), + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.06), + borderRadius: BorderRadius.circular(16.w)), + child: TextField( + controller: _contentController, + autofocus: false, + onChanged: (text) => setState(() {}), + minLines: 5, + maxLength: 200, + maxLines: 20, + decoration: InputDecoration( + border: InputBorder.none, + ), + ), + ), + ], + ), + ), + 32.w.heightBox, + Container( + width: double.infinity, + padding: EdgeInsets.only( + left: 32.w, right: 32.w, bottom: 32.w, top: 32.w), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16.w), + ), + child: Column( + children: [ + GestureDetector( + onTap: () async { + _appointDate = + await BeeDatePicker.timePicker(DateTime.now()); + }, + child: Material( + color: Colors.transparent, + child: Row( + children: [ + SizedBox( + width: 170.w, + child: '预约时间' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + ), + '${DateUtil.formatDate(_appointDate)}' + .text + .size(28.sp) + .color(Colors.black + .withOpacity(_type == 0 ? 0.25 : 0.85)) + .make(), + Spacer(), + Icon( + CupertinoIcons.chevron_right, + size: 24.w, + ), + ], + ), + ), + ), + 32.w.heightBox, + BeeDivider.horizontal(), + 32.w.heightBox, + Row( + children: [ + SizedBox( + width: 170.w, + child: '预约地址' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + ), + '${S.of(context)!.tempPlotName}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.85)) + .make(), + '|' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.25)) + .make(), + Expanded( + child: TextField( + autofocus: false, + controller: _addressController, + onChanged: (text) => setState(() {}), + decoration: InputDecoration( + contentPadding: EdgeInsets.zero, + isDense: true, + border: InputBorder.none, + hintText: '请输入', + hintStyle: TextStyle( + fontSize: 28.sp, + color: Colors.black.withOpacity(0.25), + )), + ), + ), + ], + ), + 32.w.heightBox, + BeeDivider.horizontal(), + 32.w.heightBox, + GestureDetector( + onTap: () async { + await Get.bottomSheet(CupertinoActionSheet( + cancelButton: CupertinoActionSheetAction( + onPressed: () { + Get.back(); + }, + child: '取消' + .text + .size(28.sp) + .isIntrinsic + .color(Colors.black.withOpacity(0.85)) + .make()), + actions: [ + CupertinoActionSheetAction( + onPressed: () { + _rewardType = 1; + Get.back(); + setState(() {}); + }, + child: '赏金' + .text + .size(28.sp) + .isIntrinsic + .color(Colors.black.withOpacity(0.85)) + .make()), + CupertinoActionSheetAction( + onPressed: () { + _rewardType = 2; + Get.back(); + setState(() {}); + }, + child: '积分' + .text + .size(28.sp) + .isIntrinsic + .color(Colors.black.withOpacity(0.85)) + .make()), + ], + )); + }, + child: Material( + color: Colors.transparent, + child: Row( + children: [ + SizedBox( + width: 170.w, + child: '报酬类型' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + ), + '${_rewardType == 0 ? '请选择报酬类型' : _rewardTypes[_rewardType - 1]}' + .text + .size(28.sp) + .color(Colors.black + .withOpacity(_rewardType == 0 ? 0.25 : 0.85)) + .make(), + Spacer(), + Icon( + CupertinoIcons.chevron_right, + size: 24.w, + ), + ], + ), + ), + ), + 32.w.heightBox, + BeeDivider.horizontal(), + 32.w.heightBox, + Row( + children: [ + SizedBox( + width: 170.w, + child: '${_rewardType == 1 ? '赏金金额' : '积分数量'}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + ), + Expanded( + child: TextField( + textAlign: TextAlign.end, + onChanged: (text) => setState(() {}), + autofocus: false, + controller: _rewardController, + style: TextStyle(color: Colors.red), + decoration: InputDecoration( + contentPadding: EdgeInsets.zero, + isDense: true, + border: InputBorder.none, + hintText: '请输入', + hintStyle: TextStyle( + fontSize: 28.sp, + color: Colors.black.withOpacity(0.25), + )), + ), + ), + '${_rewardType == 1 ? '元' : ''}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.85)) + .make(), + ], + ) + ], + ), + ), + ], + ), + ), + bottomNavi: Padding( + padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 32.w), + child: MaterialButton( + elevation: 0, + height: 93.w, + disabledColor: Colors.black.withOpacity(0.06), + disabledTextColor: Colors.black.withOpacity(0.25), + textColor: Colors.black.withOpacity(0.85), + shape: + RoundedRectangleBorder(borderRadius: BorderRadius.circular(65.w)), + color: kPrimaryColor, + onPressed: !canTap + ? null + : () async { + var cancel = BotToast.showLoading(); + var re = await TaskFunc.publish( + title: _titleController.text, + taskType: _type, + taskSex: _sex, + serviceObject: _service, + taskContent: _contentController.text, + taskDate: _appointDate.toString(), + taskAddress: _addressController.text, + rewardType: _rewardType, + reward: _rewardController.text); + if (re) { + Get.back(); + } + cancel(); + }, + child: '确认发布'.text.size(32.sp).bold.make(), + ), + ), + ); + } + + bool get canTap { + if (_titleController.text.isEmpty) { + return false; + } + if (_type == 0) { + return false; + } + if (_rewardType == 0) { + return false; + } + if (_sex == 0) { + return false; + } + if (_appointDate == null) { + return false; + } + if (_contentController.text.isEmpty) { + return false; + } + if (_addressController.text.isEmpty) { + return false; + } + if (_rewardController.text.isEmpty) { + return false; + } + return true; + } +} diff --git a/lib/ui/service/task_func.dart b/lib/ui/service/task_func.dart new file mode 100644 index 00000000..d302af30 --- /dev/null +++ b/lib/ui/service/task_func.dart @@ -0,0 +1,61 @@ +import 'package:aku_new_community/constants/api.dart'; +import 'package:aku_new_community/utils/network/net_util.dart'; + +class TaskFunc { + ///确认发布 + static Future publish( + {required String title, + required int taskType, + required int taskSex, + required int serviceObject, + required String taskContent, + required String taskDate, + required String taskAddress, + required int rewardType, + required String reward}) async { + var base = await NetUtil().post(API.manager.task.publish, params: { + 'title': title, + 'taskType': taskType, + 'taskSex': taskSex, + 'serviceObject': serviceObject, + 'taskContent': taskContent, + 'taskDate': taskDate, + 'taskAddress': taskAddress, + 'rewardType': rewardType, + 'reward': int.parse(reward), + }); + return base.status ?? false; + } + + ///取消任务 + static Future cancel({ + required int taskId, + }) async { + var base = await NetUtil().post(API.manager.task.cancel, params: { + 'taskId': taskId, + }); + return base.status ?? false; + } + + ///接取任务 + + static Future take({ + required int taskId, + }) async { + var base = await NetUtil().post(API.manager.task.take, params: { + 'taskId': taskId, + }); + return base.status ?? false; + } + + ///完成任务 + + static Future finish({ + required int taskId, + }) async { + var base = await NetUtil().post(API.manager.task.finish, params: { + 'taskId': taskId, + }); + return base.status ?? false; + } +} diff --git a/lib/ui/service/task_map.dart b/lib/ui/service/task_map.dart new file mode 100644 index 00000000..740d206b --- /dev/null +++ b/lib/ui/service/task_map.dart @@ -0,0 +1,26 @@ +class TaskMap { + static Map statusToString = { + 1: '未接单', + 2: '待处理', + 3: '已完成', + 4: '已取消' + }; + + static Map typeToString = {1: '跑腿', 2: '代驾', 3: '装修', 4: '陪玩'}; + static Map serviceObject = {1: '住户', 2: '物业', 3: '不限'}; + + static Map rewardType = {1: '赏金', 2: '积分'}; + static Map detailStatusToString = { + 1: '已发布', + 2: '待处理', + 3: '已完成', + 4: '已取消' + }; + + static Map subStatus = { + 1: '请耐心等待帮手领取任务', + 2: '帮手正在为您服务中', + 3: '帮手已完成任务', + 4: '该任务已取消' + }; +} diff --git a/lib/ui/service/task_page.dart b/lib/ui/service/task_page.dart new file mode 100644 index 00000000..042c7fa5 --- /dev/null +++ b/lib/ui/service/task_page.dart @@ -0,0 +1,91 @@ +import 'package:aku_new_community/ui/service/hall/hall_view.dart'; +import 'package:aku_new_community/ui/service/my_take_task/my_take_task_view.dart'; +import 'package:aku_new_community/ui/service/my_task/my_task_view.dart'; +import 'package:aku_new_community/ui/service/publish_task_page.dart'; +import 'package:aku_new_community/widget/bee_scaffold.dart'; +import 'package:aku_new_community/widget/painter/tab_indicator.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:velocity_x/velocity_x.dart'; + +class TaskPage extends StatefulWidget { + const TaskPage({Key? key}) : super(key: key); + + @override + _TaskPageState createState() => _TaskPageState(); +} + +class _TaskPageState extends State with TickerProviderStateMixin { + late TabController _tabController; + + List _tabs = ['大厅', '我服务的', '我发布的']; + + @override + void initState() { + _tabController = TabController(length: _tabs.length, vsync: this); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return BeeScaffold( + title: '', + actions: [ + IconButton( + onPressed: () { + Get.to(() => PublishTaskPage()); + }, + icon: Icon( + Icons.add_circle_outline, + size: 40.w, + color: Colors.black, + )) + ], + appBarBottom: PreferredSize( + preferredSize: Size.fromHeight(88.w), + child: Row( + children: [ + ..._tabs + .mapIndexed( + (currentValue, index) => _tabCard(currentValue, index)) + .toList(), + ], + )), + body: SafeArea( + child: TabBarView(controller: _tabController, children: [ + HallView(), + MyTakeTaskView(), + MyTaskView(), + ])), + ); + } + + Widget _tabCard(String title, int index) { + var select = index == _tabController.index; + return GestureDetector( + onTap: () { + _tabController.animateTo(index); + setState(() {}); + }, + child: Material( + color: Colors.transparent, + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + title.text + .size(select ? 36.sp : 32.sp) + .fontWeight(select ? FontWeight.bold : FontWeight.normal) + .color(Colors.black.withOpacity(select ? 0.85 : 0.65)) + .make(), + 8.w.heightBox, + select ? TabIndicator() : 10.w.heightBox, + ], + ), + ), + ), + ); + } +} diff --git a/lib/widget/painter/tab_indicator.dart b/lib/widget/painter/tab_indicator.dart new file mode 100644 index 00000000..9ca9cfaa --- /dev/null +++ b/lib/widget/painter/tab_indicator.dart @@ -0,0 +1,21 @@ +import 'package:aku_new_community/widget/painter/tab_indicator_parinter.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class TabIndicator extends StatelessWidget { + final double? width; + final double? height; + + const TabIndicator({Key? key, this.width, this.height}) : super(key: key); + + @override + Widget build(BuildContext context) { + return SizedBox( + width: width ?? 40.w, + height: height ?? 10.w, + child: CustomPaint( + painter: TabIndicatorPainter(), + ), + ); + } +} diff --git a/lib/widget/painter/tab_indicator_parinter.dart b/lib/widget/painter/tab_indicator_parinter.dart new file mode 100644 index 00000000..634f67ab --- /dev/null +++ b/lib/widget/painter/tab_indicator_parinter.dart @@ -0,0 +1,27 @@ +import 'package:aku_new_community/base/base_style.dart'; +import 'package:flutter/material.dart'; + +class TabIndicatorPainter extends CustomPainter { + @override + void paint(Canvas canvas, Size size) { + Paint paint = Paint() + ..color = kPrimaryColor + ..strokeCap = StrokeCap.round + ..strokeWidth = 2 + ..style = PaintingStyle.stroke; + Path path = Path(); + path.moveTo(0, 0); + path.quadraticBezierTo(size.width / 2, size.height, size.width, 0); + canvas.drawPath(path, paint); + } + + @override + bool shouldRebuildSemantics(covariant CustomPainter oldDelegate) { + return false; + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) { + return false; + } +} From 1b62948817c27d41c9c9b9a8ff754dd623031e1b Mon Sep 17 00:00:00 2001 From: zhangmeng <494089941@qq.com> Date: Mon, 31 Jan 2022 00:36:07 +0800 Subject: [PATCH 4/4] fix bugs --- lib/ui/service/hall/hall_card.dart | 29 +- lib/ui/service/hall/hall_detail_page.dart | 38 +-- .../my_take_task/my_take_task_card.dart | 237 +++++++++------- .../my_take_task_detail_page.dart | 268 ++++++++++++++++++ lib/ui/service/my_task/my_task_card.dart | 204 +++++++------ .../service/my_task/my_task_detail_page.dart | 268 ++++++++++++++++++ lib/ui/service/publish_task_page.dart | 2 +- lib/ui/service/task_func.dart | 6 +- 8 files changed, 829 insertions(+), 223 deletions(-) create mode 100644 lib/ui/service/my_take_task/my_take_task_detail_page.dart create mode 100644 lib/ui/service/my_task/my_task_detail_page.dart diff --git a/lib/ui/service/hall/hall_card.dart b/lib/ui/service/hall/hall_card.dart index 8e7c31b8..a829ef3b 100644 --- a/lib/ui/service/hall/hall_card.dart +++ b/lib/ui/service/hall/hall_card.dart @@ -9,6 +9,8 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:velocity_x/velocity_x.dart'; +import '../task_func.dart'; + class HallCard extends StatelessWidget { final HallListModel model; final VoidCallback refresh; @@ -109,7 +111,14 @@ class HallCard extends StatelessWidget { Row( children: [ Spacer(), - CardBottomButton.yellow(text: '领取任务', onPressed: () {}), + CardBottomButton.yellow( + text: '领取任务', + onPressed: () async { + var re = await TaskFunc.take(taskId: model.id); + if (re) { + refresh(); + } + }), ], ), ], @@ -128,8 +137,22 @@ class HallCard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.end, children: [ 40.w.heightBox, - CardBottomButton.white(text: '取消订单', onPressed: () {}), - CardBottomButton.yellow(text: '确认完成', onPressed: () {}), + CardBottomButton.white( + text: '取消订单', + onPressed: () async { + var re = await TaskFunc.cancel(taskId: model.id); + if (re) { + refresh(); + } + }), + CardBottomButton.yellow( + text: '确认完成', + onPressed: () async { + var re = await TaskFunc.finish(taskId: model.id); + if (re) { + refresh(); + } + }), ], ); case 4: diff --git a/lib/ui/service/hall/hall_detail_page.dart b/lib/ui/service/hall/hall_detail_page.dart index cd9462f4..c8c549b0 100644 --- a/lib/ui/service/hall/hall_detail_page.dart +++ b/lib/ui/service/hall/hall_detail_page.dart @@ -69,22 +69,28 @@ class _HallDetailPageState extends State { ), ), Spacer(), - Padding( - padding: EdgeInsets.only(right: 32.w), - child: MaterialButton( - color: Colors.white, - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.w), - ), - onPressed: () {}, - child: '取消订单' - .text - .size(24.sp) - .color(Colors.black.withOpacity(0.65)) - .make(), - ), - ) + // Padding( + // padding: EdgeInsets.only(right: 32.w), + // child: MaterialButton( + // color: Colors.white, + // elevation: 0, + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(8.w), + // ), + // onPressed: () async { + // var re = await TaskFunc.cancel( + // taskId: widget.model.id); + // if (re) { + // Get.back(); + // } + // }, + // child: '取消订单' + // .text + // .size(24.sp) + // .color(Colors.black.withOpacity(0.65)) + // .make(), + // ), + // ) ], ), ], diff --git a/lib/ui/service/my_take_task/my_take_task_card.dart b/lib/ui/service/my_take_task/my_take_task_card.dart index dbf96c3e..a2a20fbd 100644 --- a/lib/ui/service/my_take_task/my_take_task_card.dart +++ b/lib/ui/service/my_take_task/my_take_task_card.dart @@ -1,15 +1,20 @@ +import 'package:aku_new_community/extensions/widget_list_ext.dart'; import 'package:aku_new_community/gen/assets.gen.dart'; -import 'package:aku_new_community/models/task/hall_list_model.dart'; +import 'package:aku_new_community/models/task/my_take_task_list_model.dart'; +import 'package:aku_new_community/ui/service/my_take_task/my_take_task_detail_page.dart'; import 'package:aku_new_community/ui/service/task_map.dart'; import 'package:aku_new_community/widget/bee_divider.dart'; import 'package:aku_new_community/widget/buttons/card_bottom_button.dart'; import 'package:flustars/flustars.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; import 'package:velocity_x/velocity_x.dart'; +import '../task_func.dart'; + class MyTakeTaskCard extends StatelessWidget { - final HallListModel model; + final MyTakeTaskListModel model; final VoidCallback refresh; const MyTakeTaskCard({Key? key, required this.model, required this.refresh}) @@ -17,116 +22,121 @@ class MyTakeTaskCard extends StatelessWidget { @override Widget build(BuildContext context) { - return Container( - width: double.infinity, - decoration: BoxDecoration( - color: Color(0xFFFFF7E6), - borderRadius: BorderRadius.circular(8.w), - ), - padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), - child: Column( - children: [ - Row( - children: [ - '接单时间 ${DateUtil.formatDateStr(model.createDate)}' - .text - .size(26.sp) - .color(Colors.black.withOpacity(0.45)) - .make(), - Spacer(), - '${TaskMap.statusToString[model.status]}' - .text - .size(28.sp) - .color(Colors.black.withOpacity(0.85)) - .bold - .make() - ], - ), - 20.w.heightBox, - BeeDivider.horizontal(), - 34.w.heightBox, - Row( - children: [ - Assets.icons.clockCircle.image(width: 36.w, height: 36.w), - 24.w.widthBox, - '${DateUtil.formatDateStr(model.appointmentDate)}' - .text - .size(24.sp) - .color(Colors.black.withOpacity(0.65)) - .make(), - ], - ), - 20.w.heightBox, - Row( - children: [ - Assets.icons.environment.image(width: 36.w, height: 36.w), - 24.w.widthBox, - '${model.appointmentAddress}' - .text - .size(24.sp) - .color(Colors.black.withOpacity(0.65)) - .make(), - ], - ), - 34.w.heightBox, - Container( - width: 638.w, - decoration: BoxDecoration( - color: Colors.black.withOpacity(0.03), - borderRadius: BorderRadius.circular(8.w)), - padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + return GestureDetector( + onTap: () { + Get.to(() => MyTakeTaskDetailPage(model: model)); + }, + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8.w), + ), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + children: [ + Row( children: [ - '#${TaskMap.typeToString[model.type]}' + '接单时间 ${DateUtil.formatDateStr(model.createDate)}' + .text + .size(26.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + Spacer(), + '${TaskMap.statusToString[model.status]}' .text .size(28.sp) .color(Colors.black.withOpacity(0.85)) + .bold + .make() + ], + ), + 20.w.heightBox, + BeeDivider.horizontal(), + 34.w.heightBox, + Row( + children: [ + Assets.icons.clockCircle.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '${DateUtil.formatDateStr(model.appointmentDate)}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.65)) .make(), - 16.w.heightBox, - model.content.text - .size(28.sp) + ], + ), + 20.w.heightBox, + Row( + children: [ + Assets.icons.environment.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '${model.appointmentAddress}' + .text + .size(24.sp) .color(Colors.black.withOpacity(0.65)) .make(), ], ), - ), - 40.w.heightBox, - Row( - children: [ - Spacer(), - RichText( - text: TextSpan( - text: '实付 ', - children: model.rewardType == 2 - ? [ - WidgetSpan( - child: Assets.icons.intergral - .image(width: 24.w, height: 24.w), - ), - model.reward - .toString() - .textSpan - .size(32.sp) - .color(Colors.red) - .make(), - ] - : [ - '¥ ${model.reward}' - .toString() - .textSpan - .size(32.sp) - .color(Colors.red) - .make(), - ], - style: TextStyle( - color: Colors.black.withOpacity(0.65), fontSize: 24.sp), - ), - ) - ], - ), - _cardBottom(model.status), - ], + 34.w.heightBox, + Container( + width: 638.w, + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.03), + borderRadius: BorderRadius.circular(8.w)), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + '#${TaskMap.typeToString[model.type]}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.85)) + .make(), + 16.w.heightBox, + model.content.text + .size(28.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + ), + 40.w.heightBox, + Row( + children: [ + Spacer(), + RichText( + text: TextSpan( + text: '实付 ', + children: model.rewardType == 2 + ? [ + WidgetSpan( + child: Assets.icons.intergral + .image(width: 24.w, height: 24.w), + ), + model.reward + .toString() + .textSpan + .size(32.sp) + .color(Colors.red) + .make(), + ] + : [ + '¥ ${model.reward}' + .toString() + .textSpan + .size(32.sp) + .color(Colors.red) + .make(), + ], + style: TextStyle( + color: Colors.black.withOpacity(0.65), fontSize: 24.sp), + ), + ) + ], + ), + _cardBottom(model.status), + ], + ), ), ); } @@ -139,10 +149,25 @@ class MyTakeTaskCard extends StatelessWidget { children: [ 40.w.heightBox, Row( + mainAxisAlignment: MainAxisAlignment.end, children: [ - CardBottomButton.white(text: '取消订单', onPressed: () {}), - CardBottomButton.yellow(text: '确认完成', onPressed: () {}), - ], + // CardBottomButton.white( + // text: '取消订单', + // onPressed: () async { + // var re = await TaskFunc.cancel(taskId: model.id); + // if (re) { + // refresh(); + // } + // }), + CardBottomButton.yellow( + text: '确认完成', + onPressed: () async { + var re = await TaskFunc.finish(taskId: model.id); + if (re) { + refresh(); + } + }), + ].sepWidget(separate: 10.w.widthBox), ) ], ); diff --git a/lib/ui/service/my_take_task/my_take_task_detail_page.dart b/lib/ui/service/my_take_task/my_take_task_detail_page.dart new file mode 100644 index 00000000..bf50cc9a --- /dev/null +++ b/lib/ui/service/my_take_task/my_take_task_detail_page.dart @@ -0,0 +1,268 @@ +import 'package:aku_new_community/gen/assets.gen.dart'; +import 'package:aku_new_community/models/task/my_take_task_list_model.dart'; +import 'package:aku_new_community/ui/service/task_map.dart'; +import 'package:aku_new_community/widget/bee_divider.dart'; +import 'package:aku_new_community/widget/bee_scaffold.dart'; +import 'package:flustars/flustars.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:velocity_x/velocity_x.dart'; + +class MyTakeTaskDetailPage extends StatefulWidget { + final MyTakeTaskListModel model; + + const MyTakeTaskDetailPage({Key? key, required this.model}) : super(key: key); + + @override + _MyTakeTaskDetailPageState createState() => _MyTakeTaskDetailPageState(); +} + +class _MyTakeTaskDetailPageState extends State { + @override + Widget build(BuildContext context) { + return BeeScaffold( + extendBody: true, + title: '', + body: Stack( + children: [ + Column( + children: [ + Container( + width: double.infinity, + height: 380.w, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: widget.model.status == 4 + ? [ + Colors.white, + Color(0xFFADACAC), + ] + : [ + Color(0xFFFFB737), + Color(0xFFFFD361), + ]), + ), + child: Column( + children: [ + 150.w.heightBox, + Row( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: 32.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + '${TaskMap.detailStatusToString[widget.model.status]}' + .text + .size(40.sp) + .color(Colors.black) + .bold + .make(), + '${TaskMap.subStatus[widget.model.status]}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + ], + ), + ), + Spacer(), + // Padding( + // padding: EdgeInsets.only(right: 32.w), + // child: MaterialButton( + // color: Colors.white, + // elevation: 0, + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(8.w), + // ), + // onPressed: () async { + // var re = await TaskFunc.cancel( + // taskId: widget.model.id); + // if (re) { + // Get.back(); + // } + // }, + // child: '取消订单' + // .text + // .size(24.sp) + // .color(Colors.black.withOpacity(0.65)) + // .make(), + // ), + // ) + ], + ), + ], + ), + ), + Flexible( + child: Container( + width: double.infinity, + color: Color(0xFFE5E5E5), + ), + ), + ], + ), + Positioned( + top: 280.w, + left: 32.w, + right: 32.w, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + _content(), + 24.w.heightBox, + _taskInfo(), + ], + )), + ], + ), + ); + } + + Widget _taskInfo() { + return Container( + width: 686.w, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8.w), + ), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + children: [ + Row( + children: [ + '任务信息'.text.size(28.sp).color(Colors.black).bold.make(), + Spacer(), + ], + ), + 24.w.heightBox, + BeeDivider.horizontal(), + 24.w.heightBox, + Row( + children: [ + '创建时间' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + Spacer(), + '${DateUtil.formatDateStr(widget.model.createDate)}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.45)) + .make() + ], + ), + ], + ), + ); + } + + Widget _content() { + var head = Row( + children: [ + Container( + width: 100.w, + height: 50.w, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Color(0xFFFFF7E6), + borderRadius: BorderRadius.circular(8.w), + ), + child: '#${TaskMap.typeToString[widget.model.type]}' + .text + .size(28.sp) + .color(Color(0xFFFA8C16)) + .make(), + ), + Spacer(), + Assets.icons.intergral.image(width: 24.w, height: 24.w), + 8.w.widthBox, + '${widget.model.reward}'.text.size(32.sp).color(Colors.red).make() + ], + ); + return Container( + width: 686.w, + height: 500.w, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8.w), + ), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + children: [ + head, + 34.w.heightBox, + Row( + children: [ + Assets.icons.clockCircle.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '${DateUtil.formatDateStr(widget.model.appointmentDate)}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + 20.w.heightBox, + Row( + children: [ + Assets.icons.environment.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '${widget.model.appointmentAddress}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + 34.w.heightBox, + Container( + width: 638.w, + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.03), + borderRadius: BorderRadius.circular(8.w)), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + '#${TaskMap.typeToString[widget.model.type]}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.85)) + .make(), + 16.w.heightBox, + widget.model.content.text + .size(28.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + ), + 32.w.heightBox, + BeeDivider.horizontal(), + 32.w.heightBox, + Row( + children: [ + Assets.icons.reward.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '报酬' + .text + .size(26.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + Spacer(), + '¥${widget.model.reward}' + .text + .size(32.sp) + .color(Colors.red) + .make(), + ], + ), + ], + ), + ); + } +} diff --git a/lib/ui/service/my_task/my_task_card.dart b/lib/ui/service/my_task/my_task_card.dart index 5f662aa5..21a77f8d 100644 --- a/lib/ui/service/my_task/my_task_card.dart +++ b/lib/ui/service/my_task/my_task_card.dart @@ -1,12 +1,16 @@ import 'package:aku_new_community/gen/assets.gen.dart'; import 'package:aku_new_community/models/task/my_task_list_model.dart'; +import 'package:aku_new_community/ui/service/my_task/my_task_detail_page.dart'; import 'package:aku_new_community/ui/service/task_map.dart'; import 'package:aku_new_community/widget/buttons/card_bottom_button.dart'; import 'package:flustars/flustars.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; import 'package:velocity_x/velocity_x.dart'; +import '../task_func.dart'; + class MyTaskCard extends StatelessWidget { final MyTaskListModel model; final VoidCallback refresh; @@ -41,110 +45,122 @@ class MyTaskCard extends StatelessWidget { .make() ], ); - return Container( - width: double.infinity, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8.w), - ), - padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), - child: Column( - children: [ - head, - 34.w.heightBox, - Row( - children: [ - Assets.icons.clockCircle.image(width: 36.w, height: 36.w), - 24.w.widthBox, - '${DateUtil.formatDateStr(model.appointmentDate)}' - .text - .size(24.sp) - .color(Colors.black.withOpacity(0.65)) - .make(), - ], - ), - 20.w.heightBox, - Row( - children: [ - Assets.icons.environment.image(width: 36.w, height: 36.w), - 24.w.widthBox, - '${model.appointmentAddress}' - .text - .size(24.sp) - .color(Colors.black.withOpacity(0.65)) - .make(), - ], - ), - 34.w.heightBox, - Container( - width: 638.w, - decoration: BoxDecoration( - color: Colors.black.withOpacity(0.03), - borderRadius: BorderRadius.circular(8.w)), - padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + return GestureDetector( + onTap: () { + Get.to(() => MyTaskDetailPage(model: model)); + }, + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8.w), + ), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + children: [ + head, + 34.w.heightBox, + Row( children: [ - '#${TaskMap.typeToString[model.type]}' + Assets.icons.clockCircle.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '${DateUtil.formatDateStr(model.appointmentDate)}' .text - .size(28.sp) - .color(Colors.black.withOpacity(0.85)) + .size(24.sp) + .color(Colors.black.withOpacity(0.65)) .make(), - 16.w.heightBox, - model.content.text - .size(28.sp) + ], + ), + 20.w.heightBox, + Row( + children: [ + Assets.icons.environment.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '${model.appointmentAddress}' + .text + .size(24.sp) .color(Colors.black.withOpacity(0.65)) .make(), ], ), - ), - 40.w.heightBox, - Row( - children: [ - Spacer(), - RichText( - text: TextSpan( - text: '实付 ', - children: model.rewardType == 2 - ? [ - WidgetSpan( - child: Assets.icons.intergral - .image(width: 24.w, height: 24.w), - ), - model.reward - .toString() - .textSpan - .size(32.sp) - .color(Colors.red) - .make(), - ] - : [ - '¥ ${model.reward}' - .toString() - .textSpan - .size(32.sp) - .color(Colors.red) - .make(), - ], - style: TextStyle( - color: Colors.black.withOpacity(0.65), fontSize: 24.sp), - ), - ) - ], - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - 40.w.heightBox, - Row( + 34.w.heightBox, + Container( + width: 638.w, + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.03), + borderRadius: BorderRadius.circular(8.w)), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Spacer(), - CardBottomButton.yellow(text: '取消订单', onPressed: () {}), + '#${TaskMap.typeToString[model.type]}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.85)) + .make(), + 16.w.heightBox, + model.content.text + .size(28.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), ], ), - ], - ), - ], + ), + 40.w.heightBox, + Row( + children: [ + Spacer(), + RichText( + text: TextSpan( + text: '实付 ', + children: model.rewardType == 2 + ? [ + WidgetSpan( + child: Assets.icons.intergral + .image(width: 24.w, height: 24.w), + ), + model.reward + .toString() + .textSpan + .size(32.sp) + .color(Colors.red) + .make(), + ] + : [ + '¥ ${model.reward}' + .toString() + .textSpan + .size(32.sp) + .color(Colors.red) + .make(), + ], + style: TextStyle( + color: Colors.black.withOpacity(0.65), fontSize: 24.sp), + ), + ) + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + 40.w.heightBox, + Row( + children: [ + Spacer(), + CardBottomButton.yellow( + text: '取消订单', + onPressed: () async { + var re = await TaskFunc.cancel(taskId: model.id); + if (re) { + refresh(); + } + }), + ], + ), + ], + ), + ], + ), ), ); } diff --git a/lib/ui/service/my_task/my_task_detail_page.dart b/lib/ui/service/my_task/my_task_detail_page.dart new file mode 100644 index 00000000..627882a6 --- /dev/null +++ b/lib/ui/service/my_task/my_task_detail_page.dart @@ -0,0 +1,268 @@ +import 'package:aku_new_community/gen/assets.gen.dart'; +import 'package:aku_new_community/models/task/my_task_list_model.dart'; +import 'package:aku_new_community/ui/service/task_map.dart'; +import 'package:aku_new_community/widget/bee_divider.dart'; +import 'package:aku_new_community/widget/bee_scaffold.dart'; +import 'package:flustars/flustars.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:velocity_x/velocity_x.dart'; + +class MyTaskDetailPage extends StatefulWidget { + final MyTaskListModel model; + + const MyTaskDetailPage({Key? key, required this.model}) : super(key: key); + + @override + _MyTaskDetailPageState createState() => _MyTaskDetailPageState(); +} + +class _MyTaskDetailPageState extends State { + @override + Widget build(BuildContext context) { + return BeeScaffold( + extendBody: true, + title: '', + body: Stack( + children: [ + Column( + children: [ + Container( + width: double.infinity, + height: 380.w, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: widget.model.status == 4 + ? [ + Colors.white, + Color(0xFFADACAC), + ] + : [ + Color(0xFFFFB737), + Color(0xFFFFD361), + ]), + ), + child: Column( + children: [ + 150.w.heightBox, + Row( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: 32.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + '${TaskMap.detailStatusToString[widget.model.status]}' + .text + .size(40.sp) + .color(Colors.black) + .bold + .make(), + '${TaskMap.subStatus[widget.model.status]}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + ], + ), + ), + Spacer(), + // Padding( + // padding: EdgeInsets.only(right: 32.w), + // child: MaterialButton( + // color: Colors.white, + // elevation: 0, + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(8.w), + // ), + // onPressed: () async { + // var re = await TaskFunc.cancel( + // taskId: widget.model.id); + // if (re) { + // Get.back(); + // } + // }, + // child: '取消订单' + // .text + // .size(24.sp) + // .color(Colors.black.withOpacity(0.65)) + // .make(), + // ), + // ) + ], + ), + ], + ), + ), + Flexible( + child: Container( + width: double.infinity, + color: Color(0xFFE5E5E5), + ), + ), + ], + ), + Positioned( + top: 280.w, + left: 32.w, + right: 32.w, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + _content(), + 24.w.heightBox, + _taskInfo(), + ], + )), + ], + ), + ); + } + + Widget _taskInfo() { + return Container( + width: 686.w, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8.w), + ), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + children: [ + Row( + children: [ + '任务信息'.text.size(28.sp).color(Colors.black).bold.make(), + Spacer(), + ], + ), + 24.w.heightBox, + BeeDivider.horizontal(), + 24.w.heightBox, + Row( + children: [ + '创建时间' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + Spacer(), + '${DateUtil.formatDateStr(widget.model.createDate)}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.45)) + .make() + ], + ), + ], + ), + ); + } + + Widget _content() { + var head = Row( + children: [ + Container( + width: 100.w, + height: 50.w, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Color(0xFFFFF7E6), + borderRadius: BorderRadius.circular(8.w), + ), + child: '#${TaskMap.typeToString[widget.model.type]}' + .text + .size(28.sp) + .color(Color(0xFFFA8C16)) + .make(), + ), + Spacer(), + Assets.icons.intergral.image(width: 24.w, height: 24.w), + 8.w.widthBox, + '${widget.model.reward}'.text.size(32.sp).color(Colors.red).make() + ], + ); + return Container( + width: 686.w, + height: 500.w, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8.w), + ), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + children: [ + head, + 34.w.heightBox, + Row( + children: [ + Assets.icons.clockCircle.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '${DateUtil.formatDateStr(widget.model.appointmentDate)}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + 20.w.heightBox, + Row( + children: [ + Assets.icons.environment.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '${widget.model.appointmentAddress}' + .text + .size(24.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + 34.w.heightBox, + Container( + width: 638.w, + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.03), + borderRadius: BorderRadius.circular(8.w)), + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + '#${TaskMap.typeToString[widget.model.type]}' + .text + .size(28.sp) + .color(Colors.black.withOpacity(0.85)) + .make(), + 16.w.heightBox, + widget.model.content.text + .size(28.sp) + .color(Colors.black.withOpacity(0.65)) + .make(), + ], + ), + ), + 32.w.heightBox, + BeeDivider.horizontal(), + 32.w.heightBox, + Row( + children: [ + Assets.icons.reward.image(width: 36.w, height: 36.w), + 24.w.widthBox, + '报酬' + .text + .size(26.sp) + .color(Colors.black.withOpacity(0.45)) + .make(), + Spacer(), + '¥${widget.model.reward}' + .text + .size(32.sp) + .color(Colors.red) + .make(), + ], + ), + ], + ), + ); + } +} diff --git a/lib/ui/service/publish_task_page.dart b/lib/ui/service/publish_task_page.dart index 935f3ccf..38f21c34 100644 --- a/lib/ui/service/publish_task_page.dart +++ b/lib/ui/service/publish_task_page.dart @@ -266,7 +266,7 @@ class _PublishTaskPageState extends State { Get.back(); setState(() {}); }, - child: '业主' + child: '物业' .text .size(28.sp) .isIntrinsic diff --git a/lib/ui/service/task_func.dart b/lib/ui/service/task_func.dart index d302af30..347c3997 100644 --- a/lib/ui/service/task_func.dart +++ b/lib/ui/service/task_func.dart @@ -31,7 +31,7 @@ class TaskFunc { static Future cancel({ required int taskId, }) async { - var base = await NetUtil().post(API.manager.task.cancel, params: { + var base = await NetUtil().get(API.manager.task.cancel, params: { 'taskId': taskId, }); return base.status ?? false; @@ -42,7 +42,7 @@ class TaskFunc { static Future take({ required int taskId, }) async { - var base = await NetUtil().post(API.manager.task.take, params: { + var base = await NetUtil().get(API.manager.task.take, params: { 'taskId': taskId, }); return base.status ?? false; @@ -53,7 +53,7 @@ class TaskFunc { static Future finish({ required int taskId, }) async { - var base = await NetUtil().post(API.manager.task.finish, params: { + var base = await NetUtil().get(API.manager.task.finish, params: { 'taskId': taskId, }); return base.status ?? false;