import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:address_picker/address_picker.dart'; import 'package:amap_location/amap_location.dart'; import 'package:amap_location/amap_location_option.dart'; import 'package:bbyyy/beans/ad_bean_entity.dart'; import 'package:bbyyy/beans/commodity_category_bean_entity.dart'; import 'package:bbyyy/beans/goods_bean_entity.dart'; import 'package:bbyyy/beans/home_carousel_bean_entity.dart'; import 'package:bbyyy/beans/my_shop_bean_entity.dart'; import 'package:bbyyy/beans/store_bean_entity.dart'; import 'package:bbyyy/https/MyDio.dart'; import 'package:bbyyy/https/my_request.dart'; import 'package:bbyyy/https/url.dart'; import 'package:bbyyy/my_tools/const.dart'; import 'package:bbyyy/my_tools/dims.dart'; import 'package:bbyyy/my_tools/event_bus.dart'; import 'package:bbyyy/my_tools/my_colors.dart'; import 'package:bbyyy/my_tools/my_cookie.dart'; import 'package:bbyyy/my_tools/my_tools.dart'; import 'package:bbyyy/my_tools/my_views.dart'; import 'package:bbyyy/paegs/root_page/root_page_view.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_swiper/flutter_swiper.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; class HomePage extends StatefulWidget { @override _HomePageState createState() => _HomePageState(); } class _HomePageState extends State with AutomaticKeepAliveClientMixin { var data = []; var container = []; var puShop = []; var imgs = ['images/banner1.png', 'images/banner2.png', 'images/banner3.png']; var netImgs = []; int selectedIndex = 0; var tabs = ['全部']; var types = ['货帮', '货品']; List> sortItems = []; int typeIndex = 1; List shops = []; ScrollController _controller = ScrollController(); double maxH; double minH = 164; double H = 0; bool showInput = false; TextEditingController _description = TextEditingController(); FocusNode _descriptionFocus = FocusNode(); RefreshController _reController = RefreshController(initialRefresh: true); int page = 1; int pageIndex = 0; bool showS = false; String province; String city; Address _address; @override void initState() { super.initState(); EventBus().on('commodity_category', (arg) { setState(() {}); }); EventBus().on('uploadGoods', (arg) { _reController.requestRefresh(); }); EventBus().on('toTop', (arg) { _controller.animateTo(0.0, duration: Duration(milliseconds: 200), curve: Curves.easeIn); }); EventBus().on('homeCarousel', (arg) { if (arg is HomeCarouselBeanEntity) { arg.data.forEach((element) { netImgs.add(element.path); }); setState(() {}); } }); EventBus().on('商品变动', (arg) { _reController.requestRefresh(); }); EventBus().on('getLocation', (arg) { _reController.requestRefresh(); setState(() {}); }); _controller.addListener(() { setState(() { if (_controller.offset == 0) { RootPageView().toTop = false; EventBus().emit('ChangePage'); } else { RootPageView().toTop = true; EventBus().emit('ChangePage'); } H = maxH - _controller.offset; if (H < minH) { H = minH; } else if (H > maxH) { H = maxH; } }); }); types.forEach((element) { sortItems.add(DropdownMenuItem( child: Text( element, style: TextStyle(color: MyColors.c666666, fontSize: 14), ), value: element, )); }); _descriptionFocus.addListener(() { if (_descriptionFocus.hasFocus) { } else { if (_description.text.isEmpty) { showInput = false; } } }); homeCarousel(); } @override void dispose() { // TODO: implement dispose super.dispose(); EventBus().off('commodity_category'); EventBus().off('uploadGoods'); EventBus().off('toTop'); EventBus().off('homeCarousel'); EventBus().off('商品变动'); EventBus().off('getLocation'); } @override Widget build(BuildContext context) { maxH = MediaQuery.of(context).size.width * (520 / 750); minH = MediaQuery.of(context).padding.top + 64; if (H == 0) { H = maxH; } return GestureDetector( onTap: () { MyTools().hideKeyboard(context); }, behavior: HitTestBehavior.translucent, child: Scaffold( resizeToAvoidBottomInset: false, body: Column( children: [ Stack( children: [ AnimatedContainer( height: H, duration: Duration(milliseconds: 200), child: Swiper( itemBuilder: (BuildContext context, int index) { return netImgs.length == 0 ? Image.asset( "${imgs[index]}", fit: BoxFit.cover, ) : MyViews().netImg( imgURL(netImgs[index]), H, double.infinity, placeholder: 'images/svg/goodsDefImg.svg'); }, itemCount: netImgs.length == 0 ? imgs.length : netImgs.length, viewportFraction: 1, scale: 1, autoplay: true, ), ), SafeArea( bottom: false, child: Stack( children: [ // AnimatedOpacity( // duration: Duration(milliseconds: 200), // opacity: showS ? 0.0 : 1.0, // child: Container( // margin: EdgeInsets.only(top: 18), // width: double.infinity, // child: Row( // children: [ // GestureDetector( // onTap: () { // setState(() { // pageIndex = 0; // _reController.requestRefresh(); // }); // }, // behavior: HitTestBehavior.translucent, // child: Container( // height: 28, // width: 60, // alignment: Alignment.center, // child: Column( // children: [ // Text( // '货帮', // style: TextStyle( // color: pageIndex == 0 // ? MyColors.cFF4233 // : MyColors.c333333, // fontSize: 16, // fontWeight: FontWeight.bold), // ), // Visibility( // child: Container( // width: 32, // height: 2, // decoration: BoxDecoration( // color: MyColors.cFF4233, // borderRadius: // BorderRadius.circular(1)), // ), // visible: pageIndex == 0, // ), // ], // ), // ), // ), // Container( // width: 40, // ), // GestureDetector( // onTap: () { // setState(() { // pageIndex = 1; // _reController.requestRefresh(); // }); // }, // behavior: HitTestBehavior.translucent, // child: Container( // height: 28, // width: 60, // alignment: Alignment.center, // child: Column( // children: [ // Text( // '商品', // style: TextStyle( // color: pageIndex == 1 // ? MyColors.cFF4233 // : MyColors.c333333, // fontSize: 16, // fontWeight: FontWeight.bold), // ), // Visibility( // child: Container( // width: 32, // height: 2, // decoration: BoxDecoration( // color: MyColors.cFF4233, // borderRadius: // BorderRadius.circular(1)), // ), // visible: pageIndex == 1, // ), // ], // ), // ), // ), // ], // mainAxisAlignment: MainAxisAlignment.center, // ), // ), // ), Positioned( left: 0, child: Container( padding: EdgeInsets.only(left: 10, right: 10, top: 12), child: GestureDetector( onTap: () { addressSelection(); }, behavior: HitTestBehavior.translucent, child: Container( padding: EdgeInsets.only(left: 11, right: 14), decoration: BoxDecoration( boxShadow: [ BoxShadow( color: MyColors.c7FE1E1E1, blurRadius: 5.0, ), ], color: Colors.white, borderRadius: BorderRadius.circular(20)), child: Row( children: [ Icon( Icons.location_on_rounded, color: MyColors.c333333, size: 20, ), Text( province == null ? MyCookie().location != null ? MyCookie().location.city : '成都市' : city, style: TextStyle( color: MyColors.c333333, fontSize: 12, fontWeight: FontWeight.bold), ), ], ), height: 40, alignment: Alignment.center, ), ), alignment: Alignment.center, ), ), Container( padding: EdgeInsets.only(left: 10, right: 10, top: 12), child: GestureDetector( onTap: () { showS = !showS; if (!showS) { _description.clear(); } setState(() {}); }, behavior: HitTestBehavior.translucent, child: AnimatedContainer( height: 40, width: !showS ? 40 : MediaQuery.of(context).size.width, child: Row( children: [ SvgPicture.asset( showS ? 'images/svg/箭头.svg' : 'images/svg/搜索.svg', height: 15, width: 15, color: showS ? MyColors.cFF4233 : Colors.white, ), Visibility( visible: showS, child: Expanded( child: TextField( controller: _description, cursorColor: MyColors.cFF4233, cursorWidth: 1.0, onTap: () {}, decoration: InputDecoration( border: InputBorder.none, disabledBorder: InputBorder.none, enabledBorder: InputBorder.none, focusedBorder: InputBorder.none, isDense: true, hintText: '请输入...', hintStyle: TextStyle( color: MyColors.c999999, fontSize: 16), contentPadding: const EdgeInsets.fromLTRB( 14, 4.5, 8, 4.5), ), maxLines: 1, style: TextStyle( color: MyColors.c333333, fontSize: 16, height: 1.3, letterSpacing: 0.2), keyboardType: TextInputType.text, onChanged: (t) { setState(() {}); }, ), ), ), Visibility( visible: showS && _description.text.isNotEmpty, child: GestureDetector( onTap: () { MyTools().hideKeyboard(context); _reController.requestRefresh(); }, behavior: HitTestBehavior.translucent, child: Container( child: MyViews() .myText('搜索', Colors.white, 13), decoration: BoxDecoration( color: MyColors.cFF4233, borderRadius: BorderRadius.circular(20), ), height: 40, width: 80, alignment: Alignment.center, ), ), ) ], mainAxisAlignment: MainAxisAlignment.center, ), alignment: !showS ? Alignment.center : Alignment.centerLeft, padding: EdgeInsets.only(left: !showS ? 0 : 12), decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(20)), color: showS ? Colors.white : MyColors.cFF4233, border: Border.all( width: 0.5, color: showS ? MyColors.cf2f2f2 : MyColors.cFF4233)), duration: Duration(milliseconds: 200), ), ), alignment: Alignment.centerRight, ), ], ), ), ], ), Column( children: [ Container( height: 53, child: ListView.builder( padding: EdgeInsets.only(left: 12, right: 12), itemBuilder: (c, index) { return GestureDetector( onTap: () { setState(() { selectedIndex = index; _reController.requestRefresh(); }); }, behavior: HitTestBehavior.translucent, child: Container( padding: EdgeInsets.only(right: 15, left: 15, bottom: 9), child: Column( children: [ Text( tabs[index], style: TextStyle( color: index == selectedIndex ? MyColors.cFF4233 : MyColors.c666666, fontSize: 14), ), Container( height: 10, child: Visibility( child: SvgPicture.asset('images/svg/tab.svg'), visible: index == selectedIndex, ), ) ], mainAxisAlignment: MainAxisAlignment.end, ), height: 53, ), ); }, itemCount: tabs.length, scrollDirection: Axis.horizontal, ), ), Container( height: 1, color: MyColors.cf2f2f2, ), ], ), Expanded( flex: 1, child: SmartRefresher( controller: _reController, onRefresh: onRefresh, onLoading: onLoading, enablePullDown: true, enablePullUp: true, child: body(), ), ) ], ), ), ); } @override // TODO: implement wantKeepAlive bool get wantKeepAlive => true; void getGoods(List shopUID) { var qData; if (shopUID.length == 0) { var conditions = ["public == true", "on_sale == true"]; if (selectedIndex != 0) { conditions.add("category == ${tabs[selectedIndex]}"); } if (_description.text.isNotEmpty) { conditions.add('title LIKE ${_description.text.toString()}'); } qData = { "key": "commodity", "filters": {"conditions": conditions}, "dims": commodityDims, "order_by": ["id,desc", "no,desc"], "paging": [page, 20] }; } else { var conditions = ["shop_uid in $shopUID", "on_sale == true"]; var conditions2 = ["public == true", "on_sale == true"]; if (selectedIndex != 0) { conditions.add("category == ${tabs[selectedIndex]}"); conditions2.add("category == ${tabs[selectedIndex]}"); } if (_description.text.isNotEmpty) { conditions.add('title LIKE ${_description.text.toString()}'); conditions2.add('title LIKE ${_description.text.toString()}'); } qData = { "key": "commodity", "filters": { "or": true, "conditions": conditions, "filters": [ {"conditions": conditions2} ] }, "order_by": ["id,desc", "no,desc"], "dims": commodityDims, "paging": [page, 20] }; } MyDio().query(qData, (response, hasError) { if (!hasError) { GoodsBeanEntity entity = GoodsBeanEntity().fromJson(json.decode(response.data.toString())); container.clear(); container.addAll(entity.data.data); } queryAd(); }, (error) { queryAd(); }); } void onRefresh() { page = 1; if (pageIndex == 1) { initTabs(); findAStore(); } else { storeType(); checkPublicStores(); } } void onLoading() { page++; if (pageIndex == 1) { findAStore(); } else { checkPublicStores(); } } Future initTabs() async { List commodityCategoryBeanData = []; MyDio().query({ "key": "commodity_category", "filters": {}, "dims": [ "name", ] }, (response, hasError) { if (!hasError) { try { CommodityCategoryBeanEntity entity = CommodityCategoryBeanEntity() .fromJson(json.decode(response.data.toString())); commodityCategoryBeanData = entity.data; tabs.clear(); tabs.add('全部'); commodityCategoryBeanData.forEach((element) { tabs.insert(1, element.name); }); if (selectedIndex > tabs.length - 1) { selectedIndex = 0; } setState(() {}); } catch (e) { tabs.clear(); tabs.add('全部'); if (selectedIndex > tabs.length - 1) { selectedIndex = 0; } } } else { return commodityCategoryBeanData; } }, (error) { return commodityCategoryBeanData; }); } findAStore() { MyDio().query({ "key": "shop_user", "filters": { "or": true, "conditions": [ "role!=$shopUserOwner", "user_uid==${MyCookie().getUID()}", "review_state==1" ], "filters": [ { "conditions": [ "role==$shopUserOwner", "user_uid==${MyCookie().getUID()}" ] } ] }, "dims": shopUserDims, "paging": [1, 20000] }, (response, hasError) { if (!hasError) { MyShopBeanEntity entity = MyShopBeanEntity().fromJson(json.decode(response.data.toString())); shops = entity.data.data; var shopUID = []; shops.forEach((element) { shopUID.add(element.shopUid); }); getGoods(shopUID); } }, (error) {}); } queryAd() { int count = 5; MyDio().query({ "key": "ad", "filters": { "conditions": ['on_show == true'] }, "dims": adDims, "order_by": ["id,desc", "no,desc"], "paging": [page, count] }, (response, hasError) { if (!hasError) { AdBeanEntity entity = AdBeanEntity().fromJson(json.decode(response.data.toString())); container.addAll(entity.data.data); container.shuffle(); } if (page == 1) { data.clear(); puShop.clear(); } if (pageIndex == 1) { data.addAll(container); } else { puShop.addAll(container); } setState(() {}); endRe(_reController); }, (error) { if (page == 1) { data.clear(); } data.addAll(container); setState(() {}); endRe(_reController); }); } void checkPublicStores() { var conditions = ['private==false', 'state == $shopStateNormal']; if (selectedIndex != 0) { conditions.add("category == ${tabs[selectedIndex]}"); } if (_description.text.isNotEmpty) { conditions.add('name LIKE ${_description.text.toString()}'); } if (MyCookie().location == null && province == null) { conditions.add('province == 四川省'); conditions.add('city == 成都市'); } else { if (province != null) { conditions.add('province == $province'); conditions.add('city == $city'); } else if (MyCookie().location != null) { conditions.add('province == ${MyCookie().location.province}'); conditions.add('city == ${MyCookie().location.city}'); } } MyDio().query({ "key": "shop", "filters": {"conditions": conditions}, "dims": shopDims, "order_by": ["id,desc", "no,desc"], "paging": [page, 20] }, (response, hasError) { if (!hasError) { StoreBeanEntity entity = StoreBeanEntity().fromJson(json.decode(response.data.toString())); container.clear(); container.addAll(entity.data.data); } queryAd(); }, (error) { queryAd(); }); } void storeType() { List commodityCategoryBeanData = []; MyDio().query({ "key": "shop_category", "filters": {}, "dims": [ "name", ] }, (response, hasError) { if (!hasError) { try { CommodityCategoryBeanEntity entity = CommodityCategoryBeanEntity() .fromJson(json.decode(response.data.toString())); commodityCategoryBeanData = entity.data; tabs.clear(); tabs.add('全部'); commodityCategoryBeanData.forEach((element) { tabs.insert(1, element.name); }); setState(() {}); } catch (e) { tabs.clear(); tabs.add('全部'); if (selectedIndex > tabs.length - 1) { selectedIndex = 0; } setState(() {}); } } }, (error) {}); } body() { if (pageIndex == 1) { return body1(); } else if (pageIndex == 0) { return body2(); } } body1() { if (data.length == 0) { return SingleChildScrollView(child: noData()); } else { return GridView.builder( controller: _controller, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: 164 / 261, mainAxisSpacing: 8, crossAxisSpacing: 8), itemCount: data.length, padding: EdgeInsets.only(left: 14, right: 14, top: 14, bottom: 65), itemBuilder: (context, index) { return MyViews().getGoodsItem(data[index], context); }); } } body2() { if (puShop.length == 0) { return SingleChildScrollView(child: noData()); } else { return ListView.builder( controller: _controller, itemBuilder: (BuildContext context, int index) { return MyViews().pubShopItem(puShop[index], context); }, itemCount: puShop.length, padding: EdgeInsets.all(10), ); } } void addressSelection() { StateSetter ss; showModalBottomSheet( context: context, builder: (context) => BottomSheet( onClosing: () {}, builder: (context) => Container( height: 350, child: Column( children: [ StatefulBuilder( builder: (c, s) { ss = s; return Container( height: 40, color: Colors.white, padding: EdgeInsets.symmetric(horizontal: 15), child: Row( children: [ Row( children: [ Text( '定位到: ', style: TextStyle(color: MyColors.cFF4233, fontSize: 14), ), Text(_address==null?'北京市 北京市':'${_address.currentProvince.province} ${_address.currentCity.city}', style: TextStyle( color: MyColors.cFF4233, fontSize: 14), ), ], ), GestureDetector( child: Container( height: 40, width: 60, alignment: Alignment.center, child: Text( '确定', style: TextStyle(color: MyColors.cFF4233, fontSize: 16), ), ), onTap: () { if (_address == null) { province = '北京市'; city = '北京市'; setState(() {}); _reController.requestRefresh(); _address = null; Navigator.pop(context); } else { province = _address.currentProvince.province; city = _address.currentCity.city; setState(() {}); _reController.requestRefresh(); _address = null; Navigator.pop(context); } }, behavior: HitTestBehavior.translucent, ), ], mainAxisAlignment: MainAxisAlignment.spaceBetween, ), ); }, ), GestureDetector( onTap: (){ if(MyCookie().location != null){ province = MyCookie().location.province; city = MyCookie().location.city; setState(() {}); _reController.requestRefresh(); _address = null; Navigator.pop(context); } }, behavior: HitTestBehavior.translucent, child: Container( height: 60, color: Colors.white, padding: EdgeInsets.symmetric(horizontal: 20), child: Row(children: [ Text('当前定位:',style: TextStyle(color: MyColors.c333333,fontSize: 16),), Text(MyCookie().location != null ? '${MyCookie().location.province} ${MyCookie().location.city}' : '请开启定位权限',style: TextStyle(color: MyColors.c333333,fontSize: 16),) ],), ), ), Container( height: 250.0, child: AddressPicker( style: TextStyle(color: Colors.black, fontSize: 17), mode: AddressPickerMode.provinceAndCity, onSelectedAddressChanged: (address) { _address = address; ss((){}); }, ), ), ], ), ), ), ); } }