diff --git a/lib/retrofit/data/shoppingCart.dart b/lib/retrofit/data/shoppingCart.dart new file mode 100644 index 00000000..365ae6d7 --- /dev/null +++ b/lib/retrofit/data/shoppingCart.dart @@ -0,0 +1,146 @@ +/// cartSum : 0 +/// numberOfPeople : 0 +/// selected : 0 +/// shoppingCartSkuItemList : [{"buyNum":0,"createTime":"","groupId":0,"id":0,"platterList":[{"deleted":true,"id":0,"productId":0,"required":true,"skuId":0}],"productId":0,"productName":"","selected":0,"skuImg":"","skuName":"","skuPrice":0,"skuStock":0,"storeId":0,"tableId":0}] +/// storeId : 0 +/// storeName : "" +/// tableId : 0 + +class ShoppingCart { + int cartSum; + int numberOfPeople; + int selected; + List shoppingCartSkuItemList; + int storeId; + String storeName; + int tableId; + + static ShoppingCart fromMap(Map map) { + if (map == null) return null; + ShoppingCart shoppingCartBean = ShoppingCart(); + shoppingCartBean.cartSum = map['cartSum']; + shoppingCartBean.numberOfPeople = map['numberOfPeople']; + shoppingCartBean.selected = map['selected']; + shoppingCartBean.shoppingCartSkuItemList = List()..addAll( + (map['shoppingCartSkuItemList'] as List ?? []).map((o) => ShoppingCartSkuItemListBean.fromMap(o)) + ); + shoppingCartBean.storeId = map['storeId']; + shoppingCartBean.storeName = map['storeName']; + shoppingCartBean.tableId = map['tableId']; + return shoppingCartBean; + } + + Map toJson() => { + "cartSum": cartSum, + "numberOfPeople": numberOfPeople, + "selected": selected, + "shoppingCartSkuItemList": shoppingCartSkuItemList, + "storeId": storeId, + "storeName": storeName, + "tableId": tableId, + }; +} + +/// buyNum : 0 +/// createTime : "" +/// groupId : 0 +/// id : 0 +/// platterList : [{"deleted":true,"id":0,"productId":0,"required":true,"skuId":0}] +/// productId : 0 +/// productName : "" +/// selected : 0 +/// skuImg : "" +/// skuName : "" +/// skuPrice : 0 +/// skuStock : 0 +/// storeId : 0 +/// tableId : 0 + +class ShoppingCartSkuItemListBean { + int buyNum; + String createTime; + int groupId; + int id; + List platterList; + int productId; + String productName; + int selected; + String skuImg; + String skuName; + int skuPrice; + int skuStock; + int storeId; + int tableId; + + static ShoppingCartSkuItemListBean fromMap(Map map) { + if (map == null) return null; + ShoppingCartSkuItemListBean shoppingCartSkuItemListBean = ShoppingCartSkuItemListBean(); + shoppingCartSkuItemListBean.buyNum = map['buyNum']; + shoppingCartSkuItemListBean.createTime = map['createTime']; + shoppingCartSkuItemListBean.groupId = map['groupId']; + shoppingCartSkuItemListBean.id = map['id']; + shoppingCartSkuItemListBean.platterList = List()..addAll( + (map['platterList'] as List ?? []).map((o) => PlatterListBean.fromMap(o)) + ); + shoppingCartSkuItemListBean.productId = map['productId']; + shoppingCartSkuItemListBean.productName = map['productName']; + shoppingCartSkuItemListBean.selected = map['selected']; + shoppingCartSkuItemListBean.skuImg = map['skuImg']; + shoppingCartSkuItemListBean.skuName = map['skuName']; + shoppingCartSkuItemListBean.skuPrice = map['skuPrice']; + shoppingCartSkuItemListBean.skuStock = map['skuStock']; + shoppingCartSkuItemListBean.storeId = map['storeId']; + shoppingCartSkuItemListBean.tableId = map['tableId']; + return shoppingCartSkuItemListBean; + } + + Map toJson() => { + "buyNum": buyNum, + "createTime": createTime, + "groupId": groupId, + "id": id, + "platterList": platterList, + "productId": productId, + "productName": productName, + "selected": selected, + "skuImg": skuImg, + "skuName": skuName, + "skuPrice": skuPrice, + "skuStock": skuStock, + "storeId": storeId, + "tableId": tableId, + }; +} + +/// deleted : true +/// id : 0 +/// productId : 0 +/// required : true +/// skuId : 0 + +class PlatterListBean { + bool deleted; + int id; + int productId; + bool required; + int skuId; + + static PlatterListBean fromMap(Map map) { + if (map == null) return null; + PlatterListBean platterListBean = PlatterListBean(); + platterListBean.deleted = map['deleted']; + platterListBean.id = map['id']; + platterListBean.productId = map['productId']; + platterListBean.required = map['required']; + platterListBean.skuId = map['skuId']; + return platterListBean; + } + + Map toJson() => { + "deleted": deleted, + "id": id, + "productId": productId, + "required": required, + "skuId": skuId, + }; +} \ No newline at end of file diff --git a/lib/retrofit/min_api.dart b/lib/retrofit/min_api.dart index 25a0ec8a..77fb98d2 100644 --- a/lib/retrofit/min_api.dart +++ b/lib/retrofit/min_api.dart @@ -122,6 +122,11 @@ abstract class MinApiService { @GET("/product/queryMiNiProductDetail?id={id}") Future> miNiDetail(@Path("id") String id); + ///添加购物车 + @POST("shoppingcart") + Future> shoppingCart( + @Body() Map param,Map header); + } \ No newline at end of file diff --git a/lib/store/store_order.dart b/lib/store/store_order.dart index a9d3ac2f..82f4e831 100644 --- a/lib/store/store_order.dart +++ b/lib/store/store_order.dart @@ -45,8 +45,10 @@ class _StoreOrderPage extends State MinApiService minService; StoreInfo storeInfo; List activitys; - // RefreshController refreshController; + RefreshController refreshController; List _widgetOptions; + int allCount = 0; + double allPrice = 0; ScrollController controller = ScrollController(); @@ -61,12 +63,13 @@ class _StoreOrderPage extends State ); _widgetOptions = [ - StoreOrderListPage( - widget.arguments, - activitys, - storeInfo, - controller, - ), + StoreOrderListPage(widget.arguments, activitys, storeInfo, controller, + (ac, ap) { + setState(() { + allCount = ac; + allPrice = ap; + }); + }), ///星店活动, StoreActivity( @@ -114,75 +117,91 @@ class _StoreOrderPage extends State bottom: 54.h, child: DefaultTabController( length: 2, - child: NestedScrollView( - controller: controller, - // physics: BouncingScrollPhysics(), - dragStartBehavior: DragStartBehavior.start, - headerSliverBuilder: - (BuildContext context, bool innerBoxIsScrolled) { - return [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor( - context), - sliver: SliverAppBar( - expandedHeight: - (storeInfo != null && storeInfo.couponVOList != null) - ? 425.h : 365.h, - floating: false, - snap: false, - pinned: true, - stretch: false, - leading: GestureDetector( - onTap: () { - Navigator.of(context).pop(); - }, - child: Container( - alignment: Alignment.centerRight, - margin: EdgeInsets.only(left: 10), - padding: EdgeInsets.all(6), - child: Icon( - Icons.arrow_back_ios, - color: Colors.black, - size: 24, + child: SmartRefresher( + controller: refreshController = + RefreshController(initialRefresh: false), + enablePullDown: true, + enablePullUp: false, + header: MyHeader(), + physics: BouncingScrollPhysics(), + onRefresh: () { + queryStoreInfo(); + }, + child: NestedScrollView( + controller: controller, + dragStartBehavior: DragStartBehavior.start, + headerSliverBuilder: + (BuildContext context, bool innerBoxIsScrolled) { + return [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor( + context), + sliver: SliverAppBar( + expandedHeight: (storeInfo != null && + storeInfo.couponVOList != null) + ? 425.h + : 365.h, + floating: false, + snap: false, + pinned: true, + stretch: false, + leading: GestureDetector( + onTap: () { + Navigator.of(context).pop(); + }, + child: Container( + alignment: Alignment.centerRight, + margin: EdgeInsets.only(left: 10), + padding: EdgeInsets.all(6), + child: Icon( + Icons.arrow_back_ios, + color: Colors.black, + size: 24, + ), ), ), - ), - flexibleSpace: FlexibleSpaceBar( - title: Title( - controller, - storeInfo != null ? storeInfo.storeName : '', - ), - collapseMode: CollapseMode.pin, - stretchModes: [ - StretchMode.zoomBackground, - StretchMode.fadeTitle, - StretchMode.blurBackground, - ], - background: Stack( - children: [ - Positioned( - child: Column( - children: [ - buildSwiper(), - Expanded( - child: Container( - color: Colors.transparent, - ), - flex: 1, - ), - ], - ), - top: 0, - bottom: 0, - left: 0, - right: 0, - ), - Positioned( - child: Container( + flexibleSpace: FlexibleSpaceBar( + title: Title( + controller, + storeInfo != null ? storeInfo.storeName : '', + ), + collapseMode: CollapseMode.pin, + stretchModes: [ + StretchMode.zoomBackground, + StretchMode.fadeTitle, + StretchMode.blurBackground, + ], + background: Stack( + children: [ + Positioned( child: Column( children: [ - ///门店信息 - StoreInfoView(storeInfo), + // Image.asset( + // "assets/image/share_image_bg.png", + // fit: BoxFit.cover, + // width: MediaQuery.of(context).size.width, + // height: 180.h, + // ), + buildSwiper(), + Expanded( + child: Container( + color: Colors.transparent, + ), + flex: 1, + ), + ], + ), + top: 0, + bottom: 0, + left: 0, + right: 0, + ), + Positioned( + child: Container( + child: Column( + children: [ + ///门店信息 + StoreInfoView(storeInfo), ///门店对应优惠券 if (storeInfo != null && @@ -281,7 +300,7 @@ class _StoreOrderPage extends State ), ), Text( - "¥19.00", + "¥" + allPrice.toString(), style: TextStyle( fontSize: 20.sp, fontWeight: MyFontWeight.medium, @@ -332,7 +351,7 @@ class _StoreOrderPage extends State child: RoundButton( width: 17, height: 17, - text: "1", + text: allCount.toString(), textColor: Colors.white, fontWeight: MyFontWeight.regular, backgroup: Color(0xFF32A060), diff --git a/lib/store/store_view/store_order_list.dart b/lib/store/store_view/store_order_list.dart index 519f06cf..cb03f9bb 100644 --- a/lib/store/store_view/store_order_list.dart +++ b/lib/store/store_view/store_order_list.dart @@ -1,5 +1,6 @@ import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:huixiang/generated/l10n.dart'; import 'package:huixiang/retrofit/data/activity.dart'; import 'package:huixiang/retrofit/data/base_data.dart'; @@ -10,7 +11,6 @@ import 'package:huixiang/retrofit/min_api.dart'; import 'package:huixiang/retrofit/retrofit_api.dart'; import 'package:huixiang/store/store_view/product_sku.dart'; import 'package:huixiang/utils/font_weight.dart'; -import 'package:huixiang/utils/min.dart'; import 'package:huixiang/view_widget/custom_image.dart'; import 'package:huixiang/view_widget/round_button.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -21,13 +21,10 @@ class StoreOrderListPage extends StatefulWidget { final List activitys; final StoreInfo storeInfo; final ScrollController controller; + final Function(int allCount, double allPrice) fc; StoreOrderListPage( - this.arguments, - this.activitys, - this.storeInfo, - this.controller, - ); + this.arguments, this.activitys, this.storeInfo, this.controller, this.fc); @override State createState() { @@ -113,6 +110,18 @@ class _StoreOrderListPage extends State { } } + ///添加购物车 + addsShoppingCart() async { + BaseData baseDate = await apiService.creditOrder({ + "parentId": widget.arguments["parentId"], + "skuImg": widget.arguments["skuImg"], + "skuNameStr": widget.arguments["skuNameStr"], + "skuPrice": widget.arguments["skuPrice"], + "skuStock": widget.arguments["skuStock"], + }); + if (baseDate != null && baseDate.isSuccess) {} + } + @override Widget build(BuildContext context) { return Container( @@ -144,7 +153,7 @@ class _StoreOrderListPage extends State { physics: BouncingScrollPhysics(), padding: EdgeInsets.zero, itemBuilder: (context, position) { - return goodsItem(productListBeans[position], position); + return goodsItem(position); }, ), ), @@ -191,7 +200,7 @@ class _StoreOrderListPage extends State { ); } - Widget goodsItem(ProductListBean productListBean, position) { + Widget goodsItem(position) { return Container( color: Colors.white, padding: EdgeInsets.only(right: 16.w, bottom: 10.h, top: 10.h), @@ -201,7 +210,9 @@ class _StoreOrderListPage extends State { children: [ SizedBox(width: 12.w), MImage( - productListBean != null ? productListBean.imgPath : "", + productListBeans[position] != null + ? productListBeans[position].imgPath + : "", width: 70, height: 70, fit: BoxFit.cover, @@ -216,7 +227,7 @@ class _StoreOrderListPage extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - productListBean.productName, + productListBeans[position].productName, style: TextStyle( color: Colors.black, fontSize: 13.sp, @@ -230,7 +241,7 @@ class _StoreOrderListPage extends State { children: [ Expanded( child: Text( - productListBean.shortName, + productListBeans[position].shortName, overflow: TextOverflow.ellipsis, maxLines: 2, style: TextStyle( @@ -267,7 +278,7 @@ class _StoreOrderListPage extends State { width: 4, ), Text( - "¥${productListBean.price}", + "¥${productListBeans[position].price}", style: TextStyle( color: Color(0xFFFF7A1A), fontSize: 11.sp, @@ -290,7 +301,7 @@ class _StoreOrderListPage extends State { width: 4, ), Text( - "¥${productListBean.applyPrice}", + "¥${productListBeans[position].applyPrice}", style: TextStyle( color: Color(0xFFA29E9E), fontSize: 10.sp, @@ -302,11 +313,10 @@ class _StoreOrderListPage extends State { ], ), Spacer(), - true + productListBeans[position].attrStyle == 1 ? GestureDetector( onTap: () { - // showStoreSelector(productListBean); - queryMiNiDetail(productListBean.id); + queryMiNiDetail(productListBeans[position].id); }, child: RoundButton( width: 49.w, @@ -320,18 +330,33 @@ class _StoreOrderListPage extends State { ), ) : InkWell( - onTap: () {}, + onTap: () { + setState(() { + { + if (productListBeans[position].buyNum > 0) + productListBeans[position].buyNum--; + int allCount = 0; + double allPrice = 0; + productListBeans.forEach((element) { + allCount += element.buyNum; + allPrice += double.parse(element.price) * + element.buyNum; + }); + widget.fc(allCount, allPrice); + } + }); + }, child: Image.asset( "assets/image/reduce.png", width: 22, height: 22, ), ), - if (false) + if (productListBeans[position].attrStyle == 0) Padding( padding: EdgeInsets.only(left: 8, right: 8), child: Text( - productListBean.buyNum.toString(), + productListBeans[position].buyNum.toString(), style: TextStyle( color: Colors.black, fontSize: 14.sp, @@ -339,9 +364,23 @@ class _StoreOrderListPage extends State { ), ), ), - if (false) + if (productListBeans[position].attrStyle == 0) InkWell( - onTap: () {}, + onTap: () { + setState(() { + { + productListBeans[position].buyNum++; + int allCount = 0; + double allPrice = 0; + productListBeans.forEach((element) { + allCount += element.buyNum; + allPrice += double.parse(element.price) * + element.buyNum; + }); + widget.fc(allCount, allPrice); + } + }); + }, child: Image.asset( "assets/image/add.png", width: 22, @@ -364,16 +403,288 @@ class _StoreOrderListPage extends State { ///选规格弹窗 showStoreSelector(MiNiDetail miNiDetail) { + String selectSku = ""; + int selectCount = 1; showModalBottomSheet( context: context, backgroundColor: Colors.transparent, builder: (context) { - return StatefulBuilder(builder: (context1, state) - { - return ProductSku(miNiDetail); + return StatefulBuilder(builder: (context1, state) { + return Container( + alignment: Alignment.topCenter, + padding: EdgeInsets.only(top: 16, left: 16, right: 16), + width: double.infinity, + decoration: BoxDecoration( + color: Color(0xFFFAFAFA), + borderRadius: BorderRadius.only( + topLeft: Radius.circular(8), + topRight: Radius.circular(8), + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + MImage( + miNiDetail.imgs[0], + width: 70, + height: 70, + fit: BoxFit.cover, + errorSrc: "assets/image/default_1.png", + fadeSrc: "assets/image/default_1.png", + ), + SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + miNiDetail.productName, + style: TextStyle( + color: Colors.black, + fontSize: 16.sp, + fontWeight: MyFontWeight.medium, + ), + ), + Padding( + padding: EdgeInsets.only(top: 4, bottom: 7), + child: Text( + "已选:" + selectSku, + style: TextStyle( + color: Color(0xFF727272), + fontSize: 11.sp, + fontWeight: MyFontWeight.regular, + ), + ), + ), + Row( + children: [ + Text( + S.of(context).huiyuanjia, + style: TextStyle( + color: Color(0xFFFF7A1A), + fontSize: 13.sp, + fontWeight: MyFontWeight.medium, + ), + ), + Text( + miNiDetail.price, + style: TextStyle( + color: Color(0xFFFF7A1A), + fontSize: 14.sp, + fontWeight: MyFontWeight.medium, + ), + ) + ], + ), + ], + ), + Spacer(), + InkWell( + onTap: () { + Navigator.of(context).pop(); + }, + child: Image.asset( + "assets/image/icon_order_cancel.png", + width: 22, + height: 22, + ), + ), + ], + ), + SizedBox( + height: 23, + ), + Expanded( + child: ListView.builder( + itemCount: miNiDetail.attrList.length, + scrollDirection: Axis.vertical, + physics: BouncingScrollPhysics(), + itemBuilder: (context, position) { + return attrItem(() { + state(() { + for (var i = 0; + i < + miNiDetail + .attrList[position].attrValueList.length; + i++) { + if (tempClickIndex == i) + miNiDetail.attrList[position].attrValueList[i] + .isSelected = true; + else + miNiDetail.attrList[position].attrValueList[i] + .isSelected = false; + } + selectSku = ""; + miNiDetail.attrList.forEach((e0) { + e0.attrValueList.forEach((e1) { + if (e1.isSelected ?? false) + selectSku += e1.attrValue + " "; + }); + }); + }); + }, miNiDetail.attrList[position]); + }, + )), + SizedBox( + height: 24, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Text( + "数量", + style: TextStyle( + color: Colors.black, + fontSize: 14.sp, + fontWeight: MyFontWeight.regular, + ), + )), + InkWell( + onTap: () { + state(() { + if (selectCount > 1) selectCount--; + }); + }, + child: Image.asset( + "assets/image/reduce.png", + width: 22, + height: 22, + ), + ), + Padding( + padding: EdgeInsets.only(left: 8, right: 8), + child: Text( + selectCount.toString(), + style: TextStyle( + color: Colors.black, + fontSize: 14.sp, + fontWeight: MyFontWeight.medium, + ), + ), + ), + InkWell( + onTap: () { + state(() { + selectCount++; + }); + }, + child: Image.asset( + "assets/image/add.png", + width: 22, + height: 22, + ), + ), + ], + ), + SizedBox( + height: 24, + ), + GestureDetector( + onTap: () { + bool flag = false; + miNiDetail.productSkuVOList.forEach((element) { + if (selectSku.trim() == element.skuNameStr) { + Navigator.of(context).pop(); + flag = true; + } + }); + if (!flag) + SmartDialog.showToast("请选择規格!", + alignment: Alignment.center); + }, + child: RoundButton( + width: double.infinity, + height: 54.h, + text: "加入购物车", + textColor: Colors.white, + fontWeight: MyFontWeight.semi_bold, + radius: 27, + backgroup: Color(0xFF32A060), + fontSize: 16.sp, + // padding: EdgeInsets.symmetric(vertical: 5.h), + ), + ), + SizedBox( + height: 21.h, + ), + ], + ), + ); }); - } - ); + }, + ); + } + + Widget attrItem(Function fc, AttrListBean attrListBean) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(top: 24, bottom: 16), + child: Text( + attrListBean.attrName, + style: TextStyle( + color: Colors.black, + fontSize: 14.sp, + fontWeight: MyFontWeight.regular, + ), + )), + sweetnessStore(fc, attrListBean.attrValueList), + ], + ); + } + + Widget sweetnessStore(Function fc, List arrays) { + return GridView.builder( + itemCount: arrays.length, + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + //一行的Widget数量 + crossAxisCount: 4, + //水平子Widget之间间距 + crossAxisSpacing: 6.w, + //垂直子Widget之间间距 + mainAxisSpacing: 12.w, + //垂直单个子Widget之间间距 + childAspectRatio: 3 / 1), + itemBuilder: (contetx, index) { + return GestureDetector( + onTap: () { + tempClickIndex = index; + fc(); + }, + child: sweetnessItem( + arrays[index].attrValue, arrays[index].isSelected ?? false), + ); + }, + ); + } + + Widget sweetnessItem(String name, bool isCheck) { + return Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + RoundButton( + width: 68.w, + height: 29.h, + text: name, + textColor: !isCheck ? Color(0xFF727272) : Colors.white, + fontWeight: MyFontWeight.regular, + radius: 4, + backgroup: !isCheck ? Color(0xFFE5E5E5) : Color(0xFF32A060), + fontSize: 12.sp, + ), + ], + ), + ); } }