import 'dart:io'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_html/flutter_html.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:fluwx/fluwx.dart'; import 'package:huixiang/generated/l10n.dart'; import 'package:huixiang/retrofit/data/base_data.dart'; import 'package:huixiang/retrofit/data/vip_card.dart'; import 'package:huixiang/retrofit/retrofit_api.dart'; import 'package:huixiang/store/scan.dart'; import 'package:huixiang/utils/font_weight.dart'; import 'package:huixiang/view_widget/custom_image.dart'; import 'package:huixiang/view_widget/my_appbar.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../retrofit/data/member_recharge_list.dart'; import '../retrofit/data/rechargeActLists.dart'; import '../retrofit/data/wx_pay.dart'; import '../retrofit/min_api.dart'; import '../utils/flutter_utils.dart'; import '../utils/min.dart'; import '../view_widget/classic_header.dart'; import '../view_widget/my_footer.dart'; import '../view_widget/no_data_view.dart'; import '../view_widget/recharge_details_dialog.dart'; import 'package:tobias/tobias.dart' as tobias; class MineShopRecharge extends StatefulWidget { final Map arguments; MineShopRecharge({this.arguments}); @override State createState() { return _MineShopRecharge(); } } class _MineShopRecharge extends State { ApiService apiService; MinApiService minService; VipCard vipCard; List memberRechargeList = []; int selectIndex = 0; double discount = 100; var checkIndex = 2; dynamic payListen; int _loadCount = 0; String tenant; String storeId; String minToken; final RefreshController refreshController = RefreshController(); @override void dispose() { super.dispose(); refreshController.dispose(); if (payListen != null) payListen.cancel(); } @override void initState() { super.initState(); storeId = widget.arguments["storeId"]; tenant = widget.arguments["tenantCode"]; _onRefresh(); payListen = weChatResponseEventHandler.listen((event) async { print("payCallback: ${event.errCode}"); if (event.errCode == 0) { SmartDialog.showToast("充值成功", alignment: Alignment.center); } else { SmartDialog.showToast("充值失败", alignment: Alignment.center); } vipDetail(); }); } ///会员卡详情 vipDetail({bool isSingle = true}) async { try { BaseData baseData = await apiService.vipDetail({ "id": widget.arguments["id"], "latitude": "", "longitude": "", }).catchError((onError) {}); if (baseData != null && baseData.isSuccess) { vipCard = baseData.data; } } finally { if (isSingle) setState(() {}); else addLoadCount(); } } ///小程序登录 minLogin() async { try { var baseData = await apiService.minLogin(storeId).catchError((onError) { debugPrint(onError.toString()); }); if (baseData != null && baseData.isSuccess) { minToken = baseData.data["token"]; SharedPreferences.getInstance().then( (value) => { value.setString('minToken', minToken), value.setString('tenant', tenant), value.setString('storeId', storeId), }, ); minService = MinApiService( Dio(), context: context, token: minToken, tenant: tenant, storeId: storeId, ); } } finally {} } ///充值列表 queryRechargeActList() async { try { BaseData> baseData = await minService.memberRechargeList().catchError((onError) {}); if (baseData != null && baseData.isSuccess) { memberRechargeList = baseData.data; } } finally { addLoadCount(); } } ///门店充值 shopRecharge() async { if (minService == null) await minLogin(); BaseData baseData = await minService.memberRecharge({ "money": 0, "rechargeId": memberRechargeList[selectIndex].id, "type": checkIndex == 2 ? "wechat" : "alipay", }).catchError((error) {}); if (baseData != null && baseData.isSuccess) { if (checkIndex == 2) { if (Platform.isAndroid) { if (!(await Min.isInitialize())) { // 小程序的微信支付和app的充值支付使用同一个WXPayEntryActivity回调, // 然而充值时小程序未初始化会导致回调内部代码调用getPackage空指针, // 故而在此初始化一下 await Min.initialize(); } } WxPay wxPay = WxPay.fromJson(baseData.data); await registerWxApi( appId: wxPay.appId, doOnAndroid: true, universalLink: "https://hx.lotus-wallet.com/app/", ); payWithWeChat( appId: wxPay.appId, partnerId: wxPay.partnerId, prepayId: wxPay.prepayId, packageValue: wxPay.packageValue, nonceStr: wxPay.nonceStr, timeStamp: int.tryParse(wxPay.timeStamp), sign: wxPay.sign, ); } else { tobias.isAliPayInstalled().then((value) => { // 判断是否安装了支付宝 if (!value) {SmartDialog.showToast("请安装支付宝", alignment: Alignment.center)} else { tobias.aliPay(baseData.data["body"]).then((payRes) { if (payRes['resultStatus'] == 9000 || payRes['resultStatus'] == '9000') { SmartDialog.showToast("充值成功", alignment: Alignment.center); } else { SmartDialog.showToast(payRes['memo'], alignment: Alignment.center); } vipDetail(); }) } }); } } else { SmartDialog.showToast(baseData.msg, alignment: Alignment.center); } } _onRefresh() async { EasyLoading.show( status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black); if (apiService == null) { SharedPreferences value = await SharedPreferences.getInstance(); apiService = ApiService(Dio(), context: context, token: value.getString("token")); } if (minService == null) await minLogin(); vipDetail(isSingle: false); queryRechargeActList(); } addLoadCount() { _loadCount += 1; if (_loadCount == 2) { _loadCount = 0; EasyLoading.dismiss(); if (refreshController.isRefresh) refreshController.refreshCompleted(); if (mounted) setState(() {}); } } @override Widget build(BuildContext context) { return Scaffold( appBar: MyAppBar( title: "店铺充值", titleColor: Colors.black, background: Colors.white, brightness: Brightness.dark, leadingColor: Colors.black, ), body: SmartRefresher( enablePullDown: true, enablePullUp: false, header: MyHeader(), footer: CustomFooter( builder: (context, mode) { return MyFooter(mode); }, ), controller: refreshController, onRefresh: _onRefresh, physics: BouncingScrollPhysics(), child: Column( children: [ shopRechargeCard(), (memberRechargeList != null && (memberRechargeList?.length ?? 0) > 0) ? Expanded( child: ListView.builder( padding: EdgeInsets.zero, itemCount: (memberRechargeList != null && (memberRechargeList?.length ?? 0) > 0) ? memberRechargeList.length : 0, scrollDirection: Axis.vertical, shrinkWrap: true, physics: BouncingScrollPhysics(), itemBuilder: (context, position) { return GestureDetector( onTap: () { setState(() { selectIndex = position; }); }, child: rechargeItem( memberRechargeList[position], position)); }, )) : NoDataView( src: "assets/image/xiao_fei.webp", isShowBtn: false, text: "当前店铺暂无充值套餐~", fontSize: 16.sp, margin: EdgeInsets.only(top: 90.h, left: 60.w, right: 60.w), ), if (memberRechargeList != null && (memberRechargeList?.length ?? 0) > 0) Container( width: double.infinity, margin: EdgeInsets.only(left: 16, right: 16), padding: EdgeInsets.only( top: 20.h, bottom: 24.h, ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.only(bottom: 16.h), child: Text( S.of(context).zhifufangshi, style: TextStyle( fontSize: 16.sp, color: Colors.black, fontWeight: FontWeight.bold, ), ), ), GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { setState(() { checkIndex = 2; }); }, child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Image.asset("assets/image/icon_we_chat.webp"), Expanded( flex: 1, child: Padding( padding: EdgeInsets.only(left: 8.w), child: Text( S.of(context).weixinzhifu, style: TextStyle( fontSize: 14.sp, color: Color(0xff353535), ), ), ), ), checkView(2), ], ), ), SizedBox(height: 10.h), GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { setState(() { checkIndex = 3; }); }, child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Image.asset("assets/image/icon_alipay.webp"), Expanded( flex: 1, child: Padding( padding: EdgeInsets.only(left: 8.w), child: Text( S.of(context).zhifubao, style: TextStyle( fontSize: 14.sp, color: Color(0xff353535), ), ), ), ), checkView(3), ], ), ), ], ), ), if (memberRechargeList != null && (memberRechargeList?.length ?? 0) > 0) Align( alignment: Alignment.bottomCenter, child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { shopRecharge(); }, child: Container( height: 56.h, width: double.infinity, alignment: Alignment.center, decoration: BoxDecoration( color: Color(0xFF32A060), borderRadius: BorderRadius.circular(27), ), margin: EdgeInsets.only( top: 12.h, left: 16.w, right: 16.w, bottom: 21.h), child: Text( S.of(context).querenchongzhi, style: TextStyle( fontSize: 16.sp, fontWeight: MyFontWeight.medium, color: Colors.white, ), ), ), ), ) ], ), )); } ///卡片背景底色 int colorByName(String storeName) { if (storeName == null) return 0xFF32A060; if (storeName.contains("百年川椒") || storeName.contains("百年川椒")) { return 0xFFC30D23; } else if (storeName.contains("海峡姐妹") || storeName.contains("海峽姐妹")) { return 0xFFE4C796; } else if (storeName.contains("前进麦味") || storeName.contains("前進麥味")) { return 0xFF265782; } return 0xFF32A060; } ///卡片详情 Widget shopRechargeCard() { return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { Navigator.of(context).pushNamed('/router/mine_shop_details', arguments: {"id": widget.arguments["id"]}); }, child: Container( width: double.infinity, // height:140.h, margin: EdgeInsets.only(bottom: 24.h, top: 14.h, left: 14.w, right: 14.w), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( decoration: BoxDecoration( borderRadius: new BorderRadius.only( topLeft: Radius.circular(6), topRight: Radius.circular(6), ), color: Color(colorByName(vipCard?.tenantName ?? "")), ), padding: EdgeInsets.only(left: 12.w), height: 62.h, child: Row( children: [ MImage( (vipCard?.storeList?.length ?? 0) > 0 ? vipCard.storeList[0].logo : "", width: 38, height: 38, radius: BorderRadius.circular(100), fit: BoxFit.cover, errorSrc: "assets/image/default_1.webp", fadeSrc: "assets/image/default_1.webp", ), SizedBox( width: 6, ), Text( vipCard != null ? vipCard.tenantName : "", style: TextStyle( color: Color(0xFFFFFFFF), fontSize: 15.sp, fontWeight: MyFontWeight.medium, ), ), ], ), ), Container( decoration: BoxDecoration( borderRadius: new BorderRadius.only( bottomRight: Radius.circular(6), topRight: Radius.circular(6), ), color: Colors.white, ), padding: EdgeInsets.all(12.h), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "店铺余额(元)", style: TextStyle( color: Color(0xFF262626), fontSize: 12.sp, fontWeight: MyFontWeight.regular, ), ), Text( "No.${vipCard?.id ?? ""}", style: TextStyle( color: Color(0xFF262626), fontSize: 12.sp, fontWeight: MyFontWeight.regular, ), ), ], ), SizedBox( height: 4.h, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: Text( "¥ ${vipCard != null ? vipCard.balance : ""}", style: TextStyle( color: Color(0xFF262626), fontSize: 24.sp, fontFamily: 'JDZhengHT', fontWeight: MyFontWeight.medium, ), ), ), Text( "适用门店", style: TextStyle( color: Color(0xFF262626), fontSize: 12.sp, fontWeight: MyFontWeight.regular, ), ), SizedBox( width: 2, ), Image.asset( "assets/image/icon_right_z.webp", width: 16, height: 16, color: Color(0xFF262626), ) ], ), ], ), ), ], ), ), ); } ///充值item Widget rechargeItem(MemberRechargeList memberRechargeList, index) { return Container( width: double.infinity, height: 69.h, decoration: BoxDecoration( borderRadius: BorderRadius.circular(4), border: Border.all( color: selectIndex == index ? Color(0xFF32A060) : Color(0xFFFAFAFA), width: selectIndex == index ? 1 : 0, ), color: selectIndex == index ? Color(0XFFF0FAF4) : Colors.white), margin: EdgeInsets.only(bottom: 14.h, left: 14.w, right: 14.w), padding: EdgeInsets.only(left: 16), child: Flex( direction: Axis.horizontal, children: [ Expanded( flex: 1, child: Container( child: Text.rich( TextSpan(children: [ TextSpan( text: "储值 ", style: TextStyle( fontSize: 12.sp, color: selectIndex == index ? Color(0xFF4D4D4D) : Color(0xFF868686), fontWeight: MyFontWeight.regular), ), TextSpan( text: "${AppUtils.calculateDouble(double.tryParse(memberRechargeList.rechargeMoney) ?? 0)}元", style: TextStyle( fontSize: 18.sp, fontFamily: 'JDZhengHT', color: selectIndex == index ? Color(0xFF353535) : Color(0xFF868686), fontWeight: MyFontWeight.semi_bold), ), ]), ), )), Container( width: 1.w, height: 37.h, color: selectIndex == index ? Color(0xFF32A060) : Color(0xFF979797), margin: EdgeInsets.only(right: 16.w, left: 12), ), Expanded( flex: 2, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text.rich( TextSpan(children: [ TextSpan( text: "实际到账 ", style: TextStyle( fontSize: 12.sp, color: selectIndex == index ? Color(0xFF353535) : Color(0xFF868686), fontWeight: MyFontWeight.regular), ), TextSpan( text: "${((memberRechargeList?.limitNum ?? 0) != 0 && ((memberRechargeList?.limitNum ?? 0) - (memberRechargeList?.useNum ?? 0) <= 0)) ? (AppUtils.calculateDouble(double.tryParse(memberRechargeList.rechargeMoney) ?? 0)) : (AppUtils.calculateDouble((double.tryParse(memberRechargeList.rechargeMoney) ?? 0) + (double.tryParse(memberRechargeList.giftdMoney) ?? 0) + ((double.tryParse(memberRechargeList.rechargeMoney) ?? 0) - ((double.tryParse(memberRechargeList.rechargeMoney) ?? 0) * (discount / 100)))))}元", style: TextStyle( fontSize: 18.sp, fontFamily: 'JDZhengHT', color: selectIndex == index ? Color(0xFF353535) : Color(0xFF868686), fontWeight: MyFontWeight.semi_bold), ), ]), ), SizedBox( height: 4.h, ), GestureDetector( onTap: () { setState(() { if (selectIndex == index) showRecharge(memberRechargeList, index); }); }, child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( "充值说明", style: TextStyle( color: selectIndex == index ? Color(0xFF4D4D4D) : Color(0xFF868686), fontSize: 12.sp, fontWeight: MyFontWeight.regular, ), ), Icon( Icons.chevron_right, size: 20, color: selectIndex == index ? Color(0xFF353535) : Color(0xFF868686), ), ], )), ], )) ], )); } Widget checkView(var index) { return Container( padding: EdgeInsets.only(right: 16.w, left: 46.w), alignment: Alignment.center, child: Image.asset( checkIndex != index ? "assets/image/icon_radio_unselected.webp" : "assets/image/icon_radio_selected.webp", width: 15.w, height: 15.h, ), ); } ///充值说明底部弹窗 showRecharge(MemberRechargeList memberRechargeList, index) { showModalBottomSheet( context: context, backgroundColor: Colors.transparent, builder: (context) { return Container( padding: EdgeInsets.only(top: 12), decoration: new BoxDecoration( color: Colors.white, borderRadius: new BorderRadius.only( topLeft: const Radius.circular(25.0), topRight: const Radius.circular(25.0))), child: Container( height: 355, child: SingleChildScrollView( physics: BouncingScrollPhysics(), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: Container( margin: EdgeInsets.symmetric(vertical: 12.h), alignment: Alignment.center, child: Text( "充值说明", style: TextStyle( fontWeight: MyFontWeight.bold, fontSize: 15.sp, color: Color(0xFF353535), ), ), )), GestureDetector( onTap: () { setState(() { Navigator.of(context).pop(); }); }, child: Icon( Icons.clear, color: Colors.black, size: 18, ), ), SizedBox(width: 14), ], ), SizedBox( height: 12.h, ), Container( width: double.infinity, height: 1.h, color: Color(0xFFF2F2F2), margin: EdgeInsets.only(bottom: 13.h), ), Padding( padding: EdgeInsets.only(left: 14), child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Expanded( child: Container( color: Colors.white, child: Html( data: memberRechargeList?.remark ?? "", customImageRenders: { networkSourceMatcher(): networkImageRender( loadingWidget: () { return Container(); }, ), }, ), ), ) ], ), ) ], ), ))); }); } Widget shopItem(StoreListBean store) { return Container( decoration: BoxDecoration( borderRadius: new BorderRadius.circular(6), color: Colors.white, ), padding: EdgeInsets.all(12), margin: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h), child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( flex: 1, child: Text( (store != null) ? store.storeName : "", style: TextStyle( fontSize: 14.sp, fontWeight: MyFontWeight.semi_bold, color: Colors.black, ), ), ), GestureDetector( onTap: () { // Navigator.of(context).pushNamed('/router/union_detail_page', // arguments: {"id": store.id}); if (store.posType.code == "NORMALSTORE") { Scan.toScan( context, store.id, store.tenantCode, store.storeName, ); } else { Navigator.of(context).pushNamed( '/router/store_order', arguments: { "id": store.id, "tenant": store.tenantCode, "storeName": store.storeName }, ); } }, child: Text( S.of(context).chakan, style: TextStyle( fontSize: 12.sp, fontWeight: MyFontWeight.medium, color: Color(0xff32A060), ), ), ), Icon( Icons.chevron_right, color: Color(0xff32A060), size: 16, ), ], ), SizedBox( height: 8.h, ), Row( children: [ Text( "${S.of(context).dizhi}: ", style: TextStyle( fontSize: 12.sp, fontWeight: MyFontWeight.regular, color: Color(0xff353535), ), ), Expanded( child: Text( store.address, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 12.sp, fontWeight: MyFontWeight.regular, color: Color(0xff353535), ), ), flex: 1, ) ], ), SizedBox( height: 4.h, ), Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( flex: 1, child: Text( S.of(context).yingyeshijian((store.openStartTime == null && store.openEndTime == null) ? S.of(context).quantian : "${store.openStartTime.substring(0, store.openStartTime.lastIndexOf(":"))} - ${store.openEndTime.substring(0, store.openEndTime.lastIndexOf(":"))}"), style: TextStyle( fontSize: 12.sp, fontWeight: MyFontWeight.regular, color: Color(0xff353535), ), ), ), Text( (store.distance ?? 0) > 1000 ? S.of(context).gongli( ((store.distance ?? 0) / 1000 * 100).toInt() / 100.0) : S .of(context) .mi(((store.distance ?? 0) * 100).toInt() / 100.0), style: TextStyle( fontSize: 12.sp, fontWeight: MyFontWeight.regular, color: Color(0xff868686), ), ), ], ), ], ), ); } }