From c2b96095a73da80efa5c41a00006e4cb97bcfdba Mon Sep 17 00:00:00 2001 From: laiiihz Date: Wed, 28 Oct 2020 20:49:38 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=89=E6=8B=A9=E7=9B=B4=E6=92=AD=E5=95=86?= =?UTF-8?q?=E5=93=81UI=E6=B7=BB=E5=8A=A0=E5=8E=86=E5=8F=B2=E7=9B=B4?= =?UTF-8?q?=E6=92=AD=E5=92=8C=E7=83=AD=E9=97=A8=E5=95=86=E5=93=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/constants/api.dart | 3 + .../live_stream/live_pick_goods_page.dart | 202 ++++++++---------- .../pick_view/brand_goods_view.dart | 5 +- .../pick_view/goods_window_view.dart | 120 ++++++++--- .../live_stream/pick_view/hot_goods_view.dart | 136 ++++++++++++ .../pick_view/live_goods_card.dart | 17 -- 6 files changed, 318 insertions(+), 165 deletions(-) create mode 100644 lib/pages/live/live_stream/pick_view/hot_goods_view.dart diff --git a/lib/constants/api.dart b/lib/constants/api.dart index fd72168..53fdcb7 100644 --- a/lib/constants/api.dart +++ b/lib/constants/api.dart @@ -540,4 +540,7 @@ class LiveAPI { static const String liveAgree = '/v1/live/live/agree'; static const String recordLive = '/v1/live/live/transcribe'; + + ///热门商品列表 + static const String hotGoods = '/v1/live/goods/hot'; } diff --git a/lib/pages/live/live_stream/live_pick_goods_page.dart b/lib/pages/live/live_stream/live_pick_goods_page.dart index 65660b9..bbd770f 100644 --- a/lib/pages/live/live_stream/live_pick_goods_page.dart +++ b/lib/pages/live/live_stream/live_pick_goods_page.dart @@ -4,9 +4,9 @@ import 'package:recook/constants/api.dart'; import 'package:recook/constants/header.dart'; import 'package:recook/manager/http_manager.dart'; import 'package:recook/pages/live/live_stream/pick_search_goods_page.dart'; -import 'package:recook/pages/live/live_stream/pick_view/brand_goods_list_view.dart'; import 'package:recook/pages/live/live_stream/pick_view/brand_goods_view.dart'; import 'package:recook/pages/live/live_stream/pick_view/goods_window_view.dart'; +import 'package:recook/pages/live/live_stream/pick_view/hot_goods_view.dart'; import 'package:recook/pages/live/live_stream/pick_view/pick_cart.dart'; import 'package:recook/pages/live/models/goods_window_model.dart'; import 'package:recook/utils/custom_route.dart'; @@ -26,17 +26,12 @@ class _LivePickGoodsPageState extends State with TickerProviderStateMixin { int _goodsPage = 1; TabController _tabController; - TabController _parentTabController; @override void initState() { super.initState(); _tabController = TabController( vsync: this, - length: 2, - ); - _parentTabController = TabController( - vsync: this, - length: 2, + length: 3, ); } @@ -53,14 +48,7 @@ class _LivePickGoodsPageState extends State appBar: AppBar( elevation: 0, backgroundColor: Colors.white, - leading: _parentTabController.index == 0 - ? RecookBackButton.text() - : RecookBackButton( - onTap: () { - _parentTabController.animateTo(0); - setState(() {}); - }, - ), + leading: RecookBackButton.text(), leadingWidth: rSize(28 + 30.0), title: Text( '选择直播商品', @@ -72,109 +60,103 @@ class _LivePickGoodsPageState extends State ), centerTitle: true, ), - body: TabBarView( - controller: _parentTabController, - physics: NeverScrollableScrollPhysics(), - children: [ - NestedScrollView( - headerSliverBuilder: (context, _) { - return [ - SliverToBoxAdapter( - child: CustomImageButton( - padding: EdgeInsets.zero, - onPressed: () { - CRoute.push(context, PickSearchGoodsPage()); - }, - child: Container( - alignment: Alignment.center, - margin: EdgeInsets.symmetric(horizontal: rSize(15)), - decoration: BoxDecoration( - color: Color(0xFFF5F5F5), - borderRadius: BorderRadius.circular(rSize(15)), - ), - height: rSize(30), - child: Row( - children: [ - Padding( - padding: EdgeInsets.only( - left: rSize(12), - right: rSize(4), - ), - child: Icon( - Icons.search, - color: Color(0xFF999999), - size: rSize(15), - ), - ), - Text( - '搜索你想要添加的商品', - style: TextStyle( - color: Color(0xFF999999), - fontSize: rSP(13), - ), - ), - ], - ), - ), - ), - ), - ]; - }, - body: Column( - children: [ - Container( - margin: EdgeInsets.symmetric( - horizontal: rSize(95), - vertical: rSize(15), - ), - height: rSize(32), - child: TabBar( - controller: _tabController, - tabs: [ - Tab(text: '商品橱窗'), - Tab(text: '品牌'), - ], - labelStyle: TextStyle( - fontSize: rSP(13), - fontWeight: FontWeight.bold, - ), - labelColor: Color(0xFF333333), - unselectedLabelColor: Color(0xFF333333).withOpacity(0.3), - indicatorSize: TabBarIndicatorSize.label, - indicator: RecookIndicator( - borderSide: BorderSide( - width: rSize(3), - color: Color(0xFFDB2D2D), - )), + body: NestedScrollView( + headerSliverBuilder: (context, _) { + return [ + SliverToBoxAdapter( + child: CustomImageButton( + padding: EdgeInsets.zero, + onPressed: () { + CRoute.push(context, PickSearchGoodsPage()); + }, + child: Container( + alignment: Alignment.center, + margin: EdgeInsets.symmetric(horizontal: rSize(15)), + decoration: BoxDecoration( + color: Color(0xFFF5F5F5), + borderRadius: BorderRadius.circular(rSize(15)), ), - ), - Expanded( - child: TabBarView( - controller: _tabController, + height: rSize(30), + child: Row( children: [ - GoodsWindowView( - onPick: () { - setState(() {}); - }, + Padding( + padding: EdgeInsets.only( + left: rSize(12), + right: rSize(4), + ), + child: Icon( + Icons.search, + color: Color(0xFF999999), + size: rSize(15), + ), ), - BrandGoodsView( - controller: _parentTabController, - onTapBrand: () { - setState(() {}); - }, + Text( + '搜索你想要添加的商品', + style: TextStyle( + color: Color(0xFF999999), + fontSize: rSP(13), + ), ), ], ), ), - ], + ), ), - ), - BrandGoodsListView( - onPick: () { - setState(() {}); - }, - ), - ], + ]; + }, + body: Column( + children: [ + Container( + margin: EdgeInsets.symmetric( + vertical: rSize(15), + ), + height: rSize(32), + child: TabBar( + controller: _tabController, + isScrollable: true, + tabs: [ + Tab(text: '历史直播'), + Tab(text: '热门商品'), + Tab(text: '全部商品'), + ], + labelStyle: TextStyle( + fontSize: rSP(13), + fontWeight: FontWeight.bold, + ), + labelColor: Color(0xFF333333), + unselectedLabelColor: Color(0xFF333333).withOpacity(0.3), + indicatorSize: TabBarIndicatorSize.label, + indicator: RecookIndicator( + borderSide: BorderSide( + width: rSize(3), + color: Color(0xFFDB2D2D), + )), + ), + ), + Expanded( + child: TabBarView( + controller: _tabController, + children: [ + GoodsWindowView( + onPick: () { + setState(() {}); + }, + ), + HotGoodsView( + onPick: () { + setState(() {}); + }, + ), + BrandGoodsView( + onTapBrand: () { + setState(() {}); + }, + ), + ], + ), + ), + ], + ), ), bottomNavigationBar: BottomAppBar( color: Colors.white, diff --git a/lib/pages/live/live_stream/pick_view/brand_goods_view.dart b/lib/pages/live/live_stream/pick_view/brand_goods_view.dart index 5b6cbbd..d78dcbc 100644 --- a/lib/pages/live/live_stream/pick_view/brand_goods_view.dart +++ b/lib/pages/live/live_stream/pick_view/brand_goods_view.dart @@ -8,10 +8,8 @@ import 'package:recook/pages/live/models/live_brand_model.dart'; import 'package:recook/widgets/refresh_widget.dart'; class BrandGoodsView extends StatefulWidget { - final TabController controller; final VoidCallback onTapBrand; - BrandGoodsView({Key key, @required this.controller, this.onTapBrand}) - : super(key: key); + BrandGoodsView({Key key, this.onTapBrand}) : super(key: key); @override _BrandGoodsViewState createState() => _BrandGoodsViewState(); @@ -66,7 +64,6 @@ class _BrandGoodsViewState extends State return MaterialButton( padding: EdgeInsets.zero, onPressed: () { - widget.controller.animateTo(1); PickCart.brandModel = model; widget.onTapBrand(); }, diff --git a/lib/pages/live/live_stream/pick_view/goods_window_view.dart b/lib/pages/live/live_stream/pick_view/goods_window_view.dart index b341052..8ed7fc8 100644 --- a/lib/pages/live/live_stream/pick_view/goods_window_view.dart +++ b/lib/pages/live/live_stream/pick_view/goods_window_view.dart @@ -1,8 +1,11 @@ import 'package:flutter/material.dart'; import 'package:recook/constants/api.dart'; +import 'package:recook/constants/constants.dart'; import 'package:recook/manager/http_manager.dart'; import 'package:recook/pages/live/live_stream/pick_view/live_goods_card.dart'; +import 'package:recook/pages/live/live_stream/pick_view/pick_cart.dart'; import 'package:recook/pages/live/models/goods_window_model.dart'; +import 'package:recook/pages/user/widget/recook_check_box.dart'; import 'package:recook/widgets/refresh_widget.dart'; class GoodsWindowView extends StatefulWidget { @@ -18,51 +21,100 @@ class _GoodsWindowViewState extends State GSRefreshController _controller = GSRefreshController(); List _goodsModels = []; int _page = 1; + bool get _selectAll { + for (var item in _goodsModels) { + if (PickCart.picked.indexWhere((element) => element.id == item.id) == + -1) { + return false; + } + } + return true; + } + @override void initState() { super.initState(); Future.delayed(Duration(milliseconds: 300), () { - if(mounted) _controller.requestRefresh(); + if (mounted) _controller.requestRefresh(); }); } @override Widget build(BuildContext context) { super.build(context); - return RefreshWidget( - controller: _controller, - onRefresh: () { - _page = 1; - getGoodsWindowModels().then((models) { - setState(() { - _goodsModels = models; - }); - _controller.refreshCompleted(); - }); - }, - onLoadMore: () { - _page++; - getGoodsWindowModels().then((models) { - setState(() { - _goodsModels.addAll(models); - }); - _controller.loadComplete(); - }); - }, - body: ListView.builder( - itemBuilder: (context, index) { - final model = _goodsModels[index]; - return LiveGoodsCard( - onPick: () { - setState(() { - widget.onPick(); + return Column( + children: [ + MaterialButton( + onPressed: () { + if (_selectAll) { + PickCart.picked.removeWhere((picked) { + return _goodsModels + .indexWhere((element) => element.id == picked.id) != + -1; + }); + } else + _goodsModels.forEach((element) { + if (PickCart.picked.length < 50) { + PickCart.picked.add(element); + } + }); + widget.onPick(); + }, + child: Row( + children: [ + RecookCheckBox(state: _selectAll), + rWBox(10), + Text( + '全选', + style: TextStyle( + color: Color(0xFF333333), + fontSize: rSP(14), + ), + ), + ], + ), + ), + Expanded( + child: RefreshWidget( + controller: _controller, + onRefresh: () { + _page = 1; + getGoodsWindowModels().then((models) { + setState(() { + _goodsModels = models; + }); + _controller.refreshCompleted(); + }); + }, + onLoadMore: () { + _page++; + getGoodsWindowModels().then((models) { + setState(() { + _goodsModels.addAll(models); + }); + if (models.isEmpty) + _controller.loadNoData(); + else + _controller.loadComplete(); }); }, - model: model, - ); - }, - itemCount: _goodsModels.length, - ), + body: ListView.builder( + itemBuilder: (context, index) { + final model = _goodsModels[index]; + return LiveGoodsCard( + onPick: () { + setState(() { + widget.onPick(); + }); + }, + model: model, + ); + }, + itemCount: _goodsModels.length, + ), + ), + ), + ], ); } @@ -72,7 +124,7 @@ class _GoodsWindowViewState extends State 'limit': 15, }); if (resultData?.data['data']['list'] == null) - return null; + return []; else return (resultData.data['data']['list'] as List) .map((e) => GoodsList.fromJson(e)) diff --git a/lib/pages/live/live_stream/pick_view/hot_goods_view.dart b/lib/pages/live/live_stream/pick_view/hot_goods_view.dart new file mode 100644 index 0000000..5e44bea --- /dev/null +++ b/lib/pages/live/live_stream/pick_view/hot_goods_view.dart @@ -0,0 +1,136 @@ +import 'package:flutter/material.dart'; +import 'package:recook/constants/api.dart'; +import 'package:recook/constants/constants.dart'; +import 'package:recook/manager/http_manager.dart'; +import 'package:recook/pages/live/live_stream/pick_view/live_goods_card.dart'; +import 'package:recook/pages/live/live_stream/pick_view/pick_cart.dart'; +import 'package:recook/pages/live/models/goods_window_model.dart'; +import 'package:recook/pages/user/widget/recook_check_box.dart'; +import 'package:recook/widgets/refresh_widget.dart'; + +class HotGoodsView extends StatefulWidget { + final VoidCallback onPick; + HotGoodsView({Key key, this.onPick}) : super(key: key); + + @override + _HotGoodsViewState createState() => _HotGoodsViewState(); +} + +class _HotGoodsViewState extends State + with AutomaticKeepAliveClientMixin { + GSRefreshController _controller = GSRefreshController(); + List _goodsModels = []; + int _page = 1; + bool get _selectAll { + for (var item in _goodsModels) { + if (PickCart.picked.indexWhere((element) => element.id == item.id) == + -1) { + return false; + } + } + return true; + } + + @override + void initState() { + super.initState(); + Future.delayed(Duration(milliseconds: 300), () { + if (mounted) _controller.requestRefresh(); + }); + } + + @override + Widget build(BuildContext context) { + super.build(context); + return Column( + children: [ + MaterialButton( + onPressed: () { + if (_selectAll) { + PickCart.picked.removeWhere((picked) { + return _goodsModels + .indexWhere((element) => element.id == picked.id) != + -1; + }); + } else + _goodsModels.forEach((element) { + if (PickCart.picked.length < 50) { + PickCart.picked.add(element); + } + }); + widget.onPick(); + }, + child: Row( + children: [ + RecookCheckBox(state: _selectAll), + rWBox(10), + Text( + '全选', + style: TextStyle( + color: Color(0xFF333333), + fontSize: rSP(14), + ), + ), + ], + ), + ), + Expanded( + child: RefreshWidget( + controller: _controller, + onRefresh: () { + _page = 1; + getGoodsWindowModels().then((models) { + setState(() { + _goodsModels = models; + }); + _controller.refreshCompleted(); + }); + }, + onLoadMore: () { + _page++; + getGoodsWindowModels().then((models) { + setState(() { + _goodsModels.addAll(models); + }); + if (models.isEmpty) + _controller.loadNoData(); + else + _controller.loadComplete(); + }); + }, + body: ListView.builder( + itemBuilder: (context, index) { + final model = _goodsModels[index]; + return LiveGoodsCard( + onPick: () { + setState(() { + widget.onPick(); + }); + }, + model: model, + ); + }, + itemCount: _goodsModels.length, + ), + ), + ), + ], + ); + } + + Future> getGoodsWindowModels() async { + ResultData resultData = await HttpManager.post(LiveAPI.hotGoods, { + 'page': _page, + 'limit': 15, + }); + if (resultData?.data['data']['list'] == null) + return []; + else + return (resultData.data['data']['list'] as List) + .map((e) => GoodsList.fromJson(e)) + .toList(); + } + + @override + bool get wantKeepAlive => true; +} diff --git a/lib/pages/live/live_stream/pick_view/live_goods_card.dart b/lib/pages/live/live_stream/pick_view/live_goods_card.dart index 14a69ab..877816b 100644 --- a/lib/pages/live/live_stream/pick_view/live_goods_card.dart +++ b/lib/pages/live/live_stream/pick_view/live_goods_card.dart @@ -88,23 +88,6 @@ class _LiveGoodsCardState extends State { Row( children: [ InkWell( - onTap: () { - PickCart.brandModel = LiveBrandModel( - id: widget.model.brandId, - name: widget.model.brandName, - logoUrl: widget.model.brandImg, - ); - CRoute.push( - context, - RecookScaffold( - title: '品牌馆', - whiteBg: true, - body: BrandGoodsListView( - onPick: () {}, - ), - ), - ); - }, child: Row( children: [ FadeInImage.assetNetwork(