diff --git a/README.md b/README.md index cbc20081..aa4f7f4f 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,9 @@ samples, guidance on mobile development, and a full API reference. 小米开放平台 83364300@qq.com 具体问 :(汪姐) 推送:使用腾讯云推送 tpns 需扫码登录 (有问题同华为➕微信||或重新注册账号替换相关appKey) + + 友盟: wu_rong 密码:Zxc09876 + https://pos.platform.lotus-wallet.com/app/ 生产环境 http://192.168.10.236:8765/app/ 测试环境 diff --git a/assets/image/2x/icon_by_bike.webp b/assets/image/2x/icon_by_bike.webp new file mode 100644 index 00000000..50ccc0ed Binary files /dev/null and b/assets/image/2x/icon_by_bike.webp differ diff --git a/assets/image/2x/icon_drive.webp b/assets/image/2x/icon_drive.webp new file mode 100644 index 00000000..972be59d Binary files /dev/null and b/assets/image/2x/icon_drive.webp differ diff --git a/assets/image/2x/icon_search.webp b/assets/image/2x/icon_search.webp new file mode 100644 index 00000000..7aa75c66 Binary files /dev/null and b/assets/image/2x/icon_search.webp differ diff --git a/assets/image/2x/icon_transit.webp b/assets/image/2x/icon_transit.webp new file mode 100644 index 00000000..523aa8b0 Binary files /dev/null and b/assets/image/2x/icon_transit.webp differ diff --git a/assets/image/2x/icon_walk.webp b/assets/image/2x/icon_walk.webp new file mode 100644 index 00000000..38e49db1 Binary files /dev/null and b/assets/image/2x/icon_walk.webp differ diff --git a/assets/image/2x/position_sort.webp b/assets/image/2x/position_sort.webp new file mode 100644 index 00000000..afb9000e Binary files /dev/null and b/assets/image/2x/position_sort.webp differ diff --git a/assets/image/3x/icon_by_bike.webp b/assets/image/3x/icon_by_bike.webp new file mode 100644 index 00000000..de4e78ae Binary files /dev/null and b/assets/image/3x/icon_by_bike.webp differ diff --git a/assets/image/3x/icon_drive.webp b/assets/image/3x/icon_drive.webp new file mode 100644 index 00000000..098241c2 Binary files /dev/null and b/assets/image/3x/icon_drive.webp differ diff --git a/assets/image/3x/icon_search.webp b/assets/image/3x/icon_search.webp new file mode 100644 index 00000000..d3f8316e Binary files /dev/null and b/assets/image/3x/icon_search.webp differ diff --git a/assets/image/3x/icon_transit.webp b/assets/image/3x/icon_transit.webp new file mode 100644 index 00000000..11283036 Binary files /dev/null and b/assets/image/3x/icon_transit.webp differ diff --git a/assets/image/3x/icon_walk.webp b/assets/image/3x/icon_walk.webp new file mode 100644 index 00000000..98d95216 Binary files /dev/null and b/assets/image/3x/icon_walk.webp differ diff --git a/assets/image/3x/position_sort.webp b/assets/image/3x/position_sort.webp new file mode 100644 index 00000000..b51630af Binary files /dev/null and b/assets/image/3x/position_sort.webp differ diff --git a/assets/image/icon_by_bike.webp b/assets/image/icon_by_bike.webp new file mode 100644 index 00000000..d7871091 Binary files /dev/null and b/assets/image/icon_by_bike.webp differ diff --git a/assets/image/icon_drive.webp b/assets/image/icon_drive.webp new file mode 100644 index 00000000..67dcf346 Binary files /dev/null and b/assets/image/icon_drive.webp differ diff --git a/assets/image/icon_end.png b/assets/image/icon_end.png new file mode 100644 index 00000000..2f288f4c Binary files /dev/null and b/assets/image/icon_end.png differ diff --git a/assets/image/icon_search.webp b/assets/image/icon_search.webp new file mode 100644 index 00000000..d785e21d Binary files /dev/null and b/assets/image/icon_search.webp differ diff --git a/assets/image/icon_start.png b/assets/image/icon_start.png new file mode 100644 index 00000000..ffc9a673 Binary files /dev/null and b/assets/image/icon_start.png differ diff --git a/assets/image/icon_transit.webp b/assets/image/icon_transit.webp new file mode 100644 index 00000000..844c3f1b Binary files /dev/null and b/assets/image/icon_transit.webp differ diff --git a/assets/image/icon_walk.webp b/assets/image/icon_walk.webp new file mode 100644 index 00000000..1ec11af8 Binary files /dev/null and b/assets/image/icon_walk.webp differ diff --git a/assets/image/position_sort.webp b/assets/image/position_sort.webp new file mode 100644 index 00000000..c0b20055 Binary files /dev/null and b/assets/image/position_sort.webp differ diff --git a/assets/image/traffic_texture_smooth.png b/assets/image/traffic_texture_smooth.png new file mode 100644 index 00000000..e4252dc4 Binary files /dev/null and b/assets/image/traffic_texture_smooth.png differ diff --git a/assets/image/traffic_texture_unknown.png b/assets/image/traffic_texture_unknown.png new file mode 100644 index 00000000..2e84a9cd Binary files /dev/null and b/assets/image/traffic_texture_unknown.png differ diff --git a/assets/map_style/chinese_cities.json b/assets/map_style/chinese_cities.json new file mode 100644 index 00000000..b2a647be --- /dev/null +++ b/assets/map_style/chinese_cities.json @@ -0,0 +1,14 @@ +{ + "热门城市": [ + {"area": "武汉"}, + {"area": "北京"}, + { "area": "郑州" } + ], + "B": [ + { "area": "北京" } + ], + "W": [{ "area": "武汉" }], + "Z": [ + { "area": "郑州" } + ] +} \ No newline at end of file diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 9c6ea487..7dc542bd 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -49,8 +49,7 @@ PODS: - image_pickers (0.0.1): - AFNetworking - Flutter - - SDWebImage - - ZLPhotoBrowser (~> 4.3.9) + - ZLPhotoBrowser-objc (= 1.0.4) - mob_sharesdk (4.4.15): - mob_sharesdk/ShareSDK (= 4.4.15) - MOBFoundation (>= 3.2.9) @@ -240,9 +239,8 @@ PODS: - Flutter - webview_flutter (0.0.1): - Flutter - - ZLPhotoBrowser (4.3.9): - - ZLPhotoBrowser/Core (= 4.3.9) - - ZLPhotoBrowser/Core (4.3.9) + - ZLPhotoBrowser-objc (1.0.4): + - SDWebImage DEPENDENCIES: - emoji_picker_flutter (from `.symlinks/plugins/emoji_picker_flutter/ios`) @@ -283,7 +281,7 @@ SPEC REPOS: - TPNS-iOS - UMCommon - UMDevice - - ZLPhotoBrowser + - ZLPhotoBrowser-objc EXTERNAL SOURCES: emoji_picker_flutter: @@ -347,7 +345,7 @@ SPEC CHECKSUMS: flutter_baidu_mapapi_utils: f6a5d23da26b0e58f1ae9908da7ba87fd48384b1 flutter_bmflocation: 1bd73181196567fe1529f765aa4f8e2615a8a3cf fluwx: 838466d89c1ba099f6eec36c514801658371cda5 - image_pickers: 4406949954a5eb4fac5ada5f13810e6419ef4467 + image_pickers: 25c8916d358bc9d2707cb470ba3d57497f105773 mob_sharesdk: 0698d60b3c1549a5b0bcfdec6f407439dd2960c0 MOBFoundation: 6df2684b4db4f0f5bd71b0623f82e11271bf7ac8 number_precision: 26fa2be2212f9d1429f92d667d6b0aa4df0058d8 @@ -370,7 +368,7 @@ SPEC CHECKSUMS: video_player_avfoundation: 6d971a232d72e6ee25368378d48a079dea01f1cf wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f webview_flutter: 5fb4def2bbd4339889ee14d045b605cefc5bc232 - ZLPhotoBrowser: 02b3569b8f702d2e153e8fdb1f6b32fef3a2867c + ZLPhotoBrowser-objc: c7657d3bc85ae231884e058d0e3638f619164736 PODFILE CHECKSUM: f8bac8842dd5d4f36a3709c129ae7a2ccd5be619 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 58e111ea..304ac515 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -617,7 +617,7 @@ CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 14; DEVELOPMENT_TEAM = YF3Q8DVP52; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -625,7 +625,6 @@ "$(PROJECT_DIR)/UniMPSDK/Libs", ); GCC_INPUT_FILETYPE = automatic; - GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "COCOAPODS=1", @@ -668,7 +667,7 @@ "$(PROJECT_DIR)/baidu", "$(PROJECT_DIR)/Runner/baidu", ); - MARKETING_VERSION = 3.2.19; + MARKETING_VERSION = 3.2.20; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ( "$(inherited)", @@ -820,16 +819,14 @@ CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 14; DEVELOPMENT_TEAM = YF3Q8DVP52; ENABLE_BITCODE = NO; - ENABLE_TESTABILITY = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/UniMPSDK/Libs", ); GCC_INPUT_FILETYPE = automatic; - GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "COCOAPODS=1", @@ -872,7 +869,7 @@ "$(PROJECT_DIR)/baidu", "$(PROJECT_DIR)/Runner/baidu", ); - MARKETING_VERSION = 3.2.19; + MARKETING_VERSION = 3.2.20; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ( "$(inherited)", @@ -915,7 +912,7 @@ CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 14; DEVELOPMENT_TEAM = YF3Q8DVP52; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -923,7 +920,6 @@ "$(PROJECT_DIR)/UniMPSDK/Libs", ); GCC_INPUT_FILETYPE = automatic; - GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "COCOAPODS=1", @@ -966,7 +962,7 @@ "$(PROJECT_DIR)/baidu", "$(PROJECT_DIR)/Runner/baidu", ); - MARKETING_VERSION = 3.2.19; + MARKETING_VERSION = 3.2.20; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ( "$(inherited)", diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index e12a98a1..173f6c23 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -177,5 +177,11 @@ location + LSApplicationQueriesSchemes + + iosamap + qqmap + baidumap + diff --git a/lib/address/address_map_page.dart b/lib/address/address_map_page.dart index f885d478..1324b146 100644 --- a/lib/address/address_map_page.dart +++ b/lib/address/address_map_page.dart @@ -80,6 +80,9 @@ class _AddressMapPage extends State { BMFMapOptions( center: latLng, zoomLevel: 15, + showZoomControl: false, + showMapScaleBar: false, + rotateEnabled: false, ), ); } @@ -339,6 +342,9 @@ class _AddressMapPage extends State { double.tryParse(value.getString("longitude")), ), zoomLevel: 15, + showZoomControl: false, + showMapScaleBar: false, + rotateEnabled: false, ), ); } @@ -362,7 +368,10 @@ class _AddressMapPage extends State { child: BMFMapWidget( mapOptions: BMFMapOptions( center: BMFCoordinate(30.553111, 114.342366), - zoomLevel: 12, + zoomLevel: 15, + showZoomControl: false, + showMapScaleBar: false, + rotateEnabled: false, ), onBMFMapCreated: onMapCreated, // onCameraMoveEnd: (cameraPosition) { diff --git a/lib/community/community_details.dart b/lib/community/community_details.dart index e4cacff3..3051a971 100644 --- a/lib/community/community_details.dart +++ b/lib/community/community_details.dart @@ -100,7 +100,7 @@ class _CommunityDetails extends State void initState() { super.initState(); // comunity = widget.arguments["comment"]; - EasyLoading.show(status: S.current.zhengzaijiazai); + EasyLoading.show(status: S.current.zhengzaijiazai,maskType: EasyLoadingMaskType.black); businessId = widget.arguments["businessId"]; WidgetsBinding.instance.addObserver(this); commentFocus.addListener(_focusNodeListener); @@ -399,7 +399,7 @@ class _CommunityDetails extends State ///评论列表 _queryMemberCommentList(bool isOnRefresh) async { - if (!isOnRefresh) EasyLoading.show(status: S.current.zhengzaijiazai); + if (!isOnRefresh) EasyLoading.show(status: S.current.zhengzaijiazai,maskType: EasyLoadingMaskType.black); SharedPreferences sharedPreferences = await SharedPreferences.getInstance(); if (apiService == null) apiService = ApiService( diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index a8f1f3e9..0a7d1dc0 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -193,6 +193,7 @@ class MessageLookup extends MessageLookupByLibrary { "dianhua" : MessageLookupByLibrary.simpleMessage("电话"), "dianjidenglu" : MessageLookupByLibrary.simpleMessage("点击登录,享受更多精彩信息"), "dianneiyongcan" : MessageLookupByLibrary.simpleMessage("店内用餐"), + "dianpuchongzhi" : MessageLookupByLibrary.simpleMessage("店铺充值"), "dianputuijian" : MessageLookupByLibrary.simpleMessage("店铺推荐"), "dianpuyue" : MessageLookupByLibrary.simpleMessage("店铺余额"), "dianwolingqu" : MessageLookupByLibrary.simpleMessage("点我领取"), @@ -309,6 +310,7 @@ class MessageLookup extends MessageLookupByLibrary { "huiyuanjifen" : MessageLookupByLibrary.simpleMessage("会员积分"), "huiyuanka" : MessageLookupByLibrary.simpleMessage("会员卡"), "huiyuankaxiangqing" : MessageLookupByLibrary.simpleMessage("会员卡详情"), + "huiyuanma" : MessageLookupByLibrary.simpleMessage("会员码"), "huiyuanquanyi" : MessageLookupByLibrary.simpleMessage("会员权益"), "huiyuanyue" : MessageLookupByLibrary.simpleMessage("会员余额"), "huiyuanzhongxin" : MessageLookupByLibrary.simpleMessage("会员中心"), @@ -468,6 +470,7 @@ class MessageLookup extends MessageLookupByLibrary { "privacy_policy2" : MessageLookupByLibrary.simpleMessage("《一心回乡服务协议》"), "privacy_policy3" : MessageLookupByLibrary.simpleMessage("《隐私服务》"), "privacy_policy4" : MessageLookupByLibrary.simpleMessage("并使用本机号码登录"), + "qianbao" : MessageLookupByLibrary.simpleMessage("钱包"), "qiandao" : MessageLookupByLibrary.simpleMessage("签到"), "qiandaodejifen" : MessageLookupByLibrary.simpleMessage("签到得积分"), "qiandaolingjifen" : MessageLookupByLibrary.simpleMessage("签到领积分"), @@ -740,6 +743,7 @@ class MessageLookup extends MessageLookupByLibrary { "yinsixieyi" : MessageLookupByLibrary.simpleMessage("《隐私协议》"), "yinsizhengce1" : MessageLookupByLibrary.simpleMessage(" 感谢您使用一心回乡APP。我们非常重视您的个人信息和隐私保护。为了更好地保证您的个人权益,在您使用我们的产品前,请务必仔细阅读一心回乡"), "yinsizhengce2" : MessageLookupByLibrary.simpleMessage("     在您同意后,我们才会根据您的使用需求,收集部分可能涉及的数据(地理位置、相机、存储等信息)。"), + "yinzhang" : MessageLookupByLibrary.simpleMessage("印章"), "yiqiandao" : MessageLookupByLibrary.simpleMessage("已签到"), "yiqianshou" : MessageLookupByLibrary.simpleMessage("已签收"), "yiquxiao" : MessageLookupByLibrary.simpleMessage(" 已取消 "), @@ -812,6 +816,7 @@ class MessageLookup extends MessageLookupByLibrary { "zhunongjifen" : MessageLookupByLibrary.simpleMessage("助农积分"), "zhunongzhuanqu" : MessageLookupByLibrary.simpleMessage("助农专区"), "zhuxiaotixing" : MessageLookupByLibrary.simpleMessage("再次提醒:注销帐号后不可恢复,相关数据和信息会永久删除。"), + "zhuxiaozhanghao" : MessageLookupByLibrary.simpleMessage("注销账号"), "ziqu" : MessageLookupByLibrary.simpleMessage("自取"), "ziti" : MessageLookupByLibrary.simpleMessage("自提"), "zitidizhi" : MessageLookupByLibrary.simpleMessage("自提地址"), diff --git a/lib/generated/intl/messages_en_US.dart b/lib/generated/intl/messages_en_US.dart index c0f7c5af..baadf09e 100644 --- a/lib/generated/intl/messages_en_US.dart +++ b/lib/generated/intl/messages_en_US.dart @@ -193,6 +193,7 @@ class MessageLookup extends MessageLookupByLibrary { "dianhua" : MessageLookupByLibrary.simpleMessage("Telephone"), "dianjidenglu" : MessageLookupByLibrary.simpleMessage("Click login to enjoy more wonderful information"), "dianneiyongcan" : MessageLookupByLibrary.simpleMessage("store dining"), + "dianpuchongzhi" : MessageLookupByLibrary.simpleMessage("Recharge"), "dianputuijian" : MessageLookupByLibrary.simpleMessage("Store recommendation"), "dianpuyue" : MessageLookupByLibrary.simpleMessage("Shop balance"), "dianwolingqu" : MessageLookupByLibrary.simpleMessage("Click me to get it"), @@ -309,6 +310,7 @@ class MessageLookup extends MessageLookupByLibrary { "huiyuanjifen" : MessageLookupByLibrary.simpleMessage("Member Points"), "huiyuanka" : MessageLookupByLibrary.simpleMessage("Membership Card"), "huiyuankaxiangqing" : MessageLookupByLibrary.simpleMessage("Membership card details"), + "huiyuanma" : MessageLookupByLibrary.simpleMessage("vipCode"), "huiyuanquanyi" : MessageLookupByLibrary.simpleMessage("Membership Rights"), "huiyuanyue" : MessageLookupByLibrary.simpleMessage("Member Balance"), "huiyuanzhongxin" : MessageLookupByLibrary.simpleMessage("Member Center"), @@ -468,6 +470,7 @@ class MessageLookup extends MessageLookupByLibrary { "privacy_policy2" : MessageLookupByLibrary.simpleMessage("《Service Agreement for Returning Home with One Heart》"), "privacy_policy3" : MessageLookupByLibrary.simpleMessage("《privacy Services》"), "privacy_policy4" : MessageLookupByLibrary.simpleMessage("Log in with your own number"), + "qianbao" : MessageLookupByLibrary.simpleMessage("Wallet"), "qiandao" : MessageLookupByLibrary.simpleMessage("Sign in"), "qiandaodejifen" : MessageLookupByLibrary.simpleMessage("Sign in and get points"), "qiandaolingjifen" : MessageLookupByLibrary.simpleMessage("Sign in to receive points"), @@ -740,6 +743,7 @@ class MessageLookup extends MessageLookupByLibrary { "yinsixieyi" : MessageLookupByLibrary.simpleMessage("《Privacy Agreement》"), "yinsizhengce1" : MessageLookupByLibrary.simpleMessage(" Thank you for using the Home bound APP. We attach great importance to your personal information and privacy protection. In order to better ensure your personal rights and interests, before you use our products, please carefully read"), "yinsizhengce2" : MessageLookupByLibrary.simpleMessage("     With your consent, we will collect some possible data (geographic location, camera, storage and other information) according to your use needs。"), + "yinzhang" : MessageLookupByLibrary.simpleMessage("Seal"), "yiqiandao" : MessageLookupByLibrary.simpleMessage("Signed in"), "yiqianshou" : MessageLookupByLibrary.simpleMessage("Signed in"), "yiquxiao" : MessageLookupByLibrary.simpleMessage(" Canceled "), @@ -812,6 +816,7 @@ class MessageLookup extends MessageLookupByLibrary { "zhunongjifen" : MessageLookupByLibrary.simpleMessage("Farming aid points"), "zhunongzhuanqu" : MessageLookupByLibrary.simpleMessage("Special Area for Agricultural Aid"), "zhuxiaotixing" : MessageLookupByLibrary.simpleMessage("Reminder again: After the account is logged off, it cannot be recovered, and relevant data and information will be permanently deleted。"), + "zhuxiaozhanghao" : MessageLookupByLibrary.simpleMessage("Account cancellation"), "ziqu" : MessageLookupByLibrary.simpleMessage("self fetching"), "ziti" : MessageLookupByLibrary.simpleMessage("Self mention"), "zitidizhi" : MessageLookupByLibrary.simpleMessage("Self lifting address"), diff --git a/lib/generated/intl/messages_zh_CN.dart b/lib/generated/intl/messages_zh_CN.dart index 013804a2..494d70e7 100644 --- a/lib/generated/intl/messages_zh_CN.dart +++ b/lib/generated/intl/messages_zh_CN.dart @@ -193,6 +193,7 @@ class MessageLookup extends MessageLookupByLibrary { "dianhua" : MessageLookupByLibrary.simpleMessage("电话"), "dianjidenglu" : MessageLookupByLibrary.simpleMessage("点击登录,享受更多精彩信息"), "dianneiyongcan" : MessageLookupByLibrary.simpleMessage("店内用餐"), + "dianpuchongzhi" : MessageLookupByLibrary.simpleMessage("店铺充值"), "dianputuijian" : MessageLookupByLibrary.simpleMessage("店铺推荐"), "dianpuyue" : MessageLookupByLibrary.simpleMessage("店铺余额"), "dianwolingqu" : MessageLookupByLibrary.simpleMessage("点我领取"), @@ -309,6 +310,7 @@ class MessageLookup extends MessageLookupByLibrary { "huiyuanjifen" : MessageLookupByLibrary.simpleMessage("会员积分"), "huiyuanka" : MessageLookupByLibrary.simpleMessage("会员卡"), "huiyuankaxiangqing" : MessageLookupByLibrary.simpleMessage("会员卡详情"), + "huiyuanma" : MessageLookupByLibrary.simpleMessage("会员码"), "huiyuanquanyi" : MessageLookupByLibrary.simpleMessage("会员权益"), "huiyuanyue" : MessageLookupByLibrary.simpleMessage("会员余额"), "huiyuanzhongxin" : MessageLookupByLibrary.simpleMessage("会员中心"), @@ -468,6 +470,7 @@ class MessageLookup extends MessageLookupByLibrary { "privacy_policy2" : MessageLookupByLibrary.simpleMessage("《一心回乡服务协议》"), "privacy_policy3" : MessageLookupByLibrary.simpleMessage("《隐私服务》"), "privacy_policy4" : MessageLookupByLibrary.simpleMessage("并使用本机号码登录"), + "qianbao" : MessageLookupByLibrary.simpleMessage("钱包"), "qiandao" : MessageLookupByLibrary.simpleMessage("签到"), "qiandaodejifen" : MessageLookupByLibrary.simpleMessage("签到得积分"), "qiandaolingjifen" : MessageLookupByLibrary.simpleMessage("签到领积分"), @@ -740,6 +743,7 @@ class MessageLookup extends MessageLookupByLibrary { "yinsixieyi" : MessageLookupByLibrary.simpleMessage("《隐私协议》"), "yinsizhengce1" : MessageLookupByLibrary.simpleMessage(" 感谢您使用一心回乡APP。我们非常重视您的个人信息和隐私保护。为了更好地保证您的个人权益,在您使用我们的产品前,请务必仔细阅读一心回乡"), "yinsizhengce2" : MessageLookupByLibrary.simpleMessage("     在您同意后,我们才会根据您的使用需求,收集部分可能涉及的数据(地理位置、相机、存储等信息)。"), + "yinzhang" : MessageLookupByLibrary.simpleMessage("印章"), "yiqiandao" : MessageLookupByLibrary.simpleMessage("已签到"), "yiqianshou" : MessageLookupByLibrary.simpleMessage("已签收"), "yiquxiao" : MessageLookupByLibrary.simpleMessage(" 已取消 "), @@ -812,6 +816,7 @@ class MessageLookup extends MessageLookupByLibrary { "zhunongjifen" : MessageLookupByLibrary.simpleMessage("助农积分"), "zhunongzhuanqu" : MessageLookupByLibrary.simpleMessage("助农专区"), "zhuxiaotixing" : MessageLookupByLibrary.simpleMessage("再次提醒:注销帐号后不可恢复,相关数据和信息会永久删除。"), + "zhuxiaozhanghao" : MessageLookupByLibrary.simpleMessage("注销账号"), "ziqu" : MessageLookupByLibrary.simpleMessage("自取"), "ziti" : MessageLookupByLibrary.simpleMessage("自提"), "zitidizhi" : MessageLookupByLibrary.simpleMessage("自提地址"), diff --git a/lib/generated/intl/messages_zh_Hans_CN.dart b/lib/generated/intl/messages_zh_Hans_CN.dart index 57dd765c..1952e3b2 100644 --- a/lib/generated/intl/messages_zh_Hans_CN.dart +++ b/lib/generated/intl/messages_zh_Hans_CN.dart @@ -193,6 +193,7 @@ class MessageLookup extends MessageLookupByLibrary { "dianhua" : MessageLookupByLibrary.simpleMessage("电话"), "dianjidenglu" : MessageLookupByLibrary.simpleMessage("点击登录,享受更多精彩信息"), "dianneiyongcan" : MessageLookupByLibrary.simpleMessage("店内用餐"), + "dianpuchongzhi" : MessageLookupByLibrary.simpleMessage("店铺充值"), "dianputuijian" : MessageLookupByLibrary.simpleMessage("店铺推荐"), "dianpuyue" : MessageLookupByLibrary.simpleMessage("店铺余额"), "dianwolingqu" : MessageLookupByLibrary.simpleMessage("点我领取"), @@ -309,6 +310,7 @@ class MessageLookup extends MessageLookupByLibrary { "huiyuanjifen" : MessageLookupByLibrary.simpleMessage("会员积分"), "huiyuanka" : MessageLookupByLibrary.simpleMessage("会员卡"), "huiyuankaxiangqing" : MessageLookupByLibrary.simpleMessage("会员卡详情"), + "huiyuanma" : MessageLookupByLibrary.simpleMessage("会员码"), "huiyuanquanyi" : MessageLookupByLibrary.simpleMessage("会员权益"), "huiyuanyue" : MessageLookupByLibrary.simpleMessage("会员余额"), "huiyuanzhongxin" : MessageLookupByLibrary.simpleMessage("会员中心"), @@ -468,6 +470,7 @@ class MessageLookup extends MessageLookupByLibrary { "privacy_policy2" : MessageLookupByLibrary.simpleMessage("《一心回乡服务协议》"), "privacy_policy3" : MessageLookupByLibrary.simpleMessage("《隐私服务》"), "privacy_policy4" : MessageLookupByLibrary.simpleMessage("并使用本机号码登录"), + "qianbao" : MessageLookupByLibrary.simpleMessage("钱包"), "qiandao" : MessageLookupByLibrary.simpleMessage("签到"), "qiandaodejifen" : MessageLookupByLibrary.simpleMessage("签到得积分"), "qiandaolingjifen" : MessageLookupByLibrary.simpleMessage("签到领积分"), @@ -740,6 +743,7 @@ class MessageLookup extends MessageLookupByLibrary { "yinsixieyi" : MessageLookupByLibrary.simpleMessage("《隐私协议》"), "yinsizhengce1" : MessageLookupByLibrary.simpleMessage(" 感谢您使用一心回乡APP。我们非常重视您的个人信息和隐私保护。为了更好地保证您的个人权益,在您使用我们的产品前,请务必仔细阅读一心回乡"), "yinsizhengce2" : MessageLookupByLibrary.simpleMessage("     在您同意后,我们才会根据您的使用需求,收集部分可能涉及的数据(地理位置、相机、存储等信息)。"), + "yinzhang" : MessageLookupByLibrary.simpleMessage("印章"), "yiqiandao" : MessageLookupByLibrary.simpleMessage("已签到"), "yiqianshou" : MessageLookupByLibrary.simpleMessage("已签收"), "yiquxiao" : MessageLookupByLibrary.simpleMessage(" 已取消 "), @@ -812,6 +816,7 @@ class MessageLookup extends MessageLookupByLibrary { "zhunongjifen" : MessageLookupByLibrary.simpleMessage("助农积分"), "zhunongzhuanqu" : MessageLookupByLibrary.simpleMessage("助农专区"), "zhuxiaotixing" : MessageLookupByLibrary.simpleMessage("再次提醒:注销帐号后不可恢复,相关数据和信息会永久删除。"), + "zhuxiaozhanghao" : MessageLookupByLibrary.simpleMessage("注销账号"), "ziqu" : MessageLookupByLibrary.simpleMessage("自取"), "ziti" : MessageLookupByLibrary.simpleMessage("自提"), "zitidizhi" : MessageLookupByLibrary.simpleMessage("自提地址"), diff --git a/lib/generated/intl/messages_zh_Hant_CN.dart b/lib/generated/intl/messages_zh_Hant_CN.dart index 45688e01..af38e8de 100644 --- a/lib/generated/intl/messages_zh_Hant_CN.dart +++ b/lib/generated/intl/messages_zh_Hant_CN.dart @@ -189,6 +189,7 @@ class MessageLookup extends MessageLookupByLibrary { "dianhua" : MessageLookupByLibrary.simpleMessage("電話"), "dianjidenglu" : MessageLookupByLibrary.simpleMessage("點擊登錄,享受更多精彩信息"), "dianneiyongcan" : MessageLookupByLibrary.simpleMessage("店内用餐"), + "dianpuchongzhi" : MessageLookupByLibrary.simpleMessage("店鋪充值"), "dianputuijian" : MessageLookupByLibrary.simpleMessage("店鋪推薦"), "dianpuyue" : MessageLookupByLibrary.simpleMessage("店鋪餘額"), "dianwolingqu" : MessageLookupByLibrary.simpleMessage("點我領取"), @@ -305,6 +306,7 @@ class MessageLookup extends MessageLookupByLibrary { "huiyuanjifen" : MessageLookupByLibrary.simpleMessage("會員積分"), "huiyuanka" : MessageLookupByLibrary.simpleMessage("會員卡"), "huiyuankaxiangqing" : MessageLookupByLibrary.simpleMessage("會員卡詳情"), + "huiyuanma" : MessageLookupByLibrary.simpleMessage("會員碼"), "huiyuanquanyi" : MessageLookupByLibrary.simpleMessage("會員權益"), "huiyuanyue" : MessageLookupByLibrary.simpleMessage("會員餘額"), "huiyuanzhongxin" : MessageLookupByLibrary.simpleMessage("會員中心"), @@ -463,6 +465,7 @@ class MessageLookup extends MessageLookupByLibrary { "privacy_policy2" : MessageLookupByLibrary.simpleMessage("《一心回鄉服務協議》"), "privacy_policy3" : MessageLookupByLibrary.simpleMessage("《隱私服務》"), "privacy_policy4" : MessageLookupByLibrary.simpleMessage("并使用本機號碼登錄"), + "qianbao" : MessageLookupByLibrary.simpleMessage("錢包"), "qiandao" : MessageLookupByLibrary.simpleMessage("簽到"), "qiandaodejifen" : MessageLookupByLibrary.simpleMessage("簽到得積分"), "qiandaolingjifen" : MessageLookupByLibrary.simpleMessage("簽到領積分"), @@ -734,6 +737,7 @@ class MessageLookup extends MessageLookupByLibrary { "yinsixieyi" : MessageLookupByLibrary.simpleMessage("《隱私協議》"), "yinsizhengce1" : MessageLookupByLibrary.simpleMessage(" 感謝您使用一心回鄉APP。我們非常的重視您的個人信息和隱私保護。為了更好地保證您的個人權益,在您使用我們的產品前,請務必仔細閱讀一心回鄉"), "yinsizhengce2" : MessageLookupByLibrary.simpleMessage("     在您同意後,我們才會根據您的使用需求,收集部分可能涉及(地理位置、相機、存儲等信息)的數據。"), + "yinzhang" : MessageLookupByLibrary.simpleMessage("印章"), "yiqiandao" : MessageLookupByLibrary.simpleMessage("已簽到"), "yiqianshou" : MessageLookupByLibrary.simpleMessage("已簽收"), "yiquxiao" : MessageLookupByLibrary.simpleMessage(" 已取消 "), @@ -806,6 +810,7 @@ class MessageLookup extends MessageLookupByLibrary { "zhunongjifen" : MessageLookupByLibrary.simpleMessage("助農積分"), "zhunongzhuanqu" : MessageLookupByLibrary.simpleMessage("助農專區"), "zhuxiaotixing" : MessageLookupByLibrary.simpleMessage("再次提醒:註銷帳號後不可恢復,相關資料和資訊會永久删除。"), + "zhuxiaozhanghao" : MessageLookupByLibrary.simpleMessage("註銷帳號"), "ziqu" : MessageLookupByLibrary.simpleMessage("自取"), "ziti" : MessageLookupByLibrary.simpleMessage("自提"), "zitidizhi" : MessageLookupByLibrary.simpleMessage("自提地址"), diff --git a/lib/generated/intl/messages_zh_TW.dart b/lib/generated/intl/messages_zh_TW.dart index 7a7bab93..3656596e 100644 --- a/lib/generated/intl/messages_zh_TW.dart +++ b/lib/generated/intl/messages_zh_TW.dart @@ -191,6 +191,7 @@ class MessageLookup extends MessageLookupByLibrary { "dianhua" : MessageLookupByLibrary.simpleMessage("電話"), "dianjidenglu" : MessageLookupByLibrary.simpleMessage("點擊登錄,享受更多精彩信息"), "dianneiyongcan" : MessageLookupByLibrary.simpleMessage("店内用餐"), + "dianpuchongzhi" : MessageLookupByLibrary.simpleMessage("店鋪充值"), "dianputuijian" : MessageLookupByLibrary.simpleMessage("店鋪推薦"), "dianpuyue" : MessageLookupByLibrary.simpleMessage("店鋪餘額"), "dianwolingqu" : MessageLookupByLibrary.simpleMessage("點我領取"), @@ -307,6 +308,7 @@ class MessageLookup extends MessageLookupByLibrary { "huiyuanjifen" : MessageLookupByLibrary.simpleMessage("會員積分"), "huiyuanka" : MessageLookupByLibrary.simpleMessage("會員卡"), "huiyuankaxiangqing" : MessageLookupByLibrary.simpleMessage("會員卡詳情"), + "huiyuanma" : MessageLookupByLibrary.simpleMessage("會員碼"), "huiyuanquanyi" : MessageLookupByLibrary.simpleMessage("會員權益"), "huiyuanyue" : MessageLookupByLibrary.simpleMessage("會員餘額"), "huiyuanzhongxin" : MessageLookupByLibrary.simpleMessage("會員中心"), @@ -465,6 +467,7 @@ class MessageLookup extends MessageLookupByLibrary { "privacy_policy2" : MessageLookupByLibrary.simpleMessage("《一心回鄉服務協議》"), "privacy_policy3" : MessageLookupByLibrary.simpleMessage("《隱私服務》"), "privacy_policy4" : MessageLookupByLibrary.simpleMessage("并使用本機號碼登錄"), + "qianbao" : MessageLookupByLibrary.simpleMessage("錢包"), "qiandao" : MessageLookupByLibrary.simpleMessage("簽到"), "qiandaodejifen" : MessageLookupByLibrary.simpleMessage("簽到得積分"), "qiandaolingjifen" : MessageLookupByLibrary.simpleMessage("簽到領積分"), @@ -737,6 +740,7 @@ class MessageLookup extends MessageLookupByLibrary { "yinsixieyi" : MessageLookupByLibrary.simpleMessage("《隱私協議》"), "yinsizhengce1" : MessageLookupByLibrary.simpleMessage(" 感謝您使用一心回鄉APP。我們非常的重視您的個人信息和隱私保護。為了更好地保證您的個人權益,在您使用我們的產品前,請務必仔細閱讀一心回鄉"), "yinsizhengce2" : MessageLookupByLibrary.simpleMessage("     在您同意後,我們才會根據您的使用需求,收集部分可能涉及(地理位置、相機、存儲等信息)的數據。"), + "yinzhang" : MessageLookupByLibrary.simpleMessage("印章"), "yiqiandao" : MessageLookupByLibrary.simpleMessage("已簽到"), "yiqianshou" : MessageLookupByLibrary.simpleMessage("已簽收"), "yiquxiao" : MessageLookupByLibrary.simpleMessage(" 已取消 "), @@ -809,6 +813,7 @@ class MessageLookup extends MessageLookupByLibrary { "zhunongjifen" : MessageLookupByLibrary.simpleMessage("助農積分"), "zhunongzhuanqu" : MessageLookupByLibrary.simpleMessage("助農專區"), "zhuxiaotixing" : MessageLookupByLibrary.simpleMessage("再次提醒:註銷帳號後不可恢復,相關資料和資訊會永久删除。"), + "zhuxiaozhanghao" : MessageLookupByLibrary.simpleMessage("註銷帳號"), "ziqu" : MessageLookupByLibrary.simpleMessage("自取"), "ziti" : MessageLookupByLibrary.simpleMessage("自提"), "zitidizhi" : MessageLookupByLibrary.simpleMessage("自提地址"), diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 1f610b1e..172f28ec 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -7145,6 +7145,56 @@ class S { ); } + /// `钱包` + String get qianbao { + return Intl.message( + '钱包', + name: 'qianbao', + desc: '', + args: [], + ); + } + + /// `会员码` + String get huiyuanma { + return Intl.message( + '会员码', + name: 'huiyuanma', + desc: '', + args: [], + ); + } + + /// `印章` + String get yinzhang { + return Intl.message( + '印章', + name: 'yinzhang', + desc: '', + args: [], + ); + } + + /// `店铺充值` + String get dianpuchongzhi { + return Intl.message( + '店铺充值', + name: 'dianpuchongzhi', + desc: '', + args: [], + ); + } + + /// `注销账号` + String get zhuxiaozhanghao { + return Intl.message( + '注销账号', + name: 'zhuxiaozhanghao', + desc: '', + args: [], + ); + } + /// `并使用本机号码登录` String get privacy_policy4 { return Intl.message( diff --git a/lib/home/home_page.dart b/lib/home/home_page.dart index 4f52ddb7..be6f7b3e 100644 --- a/lib/home/home_page.dart +++ b/lib/home/home_page.dart @@ -8,7 +8,6 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_swiper/flutter_swiper.dart'; import 'package:huixiang/generated/l10n.dart'; import 'package:huixiang/home/home_view/discount_zone.dart'; -import 'package:huixiang/home/home_view/home_banner.dart'; import 'package:huixiang/home/home_view/home_recommend_goods.dart'; import 'package:huixiang/home/home_view/top_selling_list.dart'; import 'package:huixiang/home/home_view/union_entry.dart'; @@ -27,7 +26,6 @@ import 'package:huixiang/retrofit/data/goods.dart'; import 'package:huixiang/retrofit/data/goods_category.dart'; import 'package:huixiang/retrofit/data/home_rank.dart'; import 'package:huixiang/retrofit/data/login_info.dart'; -import 'package:huixiang/retrofit/data/msg_stats.dart'; import 'package:huixiang/retrofit/data/page.dart'; import 'package:huixiang/retrofit/retrofit_api.dart'; import 'package:huixiang/utils/event_type.dart'; @@ -44,6 +42,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import '../retrofit/data/user_info.dart'; import '../utils/flutter_utils.dart'; import '../view_widget/channel_dialog.dart'; +import '../view_widget/custom_image.dart'; import 'home_view/happy_help_farmers.dart'; import 'home_view/shortcut_operation.dart'; @@ -54,7 +53,8 @@ class HomePage extends StatefulWidget { final List firstLoginCouponList; HomePage(Key key, this.changeTab, - {this.invite, this.interviewCouponList, this.firstLoginCouponList}): super(key: key); + {this.invite, this.interviewCouponList, this.firstLoginCouponList}) + : super(key: key); @override State createState() { @@ -64,6 +64,32 @@ class HomePage extends StatefulWidget { class HomePageState extends State with AutomaticKeepAliveClientMixin { ApiService apiService; + final RefreshController refreshController = RefreshController(); + String categoryId; + bool showInvite = false; + bool showNew = false; + + //排序类型枚举:1-自然排序,2-销量,3-价格 + int orderType = 1; + + //是否降序排列 + bool orderDesc = true; + List goods = []; + List gooodsCategorys = []; + List bannerData = []; + List activityBannerData = []; + List brandData = []; + List
articles = []; + Founder founder; + bool isSigned = false; + int totalMsg = 0; + List coupons = []; + int state = 1; + HomeRank homeRank; + UserInfo userInfo; + dynamic mRaiseMoney = 0; //众筹金余额 + int _loadCount = 0; + DioErrorType dioErrorType; @override void initState() { @@ -74,8 +100,11 @@ class HomePageState extends State with AutomaticKeepAliveClientMixin { setState(() {}); } }); - queryActivity(); - _onRefresh(); + _onRefresh(isFirstIn: true); + if (showInvite) { + inviteShowAlertDialog(widget.invite, widget.interviewCouponList[0]); + showInvite = false; + } if ((widget.invite ?? "") != "" || widget.interviewCouponList != null && @@ -84,7 +113,6 @@ class HomePageState extends State with AutomaticKeepAliveClientMixin { //判断新人弹窗 // if (widget.firstLoginCouponList != null && widget.firstLoginCouponList.length > 0) // showNew = true; - } ///邀请成功 @@ -99,18 +127,21 @@ class HomePageState extends State with AutomaticKeepAliveClientMixin { } ///活动海报弹窗 - posterShowAlertDialog(ActivityPos activityPos,firstLoginCouponList) { + posterShowAlertDialog(ActivityPos activityPos, firstLoginCouponList) { var today = DateTime.now().day; SharedPreferences.getInstance().then((value) { - if(value.getInt("today")==today && (value.getString("ActivityPosCode") ?? "").contains("${activityPos.code}_${value.getString("userId")};")) + if (value.getInt("today") == today && + (value.getString("ActivityPosCode") ?? "") + .contains("${activityPos.code}_${value.getString("userId")};")) return; - value.setString("ActivityPosCode", "${(value.getString("ActivityPosCode")??"")}${activityPos.code}_${value.getString("userId")};"); + value.setString("ActivityPosCode", + "${(value.getString("ActivityPosCode") ?? "")}${activityPos.code}_${value.getString("userId")};"); value.setInt("today", today); //显示对话框 showDialog( context: context, builder: (BuildContext context) { - return ActivityPoster(activityPos,firstLoginCouponList); + return ActivityPoster(activityPos, firstLoginCouponList); }, ); }); @@ -127,178 +158,133 @@ class HomePageState extends State with AutomaticKeepAliveClientMixin { ); } - final SwiperController controller = SwiperController(); - - String categoryId; - int pageNum = 1; - int couponPageNum = 1; - bool showInvite = false; - bool showNew = false; - - //排序类型枚举:1-自然排序,2-销量,3-价格 - int orderType = 1; - - //是否降序排列 - bool orderDesc = true; - List goods = []; - List gooodsCategorys = []; - - List bannerData = []; - List brandData = []; - List
articles = []; - List gooods = []; - Founder founder; - bool isSigned = false; - int totalMsg = 0; - List coupons = []; - int state = 1; - HomeRank homeRank; - UserInfo userInfo; - dynamic mRaiseMoney = 0;//众筹金余额 - - queryHome() async { - // EasyLoading.show(status: S.of(context).zhengzaijiazai); - - final SharedPreferences value = await SharedPreferences.getInstance(); - apiService = ApiService(Dio(), - context: context, token: value.getString('token'), showLoading: false); - - final BaseData brand = - await apiService.queryHomeBrand().catchError((onError) { - SmartDialog.showToast(AppUtils.dioErrorTypeToString(onError.type), - alignment: Alignment.center); - refreshController.refreshFailed(); - }); - if (brand != null && brand.isSuccess) { - brandData.clear(); - brandData.addAll((brand.data["brandList"] as List) - .map((e) => Brand.fromJson(e)) - .toList()); - founder = Founder.fromJson(brand.data["founder"]); + ///头部banner + queryBanner() async { + try { + BaseData> baseData = await apiService.queryBanner({ + "model": {"type": "HOME_PAGE"}, + }).catchError((onError) { + dioErrorType = onError.type; + }); + if (baseData != null && baseData.isSuccess) { + bannerData = baseData.data.records; + // if (bannerData.length > 0) swiperController.move(0, animation: false); + } + } finally { + addLoadCount(); } + } - final BaseData> article = await apiService.queryArticle({ - "pageNum": 1, - "pageSize": 3, - "searchKey": "", - "state": 1, - "type": 2 - }).catchError((onError) { - refreshController.refreshFailed(); - }); - articles.clear(); - if (article != null && article.isSuccess) { - articles.addAll(article.data.list); + ///宣传banner + queryActivityBanner() async { + try { + BaseData> baseData = await apiService.queryBanner({ + "model": {"type": "HOME_STORE_PAGE"}, + }).catchError((onError) {}); + if (baseData != null && baseData.isSuccess) { + activityBannerData = baseData.data.records; + } + } finally { + addLoadCount(); } + } - final BaseData rank = await apiService.recommendRank().catchError((onError) {}); - if (rank != null && rank.isSuccess) { - homeRank = rank.data; + addLoadCount() { + _loadCount += 1; + if (_loadCount == 7) { + _loadCount = 0; + EasyLoading.dismiss(); + if (dioErrorType == null) + refreshController.refreshCompleted(); + else { + SmartDialog.showToast(AppUtils.dioErrorTypeToString(dioErrorType), + alignment: Alignment.center); + refreshController.refreshFailed(); + } + if (mounted) setState(() {}); } + } - final BaseData> goodsData = await apiService.creditGoods({ - "orderDesc": true, - "orderType": 1, - "pageNum": 1, - "pageSize": 100, - "state": 1 - }).catchError((onError) { - refreshController.refreshFailed(); - }); - if (goodsData != null && goodsData.isSuccess) { - gooods.clear(); - gooods.addAll(goodsData.data.list); + ///推荐排行 + queryRecommendRank() async { + try { + BaseData rank = + await apiService.recommendRank().catchError((onError) {}); + if (rank != null && rank.isSuccess) { + homeRank = rank.data; + } + } finally { + addLoadCount(); } + } - 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(); - }); - - if (dataCategory != null && - dataCategory.isSuccess && - dataCategory.data != null && - dataCategory.data.records != null && - dataCategory.data.records.length > 0) { - gooodsCategorys.clear(); - gooodsCategorys.add(GoodsCategory(name: S.of(context).quanbu)); - gooodsCategorys.addAll(dataCategory.data.records); + ///积分商城商品分類列表 + queryGoodsCategory() async { + try { + BaseData> dataCategory = + await apiService.goodsCategory({ + "current": 1, + "map": {}, + "model": {"pageNum": 1, "pageSize": 20, "searchKey": ""}, + "order": "descending", + "size": 20, + "sort": "sortOrder" + }).catchError((onError) {}); + if (dataCategory != null && + dataCategory.isSuccess && + dataCategory.data != null && + dataCategory.data.records != null && + dataCategory.data.records.length > 0) { + gooodsCategorys.clear(); + gooodsCategorys.add(GoodsCategory(name: S.of(context).quanbu)); + gooodsCategorys.addAll(dataCategory.data.records); + } + } finally { + addLoadCount(); } + } - 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(); - }); - EasyLoading.dismiss(); - if (pageGoods != null && pageGoods.isSuccess) { - if (pageNum == 1) { - goods.clear(); + ///积分商城商品列表 + queryPointsProductList(bool isRefresh) async { + try { + if (!isRefresh) + EasyLoading.show( + status: S.current.zhengzaijiazai, + maskType: EasyLoadingMaskType.black); + var param = { + "categoryId": categoryId ?? "", + "orderDesc": orderDesc, + "orderType": orderType, + "pageNum": 1, + "pageSize": 100, + "state": 1 + }; + BaseData> pageGoods = + await apiService.creditGoods(param).catchError((onError) {}); + if (pageGoods != null && pageGoods.isSuccess) { + goods = pageGoods.data.list; } - goods.addAll(pageGoods.data.list); - refreshController.refreshCompleted(); - refreshController.loadComplete(); - if (pageGoods.data.pageNum == pageGoods.data.pages) { - refreshController.loadNoData(); - } else { - pageNum += 1; + } finally { + if (isRefresh) + addLoadCount(); + else { + EasyLoading.dismiss(); + setState(() {}); } - } else { - refreshController.loadFailed(); - refreshController.refreshFailed(); } - - final BaseData> baseData = - await apiService.queryBanner({ - "model": {"type": "HOME_PAGE"}, - }).catchError((onError) { - refreshController.refreshFailed(); - }); - if (baseData != null && baseData.isSuccess) { - bannerData.clear(); - bannerData.addAll(baseData.data.records); - refreshController.refreshCompleted(); - if (bannerData.length > 0) controller.move(0, animation: false); - } else { - refreshController.refreshFailed(); - } - EasyLoading.dismiss(); - if (showInvite) { - inviteShowAlertDialog(widget.invite, widget.interviewCouponList[0]); - showInvite = false; - } - - //判断新人弹窗 - // if (showNew) { - // newShowAlertDialog(widget.firstLoginCouponList); - // showNew = false; - // } } ///查询会员信息 queryUserBalance() async { - BaseData baseData = - await apiService.queryInfo().catchError((onError) {}); - if (baseData != null && baseData.isSuccess) { - userInfo = baseData.data; - mRaiseMoney = double.tryParse(userInfo.raiseMoney); - if (mounted) setState(() {}); + try { + BaseData baseData = + await apiService.queryInfo().catchError((onError) {}); + if (baseData != null && baseData.isSuccess) { + userInfo = baseData.data; + mRaiseMoney = double.tryParse(userInfo.raiseMoney); + } + } finally { + addLoadCount(); } } @@ -326,35 +312,18 @@ class HomePageState extends State with AutomaticKeepAliveClientMixin { ///活动弹窗 queryActivity() async { - if (apiService == null) { - SharedPreferences value = await SharedPreferences.getInstance(); - apiService = ApiService( - Dio(), - context: context, - token: value.getString("token"), - showLoading: true - ); - } BaseData baseData = - await apiService.appPopup().catchError((onError) { - }); + await apiService.appPopup().catchError((onError) {}); if (baseData != null && baseData.isSuccess) { - if(baseData.data?.enabled ?? true) - posterShowAlertDialog(baseData.data,widget.firstLoginCouponList); + if (baseData.data?.enabled ?? true) + posterShowAlertDialog(baseData.data, widget.firstLoginCouponList); } } ///核销用户优惠券 queryWiped(memberCouponId) async { - if (apiService == null) { - SharedPreferences value = await SharedPreferences.getInstance(); - apiService = ApiService( - Dio(), - context: context, - token: value.getString("token"), - ); - } - BaseData baseData = await apiService.wiped(memberCouponId).catchError((onError) {}); + BaseData baseData = + await apiService.wiped(memberCouponId).catchError((onError) {}); if (baseData != null && baseData.isSuccess) { SmartDialog.showToast("核销成功", alignment: Alignment.center); } else { @@ -363,6 +332,25 @@ class HomePageState extends State with AutomaticKeepAliveClientMixin { } queryCoupon() async { + try { + BaseData> baseData = await apiService.queryCoupon({ + "centre": true, + "pageNum": 1, + "pageSize": 10, + "searchKey": "", + "state": 0 + }).catchError((onError) {}); + if (baseData != null && baseData.isSuccess) { + coupons = baseData.data.list; + } + } finally { + addLoadCount(); + } + } + + _onRefresh({bool isFirstIn = false}) async { + EasyLoading.show( + status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black); if (apiService == null) { SharedPreferences value = await SharedPreferences.getInstance(); apiService = ApiService( @@ -371,39 +359,16 @@ class HomePageState extends State with AutomaticKeepAliveClientMixin { token: value.getString("token"), ); } - BaseData> baseData = await apiService.queryCoupon({ - "centre": true, - "pageNum": couponPageNum, - "pageSize": 10, - "searchKey": "", - "state": 0 - }).catchError((onError) { - refreshController.refreshFailed(); - refreshController.loadFailed(); - }); - if (couponPageNum == 1) coupons.clear(); - if (baseData != null && baseData.isSuccess) { - coupons.addAll(baseData.data.list); - refreshController.refreshCompleted(); - refreshController.loadComplete(); - if (baseData.data.pageNum == baseData.data.pages) { - refreshController.loadNoData(); - } else { - couponPageNum += 1; - } - setState(() {}); - } - else { - refreshController.refreshFailed(); - refreshController.loadFailed(); - } - } - - _onRefresh() async{ - await queryHome(); - await queryUserBalance(); + dioErrorType = null; + if (isFirstIn) queryActivity(); + queryBanner(); + queryActivityBanner(); + queryRecommendRank(); + queryGoodsCategory(); + queryPointsProductList(true); + queryUserBalance(); // queryMsgStats(); - await queryCoupon(); + queryCoupon(); } @override @@ -412,8 +377,6 @@ class HomePageState extends State with AutomaticKeepAliveClientMixin { if (refreshController != null) refreshController.dispose(); } - final RefreshController refreshController = RefreshController(); - @override Widget build(BuildContext context) { super.build(context); @@ -502,99 +465,91 @@ class HomePageState extends State with AutomaticKeepAliveClientMixin { enablePullUp: false, header: MyHeader(), physics: BouncingScrollPhysics(), - onRefresh: () { - setState(() {_onRefresh(); - }); - }, + onRefresh: _onRefresh, child: SingleChildScrollView( - physics: NeverScrollableScrollPhysics(), - child: FutureBuilder( - future: queryHome(), - builder: (context, snapshot) { - return Column( - children: [ - ///banner - HomeBanner(bannerData, controller), - - ///吃喝玩 - UnionEntry((int jpIndex) { - widget.changeTab(1,jpIndex); - }), - - ///快捷操作 - ShortcutOperation((int jpIndex) { - widget.changeTab(1,jpIndex); - }), - - ///推广图 - spread(), - - // ///签到 - // SignView(isSigned, (value) { - // setState(() { - // isSigned = value; - // }); - // }), - - ///特惠专区 - if(coupons != null && coupons.length != 0) - DiscountZone(coupons), - - ///特惠专区-推荐商品展示 - if(homeRank != null && homeRank.commodityZone.length != 0) - HomeRecommendGoods(homeRank), - - if((homeRank?.commodityZone?.length ??0) == 0) - SizedBox(height: 20.h,), - - ///助农专区 - // if(mRaiseMoney != 0) - HappyHelpFarmers(), - - ///福利中心 - WelfareCore(), - - ///吃喝玩商品热销榜 - if(homeRank != null && homeRank.commodityList.length != 0) - TopSellingList(homeRank), - - // ///店铺推荐 - // QuickOrder(), - - // ///超级优惠券 - // CouponView(), - - // ///精选活动 - // FeaturedActivity(), - - // ///积分商城 - // HomeIntegralStore(gooods), - - ///积分商品头Tab - PointsGoodsTitle( - gooodsCategorys, - (orderType, orderDesc) { - this.orderType = orderType; - this.orderDesc = orderDesc; - setState(() {}); - }, - (index) { - categoryId = gooodsCategorys[index].id; - pageNum = 1; - setState(() {}); - }, - ), - - ///积分商品列表 - PointGoods( - goods, - (index) { - _toDetails(index); - }, - ), - ], - );}) - ), + physics: NeverScrollableScrollPhysics(), + child: Column( + children: [ + ///banner + homeBanner(), + + ///吃喝玩 + UnionEntry((int jpIndex) { + widget.changeTab(1, jpIndex); + }), + + ///快捷操作 + ShortcutOperation((int jpIndex) { + widget.changeTab(1, jpIndex); + }), + + ///推广图 + if(activityBannerData.length > 0) + spread(), + + // ///签到 + // SignView(isSigned, (value) { + // setState(() { + // isSigned = value; + // }); + // }), + + ///特惠专区 + if (coupons != null && coupons.length != 0) + DiscountZone(coupons), + + ///特惠专区-推荐商品展示 + if (homeRank != null && + homeRank.commodityZone.length != 0) + HomeRecommendGoods(homeRank), + + ///助农专区 + // if(mRaiseMoney != 0) + HappyHelpFarmers(), + + ///福利中心 + WelfareCore(), + + ///吃喝玩商品热销榜 + if (homeRank != null && + homeRank.commodityList.length != 0) + TopSellingList(homeRank), + + // ///店铺推荐 + // QuickOrder(), + + // ///超级优惠券 + // CouponView(), + + // ///精选活动 + // FeaturedActivity(), + + // ///积分商城 + // HomeIntegralStore(gooods), + + ///积分商品头Tab + PointsGoodsTitle( + gooodsCategorys, + (orderType, orderDesc) { + this.orderType = orderType; + this.orderDesc = orderDesc; + queryPointsProductList(false); + }, + (index) { + categoryId = gooodsCategorys[index].id; + queryPointsProductList(false); + }, + ), + + ///积分商品列表 + PointGoods( + goods, + (index) { + _toDetails(index); + }, + ), + ], + )), ), ), ), @@ -605,57 +560,191 @@ class HomePageState extends State with AutomaticKeepAliveClientMixin { ); } - Widget spread(){ + Widget homeBanner() { + return Container( + child: AspectRatio( + aspectRatio: 1.25, + child: bannerData != null && bannerData.isNotEmpty + ? Swiper( + pagination: SwiperPagination( + margin: EdgeInsets.only(bottom: 12.h), + alignment: Alignment.bottomCenter, + builder: DotSwiperPaginationBuilder( + size: 8, + activeSize: 8, + space: 5, + activeColor: Colors.white, + color: Colors.white.withAlpha(76), + ), + ), + autoplay: true, + duration: 1000, + autoplayDelay: 2000, + physics: BouncingScrollPhysics(), + itemBuilder: (context, position) { + return InkWell( + onTap: () { + bannerClick(bannerData[position]); + }, + child: Container( + child: MImage( + bannerData[position].imgUrl, + fit: BoxFit.cover, + errorSrc: "assets/image/default_2_1.webp", + fadeSrc: "assets/image/default_2_1.webp", + ), + ), + ); + }, + itemCount: bannerData.length, + ) + : Image.asset( + "assets/image/default_2_1.webp", + fit: BoxFit.cover, + ), + ), + ); + } + + /// contentType 跳转类型(0:不跳转,1:积分商品,2:活动,3:文章,4:页面跳转,5:课程,7:门店跳转) + bannerClick(BannerData bannerData) async { + switch (bannerData.contentType) { + case 1: + Navigator.of(context).pushNamed('/router/integral_store_page', + arguments: {"goodsId": bannerData.content}); + break; + case 2: + Navigator.of(context).pushNamed('/router/web_page', arguments: { + "activityId": bannerData.content, + }); + break; + case 3: + Navigator.of(context).pushNamed('/router/web_page', arguments: { + "articleId": bannerData.content, + }); + break; + case 4: + String router = bannerData.content; + // String router = "/router/store_order?{\"id\":\"1512378184161558528\",\"tenant\":\"1188\",\"storeName\":\"农场煮意\"}"; + if (router.contains("?")) { + String params = router.substring(router.indexOf("?") + 1); + Map map = jsonDecode(params); + Navigator.of(context).pushNamed( + router.substring(0, router.indexOf("?")), + arguments: map); + } else { + Navigator.of(context).pushNamed(router); + } + break; + case 5: + Navigator.of(context).pushNamed('/router/class_details', arguments: { + "id": bannerData.content, + }); + break; + case 7: + String params = + bannerData.content.substring(bannerData.content.indexOf("?") + 1); + Map map = jsonDecode(params); + Navigator.of(context).pushNamed( + bannerData.content.substring(0, bannerData.content.indexOf("?")), + arguments: map); + break; + } + } + + Widget spread() { return Container( width: double.infinity, + // margin: EdgeInsets.symmetric(horizontal:14.w), height: 85.h, - child: Swiper( - pagination: SwiperPagination( - alignment: Alignment.bottomCenter, - margin: EdgeInsets.only(top: 5.h), - builder: DotSwiperPaginationBuilder( - size: 8.w, - activeSize: 8.w, - space: 5.w, - activeColor: Colors.white, - color: Colors.white.withAlpha(76), - ), - ), - autoplay:true, - duration: 1000, - autoplayDelay: 2000, - itemBuilder: (context, position) { - return GestureDetector( - onTap: (){ - if(position == 0){ - Navigator.of(context).pushNamed('/router/invite_friends'); - }else if(position == 1){ - Navigator.of(context).pushNamed('/router/trading_card_page'); - } - }, - child:Container( - margin: EdgeInsets.symmetric(horizontal:14.w), - child: ClipRRect( - child:Image.asset( - spreadItem[position], - width:double.infinity, - fit: BoxFit.fill, - height:double.infinity, + child: activityBannerData != null && activityBannerData.isNotEmpty + ? Swiper( + pagination: SwiperPagination( + alignment: Alignment.bottomCenter, + margin: EdgeInsets.only(top: 5.h), + builder: DotSwiperPaginationBuilder( + size: 8.w, + activeSize: 8.w, + space: 5.w, + activeColor: Colors.white, + color: Colors.white.withAlpha(76), ), - borderRadius: BorderRadius.circular(6.w), ), + autoplay: true, + duration: 1000, + autoplayDelay: 2000, + itemBuilder: (context, position) { + return InkWell( + onTap: () { + spreadBannerClick(activityBannerData[position]); + }, + child: Container( + margin: EdgeInsets.symmetric(horizontal: 14.w), + child: MImage( + activityBannerData[position].imgUrl, + fit: BoxFit.cover, + radius: BorderRadius.circular(6), + errorSrc: "assets/image/default_2_1.webp", + fadeSrc: "assets/image/default_2_1.webp", + ), + ), + ); + }, + itemCount: activityBannerData.length, + ) + : Image.asset( + "assets/image/default_2_1.webp", + fit: BoxFit.cover, ), - ); - }, - itemCount:2, - ), ); } - final List spreadItem = [ - "assets/image/welfare_spread.webp", - "assets/image/welfare_yz.webp", - ]; + /// contentType 跳转类型(0:不跳转,1:积分商品,2:活动,3:文章,4:页面跳转,5:课程,7:门店跳转) + spreadBannerClick(BannerData activityBannerData) async { + switch (activityBannerData.contentType) { + case 1: + Navigator.of(context).pushNamed('/router/integral_store_page', + arguments: {"goodsId": activityBannerData.content}); + break; + case 2: + Navigator.of(context).pushNamed('/router/web_page', arguments: { + "activityId": activityBannerData.content, + }); + break; + case 3: + Navigator.of(context).pushNamed('/router/web_page', arguments: { + "articleId": activityBannerData.content, + }); + break; + case 4: + String router = activityBannerData.content; + // String router = "/router/store_order?{\"id\":\"1512378184161558528\",\"tenant\":\"1188\",\"storeName\":\"农场煮意\"}"; + if (router.contains("?")) { + String params = router.substring(router.indexOf("?") + 1); + Map map = jsonDecode(params); + Navigator.of(context).pushNamed( + router.substring(0, router.indexOf("?")), + arguments: map); + } else { + Navigator.of(context).pushNamed(router); + } + break; + case 5: + Navigator.of(context).pushNamed('/router/class_details', arguments: { + "id": activityBannerData.content, + }); + break; + case 7: + String params = activityBannerData.content + .substring(activityBannerData.content.indexOf("?") + 1); + Map map = jsonDecode(params); + Navigator.of(context).pushNamed( + activityBannerData.content + .substring(0, activityBannerData.content.indexOf("?")), + arguments: map); + break; + } + } ///扫码 toScan() async { @@ -681,20 +770,24 @@ class HomePageState extends State with AutomaticKeepAliveClientMixin { // 新版桌子码跳转 // http://miniscan.lotus-wallet.com/placeorder?tenant_code=1194&table_id=1669609340031467520&store_id=1637659387134738432 var result = await Navigator.of(context).pushNamed('/router/qr_scan'); - if(result.toString().contains("type\":\"coupon")){ + if (result.toString().contains("type\":\"coupon")) { ///活动优惠券赠送弹窗 activityShowAlertDialog(result.toString()); return; - }if(result.toString().contains("type\":\"wiped")){ + } + if (result.toString().contains("type\":\"wiped")) { ///核销券 queryWiped(jsonDecode(result.toString())["memberCouponId"]); return; } // String result = await scanner.scan(); Uri uri = Uri.parse(result); - String tableId = uri.queryParameters["tableId"] ?? uri.queryParameters["table_id"]; - String tenantCode = uri.queryParameters["tenantCode"] ?? uri.queryParameters["tenant_code"]; - String shopId = uri.queryParameters["shopId"] ?? uri.queryParameters["store_id"]; + String tableId = + uri.queryParameters["tableId"] ?? uri.queryParameters["table_id"]; + String tenantCode = uri.queryParameters["tenantCode"] ?? + uri.queryParameters["tenant_code"]; + String shopId = + uri.queryParameters["shopId"] ?? uri.queryParameters["store_id"]; if (tableId != null && tableId != "" && tenantCode != null && diff --git a/lib/home/huixiang_brand_page.dart b/lib/home/huixiang_brand_page.dart index 22ec8ead..af0a5425 100644 --- a/lib/home/huixiang_brand_page.dart +++ b/lib/home/huixiang_brand_page.dart @@ -44,7 +44,7 @@ class _BrandPage extends State Founder founder; queryHome() async { - EasyLoading.show(status: S.current.zhengzaijiazai); + EasyLoading.show(status: S.current.zhengzaijiazai,maskType: EasyLoadingMaskType.black); final SharedPreferences value = await SharedPreferences.getInstance(); apiService = ApiService( diff --git a/lib/home/points_mall_page.dart b/lib/home/points_mall_page.dart index e3c86fba..4e0d55fe 100644 --- a/lib/home/points_mall_page.dart +++ b/lib/home/points_mall_page.dart @@ -95,7 +95,7 @@ class _PointsMallPage extends State } creditGoods() async { - EasyLoading.show(status: S.current.zhengzaijiazai); + EasyLoading.show(status: S.current.zhengzaijiazai,maskType: EasyLoadingMaskType.black); final SharedPreferences value = await SharedPreferences.getInstance(); client = ApiService(Dio(), diff --git a/lib/home/welfare_exchange.dart b/lib/home/welfare_exchange.dart index 4fa8ecaa..b4ec8b8e 100644 --- a/lib/home/welfare_exchange.dart +++ b/lib/home/welfare_exchange.dart @@ -62,7 +62,7 @@ class _WelfareExchange extends State } queryUser() async { - EasyLoading.show(status: S.current.zhengzaijiazai); + EasyLoading.show(status: S.current.zhengzaijiazai,maskType: EasyLoadingMaskType.black); BaseData baseData = await apiService.queryInfo().catchError((onError) {}); if (baseData != null && baseData.isSuccess) { diff --git a/lib/home/welfare_page.dart b/lib/home/welfare_page.dart index 902a9511..a6cb8fdf 100644 --- a/lib/home/welfare_page.dart +++ b/lib/home/welfare_page.dart @@ -39,69 +39,48 @@ class _WelfarePage extends State { List goods = []; Goods goodsPrice; List coupons = []; - List> coupon=[]; + List> coupon = []; String categoryId; bool orderDesc = true; int orderType = 1; int type = 1; int couponIndex = 0; int swiperIndex = 0; + int _loadCount = 0; @override void initState() { super.initState(); - SharedPreferences.getInstance().then((value) => { - apiService = ApiService(Dio(), context: context, token: value.getString("token")), - _onRefresh(), - - }); + _onRefresh(); } queryGoods() async { - if (apiService == null) { - SharedPreferences value = await SharedPreferences.getInstance(); - apiService = ApiService( - Dio(), - context: context, - token: value.getString("token"), - ); - } - var param = { - "categoryId": categoryId ?? "", - "orderDesc": orderDesc, - "orderType": orderType, - "pageNum": 1, - "pageSize": 100, - "state": 1 - }; - BaseData> pageGoods = - await apiService.creditGoods(param).catchError((onError) { - refreshController.loadFailed(); - refreshController.refreshFailed(); - }); - EasyLoading.dismiss(); - if (pageGoods != null && pageGoods.isSuccess) { - setState(() { + try { + var param = { + "categoryId": categoryId ?? "", + "orderDesc": orderDesc, + "orderType": orderType, + "pageNum": 1, + "pageSize": 100, + "state": 1 + }; + BaseData> pageGoods = + await apiService.creditGoods(param).catchError((onError) { + refreshController.loadFailed(); + refreshController.refreshFailed(); + }); + EasyLoading.dismiss(); + if (pageGoods != null && pageGoods.isSuccess) { goods.clear(); goods.addAll(pageGoods.data.list); - }); - refreshController.refreshCompleted(); - refreshController.loadComplete(); - } else { - refreshController.loadFailed(); - refreshController.refreshFailed(); + } + } finally { + addLoadCount(); } } queryCoupon() async { - if (apiService == null) { - SharedPreferences value = await SharedPreferences.getInstance(); - apiService = ApiService( - Dio(), - context: context, - token: value.getString("token"), - ); - } + try{ BaseData> baseData = await apiService.queryCoupon({ "centre": true, "pageNum": 1, @@ -110,36 +89,48 @@ class _WelfarePage extends State { "state": 0 }).catchError((onError) { SmartDialog.showToast(AppUtils.dioErrorTypeToString(onError.type), - alignment: Alignment.center); - refreshController.refreshFailed(); - refreshController.loadFailed(); + alignment: Alignment.center); }); coupons.clear(); coupon.clear(); if (baseData != null && baseData.isSuccess) { coupons.addAll(baseData.data.list); - for(var i = 0;i < coupons.length~/3+1;i++){ + for (var i = 0; i < coupons.length ~/ 3 + 1; i++) { List con = []; - con = coupons.skip(i*3).take((i*3 0 && coupon[coupon.length - 1].isEmpty) - coupon.removeAt(coupon.length-1); - refreshController.refreshCompleted(); - refreshController.loadComplete(); + if (coupon.length > 0 && coupon[coupon.length - 1].isEmpty) + coupon.removeAt(coupon.length - 1); setState(() {}); - } else { - refreshController.refreshFailed(); - refreshController.loadFailed(); + }}finally{ + addLoadCount(); } } - - _onRefresh(){ + _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")); + } queryGoods(); queryCoupon(); } + addLoadCount() { + _loadCount += 1; + if (_loadCount == 2) { + _loadCount = 0; + EasyLoading.dismiss(); + if (refreshController.isRefresh) refreshController.refreshCompleted(); + if (mounted) setState(() {}); + } + } @override Widget build(BuildContext context) { @@ -157,7 +148,10 @@ class _WelfarePage extends State { width: double.infinity, height: 236.h, ), - Expanded(child: Container(color: Colors.white,)) + Expanded( + child: Container( + color: Colors.white, + )) ], ), Scaffold( @@ -170,7 +164,7 @@ class _WelfarePage extends State { titleSize: 18.sp, brightness: Brightness.dark, ), - body:SmartRefresher( + body: SmartRefresher( controller: refreshController, enablePullDown: true, enablePullUp: false, @@ -180,18 +174,15 @@ class _WelfarePage extends State { return MyFooter(mode); }, ), - onRefresh:(){ - setState(() { - _onRefresh(); - }); - }, + onRefresh:_onRefresh, physics: BouncingScrollPhysics(), scrollController: ScrollController(), child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.only( topLeft: Radius.circular(6), - topRight: Radius.circular(6),), + topRight: Radius.circular(6), + ), color: Colors.white, boxShadow: [ BoxShadow( @@ -213,12 +204,10 @@ class _WelfarePage extends State { Container( color: Colors.white, - padding: EdgeInsets.only(left: 14,right: 14), - child:Column( + padding: EdgeInsets.only(left: 14, right: 14), + child: Column( children: [ - inviteFriends(), - benefitExchange(), ], ), @@ -242,7 +231,8 @@ class _WelfarePage extends State { decoration: BoxDecoration( borderRadius: BorderRadius.only( topLeft: Radius.circular(6), - topRight: Radius.circular(6),), + topRight: Radius.circular(6), + ), color: Colors.white, boxShadow: [ BoxShadow( @@ -253,14 +243,13 @@ class _WelfarePage extends State { ), ], ), - child: Column( + child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( - padding: EdgeInsets.symmetric(horizontal: 17.w,vertical: 16.h), - child: - Row( + padding: EdgeInsets.symmetric(horizontal: 17.w, vertical: 16.h), + child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ @@ -282,81 +271,82 @@ class _WelfarePage extends State { ), ], )), - coupon.length == 0? - NoDataView( + coupon.length == 0 + ? NoDataView( + src: "assets/image/ka.webp", + isShowBtn: false, + text: S.of(context).haimeiyouyouhuiquankeyilingqu, + fontSize: 16.sp, + ) + : AspectRatio( + aspectRatio: 1.10, + child: Swiper( + onIndexChanged: (it) { + swiperIndex = it; + }, + index: couponIndex, + viewportFraction: 0.9, + scale: 0.7, + key: UniqueKey(), + pagination: SwiperPagination( + alignment: Alignment.bottomCenter, + builder: DotSwiperPaginationBuilder( + size: 8, + activeSize: 8, + space: 5, + activeColor: Colors.black, + color: Colors.black.withAlpha(76), + ), + ), + physics: BouncingScrollPhysics(), + itemBuilder: (context, position) { + return Column( + children: [ + Container( + child: weekList(coupon[position]), + ), + ], + ); + }, + itemCount: coupon.length ?? 0, + ), + ) + ], + )); + } + + Widget weekList(List cops) { + return Expanded( + child: (cops == null && cops.length == 0) + ? NoDataView( src: "assets/image/ka.webp", isShowBtn: false, text: S.of(context).haimeiyouyouhuiquankeyilingqu, fontSize: 16.sp, - ): AspectRatio( - aspectRatio: 1.10, - child: Swiper( - onIndexChanged: (it){ - swiperIndex = it; - }, - index: couponIndex, - viewportFraction: 0.9, - scale: 0.7, - key: UniqueKey(), - pagination: SwiperPagination( - alignment: Alignment.bottomCenter, - builder: DotSwiperPaginationBuilder( - size: 8, - activeSize: 8, - space: 5, - activeColor: Colors.black, - color: Colors.black.withAlpha(76), - ), - ), - physics: BouncingScrollPhysics(), - itemBuilder: (context, position) { - return Column( - children: [ - Container( - child: weekList(coupon[position]), - ), - ], - ); - }, - itemCount:coupon.length ?? 0, - ), ) - ], - ) + : ListView.builder( + padding: EdgeInsets.zero, + itemCount: cops.length, + scrollDirection: Axis.vertical, + shrinkWrap: true, + physics: BouncingScrollPhysics(), + itemBuilder: (context, position) { + return GestureDetector( + onTap: () {}, + child: weekCoupon(cops[position]), + ); + }, + ), ); } - Widget weekList(List cops){ - return Expanded( - child:(cops == null && cops.length == 0)? - NoDataView( - src: "assets/image/ka.webp", - isShowBtn: false, - text: S.of(context).haimeiyouyouhuiquankeyilingqu, - fontSize: 16.sp, - ):ListView.builder( - padding: EdgeInsets.zero, - itemCount: cops.length, - scrollDirection: Axis.vertical, - shrinkWrap: true, - physics: BouncingScrollPhysics(), - itemBuilder: (context, position) { - return GestureDetector( - onTap: () { - }, - child: weekCoupon(cops[position]), - ); - }, - ),); - } - ///优惠券列表 Widget weekCoupon(Coupon cop) { return Container( height: 95.h, width: double.infinity, - margin: EdgeInsets.only(bottom:10), - padding:EdgeInsets.symmetric(horizontal: 12), + margin: EdgeInsets.only(bottom: 10), + padding: EdgeInsets.symmetric(horizontal: 12), decoration: BoxDecoration( image: DecorationImage( fit: BoxFit.fill, @@ -367,8 +357,9 @@ class _WelfarePage extends State { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded(child: Container( - margin: EdgeInsets.only(top: 12,bottom: 12), + Expanded( + child: Container( + margin: EdgeInsets.only(top: 12, bottom: 12), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, @@ -383,31 +374,37 @@ class _WelfarePage extends State { color: Color(0xFF0D0D0D), ), ), - SizedBox(height: 12,), - (cop.status == 0)? - Text( - "发放时间: ${cop?.publishStartTime ?? ""}", - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 12.sp, - fontWeight: MyFontWeight.regular, - color: cop.status == 3 ? Color(0xFFB3B3B3) :Color(0xFF4D4D4D), - ), - ):Text( - "有效期至 ${cop?.useEndTime ?? ""}", - maxLines:1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 12.sp, - fontWeight: MyFontWeight.regular, - color: cop.status == 3 ? Color(0xFFB3B3B3) :Color(0xFF4D4D4D), - ), - ) + SizedBox( + height: 12, + ), + (cop.status == 0) + ? Text( + "发放时间: ${cop?.publishStartTime ?? ""}", + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 12.sp, + fontWeight: MyFontWeight.regular, + color: cop.status == 3 + ? Color(0xFFB3B3B3) + : Color(0xFF4D4D4D), + ), + ) + : Text( + "有效期至 ${cop?.useEndTime ?? ""}", + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 12.sp, + fontWeight: MyFontWeight.regular, + color: cop.status == 3 + ? Color(0xFFB3B3B3) + : Color(0xFF4D4D4D), + ), + ) ], ), )), - Column( // mainAxisAlignment: MainAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.end, @@ -441,7 +438,8 @@ class _WelfarePage extends State { style: TextStyle( fontSize: 16.sp, fontWeight: MyFontWeight.medium, - color: cop.status == 3 ? Color(0xFFB3B3B3):Color(0xff32A060), + color: + cop.status == 3 ? Color(0xFFB3B3B3) : Color(0xff32A060), ), ), SizedBox( @@ -450,26 +448,25 @@ class _WelfarePage extends State { Text( coupon != null ? double.tryParse("${cop.discountAmount}" ?? "0") - .toInt() - .toString() + .toInt() + .toString() : "", style: TextStyle( fontSize: 24.sp, fontWeight: MyFontWeight.semi_bold, - color: cop.status == 3 ? Color(0xFFB3B3B3):Color(0xff32A060), + color: + cop.status == 3 ? Color(0xFFB3B3B3) : Color(0xff32A060), ), ), ], ), Text( - S.of(context).manyuankeyong(coupon != null - ? ("${cop.fullAmount}" ?? "0") - .toString() - : ""), + S.of(context).manyuankeyong( + coupon != null ? ("${cop.fullAmount}" ?? "0").toString() : ""), style: TextStyle( fontSize: 12.sp, fontWeight: MyFontWeight.semi_bold, - color: cop.status == 3 ? Color(0xFFB3B3B3):Color(0xff32A060), + color: cop.status == 3 ? Color(0xFFB3B3B3) : Color(0xff32A060), ), ), ], @@ -489,7 +486,8 @@ class _WelfarePage extends State { style: TextStyle( fontSize: 22.sp, fontWeight: MyFontWeight.semi_bold, - color:cop.status == 3 ? Color(0xFFB3B3B3):Color(0xff32A060), + color: + cop.status == 3 ? Color(0xFFB3B3B3) : Color(0xff32A060), ), ), ], @@ -500,7 +498,7 @@ class _WelfarePage extends State { style: TextStyle( fontSize: 12.sp, fontWeight: MyFontWeight.semi_bold, - color: cop.status == 3 ? Color(0xFFB3B3B3):Color(0xff32A060), + color: cop.status == 3 ? Color(0xFFB3B3B3) : Color(0xff32A060), ), ), ], @@ -511,7 +509,7 @@ class _WelfarePage extends State { crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( - padding: EdgeInsets.only(bottom:10,top: 7), + padding: EdgeInsets.only(bottom: 10, top: 7), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -520,7 +518,8 @@ class _WelfarePage extends State { style: TextStyle( fontSize: 26.sp, fontWeight: MyFontWeight.semi_bold, - color: cop.status == 3 ? Color(0xFFB3B3B3):Color(0xff32A060), + color: + cop.status == 3 ? Color(0xFFB3B3B3) : Color(0xff32A060), ), ), ], @@ -531,7 +530,7 @@ class _WelfarePage extends State { style: TextStyle( fontSize: 12.sp, fontWeight: MyFontWeight.semi_bold, - color: cop.status == 3 ? Color(0xFFB3B3B3):Color(0xff32A060), + color: cop.status == 3 ? Color(0xFFB3B3B3) : Color(0xff32A060), ), ), ], @@ -547,31 +546,35 @@ class _WelfarePage extends State { textBaseline: TextBaseline.alphabetic, children: [ Text( - cop.limitAmount != "0.00"?"¥":"", + cop.limitAmount != "0.00" ? "¥" : "", style: TextStyle( fontSize: 16.sp, fontWeight: MyFontWeight.medium, - color: cop.status == 3 ? Color(0xFFB3B3B3):Color(0xff32A060), + color: + cop.status == 3 ? Color(0xFFB3B3B3) : Color(0xff32A060), ), ), SizedBox( height: 4.h, ), Text( - cop.limitAmount != "0.00"?(coupon != null - ? "${AppUtils.calculateDouble(double.tryParse(cop.limitAmount) ?? 0)}" - : "") :"", + cop.limitAmount != "0.00" + ? (coupon != null + ? "${AppUtils.calculateDouble(double.tryParse(cop.limitAmount) ?? 0)}" + : "") + : "", style: TextStyle( fontSize: 24.sp, fontWeight: FontWeight.bold, - color: cop.status == 3 ? Color(0xFFB3B3B3):Color(0xff32A060), + color: + cop.status == 3 ? Color(0xFFB3B3B3) : Color(0xff32A060), ), ), ], ), ], ); - }else{ + } else { return Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, @@ -582,25 +585,29 @@ class _WelfarePage extends State { textBaseline: TextBaseline.alphabetic, children: [ Text( - cop.discountPercent != 0 ? (coupon != null - ? "${(cop.discountPercent / 10.0 >= 10) ? 10 : cop.discountPercent / 10.0}" ?? - "0" - : ""):"", + cop.discountPercent != 0 + ? (coupon != null + ? "${(cop.discountPercent / 10.0 >= 10) ? 10 : cop.discountPercent / 10.0}" ?? + "0" + : "") + : "", style: TextStyle( fontSize: 30.sp, fontWeight: MyFontWeight.semi_bold, - color: cop.status == 3 ? Color(0xFFB3B3B3):Color(0xff32A060), + color: + cop.status == 3 ? Color(0xFFB3B3B3) : Color(0xff32A060), ), ), SizedBox( height: 4.h, ), Text( - cop.discountPercent != 0 ? "折" :"", + cop.discountPercent != 0 ? "折" : "", style: TextStyle( fontSize: 16.sp, fontWeight: MyFontWeight.semi_bold, - color: cop.status == 3 ? Color(0xFFB3B3B3):Color(0xff32A060), + color: + cop.status == 3 ? Color(0xFFB3B3B3) : Color(0xff32A060), ), ), ], @@ -612,67 +619,66 @@ class _WelfarePage extends State { ///优惠券领取状态 Widget weekBtn(Coupon cop) { - if(cop.status == 0) - return Align( - alignment: Alignment.centerRight, - child: InkWell( - onTap: () { - receiveCoupon(cop.id); - }, - child: Container( - padding: EdgeInsets.symmetric(horizontal: 12.w,vertical: 2.h), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(3), - color: Color(0xFF32A060), - ), - child: Text( - S.of(context).lingqu, - style: TextStyle( - fontSize: 12.sp, - fontWeight: MyFontWeight.medium, - color: Colors.white, - ), - ), - ), + if (cop.status == 0) + return Align( + alignment: Alignment.centerRight, + child: InkWell( + onTap: () { + receiveCoupon(cop.id); + }, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 2.h), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(3), + color: Color(0xFF32A060), + ), + child: Text( + S.of(context).lingqu, + style: TextStyle( + fontSize: 12.sp, + fontWeight: MyFontWeight.medium, + color: Colors.white, ), - ); - if(cop.status == 1 || cop.status == 2) + ), + ), + ), + ); + if (cop.status == 1 || cop.status == 2) return Align( - alignment: Alignment.centerRight, - child: InkWell( - onTap: () { - if (cop.bizType == 5 || cop.bizType == 3) { - Navigator.of(context).pushNamed( - '/router/write_off_page', - arguments: { - "couponId": cop.id, - "coupon": jsonEncode(cop.toJson()), - }); - } else { - showStoreSelector(cop.storeList); - } - }, - child: Container( - // height: 19.h, - padding: EdgeInsets.symmetric(horizontal:8.w,vertical: 1.h), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(3), - border: Border.all( - width: 1, color: Color(0xFF32A060), style: BorderStyle.solid), - color: Colors.transparent, - ), - alignment: Alignment.center, - child:Text( - S.of(context).qushiyong, - style: TextStyle( - fontSize: 12.sp, - fontWeight: MyFontWeight.regular, - color: Color(0xFF32A060), - ), - ), - ), + alignment: Alignment.centerRight, + child: InkWell( + onTap: () { + if (cop.bizType == 5 || cop.bizType == 3) { + Navigator.of(context) + .pushNamed('/router/write_off_page', arguments: { + "couponId": cop.id, + "coupon": jsonEncode(cop.toJson()), + }); + } else { + showStoreSelector(cop.storeList); + } + }, + child: Container( + // height: 19.h, + padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 1.h), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(3), + border: Border.all( + width: 1, color: Color(0xFF32A060), style: BorderStyle.solid), + color: Colors.transparent, + ), + alignment: Alignment.center, + child: Text( + S.of(context).qushiyong, + style: TextStyle( + fontSize: 12.sp, + fontWeight: MyFontWeight.regular, + color: Color(0xFF32A060), ), - ); + ), + ), + ), + ); } ///领取优惠券 @@ -682,8 +688,8 @@ class _WelfarePage extends State { if (baseData != null && baseData.isSuccess) { queryCoupon(); showAlertDialog(); - }else{ - SmartDialog.showToast(baseData?.msg,alignment: Alignment.center); + } else { + SmartDialog.showToast(baseData?.msg, alignment: Alignment.center); } } @@ -710,8 +716,8 @@ class _WelfarePage extends State { ///邀请好友 Widget inviteFriends() { return Container( - margin: EdgeInsets.only(top:24.h,bottom:20.h), - child:Column( + margin: EdgeInsets.only(top: 24.h, bottom: 20.h), + child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -723,17 +729,19 @@ class _WelfarePage extends State { color: Color(0xFF0D0D0D), ), ), - SizedBox(height: 12,), + SizedBox( + height: 12, + ), GestureDetector( - onTap: (){ + onTap: () { Navigator.of(context).pushNamed('/router/invite_friends'); }, - child:ClipRRect( - child:Image.asset( + child: ClipRRect( + child: Image.asset( "assets/image/welfare_spread.webp", - width:double.infinity, + width: double.infinity, fit: BoxFit.fill, - height:80.h, + height: 80.h, ), borderRadius: BorderRadius.circular(6.w), ), @@ -747,28 +755,29 @@ class _WelfarePage extends State { Widget benefitExchange() { return Container( width: double.infinity, - margin: EdgeInsets.only(top:24.h,bottom:20.h), - child:Column( + margin: EdgeInsets.only(top: 24.h, bottom: 20.h), + child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ GestureDetector( - onTap: (){ + onTap: () { Navigator.of(context).pushNamed('/router/welfare_exchange'); }, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Expanded(child: - Text( - S.of(context).fuliduihuan, - style: TextStyle( - fontSize: 15.sp, - fontWeight: MyFontWeight.bold, - color: Color(0xFF0D0D0D), + Expanded( + child: Text( + S.of(context).fuliduihuan, + style: TextStyle( + fontSize: 15.sp, + fontWeight: MyFontWeight.bold, + color: Color(0xFF0D0D0D), + ), ), - ),), + ), Text( S.of(context).gengduo, style: TextStyle( @@ -785,47 +794,50 @@ class _WelfarePage extends State { ], ), ), - SizedBox(height: 12,), - (goods == null || goods.length == 0)? NoDataView( - src: "assets/image/xiao_fei.webp", - isShowBtn: false, - text: "暂无商品可兑换", - fontSize: 16.sp, - margin: EdgeInsets.all(60.h), - ) - :GridView.builder( - itemCount:goods.length>6?6:goods.length, - padding: EdgeInsets.only( - // left: 16.w, - // right: 16.w, - top: 18.h, - bottom: 16.h, - ), - shrinkWrap: true, - physics: BouncingScrollPhysics(), - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - //一行的Widget数量 - crossAxisCount: 2, - //水平子Widget之间间距 - crossAxisSpacing: 11.w, - //垂直子Widget之间间距 - mainAxisSpacing: 16.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: exchangeItem(goods[index]), - ); - }, - ) + SizedBox( + height: 12, + ), + (goods == null || goods.length == 0) + ? NoDataView( + src: "assets/image/xiao_fei.webp", + isShowBtn: false, + text: "暂无商品可兑换", + fontSize: 16.sp, + margin: EdgeInsets.all(60.h), + ) + : GridView.builder( + itemCount: goods.length > 6 ? 6 : goods.length, + padding: EdgeInsets.only( + // left: 16.w, + // right: 16.w, + top: 18.h, + bottom: 16.h, + ), + shrinkWrap: true, + physics: BouncingScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + //一行的Widget数量 + crossAxisCount: 2, + //水平子Widget之间间距 + crossAxisSpacing: 11.w, + //垂直子Widget之间间距 + mainAxisSpacing: 16.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: exchangeItem(goods[index]), + ); + }, + ) ], ), ); @@ -871,10 +883,8 @@ class _WelfarePage extends State { margin: EdgeInsets.only( right: 12.w, top: 10.h, - ),padding: EdgeInsets.only( - bottom: 8, - left: 8 - ), + ), + padding: EdgeInsets.only(bottom: 8, left: 8), child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.start, @@ -894,12 +904,12 @@ class _WelfarePage extends State { Text( pointPrice(goods), style: TextStyle( - color: Color(0xFFE5600D), - fontSize: 16.sp, + color: Color(0xFFE5600D), + fontSize: 16.sp, fontFamily: 'JDZhengHT', - fontWeight: MyFontWeight.semi_bold, - ), - ), + fontWeight: MyFontWeight.semi_bold, + ), + ), ], ), ), @@ -912,16 +922,22 @@ class _WelfarePage extends State { ); } - String pointPrice(Goods goodsPrice){ - if(goodsPrice == null) - return ""; - if(goodsPrice?.oneBean!=null && goodsPrice?.oneBean!="0"){ + String pointPrice(Goods goodsPrice) { + if (goodsPrice == null) return ""; + if (goodsPrice?.oneBean != null && goodsPrice?.oneBean != "0") { return "${goodsPrice?.oneBean}印章"; - } else if(goodsPrice?.onePrice!=null && goodsPrice?.onePrice!="0"){ + } else if (goodsPrice?.onePrice != null && goodsPrice?.onePrice != "0") { return S.of(context).jifen_(goodsPrice?.onePrice); - }else if((goodsPrice?.onePrice == null || goodsPrice?.onePrice == "0") && ((goodsPrice?.price != null && goodsPrice?.price != "0") || (goodsPrice?.money != null && goodsPrice?.money != "0.00"))){ - return (goodsPrice?.price== "0"|| goodsPrice?.price == null ? "" : S.of(context).jifen_(goodsPrice?.price)) + (goodsPrice?.money== "0"|| goodsPrice?.money == null ? "" : " + ${AppUtils.calculateDouble(double.tryParse(goodsPrice?.money) ?? 0)}元"); - }else if(goodsPrice.oneMoney != null && goodsPrice.oneMoney != "0.00"){ + } else if ((goodsPrice?.onePrice == null || goodsPrice?.onePrice == "0") && + ((goodsPrice?.price != null && goodsPrice?.price != "0") || + (goodsPrice?.money != null && goodsPrice?.money != "0.00"))) { + return (goodsPrice?.price == "0" || goodsPrice?.price == null + ? "" + : S.of(context).jifen_(goodsPrice?.price)) + + (goodsPrice?.money == "0" || goodsPrice?.money == null + ? "" + : " + ${AppUtils.calculateDouble(double.tryParse(goodsPrice?.money) ?? 0)}元"); + } else if (goodsPrice.oneMoney != null && goodsPrice.oneMoney != "0.00") { return "${AppUtils.calculateDouble(double.tryParse(goodsPrice.oneMoney) ?? 0)}元"; } } @@ -929,8 +945,10 @@ class _WelfarePage extends State { ///活动任务 Widget activityTask() { return Container( - margin: EdgeInsets.only(bottom:20.h,), - child:Column( + margin: EdgeInsets.only( + bottom: 20.h, + ), + child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -956,17 +974,18 @@ class _WelfarePage extends State { ), ], ), - SizedBox(height: 12.h,), + SizedBox( + height: 12.h, + ), ListView.builder( padding: EdgeInsets.zero, - itemCount:6, + itemCount: 6, scrollDirection: Axis.vertical, shrinkWrap: true, physics: NeverScrollableScrollPhysics(), itemBuilder: (context, position) { return GestureDetector( - onTap: () { - }, + onTap: () {}, child: taskItem(), ); }, @@ -978,72 +997,76 @@ class _WelfarePage extends State { Widget taskItem() { return Container( - width:double.infinity, - height:95.h, + width: double.infinity, + height: 95.h, decoration: BoxDecoration( borderRadius: BorderRadius.circular(6), color: Colors.white, boxShadow: [ - BoxShadow( - color: Color(0x08213303).withAlpha(12), - offset: Offset(0, 2), - blurRadius: 3, - spreadRadius: 0, - ), - ], + BoxShadow( + color: Color(0x08213303).withAlpha(12), + offset: Offset(0, 2), + blurRadius: 3, + spreadRadius: 0, + ), + ], ), - padding: EdgeInsets.symmetric(horizontal: 12.w,vertical: 12.h), + padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 12.h), margin: EdgeInsets.only(bottom: 10.h), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.end, children: [ - Expanded(child:Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "海峡姐妹茶新品尝鲜(0/3)", - style: TextStyle( - fontSize: 14.sp, - fontWeight: MyFontWeight.bold, - color: Color(0xFF353535), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "海峡姐妹茶新品尝鲜(0/3)", + style: TextStyle( + fontSize: 14.sp, + fontWeight: MyFontWeight.bold, + color: Color(0xFF353535), + ), ), - ), - Text( - "可获得¥10代金券", - style: TextStyle( - fontSize: 12.sp, - fontWeight: MyFontWeight.regular, - color: Color(0xFF4D4D4D), + Text( + "可获得¥10代金券", + style: TextStyle( + fontSize: 12.sp, + fontWeight: MyFontWeight.regular, + color: Color(0xFF4D4D4D), + ), ), - ), Text( - "购买任意3杯新品", - style: TextStyle( - fontSize: 10.sp, - fontWeight: MyFontWeight.regular, - color: Color(0xFFB3B3B3), + Text( + "购买任意3杯新品", + style: TextStyle( + fontSize: 10.sp, + fontWeight: MyFontWeight.regular, + color: Color(0xFFB3B3B3), + ), ), - ), - ], - ),), + ], + ), + ), Container( width: 55.w, height: 21.h, decoration: BoxDecoration( gradient: new LinearGradient( - begin: Alignment.centerLeft, - end: Alignment.centerRight, - colors: [ - Color(0xFFFF2700), - Color(0xFFFF4F00), - ],), + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + Color(0xFFFF2700), + Color(0xFFFF4F00), + ], + ), // border: Border.all(color: Colors.white,width: 0.5), shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(3), ), alignment: Alignment.center, - child:Text( + child: Text( "领取", style: TextStyle( fontSize: 12.sp, @@ -1056,5 +1079,4 @@ class _WelfarePage extends State { ), ); } - } diff --git a/lib/integral/integral_page.dart b/lib/integral/integral_page.dart index 06ae97a7..771ec56e 100644 --- a/lib/integral/integral_page.dart +++ b/lib/integral/integral_page.dart @@ -19,10 +19,10 @@ import 'package:huixiang/view_widget/sign_in_widget.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import '../utils/flutter_utils.dart'; import 'intergra_view/integral_task.dart'; class IntegralPage extends StatefulWidget { - @override State createState() { return _IntegralPage(); @@ -51,13 +51,17 @@ class _IntegralPage extends State { ); userInfo = UserInfo.fromJson(jsonDecode(value.getString("user"))); - BaseData> rankData = await apiService.rankList() - .catchError((onError) {}); + BaseData> rankData = + await apiService.rankList().catchError((onError) { + SmartDialog.showToast(AppUtils.dioErrorTypeToString(onError.type), + alignment: Alignment.center); + refreshController.refreshFailed(); + }); if (rankData != null && rankData.isSuccess) { ranks.clear(); ranks.addAll(rankData.data); refreshController.refreshCompleted(); - }else { + } else { refreshController.refreshFailed(); } @@ -112,7 +116,9 @@ class _IntegralPage extends State { Scaffold( backgroundColor: Colors.transparent, appBar: MyAppBar( - exit: (){Navigator.of(context).pop(signInfo.todayHasSignin ?? false);}, + exit: () { + Navigator.of(context).pop(signInfo?.todayHasSignin ?? false); + }, background: Colors.transparent, leadingColor: Colors.white, title: "", @@ -124,7 +130,9 @@ class _IntegralPage extends State { margin: EdgeInsets.only(right: 16.w), child: GestureDetector( onTap: () { - Navigator.of(context).pushNamed('/router/integral_detailed_page',arguments:{"titleType":2}); + Navigator.of(context).pushNamed( + '/router/integral_detailed_page', + arguments: {"titleType": 2}); }, child: Text( S.of(context).mingxi, @@ -137,17 +145,17 @@ class _IntegralPage extends State { ), ), ), - body:SmartRefresher( + body: SmartRefresher( controller: refreshController, enablePullDown: true, enablePullUp: false, - header: MyHeader(), + header: MyHeader(color: Colors.white,), footer: CustomFooter( builder: (context, mode) { return MyFooter(mode); }, ), - onRefresh:(){ + onRefresh: () { setState(() { querySignInfo(); }); @@ -163,9 +171,19 @@ class _IntegralPage extends State { return Column( children: [ /// 上面的积分和VIP等级显示 - IntegralVip(rankLevel, signInfo, userInfo,"${ (signInfo?.signInList?.length ) ?? "0"}", - ((signInfo?.rewardList != null && signInfo.rewardList.length > (signInfo?.signInList?.length ?? 0)) ? - signInfo.rewardList[signInfo?.signInList?.length ?? 0]:0).toString()), + IntegralVip( + rankLevel, + signInfo, + userInfo, + "${(signInfo?.signInList?.length) ?? "0"}", + ((signInfo?.rewardList != null && + signInfo.rewardList.length > + (signInfo?.signInList?.length ?? + 0)) + ? signInfo.rewardList[ + signInfo?.signInList?.length ?? 0] + : 0) + .toString()), ///立即签到 InForPoints(signInfo, _signIn), @@ -191,7 +209,9 @@ class _IntegralPage extends State { SmartDialog.showToast("今日已签到了", alignment: Alignment.center); return; } - EasyLoading.show(status: S.of(context).zhengzaijiazai); + EasyLoading.show( + status: S.of(context).zhengzaijiazai, + maskType: EasyLoadingMaskType.black); BaseData baseData = await apiService.signIn().catchError((onError) {}); if (baseData != null && baseData.isSuccess) { setState(() {}); diff --git a/lib/integral/intergra_view/integral_task.dart b/lib/integral/intergra_view/integral_task.dart index 408d8694..e9bb165a 100644 --- a/lib/integral/intergra_view/integral_task.dart +++ b/lib/integral/intergra_view/integral_task.dart @@ -6,6 +6,8 @@ import 'package:huixiang/utils/font_weight.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:huixiang/view_widget/round_button.dart'; +import '../../view_widget/no_data_view.dart'; + class IntegralTask extends StatefulWidget { final SignInfo signInfo; @@ -57,28 +59,38 @@ class _IntegralTask extends State { ), Expanded( child: Container( - child: ListView.builder( - padding: EdgeInsets.only(left: 10.w, top: 20.h), - physics: BouncingScrollPhysics(), - // loop: false, - // pagination: SwiperPagination( - // alignment: Alignment.bottomCenter, - // builder: DotSwiperPaginationBuilder( - // size: 8, - // activeSize: 8, - // space: 5, - // activeColor: Colors.black, - // color: Colors.black.withAlpha(76), - // ), - // ), - itemBuilder: (context, position) { - return taskItem(widget.signInfo.taskList[position]); - }, - itemCount: (widget.signInfo != null && - widget.signInfo.taskList != null && - widget.signInfo.taskList.length > 0) - ? widget.signInfo.taskList.length - : 0), + child: (widget.signInfo != null && + widget.signInfo.taskList != null && + widget.signInfo.taskList.length > 0) + ? ListView.builder( + padding: EdgeInsets.only(left: 10.w, top: 20.h), + physics: BouncingScrollPhysics(), + // loop: false, + // pagination: SwiperPagination( + // alignment: Alignment.bottomCenter, + // builder: DotSwiperPaginationBuilder( + // size: 8, + // activeSize: 8, + // space: 5, + // activeColor: Colors.black, + // color: Colors.black.withAlpha(76), + // ), + // ), + itemBuilder: (context, position) { + return taskItem(widget.signInfo.taskList[position]); + }, + itemCount: (widget.signInfo != null && + widget.signInfo.taskList != null && + widget.signInfo.taskList.length > 0) + ? widget.signInfo.taskList.length + : 0) + : NoDataView( + src: "assets/image/xiao_fei.webp", + isShowBtn: false, + text: "暂无任务可做~", + fontSize: 16.sp, + margin: EdgeInsets.only(left: 60.w, right: 60.w), + ), ), flex: 1, ) diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 5cd89e23..eb55712d 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -743,6 +743,11 @@ "xiugai":"修改", "bangdingshouji":"绑定手机", "genggaibangdingshoujihao":"更改绑定手机号", + "qianbao":"钱包", + "huiyuanma":"会员码", + "yinzhang":"印章", + "dianpuchongzhi":"店铺充值", + "zhuxiaozhanghao":"注销账号", diff --git a/lib/l10n/intl_en_US.arb b/lib/l10n/intl_en_US.arb index bc843241..f049d607 100644 --- a/lib/l10n/intl_en_US.arb +++ b/lib/l10n/intl_en_US.arb @@ -744,6 +744,11 @@ "xiugai":"modify", "bangdingshouji":"bind phone", "genggaibangdingshoujihao":"modify bind phone", + "qianbao":"Wallet", + "huiyuanma":"vipCode", + "yinzhang":"Seal", + "dianpuchongzhi":"Recharge", + "zhuxiaozhanghao":"Account cancellation", diff --git a/lib/l10n/intl_zh_CN.arb b/lib/l10n/intl_zh_CN.arb index a106020b..bf3c8ef9 100644 --- a/lib/l10n/intl_zh_CN.arb +++ b/lib/l10n/intl_zh_CN.arb @@ -744,6 +744,11 @@ "xiugai":"修改", "bangdingshouji":"绑定手机", "genggaibangdingshoujihao":"更改绑定手机号", + "qianbao":"钱包", + "huiyuanma":"会员码", + "yinzhang":"印章", + "dianpuchongzhi":"店铺充值", + "zhuxiaozhanghao":"注销账号", diff --git a/lib/l10n/intl_zh_Hans_CN.arb b/lib/l10n/intl_zh_Hans_CN.arb index a5068c4a..557b7c95 100644 --- a/lib/l10n/intl_zh_Hans_CN.arb +++ b/lib/l10n/intl_zh_Hans_CN.arb @@ -744,6 +744,11 @@ "xiugai":"修改", "bangdingshouji":"绑定手机", "genggaibangdingshoujihao":"更改绑定手机号", + "qianbao":"钱包", + "huiyuanma":"会员码", + "yinzhang":"印章", + "dianpuchongzhi":"店铺充值", + "zhuxiaozhanghao":"注销账号", diff --git a/lib/l10n/intl_zh_Hant_CN.arb b/lib/l10n/intl_zh_Hant_CN.arb index 75d2921a..9565aa1d 100644 --- a/lib/l10n/intl_zh_Hant_CN.arb +++ b/lib/l10n/intl_zh_Hant_CN.arb @@ -735,6 +735,11 @@ "xiugai":"修改", "bangdingshouji":"綁定手機", "genggaibangdingshoujihao":"更改綁定手機號", + "qianbao":"錢包", + "huiyuanma":"會員碼", + "yinzhang":"印章", + "dianpuchongzhi":"店鋪充值", + "zhuxiaozhanghao":"註銷帳號", diff --git a/lib/l10n/intl_zh_TW.arb b/lib/l10n/intl_zh_TW.arb index 07916c48..cfefecc4 100644 --- a/lib/l10n/intl_zh_TW.arb +++ b/lib/l10n/intl_zh_TW.arb @@ -737,6 +737,11 @@ "xiugai":"修改", "bangdingshouji":"綁定手機", "genggaibangdingshoujihao":"更改綁定手機號", + "qianbao":"錢包", + "huiyuanma":"會員碼", + "yinzhang":"印章", + "dianpuchongzhi":"店鋪充值", + "zhuxiaozhanghao":"註銷帳號", diff --git a/lib/login/captcha/block_puzzle_captcha.dart b/lib/login/captcha/block_puzzle_captcha.dart new file mode 100644 index 00000000..9c4d6496 --- /dev/null +++ b/lib/login/captcha/block_puzzle_captcha.dart @@ -0,0 +1,552 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:math'; + +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +import '../../retrofit/retrofit_api.dart'; +import '../../utils/captcha_util.dart'; +import '../../utils/widget_util.dart'; +import 'click_word_captcha.dart'; + +typedef VoidSuccessCallback = dynamic Function(String v); + +class BlockPuzzleCaptchaPage extends StatefulWidget { + final VoidSuccessCallback onSuccess; //拖放完成后验证成功回调 + final VoidCallback onFail; //拖放完成后验证失败回调 + + BlockPuzzleCaptchaPage({this.onSuccess, this.onFail}); + + @override + _BlockPuzzleCaptchaPageState createState() => _BlockPuzzleCaptchaPageState(); +} + +class _BlockPuzzleCaptchaPageState extends State + with TickerProviderStateMixin { +// String baseImageBase64 = +// "/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCADIAlgDASIAAhEBAxEB/8QAHAABAAMBAQEBAQAAAAAAAAAAAAUGBwQIAwIB/8QASBAAAQMDAQUEBQYLBQkAAAAAAAECAwQFEQYHEiExURMiQWEycYGRoQgUI0KCsRUkM1JicpLB0eHwNDVzorM3U2NkdZOy0vH/xAAaAQEAAwEBAQAAAAAAAAAAAAAAAgMEBQEG/8QAMhEBAAIBAgMECQQCAwAAAAAAAAECAwQRBSExEkFR8BMiMmFxgaGxwQaR0eEUI0Jisv/aAAwDAQACEQMRAD8A9UgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR9TeaCnXD6hrndGIrvuPYiZ6I2vWkb2nZIAr8mq6Fi4SGqcnVGt/ep+otWWt/5R80P68ar/wCOSfor+DNOv00TtN4hPA56Otpa1iupKiKZE57jkXHr6HQQmNurTW1bx2qzvAADxIBE3/UNusUSOrpvpHJlkLE3nu9SdPNcIZreto12qn9na446JiqiNXd7SRfemOPTHtNen0WXUc6xy8ZcnXca0mhnsZLb28I5z/XzbADB32XWl8Y50kd0lYq5xUTdm32Ne5PghyybMNSObvJRU+907duToV4Vg6ZNRWJ8++GGvHNRk549LaY+cfiXoIHnOWxa9sDGvp4rxDGi5RKWdZW+1rHLw9aHZY9r19t0vZXqCG5RNVUeqtSGZvtRN3h03U9ZZbgGS9e1pslb/CfMfVox8cxxPZ1FLUn3x5+z0ACvaS1hZtVQK61VP07EzJTSpuyxp1VvinFOKZTzLCcTLivhtNMkbTHdLs48lcle1Sd4AAVpgIu/ahs+n4Emvdzo6CN2d3t5Uar8eDUXi5fJMmf3Pbxoqj/ss1xuC/8ALUjm/wCpuGvBoNTqI3xY5mPGI5fv0Rm9Y5TLVAY3D8obSj3okluv0Lc+k+CJUT9mRVLXY9rOibzIkVNf6aCZcfR1jXUy56IsiIir6lUnl4bq8Ub3xz+yUc+i8gNVHIitVFReKKniDCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHLX1sdIzvd6ReTE/rgh9KudKeFXc3LwanVSEgpZLhUOc9yozPff+5P64E6Viec9EbTPc4qmatukqxsRz0/MZwanr/mfeDTDn4WqqEani2JM/Ff4Fjghjp40jhYjGJ4IfQnOaY5V5KZ01bTvfmgU0rb8Yc6ocvVXp+5DlqdG0j2r2FTURu8N7DkT2YRfiWgEYzXjvV34fpskbWpDNLnpm6W1/wA4pcztZxSWnVWyN88c/cqnXYNbPic2C8L2kS8EqGp3m/rInNPNOPkpoBVtW6Wjucb6qga2KvTiqJwbN5L5+fv8tFM1cnq5Y+bh6nhWo0MzqOG2neOtZ5xP8/fwlZ43sljbJG5r2ORHNc1coqLyVFKrrbVbbPGtJQq19xenFeaQovivVeie1eGEWoWHU9ZYaeqo3Rue1EckccnBYZc8fZnOU69Mqf3R1gfqG4y1lwc91LG/elcvOZ68d3PxX+eUsppq45m+X2Y+rFn/AFDl1+Oml0Fdst+U/wDXx5/nuju3fDT2lq/U07q6umfHSvd3538Xy9d3PuzyTzxg02y2C22aNG0FKxkmMOlcm9I71uXj7OXkScbGxsayNqNY1ERrWphEToh/SnPq8mbl0jwdzhfBNPw+va27WTvtPXf3eHncABldkIPUulLNqSBzLrRRySYw2dqbsrOmHpx8c4XKdUUnATx5b4rRfHO0+5C+OuSvZvG8PNmuNB3fRFUy7WuomloYn5jrIu7LTqvLfROXTeTgvJcZRF0vZTtGj1NG22XdzIb3G3LVTg2qanNzU8HInNvtThlG6NNHHNE+KZjZIntVrmOTKOReCoqeKHm3apoyXRd6p7nZnyR2+aXfp3tXvUsyd5GZ6cMtXoiovLK/VaXU4+NU/wAXV8ssezb8T55+6XCzYL8Mt6fBzx98eHnzyekaiaKmgknqJGRQxNV75HuRrWNRMqqqvBERPE8/bSNtlRO6Wh0avzenTLX3CRnff/htX0U81TPHgiYyQOvdoV31pQ260wwvijc1jZ4IEVVq6jOEwicVbnCtZ1XjnCY1HZTstpdNwxXO+RR1N9ciOai4cyk8m+Cv6u9icMq73Bw/TcIxf5PEY7V59mn5nztHvlfOrya2/o9Nyr3yyHTmyHV2raj8I3Z7rfHOqOfVXJzpKiROqMVd5eX11b5Gi235POn4o2Lc7vdqqZPS7JY4Y1+zuucn7RtQMGq/Uuuzz6tuxXwiPz1b8Wkx448ZZFUfJ/0fLHuxz3iB35zKlqr/AJmqnwKfqT5OdQxkkmm74yf82muEW6qp45lZwz9j2no0GSnGtbSd/STPx5tVZ7PR40tt911sjuzKKZtRRxKquSgq/paWZOarGqLjxTKsVFzz6HpPZltJtGvaR6UmaS6QtR09BK5Fe1OW81frsyuMoiYymUTKFm1DY7ZqK1y2690cVZRyc45E5L1RU4tVPBUVFQ8mbRNE3rZRqijudoq6j5l2u9b7i1E3o3YX6KThje3c803Xtzw9JE31vp+LR2bRFMvj3T5/dor2cvKeUvYoKZsp1zT670wyuakcNxhVIq2mav5OTHNEXjuuTii+tMqqKXM4GXFbFecd42mFExNZ2kABW8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPzK7djc7ogEXWq6oqEYzrut/iScETYYmxs5J8ThoGb1Q5y/UT4r/SkiTvPcAAIAAAAAApWt9KSXKqirLajUqJHNjnavBFTkj/Z4+Xq42q00ENst0FHTJ9HE3GV5uXxVfNV4nWcb7nSMu0VsdMiV0sLqhkW6vGNqoiuzjHNye8tnJe9Yp3QwYeHafT6i+qpG1r9f6+Pf4y7AAVN4AAAK9dtaaftNHeaq4XBIYLPJHFXO7J7uxdJu7iYRqqud9vLPMsJO2O1Y3tG3nf8x+7yJiQjdSWal1BZKu2VzVWCoZu5Tmx3Nrk80VEX2EkDyl7Y7Res7TDy1YtE1t0lkuyXZtLYrnUXa/MY6thkfDSMauWo1Mosv2vDlhFXPPhrQBp1uty63LOXNPP7KtNpqabHGPH0AAZF4AABEat0/Rap07W2e5szT1LFbvJ6UbubXt82rhU9RLglW00tFqztMETs8ebMbtW7NtrP4OujuzhdUfg2vblUYqK7DJUzjgiq1yKv1XO6nsM8sfKosbKPWdBdI2MYy6UitkxzdLEqIrl+w+NPsnojZ/d337Q9iucr0fPU0cT5XJ4ybqI//Minb4tEZ8WLWR/yjafjHmV+ae1EXT4AOEoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPlU/kHf14n1PxOmYXp5HsdRzW7nL1yh2HBbn/TSM6oip7P/p3ntupIACIAAAAABTaz/a9a/wDo1T/rRFyK3ftN1Fwv1Nd7fd5rdVwUz6XLII5UcxzmuXg9F8WoW4ZiJneduUqssTMRtG/ODX16qrLZoPwakSXGvq4aCmdKiqxkkrt1HORPBEyvsQiKupvmlbxYvwle3Xi33OqbQStmpo4nxSua5zXsWNE7uW4VHZVOqnbVaRrbnR1VJftQVNdTSNY6Hdp4oJKeZrt5srHsTmmE4Lw588n7o9K1cl3oa/UN7muzqBVdSw/N2QRteqbvaORvpPwqoi8ETK4RC6k46V2mYnrvy68uW07cvp81NoyWtvETHTbn08d+fP6/JTNTatu1C7UNVT6gWWqt0zuyoKC2unpGMaqdyebs8o9UzvYe1Grn1Flqq286g1jX2i1XVbPRWymhknkhgjlmlllRytRFka5qNRG8eGc/D41uzuaotdws8OoaumsVVJJL81jgj32ue7fVqyKmXM3lXhzxwVyoS910vUyXn8K2S8TWuufA2mnxCyaOdjVVWq5q47yZXC58uRr9Lp9oiu2+085jlHs9Y2+PjtM9VUUzxO877cuW/wAenP4eG/gyyuueodM6f2mV6XCJL9Dc6CP55DA1GvRewj3tx281FWNeKccKq48Cztq9XX7atqqyUGoktlitkdHLmOkikna6SJy7jFe1W7rlRznK5HKm61G4RVJObZlTz6fv9sqLvWzOvNVDVz1MjGb6PY9j1wiIiYVWcscEXCcix2jTcVt1bqC/MqJHy3hlMx8StRGx9i1zUwvjne+BPNqsE1tNdptty9X3Y47491tvD5r8VbxERb7/AB/pnNLrPU9bpqz2elrKRNTVt6qbK+5up03Ejp1kV9QkXo7+6xMM9FVzyTgkpSVGrLLtYstkuWolutjrqKpqG9pSwxTLIzcRWvVjUTCbyKiojc7youcZPnq/SMVj0ivzenvlynjvrrxFPams+c0ckj3OV7Y3ZSVqbytVmHbyOXgmMpF6Gs91ue1iC/1cuo6umoLdLTvr7xRtomyyPc3djhg3GOa1Gq5VeqLlU8OGff8AValr1iIrtbujffu28O7aOXuhbz6NoABxVgAAAAAAADAflaMYtBph6/lEnnanqVrc/FELz8nlyu2P2HeXOFqGp6kqJUT4GX/KwubJL9p+2NVUfS00tVJ0xI5rW/6T/ebNshtq2nZjpqlc1Wv+ZMme1UwqOk+kci+1yn0Grr2OE4Yt1mZn/wBfyn2t67LeAD59AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ0zlpKxHYXDV96KTDXI5qOauWqmUVPE47pTLNDvRpmRvh1ToRtrubad3YVLsRKvdev1V6L5FvZ7dd46veqfABU8AAAAIbVWoqPTduWpq3b0r8pDA1e9K7onROq+HuRZVrN57NeqN71pWbWnaIcmsNWUmmvmrJWrNPM9FWNi95see8/+CeK+pSwwTR1EEc0D2yRSNR7HtXKOaqZRUPPe5eNWXC5XBkLqiaNizTbid1jU5Mb7M4TmuF5qXLZNqpjEbZK6VEY5c0b3csrxWPPxT2p0Q35tF2Me9ecx1cDTcYtbVdjLG1Lez8Y/n6TtDVQAc59CAAAAAB+KiaOngkmne2OKNqve9y4RrUTKqp+zK9rWp2ysdZKCRHNRc1b28spyjz6+K+xOqGnSaa2pyxjj5+6GHiOvx6DBOa/yjxnwW3ResKTVHztkTVgqIHriJ6950We6/7kVOOF9aFnPOK0950fcbbcViWnmkYk0W+mWvavNjvZjKc0ynJTc9JakotTW1KmjXclZhJ4HL3ondF6ovHC+PryibeJcPjD/uwc6T9J8/w5/B+Kzqo9BqOWWO7pvHn+U2ADku8AAAfKsqYKKknqquVkNNAx0ssj1w1jWplVVeiIh9TzVt52nRXuOTTmnpkfa2P/AByrYvCoci8I2L4sReKr9ZUTHD0ulwvhuXiOeMVI5d8+EeeinPnrhrvZSnpPtY2v8GSJTXKqTLVyixUcaIi557q7jfVvv8z2S1qNajWoiNRMIickMo2BbP36Vs0l3u8Kx3u4sRFjemHU0PNI+qOVe877KY7vHWDXx7V482aMOD2McbR+ftEfLd7h37O9usgAOEtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhr1aFqUdLS4SVeLmLwR38FJkEq2ms7w9idlEpb5WWiRYZGLJE3gsMndc31L4E7R6ttM+ElnWmev1Z03U/a9H4kncLdSXCPcq4WyY5LycnqVOKFVuOg45VVaOufH+jKxH/FFT95pi2HJ7fKXu8StEd2t0jd6O4Uj29WzNVPvOSt1RY6JrlqLtRIrebWyo937Lcr8CgVWzm7vcvZz256dXve1fduKfiDZZXy/2q50sCf8KJ0v3q0sjBpo52yIW3jo7dRbVIImPisNK6aTklRUIrWJ5o30l9u6U6yWG+65uS1tTLJ2DlxJXTp3cZ9GNvDPjwTCJ448dJsuzaxW97ZapklxmTj+MqisRf1Ewip68l0Y1rGo1iI1rUwiImERCU6rFgjbTxz8ZY8mlnPP+2eXg4LDZ6OxW2Oht0e5E3irl4ukd4ucviq/yTCIiGY7SNEvoppbxZY1dSuVX1FOznCvNXt/R8VTw58vR14GXFqL479vrv197zWcPxavD6G0bbdPczHQ+0NjoYqLUEmHJhsdYvJyeCSdF/S5dcc10yN7ZI2vjc17HIjmuauUVF5KilE1Xs6pLjI+qs72UVW7i6NU+hkXrhPRXzTh5Z4lJjdqbRz1aqVNJCi9O0gdn3tyuPJTTbDi1HrYp2nwcWNfrOF+prKTekdLR+f72n4tzBl1BtMq0Z+OW+CZ3g6KRY/gqOJJNpMCt/u2Xe6dqmPuKJ0mWO5qr+peGzG85NvjE/wv5/JHtjY58jmtY1FVznLhERPFTNavaNVPbikoIYl6ySLJ8ERCGcuotVvRPxiohVem5C3HublM+ak6aK3W87QyZv1XppnsaStstp6RETH35/RP6y121IpKKxPVXrlr6tOSJ4ozz/S92eaR+z/Ra1UsV2u8apToqPghdzlXwe79Honjz5c7FprQlLb3sqLm5lXUpxazH0bF9S+kvr93iXMuvq6YaTi0/f1k0fC9Trc0azifd7NO6Pj5+Pgj79Z6O+22ShuEe/C/iipwcx3g5q+Cp/JcoqoYdftPX7QtxSuoppEhauGVsCd3GfRkbxx4cFyi+Z6BP49rXtVr0RzVTCoqZRUI6LiF9JvXbtVnrEurxDhWPW7X37N46WhlendrlM9rIdQ0roJOS1FOivjXzVvpJ4ct72F3odY6crY2up73b+9yZJM2N/7LsL8CFv8AsxsF0c6Snjkt8y8c0yojFX9RcoierBSLlsXuKJ+IXajn/wAeJ0X3bx0Ix8K1POLTjnw7vz92OuTium9W9YyR4x1/H2a1PqOyU7N6ovNtib1fVManxUq1/wBrOlLQ16RVr7jO1cdlRM30Xz31wzH2jOm7FNQOem/WWhjc8VbJI5fduJ95O2vYVRtejrxeZ52/7uliSL2K5yuynsQurouD4fWy55t7oj+p+8Lo1XEMvKuKK/GWe602j6j11Mlpt1PJS0c/dSgo8ySz8OT3ImXJz4IiJjnnGTQtkuyBljqYL1qhsU1zjw+npEVHR0zvznLyc9PDHBq8UyuFTTNNaWsumYHR2S3w0quTD5Ey6R/6z1y5fUq8CaI63j0eh/xdBT0ePv8AGfPfzmZ8WnT6G0W9LqLdq30gAB826IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIq9NWWrVVmtlLvKuVcyNGOX2twpxpojTycrev/AH5P/YsYLIy3jpaWPJw/SZJ3virM++sfwiqTTtnpMdjbqZFRco5zEeqe1cqSoBCbTbrK/Fgx4Y2xVise6NgAHi0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf//Z"; + String baseImageBase64 = ""; + String slideImageBase64 = ""; + String captchaToken = ""; + String secretKey = ""; //加密key + + Size baseSize = Size.zero; //底部基类图片 + Size slideSize = Size.zero; //滑块图片 + + var sliderColor = Colors.white; //滑块的背景色 + var sliderIcon = Icons.arrow_forward; //滑块的图标 + var movedXBorderColor = Colors.white; //滑块拖动时,左边已滑的区域边框颜色 + double sliderStartX = 0; //滑块未拖前的X坐标 + double sliderXMoved = 0; + bool sliderMoveFinish = false; //滑块拖动结束 + bool checkResultAfterDrag = false; //拖动后的校验结果 + + //-------------动画------------ + int _checkMilliseconds = 0; //滑动时间 + bool _showTimeLine = false; //是否显示动画部件 + bool _checkSuccess = false; //校验是否成功 + AnimationController controller; + + //高度动画 + Animation offsetAnimation; + + //底部部件key + GlobalKey _containerKey = new GlobalKey(); + + //背景图key + GlobalKey _baseImageKey = new GlobalKey(); + + //滑块 + GlobalKey _slideImageKey = new GlobalKey(); + double _bottomSliderSize = 60.h; + + //------------动画------------ + + //校验通过 + void checkSuccess(String content) { + setState(() { + checkResultAfterDrag = true; + _checkSuccess = true; + _showTimeLine = true; + }); + _forwardAnimation(); + updateSliderColorIcon(); + + //刷新验证码 + Future.delayed(Duration(milliseconds: 1000)).then((v) { + _reverseAnimation().then((v) { + setState(() { + _showTimeLine = false; + }); + //回调 + if (widget.onSuccess != null) { + widget.onSuccess(content); + } + //关闭验证码 + print(content); + Navigator.pop(context); + }); + }); + } + + //校验失败 + void checkFail() { + setState(() { + _showTimeLine = true; + _checkSuccess = false; + checkResultAfterDrag = false; + }); + _forwardAnimation(); + updateSliderColorIcon(); + + //刷新验证码 + Future.delayed(Duration(milliseconds: 1000)).then((v) { + _reverseAnimation().then((v) { + setState(() { + _showTimeLine = false; + }); + loadCaptcha(); + //回调 + if (widget.onFail != null) { + widget.onFail(); + } + }); + }); + } + + //重设滑动颜色与图标 + void updateSliderColorIcon() { + var _sliderColor; //滑块的背景色 + var _sliderIcon; //滑块的图标 + var _movedXBorderColor; //滑块拖动时,左边已滑的区域边框颜色 + + //滑块的背景色 + if (sliderMoveFinish) { + //拖动结束 + _sliderColor = checkResultAfterDrag ? Colors.green : Colors.red; + _sliderIcon = checkResultAfterDrag ? Icons.check : Icons.close; + _movedXBorderColor = checkResultAfterDrag ? Colors.green : Colors.red; + } else { + //拖动未开始或正在拖动中 + _sliderColor = sliderXMoved > 0 ? Color(0xff447ab2) : Colors.white; + _sliderIcon = Icons.arrow_forward; + _movedXBorderColor = Color(0xff447ab2); + } + + sliderColor = _sliderColor; + sliderIcon = _sliderIcon; + movedXBorderColor = _movedXBorderColor; + setState(() {}); + } + + //加载验证码 + void loadCaptcha() async { + setState(() { + _showTimeLine = false; + sliderMoveFinish = false; + checkResultAfterDrag = false; + sliderColor = Colors.white; //滑块的背景色 + sliderIcon = Icons.arrow_forward; //滑块的图标 + movedXBorderColor = Colors.white; //滑块拖动时,左边已滑的区域边框颜色 + }); + ApiService apiIpService = ApiService(Dio(), context: context); + ClickWordCaptchaModel baseData = await apiIpService + .captchaGet({"captchaType": "blockPuzzle"}).catchError((onError) {}); + if (baseData == null) { + setState(() { + secretKey = ""; + }); + return; + } + + sliderXMoved = 0; + sliderStartX = 0; + captchaToken = ''; + checkResultAfterDrag = false; + + baseImageBase64 = baseData.imgStr; + secretKey = baseData.secretKey; + baseImageBase64 = baseImageBase64.replaceAll('\n', ''); + slideImageBase64 = baseData.jigsawImageBase64; + slideImageBase64 = slideImageBase64.replaceAll('\n', ''); + captchaToken = baseData.token; + + var baseR = await WidgetUtil.getImageWH( + image: Image.memory(Base64Decoder().convert(baseImageBase64))); + baseSize = baseR.size; + + var silderR = await WidgetUtil.getImageWH( + image: Image.memory(Base64Decoder().convert(slideImageBase64))); + slideSize = silderR.size; + + setState(() {}); + } + + //校验验证码 + void checkCaptcha(sliderXMoved, captchaToken, {BuildContext myContext}) { + setState(() { + sliderMoveFinish = true; + }); + //滑动结束,改变滑块的图标及颜色 +// updateSliderColorIcon(); + + //pointJson参数需要aes加密 + +// MediaQueryData mediaQuery = MediaQuery.of(myContext); + var pointMap = {"x": sliderXMoved, "y": 5}; + var pointStr = json.encode(pointMap); + var cryptedStr = pointStr; + + // secretKey 不为空 进行as加密 + if (!CaptchaUtil.isEmpty(secretKey)) { + cryptedStr = CaptchaUtil.aesEncode(key: secretKey, content: pointStr); + // var dcrypt = CaptchaUtil.aesDecode(key: secretKey, content: cryptedStr); + // json.decode(dcrypt); + } + + ApiService apiIpService = ApiService(Dio(), context: context); + apiIpService + .captchaCheck({ + "pointJson": cryptedStr, + "captchaType": "blockPuzzle", + "token": captchaToken + }) + .catchError((onError) {}) + .then((res) { + if (res) { + checkFail(); + return; + } + //如果不加密 将 token 和 坐标序列化 通过 --- 链接成字符串 + var captchaVerification = "$captchaToken---$pointStr"; + if (!CaptchaUtil.isEmpty(secretKey)) { + //如果加密 将 token 和 坐标序列化 通过 --- 链接成字符串 进行加密 加密密钥为 _clickWordCaptchaModel.secretKey + captchaVerification = CaptchaUtil.aesEncode( + key: secretKey, content: captchaVerification); + } + checkSuccess(captchaVerification); + }) + .catchError((error) { + loadCaptcha(); + print(error); + }); + } + + @override + void initState() { + super.initState(); + initAnimation(); + loadCaptcha(); + } + + @override + void dispose() { + controller.dispose(); + super.dispose(); + } + + // 初始化动画 + void initAnimation() { + controller = + AnimationController(duration: Duration(milliseconds: 500), vsync: this); + + offsetAnimation = Tween(begin: 0.5, end: 0) + .animate(CurvedAnimation(parent: controller, curve: Curves.ease)) + ..addListener(() { + this.setState(() {}); + }); + } + + // 反向执行动画 + _reverseAnimation() async { + await controller.reverse(); + } + + // 正向执行动画 + _forwardAnimation() async { + await controller.forward(); + } + + @override + void didUpdateWidget(BlockPuzzleCaptchaPage oldWidget) { + // TODO: implement didUpdateWidget + super.didUpdateWidget(oldWidget); + } + + @override + Widget build(BuildContext context) { + return MaxScaleTextWidget( + child: buildContent(context), + ); + } + + Widget buildContent(BuildContext context) { + var mediaQuery = MediaQuery.of(context); + var dialogWidth = 0.9 * mediaQuery.size.width; + if (dialogWidth < 330) { + dialogWidth = mediaQuery.size.width; + } + + return Scaffold( + backgroundColor: Colors.transparent, + body: Center( + child: Container( + key: _containerKey, + width: dialogWidth, + height: MediaQuery.of(context).size.height >= 750 ? 310.h:325.h, + color: Colors.white, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + _topContainer(), + _middleContainer(), + _bottomContainer(), + ], + ), + ), + ), + ); + } + + ///顶部,提示+关闭 + _topContainer() { + return Container( + height: 50.h, + padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0), + decoration: BoxDecoration( + border: Border(bottom: BorderSide(width: 1.w, color: Color(0xffe5e5e5))), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + '请完成安全验证', + style: TextStyle(fontSize: 18), + ), + IconButton( + icon: Icon(Icons.highlight_off), + iconSize: 30, + color: Colors.black38, + onPressed: () { + //退出 + Navigator.pop(context); + }), + ], + ), + ); + } + + _middleContainer() { + ////显示验证码 + return Container( + margin: EdgeInsets.symmetric(vertical: 10.h), + child: Stack( + children: [ + ///底图 310*155 + baseImageBase64.length > 0 + ? Image.memory( + Base64Decoder().convert(baseImageBase64), + fit: BoxFit.fitWidth, + key: _baseImageKey, + gaplessPlayback: true, + ) + : Container( + width: 310.w, + height: 155.h, + alignment: Alignment.center, + child: CircularProgressIndicator(), + ), + + ///滑块图 + (baseImageBase64.length > 0 && slideImageBase64.length > 0) + ? Container( + margin: EdgeInsets.fromLTRB(sliderXMoved, 0, 0, 0), + child: Image.memory( + Base64Decoder().convert(slideImageBase64), + fit: BoxFit.fitHeight, + key: _slideImageKey, + gaplessPlayback: true, + ), + ) + : Container(), + + //刷新按钮 + Positioned( + top: 0, + right: 0, + child: IconButton( + icon: Icon(Icons.refresh), + iconSize: 30, + color: Colors.black54, + onPressed: () { + //刷新 + loadCaptcha(); + }), + ), + Positioned( + bottom: 0, + left: -10.w, + right: -10.w, + child: Offstage( + offstage: !_showTimeLine, + child: FractionalTranslation( + translation: Offset(0, offsetAnimation.value), + child: Container( + margin: EdgeInsets.only(left: 10.w, right: 10.w), + height: 40.h, + color: _checkSuccess + ? Color(0x7F66BB6A) + : Color.fromRGBO(200, 100, 100, 0.4), + alignment: Alignment.centerLeft, + child: Text( + _checkSuccess + ? "${(_checkMilliseconds / (60.0 * 12)).toStringAsFixed(2)}s验证成功" + : "验证失败", + style: TextStyle(color: Colors.white), + ), + ), + ), + )), + Positioned( + bottom: -20.h, + left: 0, + right: 0, + child: Offstage( + offstage: !_showTimeLine, + child: Container( + margin: EdgeInsets.only(left: 10.w, right: 10.w), + height: 20.h, + color: Colors.white, + ), + )) + ], + ), + ); + } + + ///底部,滑动区域 + _bottomContainer() { + return baseSize.width > 0 + ? Container( + height: 70.h, + width: baseSize.width, +// color: Colors.cyanAccent, + child: Stack( + alignment: AlignmentDirectional.centerStart, + children: [ + Container( + height: _bottomSliderSize, + decoration: BoxDecoration( + border: Border.all( + width: 1.w, + color: Color(0xffe5e5e5), + ), + color: Color(0xfff8f9fb), + ), + ), + Container( + alignment: Alignment.center, + child: Text( + '向右拖动滑块填充拼图', + style: TextStyle(fontSize: 14.sp), + ), + ), + Container( + width: sliderXMoved, + height: _bottomSliderSize - 2.h, + decoration: BoxDecoration( + border: Border.all( + width: sliderXMoved > 0 ? 1 : 0, + color: movedXBorderColor, + ), + color: Color(0xfff3fef1), + ), + ), + GestureDetector( + onPanStart: (startDetails) { + ///开始 + _checkMilliseconds = + new DateTime.now().millisecondsSinceEpoch; + // print(startDetails.localPosition); + sliderStartX = startDetails.localPosition.dx; + }, + onPanUpdate: (updateDetails) { + ///更新 + // print(updateDetails.localPosition); + double _w1 = _baseImageKey.currentContext.size.width - + _slideImageKey.currentContext.size.width; + double offset = + updateDetails.localPosition.dx - sliderStartX; + if (offset < 0) { + offset = 0; + } + if (offset > _w1) { + offset = _w1; + } + // print("offset ------ $offset"); + setState(() { + sliderXMoved = offset; + }); + //滑动过程,改变滑块左边框颜色 + updateSliderColorIcon(); + }, + onPanEnd: (endDetails) { + //结束 + // print("endDetails"); + checkCaptcha(sliderXMoved, captchaToken); + int _nowTime = new DateTime.now().millisecondsSinceEpoch; + _checkMilliseconds = _nowTime - _checkMilliseconds; + }, + child: Container( + width: _bottomSliderSize, + height: _bottomSliderSize, + margin: EdgeInsets.only( + left: sliderXMoved > 0 ? sliderXMoved : 1), + decoration: BoxDecoration( + border: Border( + top: BorderSide( + width: 1.w, + color: Color(0xffe5e5e5), + ), + right: BorderSide( + width: 1.w, + color: Color(0xffe5e5e5), + ), + bottom: BorderSide( + width: 1.w, + color: Color(0xffe5e5e5), + ), + ), + color: sliderColor, + ), + child: IconButton( + icon: Icon(sliderIcon), + iconSize: 30, + color: Colors.black54, + onPressed: () {}, + ), + ), + ) + ], + )) + : Container(); + } +} + +class MaxScaleTextWidget extends StatelessWidget { + final double max; + final Widget child; + + MaxScaleTextWidget({Key key, this.max = 1.0, this.child}) : super(key: key); + + @override + Widget build(BuildContext context) { + var data = MediaQuery.of(context); + var textScaleFactor = min(max, data.textScaleFactor); + return MediaQuery( + data: data.copyWith(textScaleFactor: textScaleFactor), child: child); + } +} diff --git a/lib/login/captcha/click_word_captcha.dart b/lib/login/captcha/click_word_captcha.dart new file mode 100644 index 00000000..1afba266 --- /dev/null +++ b/lib/login/captcha/click_word_captcha.dart @@ -0,0 +1,367 @@ +import 'dart:convert'; + +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +import '../../retrofit/retrofit_api.dart'; +import '../../utils/captcha_util.dart'; +import '../../utils/widget_util.dart'; + +typedef VoidSuccessCallback = dynamic Function(String v); + +class ClickWordCaptcha extends StatefulWidget { + final VoidSuccessCallback onSuccess; //文字点击后验证成功回调 + final VoidCallback onFail; //文字点击完成后验证失败回调 + + const ClickWordCaptcha({Key key, this.onSuccess, this.onFail}) + : super(key: key); + + @override + _ClickWordCaptchaState createState() => _ClickWordCaptchaState(); +} + +class _ClickWordCaptchaState extends State { + ClickWordCaptchaState _clickWordCaptchaState = ClickWordCaptchaState.none; + List _tapOffsetList = []; + ClickWordCaptchaModel _clickWordCaptchaModel = ClickWordCaptchaModel(); + + Color titleColor = Colors.black; + Color borderColor = Color(0xffdddddd); + String bottomTitle = ""; + Size baseSize = Size(310.0, 155.0); + + //改变底部样式及字段 + _changeResultState() { + switch (_clickWordCaptchaState) { + case ClickWordCaptchaState.normal: + titleColor = Colors.black; + borderColor = Color(0xffdddddd); + break; + case ClickWordCaptchaState.success: + _tapOffsetList = []; + titleColor = Colors.green; + borderColor = Colors.green; + bottomTitle = "验证成功"; + break; + case ClickWordCaptchaState.fail: + _tapOffsetList = []; + titleColor = Colors.red; + borderColor = Colors.red; + bottomTitle = "验证失败"; + break; + default: + titleColor = Colors.black; + borderColor = Color(0xffdddddd); + bottomTitle = "数据加载中……"; + break; + } + setState(() {}); + } + + @override + void initState() { + super.initState(); + _loadCaptcha(); + } + + //加载验证码 + _loadCaptcha() async { + _tapOffsetList = []; + _clickWordCaptchaState = ClickWordCaptchaState.none; + _changeResultState(); + ApiService apiIpService = ApiService(Dio(), context: context); + ClickWordCaptchaModel baseData = await apiIpService.captchaGet({"captchaType": "clickWord"}).catchError((onError) {}); + if (baseData == null) { + _clickWordCaptchaModel.secretKey = ""; + bottomTitle = "加载失败,请刷新"; + _clickWordCaptchaState = ClickWordCaptchaState.normal; + _changeResultState(); + return; + } + else { + _clickWordCaptchaModel = baseData; + var baseR = await WidgetUtil.getImageWH( + image: Image.memory( + Base64Decoder().convert(_clickWordCaptchaModel.imgStr))); + baseSize = baseR.size; + + bottomTitle = "请依次点击【${_clickWordCaptchaModel.wordStr}】"; + } + + _clickWordCaptchaState = ClickWordCaptchaState.normal; + _changeResultState(); + } + + //校验验证码 + _checkCaptcha() async { + List> mousePos = []; + _tapOffsetList.map((size) { + mousePos + .add({"x": size.dx.roundToDouble(), "y": size.dy.roundToDouble()}); + }).toList(); + var pointStr = json.encode(mousePos); + + var cryptedStr = pointStr; + + // secretKey 不为空 进行as加密 + if (!CaptchaUtil.isEmpty(_clickWordCaptchaModel.secretKey)) { + cryptedStr = CaptchaUtil.aesEncode( + key: _clickWordCaptchaModel.secretKey, content: pointStr); + // var dcrypt = CaptchaUtil.aesDecode( + // key: _clickWordCaptchaModel.secretKey, content: cryptedStr); + } + +// Map _map = json.decode(dcrypt); + ApiService apiIpService = ApiService(Dio(), context: context); + bool baseData = await apiIpService.captchaCheck({ + "pointJson": cryptedStr, + "captchaType": "clickWord", + "token": _clickWordCaptchaModel.token + }).catchError((onError) {}); + if (baseData) { + _checkFail(); + return; + } + //如果不加密 将 token 和 坐标序列化 通过 --- 链接成字符串 + var captchaVerification = "${_clickWordCaptchaModel.token}---$pointStr"; + if (!CaptchaUtil.isEmpty(_clickWordCaptchaModel.secretKey)) { + //如果加密 将 token 和 坐标序列化 通过 --- 链接成字符串 进行加密 加密密钥为 _clickWordCaptchaModel.secretKey + captchaVerification = CaptchaUtil.aesEncode( + key: _clickWordCaptchaModel.secretKey, + content: captchaVerification); + } + _checkSuccess(captchaVerification); + } + + //校验失败 + _checkFail() async { + _clickWordCaptchaState = ClickWordCaptchaState.fail; + _changeResultState(); + + await Future.delayed(Duration(milliseconds: 1000)); + _loadCaptcha(); + //回调 + if (widget.onFail != null) { + widget.onFail(); + } + } + + //校验成功 + _checkSuccess(String pointJson) async { + _clickWordCaptchaState = ClickWordCaptchaState.success; + _changeResultState(); + + await Future.delayed(Duration(milliseconds: 1000)); + + var cryptedStr = CaptchaUtil.aesEncode(key: 'BGxdEUOZkXka4HSj', content: pointJson); + + print(cryptedStr); + //回调 pointJson 是经过es加密之后的信息 + if (widget.onSuccess != null) { + widget.onSuccess(cryptedStr); + } + //关闭 + Navigator.pop(context); + } + + @override + Widget build(BuildContext context) { + var data = MediaQuery.of(context); + var dialogWidth = 0.9 * data.size.width; + var isRatioCross = false; + if (dialogWidth < 320.0) { + dialogWidth = data.size.width; + isRatioCross = true; + } + return Scaffold( + backgroundColor: Colors.transparent, + body: Center( + child: Container( + width: dialogWidth, + height: 320.h, + color: Colors.white, + child: Column( + children: [ + _topConttainer(), + _captchaContainer(), + _bottomContainer() + ], + ), + ), + ), + ); + } + + //图片验证码 + _captchaContainer() { + List _widgetList = []; + if (!CaptchaUtil.isEmpty(_clickWordCaptchaModel.imgStr)) { + _widgetList.add(Image( + width: baseSize.width, + height: baseSize.height, + gaplessPlayback: true, + image: MemoryImage( + Base64Decoder().convert(_clickWordCaptchaModel.imgStr)))); + } + + double _widgetW = 20; + for (int i = 0; i < _tapOffsetList.length; i++) { + Offset offset = _tapOffsetList[i]; + _widgetList.add(Positioned( + left: offset.dx - _widgetW * 0.5, + top: offset.dy - _widgetW * 0.5, + child: Container( + alignment: Alignment.center, + width: _widgetW, + height: _widgetW, + decoration: BoxDecoration( + color: Color(0xCC43A047), + borderRadius: BorderRadius.all(Radius.circular(_widgetW))), + child: Text( + "${i + 1}", + style: TextStyle(color: Colors.white, fontSize: 15), + ), + ))); + } + _widgetList.add(//刷新按钮 + Positioned( + top: 0, + right: 0, + child: IconButton( + icon: Icon(Icons.refresh), + iconSize: 30, + color: Colors.deepOrangeAccent, + onPressed: () { + //刷新 + _loadCaptcha(); + }), + )); + + return GestureDetector( + onTapDown: (TapDownDetails details) { + debugPrint( + "onTapDown globalPosition全局坐标系位置: ${details.globalPosition} localPosition组件坐标系位置: ${details.localPosition} "); + if (!CaptchaUtil.isListEmpty(_clickWordCaptchaModel.wordList) && + _tapOffsetList.length < _clickWordCaptchaModel.wordList.length) { + _tapOffsetList.add( + Offset(details.localPosition.dx, details.localPosition.dy)); + } + setState(() {}); + if (!CaptchaUtil.isListEmpty(_clickWordCaptchaModel.wordList) && + _tapOffsetList.length == _clickWordCaptchaModel.wordList.length) { + _checkCaptcha(); + } + }, + child: Container( + width: baseSize.width, + height: baseSize.height, + child: Stack( + children: _widgetList, + ), + )); + } + + //底部提示部件 + _bottomContainer() { + return Container( + height: 50.h, + margin: EdgeInsets.only(top: 10), + alignment: Alignment.center, + width: baseSize.width, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(4)), + border: Border.all(color: borderColor)), + child: + Text(bottomTitle, style: TextStyle(fontSize: 18, color: titleColor)), + ); + } + + //顶部,提示+关闭 + _topConttainer() { + return Container( + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + margin: EdgeInsets.only(bottom: 20, top: 5), + decoration: BoxDecoration( + border: Border(bottom: BorderSide(width: 1, color: Color(0xffe5e5e5))), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + '请完成安全验证', + style: TextStyle(fontSize: 18), + ), + IconButton( + icon: Icon(Icons.highlight_off), + iconSize: 35, + color: Colors.black54, + onPressed: () { + //退出 + Navigator.pop(context); + }), + ], + ), + ); + } +} + +//校验状态 +enum ClickWordCaptchaState { + normal, //默认 可自定义描述 + success, //成功 + fail, //失败 + none, //无状态 用于加载使用 +} + +//请求数据模型 +class ClickWordCaptchaModel { + String imgStr; //图表url 目前用base64 data + String jigsawImageBase64; //图表url 目前用base64 data + String token; // 获取的token 用于校验 + List wordList; //显示需要点选的字 + String wordStr; //显示需要点选的字转换为字符串 + String secretKey; //加密key + + ClickWordCaptchaModel( + {this.imgStr = "", + this.jigsawImageBase64 = "", + this.token = "", + this.secretKey = "", + this.wordList = const [], + this.wordStr = ""}); + + //解析数据转换模型 + static ClickWordCaptchaModel fromMap(Map map) { + ClickWordCaptchaModel captchaModel = ClickWordCaptchaModel(); + captchaModel.imgStr = map["originalImageBase64"] ?? ""; + captchaModel.jigsawImageBase64 = map["jigsawImageBase64"] ?? ""; + captchaModel.token = map["token"] ?? ""; + captchaModel.secretKey = map["secretKey"] ?? ""; + captchaModel.wordList = map["wordList"] ?? []; + + if (!CaptchaUtil.isListEmpty(captchaModel.wordList)) { + captchaModel.wordStr = captchaModel.wordList.join(","); + } + + return captchaModel; + } + + //将模型转换 + Map toJson() { + var map = new Map(); + map['imgStr'] = imgStr; + map['jigsawImageBase64'] = jigsawImageBase64; + map['token'] = token; + map['secretKey'] = token; + map['wordList'] = wordList; + map['wordStr'] = wordStr; + return map; + } + + @override + String toString() { + // TODO: implement toString + return JsonEncoder.withIndent(' ').convert(toJson()); + } +} diff --git a/lib/login/login_page.dart b/lib/login/login_page.dart index 67bcc0ee..086cd6d8 100644 --- a/lib/login/login_page.dart +++ b/lib/login/login_page.dart @@ -75,7 +75,8 @@ class _MyLoginPageState extends State with TickerProviderStateMixin { sharedPreferences.getString("token") != null && sharedPreferences.getString("token") != "") { Navigator.of(context).popAndPushNamed('/router/main_page'); - } else {initController(); + } else { + initController(); client = ApiService(Dio(), context: context); isShowLogin = true; @@ -180,15 +181,16 @@ class _MyLoginPageState extends State with TickerProviderStateMixin { _controllerInviteCode.addListener(() { print(_controllerInviteCode.text); - if (_controllerInviteCode.text != null && _controllerInviteCode.text != "") { - if (_controllerInviteCode.text.length == 6 ){ + if (_controllerInviteCode.text != null && + _controllerInviteCode.text != "") { + if (_controllerInviteCode.text.length == 6) { statusInviteTextColor = Color(0xFF353535); - statusInviteLineColor = Color(0xFF32A060); - statusInviteVisible = false; + statusInviteLineColor = Color(0xFF32A060); + statusInviteVisible = false; } else { - statusInviteTextColor = Color(0xFFF72626); - statusInviteLineColor = Color(0xFFF72626); - statusInviteVisible = true; + statusInviteTextColor = Color(0xFFF72626); + statusInviteLineColor = Color(0xFFF72626); + statusInviteVisible = true; } } }); @@ -206,7 +208,6 @@ class _MyLoginPageState extends State with TickerProviderStateMixin { Color statusInviteTextColor = Color(0xFF353535); Color statusInviteLineColor = Color(0xFF32A060); - _sendCode() async { SharedPreferences sharedPreferences = await SharedPreferences.getInstance(); if (!sharedPreferences.containsKey("isShowPrivacyPolicy") || @@ -228,7 +229,8 @@ class _MyLoginPageState extends State with TickerProviderStateMixin { } if (_sendCodeStatus == 0) { client - .sendVerify(areaCode,mobile) + .sendVerify( + {"areaCode": areaCode, "mobile": mobile, "verification": ""}) .then((value) => { if (value.isSuccess) {_sendCodeStatus = 1, countdown()} @@ -242,8 +244,8 @@ class _MyLoginPageState extends State with TickerProviderStateMixin { } }) .catchError((error) { - SmartDialog.showToast("$error", alignment: Alignment.center); - }); + SmartDialog.showToast("$error", alignment: Alignment.center); + }); } } @@ -324,28 +326,35 @@ class _MyLoginPageState extends State with TickerProviderStateMixin { var param = { "capcha": code, "mobile": mobile, - "invite":invite, + "invite": invite, }; - EasyLoading.show(status: S.of(context).zhengzaijiazai); - BaseData value = await client.memberLogin(param).catchError((error) { + EasyLoading.show( + status: S.of(context).zhengzaijiazai, + maskType: EasyLoadingMaskType.black); + BaseData value = + await client.memberLogin(param).catchError((error) { print(error.message); - SmartDialog.showToast(AppUtils.dioErrorTypeToString(error.type), alignment: Alignment.center); + SmartDialog.showToast(AppUtils.dioErrorTypeToString(error.type), + alignment: Alignment.center); }); // EasyLoading.show(status: S.of(context).zhengzaijiazai); - Future.delayed(Duration(seconds:2), () { - if (value !=null && value.isSuccess) { + Future.delayed(Duration(seconds: 2), () { + if (value != null && value.isSuccess) { saveUserJson(value.data.authInfo.toJson()); eventBus.fire(EventType(3)); Navigator.of(context).pushNamedAndRemoveUntil( - '/router/main_page', - (route) => false,arguments:{"invite":invite,"interviewCouponList":value.data.interviewCouponList, - "firstLoginCouponList":value.data.firstLoginCouponList}); + '/router/main_page', (route) => false, + arguments: { + "invite": invite, + "interviewCouponList": value.data.interviewCouponList, + "firstLoginCouponList": value.data.firstLoginCouponList + }); EasyLoading.dismiss(); - } else { - if(value?.msg !=null) - SmartDialog.showToast("${value?.msg ??""}", alignment: Alignment.center); + if (value?.msg != null) + SmartDialog.showToast("${value?.msg ?? ""}", + alignment: Alignment.center); } }); } @@ -515,7 +524,7 @@ class _MyLoginPageState extends State with TickerProviderStateMixin { height: MediaQuery.of(context).size.height * 0.78, margin: EdgeInsets.only(top: 56.h), alignment: Alignment.topCenter, - child:Image.asset( + child: Image.asset( "assets/image/icon_login_logo.webp", width: 91.w, height: 91.h, @@ -708,7 +717,7 @@ class _MyLoginPageState extends State with TickerProviderStateMixin { ), ), Container( - height:30.h, + height: 30.h, width: MediaQuery.of(context).size.width - 80.h, // margin: EdgeInsets.only(top: 12.h), child: TextField( @@ -754,7 +763,7 @@ class _MyLoginPageState extends State with TickerProviderStateMixin { color: statusPhoneLineColor, ), SizedBox( - height:30.h, + height: 30.h, child: Visibility( visible: statusPhoneVisible, child: Text( @@ -775,7 +784,7 @@ class _MyLoginPageState extends State with TickerProviderStateMixin { ), ), Container( - height:30.h, + height: 30.h, width: MediaQuery.of(context).size.width - 80.h, child: Row( mainAxisAlignment: MainAxisAlignment.end, @@ -878,7 +887,7 @@ class _MyLoginPageState extends State with TickerProviderStateMixin { ), ), SizedBox( - height:25.h, + height: 25.h, // child: Visibility( // visible: statusPhoneVisible, // child: Text( @@ -891,89 +900,95 @@ class _MyLoginPageState extends State with TickerProviderStateMixin { // ), ), GestureDetector( - onTap: (){ + onTap: () { setState(() { invitationCode = false; }); }, - child: - invitationCode ? - Container(child: - Column(children: [ - Text( - S.of(context).woyouyaoqingma, - style: TextStyle( - fontSize: 12.sp, - fontWeight: FontWeight.bold, - color: Colors.black, - ), - ), - Container( - width: 56.w, - height: 0.5, - color: Colors.black, - ), - ],),):Container(child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - S.of(context).input_invite_code_hide, - style: TextStyle( - fontSize: 16.sp, - fontWeight: FontWeight.bold, - color: Colors.black, - ), + child: invitationCode + ? Container( + child: Column( + children: [ + Text( + S.of(context).woyouyaoqingma, + style: TextStyle( + fontSize: 12.sp, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + Container( + width: 56.w, + height: 0.5, + color: Colors.black, + ), + ], ), - Container( - height:25.h, - width: MediaQuery.of(context).size.width - 80.h, - child: TextField( - style: TextStyle( - height: 1.h, - fontSize: 16.sp, - color: statusInviteTextColor, + ) + : Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + S.of(context).input_invite_code_hide, + style: TextStyle( + fontSize: 16.sp, + fontWeight: FontWeight.bold, + color: Colors.black, + ), ), - onChanged: (value){ - setState(() { - }); - }, - controller: _controllerInviteCode, - keyboardType: TextInputType.text, - decoration: InputDecoration( - errorBorder: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, - hintText: "", - // contentPadding: EdgeInsets.only(top: 12, bottom: 12, left: 12), - hintStyle: TextStyle( - fontSize: 10.sp, - color: Color(0xFFA29E9E), + Container( + height: 25.h, + width: MediaQuery.of(context).size.width - 80.h, + child: TextField( + style: TextStyle( + height: 1.h, + fontSize: 16.sp, + color: statusInviteTextColor, + ), + onChanged: (value) { + setState(() {}); + }, + controller: _controllerInviteCode, + keyboardType: TextInputType.text, + decoration: InputDecoration( + errorBorder: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + hintText: "", + // contentPadding: EdgeInsets.only(top: 12, bottom: 12, left: 12), + hintStyle: TextStyle( + fontSize: 10.sp, + color: Color(0xFFA29E9E), + ), + ), + textInputAction: TextInputAction.next, + inputFormatters: [ + LengthLimitingTextInputFormatter(6) + ], + cursorColor: Colors.grey, + maxLines: 1, ), ), - textInputAction: TextInputAction.next, - inputFormatters: [LengthLimitingTextInputFormatter(6)], - cursorColor: Colors.grey, - maxLines: 1, - ), - ), - Container( - height: 1.h, - width: MediaQuery.of(context).size.width - 80.h, - color: statusInviteLineColor, - margin: EdgeInsets.only(bottom: 10.h), - ), - Visibility( - visible: statusInviteVisible, - child: Text( - S.of(context).invite_code_error, - style: TextStyle( - color: Color(0xFFF72626), - fontSize: 12.sp, + Container( + height: 1.h, + width: MediaQuery.of(context).size.width - 80.h, + color: statusInviteLineColor, + margin: EdgeInsets.only(bottom: 10.h), ), - ), + Visibility( + visible: statusInviteVisible, + child: Text( + S.of(context).invite_code_error, + style: TextStyle( + color: Color(0xFFF72626), + fontSize: 12.sp, + ), + ), + ), + ], ), - ], - ),), + ), ), Expanded( flex: 1, diff --git a/lib/login/new_login_page.dart b/lib/login/new_login_page.dart index c4d5f9b1..47f2d32b 100644 --- a/lib/login/new_login_page.dart +++ b/lib/login/new_login_page.dart @@ -26,6 +26,7 @@ import 'package:sharesdk_plugin/sharesdk_interface.dart'; import '../main.dart'; import '../retrofit/data/channels_list.dart'; +import 'captcha/block_puzzle_captcha.dart'; class NewLoginPage extends StatefulWidget { final Map arguments; @@ -56,22 +57,15 @@ class _NewLoginPage extends State { String area = "+86"; String channelName; ChannelsList channelsList; + String mobile; @override void initState() { super.initState(); isLogin(); - queryChannels(); } queryChannels() async{ - SharedPreferences sharedPreferences = await SharedPreferences.getInstance(); - if (!sharedPreferences.containsKey("isShowPrivacyPolicy") || - !sharedPreferences.getBool("isShowPrivacyPolicy")) { - showAlertDialog(); - return; - } - apiService = ApiService(Dio(), context: context); BaseData baseData = await apiService.appChannels().catchError((error) { print(error.message); SmartDialog.showToast(AppUtils.dioErrorTypeToString(error.type), @@ -80,7 +74,6 @@ class _NewLoginPage extends State { if (baseData != null && baseData.isSuccess) { channelsList = baseData.data; setState((){}); - EasyLoading.dismiss(); } else { if (baseData?.msg != null) SmartDialog.showToast(baseData.msg, alignment: Alignment.center); @@ -136,37 +129,22 @@ class _NewLoginPage extends State { showAlertDialog(); return; } - if (!checkStatus) { - SmartDialog.showToast(S.of(context).gouxuanxieyi, - alignment: Alignment.center); - return; - } - var mobile = _controllerPhone.text; + mobile = _controllerPhone.text; if (mobile == "") { mobileStatus = 2; mobileErrorText = S.of(context).qingshurushoujihao; + SmartDialog.showToast(S.of(context).qingshurushoujihao, + alignment: Alignment.center); setState(() {}); return; } + if (!checkStatus) { + SmartDialog.showToast(S.of(context).gouxuanxieyi, + alignment: Alignment.center); + return; + } if (_sendCodeStatus == 0) { - apiService - .sendVerify(area, mobile) - .then((value) => { - if (value.isSuccess) - {_sendCodeStatus = 1, countdown()} - else - { - btnText = S.of(context).send_code, - _sendCodeStatus = 0, - SmartDialog.showToast("${value.msg}", - alignment: Alignment.center), - refresh() - } - }) - .catchError((error) { - SmartDialog.showToast(AppUtils.dioErrorTypeToString(error.type), - alignment: Alignment.center); - }); + loadingBlockPuzzle(context); } } @@ -241,7 +219,7 @@ class _NewLoginPage extends State { "areaCode": area, "regChannel":channelName ?? "" }; - EasyLoading.show(status: S.of(context).zhengzaijiazai); + EasyLoading.show(status: S.of(context).zhengzaijiazai,maskType: EasyLoadingMaskType.black); BaseData value = await apiService.memberLogin(param).catchError((error) { print(error.message); SmartDialog.showToast(AppUtils.dioErrorTypeToString(error.type), @@ -262,11 +240,11 @@ class _NewLoginPage extends State { "interviewCouponList": userInfo.interviewCouponList, "firstLoginCouponList": userInfo.firstLoginCouponList }); - EasyLoading.dismiss(); } else { if (value.msg != null) SmartDialog.showToast(value?.msg, alignment: Alignment.center); } + EasyLoading.dismiss(); } saveUserJson(userJson) { @@ -295,11 +273,10 @@ class _NewLoginPage extends State { sharedPreferences.getString("mobile") == "13800138000"; Navigator.of(context).popAndPushNamed('/router/main_page'); } else { - initController(); - apiService = ApiService(Dio(), context: context); + initController(); isShowLogin = true; - setState(() {}); + queryChannels(); } } @@ -974,4 +951,41 @@ class _NewLoginPage extends State { r'^((13[0-9])|(14[0-9])|(15[0-9])|(16[0-9])|(17[0-9])|(18[0-9])|(19[0-9]))\d{8}$'); return exp.hasMatch(mobile); } + + //滑动拼图 + loadingBlockPuzzle(BuildContext context, + {barrierDismissible = true}) { + showDialog( + context: context, + barrierDismissible: barrierDismissible, + builder: (BuildContext context) { + return BlockPuzzleCaptchaPage( + onSuccess: (v) { + sendSms(v); + }, + onFail: () { + print("onFail"); + }, + ); + }, + ); + } + + sendSms(v) async{ + BaseData baseData = await apiService.sendVerify({"areaCode":area, "mobile": mobile, "verification": v}).catchError((onError) { + SmartDialog.showToast(AppUtils.dioErrorTypeToString(onError.type), + alignment: Alignment.center);}); + if (baseData != null && baseData.isSuccess) { + _sendCodeStatus = 1; + countdown(); + SmartDialog.showToast(baseData.data, + alignment: Alignment.center); + }else{ + btnText = S.of(context).send_code; + _sendCodeStatus = 0; + SmartDialog.showToast("${baseData.msg}", + alignment: Alignment.center); + refresh(); + } + } } diff --git a/lib/main.dart b/lib/main.dart index d12e5c28..f8bce895 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -73,6 +73,7 @@ import 'package:huixiang/settlement/settlement.dart'; import 'package:huixiang/store/store_view/product_meals_sku.dart'; import 'package:huixiang/test_page.dart'; import 'package:huixiang/union/location_map_page.dart'; +import 'package:huixiang/union/union_select_city.dart'; import 'package:huixiang/utils/ImgCachePath.dart'; import 'package:huixiang/vip/user_vip_service_page.dart'; @@ -133,6 +134,7 @@ import 'mine/manage_address_page.dart'; import 'mine/mine_greenery.dart'; import 'mine/mine_shop_details.dart'; import 'mine/mine_shop_page.dart'; +import 'mine/mine_shop_recharge.dart'; import 'mine/mine_view/community_follow.dart'; import 'mine/mine_vip/binding_assistant_card.dart'; import 'mine/mine_vip/legal_right_details.dart'; @@ -426,6 +428,8 @@ Map routers = { MineGreenery(), '/router/mine_shop_page': (context, {arguments}) => MineShopPage(), + '/router/mine_shop_recharge': (context, {arguments}) => + MineShopRecharge(arguments: arguments,), '/router/mine_shop_details': (context, {arguments}) => MineShopDetails(arguments:arguments,), '/router/coupon_page': (context, {arguments}) => @@ -462,6 +466,8 @@ Map routers = { BindingPhonePage(arguments:arguments), '/router/trading_card_page': (context, {arguments}) => TradingCardPage(), + '/router/union_select_city': (context, {arguments}) => + UnionSelectCity(arguments:arguments), '/router/business_login_page': (context, {arguments}) => BusinessLoginPage(arguments: arguments), '/router/business_page': (context, {arguments}) => diff --git a/lib/mine/mine_page.dart b/lib/mine/mine_page.dart index 98a91778..6bbc3dc7 100644 --- a/lib/mine/mine_page.dart +++ b/lib/mine/mine_page.dart @@ -26,9 +26,11 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'package:dio/dio.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import '../retrofit/data/banner.dart'; import '../retrofit/data/coupon.dart'; import '../retrofit/data/page.dart'; import '../utils/flutter_utils.dart'; +import '../view_widget/custom_image.dart'; import 'mine_view/mine_item.dart'; import 'mine_view/mine_view.dart'; @@ -49,6 +51,7 @@ class MinePageState extends State with AutomaticKeepAliveClientMixin { final RefreshController _refreshController = RefreshController(); int totalMsg = 0; String couponNum; + List activityBannerData = []; _toUserInfo() async { SharedPreferences shared = await SharedPreferences.getInstance(); @@ -78,6 +81,7 @@ class MinePageState extends State with AutomaticKeepAliveClientMixin { querySocialInfo(); queryMsgStats(); queryCoupon(); + queryActivityBanner(); // queryCard(); eventBus.on().listen((event) { @@ -136,6 +140,23 @@ class MinePageState extends State with AutomaticKeepAliveClientMixin { // EasyLoading.dismiss(); } + ///宣传banner + queryActivityBanner() async { + SharedPreferences value = await SharedPreferences.getInstance(); + apiService = ApiService( + Dio(), + context: context, + token: value.getString("token"), + showLoading: false, + ); + BaseData> baseData = await apiService.queryBanner({ + "model": {"type": "HOME_STORE_PAGE"}, + }).catchError((onError) {}); + if (baseData != null && baseData.isSuccess) { + activityBannerData = baseData.data.records; + } + } + queryCoupon() async { SharedPreferences value = await SharedPreferences.getInstance(); apiService = ApiService( @@ -166,6 +187,7 @@ class MinePageState extends State with AutomaticKeepAliveClientMixin { queryCoupon(); querySocialInfo(); queryMsgStats(); + queryActivityBanner(); } ///个人社交信息(粉丝/关注数量/成就数量) @@ -427,10 +449,11 @@ class MinePageState extends State with AutomaticKeepAliveClientMixin { ///推广图 Widget spreadImage() { return Container( - margin: EdgeInsets.only(bottom: 30.h,), width: double.infinity, + margin: EdgeInsets.only(bottom:24.h), height: 85.h, - child: Swiper( + child: activityBannerData != null && activityBannerData.isNotEmpty + ? Swiper( pagination: SwiperPagination( alignment: Alignment.bottomCenter, margin: EdgeInsets.only(top: 5.h), @@ -442,37 +465,82 @@ class MinePageState extends State with AutomaticKeepAliveClientMixin { color: Colors.white.withAlpha(76), ), ), - autoplay:true, + autoplay: true, duration: 1000, autoplayDelay: 2000, itemBuilder: (context, position) { - return GestureDetector( - onTap: (){ - if(position == 0){ - Navigator.of(context).pushNamed('/router/invite_friends'); - }else if(position == 1){ - Navigator.of(context).pushNamed('/router/trading_card_page'); - } + return InkWell( + onTap: () { + spreadBannerClick(activityBannerData[position]); }, - child:Container( - margin: EdgeInsets.symmetric(horizontal:14.w), - child: ClipRRect( - child:Image.asset( - spreadItem[position], - width:double.infinity, - fit: BoxFit.fill, - height:double.infinity, - ), - borderRadius: BorderRadius.circular(6.w), + child: Container( + margin: EdgeInsets.symmetric(horizontal: 14.w), + child: MImage( + activityBannerData[position].imgUrl, + fit: BoxFit.cover, + radius: BorderRadius.circular(6), + errorSrc: "assets/image/default_2_1.webp", + fadeSrc: "assets/image/default_2_1.webp", ), ), ); }, - itemCount:2, + itemCount: activityBannerData.length, + ) + : Image.asset( + "assets/image/default_2_1.webp", + fit: BoxFit.cover, ), ); } + /// contentType 跳转类型(0:不跳转,1:积分商品,2:活动,3:文章,4:页面跳转,5:课程,7:门店跳转) + spreadBannerClick(BannerData activityBannerData) async { + switch (activityBannerData.contentType) { + case 1: + Navigator.of(context).pushNamed('/router/integral_store_page', + arguments: {"goodsId": activityBannerData.content}); + break; + case 2: + Navigator.of(context).pushNamed('/router/web_page', arguments: { + "activityId": activityBannerData.content, + }); + break; + case 3: + Navigator.of(context).pushNamed('/router/web_page', arguments: { + "articleId": activityBannerData.content, + }); + break; + case 4: + String router = activityBannerData.content; + // String router = "/router/store_order?{\"id\":\"1512378184161558528\",\"tenant\":\"1188\",\"storeName\":\"农场煮意\"}"; + if (router.contains("?")) { + String params = router.substring(router.indexOf("?") + 1); + Map map = jsonDecode(params); + Navigator.of(context).pushNamed( + router.substring(0, router.indexOf("?")), + arguments: map); + } else { + Navigator.of(context).pushNamed(router); + } + break; + case 5: + Navigator.of(context).pushNamed('/router/class_details', arguments: { + "id": activityBannerData.content, + }); + break; + case 7: + String params = activityBannerData.content + .substring(activityBannerData.content.indexOf("?") + 1); + Map map = jsonDecode(params); + Navigator.of(context).pushNamed( + activityBannerData.content + .substring(0, activityBannerData.content.indexOf("?")), + arguments: map); + break; + } + } + final List spreadItem = [ "assets/image/welfare_spread.webp", "assets/image/welfare_yz.webp", diff --git a/lib/mine/mine_shop_details.dart b/lib/mine/mine_shop_details.dart index 244ca00c..ffbfbf16 100644 --- a/lib/mine/mine_shop_details.dart +++ b/lib/mine/mine_shop_details.dart @@ -511,6 +511,12 @@ class _MineShopDetails extends State { ), ), ), + if(((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)) != "0.0米") Text( (store.distance ?? 0) > 1000 ? S.of(context).gongli( diff --git a/lib/mine/mine_shop_page.dart b/lib/mine/mine_shop_page.dart index 2c0e5953..60fcc8e2 100644 --- a/lib/mine/mine_shop_page.dart +++ b/lib/mine/mine_shop_page.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:huixiang/generated/l10n.dart'; import 'package:huixiang/retrofit/data/base_data.dart'; import 'package:huixiang/retrofit/data/page.dart'; @@ -27,88 +28,195 @@ class MineShopPage extends StatefulWidget { } } -class _MineShopPage extends State { +class _MineShopPage extends State with WidgetsBindingObserver{ List coupons = []; ApiService apiService; int current = 1; RefreshController refreshController ; + final TextEditingController editingController = TextEditingController(); + int optionIndex = 0; + bool isKeyBoardShow = false; + List hotSearch = []; + List historySearch = []; + FocusNode _focusNode = FocusNode(); + bool hasFocus = true; + int priceOrder = 0; @override void initState() { super.initState(); refreshController = RefreshController(); - SharedPreferences.getInstance().then((value) { apiService = ApiService(Dio(), context: context, token: value.getString("token")); queryVipCard(); }); + _focusNode.addListener(() { + setState(() { + hasFocus = _focusNode.hasFocus; + }); + }); } - _onRefresh() { - current = 1; - queryVipCard(); + @override + void didChangeMetrics() { + super.didChangeMetrics(); + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() { + print("object: ${MediaQuery.of(context).viewInsets.bottom}"); + if (MediaQuery.of(context).viewInsets.bottom == 0) { + if (isKeyBoardShow) { + isKeyBoardShow = false; + //关闭键盘 软键盘关闭了, 清除输入控件的焦点, 否则重新进入页面会导致软键盘再弹出问题 + FocusScope.of(context).requestFocus(FocusNode()); + } + } else { + isKeyBoardShow = true; + } + }); + }); + } + + ///离开页面记着销毁和清除 + @override + void dispose() { + _focusNode.unfocus(); + refreshController.dispose(); + super.dispose(); } - queryVipCard() async { - BaseData> baseData = - await apiService.vipList({}).catchError((error) { - refreshController.refreshFailed(); - }); - if (baseData != null && baseData.isSuccess) { - coupons.clear(); - coupons.addAll(baseData.data); - setState(() { - refreshController.refreshCompleted(); + queryVipCard({bool showLoading = true}) async { + try{ + if(showLoading)EasyLoading.show(status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black); + BaseData> baseData = + await apiService.vipList({ + "keywords":editingController.text, + }).catchError((error) { + refreshController.refreshFailed(); }); - } else { - refreshController.refreshFailed(); + if (baseData != null && baseData.isSuccess) { + coupons.clear(); + coupons.addAll(baseData.data); + refreshController.refreshCompleted(); + } else { + refreshController.refreshFailed(); + } + }finally{ + EasyLoading.dismiss(); + setState(() {}); } } @override Widget build(BuildContext context) { - return Scaffold( - appBar: MyAppBar( - title: S.of(context).dianpuyue, - titleColor: Colors.black, - background: Colors.white, - leadingColor: Colors.black, + return GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: (){ + FocusScope.of(context).requestFocus(FocusNode()); + }, + child: Scaffold( + resizeToAvoidBottomInset: false, + appBar: MyAppBar( + title: "店铺充值", + titleColor: Colors.black, + background: Colors.white, + leadingColor: Colors.black, + ), + body:Column( + children: [ + Container( + color: Colors.white, + padding: EdgeInsets.only(top:10.h,bottom:18.h,), + child: searchShopItem(), + ), + Expanded(child: SmartRefresher( + enablePullDown: true, + enablePullUp: false, + header: MyHeader(), + footer: CustomFooter( + builder: (context, mode) { + return MyFooter(mode); + }, + ), + controller: refreshController, + onRefresh: queryVipCard, + physics: BouncingScrollPhysics(), + child: (coupons != null && coupons.length > 0) + ? ListView.builder( + padding: EdgeInsets.symmetric(vertical: 8.h), + itemBuilder: (context, position) { + return GestureDetector( + onTap: () { + Navigator.of(context).pushNamed( + '/router/mine_shop_recharge', + arguments: { + "id": coupons[position].id, + "tenantCode":coupons[position].tenantCode, + "storeId":coupons[position].storeList[0].id + }).then((value) { + queryVipCard(showLoading: false); + }); + }, + child: shopItem(coupons[position]), + ); + }, + itemCount: coupons != null ? coupons.length : 0, + ) + : NoDataView( + src: "assets/image/icon_empty.webp", + isShowBtn: false, + text: "还没有会员卡~", + fontSize: 16.sp, + margin: EdgeInsets.only(top: 120.h), + ), + ),) + ], + ), ), - body: SmartRefresher( - enablePullDown: true, - enablePullUp: false, - header: MyHeader(), - footer: CustomFooter( - builder: (context, mode) { - return MyFooter(mode); - }, + ); + } + + Widget searchShopItem() { + return Container( + margin: EdgeInsets.fromLTRB(14.w, 0, 14.w, 0), + padding: EdgeInsets.symmetric(vertical: 6.h), + decoration: BoxDecoration( + color: Color(0xFFF5FAF7), + borderRadius: BorderRadius.circular(4), + boxShadow: [ + BoxShadow( + color: Colors.black.withAlpha(12), + offset: Offset(0, 3), + blurRadius: 14, + spreadRadius: 0, + ), + ], + ), + child: TextField( + textInputAction: TextInputAction.search, + onEditingComplete: () { + FocusScope.of(context).requestFocus(FocusNode()); + queryVipCard(); + }, + controller: editingController, + style: TextStyle( + fontSize: 14.sp, ), - controller: refreshController, - onRefresh: queryVipCard, - physics: BouncingScrollPhysics(), - child: (coupons != null && coupons.length > 0) - ? ListView.builder( - padding: EdgeInsets.symmetric(vertical: 8.h), - itemBuilder: (context, position) { - return GestureDetector( - onTap: () { - Navigator.of(context).pushNamed( - '/router/mine_shop_details', - arguments: {"id": coupons[position].id}); - }, - child: shopItem(coupons[position]), - ); - }, - itemCount: coupons != null ? coupons.length : 0, - ) - : NoDataView( - src: "assets/image/icon_empty.webp", - isShowBtn: false, - text: "还没有会员卡~", - fontSize: 16.sp, - margin: EdgeInsets.only(top: 120.h), + decoration: InputDecoration( + hintText: "搜索联盟会员店", + hintStyle: TextStyle( + fontSize: 12.sp, + color: Color(0xFFB3B3B3), + ), + isCollapsed: true, + prefixIcon:Padding(padding: EdgeInsets.only(left: 5.w,right: 5.w),child: Image.asset( + "assets/image/icon_search.webp", + width: 16.h, + height: 16.h, + ),), + prefixIconConstraints: BoxConstraints(), + border: InputBorder.none, ), ), ); @@ -218,19 +326,20 @@ class _MineShopPage extends State { ), )), Text( - S.of(context).chakanxiangqing, + "去充值", style: TextStyle( - color: Color(0xFF353535), + color: Color(0xFF262626), fontSize: 12.sp, fontWeight: MyFontWeight.regular, ), ), SizedBox(width: 2,), - Icon( - Icons.chevron_right, - size: 24, - color: Colors.black, - ), + Image.asset( + "assets/image/icon_right_z.webp", + width: 16, + height: 16, + color: Color(0xFF262626), + ) ], ), ], diff --git a/lib/mine/mine_shop_recharge.dart b/lib/mine/mine_shop_recharge.dart new file mode 100644 index 00000000..3699879a --- /dev/null +++ b/lib/mine/mine_shop_recharge.dart @@ -0,0 +1,908 @@ +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), + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/lib/mine/mine_view/mine_item.dart b/lib/mine/mine_view/mine_item.dart index 7642dfc6..98f6d316 100644 --- a/lib/mine/mine_view/mine_item.dart +++ b/lib/mine/mine_view/mine_item.dart @@ -1,6 +1,5 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:huixiang/generated/l10n.dart'; import 'package:huixiang/utils/font_weight.dart'; import 'package:huixiang/view_widget/login_tips_dialog.dart'; @@ -182,7 +181,7 @@ class _MineItem extends State { }); }, child: mineItem( - S.of(context).dianpuyue, + S.of(context).dianpuchongzhi, "assets/image/shop_yue.webp", ), ),), @@ -224,7 +223,7 @@ class _MineItem extends State { ], ), SizedBox(height: 12.h,), - if(isShowMore) + // if(isShowMore) Row( children: [ ///我的砍价 @@ -323,9 +322,9 @@ class _MineItem extends State { // ),), ], ), - if(isShowMore) + // if(isShowMore) SizedBox(height: 12.h,), - if(isShowMore) + // if(isShowMore) Row( children: [ ////发票管理 @@ -354,38 +353,39 @@ class _MineItem extends State { Expanded(child:Container(),), ], ), - GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: () { - setState(() { - isShowMore = !isShowMore; - }); - }, - child: Container( - margin: EdgeInsets.symmetric(vertical: 10), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.max, - children: [ - Text( - (isShowMore != null && !isShowMore)?S.of(context).zhankai: S.of(context).shouqi, - style: TextStyle( - fontSize: 12.sp, - fontWeight: MyFontWeight.regular, - color: Color(0xFF32A060), - ), - ), - Icon( - (isShowMore != null && !isShowMore) - ? Icons.keyboard_arrow_down - : Icons.keyboard_arrow_up, - color: Color(0xFF32A060), - size: 18, - ), - ], - ),), - ) + ///收起展开 + // GestureDetector( + // behavior: HitTestBehavior.opaque, + // onTap: () { + // setState(() { + // isShowMore = !isShowMore; + // }); + // }, + // child: Container( + // margin: EdgeInsets.symmetric(vertical: 10), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.center, + // crossAxisAlignment: CrossAxisAlignment.center, + // mainAxisSize: MainAxisSize.max, + // children: [ + // Text( + // (isShowMore != null && !isShowMore)?S.of(context).zhankai: S.of(context).shouqi, + // style: TextStyle( + // fontSize: 12.sp, + // fontWeight: MyFontWeight.regular, + // color: Color(0xFF32A060), + // ), + // ), + // Icon( + // (isShowMore != null && !isShowMore) + // ? Icons.keyboard_arrow_down + // : Icons.keyboard_arrow_up, + // color: Color(0xFF32A060), + // size: 18, + // ), + // ], + // ),), + // ) ], ), ); diff --git a/lib/mine/mine_view/mine_navbar.dart b/lib/mine/mine_view/mine_navbar.dart index 263332ca..14c096f0 100644 --- a/lib/mine/mine_view/mine_navbar.dart +++ b/lib/mine/mine_view/mine_navbar.dart @@ -85,7 +85,7 @@ class _MineNavbar extends State { }); }, child: mineTopItem( - "钱包", + S.of(context).qianbao, "assets/image/wallet.webp", ), ), @@ -105,7 +105,7 @@ class _MineNavbar extends State { }); }, child: mineTopItem( - "会员码", + S.of(context).huiyuanma, "assets/image/vip_code.webp", ), ), @@ -175,18 +175,18 @@ class _MineNavbar extends State { Expanded( child: InkWell( onTap: () { - SharedPreferences.getInstance().then((value) { - if (value.getString("token") == null || - value.getString("token") == "") { - LoginTipsDialog().show(context); - return; - } - widget.toIntegralPage(); - }); + // SharedPreferences.getInstance().then((value) { + // if (value.getString("token") == null || + // value.getString("token") == "") { + // LoginTipsDialog().show(context); + // return; + // } + // widget.toIntegralPage(); + // }); }, child: mineBottomItem( widget?.userInfo?.points?? "0", - "积分", + S.of(context).jifen, ), ), ), @@ -246,7 +246,7 @@ class _MineNavbar extends State { }, child: mineBottomItem( widget?.userInfo?.happyBean?? "0", - "印章", + S.of(context).yinzhang, ), ), ), diff --git a/lib/mine/mine_view/mine_view.dart b/lib/mine/mine_view/mine_view.dart index 2c46c8f7..92f153ac 100644 --- a/lib/mine/mine_view/mine_view.dart +++ b/lib/mine/mine_view/mine_view.dart @@ -373,55 +373,56 @@ class _MineView extends State { ), ), ), - widget.userInfo == null - ? Container( - alignment: Alignment.center, - height: 50.h, - child: Icon( - Icons.keyboard_arrow_right, - size: 20, - color: Colors.black, - ), - ) - : Container( - alignment: Alignment.bottomRight, - height: 50.h, - child: GestureDetector( - onTap: () { - widget.toIntegralPage(); - }, - child: Container( - padding: EdgeInsets.only( - top: 4.h, bottom: 4.h, right: 16.w, left: 7.w), - margin: EdgeInsets.only(right: 14.w), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: Colors.white), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Image.asset( - "assets/image/icon_gold_coin.webp", - width: 16, - height: 16, - ), - Text( - S.of(context).tiantianlingjifen, - style: TextStyle( - color: Color(0xFF32A060), - fontSize: 12.sp, - fontWeight: MyFontWeight.regular, - ), - ), - // Icon( - // Icons.keyboard_arrow_right, - // size: 16, - // color: Colors.black, - // ) - ], - ), - )), - ), + ///应运营需求暂时关闭积分板块 + // widget.userInfo == null + // ? Container( + // alignment: Alignment.center, + // height: 50.h, + // child: Icon( + // Icons.keyboard_arrow_right, + // size: 20, + // color: Colors.black, + // ), + // ) + // : Container( + // alignment: Alignment.bottomRight, + // height: 50.h, + // child: GestureDetector( + // onTap: () { + // widget.toIntegralPage(); + // }, + // child: Container( + // padding: EdgeInsets.only( + // top: 4.h, bottom: 4.h, right: 16.w, left: 7.w), + // margin: EdgeInsets.only(right: 14.w), + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(12), + // color: Colors.white), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.end, + // children: [ + // Image.asset( + // "assets/image/icon_gold_coin.webp", + // width: 16, + // height: 16, + // ), + // Text( + // S.of(context).tiantianlingjifen, + // style: TextStyle( + // color: Color(0xFF32A060), + // fontSize: 12.sp, + // fontWeight: MyFontWeight.regular, + // ), + // ), + // // Icon( + // // Icons.keyboard_arrow_right, + // // size: 16, + // // color: Colors.black, + // // ) + // ], + // ), + // )), + // ), ], ), ); diff --git a/lib/mine/mine_vip/mine_attainment_page.dart b/lib/mine/mine_vip/mine_attainment_page.dart index 71665f2f..c7e1895c 100644 --- a/lib/mine/mine_vip/mine_attainment_page.dart +++ b/lib/mine/mine_vip/mine_attainment_page.dart @@ -20,6 +20,8 @@ import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import '../../view_widget/no_data_view.dart'; + class MineAttainmentPage extends StatefulWidget { final Map arguments; @@ -41,7 +43,6 @@ class _MineAttainmentPage extends State { SocialInfo infoNumber; final RefreshController refreshController = RefreshController(); - @override void dispose() { super.dispose(); @@ -115,7 +116,7 @@ class _MineAttainmentPage extends State { ); BaseData baseData = - await apiService.socialInfo().catchError((onError) {}); + await apiService.socialInfo().catchError((onError) {}); if (baseData != null && baseData.isSuccess) { setState(() { infoNumber = baseData.data; @@ -125,7 +126,7 @@ class _MineAttainmentPage extends State { EasyLoading.dismiss(); } - _onRefresh(){ + _onRefresh() { queryAttainmentBadges(); querySocialInfo(); } @@ -140,151 +141,162 @@ class _MineAttainmentPage extends State { ), ), child: Scaffold( - backgroundColor: Colors.transparent, - appBar: MyAppBar( - title:S.of(context).wodechengjiu, - titleColor: Colors.black, - titleSize: 18.sp, - background: Colors.transparent, - leadingColor: Colors.black, - ), - body: SmartRefresher( - controller: refreshController, - enablePullDown: true, - enablePullUp: false, - header: MyHeader(), - footer: CustomFooter( - builder: (context, mode) { - return MyFooter(mode); - }, - ), - onRefresh:(){ - setState(() { - _onRefresh(); - }); + backgroundColor: Colors.transparent, + appBar: MyAppBar( + title: S.of(context).wodechengjiu, + titleColor: Colors.black, + titleSize: 18.sp, + background: Colors.transparent, + leadingColor: Colors.black, + ), + body: SmartRefresher( + controller: refreshController, + enablePullDown: true, + enablePullUp: false, + header: MyHeader(), + footer: CustomFooter( + builder: (context, mode) { + return MyFooter(mode); }, - physics: BouncingScrollPhysics(), - child: Container( - child: - SingleChildScrollView( - physics: BouncingScrollPhysics(), - child: Column( - children: [ - SizedBox(height: 24), - MImage( - userInfo?.headimg ?? "", - isCircle: true, - width: 58, - height: 58, - fit: BoxFit.cover, - errorSrc: "assets/image/default_user.webp", - fadeSrc: "assets/image/default_user.webp", + ), + onRefresh: () { + setState(() { + _onRefresh(); + }); + }, + physics: BouncingScrollPhysics(), + child: Container( + child: SingleChildScrollView( + physics: BouncingScrollPhysics(), + child: Column( + children: [ + SizedBox(height: 24), + MImage( + userInfo?.headimg ?? "", + isCircle: true, + width: 58, + height: 58, + fit: BoxFit.cover, + errorSrc: "assets/image/default_user.webp", + fadeSrc: "assets/image/default_user.webp", + ), + SizedBox(height: 8), + Text( + userInfo?.nickname ?? S.of(context).denglu, + style: TextStyle( + fontSize: 16.sp, + fontWeight: FontWeight.bold, + color: Color(0xFF353535), ), - SizedBox(height: 8), - Text( - userInfo?.nickname ?? S.of(context).denglu, - style: TextStyle( - fontSize: 16.sp, - fontWeight: FontWeight.bold, - color: Color(0xFF353535), - ), + ), + SizedBox(height: 28), + Container( + margin: EdgeInsets.only( + left: 16, right: 16, top: 26, bottom: 8), + padding: EdgeInsets.all(20), + decoration: BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Colors.black.withAlpha(12), + offset: Offset(0, 3), + blurRadius: 14, + spreadRadius: 0, + ) + ], + borderRadius: BorderRadius.all(Radius.circular(8)), ), - SizedBox(height: 28), - Container( - margin: - EdgeInsets.only(left: 16, right: 16, top: 26, bottom: 8), - padding: EdgeInsets.all(20), - decoration: BoxDecoration( - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.black.withAlpha(12), - offset: Offset(0, 3), - blurRadius: 14, - spreadRadius: 0, - ) - ], - borderRadius: BorderRadius.all(Radius.circular(8)), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Text( - S.of(context).chengjiuhuizhang, - style: TextStyle( - fontWeight: MyFontWeight.medium, - fontSize: 14.sp, - color: Color(0xFF353535)), - ), - SizedBox(width: 4), - Text( - "(", - style: TextStyle( - fontWeight: MyFontWeight.medium, - fontSize: 14, - color: Color(0xFF353535)), - ), - Text( - infoNumber != null ? infoNumber.achievementNumber.toString() :"0", - style: TextStyle( - fontWeight: MyFontWeight.medium, - fontSize: 14, - color: Color(0xFF32A060)), - ), - Text( - "/${vipBadgesList.length})", - style: TextStyle( - fontWeight: MyFontWeight.medium, - fontSize: 14, - color: Color(0xFF353535)), - ), - ], - ), - SizedBox(height: 12), - attainmentBadge(), - ], - ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + S.of(context).chengjiuhuizhang, + style: TextStyle( + fontWeight: MyFontWeight.medium, + fontSize: 14.sp, + color: Color(0xFF353535)), + ), + SizedBox(width: 4), + Text( + "(", + style: TextStyle( + fontWeight: MyFontWeight.medium, + fontSize: 14, + color: Color(0xFF353535)), + ), + Text( + infoNumber != null + ? infoNumber.achievementNumber.toString() + : "0", + style: TextStyle( + fontWeight: MyFontWeight.medium, + fontSize: 14, + color: Color(0xFF32A060)), + ), + Text( + "/${vipBadgesList.length})", + style: TextStyle( + fontWeight: MyFontWeight.medium, + fontSize: 14, + color: Color(0xFF353535)), + ), + ], + ), + SizedBox(height: 12), + attainmentBadge(), + ], ), - ], - ), + ), + ], ), ), - ),), + ), + ), + ), ); } ///成就徽章列表 Widget attainmentBadge() { - return GridView.builder( - itemCount: vipBadgesList == null ? 0 : vipBadgesList.length, - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - //一行的Widget数量 - crossAxisCount: 3, - //水平子Widget之间间距 - crossAxisSpacing: 13, - //垂直子Widget之间间距 - mainAxisSpacing: 12, - //子Widget宽高比例 - childAspectRatio: AppUtils.textScale(context) > 1 - ? (1 - ((AppUtils.textScale(context) - 1))) - : 0.85, - ), - itemBuilder: (context, index) { - return GestureDetector( - onTap: () { - setState(() { - queryAchievementDetail(index); - }); - }, - child: badgeItem(vipBadgesList[index]), - ); - }, - ); + return (vipBadgesList != null && (vipBadgesList?.length ?? 0) > 0) + ? GridView.builder( + itemCount: vipBadgesList == null ? 0 : vipBadgesList.length, + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + //一行的Widget数量 + crossAxisCount: 3, + //水平子Widget之间间距 + crossAxisSpacing: 13, + //垂直子Widget之间间距 + mainAxisSpacing: 12, + //子Widget宽高比例 + childAspectRatio: AppUtils.textScale(context) > 1 + ? (1 - ((AppUtils.textScale(context) - 1))) + : 0.85, + ), + itemBuilder: (context, index) { + return GestureDetector( + onTap: () { + setState(() { + queryAchievementDetail(index); + }); + }, + child: badgeItem(vipBadgesList[index]), + ); + }, + ) + : NoDataView( + src: "assets/image/xiao_fei.webp", + isShowBtn: false, + text: "当前暂无成就徽章~", + fontSize: 16.sp, + margin: EdgeInsets.only(left: 60.w, right: 60.w), + ); + ; } Widget badgeItem(VipBadgesList vipBadgesList) { @@ -358,7 +370,7 @@ class _MineAttainmentPage extends State { ), SizedBox(height: 10), Text( - "${vipBadgesList.length >index ?vipBadgesList[index].name :""}${achievementDetail.length > checkPosition ?achievementDetail[checkPosition].name:""}徽章", + "${vipBadgesList.length > index ? vipBadgesList[index].name : ""}${achievementDetail.length > checkPosition ? achievementDetail[checkPosition].name : ""}徽章", style: TextStyle( fontSize: 16.sp, fontWeight: MyFontWeight.semi_bold, @@ -369,7 +381,7 @@ class _MineAttainmentPage extends State { height: 6.h, ), Text( - "再${vipBadgesList.length >index ? vipBadgesList[index].name :""} ${AppUtils.calculateDouble(double.tryParse(achievementDetail.length > checkPosition ?achievementDetail[checkPosition].lessScore :"") ?? 0)} 即可升级", + "再${vipBadgesList.length > index ? vipBadgesList[index].name : ""} ${AppUtils.calculateDouble(double.tryParse(achievementDetail.length > checkPosition ? achievementDetail[checkPosition].lessScore : "") ?? 0)} 即可升级", style: TextStyle( fontSize: 12.sp, fontWeight: MyFontWeight.regular, @@ -392,27 +404,29 @@ class _MineAttainmentPage extends State { ), SizedBox(width: 8), Column( - crossAxisAlignment:CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: - achievementDetail[checkPosition].rewardList != null - ? achievementDetail[checkPosition].rewardList.map((e) { - return Text( - rewardStr(e), - style: TextStyle( - fontWeight: MyFontWeight.regular, - fontSize: 12.sp, - color: Color(0xFF515151)), - ); - }).toList() - : [], + achievementDetail[checkPosition].rewardList != null + ? achievementDetail[checkPosition] + .rewardList + .map((e) { + return Text( + rewardStr(e), + style: TextStyle( + fontWeight: MyFontWeight.regular, + fontSize: 12.sp, + color: Color(0xFF515151)), + ); + }).toList() + : [], ), ], ), Expanded( child: Container( height: double.maxFinite, - margin: EdgeInsets.only(top:14), + margin: EdgeInsets.only(top: 14), child: ListView.builder( shrinkWrap: true, scrollDirection: Axis.horizontal, @@ -443,12 +457,12 @@ class _MineAttainmentPage extends State { ); } - String rewardStr(RewardList rewardList){ - if(rewardList.rewardType == 1) + String rewardStr(RewardList rewardList) { + if (rewardList.rewardType == 1) return "积分:${rewardList.refId}"; - else if(rewardList.rewardType == 2) + else if (rewardList.rewardType == 2) return "平台余额:${rewardList.refId}"; - else if(rewardList.rewardType == 3) + else if (rewardList.rewardType == 3) return "平台兑换券:${rewardList.couponName}"; return ""; } diff --git a/lib/mine/recharge_page.dart b/lib/mine/recharge_page.dart index 31b82e0e..5f946c78 100644 --- a/lib/mine/recharge_page.dart +++ b/lib/mine/recharge_page.dart @@ -19,9 +19,14 @@ import 'package:huixiang/utils/min.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:huixiang/view_widget/my_appbar.dart'; import 'package:huixiang/view_widget/recharge_details_dialog.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:tobias/tobias.dart' as tobias; +import '../view_widget/classic_header.dart'; +import '../view_widget/my_footer.dart'; +import '../view_widget/no_data_view.dart'; + class RechargePage extends StatefulWidget { @override State createState() { @@ -43,19 +48,13 @@ class _RechargePage extends State { RechargeActLists rechargeActLists; int selectStoreIndex = 0; String recommendName; + final RefreshController refreshController = RefreshController(); + int _loadCount = 0; @override void initState() { super.initState(); - - SharedPreferences.getInstance().then((value) { - apiService = ApiService(Dio(), - context: context, token: value.getString("token"), pay: true); - queryBenefitList(); - queryRuleDetails(); - queryRechargeActList(); - queryUserBalance(); - }); + _onRefresh(); payListen = weChatResponseEventHandler.listen((event) async { print("payCallback: ${event.errCode}"); if (event.errCode == 0) { @@ -77,10 +76,10 @@ class _RechargePage extends State { ///会员权益列表 queryBenefitList() async { - BaseData> baseData = - await apiService.benefitList().catchError((onError) {}); - if (baseData != null && baseData.isSuccess) { - setState(() { + try { + BaseData> baseData = + await apiService.benefitList().catchError((onError) {}); + if (baseData != null && baseData.isSuccess) { vipBenefitList.clear(); vipBenefitList.addAll(baseData.data); vipBenefitList.forEach((element) { @@ -90,51 +89,77 @@ class _RechargePage extends State { discount = double.parse(element.config); } }); - }); + } + } finally { + addLoadCount(); } - EasyLoading.dismiss(); } queryUserBalance() async { - BaseData baseData = - await apiService.queryInfo().catchError((onError) {}); - if (baseData != null && baseData.isSuccess) { - userInfo = baseData.data; - mBalance = userInfo?.money ?? "0"; - if (mounted) setState(() {}); + try { + BaseData baseData = + await apiService.queryInfo().catchError((onError) { + SmartDialog.showToast(AppUtils.dioErrorTypeToString(onError.type), + alignment: Alignment.center); + refreshController.refreshFailed(); + refreshController.loadFailed(); + }); + if (baseData != null && baseData.isSuccess) { + userInfo = baseData.data; + mBalance = userInfo?.money ?? "0"; + } + } finally { + addLoadCount(); } } ///会员权益介绍/规则/说明/储值说明 queryRuleDetails() async { - BaseData baseData = - await apiService.vipBenefit().catchError((onError) {}); - if (baseData != null && baseData.isSuccess) { - setState(() { + try { + BaseData baseData = + await apiService.vipBenefit().catchError((onError) {}); + if (baseData != null && baseData.isSuccess) { vipRuleDetails = baseData.data; - }); + } + } finally { + addLoadCount(); } - EasyLoading.dismiss(); } ///充值列表 queryRechargeActList() async { - if (apiService == null) { - SharedPreferences value = await SharedPreferences.getInstance(); - apiService = ApiService( - Dio(), - context: context, - token: value.getString("token"), - ); - } - BaseData baseData = - await apiService.rechargeActList().catchError((onError) {}); - if (baseData != null && baseData.isSuccess) { - setState(() { + try { + BaseData baseData = + await apiService.rechargeActList("admin").catchError((onError) {}); + if (baseData != null && baseData.isSuccess) { rechargeActLists = baseData.data; - }); + } + } finally { + addLoadCount(); + } + } + + _onRefresh() async { + EasyLoading.show( + status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black); + SharedPreferences value = await SharedPreferences.getInstance(); + if (apiService == null) + apiService = ApiService(Dio(), + context: context, token: value.getString("token"), pay: true); + queryBenefitList(); + queryRuleDetails(); + queryRechargeActList(); + queryUserBalance(); + } + + addLoadCount() { + _loadCount += 1; + if (_loadCount == 4) { + _loadCount = 0; + EasyLoading.dismiss(); + if (refreshController.isRefresh) refreshController.refreshCompleted(); + if (mounted) setState(() {}); } - EasyLoading.dismiss(); } @override @@ -148,415 +173,423 @@ class _RechargePage extends State { leadingColor: Colors.black, ), body: Container( - color: Color(0xFFFFFFFF), - child: SingleChildScrollView( - child: Container( - child: Stack( - children: [ - Column( + color: Color(0xFFFFFFFF), + child: SmartRefresher( + enablePullDown: true, + enablePullUp: false, + header: MyHeader(), + footer: CustomFooter( + builder: (context, mode) { + return MyFooter(mode); + }, + ), + controller: refreshController, + onRefresh: _onRefresh, + physics: BouncingScrollPhysics(), + child: SingleChildScrollView( + physics: BouncingScrollPhysics(), + child: Container( + child: Column( children: [ - SingleChildScrollView( - physics: BouncingScrollPhysics(), - child: Container( + Container( + margin: EdgeInsets.only(left: 16, right: 16), child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, children: [ - Container( - margin: EdgeInsets.only(left: 16, right: 16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - // ItemInputWidget( - // S.of(context).qingshuruchongzhijine, - // hintText: "", - // controller: controller, - // padding: EdgeInsets.all(20), - // errorText: S.of(context).chongzhizuixiaojine(100), - // titleColor: Color(0xFF727272), - // errorTextColor: Color(0xFF32A060), - // radius: 8, - // discount: discount / 10, - // style: TextStyle( - // fontWeight: FontWeight.bold, - // fontSize: 27.sp, - // color: color, - // ), - // inputLimit: 6, - // textInputType: TextInputType.number, - // textInputFormatter: - // FilteringTextInputFormatter.digitsOnly, - // onChanged: (value) { - // if (value != null && - // value != "" && - // double.tryParse(value) < 100) { - // color = Colors.red; - // } else { - // color = Colors.black; - // } - // setState(() {}); - // }, - // ), - SizedBox( - height: 20, + // ItemInputWidget( + // S.of(context).qingshuruchongzhijine, + // hintText: "", + // controller: controller, + // padding: EdgeInsets.all(20), + // errorText: S.of(context).chongzhizuixiaojine(100), + // titleColor: Color(0xFF727272), + // errorTextColor: Color(0xFF32A060), + // radius: 8, + // discount: discount / 10, + // style: TextStyle( + // fontWeight: FontWeight.bold, + // fontSize: 27.sp, + // color: color, + // ), + // inputLimit: 6, + // textInputType: TextInputType.number, + // textInputFormatter: + // FilteringTextInputFormatter.digitsOnly, + // onChanged: (value) { + // if (value != null && + // value != "" && + // double.tryParse(value) < 100) { + // color = Colors.red; + // } else { + // color = Colors.black; + // } + // setState(() {}); + // }, + // ), + SizedBox( + height: 20, + ), + Row( + children: [ + Expanded( + child: Text( + S.of(context).zhanghuyue, + style: TextStyle( + fontSize: 15.sp, + color: Color(0xFF181818), + fontFamily: 'JDZhengHT', + fontWeight: MyFontWeight.semi_bold), + )), + Text.rich( + TextSpan(children: [ + TextSpan( + text: "$mBalance", + style: TextStyle( + fontSize: 26.sp, + fontFamily: 'JDZhengHT', + color: Color(0xFF181818), + fontWeight: MyFontWeight.semi_bold), ), - Row( - children: [ - Expanded( - child: Text( - S.of(context).zhanghuyue, - style: TextStyle( - fontSize: 15.sp, - color: Color(0xFF181818), - fontFamily: 'JDZhengHT', - fontWeight: - MyFontWeight.semi_bold), - )), - Text.rich( - TextSpan(children: [ - TextSpan( - text: "$mBalance", - style: TextStyle( - fontSize: 26.sp, - fontFamily: 'JDZhengHT', - color: Color(0xFF181818), - fontWeight: - MyFontWeight.semi_bold), - ), - TextSpan( - text: "元", - style: TextStyle( - fontSize: 15.sp, - color: Color(0xFF181818), - fontWeight: - MyFontWeight.semi_bold), - ), - ]), - ), - ], + TextSpan( + text: "元", + style: TextStyle( + fontSize: 15.sp, + color: Color(0xFF181818), + fontWeight: MyFontWeight.semi_bold), ), - SizedBox(height: 28), - rechargeList(), - // Row( - // crossAxisAlignment: CrossAxisAlignment.start, - // mainAxisAlignment: MainAxisAlignment.spaceAround, - // children: [ - // if (vipRuleDetails?.recharge != null && - // vipRuleDetails.recharge != "") - // Expanded( - // child: Container( - // color: Colors.white, - // child: Html( - // data: "注意:${vipRuleDetails?.recharge ?? ""}", - // customImageRenders: { - // networkSourceMatcher(): networkImageRender( - // loadingWidget: () { - // return Container(); - // }, - // ), - // }, - // ), - // ), - // ) - // ], - // ), - ], - )), - Container( - width: double.infinity, - margin: EdgeInsets.only(left: 16, right: 16), - padding: EdgeInsets.only( - top: 20.h, - bottom: 24.h, + ]), + ), + ], + ), + SizedBox(height: 28), + rechargeList(), + // Row( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisAlignment: MainAxisAlignment.spaceAround, + // children: [ + // if (vipRuleDetails?.recharge != null && + // vipRuleDetails.recharge != "") + // Expanded( + // child: Container( + // color: Colors.white, + // child: Html( + // data: "注意:${vipRuleDetails?.recharge ?? ""}", + // customImageRenders: { + // networkSourceMatcher(): networkImageRender( + // loadingWidget: () { + // return Container(); + // }, + // ), + // }, + // ), + // ), + // ) + // ], + // ), + ], + )), + if (rechargeActLists != null && + (rechargeActLists?.preferentialList?.length ?? 0) > 0) + Container( + width: double.infinity, + margin: EdgeInsets.only(left: 16, right: 16), + padding: EdgeInsets.only( + top: 20.h, + bottom: 24.h, + ), + // decoration: BoxDecoration( + // color: Colors.white, + // borderRadius: BorderRadius.circular(4), + // ), + 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, + ), ), - // decoration: BoxDecoration( - // color: Colors.white, - // borderRadius: BorderRadius.circular(4), - // ), - child: Column( - mainAxisAlignment: - MainAxisAlignment.spaceAround, + ), + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + setState(() { + checkIndex = 2; + }); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, 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), - ), - ), - ), + 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(3), - ], + ), ), ), + checkView(2), ], ), ), - if((rechargeActLists?.isOpen ?? false) == true) + SizedBox(height: 10.h), GestureDetector( + behavior: HitTestBehavior.opaque, onTap: () { - showRecommendStore(); + setState(() { + checkIndex = 3; + }); }, - child: Container( - padding: EdgeInsets.only( - left: 14.w, - right: 16.w, - top: 14.h, - bottom: 14.h), - margin: EdgeInsets.only( - bottom: 22.h, left: 14.w, right: 14.w), - decoration: BoxDecoration( - color: Color(0xFFFAFAFA), - borderRadius: BorderRadius.circular(4), - ), - child: Row( - children: [ - Image.asset( - "assets/image/recharge_z.webp", - width: 16.w, - height: 17.h, - fit: BoxFit.fill, - ), - SizedBox(width: 8.w), - Expanded( - child: Text( - recommendName ??"为喜爱门店打call!(可选)", + 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( - fontWeight: MyFontWeight.regular, - fontSize: 12.sp, - color: (recommendName != null) ?Color(0xFF32A060):Color(0xFF868686), + fontSize: 14.sp, + color: Color(0xff353535), ), - )), - Icon( - Icons.arrow_forward_ios, - size: 16, ), - ], - )), - ), - Align( - alignment: Alignment.bottomCenter, - child: GestureDetector( - onTap: () { - recharge(); - }, - child: Container( - height: 56.h, - width: double.infinity, - alignment: Alignment.center, - decoration: BoxDecoration( - color: Color(0xFF32A060), - borderRadius: BorderRadius.circular(27), - ), - margin: EdgeInsets.only( - left: 16, right: 16, bottom: 21), - child: Text( - S.of(context).querenchongzhi, - style: TextStyle( - fontSize: 16.sp, - fontWeight: MyFontWeight.medium, - color: Colors.white, ), ), - ), + checkView(3), + ], ), - - // Container( - // height: 56.h, - // color: Colors.white, - // child: Row( - // children: [ - // Expanded(child:Container( - // padding:EdgeInsets.only(top: 7.h,left:16), - // child:Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // Row( - // children: [ - // Text( - // S.of(context).heji, - // style: TextStyle( - // fontSize: 14.sp, - // fontWeight: MyFontWeight.regular, - // color: Colors.black, - // ), - // ), - // Text( - // controller.text, - // style: TextStyle( - // fontSize: 16.sp, - // fontWeight: MyFontWeight.medium, - // color: Color(0xFF32A060), - // ), - // ), - // ], - // ), - // if(controller.text != "") - // Text.rich( - // TextSpan( - // children: [ - // TextSpan( - // text: "充值", - // style: TextStyle( - // fontSize:12.sp, - // fontWeight: MyFontWeight.regular, - // color: Color(0xFFADADAD), - // ), - // ), - // TextSpan( - // text:"¥${controller.text}", - // style: TextStyle( - // fontSize: 12.sp, - // fontWeight: MyFontWeight.regular, - // color:Color(0xff3541C9), - // ), - // ), - // TextSpan( - // text: "赠送", - // style: TextStyle( - // fontSize:12.sp, - // fontWeight: MyFontWeight.regular, - // color: Color(0xFFADADAD), - // ), - // ), - // TextSpan( - // text:"¥${((double.tryParse(controller.text)??0) - ((double.tryParse(controller.text)??0) * (discount/100))).toStringAsFixed(2)}", - // style: TextStyle( - // fontSize: 12.sp, - // fontWeight: MyFontWeight.regular, - // color: Color(0xff3541C9), - // ), - // ),TextSpan( - // text: "元", - // style: TextStyle( - // fontSize:12.sp, - // fontWeight: MyFontWeight.regular, - // color: Color(0xFFADADAD), - // ), - // ), - // ], - // ), - // ), - // ], - // )) - // ), - // GestureDetector( - // onTap: () { - // recharge(); - // }, - // child: RoundButton( - // width: 103.w, - // height: 54.h, - // text: S.of(context).chongzhi, - // textColor: Colors.white, - // fontWeight: MyFontWeight.regular, - // backgroup: Color(0xFF32A060), - // radius: 0, - // fontSize: 16.sp, - // padding: EdgeInsets.symmetric(vertical: 5.h), - // ), - // ), - // ], - // ), - // ) - ) + ), ], ), ), - ) + if ((rechargeActLists?.isOpen ?? false) == true) + GestureDetector( + onTap: () { + showRecommendStore(); + }, + child: Container( + padding: EdgeInsets.only( + left: 14.w, + right: 16.w, + top: 14.h, + bottom: 14.h), + margin: EdgeInsets.only( + bottom: 22.h, left: 14.w, right: 14.w), + decoration: BoxDecoration( + color: Color(0xFFFAFAFA), + borderRadius: BorderRadius.circular(4), + ), + child: Row( + children: [ + Image.asset( + "assets/image/recharge_z.webp", + width: 16.w, + height: 17.h, + fit: BoxFit.fill, + ), + SizedBox(width: 8.w), + Expanded( + child: Text( + recommendName ?? "为喜爱门店打call!(可选)", + style: TextStyle( + fontWeight: MyFontWeight.regular, + fontSize: 12.sp, + color: (recommendName != null) + ? Color(0xFF32A060) + : Color(0xFF868686), + ), + )), + Icon( + Icons.arrow_forward_ios, + size: 16, + ), + ], + )), + ), + if (rechargeActLists != null && + (rechargeActLists?.preferentialList?.length ?? 0) > 0) + Align( + alignment: Alignment.bottomCenter, + child: GestureDetector( + onTap: () { + recharge(); + }, + child: Container( + height: 56.h, + width: double.infinity, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Color(0xFF32A060), + borderRadius: BorderRadius.circular(27), + ), + margin: EdgeInsets.only( + left: 16, right: 16, bottom: 21), + child: Text( + S.of(context).querenchongzhi, + style: TextStyle( + fontSize: 16.sp, + fontWeight: MyFontWeight.medium, + color: Colors.white, + ), + ), + ), + ), + // Container( + // height: 56.h, + // color: Colors.white, + // child: Row( + // children: [ + // Expanded(child:Container( + // padding:EdgeInsets.only(top: 7.h,left:16), + // child:Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Row( + // children: [ + // Text( + // S.of(context).heji, + // style: TextStyle( + // fontSize: 14.sp, + // fontWeight: MyFontWeight.regular, + // color: Colors.black, + // ), + // ), + // Text( + // controller.text, + // style: TextStyle( + // fontSize: 16.sp, + // fontWeight: MyFontWeight.medium, + // color: Color(0xFF32A060), + // ), + // ), + // ], + // ), + // if(controller.text != "") + // Text.rich( + // TextSpan( + // children: [ + // TextSpan( + // text: "充值", + // style: TextStyle( + // fontSize:12.sp, + // fontWeight: MyFontWeight.regular, + // color: Color(0xFFADADAD), + // ), + // ), + // TextSpan( + // text:"¥${controller.text}", + // style: TextStyle( + // fontSize: 12.sp, + // fontWeight: MyFontWeight.regular, + // color:Color(0xff3541C9), + // ), + // ), + // TextSpan( + // text: "赠送", + // style: TextStyle( + // fontSize:12.sp, + // fontWeight: MyFontWeight.regular, + // color: Color(0xFFADADAD), + // ), + // ), + // TextSpan( + // text:"¥${((double.tryParse(controller.text)??0) - ((double.tryParse(controller.text)??0) * (discount/100))).toStringAsFixed(2)}", + // style: TextStyle( + // fontSize: 12.sp, + // fontWeight: MyFontWeight.regular, + // color: Color(0xff3541C9), + // ), + // ),TextSpan( + // text: "元", + // style: TextStyle( + // fontSize:12.sp, + // fontWeight: MyFontWeight.regular, + // color: Color(0xFFADADAD), + // ), + // ), + // ], + // ), + // ), + // ], + // )) + // ), + // GestureDetector( + // onTap: () { + // recharge(); + // }, + // child: RoundButton( + // width: 103.w, + // height: 54.h, + // text: S.of(context).chongzhi, + // textColor: Colors.white, + // fontWeight: MyFontWeight.regular, + // backgroup: Color(0xFF32A060), + // radius: 0, + // fontSize: 16.sp, + // padding: EdgeInsets.symmetric(vertical: 5.h), + // ), + // ), + // ], + // ), + // ) + ) ], ), - ], + ), ), - ), - ), - ), + )), ); } var checkIndex = 2; Widget rechargeList() { - return ListView.builder( - padding: EdgeInsets.zero, - itemCount: (rechargeActLists != null && (rechargeActLists?.preferentialList?.length ?? 0) > 0) ? rechargeActLists.preferentialList.length : 0, - scrollDirection: Axis.vertical, - shrinkWrap: true, - physics: BouncingScrollPhysics(), - itemBuilder: (context, position) { - return GestureDetector( - onTap: () { - setState(() { - selectIndex = position; - }); + return (rechargeActLists != null && + (rechargeActLists?.preferentialList?.length ?? 0) > 0) + ? ListView.builder( + padding: EdgeInsets.zero, + itemCount: (rechargeActLists != null && + (rechargeActLists?.preferentialList?.length ?? 0) > 0) + ? rechargeActLists.preferentialList.length + : 0, + scrollDirection: Axis.vertical, + shrinkWrap: true, + physics: BouncingScrollPhysics(), + itemBuilder: (context, position) { + return GestureDetector( + onTap: () { + setState(() { + selectIndex = position; + }); + }, + child: rechargeItem( + rechargeActLists.preferentialList[position], position)); }, - child: rechargeItem(rechargeActLists.preferentialList[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), + ); } Widget rechargeItem(PreferentialList preferentialList, index) { @@ -707,13 +740,13 @@ class _RechargePage extends State { ///选择推荐门店 showRecommendStore() { showModalBottomSheet( - context: context, - backgroundColor: Colors.transparent, + context: context, + backgroundColor: Colors.transparent, builder: (BuildContext context) { return StatefulBuilder(builder: ( - context, - state, - ) { + context, + state, + ) { return Container( height: 355.h, decoration: BoxDecoration( @@ -731,17 +764,17 @@ class _RechargePage extends State { children: [ Expanded( child: Container( - alignment: Alignment.center, - margin: EdgeInsets.symmetric(vertical: 12), - child: Text( - S.of(context).xuanzetuijianmendian, - style: TextStyle( - fontWeight: MyFontWeight.bold, - fontSize: 15.sp, - color: Color(0xFF353535), - ), - ), - )), + alignment: Alignment.center, + margin: EdgeInsets.symmetric(vertical: 12), + child: Text( + S.of(context).xuanzetuijianmendian, + style: TextStyle( + fontWeight: MyFontWeight.bold, + fontSize: 15.sp, + color: Color(0xFF353535), + ), + ), + )), GestureDetector( onTap: () { setState(() { @@ -764,24 +797,24 @@ class _RechargePage extends State { ), Expanded( child: ListView.builder( - physics: BouncingScrollPhysics(), - itemBuilder: (context, position) { - return GestureDetector( - onTap: () { - state(() { - selectStoreIndex = position; - }); - }, - child: recommendStoreItem(position), - ); + physics: BouncingScrollPhysics(), + itemBuilder: (context, position) { + return GestureDetector( + onTap: () { + state(() { + selectStoreIndex = position; + }); }, - itemCount: rechargeActLists.channels.length ?? 0, - )), + child: recommendStoreItem(position), + ); + }, + itemCount: rechargeActLists.channels.length ?? 0, + )), GestureDetector( onTap: () { setState(() { recommendName = - rechargeActLists.channels[selectStoreIndex]; + rechargeActLists.channels[selectStoreIndex]; Navigator.of(context).pop(); }); }, @@ -809,7 +842,8 @@ class _RechargePage extends State { ), ); }); - },); + }, + ); } Widget recommendStoreItem(index) { diff --git a/lib/mine/scan_web.dart b/lib/mine/scan_web.dart index b738be34..acab322e 100644 --- a/lib/mine/scan_web.dart +++ b/lib/mine/scan_web.dart @@ -26,7 +26,7 @@ class _ScanWeb extends State { super.initState(); result = widget.arguments["result"]; title = widget.arguments["title"]; - EasyLoading.show(status: S.current.zhengzaijiazai); + EasyLoading.show(status: S.current.zhengzaijiazai,maskType: EasyLoadingMaskType.black); } @override diff --git a/lib/order/order_detail_page.dart b/lib/order/order_detail_page.dart index 798a9c0b..925720ff 100644 --- a/lib/order/order_detail_page.dart +++ b/lib/order/order_detail_page.dart @@ -48,7 +48,7 @@ class _OrderDetailPage extends State { super.initState(); jumpState = widget.arguments["jumpState"]; SharedPreferences.getInstance().then((value) { - EasyLoading.show(status: S.of(context).zhengzaijiazai); + EasyLoading.show(status: S.of(context).zhengzaijiazai,maskType: EasyLoadingMaskType.black); apiService = ApiService(Dio(), context: context, token: value.getString("token"),); queryDetails(); diff --git a/lib/order/order_history_page.dart b/lib/order/order_history_page.dart index 9d19d9d0..dedaa653 100644 --- a/lib/order/order_history_page.dart +++ b/lib/order/order_history_page.dart @@ -1,5 +1,6 @@ import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:huixiang/generated/l10n.dart'; import 'package:huixiang/order/order_utils.dart'; @@ -132,57 +133,29 @@ class OrderHistoryList extends StatefulWidget { class _OrderHistoryList extends State with AutomaticKeepAliveClientMixin { final RefreshController refreshController = RefreshController(); - - @override - Widget build(BuildContext context) { - super.build(context); - return SmartRefresher( - controller: refreshController, - enablePullDown: true, - enablePullUp: true, - physics: BouncingScrollPhysics(), - header: MyHeader(), - footer: CustomFooter( - builder: (context, mode) { - return MyFooter(mode); - }, - ), - onRefresh: _onRefresh, - onLoading: queryOrder, - child: (orderInfos != null && orderInfos.length > 0) - ? ListView.builder( - itemCount: orderInfos != null ? orderInfos.length : 0, - itemBuilder: (context, position) { - return InkWell( - onTap: () { - Navigator.of(context).pushNamed('/router/order_details', - arguments: {"id": orderInfos[position].id,"jumpState":2}); - }, - child: orderItem(orderInfos[position]), - ); - }) - : NoDataView( - src: "assets/image/ding_dan.webp", - isShowBtn: false, - text: "目前暂无订单,快去下一单吧~", - fontSize: 16.sp, - margin: EdgeInsets.only(top: 120), - ), - ); - } - bool isRemake = true; - ApiService apiService; int current = 1; + List orderInfos = []; + UserInfo userInfo; + @override + void initState() { + super.initState(); + SharedPreferences.getInstance().then((value) => { + apiService = ApiService(Dio(), + showLoading: true, + context: context, + token: value.getString("token")), + queryOrder(), + queryUserBalance(), + }); + } _onRefresh() { current = 1; queryOrder(); } - List orderInfos = []; - queryOrder() async { BaseData> baseData = await apiService.orderList({ "current": current, @@ -213,24 +186,173 @@ class _OrderHistoryList extends State } setState(() {}); } else { - SmartDialog.showToast(baseData?.msg ?? "",alignment: Alignment.center); + if((baseData?.msg ?? "") != "") + SmartDialog.showToast(baseData.msg,alignment: Alignment.center); refreshController.refreshFailed(); refreshController.loadFailed(); } } - @override - void initState() { - super.initState(); - - SharedPreferences.getInstance().then((value) => { - apiService = ApiService(Dio(), - showLoading: true, + minLogin(OrderInfo orderInfo) { + apiService.minLogin(orderInfo.storeId).catchError((onError) { + debugPrint(onError); + }).then((baseData) { + if (baseData != null && baseData.isSuccess) { + Map minStoreInfo = baseData.data; + String minToken = minStoreInfo["token"]; + String tenant = orderInfo.tenantCode; + String storeId = orderInfo.storeId; + SharedPreferences.getInstance().then( + (value) => { + value.setString('minToken', minToken), + value.setString('tenant', tenant), + value.setString('storeId', storeId), + }, + ); + paySelected( + orderInfo, + MinApiService( + Dio(), context: context, - token: value.getString("token")), - queryOrder(), - queryUserBalance(), - }); + token: minToken, + tenant: tenant, + storeId: storeId, + )); + } + }); + } + + queryDetails(id) async { + if (apiService == null) { + SharedPreferences value = await SharedPreferences.getInstance(); + apiService = ApiService(Dio(), + context: context, token: value.getString("token"), showLoading: true); + } + BaseData baseData = + await apiService.orderDetail(id).catchError((error) {}); + if (baseData != null && baseData.isSuccess) { + return baseData.data; + } + } + + queryUserBalance() async { + BaseData baseData = + await apiService.queryInfo().catchError((onError) { + + }); + if (baseData != null && baseData.isSuccess) { + userInfo = baseData.data; + if (mounted) setState(() {}); + }else { + SmartDialog.showToast(baseData.msg, alignment: Alignment.center); + } + } + + paySelected(OrderInfo orderInfo, MinApiService minService) async { + var payChannel = await showModalBottomSheet( + context: context, + backgroundColor: Colors.transparent, + builder: (context) { + return OrderPaySelected(userInfo); + }, + ); + if (payChannel != null && payChannel > 0) { + orderInfo = await queryDetails(orderInfo.id); + OrderUtils.carryOnPay( + payChannel, + minService, + orderInfo, + (BaseData baseData) { + SmartDialog.showToast( + baseData?.msg == "ok" ? "订单支付成功" : baseData?.msg, + alignment: Alignment.center); + Future.delayed(Duration(seconds: 3), () { + _onRefresh(); + }); + }, + ); + } + } + + payResult(BaseData baseData) {} + + orderCancel(String orderId) async { + BaseData baseData = + await apiService.orderCancel(orderId).catchError((onError) {}); + if (baseData != null && baseData.isSuccess) { + SmartDialog.showToast("订单取消成功"); + _onRefresh(); + }else{ + if(baseData.msg != null) + SmartDialog.showToast(baseData.msg,alignment: Alignment.center); + } + } + + aginOrder(OrderInfo orderInfo) { + // Navigator.of(context).pushNamed( + // '/router/union_detail_page', + // arguments: {"id": storeId}, + // ); + // String storeId = (orderInfo != null && + // orderInfo.storeVO != null) + // ? (orderInfo.storeVO.id ?? "") + // : ""; + + if (orderInfo.storeVO.posType.code == "NORMALSTORE") { + Scan.toScan( + context, + orderInfo.storeVO.id, + orderInfo.tenantCode, + orderInfo.storeVO.storeName, + ); + } else { + Navigator.of(context).pushNamed( + '/router/store_order', + arguments: { + "id": orderInfo.storeVO.id, + "tenant": orderInfo.tenantCode, + "storeName": orderInfo.storeVO.storeName + }, + ); + } + } + + @override + Widget build(BuildContext context) { + super.build(context); + return SmartRefresher( + controller: refreshController, + enablePullDown: true, + enablePullUp: true, + physics: BouncingScrollPhysics(), + header: MyHeader(), + footer: CustomFooter( + builder: (context, mode) { + return MyFooter(mode); + }, + ), + onRefresh: _onRefresh, + onLoading: queryOrder, + child: (orderInfos != null && orderInfos.length > 0) + ? ListView.builder( + itemCount: orderInfos != null ? orderInfos.length : 0, + itemBuilder: (context, position) { + return InkWell( + onTap: () { + Navigator.of(context).pushNamed('/router/order_details', + arguments: {"id": orderInfos[position].id,"jumpState":2}); + }, + child: orderItem(orderInfos[position]), + ); + }) + : NoDataView( + src: "assets/image/ding_dan.webp", + isShowBtn: false, + text: "目前暂无订单,快去下一单吧~", + fontSize: 16.sp, + margin: EdgeInsets.only(top: 120), + ), + ); } String orderAllGoods(OrderInfo orderInfo) { @@ -535,130 +657,6 @@ class _OrderHistoryList extends State ); } - minLogin(OrderInfo orderInfo) { - apiService.minLogin(orderInfo.storeId).catchError((onError) { - debugPrint(onError); - }).then((baseData) { - if (baseData != null && baseData.isSuccess) { - Map minStoreInfo = baseData.data; - String minToken = minStoreInfo["token"]; - String tenant = orderInfo.tenantCode; - String storeId = orderInfo.storeId; - SharedPreferences.getInstance().then( - (value) => { - value.setString('minToken', minToken), - value.setString('tenant', tenant), - value.setString('storeId', storeId), - }, - ); - paySelected( - orderInfo, - MinApiService( - Dio(), - context: context, - token: minToken, - tenant: tenant, - storeId: storeId, - )); - } - }); - } - - queryDetails(id) async { - if (apiService == null) { - SharedPreferences value = await SharedPreferences.getInstance(); - apiService = ApiService(Dio(), - context: context, token: value.getString("token"), showLoading: true); - } - BaseData baseData = - await apiService.orderDetail(id).catchError((error) {}); - if (baseData != null && baseData.isSuccess) { - return baseData.data; - } - } - - UserInfo userInfo; - - queryUserBalance() async { - BaseData baseData = - await apiService.queryInfo().catchError((onError) {}); - if (baseData != null && baseData.isSuccess) { - userInfo = baseData.data; - if (mounted) setState(() {}); - }else { - SmartDialog.showToast(baseData.msg, alignment: Alignment.center); - } - } - - paySelected(OrderInfo orderInfo, MinApiService minService) async { - var payChannel = await showModalBottomSheet( - context: context, - backgroundColor: Colors.transparent, - builder: (context) { - return OrderPaySelected(userInfo); - }, - ); - if (payChannel != null && payChannel > 0) { - orderInfo = await queryDetails(orderInfo.id); - OrderUtils.carryOnPay( - payChannel, - minService, - orderInfo, - (BaseData baseData) { - SmartDialog.showToast( - baseData?.msg == "ok" ? "订单支付成功" : baseData?.msg, - alignment: Alignment.center); - Future.delayed(Duration(seconds: 3), () { - _onRefresh(); - }); - }, - ); - } - } - - payResult(BaseData baseData) {} - - orderCancel(String orderId) async { - BaseData baseData = - await apiService.orderCancel(orderId).catchError((onError) {}); - if (baseData != null && baseData.isSuccess) { - SmartDialog.showToast("订单取消成功"); - _onRefresh(); - }else{ - if(baseData.msg != null) - SmartDialog.showToast(baseData.msg,alignment: Alignment.center); - } - } - - aginOrder(OrderInfo orderInfo) { - // Navigator.of(context).pushNamed( - // '/router/union_detail_page', - // arguments: {"id": storeId}, - // ); - // String storeId = (orderInfo != null && - // orderInfo.storeVO != null) - // ? (orderInfo.storeVO.id ?? "") - // : ""; - - if (orderInfo.storeVO.posType.code == "NORMALSTORE") { - Scan.toScan( - context, - orderInfo.storeVO.id, - orderInfo.tenantCode, - orderInfo.storeVO.storeName, - ); - } else { - Navigator.of(context).pushNamed( - '/router/store_order', - arguments: { - "id": orderInfo.storeVO.id, - "tenant": orderInfo.tenantCode, - "storeName": orderInfo.storeVO.storeName - }, - ); - } - } - String totalPrice(orderInfo) { if (orderInfo == null) return ""; double totalPrice = (double.tryParse(orderInfo.orderSum) + diff --git a/lib/retrofit/data/ip_data.dart b/lib/retrofit/data/ip_data.dart new file mode 100644 index 00000000..532f1804 --- /dev/null +++ b/lib/retrofit/data/ip_data.dart @@ -0,0 +1,105 @@ +/// ip : "27.18.151.119" +/// pro : "湖北省" +/// proCode : "420000" +/// city : "武汉市" +/// cityCode : "420100" +/// region : "" +/// regionCode : "0" +/// addr : "湖北省武汉市 电信" +/// regionNames : "" +/// err : "" + +class IpData { + IpData({ + String ip, + String pro, + String proCode, + String city, + String cityCode, + String region, + String regionCode, + String addr, + String regionNames, + String err,}){ + _ip = ip; + _pro = pro; + _proCode = proCode; + _city = city; + _cityCode = cityCode; + _region = region; + _regionCode = regionCode; + _addr = addr; + _regionNames = regionNames; + _err = err; +} + + IpData.fromJson(dynamic json) { + _ip = json['ip']; + _pro = json['pro']; + _proCode = json['proCode']; + _city = json['city']; + _cityCode = json['cityCode']; + _region = json['region']; + _regionCode = json['regionCode']; + _addr = json['addr']; + _regionNames = json['regionNames']; + _err = json['err']; + } + String _ip; + String _pro; + String _proCode; + String _city; + String _cityCode; + String _region; + String _regionCode; + String _addr; + String _regionNames; + String _err; +IpData copyWith({ String ip, + String pro, + String proCode, + String city, + String cityCode, + String region, + String regionCode, + String addr, + String regionNames, + String err, +}) => IpData( ip: ip ?? _ip, + pro: pro ?? _pro, + proCode: proCode ?? _proCode, + city: city ?? _city, + cityCode: cityCode ?? _cityCode, + region: region ?? _region, + regionCode: regionCode ?? _regionCode, + addr: addr ?? _addr, + regionNames: regionNames ?? _regionNames, + err: err ?? _err, +); + String get ip => _ip; + String get pro => _pro; + String get proCode => _proCode; + String get city => _city; + String get cityCode => _cityCode; + String get region => _region; + String get regionCode => _regionCode; + String get addr => _addr; + String get regionNames => _regionNames; + String get err => _err; + + Map toJson() { + final map = {}; + map['ip'] = _ip; + map['pro'] = _pro; + map['proCode'] = _proCode; + map['city'] = _city; + map['cityCode'] = _cityCode; + map['region'] = _region; + map['regionCode'] = _regionCode; + map['addr'] = _addr; + map['regionNames'] = _regionNames; + map['err'] = _err; + return map; + } + +} \ No newline at end of file diff --git a/lib/retrofit/data/member_recharge_list.dart b/lib/retrofit/data/member_recharge_list.dart new file mode 100644 index 00000000..0fa2db51 --- /dev/null +++ b/lib/retrofit/data/member_recharge_list.dart @@ -0,0 +1,159 @@ +/// id : "1681490552371019776" +/// rechargeMoney : "100.00" +/// giftdMoney : "10.00" +/// limitNum : 0 +/// gitfdCouponId : null +/// startDate : null +/// endDate : null +/// startTime : null +/// endTime : null +/// tenantCode : "1175" +/// createTime : "2023-07-21 09:22:53" +/// isDeleted : 0 +/// rechargeType : 0 +/// remark : "充值100.00 赠送10.00" +/// sortValue : 0 +/// useNum : 0 + +class MemberRechargeList { + MemberRechargeList({ + String id, + String rechargeMoney, + String giftdMoney, + dynamic limitNum, + dynamic gitfdCouponId, + dynamic startDate, + dynamic endDate, + dynamic startTime, + dynamic endTime, + String tenantCode, + String createTime, + num isDeleted, + num rechargeType, + String remark, + num sortValue, + dynamic useNum,}){ + _id = id; + _rechargeMoney = rechargeMoney; + _giftdMoney = giftdMoney; + _limitNum = limitNum; + _gitfdCouponId = gitfdCouponId; + _startDate = startDate; + _endDate = endDate; + _startTime = startTime; + _endTime = endTime; + _tenantCode = tenantCode; + _createTime = createTime; + _isDeleted = isDeleted; + _rechargeType = rechargeType; + _remark = remark; + _sortValue = sortValue; + _useNum = useNum; +} + + MemberRechargeList.fromJson(dynamic json) { + _id = json['id']; + _rechargeMoney = json['rechargeMoney']; + _giftdMoney = json['giftdMoney']; + _limitNum = json['limitNum']; + _gitfdCouponId = json['gitfdCouponId']; + _startDate = json['startDate']; + _endDate = json['endDate']; + _startTime = json['startTime']; + _endTime = json['endTime']; + _tenantCode = json['tenantCode']; + _createTime = json['createTime']; + _isDeleted = json['isDeleted']; + _rechargeType = json['rechargeType']; + _remark = json['remark']; + _sortValue = json['sortValue']; + _useNum = json['useNum']; + } + String _id; + String _rechargeMoney; + String _giftdMoney; + dynamic _limitNum; + dynamic _gitfdCouponId; + dynamic _startDate; + dynamic _endDate; + dynamic _startTime; + dynamic _endTime; + String _tenantCode; + String _createTime; + num _isDeleted; + num _rechargeType; + String _remark; + num _sortValue; + dynamic _useNum; +MemberRechargeList copyWith({ String id, + String rechargeMoney, + String giftdMoney, + dynamic limitNum, + dynamic gitfdCouponId, + dynamic startDate, + dynamic endDate, + dynamic startTime, + dynamic endTime, + String tenantCode, + String createTime, + num isDeleted, + num rechargeType, + String remark, + num sortValue, + dynamic useNum, +}) => MemberRechargeList( id: id ?? _id, + rechargeMoney: rechargeMoney ?? _rechargeMoney, + giftdMoney: giftdMoney ?? _giftdMoney, + limitNum: limitNum ?? _limitNum, + gitfdCouponId: gitfdCouponId ?? _gitfdCouponId, + startDate: startDate ?? _startDate, + endDate: endDate ?? _endDate, + startTime: startTime ?? _startTime, + endTime: endTime ?? _endTime, + tenantCode: tenantCode ?? _tenantCode, + createTime: createTime ?? _createTime, + isDeleted: isDeleted ?? _isDeleted, + rechargeType: rechargeType ?? _rechargeType, + remark: remark ?? _remark, + sortValue: sortValue ?? _sortValue, + useNum: useNum ?? _useNum, +); + String get id => _id; + String get rechargeMoney => _rechargeMoney; + String get giftdMoney => _giftdMoney; + dynamic get limitNum => _limitNum; + dynamic get gitfdCouponId => _gitfdCouponId; + dynamic get startDate => _startDate; + dynamic get endDate => _endDate; + dynamic get startTime => _startTime; + dynamic get endTime => _endTime; + String get tenantCode => _tenantCode; + String get createTime => _createTime; + num get isDeleted => _isDeleted; + num get rechargeType => _rechargeType; + String get remark => _remark; + num get sortValue => _sortValue; + dynamic get useNum => _useNum; + + Map toJson() { + final map = {}; + map['id'] = _id; + map['rechargeMoney'] = _rechargeMoney; + map['giftdMoney'] = _giftdMoney; + map['limitNum'] = _limitNum; + map['gitfdCouponId'] = _gitfdCouponId; + map['startDate'] = _startDate; + map['endDate'] = _endDate; + map['startTime'] = _startTime; + map['endTime'] = _endTime; + map['tenantCode'] = _tenantCode; + map['createTime'] = _createTime; + map['isDeleted'] = _isDeleted; + map['rechargeType'] = _rechargeType; + map['remark'] = _remark; + map['sortValue'] = _sortValue; + map['useNum'] = _useNum; + return map; + } + +} \ No newline at end of file diff --git a/lib/retrofit/data/product_show.dart b/lib/retrofit/data/product_show.dart new file mode 100644 index 00000000..c4774b6b --- /dev/null +++ b/lib/retrofit/data/product_show.dart @@ -0,0 +1,749 @@ +/// id : "1484156758195699712" +/// createTime : "2022-01-20 21:32:00" +/// createUser : "1364043181062094848" +/// updateTime : "2022-01-21 18:27:02" +/// updateUser : "1364043181062094848" +/// supplierName : "一心回乡生态农场" +/// storeId : "1460885296764682240" +/// categoryId : "1460889654206136320" +/// groupId : "1484146679266410496" +/// shortName : "【一心回乡】三益米 筋道绵润、鲜稻尝鲜;自留种老品种,非转基因种子" +/// productName : "三益米1kg" +/// sellDesc : "" +/// productCode : "PRO202201202132000000000000001" +/// weight : "0" +/// applyPrice : "39.00" +/// price : "24.00" +/// vipPrice : null +/// stock : -13 +/// sellCount : 19 +/// needLogistics : 1 +/// oversold : 1 +/// organic : 0 +/// status : 1 +/// posShow : true +/// subscribeParam : null +/// isRaise : false +/// productType : 0 +/// productNumber : 1 +/// setMeal : 1 +/// attrStyle : 0 +/// detail : "" +/// isDelete : 0 +/// printerFlag : "DEFAULT" +/// materials : null +/// materialId : null +/// details : "" +/// thumbnailImg : "" +/// info : "" +/// buyCount : 12 +/// sellCountLimit : 0 +/// stockRecoveryTime : null +/// isAddPurchase : null +/// limitNum : 0 +/// rankId : "0" +/// happyBean : 0 +/// imgs : ["https://pos.upload.lotus-wallet.com/1179/2022/01/243f54db-2dc8-4a9b-9ccc-09fc7a4e2a2e.jpg"] +/// productSkuList : [{"id":"1484156758229254144","createTime":"2022-01-20 21:32:00","createUser":"1364043181062094848","updateTime":"2022-01-20 21:32:00","updateUser":"1364043181062094848","storeId":"1460885296764682240","skuCode":"P202201202132002","skuNameStr":"","productId":"1484156758195699712","skuPrice":"24.00","applyPrice":"39.00","vipPrice":"24.00","packagingFee":"0.00","skuImg":null,"skuStock":-13,"autoRenewSkuStock":0,"deliveries":0,"ticketType":"","ticketWipedTimeTemplateId":null,"takeType":null,"ticketDays":"0","ticketExpireTime":"23:59:59","sort":50,"setMeal":"","productSetMeals":null,"weight":0.0,"volume":0.0,"isDelete":0,"material":null,"version":0,"skuTickets":null,"ticketStyle":""}] + +class ProductShow { + ProductShow({ + String id, + String createTime, + String createUser, + String updateTime, + String updateUser, + String supplierName, + String storeId, + String categoryId, + String groupId, + String shortName, + String productName, + String sellDesc, + String productCode, + String weight, + String applyPrice, + String price, + dynamic vipPrice, + num stock, + num sellCount, + num needLogistics, + num oversold, + num organic, + num status, + bool posShow, + dynamic subscribeParam, + bool isRaise, + num productType, + num productNumber, + num setMeal, + num attrStyle, + String detail, + num isDelete, + String printerFlag, + dynamic materials, + dynamic materialId, + String details, + String thumbnailImg, + String info, + num buyCount, + num sellCountLimit, + dynamic stockRecoveryTime, + dynamic isAddPurchase, + num limitNum, + String rankId, + num happyBean, + List imgs, + List productSkuList,}){ + _id = id; + _createTime = createTime; + _createUser = createUser; + _updateTime = updateTime; + _updateUser = updateUser; + _supplierName = supplierName; + _storeId = storeId; + _categoryId = categoryId; + _groupId = groupId; + _shortName = shortName; + _productName = productName; + _sellDesc = sellDesc; + _productCode = productCode; + _weight = weight; + _applyPrice = applyPrice; + _price = price; + _vipPrice = vipPrice; + _stock = stock; + _sellCount = sellCount; + _needLogistics = needLogistics; + _oversold = oversold; + _organic = organic; + _status = status; + _posShow = posShow; + _subscribeParam = subscribeParam; + _isRaise = isRaise; + _productType = productType; + _productNumber = productNumber; + _setMeal = setMeal; + _attrStyle = attrStyle; + _detail = detail; + _isDelete = isDelete; + _printerFlag = printerFlag; + _materials = materials; + _materialId = materialId; + _details = details; + _thumbnailImg = thumbnailImg; + _info = info; + _buyCount = buyCount; + _sellCountLimit = sellCountLimit; + _stockRecoveryTime = stockRecoveryTime; + _isAddPurchase = isAddPurchase; + _limitNum = limitNum; + _rankId = rankId; + _happyBean = happyBean; + _imgs = imgs; + _productSkuList = productSkuList; +} + + ProductShow.fromJson(dynamic json) { + _id = json['id']; + _createTime = json['createTime']; + _createUser = json['createUser']; + _updateTime = json['updateTime']; + _updateUser = json['updateUser']; + _supplierName = json['supplierName']; + _storeId = json['storeId']; + _categoryId = json['categoryId']; + _groupId = json['groupId']; + _shortName = json['shortName']; + _productName = json['productName']; + _sellDesc = json['sellDesc']; + _productCode = json['productCode']; + _weight = json['weight']; + _applyPrice = json['applyPrice']; + _price = json['price']; + _vipPrice = json['vipPrice']; + _stock = json['stock']; + _sellCount = json['sellCount']; + _needLogistics = json['needLogistics']; + _oversold = json['oversold']; + _organic = json['organic']; + _status = json['status']; + _posShow = json['posShow']; + _subscribeParam = json['subscribeParam']; + _isRaise = json['isRaise']; + _productType = json['productType']; + _productNumber = json['productNumber']; + _setMeal = json['setMeal']; + _attrStyle = json['attrStyle']; + _detail = json['detail']; + _isDelete = json['isDelete']; + _printerFlag = json['printerFlag']; + _materials = json['materials']; + _materialId = json['materialId']; + _details = json['details']; + _thumbnailImg = json['thumbnailImg']; + _info = json['info']; + _buyCount = json['buyCount']; + _sellCountLimit = json['sellCountLimit']; + _stockRecoveryTime = json['stockRecoveryTime']; + _isAddPurchase = json['isAddPurchase']; + _limitNum = json['limitNum']; + _rankId = json['rankId']; + _happyBean = json['happyBean']; + _imgs = json['imgs'] != null ? json['imgs'].cast() : []; + if (json['productSkuList'] != null) { + _productSkuList = []; + json['productSkuList'].forEach((v) { + _productSkuList.add(ProductSkuList.fromJson(v)); + }); + } + } + String _id; + String _createTime; + String _createUser; + String _updateTime; + String _updateUser; + String _supplierName; + String _storeId; + String _categoryId; + String _groupId; + String _shortName; + String _productName; + String _sellDesc; + String _productCode; + String _weight; + String _applyPrice; + String _price; + dynamic _vipPrice; + num _stock; + num _sellCount; + num _needLogistics; + num _oversold; + num _organic; + num _status; + bool _posShow; + dynamic _subscribeParam; + bool _isRaise; + num _productType; + num _productNumber; + num _setMeal; + num _attrStyle; + String _detail; + num _isDelete; + String _printerFlag; + dynamic _materials; + dynamic _materialId; + String _details; + String _thumbnailImg; + String _info; + num _buyCount; + num _sellCountLimit; + dynamic _stockRecoveryTime; + dynamic _isAddPurchase; + num _limitNum; + String _rankId; + num _happyBean; + List _imgs; + List _productSkuList; +ProductShow copyWith({ String id, + String createTime, + String createUser, + String updateTime, + String updateUser, + String supplierName, + String storeId, + String categoryId, + String groupId, + String shortName, + String productName, + String sellDesc, + String productCode, + String weight, + String applyPrice, + String price, + dynamic vipPrice, + num stock, + num sellCount, + num needLogistics, + num oversold, + num organic, + num status, + bool posShow, + dynamic subscribeParam, + bool isRaise, + num productType, + num productNumber, + num setMeal, + num attrStyle, + String detail, + num isDelete, + String printerFlag, + dynamic materials, + dynamic materialId, + String details, + String thumbnailImg, + String info, + num buyCount, + num sellCountLimit, + dynamic stockRecoveryTime, + dynamic isAddPurchase, + num limitNum, + String rankId, + num happyBean, + List imgs, + List productSkuList, +}) => ProductShow( id: id ?? _id, + createTime: createTime ?? _createTime, + createUser: createUser ?? _createUser, + updateTime: updateTime ?? _updateTime, + updateUser: updateUser ?? _updateUser, + supplierName: supplierName ?? _supplierName, + storeId: storeId ?? _storeId, + categoryId: categoryId ?? _categoryId, + groupId: groupId ?? _groupId, + shortName: shortName ?? _shortName, + productName: productName ?? _productName, + sellDesc: sellDesc ?? _sellDesc, + productCode: productCode ?? _productCode, + weight: weight ?? _weight, + applyPrice: applyPrice ?? _applyPrice, + price: price ?? _price, + vipPrice: vipPrice ?? _vipPrice, + stock: stock ?? _stock, + sellCount: sellCount ?? _sellCount, + needLogistics: needLogistics ?? _needLogistics, + oversold: oversold ?? _oversold, + organic: organic ?? _organic, + status: status ?? _status, + posShow: posShow ?? _posShow, + subscribeParam: subscribeParam ?? _subscribeParam, + isRaise: isRaise ?? _isRaise, + productType: productType ?? _productType, + productNumber: productNumber ?? _productNumber, + setMeal: setMeal ?? _setMeal, + attrStyle: attrStyle ?? _attrStyle, + detail: detail ?? _detail, + isDelete: isDelete ?? _isDelete, + printerFlag: printerFlag ?? _printerFlag, + materials: materials ?? _materials, + materialId: materialId ?? _materialId, + details: details ?? _details, + thumbnailImg: thumbnailImg ?? _thumbnailImg, + info: info ?? _info, + buyCount: buyCount ?? _buyCount, + sellCountLimit: sellCountLimit ?? _sellCountLimit, + stockRecoveryTime: stockRecoveryTime ?? _stockRecoveryTime, + isAddPurchase: isAddPurchase ?? _isAddPurchase, + limitNum: limitNum ?? _limitNum, + rankId: rankId ?? _rankId, + happyBean: happyBean ?? _happyBean, + imgs: imgs ?? _imgs, + productSkuList: productSkuList ?? _productSkuList, +); + String get id => _id; + String get createTime => _createTime; + String get createUser => _createUser; + String get updateTime => _updateTime; + String get updateUser => _updateUser; + String get supplierName => _supplierName; + String get storeId => _storeId; + String get categoryId => _categoryId; + String get groupId => _groupId; + String get shortName => _shortName; + String get productName => _productName; + String get sellDesc => _sellDesc; + String get productCode => _productCode; + String get weight => _weight; + String get applyPrice => _applyPrice; + String get price => _price; + dynamic get vipPrice => _vipPrice; + num get stock => _stock; + num get sellCount => _sellCount; + num get needLogistics => _needLogistics; + num get oversold => _oversold; + num get organic => _organic; + num get status => _status; + bool get posShow => _posShow; + dynamic get subscribeParam => _subscribeParam; + bool get isRaise => _isRaise; + num get productType => _productType; + num get productNumber => _productNumber; + num get setMeal => _setMeal; + num get attrStyle => _attrStyle; + String get detail => _detail; + num get isDelete => _isDelete; + String get printerFlag => _printerFlag; + dynamic get materials => _materials; + dynamic get materialId => _materialId; + String get details => _details; + String get thumbnailImg => _thumbnailImg; + String get info => _info; + num get buyCount => _buyCount; + num get sellCountLimit => _sellCountLimit; + dynamic get stockRecoveryTime => _stockRecoveryTime; + dynamic get isAddPurchase => _isAddPurchase; + num get limitNum => _limitNum; + String get rankId => _rankId; + num get happyBean => _happyBean; + List get imgs => _imgs; + List get productSkuList => _productSkuList; + + Map toJson() { + final map = {}; + map['id'] = _id; + map['createTime'] = _createTime; + map['createUser'] = _createUser; + map['updateTime'] = _updateTime; + map['updateUser'] = _updateUser; + map['supplierName'] = _supplierName; + map['storeId'] = _storeId; + map['categoryId'] = _categoryId; + map['groupId'] = _groupId; + map['shortName'] = _shortName; + map['productName'] = _productName; + map['sellDesc'] = _sellDesc; + map['productCode'] = _productCode; + map['weight'] = _weight; + map['applyPrice'] = _applyPrice; + map['price'] = _price; + map['vipPrice'] = _vipPrice; + map['stock'] = _stock; + map['sellCount'] = _sellCount; + map['needLogistics'] = _needLogistics; + map['oversold'] = _oversold; + map['organic'] = _organic; + map['status'] = _status; + map['posShow'] = _posShow; + map['subscribeParam'] = _subscribeParam; + map['isRaise'] = _isRaise; + map['productType'] = _productType; + map['productNumber'] = _productNumber; + map['setMeal'] = _setMeal; + map['attrStyle'] = _attrStyle; + map['detail'] = _detail; + map['isDelete'] = _isDelete; + map['printerFlag'] = _printerFlag; + map['materials'] = _materials; + map['materialId'] = _materialId; + map['details'] = _details; + map['thumbnailImg'] = _thumbnailImg; + map['info'] = _info; + map['buyCount'] = _buyCount; + map['sellCountLimit'] = _sellCountLimit; + map['stockRecoveryTime'] = _stockRecoveryTime; + map['isAddPurchase'] = _isAddPurchase; + map['limitNum'] = _limitNum; + map['rankId'] = _rankId; + map['happyBean'] = _happyBean; + map['imgs'] = _imgs; + if (_productSkuList != null) { + map['productSkuList'] = _productSkuList.map((v) => v.toJson()).toList(); + } + return map; + } + +} + +/// id : "1484156758229254144" +/// createTime : "2022-01-20 21:32:00" +/// createUser : "1364043181062094848" +/// updateTime : "2022-01-20 21:32:00" +/// updateUser : "1364043181062094848" +/// storeId : "1460885296764682240" +/// skuCode : "P202201202132002" +/// skuNameStr : "" +/// productId : "1484156758195699712" +/// skuPrice : "24.00" +/// applyPrice : "39.00" +/// vipPrice : "24.00" +/// packagingFee : "0.00" +/// skuImg : null +/// skuStock : -13 +/// autoRenewSkuStock : 0 +/// deliveries : 0 +/// ticketType : "" +/// ticketWipedTimeTemplateId : null +/// takeType : null +/// ticketDays : "0" +/// ticketExpireTime : "23:59:59" +/// sort : 50 +/// setMeal : "" +/// productSetMeals : null +/// weight : 0.0 +/// volume : 0.0 +/// isDelete : 0 +/// material : null +/// version : 0 +/// skuTickets : null +/// ticketStyle : "" + +class ProductSkuList { + ProductSkuList({ + String id, + String createTime, + String createUser, + String updateTime, + String updateUser, + String storeId, + String skuCode, + String skuNameStr, + String productId, + String skuPrice, + String applyPrice, + String vipPrice, + String packagingFee, + dynamic skuImg, + num skuStock, + num autoRenewSkuStock, + num deliveries, + String ticketType, + dynamic ticketWipedTimeTemplateId, + dynamic takeType, + String ticketDays, + String ticketExpireTime, + num sort, + String setMeal, + dynamic productSetMeals, + num weight, + num volume, + num isDelete, + dynamic material, + num version, + dynamic skuTickets, + String ticketStyle,}){ + _id = id; + _createTime = createTime; + _createUser = createUser; + _updateTime = updateTime; + _updateUser = updateUser; + _storeId = storeId; + _skuCode = skuCode; + _skuNameStr = skuNameStr; + _productId = productId; + _skuPrice = skuPrice; + _applyPrice = applyPrice; + _vipPrice = vipPrice; + _packagingFee = packagingFee; + _skuImg = skuImg; + _skuStock = skuStock; + _autoRenewSkuStock = autoRenewSkuStock; + _deliveries = deliveries; + _ticketType = ticketType; + _ticketWipedTimeTemplateId = ticketWipedTimeTemplateId; + _takeType = takeType; + _ticketDays = ticketDays; + _ticketExpireTime = ticketExpireTime; + _sort = sort; + _setMeal = setMeal; + _productSetMeals = productSetMeals; + _weight = weight; + _volume = volume; + _isDelete = isDelete; + _material = material; + _version = version; + _skuTickets = skuTickets; + _ticketStyle = ticketStyle; +} + + ProductSkuList.fromJson(dynamic json) { + _id = json['id']; + _createTime = json['createTime']; + _createUser = json['createUser']; + _updateTime = json['updateTime']; + _updateUser = json['updateUser']; + _storeId = json['storeId']; + _skuCode = json['skuCode']; + _skuNameStr = json['skuNameStr']; + _productId = json['productId']; + _skuPrice = json['skuPrice']; + _applyPrice = json['applyPrice']; + _vipPrice = json['vipPrice']; + _packagingFee = json['packagingFee']; + _skuImg = json['skuImg']; + _skuStock = json['skuStock']; + _autoRenewSkuStock = json['autoRenewSkuStock']; + _deliveries = json['deliveries']; + _ticketType = json['ticketType']; + _ticketWipedTimeTemplateId = json['ticketWipedTimeTemplateId']; + _takeType = json['takeType']; + _ticketDays = json['ticketDays']; + _ticketExpireTime = json['ticketExpireTime']; + _sort = json['sort']; + _setMeal = json['setMeal']; + _productSetMeals = json['productSetMeals']; + _weight = json['weight']; + _volume = json['volume']; + _isDelete = json['isDelete']; + _material = json['material']; + _version = json['version']; + _skuTickets = json['skuTickets']; + _ticketStyle = json['ticketStyle']; + } + String _id; + String _createTime; + String _createUser; + String _updateTime; + String _updateUser; + String _storeId; + String _skuCode; + String _skuNameStr; + String _productId; + String _skuPrice; + String _applyPrice; + String _vipPrice; + String _packagingFee; + dynamic _skuImg; + num _skuStock; + num _autoRenewSkuStock; + num _deliveries; + String _ticketType; + dynamic _ticketWipedTimeTemplateId; + dynamic _takeType; + String _ticketDays; + String _ticketExpireTime; + num _sort; + String _setMeal; + dynamic _productSetMeals; + num _weight; + num _volume; + num _isDelete; + dynamic _material; + num _version; + dynamic _skuTickets; + String _ticketStyle; +ProductSkuList copyWith({ String id, + String createTime, + String createUser, + String updateTime, + String updateUser, + String storeId, + String skuCode, + String skuNameStr, + String productId, + String skuPrice, + String applyPrice, + String vipPrice, + String packagingFee, + dynamic skuImg, + num skuStock, + num autoRenewSkuStock, + num deliveries, + String ticketType, + dynamic ticketWipedTimeTemplateId, + dynamic takeType, + String ticketDays, + String ticketExpireTime, + num sort, + String setMeal, + dynamic productSetMeals, + num weight, + num volume, + num isDelete, + dynamic material, + num version, + dynamic skuTickets, + String ticketStyle, +}) => ProductSkuList( id: id ?? _id, + createTime: createTime ?? _createTime, + createUser: createUser ?? _createUser, + updateTime: updateTime ?? _updateTime, + updateUser: updateUser ?? _updateUser, + storeId: storeId ?? _storeId, + skuCode: skuCode ?? _skuCode, + skuNameStr: skuNameStr ?? _skuNameStr, + productId: productId ?? _productId, + skuPrice: skuPrice ?? _skuPrice, + applyPrice: applyPrice ?? _applyPrice, + vipPrice: vipPrice ?? _vipPrice, + packagingFee: packagingFee ?? _packagingFee, + skuImg: skuImg ?? _skuImg, + skuStock: skuStock ?? _skuStock, + autoRenewSkuStock: autoRenewSkuStock ?? _autoRenewSkuStock, + deliveries: deliveries ?? _deliveries, + ticketType: ticketType ?? _ticketType, + ticketWipedTimeTemplateId: ticketWipedTimeTemplateId ?? _ticketWipedTimeTemplateId, + takeType: takeType ?? _takeType, + ticketDays: ticketDays ?? _ticketDays, + ticketExpireTime: ticketExpireTime ?? _ticketExpireTime, + sort: sort ?? _sort, + setMeal: setMeal ?? _setMeal, + productSetMeals: productSetMeals ?? _productSetMeals, + weight: weight ?? _weight, + volume: volume ?? _volume, + isDelete: isDelete ?? _isDelete, + material: material ?? _material, + version: version ?? _version, + skuTickets: skuTickets ?? _skuTickets, + ticketStyle: ticketStyle ?? _ticketStyle, +); + String get id => _id; + String get createTime => _createTime; + String get createUser => _createUser; + String get updateTime => _updateTime; + String get updateUser => _updateUser; + String get storeId => _storeId; + String get skuCode => _skuCode; + String get skuNameStr => _skuNameStr; + String get productId => _productId; + String get skuPrice => _skuPrice; + String get applyPrice => _applyPrice; + String get vipPrice => _vipPrice; + String get packagingFee => _packagingFee; + dynamic get skuImg => _skuImg; + num get skuStock => _skuStock; + num get autoRenewSkuStock => _autoRenewSkuStock; + num get deliveries => _deliveries; + String get ticketType => _ticketType; + dynamic get ticketWipedTimeTemplateId => _ticketWipedTimeTemplateId; + dynamic get takeType => _takeType; + String get ticketDays => _ticketDays; + String get ticketExpireTime => _ticketExpireTime; + num get sort => _sort; + String get setMeal => _setMeal; + dynamic get productSetMeals => _productSetMeals; + num get weight => _weight; + num get volume => _volume; + num get isDelete => _isDelete; + dynamic get material => _material; + num get version => _version; + dynamic get skuTickets => _skuTickets; + String get ticketStyle => _ticketStyle; + + Map toJson() { + final map = {}; + map['id'] = _id; + map['createTime'] = _createTime; + map['createUser'] = _createUser; + map['updateTime'] = _updateTime; + map['updateUser'] = _updateUser; + map['storeId'] = _storeId; + map['skuCode'] = _skuCode; + map['skuNameStr'] = _skuNameStr; + map['productId'] = _productId; + map['skuPrice'] = _skuPrice; + map['applyPrice'] = _applyPrice; + map['vipPrice'] = _vipPrice; + map['packagingFee'] = _packagingFee; + map['skuImg'] = _skuImg; + map['skuStock'] = _skuStock; + map['autoRenewSkuStock'] = _autoRenewSkuStock; + map['deliveries'] = _deliveries; + map['ticketType'] = _ticketType; + map['ticketWipedTimeTemplateId'] = _ticketWipedTimeTemplateId; + map['takeType'] = _takeType; + map['ticketDays'] = _ticketDays; + map['ticketExpireTime'] = _ticketExpireTime; + map['sort'] = _sort; + map['setMeal'] = _setMeal; + map['productSetMeals'] = _productSetMeals; + map['weight'] = _weight; + map['volume'] = _volume; + map['isDelete'] = _isDelete; + map['material'] = _material; + map['version'] = _version; + map['skuTickets'] = _skuTickets; + map['ticketStyle'] = _ticketStyle; + return map; + } + +} \ No newline at end of file diff --git a/lib/retrofit/data/store.dart b/lib/retrofit/data/store.dart index 1dd45b68..e94cc87a 100644 --- a/lib/retrofit/data/store.dart +++ b/lib/retrofit/data/store.dart @@ -1,8 +1,7 @@ - import 'package:huixiang/retrofit/data/coupon_vo.dart'; +import 'package:huixiang/retrofit/data/product_show.dart'; import 'package:huixiang/retrofit/data/store_type.dart'; - class Store { Store(); @@ -38,81 +37,94 @@ class Store { CouponVo couponVO; dynamic deliveryInfo; String businessType; + String businessService; + List productShow; StoreType posType; - factory Store.fromJson(Map json) => Store() - ..id = json['id'] as String - ..createTime = json['createTime'] as String - ..createUser = json['createUser'] as String - ..updateTime = json['updateTime'] as String - ..updateUser = json['updateUser'] as String - ..tenantCode = json['tenantCode'] as String - ..useErp = json['useErp'] as bool - ..openStartTime = json['openStartTime'] as String - ..openEndTime = json['openEndTime'] as String - ..perCapitaConsumption = json['perCapitaConsumption'] as String - ..storeName = json['storeName'] as String - ..distance = (json['distance'] as num)?.toDouble() - ..logo = json['logo'] as String - ..facade = json['facade'] as String - ..shipAddress = json['shipAddress'] as String - ..remark = json['remark'] - ..mobile = json['mobile'] as String - ..longitude = json['longitude'] as String - ..latitude = json['latitude'] as String - ..refundAddress = json['refundAddress'] - ..refundTel = json['refundTel'] - ..refundContact = json['refundContact'] - ..isAutoSendRefundAddress = json['isAutoSendRefundAddress'] as int - ..province = json['province'] as String - ..city = json['city'] as String - ..district = json['district'] as String - ..address = json['address'] as String - ..headName = json['headName'] as String - ..headMobile = json['headMobile'] as String - ..deliveryInfo = json['deliveryInfo'] - ..businessType = json['businessType'] as String - ..couponVO = json['couponVO'] == null ? null : CouponVo.fromJson(json['couponVO']) - ..posType = json['posType'] == null - ? null - : StoreType.fromJson(json['posType'] as Map); - - Map toJson() => { - 'id': this.id, - 'createTime': this.createTime, - 'createUser': this.createUser, - 'updateTime': this.updateTime, - 'updateUser': this.updateUser, - 'tenantCode': this.tenantCode, - 'useErp': this.useErp, - 'openStartTime': this.openStartTime, - 'openEndTime': this.openEndTime, - 'perCapitaConsumption': this.perCapitaConsumption, - 'storeName': this.storeName, - 'distance': this.distance, - 'logo': this.logo, - 'facade': this.facade, - 'shipAddress': this.shipAddress, - 'remark': this.remark, - 'mobile': this.mobile, - 'longitude': this.longitude, - 'latitude': this.latitude, - 'refundAddress': this.refundAddress, - 'refundTel': this.refundTel, - 'refundContact': this.refundContact, - 'isAutoSendRefundAddress': this.isAutoSendRefundAddress, - 'province': this.province, - 'city': this.city, - 'district': this.district, - 'address': this.address, - 'headName': this.headName, - 'headMobile': this.headMobile, - 'deliveryInfo': this.deliveryInfo, - 'businessType': this.businessType, - 'couponVO': this.couponVO != null ? this.couponVO.toJson() : null, - 'posType': this.posType, - }; + factory Store.fromJson(Map json) => + Store() + ..id = json['id'] as String + ..createTime = json['createTime'] as String + ..createUser = json['createUser'] as String + ..updateTime = json['updateTime'] as String + ..updateUser = json['updateUser'] as String + ..tenantCode = json['tenantCode'] as String + ..useErp = json['useErp'] as bool + ..openStartTime = json['openStartTime'] as String + ..openEndTime = json['openEndTime'] as String + ..perCapitaConsumption = json['perCapitaConsumption'] as String + ..storeName = json['storeName'] as String + ..distance = (json['distance'] as num)?.toDouble() + ..logo = json['logo'] as String + ..facade = json['facade'] as String + ..shipAddress = json['shipAddress'] as String + ..remark = json['remark'] + ..mobile = json['mobile'] as String + ..longitude = json['longitude'] as String + ..latitude = json['latitude'] as String + ..refundAddress = json['refundAddress'] + ..refundTel = json['refundTel'] + ..refundContact = json['refundContact'] + ..isAutoSendRefundAddress = json['isAutoSendRefundAddress'] as int + ..province = json['province'] as String + ..city = json['city'] as String + ..district = json['district'] as String + ..address = json['address'] as String + ..headName = json['headName'] as String + ..headMobile = json['headMobile'] as String + ..deliveryInfo = json['deliveryInfo'] + ..businessType = json['businessType'] as String + ..businessService = json['businessService'] as String + ..couponVO = json['couponVO'] == null ? null : CouponVo.fromJson( + json['couponVO']) + ..productShow = (json['productShow'] as List) + ?.map((e) => + e == null ? null : ProductShow.fromJson(e as Map)) + ?.toList() + ..posType = json['posType'] == null + ? null + : StoreType.fromJson(json['posType'] as Map); + Map toJson() => + { + 'id': this.id, + 'createTime': this.createTime, + 'createUser': this.createUser, + 'updateTime': this.updateTime, + 'updateUser': this.updateUser, + 'tenantCode': this.tenantCode, + 'useErp': this.useErp, + 'openStartTime': this.openStartTime, + 'openEndTime': this.openEndTime, + 'perCapitaConsumption': this.perCapitaConsumption, + 'storeName': this.storeName, + 'distance': this.distance, + 'logo': this.logo, + 'facade': this.facade, + 'shipAddress': this.shipAddress, + 'remark': this.remark, + 'mobile': this.mobile, + 'longitude': this.longitude, + 'latitude': this.latitude, + 'refundAddress': this.refundAddress, + 'refundTel': this.refundTel, + 'refundContact': this.refundContact, + 'isAutoSendRefundAddress': this.isAutoSendRefundAddress, + 'province': this.province, + 'city': this.city, + 'district': this.district, + 'address': this.address, + 'headName': this.headName, + 'headMobile': this.headMobile, + 'deliveryInfo': this.deliveryInfo, + 'businessType': this.businessType, + 'businessService': this.businessService, + 'couponVO': this.couponVO != null ? this.couponVO.toJson() : null, + 'productShow': this.productShow.map((e) => e.toJson()).toList(), + 'posType': this.posType, + }; } + + diff --git a/lib/retrofit/min_api.dart b/lib/retrofit/min_api.dart index 286a292b..c8cf737b 100644 --- a/lib/retrofit/min_api.dart +++ b/lib/retrofit/min_api.dart @@ -19,6 +19,7 @@ import 'data/activity_order_list.dart'; import 'data/findMiNiGroupList.dart'; import 'data/home_recommend_list.dart'; import 'data/launch_join_act.dart'; +import 'data/member_recharge_list.dart'; import 'data/miNiDetail.dart'; import 'data/settleOrderInfo.dart'; import 'data/shoppingCart.dart'; @@ -26,7 +27,7 @@ import 'data/shopping_home_config.dart'; part 'min_api.g.dart'; -const localBaseUrl = "http://192.168.10.78:8765/app/";///本地 +const localBaseUrl = "http://app-api.test.yixinhuixiang.com/app/";///本地 // const localBaseUrl = "http://pos-test.api.lotus-wallet.com/app/";///测试 const serviceBaseUrl = "https://pos.api.lotus-wallet.com/app/";///线上 @@ -49,7 +50,7 @@ abstract class MinApiService { headers["tenant"] = tenant; } if (storeId != null && storeId != "") { - headers["store_id"] = storeId; + headers["store-id"] = storeId; } headers["Environment"] = "app"; dio.options = BaseOptions( @@ -67,7 +68,7 @@ abstract class MinApiService { debugPrint("headers = ${options.headers}"); if (showLoading && !EasyLoading.isShow) { //是否显示loading - EasyLoading.show(status: S.of(context).zhengzaijiazai); + EasyLoading.show(status: S.of(context).zhengzaijiazai,maskType: EasyLoadingMaskType.black); } if (options.data is FormData) { debugPrint("params data = FormData"); @@ -243,4 +244,13 @@ abstract class MinApiService { @POST("promotion/useMemberCoupon") Future useMemberCoupon(@Body() Map param); + ///商户充值 + @POST("/member/recharge") + Future> memberRecharge(@Body() Map param); + + ///充值列表 + @GET("/store/getRechargePreferential") + Future>> memberRechargeList(); + + } diff --git a/lib/retrofit/min_api.g.dart b/lib/retrofit/min_api.g.dart index a1aac3c6..215825a0 100644 --- a/lib/retrofit/min_api.g.dart +++ b/lib/retrofit/min_api.g.dart @@ -651,4 +651,49 @@ class _MinApiService implements MinApiService { ); return value; } + + @override + Future> memberRecharge(param) async { + ArgumentError.checkNotNull(param, 'param'); + const _extra = {}; + final queryParameters = {}; + final _data = {}; + _data.addAll(param ?? {}); + final _result = await _dio.request>('//member/recharge', + queryParameters: queryParameters, + options: RequestOptions( + method: 'POST', + headers: {}, + extra: _extra, + baseUrl: baseUrl), + data: _data); + final value = BaseData.fromJson( + _result.data, + (json) => json as dynamic, + ); + return value; + } + + @override + Future>> memberRechargeList() async { + const _extra = {}; + final queryParameters = {}; + final _data = {}; + final _result = await _dio.request>( + '/store/getRechargePreferential', + queryParameters: queryParameters, + options: RequestOptions( + method: 'GET', + headers: {}, + extra: _extra, + baseUrl: baseUrl), + data: _data); + final value = BaseData>.fromJson( + _result.data, + (json) => (json as List) + .map( + (i) => MemberRechargeList.fromJson(i as Map)) + .toList()); + return value; + } } diff --git a/lib/retrofit/retrofit_api.dart b/lib/retrofit/retrofit_api.dart index 4beff7f6..686a8ffb 100644 --- a/lib/retrofit/retrofit_api.dart +++ b/lib/retrofit/retrofit_api.dart @@ -6,7 +6,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; -import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:gbk2utf8/gbk2utf8.dart'; import 'package:huixiang/generated/l10n.dart'; import 'package:huixiang/retrofit/data/activity.dart'; import 'package:huixiang/retrofit/data/article.dart'; @@ -14,11 +14,11 @@ import 'package:huixiang/retrofit/data/base_data.dart'; import 'package:huixiang/retrofit/data/comunity_comment.dart'; import 'package:huixiang/retrofit/data/coupon.dart'; import 'package:huixiang/retrofit/data/farmers_list.dart'; -import 'package:huixiang/retrofit/data/login_info.dart'; import 'package:huixiang/retrofit/data/order_info.dart'; import 'package:huixiang/view_widget/login_tips_dialog.dart'; import 'package:retrofit/retrofit.dart'; +import '../login/captcha/click_word_captcha.dart'; import '../utils/flutter_utils.dart'; import 'data/achievement_detail_list.dart'; import 'data/activity_pos.dart'; @@ -41,6 +41,7 @@ import 'data/headlines_list.dart'; import 'data/headlines_list_details.dart'; import 'data/home_rank.dart'; import 'data/invitation_list.dart'; +import 'data/ip_data.dart'; import 'data/logistics.dart'; import 'data/member_Infor.dart'; import 'data/member_comment_list.dart'; @@ -49,7 +50,6 @@ import 'data/msg_stats.dart'; import 'data/page.dart'; import 'data/rank.dart'; import 'data/rechargeActLists.dart'; -import 'data/recharge_list.dart'; import 'data/second_card_list.dart'; import 'data/sign_info.dart'; import 'data/social_info.dart'; @@ -66,9 +66,15 @@ import 'data/wx_pay.dart'; part 'retrofit_api.g.dart'; -const localBaseUrl = "http://192.168.10.78:8766/app/";///本地 +const localBaseUrl = "http://platform-api.test.yixinhuixiang.com/app/";///本地 // const localBaseUrl = "http://platform.test.api.lotus-wallet.com/app/";///测试 -const serviceBaseUrl = "https://pos.platform.lotus-wallet.com/app/";///线上 +const serviceBaseUrl = "https://pos.platform.lotus-wallet.com/app/"; + +///线上 + +const ipBaseUrl = "http://whois.pconline.com.cn"; + +///ip @RestApi(baseUrl: localBaseUrl) abstract class ApiService { @@ -78,6 +84,7 @@ abstract class ApiService { BuildContext context, String token, bool showLoading = false, + bool isIp = false, bool pay = true, }) { Map headers = @@ -85,6 +92,9 @@ abstract class ApiService { if (pay) { headers["Environment"] = "app"; } + print("软件当前运行的模式 kReleaseMode:"+(kReleaseMode ? "发布模式":"调试模式")); + if (kReleaseMode) baseUrl = serviceBaseUrl; + if (isIp) baseUrl = ipBaseUrl; dio.options = BaseOptions( connectTimeout: 60000, receiveTimeout: 60000, @@ -93,34 +103,40 @@ abstract class ApiService { ); dio.interceptors.add( InterceptorsWrapper(onRequest: (RequestOptions options) { + try { debugPrint("\n======================= 请求数据 ======================="); debugPrint("method = ${options.method.toString()}"); debugPrint("url = ${options.uri.toString()}"); debugPrint("headers = ${options.headers}"); if (showLoading && !EasyLoading.isShow) { //是否显示loading - EasyLoading.show(status: S.of(context).zhengzaijiazai); + EasyLoading.show( + status: S.of(context).zhengzaijiazai, + maskType: EasyLoadingMaskType.black); } if (options.data is FormData) { debugPrint("params data = FormData"); } else { - debugPrint("params data = ${jsonEncode(options.data)}"); + debugPrint("params data = ${jsonEncode(options.data)}"); } debugPrint("params queryParameters = ${options.queryParameters}"); + } catch (e1) {} }, onResponse: (Response response) { + try { debugPrint("\n======================= 响应数据开始 ======================="); if (showLoading && EasyLoading.isShow) { EasyLoading.dismiss(); } debugPrint("code = ${response.statusCode}"); + p(jsonEncode(response.data)); // debugPrint(jsonEncode(response.data), wrapWidth: response.data.toString().length * 10); Map map = response.data; - if (map["code"] != 0) { - EasyLoading.dismiss(); - } + // if (map["code"] != 0) { + // EasyLoading.dismiss(); + // } if (map["code"] == 40005 || map["code"] == 40001) { if (!LoginTipsDialog().isShow) { print("show: ${LoginTipsDialog().isShow}"); @@ -131,6 +147,7 @@ abstract class ApiService { // SmartDialog.showToast(map["msg"], alignment: Alignment.center); } debugPrint("======================= 响应数据结束 =======================\n"); + } catch (e2) {} }, onError: (DioError e) { if (EasyLoading.isShow) { EasyLoading.dismiss(); @@ -143,16 +160,14 @@ abstract class ApiService { debugPrint("\n"); }), ); - - if (kReleaseMode) { - baseUrl = serviceBaseUrl; - } return _ApiService(dio, baseUrl: baseUrl); } static void p(String msg) { //因为String的length是字符数量不是字节数量所以为了防止中文字符过多, // 把4*1024的MAX字节打印长度改为1000字符数 + if(msg.length > 10000) + return; int maxStrLength = 900; //大于1000时 while (msg.length > maxStrLength) { @@ -166,11 +181,12 @@ abstract class ApiService { ///文件上传 @POST("/file/upload") @MultiPart() - Future> upload( - @Part(name: "file") File data, @Part(name: "folderId") int folderId,bool isVideo); + Future> upload(@Part(name: "file") File data, + @Part(name: "folderId") int folderId, bool isVideo); /// 周边搜索 - @GET("https://restapi.amap.com/v3/place/around?key=542b46afa8e4b88fe1eb3c4d0ba0872f&location={lat},{lng}&keywords={keywords}&offset={size}&page={page}&extensions=all") + @GET( + "https://restapi.amap.com/v3/place/around?key=542b46afa8e4b88fe1eb3c4d0ba0872f&location={lat},{lng}&keywords={keywords}&offset={size}&page={page}&extensions=all") Future searchPoi(@Path("lat") String lat, @Path("lng") String lng, @Path("keywords") String keywords, int size, int page); @@ -183,8 +199,8 @@ abstract class ApiService { Future> appChannels(); ///发送验证码 - @GET("/auth/sendVerify/{areaCode}/{mobile}") - Future sendVerify(@Path("areaCode") String areaCode, @Path("mobile") String mobile); + @POST("/auth/sendVerify") + Future> sendVerify(@Body() Map param); ///积分商城商品列表 @POST("/creditGoods/list") @@ -221,8 +237,9 @@ abstract class ApiService { Future> recharge(@Body() Map param); ///充值活动列表 - @GET("/wallet/rechargeActList") - Future> rechargeActList(); + @GET("/wallet/rechargeActList?tenantCode={tenantCode}") + Future> rechargeActList( + @Path("tenantCode") String tenantCode); ///领取优惠券 @GET("/coupon/receive?couponId={couponId}") @@ -298,11 +315,13 @@ abstract class ApiService { ///分页查看资讯列表 @POST("/information/list") - Future>> queryArticle(@Body() Map param); + Future>> queryArticle( + @Body() Map param); ///banner查询 @POST("/banner/page") - Future>> queryBanner(@Body() Map param); + Future>> queryBanner( + @Body() Map param); ///品牌信息 @GET("/home/brand") @@ -351,6 +370,16 @@ abstract class ApiService { Future>> msgList( @Body() Map param); + ///加载验证码 + @POST("/captcha/get") + Future captchaGet( + @Body() Map param); + + ///校验验证码 + @POST("/captcha/check") + Future captchaCheck( + @Body() Map param); + ///App消息详情 @GET("/app-msg/{id}") Future queryMsg(@Path("id") String id); @@ -404,11 +433,13 @@ abstract class ApiService { /// 动态列表 @POST("/information/trend-list") - Future>> trendList(@Body() Map map); + Future>> trendList( + @Body() Map map); /// 我关注/粉丝的会员列表 @POST("/member/follow/list") - Future>> followList(@Body() Map map); + Future>> followList( + @Body() Map map); ///关注/取关会员 @PUT("/member/follow/{followId}") @@ -428,11 +459,13 @@ abstract class ApiService { ///课程章节列表 @GET("/course/catalogList/{courseId}") - Future>> catalogList(@Path("courseId") String courseId); + Future>> catalogList( + @Path("courseId") String courseId); /// 课程列表 @POST("/course/list") - Future>> courseList(@Body() Map map); + Future>> courseList( + @Body() Map map); ///课程的合集列表 @GET("/course/collectList") @@ -440,7 +473,8 @@ abstract class ApiService { ///合集包含的课程列表 @GET("/course/collect/{collectId}") - Future>> collect(@Path("collectId") String collectId); + Future>> collect( + @Path("collectId") String collectId); ///课程详情 @GET("/course/{id}") @@ -452,15 +486,18 @@ abstract class ApiService { /// APP查询所有成就徽章 并显示会员完成的 @POST("/app-memberAchievement/findBadges") - Future>> findBadges(@Body() Map map); + Future>> findBadges( + @Body() Map map); ///查看一个成就大类详情 - @GET("/app-memberAchievement/getAchievementDetail?achievementCategoryId={achievementCategoryId}") - Future>> getAchievementDetail(@Path("achievementCategoryId") String achievementCategoryId); + @GET( + "/app-memberAchievement/getAchievementDetail?achievementCategoryId={achievementCategoryId}") + Future>> getAchievementDetail( + @Path("achievementCategoryId") String achievementCategoryId); ///会员的权益列表 - @GET("/member/benefitList") - Future>> benefitList(); + @GET("/member/benefitList") + Future>> benefitList(); ///会员权益 @GET("/home/vipBenefit") @@ -480,7 +517,8 @@ abstract class ApiService { ///查看积分订单物流 @GET("/creditOrder/getAppShippingTrace?orderId={orderId}") - Future> getAppShippingTrace(@Path("orderId") String orderId); + Future> getAppShippingTrace( + @Path("orderId") String orderId); ///购买会员等级 @POST("/member/rankBuy") @@ -492,11 +530,13 @@ abstract class ApiService { ///文章合集详情 @GET("/information/category/{id}") - Future> headlinesDetails(@Path("id") String id); + Future> headlinesDetails( + @Path("id") String id); /// 我的邀请会员列表 @POST("/member/inviteMemberList") - Future>> inviteMemberList(@Body() Map map); + Future>> inviteMemberList( + @Body() Map map); ///核销优惠券 @GET("/coupon/wiped/{memberCouponId}") @@ -564,5 +604,10 @@ abstract class ApiService { ///兑换积分门店列表 @GET("/store/storeListByCreditId/{creditGoodsId}") - Future>> storeListByCreditId(@Path("creditGoodsId") String creditGoodsId); + Future>> storeListByCreditId( + @Path("creditGoodsId") String creditGoodsId); + + ///获取APP门店推广渠道 + @GET("/ipJson.jsp") + Future getIpInfo(); } diff --git a/lib/retrofit/retrofit_api.g.dart b/lib/retrofit/retrofit_api.g.dart index c1e355fc..386d5a17 100644 --- a/lib/retrofit/retrofit_api.g.dart +++ b/lib/retrofit/retrofit_api.g.dart @@ -17,21 +17,18 @@ class _ApiService implements ApiService { String baseUrl; @override - Future> upload(data, folderId,bool isVideo) async { + Future> upload(data, folderId, bool isVideo) async { ArgumentError.checkNotNull(data, 'data'); ArgumentError.checkNotNull(folderId, 'folderId'); const _extra = {}; final queryParameters = {}; final _data = FormData(); String fileName = data.path.split(Platform.pathSeparator).last; - if(!isVideo && !fileName.contains(".jpeg") && !fileName.contains(".png")) + if (!isVideo && !fileName.contains(".jpeg") && !fileName.contains(".png")) fileName += ".jpeg"; - else if(isVideo && !fileName.contains(".mp4")) - fileName += ".mp4"; + else if (isVideo && !fileName.contains(".mp4")) fileName += ".mp4"; _data.files.add(MapEntry( - 'file', - MultipartFile.fromFileSync(data.path, - filename: fileName))); + 'file', MultipartFile.fromFileSync(data.path, filename: fileName))); print("filename:$fileName"); if (folderId != null) { _data.fields.add(MapEntry('folderId', folderId.toString())); @@ -93,7 +90,7 @@ class _ApiService implements ApiService { data: _data); final value = BaseData.fromJson( _result.data, - (json) => json==null?null:json, + (json) => json == null ? null : json, ); return value; } @@ -114,30 +111,29 @@ class _ApiService implements ApiService { data: _data); final value = BaseData.fromJson( _result.data, - (json) => ChannelsList.fromJson(json), + (json) => ChannelsList.fromJson(json), ); return value; } @override - Future> sendVerify(areaCode,mobile) async { - ArgumentError.checkNotNull(mobile, 'mobile'); - ArgumentError.checkNotNull(areaCode, 'areaCode'); + Future> sendVerify(param) async { + ArgumentError.checkNotNull(param, 'param'); const _extra = {}; final queryParameters = {}; final _data = {}; - final _result = await _dio.request>( - '/auth/sendVerify/$areaCode/$mobile', + _data.addAll(param ?? {}); + final _result = await _dio.request>('/auth/sendVerify', queryParameters: queryParameters, options: RequestOptions( - method: 'GET', + method: 'POST', headers: {}, extra: _extra, baseUrl: baseUrl), data: _data); final value = BaseData.fromJson( _result.data, - (json) => json as dynamic, + (json) => json == null ? null :json as dynamic, ); return value; } @@ -322,12 +318,12 @@ class _ApiService implements ApiService { } @override - Future> rechargeActList() async { + Future> rechargeActList(tenantCode) async { const _extra = {}; final queryParameters = {}; final _data = {}; final _result = await _dio.request>( - '/wallet/rechargeActList', + '/wallet/rechargeActList?tenantCode=$tenantCode', queryParameters: queryParameters, options: RequestOptions( method: 'GET', @@ -337,7 +333,7 @@ class _ApiService implements ApiService { data: _data); final value = BaseData.fromJson( _result.data, - (json) => RechargeActLists.fromJson(json), + (json) => RechargeActLists.fromJson(json), ); return value; } @@ -359,7 +355,7 @@ class _ApiService implements ApiService { data: _data); final value = BaseData.fromJson( _result.data, - (json) => json == null ? null :json as dynamic, + (json) => json == null ? null : json as dynamic, ); return value; } @@ -592,9 +588,11 @@ class _ApiService implements ApiService { data: _data); final value = BaseData>.fromJson( _result.data, - (json) => (json as List) - .map((i) => Store.fromJson(i as Map)) - .toList()); + (json) => ((json ?? "") == "") + ? null + : (json as List) + .map((i) => Store.fromJson(i as Map)) + .toList()); return value; } @@ -885,10 +883,12 @@ class _ApiService implements ApiService { data: _data); final value = BaseData>.fromJson( _result.data, - (json) => ((json??"") == "")?null:PageInfo.fromJson( - json, - (json) => OrderInfo.fromJson(json), - ), + (json) => ((json ?? "") == "") + ? null + : PageInfo.fromJson( + json, + (json) => OrderInfo.fromJson(json), + ), ); return value; } @@ -1031,6 +1031,46 @@ class _ApiService implements ApiService { return value; } + @override + Future captchaGet(param) async { + ArgumentError.checkNotNull(param, 'param'); + const _extra = {}; + final queryParameters = {}; + final _data = {}; + _data.addAll(param ?? {}); + final _result = await _dio.request>('/captcha/get', + queryParameters: queryParameters, + options: RequestOptions( + method: 'POST', + headers: {}, + extra: _extra, + baseUrl: baseUrl), + data: _data); + final value = + (_result.data['repCode'] != '0000' || _result.data['repData'] == null) + ? null + : ClickWordCaptchaModel.fromMap(_result.data['repData']); + return value; + } + + @override + Future captchaCheck(param) async { + ArgumentError.checkNotNull(param, 'param'); + const _extra = {}; + final queryParameters = {}; + final _data = {}; + _data.addAll(param ?? {}); + final _result = await _dio.request>('/captcha/check', + queryParameters: queryParameters, + options: RequestOptions( + method: 'POST', + headers: {}, + extra: _extra, + baseUrl: baseUrl), + data: _data); + return (_result.data['repCode'] != '0000' || _result.data['repData'] == null || !_result.data['repData']['result']); + } + @override Future> queryMsg(id) async { ArgumentError.checkNotNull(id, 'id'); @@ -1272,7 +1312,7 @@ class _ApiService implements ApiService { data: _data); final value = BaseData.fromJson( _result.data, - (json) => json==null?null:(json as String), + (json) => json == null ? null : (json as String), ); return value; } @@ -1295,7 +1335,7 @@ class _ApiService implements ApiService { data: _data); final value = BaseData.fromJson( _result.data, - (json) => (json??"")=="" ? null :(json as bool), + (json) => (json ?? "") == "" ? null : (json as bool), ); return value; } @@ -1881,7 +1921,8 @@ class _ApiService implements ApiService { const _extra = {}; final queryParameters = {}; final _data = {}; - final _result = await _dio.request>('coupon/detail/$memberCouponId', + final _result = await _dio.request>( + 'coupon/detail/$memberCouponId', queryParameters: queryParameters, options: RequestOptions( method: 'GET', @@ -2018,7 +2059,7 @@ class _ApiService implements ApiService { data: _data); final value = BaseData.fromJson( _result.data, - (json) => HomeRank.fromJson(json), + (json) => HomeRank.fromJson(json), ); return value; } @@ -2039,7 +2080,7 @@ class _ApiService implements ApiService { data: _data); final value = BaseData.fromJson( _result.data, - (json) => json as dynamic, + (json) => json as dynamic, ); return value; } @@ -2051,7 +2092,8 @@ class _ApiService implements ApiService { final queryParameters = {}; final _data = {}; _data.addAll(param ?? {}); - final _result = await _dio.request>('/member/updatePayPwd', + final _result = await _dio.request>( + '/member/updatePayPwd', queryParameters: queryParameters, options: RequestOptions( method: 'POST', @@ -2061,7 +2103,7 @@ class _ApiService implements ApiService { data: _data); final value = BaseData.fromJson( _result.data, - (json) => json as dynamic, + (json) => json as dynamic, ); return value; } @@ -2073,7 +2115,8 @@ class _ApiService implements ApiService { final queryParameters = {}; final _data = {}; _data.addAll(param ?? {}); - final _result = await _dio.request>('/member/verifyByUpdatePayPwd', + final _result = await _dio.request>( + '/member/verifyByUpdatePayPwd', queryParameters: queryParameters, options: RequestOptions( method: 'POST', @@ -2083,7 +2126,7 @@ class _ApiService implements ApiService { data: _data); final value = BaseData.fromJson( _result.data, - (json) => json as dynamic, + (json) => json as dynamic, ); return value; } @@ -2093,8 +2136,7 @@ class _ApiService implements ApiService { const _extra = {}; final queryParameters = {}; final _data = {}; - final _result = await _dio.request>( - '/vipCard/index', + final _result = await _dio.request>('/vipCard/index', queryParameters: queryParameters, options: RequestOptions( method: 'GET', @@ -2104,11 +2146,30 @@ class _ApiService implements ApiService { data: _data); final value = BaseData.fromJson( _result.data, - (json) => VipCardHome.fromJson(json), + (json) => VipCardHome.fromJson(json), ); return value; } + @override + Future getIpInfo() async { + const _extra = {}; + final queryParameters = {}; + final _data = {}; + final _result = await _dio.request>('/ipJson.jsp', + queryParameters: queryParameters, + options: RequestOptions( + method: 'GET', + extra: _extra, + baseUrl: baseUrl, + responseType: ResponseType.bytes), + data: _data); + var ts = gbk.decode(_result.data); + final value = IpData.fromJson(jsonDecode( + ts.substring(ts.indexOf("{\"ip\":\"")).replaceAll(");}", ""))); + return value; + } + @override Future> orderVip(param) async { ArgumentError.checkNotNull(param, 'param'); @@ -2116,7 +2177,8 @@ class _ApiService implements ApiService { final queryParameters = {}; final _data = {}; _data.addAll(param ?? {}); - final _result = await _dio.request>('/vipCard/orderVip', + final _result = await _dio.request>( + '/vipCard/orderVip', queryParameters: queryParameters, options: RequestOptions( method: 'POST', @@ -2126,7 +2188,7 @@ class _ApiService implements ApiService { data: _data); final value = BaseData.fromJson( _result.data, - (json) => json as dynamic, + (json) => json as dynamic, ); return value; } @@ -2136,8 +2198,7 @@ class _ApiService implements ApiService { const _extra = {}; final queryParameters = {}; final _data = {}; - final _result = await _dio.request>( - '/raise/products', + final _result = await _dio.request>('/raise/products', queryParameters: queryParameters, options: RequestOptions( method: 'GET', @@ -2147,7 +2208,7 @@ class _ApiService implements ApiService { data: _data); final value = BaseData>.fromJson( _result.data, - (json) => (json as List) + (json) => (json as List) .map( (i) => FarmersList.fromJson(i as Map)) .toList()); @@ -2161,7 +2222,8 @@ class _ApiService implements ApiService { final queryParameters = {}; final _data = {}; _data.addAll(param ?? {}); - final _result = await _dio.request>('/auth/changePhone', + final _result = await _dio.request>( + '/auth/changePhone', queryParameters: queryParameters, options: RequestOptions( method: 'POST', @@ -2171,7 +2233,7 @@ class _ApiService implements ApiService { data: _data); final value = BaseData.fromJson( _result.data, - (json) => json as dynamic, + (json) => json as dynamic, ); return value; } @@ -2193,7 +2255,7 @@ class _ApiService implements ApiService { data: _data); final value = BaseData.fromJson( _result.data, - (json) => json as dynamic, + (json) => json as dynamic, ); return value; } @@ -2215,9 +2277,8 @@ class _ApiService implements ApiService { data: _data); final value = BaseData>.fromJson( _result.data, - (json) => (json as List) - .map( - (i) => Store.fromJson(i as Map)) + (json) => (json as List) + .map((i) => Store.fromJson(i as Map)) .toList()); return value; } diff --git a/lib/setting/account_security_page.dart b/lib/setting/account_security_page.dart index bb9e859d..50ee2cf4 100644 --- a/lib/setting/account_security_page.dart +++ b/lib/setting/account_security_page.dart @@ -26,7 +26,7 @@ class _AccountSecurityPage extends State { @override void initState() { super.initState(); - EasyLoading.show(status: S.current.zhengzaijiazai); + EasyLoading.show(status: S.current.zhengzaijiazai,maskType: EasyLoadingMaskType.black); SharedPreferences.getInstance().then((value) => { apiService = ApiService(Dio(), context: context, token: value.getString("token"),), diff --git a/lib/setting/binding_phone_page.dart b/lib/setting/binding_phone_page.dart index b9de973d..d9f21804 100644 --- a/lib/setting/binding_phone_page.dart +++ b/lib/setting/binding_phone_page.dart @@ -14,6 +14,7 @@ import 'package:huixiang/utils/font_weight.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import '../login/captcha/block_puzzle_captcha.dart'; import '../view_widget/border_text.dart'; class BindingPhonePage extends StatefulWidget { @@ -42,6 +43,8 @@ class _BindingPhonePage extends State { Timer _timer; UserInfo userInfo; int phoneState = 1; + String mobile; + String newMobile; @override void initState() { @@ -114,16 +117,6 @@ class _BindingPhonePage extends State { ///验证验证码 verificationCode() async { - var mobile = _controllerPhone.text; - if (mobile == "" && phoneState == 1) { - SmartDialog.showToast(S.of(context).qingshurushoujihao, alignment: Alignment.center); - return; - } - var newMobile = _controllerNewPhone.text; - if (newMobile == "" && phoneState == 2) { - SmartDialog.showToast(S.of(context).qingshurushoujihao, alignment: Alignment.center); - return; - } if (apiService == null) { SharedPreferences value = await SharedPreferences.getInstance(); apiService = ApiService(Dio(), @@ -466,7 +459,22 @@ class _BindingPhonePage extends State { alignment: Alignment.bottomCenter, child: InkWell( onTap: (){ - verificationCode(); + mobile = _controllerPhone.text; + if (mobile == "" && phoneState == 1) { + SmartDialog.showToast(S.of(context).qingshurushoujihao, alignment: Alignment.center); + return; + } + newMobile = _controllerNewPhone.text; + if (newMobile == "" && phoneState == 2) { + SmartDialog.showToast(S.of(context).qingshurushoujihao, alignment: Alignment.center); + return; + } + if(mobile != (userInfo?.phone??"")){ + SmartDialog.showToast("手机号码不正确", + alignment: Alignment.center); + return ; + } + loadingBlockPuzzle(context); }, child: BorderText( text: btnText, @@ -691,7 +699,17 @@ class _BindingPhonePage extends State { alignment: Alignment.bottomCenter, child: InkWell( onTap:(){ - verificationCode(); + mobile = _controllerPhone.text; + if (mobile == "" && phoneState == 1) { + SmartDialog.showToast(S.of(context).qingshurushoujihao, alignment: Alignment.center); + return; + } + newMobile = _controllerNewPhone.text; + if (newMobile == "" && phoneState == 2) { + SmartDialog.showToast(S.of(context).qingshurushoujihao, alignment: Alignment.center); + return; + } + loadingBlockPuzzle(context); }, child: BorderText( text: btnText, @@ -803,4 +821,23 @@ class _BindingPhonePage extends State { ), ); } + + //滑动拼图 + loadingBlockPuzzle(BuildContext context, + {barrierDismissible = true}) { + showDialog( + context: context, + barrierDismissible: barrierDismissible, + builder: (BuildContext context) { + return BlockPuzzleCaptchaPage( + onSuccess: (v) { + verificationCode(); + }, + onFail: () { + print("onFail"); + }, + ); + }, + ); + } } diff --git a/lib/setting/logout_ing.dart b/lib/setting/logout_ing.dart index f097aea4..0a9f2bdf 100644 --- a/lib/setting/logout_ing.dart +++ b/lib/setting/logout_ing.dart @@ -17,6 +17,7 @@ import 'package:huixiang/view_widget/my_appbar.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import '../login/captcha/block_puzzle_captcha.dart'; import '../main.dart'; class LogoutIng extends StatefulWidget { @@ -73,16 +74,20 @@ class _LogoutIng extends State { } if (_sendCodeStatus != 0) return; - if (apiService == null) { - SharedPreferences value = await SharedPreferences.getInstance(); - apiService = ApiService( - Dio(), - context: context, - token: value.getString("token"), - showLoading: true - ); + loadingBlockPuzzle(context); } - BaseData baseData = await apiService.sendVerify("+86",mobile).catchError((onError) {}); + + sendProving(v) async{ + if (apiService == null) { + SharedPreferences value = await SharedPreferences.getInstance(); + apiService = ApiService( + Dio(), + context: context, + token: value.getString("token"), + showLoading: true + ); + } + BaseData baseData = await apiService.sendVerify({"areaCode": "+86", "mobile": phoneController.text, "verification": v}).catchError((onError) {}); if (baseData != null && baseData.isSuccess) { countdown(); SmartDialog.showToast(baseData.data, @@ -497,4 +502,23 @@ class _LogoutIng extends State { // xgFlutterPlugin.stopXg(); // } } + + //滑动拼图 + loadingBlockPuzzle(BuildContext context, + {barrierDismissible = true}) { + showDialog( + context: context, + barrierDismissible: barrierDismissible, + builder: (BuildContext context) { + return BlockPuzzleCaptchaPage( + onSuccess: (v) { + sendProving(v); + }, + onFail: () { + print("onFail"); + }, + ); + }, + ); + } } diff --git a/lib/setting/platform_code_page.dart b/lib/setting/platform_code_page.dart index 713bf933..7a61e7a4 100644 --- a/lib/setting/platform_code_page.dart +++ b/lib/setting/platform_code_page.dart @@ -15,6 +15,8 @@ import 'package:huixiang/view_widget/pay_selected_dialog.dart'; import 'package:pin_input_text_field/pin_input_text_field.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import '../login/captcha/block_puzzle_captcha.dart'; + class PlatformCodePage extends StatefulWidget { final Map arguments; @@ -189,7 +191,7 @@ class _PlatformCodePage extends State { GestureDetector( onTap: () { setState(() { - sendCode(); + loadingBlockPuzzle(context); }); }, child: Container( @@ -308,4 +310,23 @@ class _PlatformCodePage extends State { ), ); } + + //滑动拼图 + loadingBlockPuzzle(BuildContext context, + {barrierDismissible = true}) { + showDialog( + context: context, + barrierDismissible: barrierDismissible, + builder: (BuildContext context) { + return BlockPuzzleCaptchaPage( + onSuccess: (v) { + sendCode(); + }, + onFail: () { + print("onFail"); + }, + ); + }, + ); + } } diff --git a/lib/setting/setting_page.dart b/lib/setting/setting_page.dart index 3f513c9f..c70a0929 100644 --- a/lib/setting/setting_page.dart +++ b/lib/setting/setting_page.dart @@ -175,7 +175,7 @@ class _SettingPage extends State { height: 16.h, ), GestureDetector( - child: settingSingleItem("注销账号"), + child: settingSingleItem(S.of(context).zhuxiaozhanghao), onTap: () { Navigator.of(context).pushNamed('/router/logout_page'); }, diff --git a/lib/setting/treaty_page.dart b/lib/setting/treaty_page.dart index a3c2ec26..cd44bac6 100644 --- a/lib/setting/treaty_page.dart +++ b/lib/setting/treaty_page.dart @@ -23,7 +23,7 @@ class _TreatyPage extends State { @override void initState() { super.initState(); - EasyLoading.show(status: S.current.zhengzaijiazai); + EasyLoading.show(status: S.current.zhengzaijiazai,maskType: EasyLoadingMaskType.black); // if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView(); // if (Platform.isIOS) WebView.platform = CupertinoWebView(); } diff --git a/lib/setting/user_service_page.dart b/lib/setting/user_service_page.dart index 83e6e9d7..95c1316c 100644 --- a/lib/setting/user_service_page.dart +++ b/lib/setting/user_service_page.dart @@ -25,7 +25,7 @@ class _UserServicePage extends State with WidgetsBindingObserve void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); - EasyLoading.show(status: S.current.zhengzaijiazai); + EasyLoading.show(status: S.current.zhengzaijiazai,maskType: EasyLoadingMaskType.black); if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView(); if (Platform.isIOS) WebView.platform = CupertinoWebView(); } diff --git a/lib/settlement/settlement.dart b/lib/settlement/settlement.dart index b722a1bf..9aef543d 100644 --- a/lib/settlement/settlement.dart +++ b/lib/settlement/settlement.dart @@ -140,7 +140,7 @@ class _Settlement extends State { storeId: storeId, showLoading: false); queryMemberInfo(); - if (promotions != null && promotions != "" && tableId <= 0) { + if (widget.arguments["pid"] != null && widget.arguments["pid"] != "" && tableId <= 0) { queryOrderInfo( address != null ? address.id : null, ((storeInfo?.pickupType?.dineInTakeStatus ?? false) == true && @@ -155,13 +155,13 @@ class _Settlement extends State { productSkuId ?? "", actProductId ?? "", actProductSkuId ?? "", - "ACTIVITY", + "AUTO", // useVipPriceSelect, // useBenefitSelect, count1, payChannel, tableId); - } else if (coupons != null && coupons != "" && tableId <= 0) { + } else if ( widget.arguments["cid"] != null && widget.arguments["cid"] != "" && tableId <= 0) { queryOrderInfo( address != null ? address.id : null, ((storeInfo?.pickupType?.dineInTakeStatus ?? false) == true && @@ -170,13 +170,13 @@ class _Settlement extends State { selectedBtn != 2) ? diningStatus : selectedBtn, - widget.arguments["cid"], + widget.arguments["cid"]??0, 0, productId ?? 0, productSkuId ?? "", actProductId ?? "", actProductSkuId ?? "", - "COUPON", + "AUTO", // useVipPriceSelect, // useBenefitSelect, count1, @@ -228,7 +228,7 @@ class _Settlement extends State { payChannel, tableId) async { try { - EasyLoading.show(status: S.current.zhengzaijiazai); + EasyLoading.show(status: S.current.zhengzaijiazai,maskType: EasyLoadingMaskType.black); BaseData baseData = await minService.getOrderInfo({ "addressId": addressId, @@ -329,7 +329,7 @@ class _Settlement extends State { ///查看订单详情 queryOrderDetails(id) async { - EasyLoading.show(status: S.current.zhengzaijiazai); + EasyLoading.show(status: S.current.zhengzaijiazai,maskType: EasyLoadingMaskType.black); BaseData baseData = await minService.getOrderDetails({ "id": pageType != null ? widget.arguments["orderId"] : id ?? parentId, }).catchError((error) {}); @@ -632,7 +632,7 @@ class _Settlement extends State { print("error: $error"); }); if (baseData != null && baseData.isSuccess) { - EasyLoading.show(status: S.current.zhengzaijiazai); + EasyLoading.show(status: S.current.zhengzaijiazai,maskType: EasyLoadingMaskType.black); placeOrder = true; this.downOrder = DownOrder.fromJson(baseData.data); querySettlement(); @@ -1383,7 +1383,7 @@ class _Settlement extends State { 0, (settleOrderInfo.isRaise || payChannel == 5) ? "" - : promotion?.id ?? productId, + : widget.arguments["pid"] ?? (promotion?.id ?? productId), productSkuId ?? "", actProductId ?? "", actProductSkuId ?? "", diff --git a/lib/settlement/settlement_view/pay_method.dart b/lib/settlement/settlement_view/pay_method.dart index a97f1bb5..dac2da36 100644 --- a/lib/settlement/settlement_view/pay_method.dart +++ b/lib/settlement/settlement_view/pay_method.dart @@ -287,9 +287,7 @@ class _PayMethod extends State { ), ), if(mRaiseMoney !="0" && (widget.tableId > 0 ? !(widget?.minOrderInfo?.isRaise ?? false) : !(widget?.settleOrderInfo?.isRaise ?? false))) - SizedBox( - height: 10, - ), + if(widget.tableId > 0 ? !(widget?.minOrderInfo?.isRaise ?? false) : !(widget?.settleOrderInfo?.isRaise ?? false)) GestureDetector( behavior: HitTestBehavior.opaque, diff --git a/lib/store/shop_details_page.dart b/lib/store/shop_details_page.dart index c2285615..51731ef2 100644 --- a/lib/store/shop_details_page.dart +++ b/lib/store/shop_details_page.dart @@ -94,7 +94,7 @@ class _ShopDetailsPage extends State { /// 查询店铺信息 queryStoreInfo() async { - EasyLoading.show(status: S.current.zhengzaijiazai); + EasyLoading.show(status: S.current.zhengzaijiazai,maskType: EasyLoadingMaskType.black); SharedPreferences value = await SharedPreferences.getInstance(); if (apiService == null) apiService = ApiService( @@ -321,7 +321,7 @@ class _ShopDetailsPage extends State { ///选规格 _queryMiNiDetail(String id, int count) async { - EasyLoading.show(status: S.current.zhengzaijiazai); + EasyLoading.show(status: S.current.zhengzaijiazai,maskType: EasyLoadingMaskType.black); if (count < 0) { shopCarGoods.shoppingCartSkuItemList.forEach((element) { if (element.productId == id) { diff --git a/lib/store/shopping/activity_prefecture_details.dart b/lib/store/shopping/activity_prefecture_details.dart index c3d645ed..743cb5af 100644 --- a/lib/store/shopping/activity_prefecture_details.dart +++ b/lib/store/shopping/activity_prefecture_details.dart @@ -95,7 +95,7 @@ class _ActivityPrefectureDetails extends State { /// 小程序登录 minLogin(SharedPreferences shared) async { - EasyLoading.show(status: S.of(context).zhengzaijiazai); + EasyLoading.show(status: S.of(context).zhengzaijiazai,maskType: EasyLoadingMaskType.black); apiService = ApiService( Dio(), context: context, diff --git a/lib/store/shopping/shopping_goods_details.dart b/lib/store/shopping/shopping_goods_details.dart index 970ef188..60e8fb5e 100644 --- a/lib/store/shopping/shopping_goods_details.dart +++ b/lib/store/shopping/shopping_goods_details.dart @@ -116,7 +116,7 @@ class _ShoppingGoodsDetails extends State { /// 小程序登录 minLogin(SharedPreferences shared) async { - EasyLoading.show(status: S.of(context).zhengzaijiazai); + EasyLoading.show(status: S.of(context).zhengzaijiazai,maskType: EasyLoadingMaskType.black); apiService = ApiService( Dio(), context: context, diff --git a/lib/store/shopping/shopping_mall_home.dart b/lib/store/shopping/shopping_mall_home.dart index b761fedf..0de56f71 100644 --- a/lib/store/shopping/shopping_mall_home.dart +++ b/lib/store/shopping/shopping_mall_home.dart @@ -55,7 +55,7 @@ class _ShoppingMallHome extends State /// 小程序登录 minLogin(SharedPreferences shared) async { - EasyLoading.show(status: S.of(context).zhengzaijiazai); + EasyLoading.show(status: S.of(context).zhengzaijiazai,maskType: EasyLoadingMaskType.black); apiService = ApiService( Dio(), context: context, diff --git a/lib/store/store_order.dart b/lib/store/store_order.dart index b7b60ce2..b56907f8 100644 --- a/lib/store/store_order.dart +++ b/lib/store/store_order.dart @@ -97,12 +97,13 @@ class _StoreOrderPage extends State /// 小程序登录 minLogin(SharedPreferences shared) async { - EasyLoading.show(status: S.of(context).zhengzaijiazai); + EasyLoading.show( + status: S.of(context).zhengzaijiazai, + maskType: EasyLoadingMaskType.black); apiService = ApiService( Dio(), context: context, token: shared.getString('token'), - showLoading: true, ); apiService.minLogin(storeId).catchError((onError) { SmartDialog.showToast(AppUtils.dioErrorTypeToString(onError.type), @@ -128,8 +129,6 @@ class _StoreOrderPage extends State storeId: storeId, ); - EasyLoading.dismiss(); - queryMemberInfo(); queryShopCar().then((value) { @@ -207,7 +206,6 @@ class _StoreOrderPage extends State setState(() {}); } } - EasyLoading.dismiss(); } RefreshController refreshController; @@ -247,7 +245,7 @@ class _StoreOrderPage extends State context), sliver: SliverAppBar( expandedHeight: (storeInfo != null && - storeInfo.couponVOList != null) + storeInfo.couponVOList != null) ? 400.h : 395.h, floating: false, @@ -330,7 +328,10 @@ class _StoreOrderPage extends State CrossAxisAlignment.start, children: [ ///门店信息 - StoreInfoView(storeInfo), + StoreInfoView( + storeInfo, + widget.arguments["distance"], + ), // Padding(padding:EdgeInsets.only(left: 14.w), // child: Text( // S.of(context).diandan, @@ -658,9 +659,8 @@ class _StoreOrderPage extends State "shoppingCart": shopCarGoods, "numberOfPeople": numberOfPeople, "distance": widget.arguments["distance"], - "vipLevelName": memberVo?.memberRankVo?.rankName ??"", + "vipLevelName": memberVo?.memberRankVo?.rankName ?? "", "isVips": memberVo?.isVip ?? false, - "distance": widget.arguments["distance"], "subscribeParam": miNiDetail?.subscribeParam, }, ); @@ -757,7 +757,8 @@ class _StoreOrderPage extends State ///选规格 _queryMiNiDetail(String id, int count) async { - EasyLoading.show(status: S.current.zhengzaijiazai); + EasyLoading.show( + status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black); if (count < 0) { shopCarGoods.shoppingCartSkuItemList.forEach((element) async { if (element.productId == id) { @@ -1058,17 +1059,17 @@ class _Title extends State { double maxScrollExtent = widget.controller.position.maxScrollExtent; double alphaHeight = (kToolbarHeight) / 2; double alphaProgress = maxScrollExtent - widget.controller.offset; - double alphatemp = 0; + double alphaTemp = 0; if (alphaProgress <= 1) { - alphatemp = 1; + alphaTemp = 1; } else if (alphaProgress <= alphaHeight) { - alphatemp = + alphaTemp = (((alphaHeight - alphaProgress) / alphaHeight) > 0.5) ? 1 : 0; } else { - alphatemp = 0; + alphaTemp = 0; } - if (alpha != alphatemp && mounted) { - alpha = alphatemp; + if (alpha != alphaTemp && mounted) { + alpha = alphaTemp; print("object: $alpha"); widget.scrollChange(alpha); setState(() {}); @@ -1080,14 +1081,16 @@ class _Title extends State<Title> { Widget build(BuildContext context) { return Container( margin: EdgeInsets.only(bottom: 38.h), - child: Text( - widget.title ?? "", - style: TextStyle( - color: Colors.black.withOpacity(alpha), - fontWeight: FontWeight.bold, - fontSize: 18.sp, - ), - ), + child: alpha == 0 + ? null + : Text( + widget.title ?? "", + style: TextStyle( + color: Colors.black, + fontWeight: FontWeight.bold, + fontSize: 18.sp, + ), + ), ); } } diff --git a/lib/store/store_view/product_sku.dart b/lib/store/store_view/product_sku.dart index 45144057..08902b3e 100644 --- a/lib/store/store_view/product_sku.dart +++ b/lib/store/store_view/product_sku.dart @@ -244,7 +244,7 @@ class _ProductSku extends State<ProductSku> { false) == false) { _isTapEd = true; - EasyLoading.show(status: S.current.zhengzaijiazai); + EasyLoading.show(status: S.current.zhengzaijiazai,maskType: EasyLoadingMaskType.black); await widget.reduce(widget.miNiDetail, selectSkus); } count -= 1; @@ -275,7 +275,7 @@ class _ProductSku extends State<ProductSku> { false) == false) { _isTapEd = true; - EasyLoading.show(status: S.current.zhengzaijiazai); + EasyLoading.show(status: S.current.zhengzaijiazai,maskType: EasyLoadingMaskType.black); if (count == 1 && realCount == 0) await widget.addShopCar( widget.miNiDetail, selectSkus, 2); diff --git a/lib/store/store_view/shop_goods.dart b/lib/store/store_view/shop_goods.dart index 3baaa943..3c0fede4 100644 --- a/lib/store/store_view/shop_goods.dart +++ b/lib/store/store_view/shop_goods.dart @@ -359,7 +359,7 @@ class _ShopGoods extends State<ShopGoods> { // SmartDialog.showToast("库存不足", // alignment: Alignment.center); // } else - if (_jumpType == -1) + if (_jumpType == -1) queryMiNiDetail(widget.productListBean.id); else if (_jumpType == 0) widget.add(widget.shoppingCartSkuItemListBean); @@ -497,6 +497,7 @@ class _ShopGoods extends State<ShopGoods> { SizedBox( height: 4.h, ), + ///VIP价格(暂时弃用) // if (widget.productListBean.vipPrice != null) // Row( @@ -645,9 +646,12 @@ class _ShopGoods extends State<ShopGoods> { // 新版桌子码跳转 // http://miniscan.lotus-wallet.com/placeorder?tenant_code=1194&table_id=1669609340031467520&store_id=1637659387134738432 Uri uri = Uri.parse(result); - String tableId = uri.queryParameters["tableId"] ?? uri.queryParameters["table_id"]; - String tenantCode = uri.queryParameters["tenantCode"] ?? uri.queryParameters["tenant_code"]; - String shopId = uri.queryParameters["shopId"] ?? uri.queryParameters["store_id"]; + String tableId = + uri.queryParameters["tableId"] ?? uri.queryParameters["table_id"]; + String tenantCode = uri.queryParameters["tenantCode"] ?? + uri.queryParameters["tenant_code"]; + String shopId = + uri.queryParameters["shopId"] ?? uri.queryParameters["store_id"]; if (tableId != null && tableId != "" && tenantCode != null && diff --git a/lib/store/store_view/store_header.dart b/lib/store/store_view/store_header.dart index baebe3d0..79214b12 100644 --- a/lib/store/store_view/store_header.dart +++ b/lib/store/store_view/store_header.dart @@ -43,7 +43,7 @@ class StoreHeader extends SliverPersistentHeaderDelegate { child: Column( children: [ ///门店信息 - StoreInfoView(storeInfo), + StoreInfoView(storeInfo,0), ///门店对应优惠券 if (storeInfo != null && storeInfo.couponVOList != null) diff --git a/lib/store/store_view/store_info.dart b/lib/store/store_view/store_info.dart index ca817aef..5aff71d7 100644 --- a/lib/store/store_view/store_info.dart +++ b/lib/store/store_view/store_info.dart @@ -11,8 +11,9 @@ import 'package:url_launcher/url_launcher.dart'; class StoreInfoView extends StatefulWidget { final StoreInfo storeInfo; + final double distance; - StoreInfoView(this.storeInfo); + StoreInfoView(this.storeInfo,this.distance); @override State<StatefulWidget> createState() { @@ -172,13 +173,14 @@ class _StoreInfoView extends State<StoreInfoView> { arguments: { "lat": widget.storeInfo.latitude, "lng": widget.storeInfo.longitude, - "storeName": widget.storeInfo.storeName, + "storeInfo":widget.storeInfo, + "distance":widget.distance }, ); }, child:Container( color: Colors.transparent, - padding:EdgeInsets.only(right: 8.w) , + padding:EdgeInsets.only(right: 8.w,bottom: 16.h) , child: Image.asset( "assets/image/icon_union_location.webp", width: 20, @@ -190,28 +192,34 @@ class _StoreInfoView extends State<StoreInfoView> { child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { - Navigator.of(context).pushNamed( - '/router/location_map', - arguments: { - "lat": widget.storeInfo.latitude, - "lng": widget.storeInfo.longitude, - "storeName": widget.storeInfo.storeName, - }, - ); + if(widget.storeInfo.longitude != null && widget.storeInfo.latitude != null){ + Navigator.of(context).pushNamed( + '/router/location_map', + arguments: { + "lat": widget.storeInfo.latitude, + "lng": widget.storeInfo.longitude, + "storeInfo":widget.storeInfo, + "distance":widget.distance + }, + ); + }else{ + return; + } }, - child: Text( - "${S.of(context).dizhi}:${widget.storeInfo != null ? widget.storeInfo.address : ""}", - maxLines: 2, - textAlign: TextAlign.justify, - style: TextStyle( - color: Color(0xFF353535), - fontWeight: MyFontWeight.regular, - fontSize: 12.sp, + child:Padding(padding: EdgeInsets.only(bottom: 16.h,), + child: Text( + "${S.of(context).dizhi}:${widget.storeInfo != null ? widget.storeInfo.address : ""}", + maxLines: 2, + textAlign: TextAlign.justify, + style: TextStyle( + color: Color(0xFF353535), + fontWeight: MyFontWeight.regular, + fontSize: 12.sp, + ), ), ), ), ), - if((widget?.storeInfo?.tel ?? "") != "") GestureDetector( behavior: HitTestBehavior.opaque, @@ -219,7 +227,7 @@ class _StoreInfoView extends State<StoreInfoView> { showCallMobile(); }, child: Container( - padding:EdgeInsets.only(left: 16.w,right: 8.w) , + padding:EdgeInsets.only(left: 16.w,right: 8.w,bottom: 16.h) , child: Image.asset( "assets/image/icon_union_call.webp", width: 24, @@ -233,7 +241,6 @@ class _StoreInfoView extends State<StoreInfoView> { width: double.infinity, height: 1, color: Color(0xFFF4F5F2), - margin: EdgeInsets.only(top: 16), ) ], ), @@ -291,8 +298,8 @@ class _StoreInfoView extends State<StoreInfoView> { text: "$e", backgroup: Color(0xFFFF7A1A), padding: EdgeInsets.only( - left: 2.w, - right: 2.w, + left: 4.w, + right: 4.w, ), fontSize: 10.sp, textColor: Colors.white, diff --git a/lib/union/location_map_page.dart b/lib/union/location_map_page.dart index d63e223c..ec1d52a6 100644 --- a/lib/union/location_map_page.dart +++ b/lib/union/location_map_page.dart @@ -1,15 +1,30 @@ +import 'dart:convert'; +import 'dart:io'; import 'dart:ui'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart'; import 'package:flutter_baidu_mapapi_map/flutter_baidu_mapapi_map.dart'; +import 'package:flutter_baidu_mapapi_search/flutter_baidu_mapapi_search.dart'; +import 'package:flutter_baidu_mapapi_utils/flutter_baidu_mapapi_utils.dart'; import 'package:flutter_bmflocation/flutter_bmflocation.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:huixiang/utils/flutter_utils.dart'; +import 'package:huixiang/utils/font_weight.dart'; import 'package:huixiang/utils/location.dart'; -import 'package:huixiang/view_widget/my_appbar.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import '../generated/l10n.dart'; +import '../retrofit/data/store_info.dart'; +import '../view_widget/custom_image.dart'; +import '../view_widget/location_tips.dart'; +import '../view_widget/round_button.dart'; class LocationMap extends StatefulWidget { - final Map<String, String> arguments; + final Map<String, dynamic> arguments; LocationMap({this.arguments}); @@ -19,27 +34,74 @@ class LocationMap extends StatefulWidget { } } -class _LocationMap extends State<LocationMap> { +class _LocationMap extends State<LocationMap> with WidgetsBindingObserver { + StoreInfo storeInfo; + int navigationState = 0; + double distance; + int navigationType = 0; + bool positionSorta = false; + String myAddress; + String myCity; + String hours; + String minutes; + String polylineId; + bool _isShowLocalTips = false; + @override void initState() { super.initState(); - - startLocation(); + WidgetsBinding.instance.addObserver(this); + storeInfo = widget.arguments["storeInfo"]; + distance = widget.arguments["distance"]; + getLocation(); } - void startLocation() { - Location.getInstance().startLocation(context, (BaiduLocation result) { - if (result != null && - result.latitude != null && - result.longitude != null) { - print("location: $result"); - myLatLng = BMFCoordinate(result.latitude, result.longitude); - AppUtils.coordConvert(myLatLng).then((value) { - this.myLatLng = value; - locationShow(); - }); + void getLocation() async { + bool powerFlag = false; + try { + Future.delayed(Duration(seconds: 5), () { + Location.getInstance().stopLocation(); + }); + powerFlag = await Location.getInstance().startLocation(context, + (BaiduLocation result) { + if (result != null && + result.latitude != null && + result.longitude != null) { + print("location: $result"); + myLatLng = BMFCoordinate(result.latitude, result.longitude); + myAddress = result.locationDetail; + myCity = result.city; + if (distance == null) calculate(); + // AppUtils.coordConvert(myLatLng).then((value) { + // this.myLatLng = value; + locationShow(); + // }); + Location.getInstance().stopLocation(); + } + }); + } finally { + if (!powerFlag) { + if (await Permission.locationWhenInUse.status.isGranted) { + getLocation(); + } else { + _isShowLocalTips = true; + } + // else { + // SmartDialog.showToast("您定位服务未开启,请前往系统设置中开启定位服务", + // alignment: Alignment.center); + // } } - }); + setState(() {}); + } + } + + calculate() async { + BMFCoordinate bmfCoordinate = BMFCoordinate( + double.tryParse(storeInfo.latitude), + double.tryParse(storeInfo.longitude), + ); + distance = double.tryParse( + await AppUtils.calculateDistance(bmfCoordinate, myLatLng, isMi: true)); } locationShow() { @@ -61,38 +123,1045 @@ class _LocationMap extends State<LocationMap> { @override void dispose() { - super.dispose(); + WidgetsBinding.instance.removeObserver(this); Location.getInstance().stopLocation(); + super.dispose(); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + if (state == AppLifecycleState.resumed) { + // 处理应用程序切换回前台的逻辑 + permissionSettings(); + } else if (state == AppLifecycleState.paused) { + // 处理应用程序切换到后台的逻辑 + } + } + + void permissionSettings() async { + if (_isShowLocalTips && await Permission.location.isGranted) { + _isShowLocalTips = false; + getLocation(); + } } @override Widget build(BuildContext context) { return Scaffold( - appBar: MyAppBar( - background: Color(0xFFF7F7F7), - title: widget.arguments["storeName"], - titleColor: Colors.black87, - titleSize: 18.sp, - leadingColor: Colors.black, + // appBar: MyAppBar( + // background: Color(0xFFF7F7F7), + // title: widget.arguments["storeName"], + // titleColor: Colors.black87, + // titleSize: 18.sp, + // leadingColor: Colors.black, + // ), + body: Stack( + children: [ + Stack( + children: [ + Column( + children: [ + Expanded( + child: Container( + //BMFMapWidget 组件会自动默认沾满全屏,并且挡住所有遮盖物 ,BMFTextureMapWidget不会强制遮盖其他控件。 + child: (Platform.isAndroid) + ? BMFTextureMapWidget( + mapOptions: BMFMapOptions( + center: BMFCoordinate( + double.tryParse(widget.arguments["lat"]), + double.tryParse(widget.arguments["lng"]), + ), + showZoomControl: false, + showMapScaleBar: false, + rotateEnabled: false, + zoomLevel: 15, + ), + onBMFMapCreated: onMapCreated, + ) + : BMFMapWidget( + mapOptions: BMFMapOptions( + center: BMFCoordinate( + double.tryParse(widget.arguments["lat"]), + double.tryParse(widget.arguments["lng"]), + ), + showZoomControl: false, + showMapScaleBar: false, + rotateEnabled: false, + zoomLevel: 15, + ), + onBMFMapCreated: onMapCreated, + )), + flex: 3, + ), + navigationState == 0 + ? Container( + height: 253.h, + padding: EdgeInsets.only( + top: 16.h, left: 16.w, right: 28.w), + decoration: BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Color(0x08213303), + offset: Offset(0, 2), + blurRadius: 4, + spreadRadius: 0, + ), + ], + borderRadius: BorderRadius.vertical( + top: Radius.circular(8), + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Row( + children: [ + Expanded( + child: Column( + children: [ + Text( + storeInfo?.storeName ?? "", + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 20.sp, + color: Color(0xFF0D0D0D), + fontWeight: MyFontWeight.medium, + ), + ), + Row( + children: [ + Text( + S.of(context).ren( + storeInfo != null + ? storeInfo + .perCapitaConsumption + : "", + ), + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 12.sp, + fontWeight: + MyFontWeight.regular, + color: Color(0xFF4D4D4D), + ), + ), + SizedBox( + width: 20.w, + ), + ]..addAll(itemServer( + storeInfo != null + ? storeInfo.businessService + : "")), + ), + Text( + S.of(context).yingyeshijian(storeInfo == + null + ? "" + : (storeInfo.openStartTime == + null && + storeInfo.openEndTime == + null) + ? S.of(context).quantian + : "${storeInfo.openStartTime.substring(0, storeInfo.openStartTime.lastIndexOf(":"))} " + "- ${storeInfo.openEndTime.substring(0, storeInfo.openEndTime.lastIndexOf(":"))}"), + style: TextStyle( + color: Color(0xFF4D4D4D), + fontWeight: MyFontWeight.medium, + fontSize: 12.sp, + ), + ), + ], + mainAxisAlignment: + MainAxisAlignment.spaceAround, + crossAxisAlignment: + CrossAxisAlignment.start, + ), + ), + MImage( + storeInfo != null ? storeInfo.logo : "", + width: 72.h, + height: 72.h, + fit: BoxFit.cover, + errorSrc: "assets/image/default_1.webp", + fadeSrc: "assets/image/default_1.webp", + ), + ], + ), + ), + Padding( + padding: EdgeInsets.only(bottom: 32.h), + child: Text( + "${storeInfo != null ? storeInfo.address : ""}", + maxLines: 2, + textAlign: TextAlign.justify, + style: TextStyle( + color: Color(0xFF353535), + fontWeight: MyFontWeight.regular, + fontSize: 12.sp, + ), + ), + ), + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + if (myLatLng == null) { + // onOpenBaiduMap(); + SmartDialog.showToast( + "您定位服务未开启,请前往系统设置中开启定位服务", + alignment: Alignment.center); + } else { + navigationState = 1; + if ((distance ?? 0) < 500) + navigationType = 1; + else if ((distance ?? 0) < 1500) + navigationType = 2; + else + navigationType = 4; + navigationPosition(); + } + }, + child: Container( + alignment: Alignment.center, + width: double.infinity, + padding: EdgeInsets.symmetric(vertical: 10.h), + margin: EdgeInsets.only(bottom: 30.h), + decoration: BoxDecoration( + color: Color(0xFF32A060), + borderRadius: BorderRadius.circular(23), + ), + child: Text( + "到这去", + style: TextStyle( + fontSize: 20.sp, + color: Colors.white, + fontWeight: MyFontWeight.medium, + ), + ), + ), + ) + ], + ), + ) + : navigationDistance(), + ], + ), + navigationState == 0 + ? GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + Navigator.of(context).pop(); + }, + child: Container( + height: 56.h, + margin: EdgeInsets.only( + top: MediaQuery.of(context).padding.top + 16.h, + left: 14.w, + right: 14.w), + padding: EdgeInsets.only(left: 12.w, right: 21.w), + decoration: BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Color(0x08213303), + offset: Offset(0, 2), + blurRadius: 4, + spreadRadius: 0, + ), + ], + borderRadius: BorderRadius.circular(6), + ), + child: Row( + children: [ + Icon( + Icons.arrow_back_ios, + color: Color(0xFF353535), + size: 24, + ), + Expanded( + child: Text( + storeInfo?.storeName ?? "", + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Color(0xFF0D0D0D), + fontSize: 18.sp, + fontWeight: MyFontWeight.regular, + ), + )) + ], + ), + ), + ) + : navigationBox(), + ], + ), + if (_isShowLocalTips) + Padding( + padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top), + child: LocationTips(() { + setState(() { + _isShowLocalTips = false; + }); + }), + ) + ], ), - body: Container( - //BMFMapWidget 组件会自动默认沾满全屏,并且挡住所有遮盖物 ,BMFTextureMapWidget不会强制遮盖其他控件。 - child:BMFMapWidget( - mapOptions: BMFMapOptions( - center: BMFCoordinate( - double.tryParse(widget.arguments["lat"]), - double.tryParse(widget.arguments["lng"]), + ); + } + + void onOpenBaiduMap() async { + launch( + "baidumap://map/marker?location=${storeInfo.latitude},${storeInfo.longitude}&title=${storeInfo.storeName}&content=${storeInfo.storeName}&traffic=on&src=andr.baidu.openAPIdemo&coord_type=gcj02"); + } + + //調取百度地圖APP + void onOpenBaiduMapRoute() async { + // 我的位置 + BMFCoordinate startCoord = BMFCoordinate( + positionSorta == false + ? myLatLng.latitude + : latLng.latitude, + positionSorta == false + ? myLatLng.longitude + : latLng.longitude); + String startName = ((positionSorta == false) ? "我的位置" : "终点"); + // 去的位置 + String endName = ((positionSorta == false) ? "终点" : "我的位置"); + BMFCoordinate endCoord = BMFCoordinate( + positionSorta == false + ? latLng.latitude + : myLatLng.latitude, + positionSorta == false + ? latLng.longitude + : myLatLng.longitude); + BMFOpenRouteOption routeOption = BMFOpenRouteOption( + startCoord: startCoord, + startName: startName, + endCoord: endCoord, + endName: endName, + routeType: navigationType == 1 + ? BMFOpenRouteType.WalkingRoute + : navigationType == 2 + ? BMFOpenRouteType.WalkingRoute + : navigationType == 3 + ? BMFOpenRouteType.TransitRoute + : BMFOpenRouteType.DrivingRoute, + appScheme: 'baidumapsdk_flutter://mapsdk.baidu.com', + // 指定返回自定义scheme + isSupportWeb: true); + BMFOpenErrorCode flag = + await BMFOpenMapUtils.openBaiduMapRoute(routeOption); + print('open - route - errorCode = $flag'); + } + + updateMapLine(List<BMFCoordinate> coordinates, int needHours, int needMinutes, + double needDistance) { + try { + //刪除之前的創建的點和綫 + _mapController.cleanAllMarkers(); + if (polylineId != null) _mapController.removeOverlay(polylineId); + + /// 创建polyline + BMFPolyline colorsPolyline = BMFPolyline( + // id: polylineOptions.hashCode.toString(), + coordinates: coordinates, + indexs: [0], + textures: [ + navigationType != 4 + ? 'assets/image/traffic_texture_unknown.png' + : 'assets/image/traffic_texture_smooth.png' + ], + width: Platform.isAndroid ? 16 : 10, + lineDashType: BMFLineDashType.LineDashTypeNone, + lineCapType: BMFLineCapType.LineCapButt, + lineJoinType: BMFLineJoinType.LineJoinRound); + polylineId = colorsPolyline.id; + + /// 添加polyline + _mapController.addPolyline(colorsPolyline); + var startBmfMarker = BMFMarker.icon( + position: BMFCoordinate( + coordinates.first.latitude, coordinates.first.longitude), + centerOffset: BMFPoint(0.5, 0.7), + enabled: false, + icon: "assets/image/icon_start.png", + draggable: false, + ); + _mapController.addMarker(startBmfMarker); + + var terminalBmfMarker = BMFMarker.icon( + position: BMFCoordinate( + coordinates.last.latitude, coordinates.last.longitude), + centerOffset: BMFPoint(0.5, 0.7), + enabled: false, + icon: "assets/image/icon_end.png", + draggable: false, + ); + _mapController.addMarker(terminalBmfMarker); + + double maxLatitude = 0, + minLatitude = 0, + maxLongitude = 0, + minLongitude = 0; + coordinates.forEach((element) { + if (element.latitude > maxLatitude) maxLatitude = element.latitude; + if (minLatitude == 0) + minLatitude = element.latitude; + else if (element.latitude < minLatitude) minLatitude = element.latitude; + + if (element.longitude > maxLongitude) maxLongitude = element.longitude; + if (minLongitude == 0) + minLongitude = element.longitude; + else if (element.longitude < minLongitude) + minLongitude = element.longitude; + }); + _mapController.setVisibleMapBounds( + BMFCoordinateBounds( + northeast: BMFCoordinate( + maxLatitude + ((maxLatitude - minLatitude) * 0.8), + maxLongitude + ((maxLongitude - minLongitude) / 2)), + southwest: BMFCoordinate( + minLatitude - ((maxLatitude - minLatitude) * 0.2), + minLongitude - ((maxLongitude - minLongitude) / 2))), + true); + + hours = needHours == 0 ? "" : "$needHours小时"; + minutes = needMinutes == 0 ? "" : "$needMinutes分钟"; + distance = needDistance; + } finally { + setState(() {}); + EasyLoading.dismiss(); + } + } + + navigationPosition() async { + EasyLoading.show( + status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black); + BMFPlanNode from = BMFPlanNode( + cityName: positionSorta == false ? myCity : (storeInfo?.city ?? ""), + name: positionSorta == false ? myAddress : storeInfo?.address ?? "", + pt: positionSorta == false + ? BMFCoordinate(myLatLng?.latitude ?? 0, myLatLng?.longitude ?? 0) + : latLng); + BMFPlanNode to = BMFPlanNode( + // cityName: positionSorta == false ? (storeInfo?.city ?? "") : myCity, + // name: positionSorta == false ? (storeInfo?.address ?? "") : myAddress, + pt: positionSorta == false + ? latLng + : BMFCoordinate(myLatLng?.latitude ?? 0, myLatLng?.longitude ?? 0)); + if (navigationType == 1) { + //步行 + BMFWalkingRoutePlanOption walkingRoutePlanOption = + BMFWalkingRoutePlanOption(from: from, to: to); + // 检索实例 + BMFWalkingRouteSearch walkingRouteSearch = BMFWalkingRouteSearch(); + // 检索回调 + walkingRouteSearch.onGetWalkingRouteSearchResult(callback: + (BMFWalkingRouteResult result, BMFSearchErrorCode errorCode) async { + if (errorCode == BMFSearchErrorCode.RESULT_NOT_FOUND) { + SmartDialog.showToast("该方案暂无可用的规划路线", alignment: Alignment.center); + EasyLoading.dismiss(); + return; + } else if (errorCode != BMFSearchErrorCode.NO_ERROR) { + SmartDialog.showToast("获取路线规划失败,请稍后再试", alignment: Alignment.center); + EasyLoading.dismiss(); + return; + } + print( + '`步行检索回调 errorCode = ${errorCode} \n result = ${result?.toMap()}'); + + /// 坐标点 + List<BMFCoordinate> coordinates = []; + result.routes.first.steps.forEach((e1) { + e1.points.forEach((e2) { + coordinates.add(BMFCoordinate(e2.latitude, e2.longitude)); + }); + }); + updateMapLine( + coordinates, + result.routes.first.duration.hours, + result.routes.first.duration.minutes, + result.routes.first.distance.toDouble()); + }); + bool flag = + await walkingRouteSearch.walkingRouteSearch(walkingRoutePlanOption); + } else if (navigationType == 2) { + //骑行 + BMFRidingRoutePlanOption ridingRoutePlanOption = + BMFRidingRoutePlanOption(from: from, to: to); + BMFRidingRouteSearch ridingRouteSearch = BMFRidingRouteSearch(); + ridingRouteSearch.onGetRidingRouteSearchResult(callback: + (BMFRidingRouteResult result, BMFSearchErrorCode errorCode) { + if (errorCode == BMFSearchErrorCode.RESULT_NOT_FOUND) { + SmartDialog.showToast("该方案暂无可用的规划路线", alignment: Alignment.center); + EasyLoading.dismiss(); + return; + } else if (errorCode != BMFSearchErrorCode.NO_ERROR) { + SmartDialog.showToast("获取路线规划失败,请稍后再试", alignment: Alignment.center); + EasyLoading.dismiss(); + return; + } + print( + '`骑行检索回调 errorCode = ${errorCode} \n result = ${result?.toMap()}'); + + /// 坐标点 + List<BMFCoordinate> coordinates = []; + result.routes.first.steps.forEach((e1) { + e1.points.forEach((e2) { + coordinates.add(BMFCoordinate(e2.latitude, e2.longitude)); + }); + }); + updateMapLine( + coordinates, + result.routes.first.duration.hours, + result.routes.first.duration.minutes, + result.routes.first.distance.toDouble()); + }); +// 发起检索 + bool flag = + await ridingRouteSearch.ridingRouteSearch(ridingRoutePlanOption); + } else if (navigationType == 3) { + //公交 + BMFTransitRoutePlanOption transitRoutePlanOption = + BMFTransitRoutePlanOption(from: from, to: to, city: '武汉市'); + BMFTransitRouteSearch transitRouteSearch = BMFTransitRouteSearch(); + transitRouteSearch.onGetTransitRouteSearchResult(callback: + (BMFTransitRouteResult result, BMFSearchErrorCode errorCode) { + if (errorCode == BMFSearchErrorCode.RESULT_NOT_FOUND) { + SmartDialog.showToast("该方案暂无可用的规划路线", alignment: Alignment.center); + EasyLoading.dismiss(); + return; + } else if (errorCode != BMFSearchErrorCode.NO_ERROR) { + SmartDialog.showToast("获取路线规划失败,请稍后再试", alignment: Alignment.center); + EasyLoading.dismiss(); + return; + } + print( + '`市内公交检索回调 errorCode = ${errorCode} \n result = ${result?.toMap()}'); + + /// 坐标点 + List<BMFCoordinate> coordinates = []; + result.routes.first.steps.forEach((e1) { + e1.points.forEach((e2) { + coordinates.add(BMFCoordinate(e2.latitude, e2.longitude)); + }); + }); + updateMapLine( + coordinates, + result.routes.first.duration.hours, + result.routes.first.duration.minutes, + result.routes.first.distance.toDouble()); + }); +// 发起检索 + bool flag = + await transitRouteSearch.transitRouteSearch(transitRoutePlanOption); + } else { + //驾车 + BMFDrivingRoutePlanOption drivingRoutePlanOption = + BMFDrivingRoutePlanOption(from: from, to: to); + BMFDrivingRouteSearch drivingRouteSearch = BMFDrivingRouteSearch(); + drivingRouteSearch.onGetDrivingRouteSearchResult(callback: + (BMFDrivingRouteResult result, BMFSearchErrorCode errorCode) { + if (errorCode == BMFSearchErrorCode.RESULT_NOT_FOUND) { + SmartDialog.showToast("该方案暂无可用的规划路线", alignment: Alignment.center); + EasyLoading.dismiss(); + return; + } else if (errorCode != BMFSearchErrorCode.NO_ERROR) { + SmartDialog.showToast("获取路线规划失败,请稍后再试", alignment: Alignment.center); + EasyLoading.dismiss(); + return; + } + print( + '驾车检索回调 errorCode = ${errorCode} \n result = ${result?.toMap()}'); + + /// 坐标点 + List<BMFCoordinate> coordinates = []; + result.routes.first.steps.forEach((e1) { + e1.points.forEach((e2) { + coordinates.add(BMFCoordinate(e2.latitude, e2.longitude)); + }); + }); + updateMapLine( + coordinates, + result.routes.first.duration.hours, + result.routes.first.duration.minutes, + result.routes.first.distance.toDouble()); + }); +// 发起检索 + bool flag = + await drivingRouteSearch.dringRouteSearch(drivingRoutePlanOption); + } + } + + Widget navigationBox() { + return Container( + height: 132.h, + margin: EdgeInsets.only( + top: MediaQuery.of(context).padding.top + 16.h, + left: 14.w, + right: 14.w), + padding: EdgeInsets.only(left: 12.w, right: 18.w, top: 8.h), + decoration: BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Color(0x08213303), + offset: Offset(0, 2), + blurRadius: 4, + spreadRadius: 0, + ), + ], + borderRadius: BorderRadius.circular(6), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + setState(() { + navigationState = 0; + }); + }, + child: Padding( + padding: EdgeInsets.only(top: 10.h, right: 10.w), + child: Icon( + Icons.arrow_back_ios, + color: Color(0xFF353535), + size: 24, + ), + ), + ), + Expanded( + child: Column( + children: [ + Container( + width: double.infinity, + decoration: BoxDecoration( + color: Color(0xFFF5F5F5), + borderRadius: BorderRadius.circular(6), + ), + padding: EdgeInsets.only( + top: 12.h, + bottom: 12.h, + left: 15.w, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only( + bottom: 14.h, + ), + child: Row( + children: [ + Container( + width: 4.h, + height: 4.h, + margin: EdgeInsets.only(right: 20.w), + decoration: BoxDecoration( + color: Color(0xFF32A060), + borderRadius: BorderRadius.circular(6), + ), + ), + Expanded( + child: Text( + positionSorta == false + ? "我的位置" + : (storeInfo?.storeName ?? ""), + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Color(0xFF0D0D0D), + fontSize: 14.sp, + fontWeight: MyFontWeight.semi_bold, + ), + )) + ], + ), + ), + Row( + children: [ + Container( + width: 4.h, + height: 4.h, + margin: EdgeInsets.only(right: 20.w), + decoration: BoxDecoration( + color: Color(0xFFFA5151), + borderRadius: BorderRadius.circular(6), + ), + ), + Expanded( + child: Text( + positionSorta == false + ? (storeInfo?.storeName ?? "") + : "我的位置", + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Color(0xFF0D0D0D), + fontSize: 14.sp, + fontWeight: MyFontWeight.semi_bold, + ), + )) + ], + ) + ], + )), + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + positionSorta = !positionSorta; + navigationPosition(); + }, + child: Container( + padding: EdgeInsets.only(right: 24.w), + child: Image.asset( + "assets/image/position_sort.webp", + fit: BoxFit.fill, + height: 16.h, + width: 14.w, + ), + ), + ) + ], + ), + ), + SizedBox( + height: 12.h, + ), + Row( + children: [ + Expanded( + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + navigationType = 4; + navigationPosition(); + }, + child: Container( + decoration: BoxDecoration( + color: navigationType == 4 + ? Color(0xFFE8FFF2) + : Colors.transparent, + borderRadius: BorderRadius.circular(23), + ), + padding: + EdgeInsets.symmetric(vertical: 5.h, horizontal: 13.w), + child: Row( + children: [ + if (navigationType == 4) + Image.asset( + "assets/image/icon_drive.webp", + fit: BoxFit.fill, + height: 16.h, + width: 14.w, + ), + Padding( + padding: EdgeInsets.only(left: 2.w), + child: Text( + "驾车", + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: navigationType == 4 + ? Color(0xFF32A060) + : Colors.black, + fontSize: 12.sp, + fontWeight: MyFontWeight.medium, + ), + ), + ) + ], + ), + ), + )), + Expanded( + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + navigationType = 3; + navigationPosition(); + }, + child: Container( + decoration: BoxDecoration( + color: navigationType == 3 + ? Color(0xFFE8FFF2) + : Colors.transparent, + borderRadius: BorderRadius.circular(23), + ), + padding: EdgeInsets.symmetric( + vertical: 5.h, horizontal: 13.w), + child: Row( + children: [ + if (navigationType == 3) + Image.asset( + "assets/image/icon_transit.webp", + fit: BoxFit.fill, + height: 16.h, + width: 14.w, + ), + Padding( + padding: EdgeInsets.only(left: 2.w), + child: Text( + "公交", + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: navigationType == 3 + ? Color(0xFF32A060) + : Colors.black, + fontSize: 12.sp, + fontWeight: MyFontWeight.medium, + ), + ), + ) + ], + ), + ))), + Expanded( + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + navigationType = 2; + navigationPosition(); + }, + child: Container( + decoration: BoxDecoration( + color: navigationType == 2 + ? Color(0xFFE8FFF2) + : Colors.transparent, + borderRadius: BorderRadius.circular(23), + ), + padding: EdgeInsets.symmetric( + vertical: 5.h, horizontal: 13.w), + child: Row( + children: [ + if (navigationType == 2) + Image.asset( + "assets/image/icon_by_bike.webp", + fit: BoxFit.fill, + height: 16.h, + width: 14.w, + ), + Padding( + padding: EdgeInsets.only(left: 2.w), + child: Text( + "骑行", + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: navigationType == 2 + ? Color(0xFF32A060) + : Colors.black, + fontSize: 12.sp, + fontWeight: MyFontWeight.medium, + ), + ), + ) + ], + ), + ))), + Expanded( + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + navigationType = 1; + navigationPosition(); + }, + child: Container( + decoration: BoxDecoration( + color: navigationType == 1 + ? Color(0xFFE8FFF2) + : Colors.transparent, + borderRadius: BorderRadius.circular(23), + ), + padding: EdgeInsets.symmetric( + vertical: 5.h, horizontal: 13.w), + child: Row( + children: [ + if (navigationType == 1) + Image.asset( + "assets/image/icon_walk.webp", + fit: BoxFit.fill, + height: 16.h, + width: 14.w, + ), + Padding( + padding: EdgeInsets.only(left: 2.w), + child: Text( + "步行", + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: navigationType == 1 + ? Color(0xFF32A060) + : Colors.black, + fontSize: 12.sp, + fontWeight: MyFontWeight.medium, + ), + ), + ) + ], + ), + ))), + ], + ) + ], + )) + ], + ), + ); + } + + Widget navigationDistance() { + return Container( + height: 173.h, + padding: EdgeInsets.only(top: 16.h, left: 16.w, right: 16.w), + decoration: BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Color(0x08213303), + offset: Offset(0, 2), + blurRadius: 4, + spreadRadius: 0, + ), + ], + borderRadius: BorderRadius.vertical( + top: Radius.circular(8), + ), + ), + child: Column( + // mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "${navigationType == 1 ? "步行" : navigationType == 2 ? "骑行" : navigationType == 3 ? "公交" : "驾车"}${(hours ?? "") + (minutes ?? "")}", + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 20.sp, + color: Color(0xFF0D0D0D), + fontWeight: MyFontWeight.bold, + ), + ), + Padding( + padding: EdgeInsets.only(left: 40.w), + child: Text( + (distance ?? 0) > 1000 + ? S.of(context).gongli( + ((distance ?? 0) / 1000 * 100).toInt() / 100.0) + : S + .of(context) + .mi(((distance ?? 0) * 100).toInt() / 100.0), + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 20.sp, + color: Color(0xFF0D0D0D), + fontWeight: MyFontWeight.bold, + ), + ), + ), + ], ), - showZoomControl: false, - showMapScaleBar: false, - zoomLevel: 12, ), - onBMFMapCreated: onMapCreated, - ) + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + setState(() { + navigationState = 1; + showMapSelect(); + }); + }, + child: Container( + alignment: Alignment.center, + width: double.infinity, + padding: EdgeInsets.symmetric(vertical: 10.h), + margin: EdgeInsets.only(bottom: 30.h), + decoration: BoxDecoration( + color: Color(0xFF32A060), + borderRadius: BorderRadius.circular(23), + ), + child: Text( + navigationType == 1 + ? "步行导航" + : navigationType == 2 + ? "骑行导航" + : navigationType == 3 + ? "公交导航" + : "驾车导航", + style: TextStyle( + fontSize: 20.sp, + color: Colors.white, + fontWeight: MyFontWeight.medium, + ), + ), + ), + ) + ], ), ); } + showMapSelect() { + showCupertinoModalPopup( + context: context, + builder: (context) { + return CupertinoActionSheet( + actions: [ + CupertinoActionSheetAction( + child: Text( + "百度地图", + style: TextStyle( + fontWeight: MyFontWeight.regular, + ), + ), + onPressed: () { + onOpenBaiduMapRoute(); + Navigator.of(context).pop(); + }, + isDefaultAction: true, + isDestructiveAction: false, + ), + ], + cancelButton: CupertinoActionSheetAction( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text(S.of(context).quxiao, + style: TextStyle( + color: Colors.blue, + ),), + isDestructiveAction: true, + ), + ); + }); + } + + List<Widget> itemServer(String businessService) { + if (businessService == null || businessService == "") return []; + var list = businessService.split(","); + return list + .map((e) => Container( + margin: EdgeInsets.only(right: 8.w), + child: RoundButton( + height: 17.h * AppUtils.textScale(context), + text: "$e", + backgroup: Color(0xFFFF7A1A), + padding: EdgeInsets.only( + left: 2.w, + right: 2.w, + ), + fontSize: 10.sp, + textColor: Colors.white, + ), + )) + .toList(); + } + BMFMapController _mapController; BMFCoordinate latLng; BMFCoordinate myLatLng; @@ -119,13 +1188,13 @@ class _LocationMap extends State<LocationMap> { } addMarker() async { - // latLng = await AppUtils.coordConvert(BMFCoordinate(double.tryParse(widget.arguments["lat"]), - // double.tryParse(widget.arguments["lng"]))); - latLng = BMFCoordinate(double.tryParse(widget.arguments["lat"]), - double.tryParse(widget.arguments["lng"])); + latLng = await AppUtils.coordConvert(BMFCoordinate(double.tryParse(widget.arguments["lat"]), + double.tryParse(widget.arguments["lng"]))); + // latLng = BMFCoordinate(double.tryParse(widget.arguments["lat"]), + // double.tryParse(widget.arguments["lng"])); if (bmfMarker == null && _mapController != null) { - bmfMarker = BMFMarker( + bmfMarker = BMFMarker.icon( position: latLng, centerOffset: BMFPoint(0.5, 0.7), enabled: false, @@ -134,11 +1203,6 @@ class _LocationMap extends State<LocationMap> { ); _mapController.addMarker(bmfMarker); } - _mapController.updateMapOptions( - BMFMapOptions( - center: latLng, - zoomLevel: 15, - ), - ); + _mapController.setCenterCoordinate(latLng, true); } } diff --git a/lib/union/union_list.dart b/lib/union/union_list.dart index c381f3f0..173bc4ef 100644 --- a/lib/union/union_list.dart +++ b/lib/union/union_list.dart @@ -1,28 +1,37 @@ +import 'package:dio/dio.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart'; +import 'package:flutter_baidu_mapapi_utils/flutter_baidu_mapapi_utils.dart'; +import 'package:flutter_bmflocation/flutter_bmflocation.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:huixiang/generated/l10n.dart'; import 'package:huixiang/retrofit/data/store.dart'; import 'package:huixiang/utils/font_weight.dart'; -import 'package:huixiang/view_widget/border_text.dart'; -import 'package:huixiang/view_widget/classic_header.dart'; +import 'package:huixiang/utils/location.dart'; import 'package:huixiang/view_widget/custom_image.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:huixiang/view_widget/request_permission.dart'; -import 'package:huixiang/view_widget/round_button.dart'; -import 'package:permission_handler/permission_handler.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:shimmer/shimmer.dart'; +import '../retrofit/data/base_data.dart'; +import '../retrofit/data/product_show.dart'; +import '../retrofit/retrofit_api.dart'; +import '../utils/flutter_utils.dart'; +import '../view_widget/classic_header.dart'; import '../view_widget/no_data_view.dart'; +import '../view_widget/round_button.dart'; class UnionList extends StatefulWidget { - final RefreshController refreshController; - final List<Store> storeList; - final Function onRefresh; - final Function queryStore; - - UnionList(this.refreshController,this.storeList,this.onRefresh,this.queryStore); + final String serviceType; + final BMFCoordinate latLng; + final String searchKey; + final String city; + UnionList(Key key, this.serviceType, this.latLng, this.searchKey, this.city) + : super(key: key); @override State<StatefulWidget> createState() { @@ -30,89 +39,112 @@ class UnionList extends StatefulWidget { } } -class _UnionList extends State<UnionList> { - final TextEditingController editingController = TextEditingController(); +class _UnionList extends State<UnionList> with AutomaticKeepAliveClientMixin { + ApiService apiService; + List<Store> storeList; + BMFCoordinate latLng; + final RefreshController _refreshController = RefreshController(); + + @override + bool get wantKeepAlive => true; + + @override + void initState() { + super.initState(); + queryStore(); + } + + queryStore() async { + if (apiService == null) { + SharedPreferences value = await SharedPreferences.getInstance(); + apiService = ApiService( + Dio(), + context: context, + token: value.getString("token"), + ); + } + BaseData<List<Store>> baseData = await apiService.queryStore({ + "city": widget.city ?? "", + // "district": district, + // "province": province, + "latitude": (widget.latLng?.latitude ?? "").toString(), + "longitude": (widget.latLng?.longitude ?? "").toString(), + if (widget.searchKey != "") "searchKey": widget.searchKey, + "serviceType": widget.serviceType, + "exchange": false, + }).catchError((error) { + SmartDialog.showToast(AppUtils.dioErrorTypeToString(error.type), + alignment: Alignment.center); + _refreshController.refreshFailed(); + }); + if (baseData != null && baseData.isSuccess) { + storeList = baseData.data; + _refreshController.refreshCompleted(); + } else { + _refreshController.refreshFailed(); + } + EasyLoading.dismiss(); + setState(() {}); + } @override Widget build(BuildContext context) { - return Column( - children: [ - buildSearchItem(), - Container( - height: MediaQuery.of(context).size.height - - 103.h - - MediaQuery.of(context).padding.top, - child: SmartRefresher( - controller: widget.refreshController, - enablePullUp: false, - enablePullDown: true, - physics: BouncingScrollPhysics(), - header: MyHeader(), - onRefresh: widget.onRefresh, - child: (widget.storeList == null || widget.storeList.length == 0) - ? NoDataView( - src:"assets/image/di_zhi.webp", - isShowBtn: false, - text: "暂无店铺列表~", - fontSize: 16.sp, - margin: EdgeInsets.only(top: 120.h), - ):ListView.builder( - itemCount:widget.storeList == null ? 0 : widget.storeList.length, - padding: EdgeInsets.only( - top: 8.h, - bottom: 100.h, /* + (375.h - 88.h) + 4.h*/ - ), - physics: NeverScrollableScrollPhysics(), - itemBuilder: (context, position) { - return InkWell( - onTap: () { - // if (widget.storeList[position].posType.code == "NORMALSTORE") { - // showDeleteDialog(); - // } - // else - // if ( widget.storeList[position].storeName == "一心回乡商城") { - // Navigator.of(context).pushNamed( - // '/router/shopping_mall_home', - // arguments: { - // "type": 0, - // "id": widget.storeList[position].id, - // "tenant": widget.storeList[position].tenantCode, - // "storeName": widget.storeList[position].storeName - // }, - // ); - // } - // else - { - Navigator.of(context).pushNamed( - '/router/store_order', - arguments: { - "id": widget.storeList[position].id, - "tenant": widget.storeList[position].tenantCode, - "storeName": widget.storeList[position].storeName, - "distance":widget.storeList[position].distance - }, - ); - } - }, - child: - buildStoreItem(widget.storeList[position], position), - ); - })), - ) - ], + return SmartRefresher( + controller: _refreshController, + enablePullDown: true, + enablePullUp: false, + header: MyHeader( + color: Colors.white, + ), + physics: BouncingScrollPhysics(), + onRefresh: queryStore, + child: (storeList == null || storeList.length == 0) + ? NoDataView( + src: "assets/image/di_zhi.webp", + isShowBtn: false, + text: ((widget.city??"") != "武汉" && (widget.city??"") != "郑州" && (widget.city??"") != "北京") ? + " 当前回乡开放门店 仅包含 武汉/北京/郑州,您当前的位置无法获取,请手动更换城市" :"暂无店铺列表~", + fontSize: 16.sp, + margin: EdgeInsets.only(top: 120.h,left:45.w,right:45.w), + ) + : ListView.builder( + itemCount: storeList.length, + padding: EdgeInsets.only( + top: 8.h, + bottom: 100.h, + ), + itemBuilder: (context, position) { + return InkWell( + onTap: () { + { + Navigator.of(context).pushNamed( + '/router/store_order', + arguments: { + "id": storeList[position].id, + "tenant": storeList[position].tenantCode, + "storeName": storeList[position].storeName, + "distance": storeList[position].distance + }, + ); + } + }, + child: buildStoreItem(storeList[position], position), + ); + }, + ), ); } - Widget sm(){ + Widget sm() { return Container( - margin:EdgeInsets.symmetric(horizontal: 14.w,vertical: 8.h), + margin: EdgeInsets.symmetric(horizontal: 14.w, vertical: 8.h), width: double.infinity, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(6), ), height: 223.h, - child:Column( + child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Shimmer.fromColors( @@ -124,19 +156,25 @@ class _UnionList extends State<UnionList> { height: 140.h, ), ), - Padding(padding: EdgeInsets.only(left: 6.w,bottom: 5.h,top: 12.h), - child: Shimmer.fromColors( - baseColor: Color(0XFFD8D8D8), - highlightColor: Color(0XFFD8D8D8), - child: Container( - decoration: BoxDecoration( - color: Color(0XFFD8D8D8), - borderRadius: BorderRadius.circular(2), + Padding( + padding: EdgeInsets.only(left: 6.w, bottom: 5.h, top: 12.h), + child: Shimmer.fromColors( + baseColor: Color(0XFFD8D8D8), + highlightColor: Color(0XFFD8D8D8), + child: Container( + decoration: BoxDecoration( + color: Color(0XFFD8D8D8), + borderRadius: BorderRadius.circular(2), + ), + width: 108.w, + height: 20.h, ), - width: 108.w, - height: 20.h, ), - ),),Padding(padding: EdgeInsets.only(left: 6.w,), + ), + Padding( + padding: EdgeInsets.only( + left: 6.w, + ), child: Shimmer.fromColors( baseColor: Color(0XFFD8D8D8), highlightColor: Color(0XFFD8D8D8), @@ -148,68 +186,212 @@ class _UnionList extends State<UnionList> { width: 260.w, height: 20.h, ), - ),), + ), + ), ], ), ); } - Widget buildSearchItem() { + Widget buildStoreItem(Store store, position) { return Container( - height: 36.h, - margin: EdgeInsets.fromLTRB(6.w, 0, 14.w, 0), - padding: EdgeInsets.fromLTRB(0, 6.h, 0, 6.h), + margin: EdgeInsets.fromLTRB(16.w, 8.h, 16.w, 12.h), + padding: EdgeInsets.symmetric(horizontal:12.w,vertical: 12.h), decoration: BoxDecoration( - color: Color(0xFFF5FAF7), - borderRadius: BorderRadius.circular(4), - boxShadow: [ - BoxShadow( - color: Colors.black.withAlpha(12), - offset: Offset(0, 3), - blurRadius: 14, - spreadRadius: 0, + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(6)), + boxShadow: [ + BoxShadow( + color: Colors.black.withAlpha(25), + offset: Offset(0, 1), + blurRadius: 12, + spreadRadius: 0, + ) + ]), + width: double.infinity, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Stack( + children: [ + MImage( + store.facade, + width: 74.h, + height: 74.h, + fit: BoxFit.cover, + radius: BorderRadius.circular(6), + errorSrc: "assets/image/default_1.webp", + fadeSrc: "assets/image/default_1.webp", + ), + Container( + decoration: BoxDecoration( + color: Color(0xFF32A060), + borderRadius: BorderRadius.only( + topLeft: Radius.circular(6), + bottomRight: Radius.circular(6), + topRight: Radius.circular(2), + bottomLeft: Radius.circular(2)), + ), + padding: EdgeInsets.symmetric(horizontal: 3.w, vertical: 2.h), + child: Text( + "品牌", + style: TextStyle( + color: Colors.white, + fontSize: 10.sp, + fontWeight: MyFontWeight.regular, + ), + ), + ) + ], ), + SizedBox( + width: 12.w, + ), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + store?.storeName ?? "", + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Color(0xFF0D0D0D), + fontSize: 14.sp, + fontWeight: MyFontWeight.bold, + ), + ), + SizedBox(height: 6.h), + Row( + children: [ + Text( + S.of(context).ren( + store?.perCapitaConsumption ?? "", + ), + style: TextStyle( + color: Color(0xFF4D4D4D), + fontSize: 12.sp, + fontWeight: MyFontWeight.regular, + ), + ), + SizedBox(width: 22.w), + if (store.distance != null) + Image.asset( + "assets/image/icon_union_location_black.webp", + fit: BoxFit.fill, + height: 12, + width: 12, + ), + SizedBox(width: 4.w), + if (store.distance != null) + 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( + color: Color(0xFF4D4D4D), + fontSize: 12.sp, + ), + ), + ], + ), + SizedBox(height: 10.h), + Row( + children: []..addAll( + itemServer(store != null ? store.businessService : "")), + ), + if (storeList[position].productShow != null) + SizedBox(height: store.businessService == "" ? 40.h : 23.h), + if (storeList[position].productShow != null) + Container( + height: 100.h, + child: ListView.builder( + padding: EdgeInsets.zero, + itemCount: + (storeList[position].productShow?.length ?? 0) > 3 + ? 3 + : storeList[position].productShow?.length ?? 0, + scrollDirection: Axis.horizontal, + shrinkWrap: true, + physics:BouncingScrollPhysics(), + itemBuilder: (context, index) { + return GestureDetector( + onTap: () {}, + child: unionGoodsItem( + storeList[position].productShow[index]), + ); + }, + ), + ), + ], + )) ], ), - child: TextField( - textInputAction: TextInputAction.search, - onEditingComplete: () { - FocusScope.of(context).requestFocus(FocusNode()); - widget.queryStore(editingController.text); - }, - controller: editingController, - cursorHeight: 25.h, - decoration: InputDecoration( - contentPadding: EdgeInsets.symmetric( - vertical: 12.h, - ), - prefixIcon:InkWell( - onTap: () { - widget.queryStore(editingController.text); - }, - child: Icon( - Icons.search, - size: 24, - color: Colors.black, - ), + ); + } + + ///标签 + List<Widget> itemServer(String businessService) { + if (businessService == null || businessService == "") return []; + var list = businessService.split(","); + return list + .map((e) => Container( + margin: EdgeInsets.only(right: 8.w), + child: RoundButton( + height: 17.h * AppUtils.textScale(context), + text: "$e", + backgroup: Color(0xFFF65720), + padding: EdgeInsets.only( + left: 4.w, + right: 4.w, ), - suffixIcon: InkWell( - onTap: () { - editingController.clear(); - }, - child: Icon( - Icons.close, - size: 19, - color: Colors.grey, + fontSize: 10.sp, + textColor: Colors.white, + ), + )) + .toList(); + } + + Widget unionGoodsItem(ProductShow productShow) { + return Container( + width: 74.h, + margin: EdgeInsets.only(right: 8.w), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + MImage( + productShow?.imgs[0] ?? "", + width: 74.h, + height: 74.h, + fit: BoxFit.cover, + radius: BorderRadius.circular(4), + errorSrc: "assets/image/default_1.webp", + fadeSrc: "assets/image/default_1.webp", + ), + Padding( + padding: EdgeInsets.only(top: 8.h), + child: Text( + productShow?.productName ?? "", + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Color(0xFFA29E9E), + fontSize: 12.sp, + fontWeight: MyFontWeight.regular, + ), ), ), - border: InputBorder.none, - ), + ], ), ); } - Widget buildStoreItem(Store store, position) { + //旧ui + Widget buildStoreItems(Store store, position) { return Container( margin: EdgeInsets.fromLTRB(16.w, 8.h, 16.w, 12.h), decoration: BoxDecoration( @@ -275,62 +457,65 @@ class _UnionList extends State<UnionList> { ), Expanded( child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - height: 40.h, - ), - Text( - store?.storeName ?? "", - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: Color(0xFF0D0D0D), - fontSize: 14.sp, - fontWeight: MyFontWeight.bold, - ), + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 40.h, + ), + Text( + store?.storeName ?? "", + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Color(0xFF0D0D0D), + fontSize: 14.sp, + fontWeight: MyFontWeight.bold, + ), + ), + SizedBox( + height: 5.h, + ), + Expanded( + child: Text( + "${S.of(context).dizhi}:${store.address}", + maxLines: 2, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Color(0xFF4D4D4D), + fontSize: 12.sp, + fontWeight: MyFontWeight.regular, ), - SizedBox( - height: 5.h, + ), + ) + ], + )), + if (store.distance != null) + Container( + width: 59.w, + height: 18.h, + alignment: Alignment.center, + margin: EdgeInsets.only(top: 20.h), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(2), + color: Color(0xFF32A060), + ), + child: Visibility( + child: 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( + color: Color(0xFFFFFFFF), + fontSize: 10.sp, ), - Expanded(child: Text( - "${S.of(context).dizhi}:${store.address}", - maxLines: 2, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: Color(0xFF4D4D4D), - fontSize: 12.sp, - fontWeight: MyFontWeight.regular, - ), - ),) - ], - )), - if(store.distance != null) - Container( - width: 59.w, - height: 18.h, - alignment: Alignment.center, - margin: EdgeInsets.only(top: 20.h), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(2), - color: Color(0xFF32A060), - ), - child: Visibility( - child: 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( - color: Color(0xFFFFFFFF), - fontSize: 10.sp, ), + visible: store.distance != null, ), - visible: store.distance != null, ), - ), ], ), ), @@ -339,130 +524,4 @@ class _UnionList extends State<UnionList> { ), ); } - - ///扫码提示弹窗 - showDeleteDialog() { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - content: Container( - width: MediaQuery.of(context).size.width - 84.w, - height: 130.h, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - "您即将进行扫码点餐", - style: TextStyle( - fontSize: 17.sp, - fontWeight: FontWeight.bold, - color: Colors.black, - ), - ), - SizedBox( - height: 30.h, - ), - Row( - children: [ - Expanded( - child: InkWell( - child: BorderText( - text: "取消", - textColor: Color(0xFF32A060), - fontSize: 16.sp, - fontWeight: FontWeight.bold, - borderColor: Color(0xFF32A060), - radius: 4, - padding: EdgeInsets.all(12), - borderWidth: 1, - ), - onTap: () { - Navigator.of(context).pop(); - }, - ), - flex: 1, - ), - SizedBox( - width: 16.w, - ), - Expanded( - child: InkWell( - child: RoundButton( - text: "确定", - textColor: Colors.white, - radius: 4, - padding: EdgeInsets.all(12), - backgroup: Color(0xFF32A060), - fontSize: 16.sp, - fontWeight: FontWeight.bold, - ), - onTap: () { - toScan(); - Navigator.of(context).pop(); - }, - ), - flex: 1, - ), - ], - ) - ], - ), - ), - ); - }, - ); - } - - ///扫码 - toScan() async { - if (await Permission.camera.isPermanentlyDenied) { - showCupertinoDialog( - context: context, - builder: (context) { - return RequestPermission( - "assets/image/icon_camera_permission_tips.webp", - S.of(context).ninxiangjiquanxianweikaiqi, - S.of(context).weilekaipaizhaoxuanzhetouxiang, - S.of(context).kaiqiquanxian, - (result) async { - if (result) { - await openAppSettings(); - } - }, - heightRatioWithWidth: 0.82, - ); - }); - } else if (await Permission.camera.isGranted) { - // http://pos.app.gznl.top/placeorder/?tableId=1315903669597634560&tenantCode=1166&shopId=1300372027722432512 - // 新版桌子码跳转 - // http://miniscan.lotus-wallet.com/placeorder?tenant_code=1194&table_id=1669609340031467520&store_id=1637659387134738432 - var result = await Navigator.of(context).pushNamed('/router/qr_scan'); - // String result = await scanner.scan(); - Uri uri = Uri.parse(result); - String tableId = uri.queryParameters["tableId"] ?? uri.queryParameters["table_id"]; - String tenantCode = uri.queryParameters["tenantCode"] ?? uri.queryParameters["tenant_code"]; - String shopId = uri.queryParameters["shopId"] ?? uri.queryParameters["store_id"]; - if (tableId != null && - tableId != "" && - tenantCode != null && - tenantCode != "" && - shopId != null && - shopId != "") { - Navigator.of(context).pushNamed( - '/router/store_order', - arguments: { - "id": shopId, - "tenant": tenantCode, - "storeName": "", - "tableId": int.tryParse(tableId), - }, - ); - } - } else { - await Permission.camera.request(); - } - } - } diff --git a/lib/union/union_page.dart b/lib/union/union_page.dart index 19e69013..c8158739 100644 --- a/lib/union/union_page.dart +++ b/lib/union/union_page.dart @@ -4,35 +4,26 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_baidu_mapapi_map/flutter_baidu_mapapi_map.dart'; import 'package:flutter_baidu_mapapi_utils/flutter_baidu_mapapi_utils.dart'; import 'package:flutter_bmflocation/flutter_bmflocation.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; -import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:huixiang/generated/l10n.dart'; import 'package:huixiang/main.dart'; -import 'package:huixiang/retrofit/data/base_data.dart'; -import 'package:huixiang/retrofit/data/store.dart'; +import 'package:huixiang/retrofit/data/ip_data.dart'; import 'package:huixiang/retrofit/retrofit_api.dart'; import 'package:huixiang/union/union_list.dart'; import 'package:huixiang/utils/event_type.dart'; -import 'package:huixiang/utils/font_weight.dart'; import 'package:huixiang/utils/location.dart'; -import 'package:huixiang/view_widget/border_text.dart'; -import 'package:huixiang/view_widget/classic_header.dart'; -import 'package:huixiang/view_widget/custom_image.dart'; -import 'package:huixiang/view_widget/my_appbar.dart'; import 'package:huixiang/view_widget/my_tab.dart'; -import 'package:huixiang/view_widget/request_permission.dart'; -import 'package:huixiang/view_widget/round_button.dart'; import 'package:permission_handler/permission_handler.dart'; -import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart'; +import 'package:visibility_detector/visibility_detector.dart'; -import '../utils/flutter_utils.dart'; +import '../view_widget/location_tips.dart'; +import '../view_widget/no_data_view.dart'; class UnionPage extends StatefulWidget { final int initialIndex; @@ -50,17 +41,14 @@ class UnionPageState extends State<UnionPage> AutomaticKeepAliveClientMixin, WidgetsBindingObserver, SingleTickerProviderStateMixin { - final RefreshController refreshController = - RefreshController(initialRefresh: false); - final RefreshController refreshController1 = - RefreshController(initialRefresh: false); - final RefreshController refreshController2 = - RefreshController(initialRefresh: false); - final RefreshController refreshController3 = - RefreshController(initialRefresh: false); - ApiService apiService; + final TextEditingController editingController = TextEditingController(); bool isKeyBoardShow = false; + TabController tabController; BMFCoordinate latLng; + String areaName; + List<GlobalKey> _allKey = []; + bool _isShowLocalTips = false; + double visiblePercentage; jumpIndex(jpIndex) { tabController.index = jpIndex; @@ -73,11 +61,24 @@ class UnionPageState extends State<UnionPage> if (Location.getInstance() != null && Location.getInstance().aMapFlutterLocation != null) Location.getInstance().aMapFlutterLocation.stopLocation(); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + if (state == AppLifecycleState.resumed) { + // 处理应用程序切换回前台的逻辑 + if(visiblePercentage == 1) + permissionSettings(); + } else if (state == AppLifecycleState.paused) { + // 处理应用程序切换到后台的逻辑 + } + } - if (refreshController != null) refreshController.dispose(); - if (refreshController1 != null) refreshController1.dispose(); - if (refreshController2 != null) refreshController2.dispose(); - if (refreshController3 != null) refreshController3.dispose(); + void permissionSettings() async { + if (_isShowLocalTips && await Permission.location.isGranted){ + _isShowLocalTips = false; + getLocation(); + } } @override @@ -102,79 +103,60 @@ class UnionPageState extends State<UnionPage> @override void initState() { super.initState(); - if (tabController == null) - tabController = TabController( - length: 4, vsync: this, initialIndex: widget.initialIndex); - // tabController?.addListener(() { - // startLocation(); - // }); + tabController = TabController( + length: 4, vsync: this, initialIndex: widget.initialIndex); WidgetsBinding.instance.addObserver(this); - eventBus.on<EventType>().listen((event) { if (event.type < 3) { setState(() {}); } }); - - getLatLng(); - startLocation(false); - } - - RefreshController tabRefresh() { - RefreshController tempRef; - if (tabController.index == 0) - tempRef = refreshController; - else if (tabController.index == 1) - tempRef = refreshController1; - else if (tabController.index == 2) - tempRef = refreshController2; - else if (tabController.index == 3) tempRef = refreshController3; - return tempRef; + queryIpInfo(); } - startLocation(bool isOnRefresh) async { - if (!isOnRefresh) EasyLoading.show(status: S.current.zhengzaijiazai); - Location.getInstance().startLocation(context, (BaiduLocation result) { - if (result != null && - result.latitude != null && - result.longitude != null) { - print("location: $result"); - latLng = BMFCoordinate(result.latitude, result.longitude); - BMFCalculateUtils.coordConvert( - coordinate: latLng, - fromType: BMF_COORD_TYPE.BD09LL, - toType: BMF_COORD_TYPE.COMMON) - .then((value) { - this.latLng = value; - saveLatLng( - value, result.province, result.city, result.district); - print("union: Location result ${value.latitude} " - "${value.longitude}"); + getLocation({bool showLoading = true}) async { + if(showLoading) + EasyLoading.show( + status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black); + bool powerFlag = false; + // bool finallyFlag = false; + try { + Future.delayed(Duration(seconds: 5), () { + // if (!finallyFlag) + Location.getInstance().stopLocation(); + }); + powerFlag = await Location.getInstance().startLocation(context, + (BaiduLocation result) async { + if (result != null && + result.latitude != null && + result.longitude != null) { + print("location: $result"); + latLng = BMFCoordinate(result.latitude, result.longitude); + latLng = await BMFCalculateUtils.coordConvert( + coordinate: latLng, + fromType: BMF_COORD_TYPE.BD09LL, + toType: BMF_COORD_TYPE.COMMON); + await saveLatLng( + latLng, result.province, result.city, result.district); + print("union: Location result ${latLng.latitude} " + "${latLng.longitude}"); Location.getInstance().stopLocation(); - queryStore( - "${value.latitude}", - "${value.longitude}", - result.province, - result.city, - result.district, - "", - -1); - if (_mapController != null) - _mapController.updateMapOptions(BMFMapOptions( - center: value, - zoomLevel: 15, - )); - }); - } else { - getLatLng(); - // EasyLoading.dismiss(); - } - }).then((value) { - if (!value) { - EasyLoading.dismiss(); - tabRefresh().refreshCompleted(); + } else { + await getLatLng(); + } + loadFinish(showLoading: false); + }); + } finally { + // finallyFlag = true; + if (!powerFlag) { + if (await Permission.locationWhenInUse.status.isGranted) { + getLocation(); + } else { + _isShowLocalTips = true; + loadFinish(showLoading: false); + } } - }); + } } saveLatLng(BMFCoordinate latLng, province, city, district) async { @@ -187,713 +169,233 @@ class UnionPageState extends State<UnionPage> } getLatLng() async { - SharedPreferences.getInstance().then( - (value) => { - // apiService = ApiService(Dio(), - // context: context, - // token: value.getString('token'), - // showLoading: false), - if (value.containsKey("latitude") && - value.containsKey("longitude") && - value.containsKey("province") && - value.containsKey("city") && - value.containsKey("district")) - { - latLng = BMFCoordinate(double.tryParse(value.getString("latitude")), - double.tryParse(value.getString("longitude"))), - queryStore( - value.getString("latitude"), - value.getString("longitude"), - value.getString("province"), - value.getString("city"), - value.getString("district"), - "", - -1), - setState(() { - if (_mapController != null) { - _mapController.updateMapOptions(BMFMapOptions( - center: latLng, - zoomLevel: 15, - )); - } - }) - } - else - { - queryStore("", "", "", "", "", "", -1), - } - }, - ); + var tempLatLng = await SharedPreferences.getInstance(); + if (tempLatLng.containsKey("latitude") && + tempLatLng.containsKey("longitude") && + tempLatLng.containsKey("province") && + tempLatLng.containsKey("city") && + tempLatLng.containsKey("district")) { + latLng = BMFCoordinate(double.tryParse(tempLatLng.getString("latitude")), + double.tryParse(tempLatLng.getString("longitude"))); + } } - List<Store> storeList; - List<Store> storeList1; - List<Store> storeList2; - List<Store> storeList3; - - queryStore(latitude, longitude, province, city, district, searchKey, - int index) async { - if (apiService == null) { - SharedPreferences value = await SharedPreferences.getInstance(); - apiService = ApiService( - Dio(), - context: context, - token: value.getString("token"), - ); - } - BaseData<List<Store>> baseData = await apiService.queryStore({ - // "city": city, - // "district": district, - // "province": province, - "latitude": latitude, - "longitude": longitude, - if(searchKey != "") - "searchKey": searchKey, - "serviceType": (tabController.index == 0 && index == -1) || index == 0 - ? "" - : ((tabController.index == 1 && index == -1) || index == 1 - ? "EATSTORE" - : ((tabController.index == 2 && index == -1) || index == 2 - ? "DRINKSTORE" - : "HAPPYSTORE")), - "exchange":false, - }).catchError((error) { - SmartDialog.showToast(AppUtils.dioErrorTypeToString(error.type), - alignment: Alignment.center); - if (index == -1) tabRefresh().refreshFailed(); - }); - if (baseData != null && baseData.isSuccess) { - if (index == -1 && storeList == null) { - if (tabController.index != 0) - queryStore( - latitude, longitude, province, city, district, searchKey, 0); - if (tabController.index != 1) - queryStore( - latitude, longitude, province, city, district, searchKey, 1); - if (tabController.index != 2) - queryStore( - latitude, longitude, province, city, district, searchKey, 2); - if (tabController.index != 3) - queryStore( - latitude, longitude, province, city, district, searchKey, 3); + queryIpInfo() async { + EasyLoading.show( + status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black); + try { + ApiService apiIpService = ApiService(Dio(), context: context, isIp: true); + IpData baseData = await apiIpService.getIpInfo().catchError((onError) {}); + if (baseData?.city != null) { + areaName = baseData.city.replaceAll("市", ""); } - if ((tabController.index == 0 && index == -1) || index == 0) - storeList = baseData.data; - else if ((tabController.index == 1 && index == -1) || index == 1) - storeList1 = baseData.data; - else if ((tabController.index == 2 && index == -1) || index == 2) - storeList2 = baseData.data; - else if ((tabController.index == 3 && index == -1) || index == 3) - storeList3 = baseData.data; - if (index == -1) tabRefresh().refreshCompleted(); - } else { - if (index == -1) tabRefresh().refreshFailed(); + } finally { + getLocation(showLoading: false); } - EasyLoading.dismiss(); - setState(() {}); } - TabController tabController; + loadFinish({bool showLoading = true}) { + if (showLoading) + EasyLoading.show( + status: S.current.zhengzaijiazai, + maskType: EasyLoadingMaskType.black); + _allKey = [GlobalKey(), GlobalKey(), GlobalKey(), GlobalKey()]; + setState(() {}); + } @override Widget build(BuildContext context) { super.build(context); - return GestureDetector( - behavior: HitTestBehavior.translucent, - onTap: () { - FocusScope.of(context).requestFocus(FocusNode()); + return VisibilityDetector( + key: Key('my-widget-key'), + onVisibilityChanged: (visibilityInfo) { + visiblePercentage = visibilityInfo.visibleFraction; + if(visiblePercentage == 1) + permissionSettings(); }, - child: Scaffold( - resizeToAvoidBottomInset: false, - appBar: MyAppBar( - title: "", - leading: false, - brightness: Brightness.light, - titleChild: PreferredSize( - preferredSize: Size(double.infinity, 38.h), - child: Theme( - data: ThemeData( - splashColor: Colors.transparent, // 点击时的水波纹颜色设置为透明 - highlightColor: Colors.transparent, // 点击时的背景高亮颜色设置为透明 - ), - child: TabBar( - controller: tabController, - isScrollable: true, - //可滚动 - indicatorColor: Color(0xff39B54A), - labelColor: Colors.black, - labelStyle: TextStyle( - fontSize: 18.sp, - fontWeight: FontWeight.bold, - ), - unselectedLabelStyle: TextStyle( - fontSize: 15.sp, - fontWeight: FontWeight.normal, - ), - // controller: tabController, - //未选中文字颜色 - unselectedLabelColor: Color(0xffA29E9E), - indicatorSize: TabBarIndicatorSize.label, - //指示器与文字等宽 - tabs: <Widget>[ - MyTab(text: S.of(context).quanbu), - MyTab(text: S.of(context).chi), - MyTab(text: S.of(context).he), - MyTab(text: S.of(context).wan), - ], - )), - )), - body: TabBarView( - controller: tabController, - children: [ - UnionList(refreshController, storeList, () { - startLocation(true); - },(txt){ - queryStore("","","","","",txt,0); - }), - UnionList(refreshController1, storeList1, () { - startLocation(true); - },(txt){ - queryStore("","","","","",txt,0); - }), - UnionList(refreshController2, storeList2, () { - startLocation(true); - },(txt){ - queryStore("","","","","",txt,0); - }), - UnionList(refreshController3, storeList3, () { - startLocation(true); - },(txt){ - queryStore("","","","","",txt,0); - }), - ], - ), - )); - // GestureDetector( - // onTap: () { - // FocusScope.of(context).requestFocus(FocusNode()); - // }, - // child: Scaffold( - // backgroundColor: Colors.white, - // resizeToAvoidBottomInset: false, - // appBar: MyAppBar( - // // titleChild: buildSearchItem(), - // title: "", - // leading: false, - // background: Colors.white, - // brightness: Brightness.light, - // ), - // body: Column( - // children: [ - // // Row( - // // mainAxisAlignment: MainAxisAlignment.start, - // // crossAxisAlignment: CrossAxisAlignment.end, - // // children: [ - // // Expanded(child:PreferredSize( - // // preferredSize: Size(double.infinity, 52.h), - // // child: Container( - // // padding: EdgeInsets.only(top:15.h), - // // color: Color(0xFFFAFAFA), - // // child: ItemTitle( - // // text: S.of(context).jingbilianmenghuiyuandian, - // // imgPath: "assets/image/icon_union_store.webp", - // // ), - // // ), - // // )), - // // GestureDetector( - // // onTap: (){ - // // setState(() { - // // var storeName = storeList.firstWhere((x)=>x.storeName == "一心回乡商城"); - // // if(storeName == null) - // // return; - // // Navigator.of(context).pushNamed( - // // '/router/shopping_mall_home', - // // arguments: { - // // "type":0, - // // "id":storeName.id, - // // "tenant": storeName.tenantCode, - // // "storeName":storeName.storeName - // // }, - // // ); - // // }); - // // }, - // // child:Container( - // // margin: EdgeInsets.only(right: 18), - // // height: 25.h, - // // width: 102.w, - // // color: Colors.white, - // // child:Row( - // // mainAxisAlignment: MainAxisAlignment.center, - // // crossAxisAlignment: CrossAxisAlignment.center, - // // children: [ - // // Text( - // // "一心回乡商城", - // // style: TextStyle( - // // fontSize: 12.sp, - // // fontWeight: MyFontWeight.regular, - // // color: Colors.black, - // // ), - // // ), - // // Icon( - // // Icons.keyboard_arrow_right, - // // size: 16, - // // ), - // // ], - // // ), - // // ), - // // ), - // // ], - // // ), - // buildItem() - // ], - // ), - // ), - // ); - } - - Widget buildItem( - RefreshController refreshController, - ) { - return Column( - children: [ - // buildSearchItem(), - Container( - height: MediaQuery.of(context).size.height - - 103.h - - MediaQuery.of(context).padding.top, - child: SmartRefresher( - controller: refreshController, - enablePullUp: false, - enablePullDown: true, - physics: BouncingScrollPhysics(), - header: MyHeader(), - onRefresh: () { - startLocation(false); - }, - child: ListView.builder( - itemCount: storeList == null ? 0 : storeList.length, - padding: EdgeInsets.only( - top: 8.h, - bottom: 84.h, /* + (375.h - 88.h) + 4.h*/ - ), - physics: NeverScrollableScrollPhysics(), - itemBuilder: (context, position) { - return InkWell( - onTap: () { - if (storeList[position].posType.code == "NORMALSTORE") { - showDeleteDialog(); - } else if (storeList[position].posType.code == - "RETAILSTORE" && - storeList[position].storeName == "一心回乡商城") { - Navigator.of(context).pushNamed( - '/router/shopping_mall_home', - arguments: { - "type": 0, - "id": storeList[position].id, - "tenant": storeList[position].tenantCode, - "storeName": storeList[position].storeName - }, - ); - } else { - Navigator.of(context).pushNamed( - '/router/store_order', - arguments: { - "id": storeList[position].id, - "tenant": storeList[position].tenantCode, - "storeName": storeList[position].storeName - }, - ); - } - }, - child: buildStoreItem(storeList[position], position), - ); - })), - ) - ], - ); - } - - BMFMapController _mapController; - - void onMapCreated(BMFMapController controller) { - _mapController = controller; - } - - // Widget buildSearchItem() { - // return Container( - // height: 36.h, - // margin: EdgeInsets.fromLTRB(6.w, 0, 14.w, 0), - // padding: EdgeInsets.fromLTRB(0, 6.h, 0, 6.h), - // decoration: BoxDecoration( - // color: Color(0xFFF5FAF7), - // borderRadius: BorderRadius.circular(4), - // boxShadow: [ - // BoxShadow( - // color: Colors.black.withAlpha(12), - // offset: Offset(0, 3), - // blurRadius: 14, - // spreadRadius: 0, - // ), - // ], - // ), - // child: TextField( - // textInputAction: TextInputAction.search, - // onEditingComplete: () { - // startLocation(false); - // }, - // controller: editingController, - // cursorHeight: 30.h, - // decoration: InputDecoration( - // contentPadding: EdgeInsets.symmetric( - // vertical: 12.h, - // ), - // prefixIcon: Icon( - // Icons.search, - // size: 24, - // color: Colors.black, - // ), - // suffixIcon: InkWell( - // onTap: () { - // editingController.clear(); - // }, - // child: Icon( - // Icons.close, - // size: 19, - // color: Colors.grey, - // ), - // ), - // border: InputBorder.none, - // ), - // ), - // ); - // } - - // Widget buildSliverAppBar(BMFMapWidget map) { - // return SliverAppBar( - // // 滑上去时搜索隐藏 - // // floating: true, - // // snap: true, - // pinned: true, - // backgroundColor: Color(0xFFFAFAFA), - // elevation: 0, - // automaticallyImplyLeading: false, - // title: Container( - // height: 36.h, - // margin: EdgeInsets.fromLTRB(16.w, 0, 16.w, 0), - // padding: EdgeInsets.fromLTRB(0, 6.h, 0, 6.h), - // decoration: BoxDecoration( - // color: Colors.white, - // borderRadius: BorderRadius.all(Radius.circular(4)), - // boxShadow: [ - // BoxShadow( - // color: Colors.black.withAlpha(12), - // offset: Offset(0, 3), - // blurRadius: 14, - // spreadRadius: 0, - // ) - // ]), - // child: TextField( - // textInputAction: TextInputAction.search, - // onEditingComplete: () { - // startLocation(); - // }, - // controller: editingController, - // cursorHeight: 30.h, - // decoration: InputDecoration( - // contentPadding: EdgeInsets.symmetric(vertical: 12.h), - // prefixIcon: Icon( - // Icons.search, - // size: 24, - // color: Colors.black, - // ), - // suffixIcon: InkWell( - // onTap: () { - // editingController.clear(); - // }, - // child: Icon( - // Icons.close, - // size: 19, - // color: Colors.grey, - // ), - // ), - // border: InputBorder.none, - // ), - // ), - // ), - // flexibleSpace: FlexibleSpaceBar( - // background: Container( - // child: map, - // ), - // ), - // expandedHeight: 375.h, - // bottom: PreferredSize( - // preferredSize: Size(double.infinity, 52.h), - // child: Container( - // padding: EdgeInsets.only(top: 6.h), - // color: Color(0xFFFAFAFA), - // child: ItemTitle( - // text: S.of(context).jingbilianmenghuiyuandian, - // imgPath: "assets/image/icon_union_store.webp", - // ), - // ), - // ), - // ); - // } - - Widget buildStoreItem(Store store, position) { - return Container( - margin: EdgeInsets.fromLTRB(16.w, 8.h, 16.w, 8.h), - // padding: EdgeInsets.fromLTRB(20.w, 20.h, 20.w, 20.h), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(8)), - boxShadow: [ - BoxShadow( - color: Colors.black.withAlpha(25), - offset: Offset(0, 1), - blurRadius: 12, - spreadRadius: 0, - ) - ]), - width: double.infinity, - height: 228.h, + child: GestureDetector( + behavior: HitTestBehavior.translucent, + onTap: () { + FocusScope.of(context).requestFocus(FocusNode()); + }, child: Stack( + alignment: Alignment.bottomCenter, children: [ - Positioned( - top: 0, - left: 0, - right: 0, - child: ClipRRect( - child: MImage( - store.facade, - width: double.infinity, - height: 140.h, - fit: BoxFit.cover, - errorSrc: "assets/image/default_1.webp", - fadeSrc: "assets/image/default_1.webp", - ), - borderRadius: BorderRadius.vertical( - top: Radius.circular(4), - ), - ), - ), - Positioned( - bottom: 0, - left: 0, - right: 0, - child: Container(), - ), - Positioned( - bottom: 16.h, - left: 12.w, - right: 0, - child: Container( - height: 100.h, - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - MImage( - store.logo, - width: 57, - height: 57, - fit: BoxFit.cover, - isCircle: true, - errorSrc: "assets/image/default_1.webp", - fadeSrc: "assets/image/default_1.webp", - ), - SizedBox( - width: 6.w, - ), - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - height: 40.h, - ), - Text( - store.storeName, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: Color(0xFF0D0D0D), - fontSize: 14.sp, - fontWeight: MyFontWeight.bold, - ), - ), - SizedBox( - height: 5.h, - ), - Text( - "${S.of(context).dizhi}:${store.address}", - maxLines: 2, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: Color(0xFF4D4D4D), - fontSize: 12.sp, - fontWeight: MyFontWeight.regular, - ), - ), - ], - )), - Container( - width: 59.w, - height: 18.h, - alignment: Alignment.center, - margin: EdgeInsets.only(top: 20.h), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(2), - color: Color(0xFF32A060), - ), - child: Visibility( - child: 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( - color: Color(0xFFFFFFFF), - fontSize: 10.sp, - ), - ), - visible: store.distance != null, - ), - ), - ], - ), - ), - ), - ], - ), - ); - } - - ///扫码提示弹窗 - showDeleteDialog() { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - content: Container( - width: MediaQuery.of(context).size.width - 84.w, - height: 130.h, + Container( child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text( - "您即将进行扫码点餐", - style: TextStyle( - fontSize: 17.sp, - fontWeight: FontWeight.bold, - color: Colors.black, - ), - ), - SizedBox( - height: 30.h, - ), Row( children: [ - Expanded( - child: InkWell( - child: BorderText( - text: "取消", - textColor: Color(0xFF32A060), - fontSize: 16.sp, - fontWeight: FontWeight.bold, - borderColor: Color(0xFF32A060), - radius: 4, - padding: EdgeInsets.all(12), - borderWidth: 1, - ), + Padding( + padding: EdgeInsets.only(left: 18.w, right: 10.w), + child: GestureDetector( + behavior: HitTestBehavior.opaque, onTap: () { - Navigator.of(context).pop(); + Navigator.of(context).pushNamed( + '/router/union_select_city', + arguments: {"cityName": areaName}).then((value) { + if (value != null) { + areaName = value; + loadFinish(); + } + }); }, - ), - flex: 1, - ), - SizedBox( - width: 16.w, - ), - Expanded( - child: InkWell( - child: RoundButton( - text: "确定", - textColor: Colors.white, - radius: 4, - padding: EdgeInsets.all(12), - backgroup: Color(0xFF32A060), - fontSize: 16.sp, - fontWeight: FontWeight.bold, + child: Row( + children: [ + Text( + areaName ?? "", + overflow: TextOverflow.ellipsis, + maxLines: 1, + style: TextStyle( + fontSize: 14.sp, + fontWeight: FontWeight.bold, + color: Colors.white), + ), + Icon( + Icons.keyboard_arrow_down, + color: Colors.white, + size: 24, + ) + ], ), - onTap: () { - toScan(); - Navigator.of(context).pop(); - }, ), - flex: 1, ), + Expanded(child: buildSearchItem()) ], - ) + ), + Align( + alignment: Alignment.centerLeft, + child: TabBar( + controller: tabController, + isScrollable: true, + //可滚动 + indicatorColor: Colors.white, + labelColor: Colors.white, + labelStyle: TextStyle( + fontSize: 18.sp, + fontWeight: FontWeight.bold, + ), + unselectedLabelStyle: TextStyle( + fontSize: 15.sp, + fontWeight: FontWeight.normal, + ), + //未选中文字颜色 + unselectedLabelColor: Colors.white, + indicatorSize: TabBarIndicatorSize.label, + //指示器与文字等宽 + tabs: <Widget>[ + MyTab(text: S.of(context).quanbu), + MyTab(text: S.of(context).chi), + MyTab(text: S.of(context).he), + MyTab(text: S.of(context).wan), + ], + ), + ), + _allKey.isEmpty + ? NoDataView( + src: "assets/image/di_zhi.webp", + isShowBtn: false, + text: "暂无店铺列表~", + fontSize: 16.sp, + margin: EdgeInsets.only(top: 120.h), + ) + : Expanded( + child: TabBarView( + controller: tabController, + children: [ + UnionList(_allKey[0], "", latLng, + editingController.text, areaName), + UnionList(_allKey[1], "EATSTORE", latLng, + editingController.text, areaName), + UnionList(_allKey[2], "DRINKSTORE", latLng, + editingController.text, areaName), + UnionList(_allKey[3], "HAPPYSTORE", latLng, + editingController.text, areaName), + ], + ), + ) ], ), + padding: + EdgeInsets.only(top: MediaQuery.of(context).padding.top + 17.h), + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xFF32A060), + Color(0xFF32A060), + Colors.white, + Colors.white, + ], + stops: [ + 0, + 0.2, + 0.4, + 1 + ]), + ), ), - ); - }, - ); + if (_isShowLocalTips) + Padding( + padding: EdgeInsets.only(bottom: 70.h), + child: LocationTips(() { + setState(() { + _isShowLocalTips = false; + }); + }), + ) + ], + ), + )); } - ///扫码 - toScan() async { - if (await Permission.camera.isPermanentlyDenied) { - showCupertinoDialog( - context: context, - builder: (context) { - return RequestPermission( - "assets/image/icon_camera_permission_tips.webp", - S.of(context).ninxiangjiquanxianweikaiqi, - S.of(context).weilekaipaizhaoxuanzhetouxiang, - S.of(context).kaiqiquanxian, - (result) async { - if (result) { - await openAppSettings(); - } - }, - heightRatioWithWidth: 0.82, - ); - }); - } else if (await Permission.camera.isGranted) { - // http://pos.app.gznl.top/placeorder/?tableId=1315903669597634560&tenantCode=1166&shopId=1300372027722432512 - // 新版桌子码跳转 - // http://miniscan.lotus-wallet.com/placeorder?tenant_code=1194&table_id=1669609340031467520&store_id=1637659387134738432 - var result = await Navigator.of(context).pushNamed('/router/qr_scan'); - // String result = await scanner.scan(); - Uri uri = Uri.parse(result); - String tableId = uri.queryParameters["tableId"] ?? uri.queryParameters["table_id"]; - String tenantCode = uri.queryParameters["tenantCode"] ?? uri.queryParameters["tenant_code"]; - String shopId = uri.queryParameters["shopId"] ?? uri.queryParameters["store_id"]; - if (tableId != null && - tableId != "" && - tenantCode != null && - tenantCode != "" && - shopId != null && - shopId != "") { - Navigator.of(context).pushNamed( - '/router/store_order', - arguments: { - "id": shopId, - "tenant": tenantCode, - "storeName": "", - "tableId": int.tryParse(tableId), - }, - ); - } - } else { - await Permission.camera.request(); - } + Widget buildSearchItem() { + return Container( + margin: EdgeInsets.fromLTRB(6.w, 0, 14.w, 0), + padding: EdgeInsets.symmetric(vertical: 6.h), + decoration: BoxDecoration( + color: Color(0xFFF5FAF7), + borderRadius: BorderRadius.circular(4), + boxShadow: [ + BoxShadow( + color: Colors.black.withAlpha(12), + offset: Offset(0, 3), + blurRadius: 14, + spreadRadius: 0, + ), + ], + ), + child: TextField( + textInputAction: TextInputAction.search, + onEditingComplete: () { + FocusScope.of(context).requestFocus(FocusNode()); + loadFinish(); + }, + controller: editingController, + style: TextStyle( + fontSize: 14.sp, + ), + decoration: InputDecoration( + hintText: "搜索联盟会员店", + hintStyle: TextStyle( + fontSize: 12.sp, + color: Color(0xFFB3B3B3), + ), + isCollapsed: true, + prefixIcon: Padding( + padding: EdgeInsets.only(left: 5.w, right: 5.w), + child: Image.asset( + "assets/image/icon_search.webp", + width: 16.h, + height: 16.h, + ), + ), + prefixIconConstraints: BoxConstraints(), + border: InputBorder.none, + ), + ), + ); } @override diff --git a/lib/union/union_select_city.dart b/lib/union/union_select_city.dart new file mode 100644 index 00000000..5856b5b4 --- /dev/null +++ b/lib/union/union_select_city.dart @@ -0,0 +1,372 @@ +import 'dart:convert'; + +import 'package:dio/dio.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:huixiang/utils/font_weight.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; + +import '../retrofit/data/ip_data.dart'; +import '../retrofit/retrofit_api.dart'; + +class UnionSelectCity extends StatefulWidget { + final Map<String, dynamic> arguments; + + UnionSelectCity({this.arguments}); + @override + State<StatefulWidget> createState() { + return _UnionSelectCity(); + } +} + +class _UnionSelectCity extends State<UnionSelectCity> { + RefreshController refreshController = RefreshController(); + Map<String, dynamic> areaMap; + ApiService apiIpService; + String ipName; + int ipState = 0; + List<String> hotCity = []; + List<String> areaList = []; + + @override + void initState() { + super.initState(); + areaCode(); + queryIpInfo(); + } + + void areaCode({String searchTxt}) async { + var value = + await rootBundle.loadString('assets/map_style/chinese_cities.json'); + areaList.clear(); + areaMap = jsonDecode(value); + hotCity = (areaMap["热门城市"] as List).map((e) { + return e["area"].toString(); + }).toList(); + areaMap.remove("热门城市"); + Map<String, dynamic> tempAreaMap = jsonDecode(value); + areaMap.forEach((key, value) { + if (searchTxt != null && searchTxt.trim() != "") + value.forEach((element) { + if (!element["area"].contains(searchTxt)) + (tempAreaMap[key] as List) + .removeWhere((el) => el["area"] == element["area"]); + }); + if (tempAreaMap[key].isNotEmpty) areaList.add(key); + }); + areaMap = tempAreaMap; + setState(() {}); + } + + queryIpInfo() async { + apiIpService = ApiService( + Dio(), + context: context, + isIp: true + ); + IpData baseData = await apiIpService.getIpInfo().catchError((onError) {}); + if (baseData?.city != null) { + ipName = baseData.city.replaceAll("市", ""); + if(ipName != widget.arguments["cityName"] ){ + ipState=2; + setState((){}); + } + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + resizeToAvoidBottomInset: false, + backgroundColor: Color(0xFFF0F0F0), + body: Container( + color: Color(0xFFF0F0F0), + child: Column( + children: [ + Container( + color: Colors.white, + padding: EdgeInsets.only(left: 14.w, top: 44.h, bottom: 24.h), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + Navigator.of(context).pop(); + }, + child: Container( + padding: EdgeInsets.only(right: 21.w), + child: Icon( + Icons.arrow_back_ios, + color: Colors.black, + ), + )), + Expanded(child: searchCityItem()) + ], + ), + Padding( + padding: EdgeInsets.only(top: 16.h, bottom: 24.h), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.only(right: 10.w), + child: Text( + (ipState == 0||ipState == 1) ? "当前位置" : "已选:", + style: TextStyle( + color: Color(0xFFA29E9E), + fontWeight: MyFontWeight.medium, + fontSize: 16.sp, + ), + ), + ), + Image.asset( + "assets/image/icon_union_location.webp", + width: 20, + height: 20, + ), + Expanded( + // padding: EdgeInsets.only( + // left: 8.w, + // ), + child: Text( + (ipState== 1) ? (ipName??""):widget.arguments["cityName"] ?? "", + style: TextStyle( + color: Color(0xFF4D4D4D), + fontWeight: MyFontWeight.medium, + fontSize: 16.sp, + ), + ), + ), + if(ipState == 2) + Icon( + Icons.gps_fixed, + color: Colors.grey, + size: 18, + ), + if(ipState == 2) + Padding(padding:EdgeInsets.only(left:5.w,right: 12.w), + child:GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: (){ + setState((){ + ipState = 1; + Navigator.of(context).pop(ipName); + }); + }, + child: Text( + "重新定位", + style: TextStyle( + color: Color(0xFF4D4D4D), + fontWeight: MyFontWeight.medium, + fontSize: 16.sp, + ), + ), + ),) + ], + )), + Padding( + padding: EdgeInsets.only(bottom: 16.h), + child: Text( + "热门城市", + style: TextStyle( + color: Color(0xFFA29E9E), + fontWeight: MyFontWeight.medium, + fontSize: 16.sp, + ), + ), + ), + GridView.builder( + itemCount: hotCity.length, + padding: EdgeInsets.only(right: 14.h, bottom: 14.h), + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 4, + crossAxisSpacing: 12.w, + mainAxisSpacing: 12.w, + childAspectRatio: 2.5, + ), + itemBuilder: (context, index) { + return GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + Navigator.of(context).pop(hotCity[index]); + setState((){}); + }, + child: Container( + decoration: BoxDecoration( + color: Color(0xFFF7F7F7), + borderRadius: BorderRadius.circular(4), + ), + alignment: Alignment.center, + child: Text( + hotCity[index], + style: TextStyle( + color: Color(0xFF4D4D4D), + fontWeight: MyFontWeight.medium, + fontSize: 16.sp, + ), + ))); + }, + ), + ], + ), + ), + Expanded(child: sortList()) + ], + ), + ), + ); + } + + Widget searchCityItem() { + return Container( + margin: EdgeInsets.fromLTRB(6.w, 0, 14.w, 0), + padding: EdgeInsets.symmetric(vertical: 6.h), + decoration: BoxDecoration( + color: Color(0xFFF1F1F1), + borderRadius: BorderRadius.circular(6), + boxShadow: [ + BoxShadow( + color: Colors.black.withAlpha(12), + offset: Offset(0, 3), + blurRadius: 14, + spreadRadius: 0, + ), + ], + ), + child: TextField( + textInputAction: TextInputAction.search, + onEditingComplete: () { + FocusScope.of(context).requestFocus(FocusNode()); + }, + onChanged: (txt) { + areaCode(searchTxt: txt); + }, + style: TextStyle( + fontSize: 14.sp, + ), + decoration: InputDecoration( + hintText: "搜索联盟会员店", + hintStyle: TextStyle( + fontSize: 12.sp, + color: Color(0xFFB3B3B3), + ), + isCollapsed: true, + prefixIcon:Padding(padding: EdgeInsets.only(left: 5.w,right: 5.w),child: Image.asset( + "assets/image/icon_search.webp", + width: 16.h, + height: 16.h, + ),), + prefixIconConstraints: BoxConstraints(), + border: InputBorder.none, + ), + ), + ); + } + + Widget sortList() { + return areaList.length != 0 ?ListView.builder( + padding: EdgeInsets.zero, + itemCount: areaList.length, + scrollDirection: Axis.vertical, + shrinkWrap: true, + physics: BouncingScrollPhysics(), + itemBuilder: (context, position) { + return GestureDetector( + onTap: () {}, + child: sortItem(position), + ); + }, + ):Padding(padding:EdgeInsets.only(top:12.h), + child: Text( + "抱歉,未找到相关位置,可尝试修改后重试", + style: TextStyle( + color: Color(0xFF4D4D4D), + fontWeight: MyFontWeight.medium, + fontSize: 14.sp, + ), + )); + } + + Widget sortItem(int position) { + return Column( + children: [ + Container( + width: double.infinity, + // color: Colors.white, + padding: EdgeInsets.only(top: 14.h, bottom: 4.h, left: 16.w), + margin: EdgeInsets.only(bottom: 12.h), + child: Text( + areaList[position], + style: TextStyle( + color: Color(0xFF4D4D4D), + fontWeight: MyFontWeight.medium, + fontSize: 16.sp, + ), + ), + ), + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6.w), + color: Colors.white, + ), + margin: EdgeInsets.symmetric(horizontal: 14.w), + padding: EdgeInsets.only( + top: 8.h, + ), + child: mapWidget(position), + ) + ], + ); + } + + Widget mapWidget(position) { + int mapIndex = 0; + return Column( + children: (areaMap[areaList[position]] as List).map((e) { + mapIndex += 1; + return globalRoamingItem( + e, mapIndex == areaMap[areaList[position]].length); + }).toList(), + ); + } + + Widget globalRoamingItem(data, isLast) { + return GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + Navigator.of(context).pop(data["area"]); + }, + child: Container( + width: double.infinity, + child: Text( + data["area"], + style: TextStyle( + color: Color(0xFF000000), + fontWeight: MyFontWeight.regular, + fontSize: 14.sp, + ), + ), + decoration: BoxDecoration( + border: isLast + ? null + : Border( + bottom: BorderSide( + width: 1.w, + color: Color(0xFFDCDCDC), + style: BorderStyle.solid, + ), + ), + ), + padding: EdgeInsets.only(top: 16.h, bottom: 16.h, left: 16.w), + ), + ); + } +} diff --git a/lib/utils/captcha_util.dart b/lib/utils/captcha_util.dart new file mode 100644 index 00000000..a84cd08b --- /dev/null +++ b/lib/utils/captcha_util.dart @@ -0,0 +1,86 @@ +import 'dart:convert'; +import 'package:steel_crypt/steel_crypt.dart'; +import 'package:convert/convert.dart'; +import 'package:crypto/crypto.dart'; + +class CaptchaUtil{ + ///aes加密 + /// [key]AesCrypt加密key + /// [content] 需要加密的内容字符串 + static String aesEncode({String key, String content}) { + var aesCrypt = AesCrypt( + key: base64UrlEncode(key.codeUnits), padding: PaddingAES.pkcs7); + return aesCrypt.ecb.encrypt(inp: content); + } + + ///aes解密 + /// [key]aes解密key + /// [content] 需要加密的内容字符串 + static String aesDecode({String key, String content}) { + var aesCrypt = AesCrypt( + key: base64UrlEncode(key.codeUnits), padding: PaddingAES.pkcs7); + return aesCrypt.ecb.decrypt(enc: content); + } + /// isEmpty. + static bool isEmpty(Object value) { + if (value == null) return true; + if (value is String && value.isEmpty) { + return true; + } + return false; + } + + //list length == 0 || list == null + static bool isListEmpty(Object value) { + if (value == null) return true; + if (value is List && value.length == 0) { + return true; + } + return false; + } + + static String jsonFormat(Map<dynamic, dynamic> map) { + Map _map = Map<String, Object>.from(map); + JsonEncoder encoder = JsonEncoder.withIndent(' '); + return encoder.convert(_map); + } + + + static String generateMd5(String data){ + var content = new Utf8Encoder().convert(data); + var digest = md5.convert(content); + return hex.encode(digest.bytes); + } + + static signData(Object params, tokenStr) async { + var time = new DateTime.now().millisecondsSinceEpoch; + String token = tokenStr; + Map<String, dynamic> reqData = new Map(); + Map<String, dynamic> paramsObj = new Map(); + paramsObj = params as Map<String, dynamic>; + var arr = []; + //将字典转成数组 + paramsObj?.forEach((key, value) => arr.add(key)); + //进行签名校验 + Map cr = new Map(); + cr['token'] = token; + cr['time'] = time.toString(); + cr['reqData'] = json.encode(paramsObj); + var array = []; + cr.forEach((key, value) => array.add(key)); + array.sort(); + var str = ''; + for (var i = 0; i < array.length; i++) { + var key = array[i]; + var value = cr[key]; + str += key + value; + } + + reqData["time"] = time; + reqData["token"] = token; + reqData['reqData'] = params; + reqData['sign'] = generateMd5(str); + + return reqData; + } +} \ No newline at end of file diff --git a/lib/utils/flutter_utils.dart b/lib/utils/flutter_utils.dart index 2811d185..f9257c79 100644 --- a/lib/utils/flutter_utils.dart +++ b/lib/utils/flutter_utils.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'dart:io'; import 'package:dio/dio.dart'; @@ -10,11 +11,11 @@ import 'package:path_provider/path_provider.dart'; class AppUtils { ///计算距离(当前位置到店位置直线距离) static Future<String> calculateDistance( - BMFCoordinate bmfCoordinate, BMFCoordinate myLatLng) async { + BMFCoordinate bmfCoordinate, BMFCoordinate myLatLng, {bool isMi = false}) async { double mi = await BMFCalculateUtils.getLocationDistance(bmfCoordinate, myLatLng); NumberFormat numberFormat = NumberFormat("#.#"); - return "${numberFormat.format(mi / 1000)}"; + return "${numberFormat.format(mi / (isMi ? 1 :1000))}"; } @@ -77,12 +78,12 @@ class AppUtils { return resString; } - ///坐标系转换 + ///坐标系转换(高德转百度) static Future<BMFCoordinate> coordConvert(BMFCoordinate latLng) async { return BMFCalculateUtils.coordConvert( coordinate: latLng, - fromType: BMF_COORD_TYPE.BD09LL, - toType: BMF_COORD_TYPE.COMMON); + fromType: BMF_COORD_TYPE.COMMON, + toType: BMF_COORD_TYPE.BD09LL); } static bool isPhone(mobile) { diff --git a/lib/utils/location.dart b/lib/utils/location.dart index f678878c..2b1f1482 100644 --- a/lib/utils/location.dart +++ b/lib/utils/location.dart @@ -11,10 +11,9 @@ import 'package:permission_handler/permission_handler.dart'; import 'font_weight.dart'; - BaiduLocationAndroidOption initAndroidOptions() { BaiduLocationAndroidOption options = BaiduLocationAndroidOption( - // 定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式 + // 定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式 locationMode: BMFLocationMode.hightAccuracy, // 是否需要返回地址信息 isNeedAddress: true, @@ -63,7 +62,6 @@ BaiduLocationIOSOption initIOSOptions() { return options; } - class Location { static Location _instance; @@ -80,17 +78,18 @@ class Location { LocationFlutterPlugin aMapFlutterLocation; - Future<bool> startLocation(context, Function(BaiduLocation result) locationCallback) async { - aMapFlutterLocation.prepareLoc(initAndroidOptions().getMap(), initIOSOptions().getMap()); - if (!(await Permission.locationWhenInUse.serviceStatus.isEnabled)) { - enableLocation(context); + Future<bool> startLocation( + context, Function(BaiduLocation result) locationCallback) async { + aMapFlutterLocation.prepareLoc( + initAndroidOptions().getMap(), initIOSOptions().getMap()); + var permissionStatus = await Permission.location.status; + if (!permissionStatus.isGranted) { + if (permissionStatus.isUndetermined) + showTipsAlertDialog(context); return false; - } - if (await Permission.location.isPermanentlyDenied) { - requestDialog(context, locationCallback); - return false; - } else if (await Permission.location.isGranted) { - aMapFlutterLocation.singleLocationCallback(callback: (BaiduLocation result) { + } else { + aMapFlutterLocation.singleLocationCallback( + callback: (BaiduLocation result) { locationCallback.call(result); }); if (Platform.isIOS) { @@ -102,21 +101,6 @@ class Location { await aMapFlutterLocation.startLocation(); } return true; - } else if (await Permission.location.isUndetermined) { - showAlertDialog(context); - await Permission.location.request(); - Navigator.of(context).pop(); - return false; - } else { - if (Platform.isIOS) { - //去设置中心 - requestDialog(context, locationCallback); - } else { - showAlertDialog(context); - await Permission.location.request(); - Navigator.of(context).pop(); - } - return false; } } @@ -172,56 +156,173 @@ class Location { } ///定位权限说明弹窗 - showAlertDialog(context) { + showTipsAlertDialog(context) async { //显示对话框 showDialog( context: context, + barrierDismissible: false, + barrierColor: null, builder: (BuildContext context) { - return SimpleDialog( - titlePadding: EdgeInsets.all(10), - backgroundColor: Colors.transparent, - elevation: 0, - alignment: Alignment.topCenter, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6), - ), - children: <Widget>[ + return Column( + children: [ Container( width: double.infinity, - height: 120.h, - padding: EdgeInsets.all(16), + padding: EdgeInsets.all(15), + margin: EdgeInsets.all(15), decoration: new BoxDecoration( color: Colors.white, - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(10), ), - child:Column( + child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "访问精确地理位置信息权限说明", - style: TextStyle( - fontSize: 15.sp, - fontWeight:MyFontWeight.regular, - color: Colors.black, - ), + Icon( + Icons.location_on_outlined, + color: Colors.black, + size: 22, ), - SizedBox(height: 3.h,), - Text( - "为了向您推荐附近的门店信息,推荐您在使用期间让我们使用位置信息,不授权该权限不影响app正常使用。", - style: TextStyle( - fontSize: 13.sp, - height: 1.3.h, - fontWeight:MyFontWeight.regular, - color: Colors.black, + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + // "访问精确地理位置信息权限说明", + "位置权限使用说明", + style: TextStyle( + fontSize: 18.sp, + fontWeight: MyFontWeight.regular, + color: Colors.black, + ), + ), + SizedBox( + height: 3.h, + ), + Text( + // "为了向您推荐附近的门店信息,推荐您在使用期间让我们使用位置信息,不授权该权限不影响app正常使用。", + "为了向您推荐附近的门店信息,推荐您在使用期间让我们使用位置信息", + style: TextStyle( + fontSize: 13.sp, + fontWeight: MyFontWeight.regular, + color: Colors.black, + ), + ), + ], ), ), ], ), - ), + ) ], + mainAxisSize: MainAxisSize.min, ); }, ); + await Permission.location.request(); + Navigator.of(context).pop(); } + ///定位权限说明和申请弹窗 + showAlertDialog(context) { + //显示对话框 + showDialog( + context: context, + barrierDismissible: true, + barrierColor: null, + builder: (BuildContext context) { + return Column( + children: [ + Container( + width: double.infinity, + padding: EdgeInsets.all(15), + margin: EdgeInsets.all(15), + decoration: new BoxDecoration( + color: Colors.black.withOpacity(0.6), + borderRadius: BorderRadius.circular(10), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + // "访问精确地理位置信息权限说明", + "定位服务未开启", + style: TextStyle( + fontSize: 18.sp, + fontWeight: MyFontWeight.regular, + color: Colors.white, + ), + ), + SizedBox( + height: 3.h, + ), + Text( + // "为了向您推荐附近的门店信息,推荐您在使用期间让我们使用位置信息,不授权该权限不影响app正常使用。", + "开启后才能提供更详细的定位服务哦!", + style: TextStyle( + fontSize: 13.sp, + fontWeight: MyFontWeight.regular, + color: Colors.white, + ), + ), + ], + ), + ), + GestureDetector( + child: Container( + child: Text( + "去开启", + style: TextStyle( + fontSize: 15.sp, + fontWeight: MyFontWeight.regular, + color: Colors.white, + ), + ), + margin: EdgeInsets.symmetric( + horizontal: 15.w, vertical: 25.h), + padding: + EdgeInsets.symmetric(vertical: 2.h, horizontal: 10.w), + decoration: BoxDecoration( + color: Colors.green, + borderRadius: BorderRadius.circular(100), + ), + ), + onTap: () async { + await openAppSettings(); + if (await Permission.location.isGranted) + Navigator.of(context).pop(); + }, + behavior: HitTestBehavior.opaque, + ), + GestureDetector( + behavior: HitTestBehavior.opaque, + child: Container( + child: Icon( + Icons.close, + color: Colors.white.withOpacity(0.8), + size: 12, + ), + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.8), + borderRadius: BorderRadius.circular(100), + ), + padding: EdgeInsets.all(5), + ), + onTap: () { + Navigator.of(context).pop(); + }, + ) + ], + ), + ) + ], + mainAxisSize: MainAxisSize.min, + ); + }, + ); + } } diff --git a/lib/utils/widget_util.dart b/lib/utils/widget_util.dart new file mode 100644 index 00000000..dabac5cb --- /dev/null +++ b/lib/utils/widget_util.dart @@ -0,0 +1,133 @@ +import 'dart:async'; + +import 'package:flutter/widgets.dart'; + +import 'captcha_util.dart'; +/** + * @Author: thl + * @GitHub: https://github.com/Sky24n + * @Email: 863764940@qq.com + * @Email: sky24no@gmail.com + * @Description: Widget Util. + * @Date: 2018/9/10 + */ + +/// Widget Util. +class WidgetUtil { + bool _hasMeasured = false; + double _width; + double _height; + + /// Widget rendering listener. + /// Widget渲染监听. + /// context: Widget context. + /// isOnce: true,Continuous monitoring false,Listen only once. + /// onCallBack: Widget Rect CallBack. + void asyncPrepare( + BuildContext context, bool isOnce, ValueChanged<Rect> onCallBack) { + if (_hasMeasured) return; + WidgetsBinding.instance.addPostFrameCallback((Duration timeStamp) { + RenderObject box = context.findRenderObject(); + if (box != null) { + if (isOnce) _hasMeasured = true; + double width = box.semanticBounds.width; + double height = box.semanticBounds.height; + if (_width != width || _height != height) { + _width = width; + _height = height; + if (onCallBack != null) onCallBack(box.semanticBounds); + } + } + }); + } + + /// Widget渲染监听. + void asyncPrepares(bool isOnce, ValueChanged<Rect> onCallBack) { + if (_hasMeasured) return; + WidgetsBinding.instance.addPostFrameCallback((Duration timeStamp) { + if (isOnce) _hasMeasured = true; + if (onCallBack != null) onCallBack(null); + }); + } + + ///get Widget Bounds (width, height, left, top, right, bottom and so on).Widgets must be rendered completely. + ///获取widget Rect + static Rect getWidgetBounds(BuildContext context) { + RenderObject box = context.findRenderObject(); + return (box != null) ? box.semanticBounds : Rect.zero; + } + + ///Get the coordinates of the widget on the screen.Widgets must be rendered completely. + ///获取widget在屏幕上的坐标,widget必须渲染完成 + static Offset getWidgetLocalToGlobal(BuildContext context) { + RenderBox box = context.findRenderObject() as RenderBox; + return box == null ? Offset.zero : box.localToGlobal(Offset.zero); + } + + /// get image width height,load error return Rect.zero.(unit px) + /// 获取图片宽高,加载错误情况返回 Rect.zero.(单位 px) + /// image + /// url network + /// local url , package + static Future<Rect> getImageWH( + {Image image, String url, String localUrl, String package}) { + if (CaptchaUtil.isEmpty(image) && + CaptchaUtil.isEmpty(url) && + CaptchaUtil.isEmpty(localUrl)) { + return Future.value(Rect.zero); + } + Completer<Rect> completer = Completer<Rect>(); + Image img = image ?? ((url != null && url.isNotEmpty) + ? Image.network(url) + : Image.asset(localUrl, package: package)); + img.image + .resolve(const ImageConfiguration()) + .addListener(ImageStreamListener( + (ImageInfo info, bool _) { + completer.complete(Rect.fromLTWH(0, 0, info.image.width.toDouble(), + info.image.height.toDouble())); + }, + onError: (Object exception, StackTrace stackTrace) { + completer.completeError(exception, stackTrace); + }, + )); + return completer.future; + } + + /// get image width height, load error throw exception.(unit px) + /// 获取图片宽高,加载错误会抛出异常.(单位 px) + /// image + /// url network + /// local url (full path/全路径,example:"assets/images/ali_connors.png",""assets/images/3.0x/ali_connors.png"" ); + /// package + static Future<Rect> getImageWHE( + {Image image, + String url, + String localUrl, + String package}) { + if (CaptchaUtil.isEmpty(image) && + CaptchaUtil.isEmpty(url) && + CaptchaUtil.isEmpty(localUrl)) { + return Future.error("image is null."); + } + Completer<Rect> completer = Completer<Rect>(); + Image img = image != null + ? image + : ((url != null && url.isNotEmpty) + ? Image.network(url) + : Image.asset(localUrl, package: package)); + img.image + .resolve(const ImageConfiguration()) + .addListener(ImageStreamListener( + (ImageInfo info, bool _) { + completer.complete(Rect.fromLTWH(0, 0, info.image.width.toDouble(), + info.image.height.toDouble())); + }, + onError: (Object exception, StackTrace stackTrace) { + completer.completeError(exception, stackTrace); + }, + )); + + return completer.future; + } +} diff --git a/lib/view_widget/channel_dialog.dart b/lib/view_widget/channel_dialog.dart index 9e133439..9b235dd9 100644 --- a/lib/view_widget/channel_dialog.dart +++ b/lib/view_widget/channel_dialog.dart @@ -28,7 +28,7 @@ class _ChannelDialog extends State<ChannelDialog> { @override void initState() { super.initState(); - EasyLoading.show(status: S.current.zhengzaijiazai); + EasyLoading.show(status: S.current.zhengzaijiazai,maskType: EasyLoadingMaskType.black); queryChannels(); } diff --git a/lib/view_widget/location_tips.dart b/lib/view_widget/location_tips.dart new file mode 100644 index 00000000..726b94ad --- /dev/null +++ b/lib/view_widget/location_tips.dart @@ -0,0 +1,120 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:huixiang/retrofit/data/activity_pos.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:permission_handler/permission_handler.dart'; + +import '../retrofit/data/login_info.dart'; +import '../utils/font_weight.dart'; +import 'custom_image.dart'; +import 'new_people_reward.dart'; + +class LocationTips extends StatefulWidget { + final Function disMissLocationTips; + + LocationTips(this.disMissLocationTips); + + @override + State<StatefulWidget> createState() { + return _LocationTips(); + } +} + +class _LocationTips extends State<LocationTips> { + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + padding: EdgeInsets.all(10), + margin: EdgeInsets.only(left: 15.w, right: 15.w, bottom: 15.h), + decoration: new BoxDecoration( + color: Colors.black.withOpacity(0.8), + borderRadius: BorderRadius.circular(10), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + // "访问精确地理位置信息权限说明", + "定位服务未开启", + style: TextStyle( + fontSize: 16.sp, + fontWeight: MyFontWeight.regular, + color: Colors.white, + ), + ), + SizedBox( + height: 3.h, + ), + Text( + // "为了向您推荐附近的门店信息,推荐您在使用期间让我们使用位置信息,不授权该权限不影响app正常使用。", + "开启后才能提供更详细的定位服务哦!", + style: TextStyle( + fontSize: 13.sp, + fontWeight: MyFontWeight.regular, + color: Colors.white, + ), + ), + ], + ), + ), + GestureDetector( + child: Container( + child: Text( + "去开启", + style: TextStyle( + fontSize: 13.sp, + fontWeight: MyFontWeight.regular, + color: Colors.white, + ), + ), + margin: EdgeInsets.only(left: 15.w, right: 15.w, top: 15.h), + padding: EdgeInsets.symmetric(vertical: 2.h, horizontal: 10.w), + decoration: BoxDecoration( + color: Colors.green, + borderRadius: BorderRadius.circular(100), + ), + ), + onTap: () async { + if (!await openAppSettings()) { + SmartDialog.showToast("打开应用设置失败,请手动前往系统设置中心开启应用位置权限", + alignment: Alignment.center); + } + }, + behavior: HitTestBehavior.opaque, + ), + GestureDetector( + behavior: HitTestBehavior.opaque, + child: Container( + child: Icon( + Icons.close, + color: Colors.white.withOpacity(0.8), + size: 10, + ), + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.8), + borderRadius: BorderRadius.circular(100), + ), + padding: EdgeInsets.all(3), + ), + onTap: () { + widget.disMissLocationTips(); + }, + ) + ], + ), + ); + } +} diff --git a/lib/view_widget/my_appbar.dart b/lib/view_widget/my_appbar.dart index 7a3ce7c5..52760e27 100644 --- a/lib/view_widget/my_appbar.dart +++ b/lib/view_widget/my_appbar.dart @@ -70,8 +70,7 @@ class MyAppBar extends StatelessWidget implements PreferredSizeWidget { }, child: Container( alignment: Alignment.centerRight, - margin: EdgeInsets.only(left: 12,), - padding: EdgeInsets.all(6), + padding: EdgeInsets.only(top: 6.h,bottom: 6.h,left:20.w,right:6.w), child: Icon( Icons.arrow_back_ios, color: leadingColor, diff --git a/lib/view_widget/new_people_reward.dart b/lib/view_widget/new_people_reward.dart index ad29fd59..691c7708 100644 --- a/lib/view_widget/new_people_reward.dart +++ b/lib/view_widget/new_people_reward.dart @@ -27,7 +27,7 @@ class _NewPeopleReward extends State<NewPeopleReward> { width: double.infinity, height: 500.h, padding: EdgeInsets.only(top: 210.h), - margin: EdgeInsets.only(top: 20.h, left: 20, right: 20), + margin: EdgeInsets.only(top: 20.h, left: 20.w, right: 20.w), decoration: BoxDecoration( image: DecorationImage( fit: BoxFit.fill, @@ -58,7 +58,7 @@ class _NewPeopleReward extends State<NewPeopleReward> { borderRadius: BorderRadius.circular(22.5), ), width: MediaQuery.of(context).size.width, - height: 40, + height: 40.h, alignment: Alignment.center, child: Text( S.of(context).lijilingqu, @@ -73,7 +73,7 @@ class _NewPeopleReward extends State<NewPeopleReward> { ], ), ), - SizedBox(height: 35), + SizedBox(height: 35.h), GestureDetector( onTap: () { setState(() { @@ -82,8 +82,8 @@ class _NewPeopleReward extends State<NewPeopleReward> { }, child: Image.asset( "assets/image/yq_qx.webp", - width: 34, - height: 34, + width: 34.h, + height: 34.h, ), ) ], @@ -117,7 +117,7 @@ class _NewPeopleReward extends State<NewPeopleReward> { image: AssetImage("assets/image/xin_rq.webp"), ), ), - margin: EdgeInsets.symmetric(horizontal: 60, vertical: 5), + margin: EdgeInsets.symmetric(horizontal: 50.w, vertical: 5.h), padding: EdgeInsets.only(left: 16.w, right: 25.w), child: Row( crossAxisAlignment: CrossAxisAlignment.center, @@ -150,13 +150,13 @@ class _NewPeopleReward extends State<NewPeopleReward> { ), ), Expanded(child:Padding( - padding: EdgeInsets.only(top: 4, bottom: 4,left:30), + padding: EdgeInsets.only(top: 4.h, bottom: 4.h,left:30.w), child: Column( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - firstLoginCouponList.storeName, + firstLoginCouponList.couponName, overflow: TextOverflow.ellipsis, maxLines: 2, style: TextStyle( @@ -166,7 +166,7 @@ class _NewPeopleReward extends State<NewPeopleReward> { ), ), Text( - firstLoginCouponList.couponName, + firstLoginCouponList.storeName, overflow: TextOverflow.ellipsis, maxLines: 1, style: TextStyle( diff --git a/lib/view_widget/recharge_details_dialog.dart b/lib/view_widget/recharge_details_dialog.dart index 5d180df4..aa93077e 100644 --- a/lib/view_widget/recharge_details_dialog.dart +++ b/lib/view_widget/recharge_details_dialog.dart @@ -1,15 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_html/flutter_html.dart'; -import 'package:huixiang/generated/l10n.dart'; -import 'package:huixiang/retrofit/data/coupon.dart'; -import 'package:huixiang/retrofit/data/recharge_list.dart'; -import 'package:huixiang/retrofit/data/store.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:huixiang/store/scan.dart'; import 'package:huixiang/utils/font_weight.dart'; -import 'package:huixiang/view_widget/border_text.dart'; -import 'package:huixiang/view_widget/custom_image.dart'; -import 'package:huixiang/view_widget/round_button.dart'; import '../retrofit/data/rechargeActLists.dart'; diff --git a/lib/vip/user_vip_service_page.dart b/lib/vip/user_vip_service_page.dart index 29a2d908..038ec2d9 100644 --- a/lib/vip/user_vip_service_page.dart +++ b/lib/vip/user_vip_service_page.dart @@ -25,7 +25,7 @@ class _UserVipServicePage extends State<UserVipServicePage> with WidgetsBindingO void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); - EasyLoading.show(status: S.current.zhengzaijiazai); + EasyLoading.show(status: S.current.zhengzaijiazai,maskType: EasyLoadingMaskType.black); if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView(); if (Platform.isIOS) WebView.platform = CupertinoWebView(); } diff --git a/pubspec.lock b/pubspec.lock index 221953a7..71750e46 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -15,6 +15,20 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.0.2" + args: + dependency: transitive + description: + name: args + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.3.1" + asn1lib: + dependency: transitive + description: + name: asn1lib + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.4.1" async: dependency: transitive description: @@ -64,20 +78,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.3.1" - charts_common: - dependency: transitive - description: - name: charts_common - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.12.0" - charts_flutter: - dependency: "direct main" - description: - name: charts_flutter - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.12.0" chewie: dependency: transitive description: @@ -106,6 +106,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.16.0" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.1.0" crypto: dependency: transitive description: @@ -141,13 +148,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.4.1" - equatable: - dependency: transitive + encrypt: + dependency: "direct main" description: - name: equatable + name: encrypt url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.5" + version: "5.0.1" event_bus: dependency: "direct main" description: @@ -176,13 +183,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "6.1.4" - fl_chart: - dependency: "direct main" - description: - name: fl_chart - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.62.0" flare_flutter: dependency: "direct main" description: @@ -291,13 +291,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "5.0.0+1" - flutter_skeleton: - dependency: "direct main" - description: - name: flutter_skeleton - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.1.0+1" flutter_slidable: dependency: "direct main" description: @@ -311,7 +304,7 @@ packages: name: flutter_smart_dialog url: "https://pub.flutter-io.cn" source: hosted - version: "3.5.0" + version: "3.0.6" flutter_spinkit: dependency: "direct main" description: @@ -364,6 +357,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "9.2.0" + gbk2utf8: + dependency: "direct main" + description: + name: gbk2utf8 + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.1" gradient_widgets: dependency: "direct main" description: @@ -398,7 +398,7 @@ packages: name: image_pickers url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.4+1" + version: "2.0.0" intl: dependency: "direct main" description: @@ -441,13 +441,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.4.0" - logging: - dependency: transitive - description: - name: logging - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.1.0" matcher: dependency: transitive description: @@ -609,6 +602,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.0.3" + pointycastle: + dependency: transitive + description: + name: pointycastle + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.7.3" process: dependency: transitive description: @@ -768,6 +768,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.10.0" + steel_crypt: + dependency: "direct main" + description: + name: steel_crypt + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.0+1" stream_channel: dependency: transitive description: @@ -782,20 +789,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" - syncfusion_flutter_core: - dependency: transitive - description: - name: syncfusion_flutter_core - url: "https://pub.flutter-io.cn" - source: hosted - version: "19.4.56" - syncfusion_flutter_datepicker: - dependency: "direct main" - description: - name: syncfusion_flutter_datepicker - url: "https://pub.flutter-io.cn" - source: hosted - version: "19.4.56" table_calendar: dependency: "direct main" description: @@ -830,13 +823,13 @@ packages: name: tobias url: "https://pub.flutter-io.cn" source: hosted - version: "2.4.2" + version: "2.4.1" tpns_flutter_plugin: dependency: "direct main" description: path: "." ref: "V1.1.6" - resolved-ref: c21ce8a966f9238a5bf70a617c30468b79baa5a7 + resolved-ref: a7e45d151171f9ec4b56bc97a720f545aa4a8722 url: "https://github.com/TencentCloud/TPNS-Flutter-Plugin" source: git version: "1.1.6" @@ -952,6 +945,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.0.15" + visibility_detector: + dependency: "direct main" + description: + name: visibility_detector + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.3.3" wakelock: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 0dad5a8e..71b7b705 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: 一心回乡. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 3.2.16+60 +version: 3.2.20+63 environment: sdk: ">=2.7.0 <3.0.0" @@ -13,9 +13,10 @@ dependencies: sdk: flutter flutter_localizations: sdk: flutter - fluwx: ^3.9.0+2 + fluwx: 3.9.0+2 + + tobias: 2.4.1 - tobias: ^2.4.1 gradient_widgets: ^0.6.0 @@ -40,11 +41,11 @@ dependencies: permission_handler: ^5.0.1+1 - flutter_bmflocation: ^3.2.1 - flutter_baidu_mapapi_base: ^3.2.0 - flutter_baidu_mapapi_map: ^3.2.1 - flutter_baidu_mapapi_search: ^3.2.0 - flutter_baidu_mapapi_utils: ^3.2.0 + flutter_bmflocation: 3.2.1 + flutter_baidu_mapapi_base: 3.2.0 + flutter_baidu_mapapi_map: 3.2.1 + flutter_baidu_mapapi_search: 3.2.0 + flutter_baidu_mapapi_utils: 3.2.0 dio: ^3.0.10 rxdart: ^0.26.0 @@ -54,9 +55,16 @@ dependencies: pin_input_text_field: ^4.1.2 android_intent_plus: ^1.0.2 - flutter_screenutil: ^5.0.0+1 + flutter_screenutil: 5.0.0+1 bubble_tab_indicator: ^0.1.6 + gbk2utf8: ^1.0.1 + + visibility_detector: ^0.3.3 + + steel_crypt: ^3.0.0+1 + encrypt: ^5.0.1 + event_bus: ^2.0.0 intl: ^0.17.0 shared_preferences: ^2.0.6 @@ -67,7 +75,7 @@ dependencies: url_launcher: ^5.0.0 #多图, 裁剪 - image_pickers: ^2.0.0 + image_pickers: 2.0.0 # flutter_scankit: ^1.2.0 # qrscan: ^0.3.1