import 'dart:convert'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:huixiang/constant.dart'; import 'package:huixiang/data/base_data.dart'; import 'package:huixiang/data/goods.dart'; import 'package:huixiang/data/goods_category.dart'; import 'package:huixiang/data/page.dart'; import 'package:huixiang/data/user_info.dart'; import 'package:huixiang/generated/l10n.dart'; import 'package:huixiang/retrofit/retrofit_api.dart'; import 'package:huixiang/utils/flutter_utils.dart'; import 'package:huixiang/utils/font_weight.dart'; import 'package:huixiang/utils/shared_preference.dart'; import 'package:huixiang/view_widget/classic_header.dart'; import 'package:huixiang/view_widget/custom_image.dart'; import 'package:huixiang/view_widget/my_footer.dart'; import 'package:huixiang/view_widget/my_tab.dart'; import 'package:huixiang/view_widget/no_data_view.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; class WelfareExchange extends StatefulWidget { @override State createState() { return _WelfareExchange(); } } class _WelfareExchange extends State with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin { ApiService? apiService; final RefreshController refreshController = RefreshController(); int pageNum = 1; //排序类型枚举:1-自然排序,2-销量,3-价格 int orderType = 1; //是否降序排列 bool orderDesc = true; List goods = []; List gooods = []; List gooodsCategorys = []; UserInfo? userInfo; String? categoryId; @override void dispose() { super.dispose(); refreshController.dispose(); } @override void initState() { super.initState(); apiService = ApiService(Dio(), context: context, token: SharedInstance.instance.token, showLoading: false); creditGoods(); } queryUser() async { BaseData? baseData = await apiService?.queryInfo().catchError((onError) { return BaseData()..isSuccess = false; }); if ((baseData?.isSuccess ?? false) && baseData!.data != null) { userInfo = baseData.data; SharedInstance.instance.saveUser(baseData.data!); } } creditGoods({bool isLoading = true}) async { try { if (isLoading) S.current.zhengzaijiazai.loading; apiService = ApiService(Dio(), context: context, token: SharedInstance.instance.token, showLoading: false); await queryUser(); BaseData>? goodsData = await apiService?.creditGoods({ "orderDesc": true, "orderType": 1, "pageNum": 1, "pageSize": 100, "state": 1 }).catchError((onError) { refreshController.refreshFailed(); return BaseData>()..isSuccess = false; }); if (goodsData?.isSuccess ?? false) { gooods.clear(); gooods.addAll(goodsData?.data?.list ?? []); } BaseData>? dataCategory = await apiService?.goodsCategory({ "current": 1, "map": {}, "model": {"pageNum": 1, "pageSize": 20, "searchKey": ""}, "order": "descending", "size": 20, "sort": "sortOrder" }).catchError((onError) { refreshController.loadFailed(); refreshController.refreshFailed(); return BaseData>()..isSuccess = false; }); if ((dataCategory?.isSuccess ?? false) && (dataCategory?.data?.records?.isNotEmpty ?? false)) { gooodsCategorys.clear(); gooodsCategorys.add(GoodsCategory()..name = S.of(context).quanbu); gooodsCategorys.addAll(dataCategory?.data?.records ?? []); } var param = { "categoryId": categoryId ?? "", "orderDesc": orderDesc, "orderType": orderType, "pageNum": pageNum, "pageSize": 100, "state": 1 }; BaseData>? pageGoods = await apiService?.creditGoods(param).catchError((onError) { refreshController.loadFailed(); refreshController.refreshFailed(); return BaseData>()..isSuccess = false; }); if (pageGoods?.isSuccess ?? false) { if (pageNum == 1) { goods.clear(); } goods.addAll(pageGoods?.data?.list ?? []); refreshController.refreshCompleted(); refreshController.loadComplete(); if (pageGoods?.data?.pageNum == pageGoods?.data?.pages) { refreshController.loadNoData(); } else { pageNum += 1; } } else { refreshController.loadFailed(); refreshController.refreshFailed(); } } finally { setState(() {}); } } _onRefresh() { creditGoods(isLoading: false); } @override Widget build(BuildContext context) { super.build(context); return Scaffold( backgroundColor: Colors.white, body: NestedScrollView( headerSliverBuilder: (context, inner) { return [ SliverAppBar( pinned: true, backgroundColor: Color(0xFF277D4B), elevation: 0, title: Text( S.of(context).fuliduihuan, style: TextStyle( fontWeight: FontWeight.w500, color: Colors.white, ), ), centerTitle: true, leading: GestureDetector( onTap: () { Navigator.of(context).pop(); }, child: Container( alignment: Alignment.centerRight, margin: EdgeInsets.only(left: 10.w), padding: EdgeInsets.all(6), child: Icon( Icons.arrow_back_ios, color: Colors.white, size: 24, ), ), ), toolbarHeight: kToolbarHeight, collapsedHeight: kToolbarHeight + MediaQuery.of(context).padding.top, flexibleSpace: FlexibleSpaceBar( background: Stack( children: [ Positioned.fill( top: kToolbarHeight + MediaQuery.of(context).padding.top, child: Container( // padding: EdgeInsets.only(top: 40.h), height: 172.h - (kToolbarHeight + MediaQuery.of(context).padding.top), decoration: BoxDecoration( color: Colors.white, ), padding: EdgeInsets.only(bottom: 75.h), child: Container( decoration: BoxDecoration( color: Color(0xFF277D4B), shape: BoxShape.rectangle, borderRadius: BorderRadius.only( bottomRight: Radius.circular(40.r), bottomLeft: Radius.circular(40.r), ), ), ), ), ), Container( alignment: Alignment.topCenter, margin: EdgeInsets.only(top: 110.h), child: pointUser(), ), ], ), ), expandedHeight: MediaQuery.of(context).size.height >= 750 ? 245.h : 258.h, bottom: PreferredSize( preferredSize: Size(double.infinity, 0), child: DefaultTabController( length: gooodsCategorys.length, child: Container( color: Colors.white, alignment: Alignment.centerLeft, child: TabBar( isScrollable: true, //可滚动 indicatorColor: Color(0xff39B54A), labelColor: Color(0xff32A060), dividerHeight: 0, tabAlignment: TabAlignment.start, labelStyle: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.bold, ), unselectedLabelStyle: TextStyle( fontSize: 14.sp, fontWeight: MyFontWeight.regular, ), // controller: tabController, //未选中文字颜色 unselectedLabelColor: Color(0xff4D4D4D), indicatorSize: TabBarIndicatorSize.label, //指示器与文字等宽 tabs: gooodsCategorys.map((e) => MyTab(text: "${e.name}")).toList(), onTap: (index) { categoryId = gooodsCategorys[index].id; pageNum = 1; creditGoods(); }, ), ), ), ), ), ]; }, body: SmartRefresher( controller: refreshController, enablePullDown: true, enablePullUp: false, physics: ClampingScrollPhysics(), header: MyHeader(), footer: CustomFooter( builder: (context, mode) { return MyFooter(mode); }, ), onRefresh: _onRefresh, child: Container( color: Colors.white, child: pointList(), ), ), ), ); } Widget pointUser() { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(4.r)), boxShadow: [ BoxShadow( color: Colors.black.withAlpha(12), offset: Offset(0, 1), blurRadius: 8, spreadRadius: 0, ), ], ), margin: EdgeInsets.all(16), padding: EdgeInsets.all(16), child: Row( children: [ MImage( userInfo?.headimg ?? "", width: 50, height: 50, isCircle: true, fit: BoxFit.cover, errorSrc: "assets/image/default_user.webp", fadeSrc: "assets/image/default_user.webp", ), Expanded( child: Container( margin: EdgeInsets.only(left: 12.w), height: 55.h, child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.start, children: [ userInfo == null ? Text( S.of(context).denglu, style: TextStyle( fontSize: 16.sp, fontWeight: MyFontWeight.medium, color: Color(0xFF353535), ), ) : Text( userInfo?.nickname ?? "", style: TextStyle( fontSize: 16.sp, fontWeight: MyFontWeight.bold, color: Color(0xFF353535), ), ), SizedBox( height: 2.h, ), userInfo == null ? Text( S.of(context).weidengluxinxi, style: TextStyle( fontSize: 12.sp, fontWeight: MyFontWeight.regular, color: Color(0xFF353535), ), ) : Text( userInfo == null ? "" : AppUtils.phoneEncode(userInfo?.phone ?? ""), style: TextStyle( fontSize: 12.sp, fontWeight: MyFontWeight.regular, color: Color(0xFF353535), ), ), ], ), ), flex: 1, ), userInfo == null ? Icon( Icons.keyboard_arrow_right, size: 20, color: Colors.black, ) : Container( margin: EdgeInsets.only(left: 15.w), height: 62.h, child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( "总积分", style: TextStyle( fontSize: 14.sp, fontWeight: MyFontWeight.medium, color: Color(0xFF4C4C4C), ), ), Padding( padding: EdgeInsets.only(left: 2.w), child: Text( "${userInfo?.points}" ?? "", style: TextStyle( fontSize: 16.sp, color: Color(0xFF32A060), fontFamily: 'JDZhengHT', fontWeight: MyFontWeight.medium, ), ), ), SizedBox( width: 4.w, ), Image.asset( "assets/image/icon_gold_coin.webp", width: 18, height: 18, ), ], ), SizedBox( height: 4.h, ), Row( children: [ Text( "总印章", style: TextStyle( fontSize: 14.sp, fontWeight: MyFontWeight.medium, color: Color(0xFF4C4C4C), ), ), Padding( padding: EdgeInsets.only(left: 2.w), child: Text( "${userInfo?.happyBean ?? 0}" ?? "", style: TextStyle( fontSize: 16.sp, color: Color(0xFF32A060), fontFamily: 'JDZhengHT', fontWeight: MyFontWeight.medium, ), ), ), SizedBox( width: 4.w, ), Image.asset( "assets/image/trading_logo.webp", width: 18, height: 18, ), ], ), ], ), ), ], ), ); } Widget pointList() { return Container( child: (goods.isEmpty) ? NoDataView( src: "assets/image/xiao_fei.webp", isShowBtn: false, text: "当前分类暂无商品", fontSize: 16.sp, margin: EdgeInsets.only( top: 120.h, left: 60.w, right: 60.w, ), ) : GridView.builder( itemCount: goods.length, padding: EdgeInsets.only( left: 12.w, right: 12.w, top: 16.h, bottom: 16.h, ), shrinkWrap: true, physics: BouncingScrollPhysics(), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( //一行的Widget数量 crossAxisCount: 2, //水平子Widget之间间距 crossAxisSpacing: 12.w, //垂直子Widget之间间距 mainAxisSpacing: 12.w, //子Widget宽高比例 0.59 childAspectRatio: 200 / (285 / 2 + (285 / 2) * AppUtils.textScale(context)), ), itemBuilder: (context, index) { return GestureDetector( onTap: () { Navigator.of(context).pushNamed( '/router/integral_store_page', arguments: {"goodsId": goods[index].id}, ); }, child: pointItem(goods[index]), ); }, ), ); } Widget pointItem(Goods goods) { return Container( alignment: Alignment.center, decoration: BoxDecoration( color: Color(0xFFFFFFFF), borderRadius: BorderRadius.circular(4), boxShadow: [ BoxShadow( color: Colors.black.withAlpha(12), offset: Offset(0, 2), blurRadius: 4, spreadRadius: 0, ), ], ), child: Stack( alignment: AlignmentDirectional.topEnd, fit: StackFit.loose, children: [ Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.max, children: [ MImage( goods.mainImgPath ?? "", aspectRatio: 1.1, fit: BoxFit.cover, radius: BorderRadius.only( topLeft: Radius.circular(4), topRight: Radius.circular(4), ), errorSrc: "assets/image/default_1.webp", fadeSrc: "assets/image/default_1.webp", ), Expanded( child: Container( margin: EdgeInsets.only( right: 12.w, top: 10.h, ), padding: EdgeInsets.only(bottom: 8.h, left: 8.w), child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( goods.name ?? "", overflow: TextOverflow.ellipsis, maxLines: 1, style: TextStyle( color: Color(0xFF0D0D0D), height: 1.2, fontWeight: MyFontWeight.regular, fontSize: 14.sp, ), ), Spacer(), Text( pointPrice(goods), overflow: TextOverflow.ellipsis, maxLines: 2, style: TextStyle( color: Color(0xFFE5600D), fontFamily: 'JDZhengHT', fontSize: 16.sp, fontWeight: MyFontWeight.semi_bold, ), ), ], ), ), flex: 1, ), ], ), ], ), ); } String pointPrice(Goods goods) { if (goods.oneBean != "0") { return "${goods.oneBean}印章"; } else if (goods.onePrice != "0") { return S.of(context).jifen_("${goods.onePrice}"); } else if ((goods.onePrice == "0") && ((goods.price != "0") || (goods.money != "0.00"))) { return (goods.price == "0" ? "" : S.of(context).jifen_("${goods.price}")) + (goods.money == "0" ? "" : " + ${AppUtils.calculateDouble(double.tryParse("${goods.money}") ?? 0)}元"); } else if (goods.oneMoney != "0.00") { return "${AppUtils.calculateDouble(double.tryParse("${goods.oneMoney}") ?? 0)}元"; } return ""; } @override bool get wantKeepAlive => true; }