├── .DS_Store ├── .gitignore ├── .idea ├── GHMall.iml ├── codeStyles │ └── Project.xml ├── encodings.xml ├── libraries │ ├── Dart_Packages.xml │ ├── Dart_SDK.xml │ ├── Flutter_Plugins.xml │ └── KotlinJavaRuntime.xml ├── misc.xml ├── modules.xml ├── runConfigurations │ └── main_dart.xml ├── vcs.xml └── workspace.xml ├── .metadata ├── 2f7f1a6d17a91f4167b85af5a47c65b131f3a64268732-eYhpx3_fw658副本.png ├── GHMall.iml ├── LICENSE ├── README.md ├── android ├── .gitignore ├── GHMall_android.iml ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── GHMall │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable │ │ │ └── launch_background.xml │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ │ └── values │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── ghome_project.iml ├── images ├── .DS_Store ├── 2.0x │ ├── bg.png │ ├── logo.png │ ├── user.png │ └── user_bg.jpg ├── 3.0x │ ├── bg.png │ ├── logo.png │ ├── user.png │ └── user_bg.jpg ├── bg.jpg ├── checkNormal.png ├── checkSelected.png ├── collect.png ├── customerService.png ├── down.png ├── downSeletecd.png ├── filter.png ├── filterSeletecd.png ├── goPublic.png ├── logo.png ├── pay_alipay.png ├── pay_wechat.png ├── price.png ├── screen.png ├── serviceIcon.png ├── shop.png ├── shoppingCart.png ├── thickness.png ├── up.png ├── upSeletecd.png ├── user.png └── user_bg.jpg ├── ios ├── .DS_Store ├── .gitignore ├── Flutter │ ├── .last_build_id │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Podfile ├── Podfile.lock ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── icon-1024.png │ │ ├── icon-20-ipad.png │ │ ├── icon-20@2x-ipad.png │ │ ├── icon-20@2x.png │ │ ├── icon-20@3x.png │ │ ├── icon-29-ipad.png │ │ ├── icon-29.png │ │ ├── icon-29@2x-ipad.png │ │ ├── icon-29@2x.png │ │ ├── icon-29@3x.png │ │ ├── icon-40.png │ │ ├── icon-40@2x.png │ │ ├── icon-40@3x.png │ │ ├── icon-60@2x.png │ │ ├── icon-60@3x.png │ │ ├── icon-76.png │ │ ├── icon-76@2x.png │ │ └── icon-83.5@2x.png │ └── LaunchImage.imageset │ │ ├── Contents.json │ │ ├── LaunchImage.png │ │ ├── LaunchImage@2x.png │ │ ├── LaunchImage@3x.png │ │ └── README.md │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h ├── lib ├── .DS_Store ├── generated_plugin_registrant.dart ├── main.dart ├── model │ ├── .DS_Store │ ├── GHAddressModel.dart │ ├── GHCategoryModel.dart │ ├── GHGoodDetailsModel.dart │ ├── GHGoodsModel.dart │ ├── GHGuessLikeModel.dart │ ├── GHHotGoodsModel.dart │ └── GHomeCarouselDataModel.dart ├── pages │ ├── .DS_Store │ ├── Cart │ │ └── CartItem.dart │ ├── GHAddressEdit.dart │ ├── GHAddressList.dart │ ├── GHCheckOutPage.dart │ ├── GHGoodsDetails.dart │ ├── GHGoodsList.dart │ ├── GHLoginPage.dart │ ├── GHOnlinePayments.dart │ ├── GHOrderList.dart │ ├── Search.dart │ ├── Test.dart │ └── tabs │ │ ├── GHCategoryPage.dart │ │ ├── GHHomePage.dart │ │ ├── GHShopCartPage.dart │ │ ├── GHUserPage.dart │ │ └── Tabs.dart ├── provider │ └── Cart.dart ├── routers │ └── router.dart ├── services │ ├── EventBus.dart │ ├── GHLog.dart │ ├── GHToast.dart │ ├── ScreenAdaper.dart │ ├── SearchServices.dart │ ├── Storage.dart │ ├── gh_sqflite.dart │ └── httptool.dart └── widget │ ├── GHButton.dart │ ├── GHCountItemWidget.dart │ ├── GHCustomAppbar.dart │ ├── GHDialog.dart │ ├── GHLoading.dart │ ├── GHRichTextPriceWidget.dart │ ├── GHTextWidget.dart │ └── LoadingWidget.dart ├── pubspec.yaml └── test └── widget_test.dart /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://www.dartlang.org/guides/libraries/private-files 2 | 3 | # Files and directories created by pub 4 | .dart_tool/ 5 | .packages 6 | build/ 7 | # If you're building an application, you may want to check-in your pubspec.lock 8 | pubspec.lock 9 | 10 | # Directory created by dartdoc 11 | # If you don't generate documentation locally you can remove this line. 12 | doc/api/ 13 | *.psd 14 | 15 | # Avoid committing generated Javascript files: 16 | *.dart.js 17 | *.info.json # Produced by the --dump-info flag. 18 | *.js # When generated by dart2js. Don't specify *.js if your 19 | # project includes source files written in JavaScript. 20 | *.js_ 21 | *.js.deps 22 | *.js.map 23 | 24 | .flutter-plugins 25 | .flutter-plugins-dependencies -------------------------------------------------------------------------------- /.idea/GHMall.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/libraries/Dart_SDK.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/libraries/Flutter_Plugins.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/libraries/KotlinJavaRuntime.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/runConfigurations/main_dart.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | 20 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 1592740531740 58 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | file://$PROJECT_DIR$/lib/pages/GHGoodsDetails.dart 107 | 109 | 110 | file://$PROJECT_DIR$/lib/main.dart 111 | 10 112 | 114 | 115 | file://$PROJECT_DIR$/lib/pages/tabs/GHCategoryPage.dart 116 | 300 117 | 119 | 120 | file://$PROJECT_DIR$/lib/widget/GHButton.dart 121 | 6 122 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 1aafb3a8b9b0c36241c5f5b34ee914770f015818 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /2f7f1a6d17a91f4167b85af5a47c65b131f3a64268732-eYhpx3_fw658副本.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/2f7f1a6d17a91f4167b85af5a47c65b131f3a64268732-eYhpx3_fw658副本.png -------------------------------------------------------------------------------- /GHMall.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 GHome 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GHMall 2 | 3 | ![2f7f1a6d17a91f4167b85af5a47c65b131f3a64268732-eYhpx3_fw658副本.png](https://upload-images.jianshu.io/upload_images/668798-fe7c1d5f80822290.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 4 | 5 | 一个练习的flutter电商项目,基本功能已经完成。 6 | 7 | 环境 8 | 9 | ``` 10 | Flutter 2.0.0 • channel stable • https://github.com/flutter/flutter.git 11 | Framework • revision 60bd88df91 (10 hours ago) • 2021-03-03 09:13:17 -0800 12 | Engine • revision 40441def69 13 | Tools • Dart 2.12.0 14 | 15 | ``` 16 | 如果还没有配置环境,[跳转](https://github.com/shabake/Configure-the-Flutter-environment)配置`Flutter`环境 17 | 18 | 19 | #### 体验demo 20 | ![](https://oscimg.oschina.net/oscnet/up-ce4747b9241fd24f078e0b269925672b53d.png) 21 | 22 | 23 | #### 安装方法: 24 | 25 | ``` 26 | cd 你要存放的目录 27 | ``` 28 | 29 | ``` 30 | git clone https://github.com/shabake/GHMall.git 31 | ``` 32 | 33 | ``` 34 | flutter pub get 35 | ``` 36 | 37 | 如果终端输出 38 | 39 | ``` 40 | Waiting for another flutter command to release the startup lock 41 | ``` 42 | 找到`flutterSDK`文件夹 43 | 44 | 如`flutter/bin/cache` 45 | 46 | 删除`lockfile` 47 | 48 | 重新执行`flutter pub get ` 49 | 50 | 运行一个`iOS`或安卓模拟器 51 | 52 | 如果连接真机`iOS`打开在`GHMall/ios/Runner.xcworkspace` 53 | 54 | 配置开发者账户 55 | 56 | 最后执行`flutter run` 57 | 58 | 59 | 60 | ##  项目中用到的插件 61 | 62 | | 名称 | 描述 | 63 | | ----------------------------- | ------------ | 64 | | dio | 网络请求 | 65 | | fluttertoast | 提示 toast | 66 | | sqflite | 数据持久化 | 67 | | flutter_swiper | 轮播图 | 68 | | flutter_screenutil | 屏幕适配 | 69 | | cached_network_image | 缓存网络图片 | 70 | | shared_preferences | 本地存储 | 71 | | event_bus | 事件通知 | 72 | | provider | 状态管理 | 73 | | flutter_screenutil | 屏幕适配 | 74 | | city_pickers | 城市选择器 | 75 | | flutter_easyrefresh | 刷新控件 | 76 | | transparent_image | 图片动画 | 77 | 78 | ```diff 79 | 已经实现 80 | + 实现用户注册登录 81 | + 商品浏览 82 | + 商品属性筛选 83 | + 添加商品 84 | + 购物车增加减少商品 85 | + 提交订单 86 | + 已经适配iOS,测试模拟器iPhone11 87 | 88 | 计划实现 89 | - 用户登录验证码倒计时 90 | - 用户地址 91 | - 用户订单列表查看 92 | - 用户订单详情 93 | 94 | ``` 95 | 96 | 97 | 98 | ### 在使用中如有任何问题欢迎骚扰我,如果对你有帮助请点帮我一个✨,小弟感激不尽:blush: 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | -------------------------------------------------------------------------------- /android/GHMall_android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 29 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | lintOptions { 36 | disable 'InvalidPackage' 37 | } 38 | 39 | defaultConfig { 40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 41 | applicationId "com.example.GHMall" 42 | minSdkVersion 16 43 | targetSdkVersion 29 44 | versionCode flutterVersionCode.toInteger() 45 | versionName flutterVersionName 46 | } 47 | 48 | buildTypes { 49 | release { 50 | // TODO: Add your own signing config for the release build. 51 | // Signing with the debug keys for now, so `flutter run --release` works. 52 | signingConfig signingConfigs.debug 53 | } 54 | } 55 | } 56 | 57 | flutter { 58 | source '../..' 59 | } 60 | 61 | dependencies { 62 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 63 | } 64 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 14 | 15 | 22 | 26 | 30 | 35 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/example/GHMall/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.GHMall 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.5.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | android.enableR8=true 5 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip 7 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /ghome_project.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /images/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/.DS_Store -------------------------------------------------------------------------------- /images/2.0x/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/2.0x/bg.png -------------------------------------------------------------------------------- /images/2.0x/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/2.0x/logo.png -------------------------------------------------------------------------------- /images/2.0x/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/2.0x/user.png -------------------------------------------------------------------------------- /images/2.0x/user_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/2.0x/user_bg.jpg -------------------------------------------------------------------------------- /images/3.0x/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/3.0x/bg.png -------------------------------------------------------------------------------- /images/3.0x/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/3.0x/logo.png -------------------------------------------------------------------------------- /images/3.0x/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/3.0x/user.png -------------------------------------------------------------------------------- /images/3.0x/user_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/3.0x/user_bg.jpg -------------------------------------------------------------------------------- /images/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/bg.jpg -------------------------------------------------------------------------------- /images/checkNormal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/checkNormal.png -------------------------------------------------------------------------------- /images/checkSelected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/checkSelected.png -------------------------------------------------------------------------------- /images/collect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/collect.png -------------------------------------------------------------------------------- /images/customerService.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/customerService.png -------------------------------------------------------------------------------- /images/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/down.png -------------------------------------------------------------------------------- /images/downSeletecd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/downSeletecd.png -------------------------------------------------------------------------------- /images/filter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/filter.png -------------------------------------------------------------------------------- /images/filterSeletecd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/filterSeletecd.png -------------------------------------------------------------------------------- /images/goPublic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/goPublic.png -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/logo.png -------------------------------------------------------------------------------- /images/pay_alipay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/pay_alipay.png -------------------------------------------------------------------------------- /images/pay_wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/pay_wechat.png -------------------------------------------------------------------------------- /images/price.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/price.png -------------------------------------------------------------------------------- /images/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/screen.png -------------------------------------------------------------------------------- /images/serviceIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/serviceIcon.png -------------------------------------------------------------------------------- /images/shop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/shop.png -------------------------------------------------------------------------------- /images/shoppingCart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/shoppingCart.png -------------------------------------------------------------------------------- /images/thickness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/thickness.png -------------------------------------------------------------------------------- /images/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/up.png -------------------------------------------------------------------------------- /images/upSeletecd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/upSeletecd.png -------------------------------------------------------------------------------- /images/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/user.png -------------------------------------------------------------------------------- /images/user_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/images/user_bg.jpg -------------------------------------------------------------------------------- /ios/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/.DS_Store -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /ios/Flutter/.last_build_id: -------------------------------------------------------------------------------- 1 | a67acd9601eb94d3b5d8b2f461b84a41 -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | end 36 | 37 | post_install do |installer| 38 | installer.pods_project.targets.each do |target| 39 | flutter_additional_ios_build_settings(target) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Flutter (1.0.0) 3 | - flutter_webview_plugin (0.0.1): 4 | - Flutter 5 | - fluttertoast (0.0.2): 6 | - Flutter 7 | - FMDB (2.7.5): 8 | - FMDB/standard (= 2.7.5) 9 | - FMDB/standard (2.7.5) 10 | - HandyJSON (5.0.2) 11 | - shared_preferences (0.0.1): 12 | - Flutter 13 | - sqflite (0.0.2): 14 | - Flutter 15 | - FMDB (>= 2.7.5) 16 | - tencent_im_plugin (0.0.1): 17 | - Flutter 18 | - HandyJSON 19 | - TXIMSDK_iOS (= 4.6.58) 20 | - TXIMSDK_iOS (4.6.58) 21 | 22 | DEPENDENCIES: 23 | - Flutter (from `Flutter`) 24 | - flutter_webview_plugin (from `.symlinks/plugins/flutter_webview_plugin/ios`) 25 | - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) 26 | - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`) 27 | - sqflite (from `.symlinks/plugins/sqflite/ios`) 28 | - tencent_im_plugin (from `.symlinks/plugins/tencent_im_plugin/ios`) 29 | 30 | SPEC REPOS: 31 | trunk: 32 | - FMDB 33 | - HandyJSON 34 | - TXIMSDK_iOS 35 | 36 | EXTERNAL SOURCES: 37 | Flutter: 38 | :path: Flutter 39 | flutter_webview_plugin: 40 | :path: ".symlinks/plugins/flutter_webview_plugin/ios" 41 | fluttertoast: 42 | :path: ".symlinks/plugins/fluttertoast/ios" 43 | shared_preferences: 44 | :path: ".symlinks/plugins/shared_preferences/ios" 45 | sqflite: 46 | :path: ".symlinks/plugins/sqflite/ios" 47 | tencent_im_plugin: 48 | :path: ".symlinks/plugins/tencent_im_plugin/ios" 49 | 50 | SPEC CHECKSUMS: 51 | Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c 52 | flutter_webview_plugin: ed9e8a6a96baf0c867e90e1bce2673913eeac694 53 | fluttertoast: b644586ef3b16f67fae9a1f8754cef6b2d6b634b 54 | FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a 55 | HandyJSON: 9e4e236f5d2dbefad5155a77417bbea438201c03 56 | shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d 57 | sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 58 | tencent_im_plugin: a055ed155fd2cae7f006e756dbec96255b4aa0a3 59 | TXIMSDK_iOS: d4231ccd8a045f54ca04d008dba46fdbf25687fb 60 | 61 | PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c 62 | 63 | COCOAPODS: 1.9.3 64 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "size": "20x20", 5 | "idiom": "iphone", 6 | "filename": "icon-20@2x.png", 7 | "scale": "2x" 8 | }, 9 | { 10 | "size": "20x20", 11 | "idiom": "iphone", 12 | "filename": "icon-20@3x.png", 13 | "scale": "3x" 14 | }, 15 | { 16 | "size": "29x29", 17 | "idiom": "iphone", 18 | "filename": "icon-29.png", 19 | "scale": "1x" 20 | }, 21 | { 22 | "size": "29x29", 23 | "idiom": "iphone", 24 | "filename": "icon-29@2x.png", 25 | "scale": "2x" 26 | }, 27 | { 28 | "size": "29x29", 29 | "idiom": "iphone", 30 | "filename": "icon-29@3x.png", 31 | "scale": "3x" 32 | }, 33 | { 34 | "size": "40x40", 35 | "idiom": "iphone", 36 | "filename": "icon-40@2x.png", 37 | "scale": "2x" 38 | }, 39 | { 40 | "size": "40x40", 41 | "idiom": "iphone", 42 | "filename": "icon-40@3x.png", 43 | "scale": "3x" 44 | }, 45 | { 46 | "size": "60x60", 47 | "idiom": "iphone", 48 | "filename": "icon-60@2x.png", 49 | "scale": "2x" 50 | }, 51 | { 52 | "size": "60x60", 53 | "idiom": "iphone", 54 | "filename": "icon-60@3x.png", 55 | "scale": "3x" 56 | }, 57 | { 58 | "size": "20x20", 59 | "idiom": "ipad", 60 | "filename": "icon-20-ipad.png", 61 | "scale": "1x" 62 | }, 63 | { 64 | "size": "20x20", 65 | "idiom": "ipad", 66 | "filename": "icon-20@2x-ipad.png", 67 | "scale": "2x" 68 | }, 69 | { 70 | "size": "29x29", 71 | "idiom": "ipad", 72 | "filename": "icon-29-ipad.png", 73 | "scale": "1x" 74 | }, 75 | { 76 | "size": "29x29", 77 | "idiom": "ipad", 78 | "filename": "icon-29@2x-ipad.png", 79 | "scale": "2x" 80 | }, 81 | { 82 | "size": "40x40", 83 | "idiom": "ipad", 84 | "filename": "icon-40.png", 85 | "scale": "1x" 86 | }, 87 | { 88 | "size": "40x40", 89 | "idiom": "ipad", 90 | "filename": "icon-40@2x.png", 91 | "scale": "2x" 92 | }, 93 | { 94 | "size": "76x76", 95 | "idiom": "ipad", 96 | "filename": "icon-76.png", 97 | "scale": "1x" 98 | }, 99 | { 100 | "size": "76x76", 101 | "idiom": "ipad", 102 | "filename": "icon-76@2x.png", 103 | "scale": "2x" 104 | }, 105 | { 106 | "size": "83.5x83.5", 107 | "idiom": "ipad", 108 | "filename": "icon-83.5@2x.png", 109 | "scale": "2x" 110 | }, 111 | { 112 | "size": "1024x1024", 113 | "idiom": "ios-marketing", 114 | "filename": "icon-1024.png", 115 | "scale": "1x" 116 | } 117 | ], 118 | "info": { 119 | "version": 1, 120 | "author": "icon.wuruihong.com" 121 | } 122 | } -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-1024.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | GHMall 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(MARKETING_VERSION) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /lib/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/lib/.DS_Store -------------------------------------------------------------------------------- /lib/generated_plugin_registrant.dart: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // ignore_for_file: lines_longer_than_80_chars 6 | 7 | import 'package:shared_preferences_web/shared_preferences_web.dart'; 8 | 9 | import 'package:flutter_web_plugins/flutter_web_plugins.dart'; 10 | 11 | // ignore: public_member_api_docs 12 | void registerPlugins(Registrar registrar) { 13 | SharedPreferencesPlugin.registerWith(registrar); 14 | registrar.registerMessageHandler(); 15 | } 16 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'routers/router.dart'; 3 | import 'package:provider/provider.dart'; 4 | import 'provider/Cart.dart'; 5 | import 'package:flutter/cupertino.dart'; 6 | 7 | void main() { 8 | /// 将状态栏设置为白色 9 | // SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light); 10 | 11 | runApp(MyApp()); 12 | } 13 | 14 | class MyApp extends StatefulWidget { 15 | MyApp({Key key}) : super(key: key); 16 | 17 | _MyAppState createState() => _MyAppState(); 18 | } 19 | 20 | class _MyAppState extends State { 21 | @override 22 | Widget build(BuildContext context) { 23 | return MaterialApp( 24 | /// 隐藏debug 25 | debugShowCheckedModeBanner: false, 26 | /// 配置路由 27 | initialRoute: '/', 28 | onGenerateRoute: onGenerateRoute, 29 | /// 设置主题 30 | theme: ThemeData( 31 | primaryColor: Colors.white, 32 | ), 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/model/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/lib/model/.DS_Store -------------------------------------------------------------------------------- /lib/model/GHAddressModel.dart: -------------------------------------------------------------------------------- 1 | 2 | class GHAddressModel { 3 | List results; 4 | 5 | GHAddressModel({this.results}); 6 | 7 | GHAddressModel.fromJson(Map json) { 8 | if (json['results'] != null) { 9 | results = new List(); 10 | json['results'].forEach((v) { 11 | results.add(new Results.fromJson(v)); 12 | }); 13 | } 14 | } 15 | 16 | Map toJson() { 17 | final Map data = new Map(); 18 | if (this.results != null) { 19 | data['results'] = this.results.map((v) => v.toJson()).toList(); 20 | } 21 | return data; 22 | } 23 | } 24 | 25 | class Results { 26 | String province; 27 | String area; 28 | String city; 29 | String detailsAddress; 30 | String remark; 31 | String zone; 32 | String phone; 33 | String userId; 34 | String objectId; 35 | String updatedAt; 36 | String createdAt; 37 | String name; 38 | String isDefault; 39 | Where where; 40 | 41 | Results( 42 | {this.detailsAddress, 43 | this.remark, 44 | this.province, 45 | this.area, 46 | this.city, 47 | this.zone, 48 | this.phone, 49 | this.userId, 50 | this.objectId, 51 | this.updatedAt, 52 | this.createdAt, 53 | this.name, 54 | this.isDefault, 55 | this.where}); 56 | 57 | Results.fromJson(Map json) { 58 | detailsAddress = json['detailsAddress']; 59 | if (detailsAddress == null) { 60 | detailsAddress = "暂无地址"; 61 | } 62 | remark = json['remark']; 63 | zone = json['zone']; 64 | if (zone == null) { 65 | zone = "暂无地址"; 66 | } 67 | phone = json['phone']; 68 | if (phone == null) { 69 | phone = "13800000000"; 70 | } 71 | userId = json['userId']; 72 | objectId = json['objectId']; 73 | updatedAt = json['updatedAt']; 74 | createdAt = json['createdAt']; 75 | province = json['province']; 76 | city = json['city']; 77 | area = json['area']; 78 | name = json['name']; 79 | if (name == null) { 80 | name = "没有设置"; 81 | } 82 | isDefault = json['isDefault']; 83 | where = json['where'] != null ? new Where.fromJson(json['where']) : null; 84 | } 85 | 86 | Map toJson() { 87 | final Map data = new Map(); 88 | data['detailsAddress'] = this.detailsAddress; 89 | data['remark'] = this.remark; 90 | data['zone'] = this.zone; 91 | data['phone'] = this.phone; 92 | data['userId'] = this.userId; 93 | data['objectId'] = this.objectId; 94 | data['updatedAt'] = this.updatedAt; 95 | data['createdAt'] = this.createdAt; 96 | data['name'] = this.name; 97 | data['isDefault'] = this.isDefault; 98 | data['province'] = this.province; 99 | data['city'] = this.city; 100 | data['area'] = this.area; 101 | 102 | 103 | if (this.where != null) { 104 | data['where'] = this.where.toJson(); 105 | } 106 | return data; 107 | } 108 | } 109 | 110 | class Where { 111 | String token; 112 | String userId; 113 | 114 | Where({this.token, this.userId}); 115 | 116 | Where.fromJson(Map json) { 117 | token = json['token']; 118 | userId = json['userId']; 119 | } 120 | 121 | Map toJson() { 122 | final Map data = new Map(); 123 | data['token'] = this.token; 124 | data['userId'] = this.userId; 125 | return data; 126 | } 127 | } 128 | 129 | -------------------------------------------------------------------------------- /lib/model/GHCategoryModel.dart: -------------------------------------------------------------------------------- 1 | class GHCategoryModel { 2 | List results; 3 | 4 | GHCategoryModel({this.results}); 5 | 6 | GHCategoryModel.fromJson(Map json) { 7 | if (json['results'] != null) { 8 | results = new List(); 9 | json['results'].forEach((v) { 10 | results.add(new GHCategoryItemModel.fromJson(v)); 11 | }); 12 | } 13 | } 14 | 15 | Map toJson() { 16 | final Map data = new Map(); 17 | if (this.results != null) { 18 | data['result'] = this.results.map((v) => v.toJson()).toList(); 19 | } 20 | return data; 21 | } 22 | } 23 | 24 | class GHCategoryItemModel { 25 | 26 | String categoryName; //所有的类型都继承 Object 27 | String type; 28 | String url; 29 | 30 | GHCategoryItemModel( 31 | { 32 | this.categoryName, 33 | this.type, 34 | this.url, 35 | }); 36 | 37 | GHCategoryItemModel.fromJson(Map json) { 38 | categoryName = json['categoryName']; 39 | url = json['url']; 40 | type = json['type']; 41 | } 42 | 43 | Map toJson() { 44 | final Map data = new Map(); 45 | 46 | data['categoryName'] = this.categoryName; 47 | data['url'] = this.url; 48 | data['type'] = this.type; 49 | 50 | return data; 51 | } 52 | } -------------------------------------------------------------------------------- /lib/model/GHGoodDetailsModel.dart: -------------------------------------------------------------------------------- 1 | class GHGoodDetailsModel { 2 | String isSelf; 3 | String description; 4 | List coupons; 5 | List service; 6 | int sales; 7 | List urls; 8 | String receiptTip; 9 | String updatedAt; 10 | String evaluate; 11 | String objectId; 12 | List storeAdvantages; 13 | String createdAt; 14 | String title; 15 | String goodId; 16 | Operators operators; 17 | String url; 18 | Object price; 19 | int count; 20 | String seletecdStrings; 21 | bool check; 22 | 23 | GHGoodDetailsModel( 24 | {this.isSelf, 25 | this.description, 26 | this.coupons, 27 | this.service, 28 | this.sales, 29 | this.urls, 30 | this.receiptTip, 31 | this.updatedAt, 32 | this.evaluate, 33 | this.objectId, 34 | this.goodId, 35 | this.storeAdvantages, 36 | this.createdAt, 37 | this.title, 38 | this.operators, 39 | this.url, 40 | this.count, 41 | this.seletecdStrings, 42 | this.check, 43 | this.price}); 44 | 45 | GHGoodDetailsModel.fromJson(Map json) { 46 | isSelf = json['isSelf']; 47 | description = json['description']; 48 | Object tempCoupons = json['coupons']; 49 | if (tempCoupons is List) { 50 | coupons = tempCoupons.cast(); 51 | } else { 52 | coupons = []; 53 | } 54 | 55 | Object tempservice = json['service']; 56 | if (tempservice is List) { 57 | service = tempservice.cast(); 58 | } else { 59 | service = []; 60 | } 61 | 62 | sales = json['sales']; 63 | 64 | Object tempurls = json['urls']; 65 | if (tempurls is List) { 66 | urls = tempurls.cast(); 67 | } else { 68 | urls = []; 69 | } 70 | count = json['count']; 71 | check = json['check']; 72 | goodId = json['goodId']; 73 | receiptTip = json['receiptTip']; 74 | updatedAt = json['updatedAt']; 75 | evaluate = json['evaluate']; 76 | objectId = json['objectId']; 77 | Object tempstoreAdvantages = json['storeAdvantages']; 78 | if (tempstoreAdvantages is List) { 79 | storeAdvantages = tempstoreAdvantages.cast(); 80 | } else { 81 | storeAdvantages = []; 82 | } 83 | 84 | createdAt = json['createdAt']; 85 | title = json['title']; 86 | operators = json['operators'] != null 87 | ? new Operators.fromJson(json['operators']) 88 | : null; 89 | url = json['url']; 90 | price = json['price']; 91 | seletecdStrings = json['seletecdStrings']; 92 | } 93 | 94 | Map toJson() { 95 | final Map data = new Map(); 96 | data['isSelf'] = this.isSelf; 97 | data['description'] = this.description; 98 | data['coupons'] = this.coupons; 99 | data['service'] = this.service; 100 | data['sales'] = this.sales; 101 | data['urls'] = this.urls; 102 | data['receiptTip'] = this.receiptTip; 103 | data['updatedAt'] = this.updatedAt; 104 | data['evaluate'] = this.evaluate; 105 | data['objectId'] = this.objectId; 106 | data['count'] = this.count; 107 | data['check'] = this.check; 108 | data['storeAdvantages'] = this.storeAdvantages; 109 | data['createdAt'] = this.createdAt; 110 | data['title'] = this.title; 111 | data['goodId'] = this.goodId; 112 | 113 | data['seletecdStrings'] = this.seletecdStrings; 114 | if (this.operators != null) { 115 | data['operators'] = this.operators.toJson(); 116 | } 117 | data['url'] = this.url; 118 | data['price'] = this.price; 119 | return data; 120 | } 121 | } 122 | 123 | class Operators { 124 | List operator; 125 | 126 | Operators({this.operator}); 127 | 128 | Operators.fromJson(Map json) { 129 | if (json['operator'] != null) { 130 | operator = new List(); 131 | json['operator'].forEach((v) { 132 | operator.add(new Operator.fromJson(v)); 133 | }); 134 | } 135 | } 136 | 137 | Map toJson() { 138 | final Map data = new Map(); 139 | if (this.operator != null) { 140 | data['operator'] = this.operator.map((v) => v.toJson()).toList(); 141 | } 142 | return data; 143 | } 144 | } 145 | 146 | class Operator { 147 | String title; 148 | 149 | Operator({this.title}); 150 | Operator.fromJson(Map json) { 151 | title = json['title']; 152 | } 153 | 154 | Map toJson() { 155 | final Map data = new Map(); 156 | data['title'] = this.title; 157 | return data; 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /lib/model/GHGoodsModel.dart: -------------------------------------------------------------------------------- 1 | class GHGoodsModel { 2 | List results; 3 | 4 | GHGoodsModel({this.results}); 5 | 6 | GHGoodsModel.fromJson(Map json) { 7 | if (json['results'] != null) { 8 | results = new List(); 9 | json['results'].forEach((v) { 10 | results.add(new GHGoodsItemModel.fromJson(v)); 11 | }); 12 | } 13 | } 14 | 15 | Map toJson() { 16 | final Map data = new Map(); 17 | if (this.results != null) { 18 | data['results'] = this.results.map((v) => v.toJson()).toList(); 19 | } 20 | return data; 21 | } 22 | } 23 | 24 | class GHGoodsItemModel { 25 | String description; 26 | String updatedAt; 27 | String evaluate; 28 | String objectId; 29 | String createdAt; 30 | String title; 31 | String url; 32 | int price; 33 | int sales; 34 | String isSelf; 35 | 36 | GHGoodsItemModel( 37 | {this.description, 38 | this.updatedAt, 39 | this.evaluate, 40 | this.objectId, 41 | this.createdAt, 42 | this.title, 43 | this.url, 44 | this.sales, 45 | this.isSelf, 46 | this.price}); 47 | 48 | GHGoodsItemModel.fromJson(Map json) { 49 | description = json['description']; 50 | updatedAt = json['updatedAt']; 51 | evaluate = json['evaluate']; 52 | objectId = json['objectId']; 53 | createdAt = json['createdAt']; 54 | title = json['title']; 55 | url = json['url']; 56 | sales = json['sales']; 57 | isSelf = json['isSelf']; 58 | price = json['price']; 59 | } 60 | 61 | Map toJson() { 62 | final Map data = new Map(); 63 | data['description'] = this.description; 64 | data['updatedAt'] = this.updatedAt; 65 | data['evaluate'] = this.evaluate; 66 | data['objectId'] = this.objectId; 67 | data['createdAt'] = this.createdAt; 68 | data['title'] = this.title; 69 | data['url'] = this.url; 70 | data['sales'] = this.sales; 71 | data['price'] = this.price; 72 | data['isSelf'] = this.isSelf; 73 | return data; 74 | } 75 | } -------------------------------------------------------------------------------- /lib/model/GHGuessLikeModel.dart: -------------------------------------------------------------------------------- 1 | class GHGuessLikeModel { 2 | List results; 3 | 4 | GHGuessLikeModel({this.results}); 5 | 6 | GHGuessLikeModel.fromJson(Map json) { 7 | if (json['results'] != null) { 8 | results = new List(); 9 | json['results'].forEach((v) { 10 | results.add(new GHGuessLikeItemModel.fromJson(v)); 11 | }); 12 | } 13 | } 14 | 15 | Map toJson() { 16 | final Map data = new Map(); 17 | if (this.results != null) { 18 | data['result'] = this.results.map((v) => v.toJson()).toList(); 19 | } 20 | return data; 21 | } 22 | } 23 | 24 | class GHGuessLikeItemModel { 25 | 26 | Object price; //所有的类型都继承 Object 27 | String url; 28 | 29 | GHGuessLikeItemModel( 30 | { 31 | this.price, 32 | 33 | this.url, 34 | }); 35 | 36 | GHGuessLikeItemModel.fromJson(Map json) { 37 | url = json['url']; 38 | 39 | price = json['price']; 40 | 41 | } 42 | 43 | Map toJson() { 44 | final Map data = new Map(); 45 | 46 | data['price'] = this.price; 47 | 48 | data['url'] = this.url; 49 | 50 | return data; 51 | } 52 | } -------------------------------------------------------------------------------- /lib/model/GHHotGoodsModel.dart: -------------------------------------------------------------------------------- 1 | class GHHotGoodsModel { 2 | List results; 3 | 4 | GHHotGoodsModel({this.results}); 5 | 6 | GHHotGoodsModel.fromJson(Map json) { 7 | if (json['results'] != null) { 8 | results = new List(); 9 | json['results'].forEach((v) { 10 | results.add(new GHHotGoodsItemModel.fromJson(v)); 11 | }); 12 | } 13 | } 14 | 15 | Map toJson() { 16 | final Map data = new Map(); 17 | if (this.results != null) { 18 | data['result'] = this.results.map((v) => v.toJson()).toList(); 19 | } 20 | return data; 21 | } 22 | } 23 | 24 | class GHHotGoodsItemModel { 25 | 26 | String price; //所有的类型都继承 Object 27 | String url; 28 | String oldPrice; 29 | String title; 30 | 31 | GHHotGoodsItemModel( 32 | { 33 | this.price, 34 | this.oldPrice, 35 | this.title, 36 | this.url, 37 | }); 38 | 39 | GHHotGoodsItemModel.fromJson(Map json) { 40 | url = json['url']; 41 | oldPrice = json['oldPrice']; 42 | title = json['title']; 43 | price = json['price']; 44 | } 45 | 46 | Map toJson() { 47 | final Map data = new Map(); 48 | 49 | data['price'] = this.price; 50 | data['title'] = this.title; 51 | data['oldPrice'] = this.oldPrice; 52 | data['url'] = this.url; 53 | return data; 54 | } 55 | } -------------------------------------------------------------------------------- /lib/model/GHomeCarouselDataModel.dart: -------------------------------------------------------------------------------- 1 | class GHomeCarouselDataModel { 2 | List results; 3 | 4 | GHomeCarouselDataModel({this.results}); 5 | 6 | GHomeCarouselDataModel.fromJson(Map json) { 7 | if (json['results'] != null) { 8 | results = new List(); 9 | json['results'].forEach((v) { 10 | results.add(new GHomeCarouselDataItemModel.fromJson(v)); 11 | }); 12 | } 13 | } 14 | 15 | Map toJson() { 16 | final Map data = new Map(); 17 | if (this.results != null) { 18 | data['results'] = this.results.map((v) => v.toJson()).toList(); 19 | } 20 | return data; 21 | } 22 | } 23 | 24 | class GHomeCarouselDataItemModel { 25 | String objectId; 26 | String updatedAt; 27 | String url; 28 | String createdAt; 29 | GHomeCarouselDataItemModel({this.objectId, this.updatedAt, this.url, this.createdAt}); 30 | 31 | GHomeCarouselDataItemModel.fromJson(Map json) { 32 | objectId = json['objectId']; 33 | updatedAt = json['updatedAt']; 34 | url = json['url']; 35 | createdAt = json['createdAt']; 36 | } 37 | 38 | Map toJson() { 39 | final Map data = new Map(); 40 | data['objectId'] = this.objectId; 41 | data['updatedAt'] = this.updatedAt; 42 | data['url'] = this.url; 43 | data['createdAt'] = this.createdAt; 44 | return data; 45 | } 46 | } -------------------------------------------------------------------------------- /lib/pages/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHMall/a0f38fc75d737377cd14f0950b7aa2fe0b4eae58/lib/pages/.DS_Store -------------------------------------------------------------------------------- /lib/pages/Cart/CartItem.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:provider/provider.dart'; 3 | import '../../provider/Cart.dart'; 4 | 5 | class CartItem extends StatefulWidget { 6 | 7 | 8 | /// 数据模型 9 | Map _itemData; 10 | 11 | bool isEnable; 12 | 13 | CartItem(this._itemData, {Key key,this.isEnable = true}) : super(key: key); 14 | 15 | _CartItemState createState() => _CartItemState(); 16 | } 17 | 18 | class _CartItemState extends State { 19 | @override 20 | Map _itemData; 21 | var cartProvider; 22 | 23 | void initState() { 24 | super.initState(); 25 | this._itemData = widget._itemData; 26 | } 27 | 28 | Widget _cartCenterNumber() { 29 | return Container( 30 | decoration: BoxDecoration( 31 | border: Border.all( 32 | width: 1, 33 | color: Colors.black12, 34 | )), 35 | child: Row( 36 | children: [ 37 | Container( 38 | alignment: Alignment.center, 39 | width: 40, 40 | height: 20, 41 | child: Text("${this._itemData["count"]}"), 42 | decoration: BoxDecoration( 43 | border: Border( 44 | left: BorderSide( 45 | width: 0.5, 46 | color: Colors.black12, 47 | ), 48 | right: BorderSide( 49 | width: 1, 50 | color: Colors.black12, 51 | )), 52 | ), 53 | ), 54 | ], 55 | ), 56 | ); 57 | } 58 | 59 | Widget _cartRightNumber() { 60 | return InkWell( 61 | onTap: () { 62 | if(!widget.isEnable) { 63 | print("禁止响应"); 64 | return; 65 | } 66 | setState(() { 67 | 68 | this._itemData["count"]++; 69 | }); 70 | this.cartProvider.changeCartList(); 71 | }, 72 | child: Container( 73 | decoration: BoxDecoration( 74 | border: Border.all( 75 | width: 1, 76 | color: Colors.black12, 77 | )), 78 | child: Row( 79 | children: [ 80 | Container( 81 | alignment: Alignment.center, 82 | width: 20, 83 | height: 20, 84 | child: Text("+"), 85 | ), 86 | ], 87 | ), 88 | ), 89 | ); 90 | } 91 | 92 | Widget _cartLeftNumber() { 93 | return InkWell( 94 | onTap: () { 95 | if(!widget.isEnable) { 96 | print("禁止响应"); 97 | return; 98 | } 99 | if (this._itemData["count"] > 1) { 100 | setState(() { 101 | this._itemData["count"]--; 102 | }); 103 | } 104 | this.cartProvider.changeCartList(); 105 | }, 106 | child: Container( 107 | decoration: BoxDecoration( 108 | border: Border.all( 109 | width: 1, 110 | color: Colors.black12, 111 | )), 112 | child: Row( 113 | children: [ 114 | Container( 115 | alignment: Alignment.center, 116 | width: 20, 117 | height: 20, 118 | child: Text("-"), 119 | ), 120 | ], 121 | ), 122 | ), 123 | ); 124 | } 125 | 126 | Widget build(BuildContext context) { 127 | this.cartProvider = Provider.of(context); 128 | return Container( 129 | child: Row( 130 | mainAxisAlignment: MainAxisAlignment.end, 131 | children: [ 132 | _cartLeftNumber(), 133 | _cartCenterNumber(), 134 | _cartRightNumber(), 135 | ], 136 | ), 137 | ); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /lib/pages/GHAddressEdit.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../widget/GHButton.dart'; 3 | import '../widget/GHTextWidget.dart'; 4 | import '../services/ScreenAdaper.dart'; 5 | //import 'package:city_pickers/city_pickers.dart'; 6 | import '../services/httptool.dart'; 7 | import '../widget/GHLoading.dart'; 8 | import '../services/GHToast.dart'; 9 | 10 | /// 编辑/新增收货地址 11 | class GHAddressEdit extends StatefulWidget { 12 | final Map arguments; 13 | 14 | @override 15 | GHAddressEdit({Key key, this.arguments}) : super(key: key); 16 | _GHAddressEditState createState() => _GHAddressEditState(); 17 | } 18 | 19 | class _GHAddressEditState extends State { 20 | /// 收件人姓名 21 | String _name = ""; 22 | 23 | /// 收货人电话 24 | String _phoneNumber = ""; 25 | 26 | /// 省份 27 | String _province = "省"; 28 | 29 | /// 市 30 | String _city = "市"; 31 | 32 | /// 区 33 | String _area = "区"; 34 | 35 | /// 省编码 36 | String _locationCode = "110000"; 37 | 38 | /// 详细地址 39 | String _detailsAddress = ""; 40 | 41 | /// 完整地址 42 | String _fullAddress = ""; 43 | 44 | TextEditingController _addressController = new TextEditingController(); 45 | TextEditingController _nameController = new TextEditingController(); 46 | TextEditingController _phoneNumberController = new TextEditingController(); 47 | TextEditingController _detailsAddressController = new TextEditingController(); 48 | 49 | FocusNode _contentFocusNode = FocusNode(); 50 | 51 | void initState() { 52 | super.initState(); 53 | if (widget.arguments != null) { 54 | this._nameController.text = widget.arguments["name"]; 55 | this._phoneNumberController.text = widget.arguments["phoneNumber"]; 56 | this._addressController.text = widget.arguments["address"]; 57 | } 58 | } 59 | 60 | _changeAddress() { 61 | 62 | } 63 | 64 | bool _checkAddress(){ 65 | if(this._nameController.text.isEmpty 66 | ||this._phoneNumberController.text.isEmpty 67 | ||this._province.isEmpty 68 | ||this._city.isEmpty 69 | ||this._area.isEmpty 70 | ||this._detailsAddressController.text.isEmpty) { 71 | GHToast.showTost("地址信息填写不全"); 72 | return false; 73 | } 74 | return true; 75 | } 76 | 77 | _addAddress(BuildContext context) { 78 | 79 | var url = 80 | "https://a4cj1hm5.api.lncld.net/1.1/classes/shopAddress"; 81 | Map params ={ 82 | 'name':this._nameController.text, 83 | 'phoneNumber':this._phoneNumberController.text, 84 | 'province':this._province, 85 | 'city':this._city, 86 | 'area':this._area, 87 | 'detailsAddress':this._detailsAddressController.text, 88 | }; 89 | HttpRequest.request(url, method: 'POST',params:params).then((value) { 90 | var objectId = value["objectId"]; 91 | if (objectId != null) { 92 | GHToast.showTost("添加地址成功"); 93 | Navigator.pop(context); 94 | } 95 | }); 96 | } 97 | 98 | _getAddress() { 99 | var url = 100 | "https://a4cj1hm5.api.lncld.net/1.1/classes/addressDetails/${widget.arguments["objectId"]}"; 101 | HttpRequest.request(url, method: 'GET').then((value) { 102 | print(value); 103 | }); 104 | } 105 | 106 | _deletecdAddress(BuildContext context) { 107 | var url = 108 | "https://a4cj1hm5.api.lncld.net/1.1/classes/addressDetails/${widget.arguments["objectId"]}"; 109 | HttpRequest.request(url, method: 'DELETE').then((value) { 110 | GHToast.showTost("删除成功"); 111 | Navigator.pop(context); 112 | }); 113 | } 114 | 115 | _showCityPicker(BuildContext context) async { 116 | // Result result = await CityPickers.showCityPicker( 117 | // cancelWidget: Container( 118 | // child: Text( 119 | // "取消", 120 | // style: TextStyle(fontSize: 16), 121 | // ), 122 | // ), 123 | // locationCode: this._locationCode, 124 | // confirmWidget: Container( 125 | // child: Text( 126 | // "确定", 127 | // style: TextStyle(fontSize: 16), 128 | // ), 129 | // ), 130 | // height: 300, 131 | // context: context, 132 | // ); 133 | //{"provinceName":"北京市","provinceId":"110000", 134 | // "cityName":"北京城区","cityId":"110100", 135 | // "areaName":"东城区","areaId":"110101"} 136 | // setState(() { 137 | // this._province = result.provinceName; 138 | // this._city = result.cityName; 139 | // this._area = result.areaName; 140 | // this._locationCode = result.provinceId; 141 | // this._fullAddress = _province + _city + _area; 142 | // }); 143 | } 144 | 145 | @override 146 | 147 | Widget build(BuildContext context) { 148 | ScreenAdaper.init(context); 149 | return Scaffold( 150 | appBar: AppBar( 151 | actions: [ 152 | TextButton( 153 | onPressed: () { 154 | _contentFocusNode.unfocus(); 155 | _deletecdAddress(context); 156 | }, 157 | child: Text("删除")) 158 | ], 159 | title: widget.arguments == null ? Text("新增收货地址"):Text("新增收货地址"), 160 | ), 161 | body: GestureDetector( 162 | onTap: () { 163 | _contentFocusNode.unfocus(); 164 | }, 165 | child: Container( 166 | padding: EdgeInsets.all(20), 167 | child: ListView( 168 | children: [ 169 | Container( 170 | child: GHTextWidget( 171 | "收件人姓名", 172 | textEditingController: _nameController, 173 | ), 174 | ), 175 | Container( 176 | child: GHTextWidget( 177 | "收件人电话", 178 | textEditingController: _phoneNumberController, 179 | ), 180 | ), 181 | Container( 182 | child: InkWell( 183 | onTap: () { 184 | this._showCityPicker(context); 185 | }, 186 | child: Container( 187 | height: 50, 188 | child: Row( 189 | crossAxisAlignment: CrossAxisAlignment.center, 190 | children: [ 191 | Icon( 192 | Icons.location_on, 193 | color: Colors.red, 194 | ), 195 | SizedBox( 196 | width: 5, 197 | ), 198 | Text( 199 | "${this._province} /${this._city}/${this._area}", 200 | style: TextStyle( 201 | fontSize: 14, 202 | ), 203 | ), 204 | ], 205 | ), 206 | ), 207 | ), 208 | ), 209 | Divider( 210 | height: 1, 211 | color: Colors.black12, 212 | ), 213 | ListView( 214 | shrinkWrap: true, 215 | physics: NeverScrollableScrollPhysics(), 216 | children: [ 217 | Container( 218 | child: TextField( 219 | controller: this._detailsAddressController, 220 | focusNode: this._contentFocusNode, 221 | maxLines: null, 222 | decoration: InputDecoration( 223 | contentPadding: EdgeInsets.only(left: 0, top: 0), 224 | hintText: "详细地址", 225 | border: OutlineInputBorder( 226 | borderRadius: BorderRadius.circular(30), 227 | borderSide: BorderSide.none), 228 | )), 229 | ), 230 | SizedBox( 231 | height: 10, 232 | ), 233 | Container( 234 | child: GHButton( 235 | "确定", 236 | tapAction: () { 237 | _contentFocusNode.unfocus(); 238 | if(this._checkAddress()) { 239 | this._addAddress(context); 240 | } 241 | }, 242 | ), 243 | ) 244 | ], 245 | ) 246 | ], 247 | ), 248 | ), 249 | )); 250 | } 251 | } 252 | -------------------------------------------------------------------------------- /lib/pages/GHAddressList.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../services/ScreenAdaper.dart'; 3 | import '../services/httptool.dart'; 4 | import 'package:common_utils/common_utils.dart'; 5 | import '../model/GHAddressModel.dart'; 6 | import 'package:flutter_easyrefresh/easy_refresh.dart'; 7 | 8 | /// 收货地址列表 9 | class GHAddressList extends StatefulWidget { 10 | @override 11 | _GHAddressListState createState() => _GHAddressListState(); 12 | } 13 | 14 | class _GHAddressListState extends State { 15 | /// 地址列表 16 | var _list = []; 17 | 18 | GlobalKey _easyRefreshKey = new GlobalKey(); 19 | 20 | _getAddressList() async { 21 | //addressDetails 22 | //shopAddress 23 | var url = "https://a4cj1hm5.api.lncld.net/1.1/classes/shopAddress"; 24 | var c = Uri.encodeComponent('-createdAt'); 25 | var d = Uri.encodeComponent('李'); 26 | 27 | // --data-urlencode 'scan_key=score' \ \ 28 | //%7Bname:%20%E6%9D%8E%7D 29 | //%7b%22name%22%3a+%22%e6%9d%8e%22%7d 30 | // var b = Uri.encodeQueryComponent(map.toString()); 31 | //where={"score": 100} 32 | // url = url+'?'+ "limit="+c + "&" + "where="+b; 33 | 34 | url = url + '?' + "order=" + c; 35 | 36 | HttpRequest.request(url, method: 'GET').then((res) { 37 | var list = new GHAddressModel.fromJson(res).results; 38 | setState(() { 39 | this._list = list; 40 | }); 41 | }); 42 | } 43 | 44 | void initState() { 45 | super.initState(); 46 | this._easyRefreshKey.currentState; 47 | } 48 | 49 | void deactivate() { 50 | // 返回到当前页刷新 51 | var bool = ModalRoute.of(context).isCurrent; 52 | if (bool) { 53 | this._getAddressList(); 54 | } 55 | } 56 | 57 | Widget ListItem(Results results) { 58 | return InkWell( 59 | onTap: () {}, 60 | child: Container( 61 | margin: EdgeInsets.only(top: 5, bottom: 5), 62 | width: ScreenAdaper.getScreenWidth(), 63 | child: Column( 64 | children: [ 65 | Row( 66 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 67 | children: [ 68 | Row ( 69 | children: [ 70 | Column( 71 | crossAxisAlignment: CrossAxisAlignment.start, 72 | children: [ 73 | Container( 74 | child: Row( 75 | children: [ 76 | Container( 77 | width:50, 78 | child: Text( 79 | results.name, 80 | overflow: TextOverflow.ellipsis, 81 | style:TextStyle( 82 | fontSize: 18, 83 | fontWeight: FontWeight.bold, 84 | ), 85 | ), 86 | ), 87 | SizedBox( 88 | width: 10, 89 | ), 90 | Container( 91 | child: Text( 92 | results.phone, 93 | style: TextStyle(fontSize: 16,fontWeight: FontWeight.bold), 94 | ), 95 | ), 96 | ], 97 | ), 98 | ), 99 | Container( 100 | width: ScreenAdaper.getScreenWidth() - 20 - 20 - 30, 101 | child: Text( 102 | results.province + 103 | results.city + 104 | results.area + 105 | results.detailsAddress, 106 | style: TextStyle(fontSize: 14, color: Colors.black54), 107 | ), 108 | ), 109 | 110 | ], 111 | ) 112 | ], 113 | ), 114 | GestureDetector( 115 | 116 | onTap: () { 117 | Navigator.pushNamed(context, '/GHAddressEdit', arguments: { 118 | 'name': "${results.name}", 119 | 'zone': "${results.zone}", 120 | 'detailsAddress': "${results.detailsAddress}", 121 | 'phoneNumber': results.phone, 122 | 'objectId': results.objectId, 123 | }); 124 | }, 125 | child: Container( 126 | child: Icon( 127 | Icons.edit, 128 | size: 30, 129 | ), 130 | ), 131 | ), 132 | ], 133 | ), 134 | Divider(), 135 | ], 136 | ) 137 | ), 138 | ); 139 | } 140 | 141 | @override 142 | Widget build(BuildContext context) { 143 | ScreenAdaper.init(context); 144 | ScreenAdaper.init(context); 145 | return Scaffold( 146 | appBar: AppBar( 147 | actions: [ 148 | TextButton( 149 | onPressed: () { 150 | Navigator.pushNamed(context, '/GHAddressEdit'); 151 | }, 152 | child: Icon(Icons.add), 153 | ) 154 | ], 155 | title: Text("地址管理"), 156 | ), 157 | body: Container( 158 | padding: EdgeInsets.all(20), 159 | child: EasyRefresh( 160 | firstRefresh: true, 161 | key:_easyRefreshKey, 162 | onRefresh: () async { 163 | await this._getAddressList(); 164 | }, 165 | onLoad: () async { 166 | await this._getAddressList(); 167 | }, 168 | child: ListView.builder( 169 | itemBuilder: (context, index) { 170 | return ListItem(this._list[index]); 171 | }, 172 | itemCount: this._list.length, 173 | ), 174 | )), 175 | ); 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /lib/pages/GHLoginPage.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../widget/GHTextWidget.dart'; 3 | import '../widget/GHButton.dart'; 4 | import '../services/GHToast.dart'; 5 | import '../services/gh_sqflite.dart'; 6 | import '../services/EventBus.dart'; 7 | import 'package:flutter/gestures.dart'; 8 | import 'dart:core'; 9 | import '../services/httptool.dart'; 10 | 11 | /// 登录页面 12 | class GHLoginPage extends StatefulWidget { 13 | @override 14 | _GHLoginPageState createState() => _GHLoginPageState(); 15 | } 16 | 17 | class _GHLoginPageState extends State { 18 | /// 手机号码 19 | TextEditingController _mobilePhoneNumberEditingController = 20 | TextEditingController(); 21 | 22 | /// 验证码 23 | TextEditingController _codeEditingController = TextEditingController(); 24 | 25 | @override 26 | void initState() { 27 | super.initState(); 28 | } 29 | 30 | /// 注册或登录 31 | void _login(String mobilePhoneNumber, String smsCode) async { 32 | var url = "https://a4cj1hm5.api.lncld.net/1.1/usersByMobilePhone"; 33 | Map params = { 34 | "mobilePhoneNumber": "+86${mobilePhoneNumber}", 35 | "smsCode": smsCode, 36 | }; 37 | print(params); 38 | await HttpRequest.request(url, method: 'POST', params: params).then((res) { 39 | print(res); 40 | if (res == null) { 41 | GHToast.showTost("登录失败,请重试"); 42 | } else { 43 | GHToast.showTost("登录成功"); 44 | String objectId = res["objectId"]; 45 | String username = res["username"]; 46 | String mobilePhone = res["mobilePhoneNumber"]; 47 | GHSqflite sqflite = GHSqflite(); 48 | sqflite.add(objectId, username, mobilePhone); 49 | 50 | /// 发送广播 51 | eventBus.fire(LoginSuccessEvent('登录成功')); 52 | 53 | /// 返回到根控制器 54 | Navigator.pop(context); 55 | } 56 | }); 57 | } 58 | 59 | /// 请求验证码 60 | void _requestSmsCode(String mobilePhoneNumber) async { 61 | var url = "https://a4cj1hm5.api.lncld.net/1.1/requestSmsCode"; 62 | Map params = { 63 | "mobilePhoneNumber": mobilePhoneNumber, 64 | }; 65 | await HttpRequest.request(url, method: 'POST', params: params).then((res) { 66 | if (res == null) { 67 | GHToast.showTost("请求验证码失败"); 68 | } else { 69 | GHToast.showTost("请求验证码成功"); 70 | } 71 | }); 72 | } 73 | 74 | /// 校验手机号码 75 | bool _checkParameters(String username) { 76 | if (username == null) { 77 | return false; 78 | } 79 | RegExp reg = new RegExp(r"^1\d{10}$"); 80 | if (reg.hasMatch(username)) { 81 | return true; 82 | } else { 83 | GHToast.showTost("手机号格式不正确,请重新输入"); 84 | return false; 85 | } 86 | } 87 | 88 | Widget build(BuildContext context) { 89 | return Scaffold( 90 | body: GestureDetector( 91 | behavior: HitTestBehavior.translucent, 92 | onTap: () => FocusScope.of(context).requestFocus(FocusNode()), 93 | child: Container( 94 | padding: EdgeInsets.all(20), 95 | child: ListView( 96 | children: [ 97 | /// logo 98 | Container( 99 | margin: EdgeInsets.only(top: 30, bottom: 30), 100 | child: Center( 101 | child: Image.asset( 102 | 'images/logo.png', 103 | fit: BoxFit.fill, 104 | width: 100, 105 | height: 100, 106 | ), 107 | )), 108 | SizedBox( 109 | height: 20, 110 | ), 111 | Container( 112 | height: 50, 113 | child: GHTextWidget( 114 | "请输入用户名", 115 | onChanged: (value) {}, 116 | textEditingController: 117 | this._mobilePhoneNumberEditingController, 118 | ), 119 | ), 120 | SizedBox( 121 | height: 20, 122 | ), 123 | Container( 124 | child: Row( 125 | children: [ 126 | Container( 127 | width: 240, 128 | height: 50, 129 | child: Container( 130 | child: GHTextWidget( 131 | "验证码", 132 | textEditingController: this._codeEditingController, 133 | ), 134 | ), 135 | ), 136 | Container( 137 | width: 10, 138 | child: Text(""), 139 | ), 140 | Expanded( 141 | flex: 1, 142 | child: Container( 143 | decoration: BoxDecoration( 144 | border: Border.all(color: Colors.black12, width: 1)), 145 | child: TextButton( 146 | onPressed: () { 147 | this._requestSmsCode( 148 | this._mobilePhoneNumberEditingController.text); 149 | }, 150 | child: Text( 151 | "重新发送", 152 | style: TextStyle(fontSize: 14, color: Colors.black54), 153 | ), 154 | ), 155 | ), 156 | ) 157 | ], 158 | )), 159 | 160 | Container( 161 | height: 50, 162 | padding: EdgeInsets.only(top: 10, bottom: 10), 163 | child: Stack( 164 | children: [ 165 | InkWell( 166 | onTap: () { 167 | print("忘记密码"); 168 | }, 169 | child: Align( 170 | alignment: Alignment.centerLeft, 171 | child: Text( 172 | "忘记密码", 173 | style: 174 | TextStyle(fontSize: 14, color: Colors.black54), 175 | ), 176 | ), 177 | ), 178 | ], 179 | )), 180 | Container( 181 | height: 50, 182 | child: GHButton( 183 | "登录", 184 | backGroudColor: Colors.red, 185 | tapAction: () { 186 | FocusScope.of(context).requestFocus(FocusNode()); 187 | var username = 188 | this._mobilePhoneNumberEditingController.text.trim(); 189 | if (this._checkParameters(username)) { 190 | this._login(this._mobilePhoneNumberEditingController.text, 191 | this._codeEditingController.text); 192 | } 193 | }, 194 | ), 195 | ), 196 | SizedBox( 197 | height: 20, 198 | ), 199 | Container( 200 | child: RichText( 201 | text: TextSpan( 202 | text: "登录即代表同意", 203 | style: TextStyle(color: Colors.black), 204 | children: [ 205 | TextSpan( 206 | recognizer: TapGestureRecognizer() 207 | ..onTap = () { 208 | print('点击了隐私政策'); 209 | }, 210 | text: "《隐私协议》", 211 | style: TextStyle(color: Colors.blue)), 212 | ])), 213 | ) 214 | ], 215 | ), 216 | ), 217 | ), 218 | appBar: AppBar( 219 | leading: IconButton( 220 | icon: Icon( 221 | Icons.arrow_back_ios, 222 | color: Colors.black38, 223 | ), 224 | onPressed: () { 225 | Navigator.pop(context); 226 | }, 227 | ), 228 | actions: [ 229 | TextButton( 230 | onPressed: () { 231 | GHToast.showTost("点击了联系客服"); 232 | }, 233 | child: Text( 234 | "客服", 235 | style: TextStyle(fontSize: 16, color: Colors.black54), 236 | ), 237 | ), 238 | ], 239 | ), 240 | ); 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /lib/pages/GHOnlinePayments.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../widget/GHButton.dart'; 3 | import '../services/httptool.dart'; 4 | import '../widget/GHRichTextPriceWidget.dart'; 5 | import '../services/GHToast.dart'; 6 | 7 | /// 在线支付 8 | class GHOnlinePayments extends StatefulWidget { 9 | Map arguments; 10 | 11 | @override 12 | GHOnlinePayments({Key key, this.arguments}) : super(key: key); 13 | 14 | _GHOnlinePaymentsState createState() => _GHOnlinePaymentsState(); 15 | } 16 | 17 | class _GHOnlinePaymentsState extends State { 18 | /// 支付方式 true 微信 false 支付宝 19 | bool _seletecd = true; 20 | String _orderId = ""; 21 | double _total = 0; 22 | List _goodList = []; 23 | 24 | /// 获取订单详情 25 | void _getOrderDetails(String id) async { 26 | var url = "https://a4cj1hm5.api.lncld.net/1.1/classes/shopOrderList/${id}"; 27 | await HttpRequest.request(url, method: 'GET').then((res) { 28 | print(res); 29 | _goodList = res["goodList"]; 30 | double _temptotal = res["total"]; 31 | setState(() { 32 | this._total = _temptotal; 33 | }); 34 | }); 35 | } 36 | 37 | /// 增加用户支付方式 38 | void _addPayway(String id, String payway) async { 39 | Map params = { 40 | "payway": payway, 41 | }; 42 | var url = "https://a4cj1hm5.api.lncld.net/1.1/classes/shopOrderList/${id}"; 43 | await HttpRequest.request(url, method: 'PUT', params: params).then((res) { 44 | String updatedAt = res["updatedAt"]; 45 | if (updatedAt != null) { 46 | GHToast.showTost("选择支付方式成功"); 47 | List _goodIds = []; 48 | for (var dict in _goodList) { 49 | String goodId = dict["goodId"]; 50 | _goodIds.add(goodId); 51 | } 52 | this._deletedGoods(_goodIds); 53 | 54 | } else { 55 | GHToast.showTost("选择支付方式失败"); 56 | } 57 | }); 58 | } 59 | 60 | /// 批量删除购物车中的商品 61 | void _deletedGoods(List goods) async { 62 | List maps = []; 63 | for (var i = 0; i < goods.length; i++) { 64 | String gooodId = goods[i]; 65 | print("商品id是"); 66 | print(gooodId); 67 | Map map = { 68 | "method": "DELETE", 69 | "path": "/1.1/classes/shopCartList/${gooodId}" 70 | }; 71 | maps.add(map); 72 | } 73 | 74 | print(maps); 75 | 76 | var url = "https://a4cj1hm5.api.lncld.net/1.1/batch"; 77 | Map params = {"requests": maps}; 78 | HttpRequest.request(url, method: 'POST', params: params).then((value) { 79 | print(value); 80 | if (value != null) { 81 | GHToast.showTost("成功"); 82 | Navigator.pushNamed(context, '/', arguments: { 83 | "index": 2, 84 | }); 85 | } else { 86 | GHToast.showTost("删除失败"); 87 | } 88 | }); 89 | } 90 | 91 | @override 92 | void initState() { 93 | super.initState(); 94 | this._orderId = widget.arguments["id"]; 95 | this._getOrderDetails(this._orderId); 96 | } 97 | 98 | Widget build(BuildContext context) { 99 | return Scaffold( 100 | appBar: AppBar( 101 | title: Text("支付方式"), 102 | ), 103 | body: Container( 104 | padding: EdgeInsets.all(20), 105 | child: ListView( 106 | children: [ 107 | Container( 108 | padding: EdgeInsets.only(bottom: 10), 109 | child: Text( 110 | "订单号: ${this._orderId}", 111 | style: TextStyle(fontSize: 16), 112 | ), 113 | ), 114 | Container( 115 | height: 10, 116 | color: Color.fromRGBO(245, 245, 245, 1), 117 | ), 118 | GestureDetector( 119 | behavior: HitTestBehavior.opaque, 120 | onTap: () { 121 | setState(() { 122 | this._seletecd = !this._seletecd; 123 | }); 124 | }, 125 | child: Container( 126 | height: 60, 127 | child: Row( 128 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 129 | children: [ 130 | Row(children: [ 131 | Container( 132 | height: 40, 133 | width: 40, 134 | child: Image.asset( 135 | 'images/pay_wechat.png', 136 | fit: BoxFit.cover, 137 | ), 138 | ), 139 | SizedBox( 140 | width: 10, 141 | ), 142 | Container( 143 | child: Text( 144 | "微信", 145 | style: TextStyle(fontSize: 18), 146 | ), 147 | ), 148 | ]), 149 | Container( 150 | width: 20, 151 | height: 20, 152 | child: this._seletecd == true 153 | ? Image.asset('images/checkSelected.png') 154 | : Image.asset('images/checkNormal.png')) 155 | ])), 156 | ), 157 | Divider(), 158 | GestureDetector( 159 | behavior: HitTestBehavior.opaque, 160 | onTap: () { 161 | setState(() { 162 | this._seletecd = !this._seletecd; 163 | }); 164 | }, 165 | child: Container( 166 | height: 60, 167 | child: Row( 168 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 169 | children: [ 170 | Row(children: [ 171 | Container( 172 | height: 40, 173 | width: 40, 174 | child: Image.asset( 175 | 'images/pay_alipay.png', 176 | fit: BoxFit.fill, 177 | ), 178 | ), 179 | SizedBox( 180 | width: 10, 181 | ), 182 | Container( 183 | child: Text( 184 | "支付宝", 185 | style: TextStyle(fontSize: 18), 186 | ), 187 | ), 188 | ]), 189 | Container( 190 | width: 20, 191 | height: 20, 192 | child: this._seletecd != true 193 | ? Image.asset('images/checkSelected.png') 194 | : Image.asset('images/checkNormal.png')) 195 | ], 196 | )), 197 | ), 198 | Divider(), 199 | Container( 200 | padding: EdgeInsets.all(10), 201 | child: Row( 202 | mainAxisAlignment: MainAxisAlignment.end, 203 | children: [ 204 | Container( 205 | child: GestureDetector( 206 | behavior: HitTestBehavior.opaque, 207 | onTap: () {}, 208 | child: Text("待支付金额"), 209 | )), 210 | SizedBox( 211 | width: 5, 212 | ), 213 | Container( 214 | child: GHRichTextPriceWidget(this._total + 10), 215 | ), 216 | ], 217 | ), 218 | ), 219 | Container( 220 | padding: EdgeInsets.all(10), 221 | child: GHButton( 222 | "确定", 223 | tapAction: () { 224 | this._addPayway(widget.arguments["id"], 225 | this._seletecd == true ? "微信" : "支付宝"); 226 | }, 227 | ), 228 | ), 229 | Container( 230 | alignment: Alignment.centerRight, 231 | padding: EdgeInsets.all(10), 232 | child: Text("线上下单,线下支付")), 233 | ], 234 | ), 235 | ), 236 | ); 237 | } 238 | } 239 | -------------------------------------------------------------------------------- /lib/pages/GHOrderList.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../services/httptool.dart'; 3 | 4 | class GHOrderListPage extends StatefulWidget { 5 | @override 6 | _GHOrderListPageState createState() => _GHOrderListPageState(); 7 | } 8 | 9 | class _GHOrderListPageState extends State { 10 | @override 11 | void initState() { 12 | super.initState(); 13 | _getOrderList(); 14 | } 15 | 16 | /// 获取订单列表数据 17 | void _getOrderList() async { 18 | var url = "https://a4cj1hm5.api.lncld.net/1.1/classes/shopOrderList"; 19 | await HttpRequest.request(url, method: 'GET').then((value) { 20 | List results = value["results"]; 21 | print(value); 22 | }); 23 | } 24 | 25 | Widget _orderListWidget() { 26 | return Container(child: Text("2222")); 27 | } 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | return Scaffold( 32 | appBar: AppBar( 33 | title: Text("订单列表"), 34 | ), 35 | body: _orderListWidget()); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/pages/Search.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../services/ScreenAdaper.dart'; 3 | import '../widget/GHButton.dart'; 4 | import '../widget/GHCustomAppbar.dart'; 5 | 6 | /// 搜索 7 | class SearchPage extends StatefulWidget { 8 | SearchPage({Key key}) : super(key: key); 9 | 10 | _SearchPageState createState() => _SearchPageState(); 11 | } 12 | 13 | class _SearchPageState extends State { 14 | @override 15 | final GlobalKey _scaffoldKey = new GlobalKey(); 16 | 17 | /// 用户输入的关键字 18 | var _keywors; 19 | 20 | /// 热搜关键字 21 | var _hotwords = [ 22 | {"key": "apple", "type": "1"}, 23 | {"key": "小米", "type": "1"}, 24 | {"key": "华为", "type": "1"}, 25 | {"key": "魅族", "type": "1"}, 26 | {"key": "iPad", "type": "1"}, 27 | {"key": "口罩", "type": "1"} 28 | ]; 29 | 30 | Widget build(BuildContext context) { 31 | ScreenAdaper.init(context); 32 | final double topPadding = MediaQuery.of(context).padding.top; 33 | return Scaffold( 34 | key: _scaffoldKey, 35 | drawer: Drawer( 36 | child: Container( 37 | child: Text("22"), 38 | )), 39 | appBar: GHCustomAppbar( 40 | contentHeight: topPadding + 44, 41 | leadingWidget: Container( 42 | padding: EdgeInsets.only(left: 20), 43 | child: InkWell( 44 | onTap: () { 45 | Navigator.pop(context); 46 | }, 47 | child: Icon( 48 | Icons.arrow_back_ios, 49 | color: Colors.black38, 50 | size: 20, 51 | ), 52 | ), 53 | ), 54 | titleWidget: Container( 55 | child: Container( 56 | width: ScreenAdaper.getScreenWidth() - 100, 57 | height: ScreenAdaper.height(50), 58 | decoration: BoxDecoration( 59 | color: Color.fromRGBO(233, 233, 233, 0.8), 60 | borderRadius: BorderRadius.circular(30), 61 | ), 62 | child: Row( 63 | children: [ 64 | Container( 65 | padding: EdgeInsets.fromLTRB(5, 5, 0, 5), 66 | alignment: Alignment.center, 67 | child: Icon( 68 | Icons.search, 69 | color: Colors.black12, 70 | ), 71 | ), 72 | Container( 73 | alignment: Alignment.center, 74 | height: ScreenAdaper.height(50), 75 | width: ScreenAdaper.width(240), 76 | child: TextField( 77 | maxLength: 30, 78 | cursorColor: Color.fromRGBO(170, 170, 170, 1), 79 | onChanged: (value) { 80 | this._keywors = value; 81 | }, 82 | style: TextStyle(fontSize: 14), 83 | autofocus: true, 84 | decoration: InputDecoration( 85 | contentPadding: EdgeInsets.only(left: 0, top: 0), 86 | counterText: '', 87 | hintText: "请输入要搜索的内容", 88 | hintStyle: TextStyle( 89 | color: Color.fromRGBO(170, 170, 170, 0.1), 90 | ), 91 | border: OutlineInputBorder( 92 | borderSide: BorderSide.none, 93 | borderRadius: BorderRadius.circular(30), 94 | )), 95 | ), 96 | ), 97 | ], 98 | ), 99 | ), 100 | ), 101 | trailingWidget: Container( 102 | alignment: Alignment.center, 103 | width: 40, 104 | child: InkWell( 105 | onTap: () { 106 | print("222"); 107 | _scaffoldKey.currentState.openDrawer(); 108 | }, 109 | child: Text( 110 | "搜索", 111 | style: TextStyle(fontSize: 14), 112 | ), 113 | )), 114 | ), 115 | body: ListView( 116 | children: [ 117 | _commomTitleWidget("热搜", Icons.whatshot), 118 | Container( 119 | padding: EdgeInsets.fromLTRB(20, 0, 20, 0), 120 | child: Column( 121 | crossAxisAlignment: CrossAxisAlignment.start, 122 | children: [ 123 | Wrap( 124 | children: this._hotwords.map((value) { 125 | return Container( 126 | padding: EdgeInsets.fromLTRB(5, 0, 5, 0), 127 | child: Chip( 128 | backgroundColor: Color.fromRGBO(235, 235, 235, 1), 129 | shape: RoundedRectangleBorder( 130 | borderRadius: BorderRadius.circular(5.0)), 131 | label: Text("${value["key"]}"), 132 | ), 133 | ); 134 | }).toList(), 135 | ), 136 | ], 137 | ), 138 | ), 139 | _commomTitleWidget("历史记录", Icons.history), 140 | Column( 141 | mainAxisAlignment: MainAxisAlignment.start, 142 | children: [ 143 | Container( 144 | padding: 145 | EdgeInsets.only(left: 20, top: 10, right: 10, bottom: 10), 146 | alignment: Alignment.centerLeft, 147 | child: Row( 148 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 149 | children: [ 150 | Container( 151 | child: Text( 152 | "apple", 153 | style: TextStyle( 154 | fontSize: 16, 155 | fontWeight: FontWeight.normal, 156 | ), 157 | ), 158 | ), 159 | Container( 160 | child: InkWell( 161 | onTap: () { 162 | print("删除"); 163 | }, 164 | child: Icon(Icons.delete_outline), 165 | ), 166 | ) 167 | ], 168 | )), 169 | Divider(), 170 | Container( 171 | padding: EdgeInsets.only(top: 50), 172 | width: ScreenAdaper.getScreenWidth() - 40, 173 | child: GHButton( 174 | "清空历史记录", 175 | tapAction: () { 176 | print("清空"); 177 | }, 178 | ), 179 | ), 180 | ], 181 | ) 182 | ], 183 | ), 184 | ); 185 | } 186 | 187 | Widget _commomTitleWidget(text, iconData) { 188 | return Column( 189 | crossAxisAlignment: CrossAxisAlignment.start, 190 | children: [ 191 | Container( 192 | padding: EdgeInsets.fromLTRB(20, 20, 20, 0), 193 | child: Row( 194 | children: [ 195 | Container( 196 | child: Icon( 197 | iconData, 198 | color: Colors.red, 199 | ), 200 | ), 201 | SizedBox( 202 | width: 5, 203 | ), 204 | Container( 205 | child: Text(text, 206 | style: 207 | TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), 208 | ), 209 | ], 210 | )), 211 | Divider(), 212 | ], 213 | ); 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /lib/pages/Test.dart: -------------------------------------------------------------------------------- 1 | //import 'dart:convert'; 2 | // 3 | //import 'package:flutter/material.dart'; 4 | ////import 'package:sy_flutter_alipay/sy_flutter_alipay.dart'; 5 | ////import 'package:dio/dio.dart'; 6 | ////import 'package:sy_flutter_wechat/sy_flutter_wechat.dart'; 7 | // 8 | //class AliPay extends StatefulWidget { 9 | // @override 10 | // _AliPayState createState() => _AliPayState(); 11 | //} 12 | // 13 | //class _AliPayState extends State { 14 | // @override 15 | // void initState() { 16 | // super.initState(); 17 | // _register(); 18 | // } 19 | // 20 | // _register() async { 21 | // bool result = await SyFlutterWechat.register('wx5881fa2638a2ca60'); 22 | // print(result); 23 | // } 24 | // _wxPay() async{ 25 | // var apiUrl='http://agent.itying.com/wxpay/'; 26 | // var myPayInfo =await Dio().get(apiUrl); 27 | // 28 | // Map myInfo =json.decode(myPayInfo.data); 29 | // print(myInfo); 30 | // 31 | // var payInfo={ 32 | // "appid":myInfo["appid"].toString(), 33 | // "partnerid":myInfo["partnerid"].toString(), 34 | // "prepayid":myInfo["prepayid"].toString(), 35 | // "package":myInfo["package"].toString(), 36 | // "noncestr":myInfo["noncestr"].toString(), 37 | // "timestamp":myInfo["timestamp"].toString(), 38 | // "sign":myInfo["sign"].toString(), 39 | // }; 40 | // SyPayResult payResult = await SyFlutterWechat.pay( 41 | // SyPayInfo.fromJson(payInfo) 42 | // ); 43 | // 44 | // print(payResult); 45 | // } 46 | // 47 | // //支付宝支付 48 | // _doAliPay() async { 49 | // print("支付宝支付..."); 50 | // var serverApi = "http://agent.itying.com/alipay/"; 51 | // 52 | // var serverData = await Dio().get(serverApi); 53 | // 54 | // var payInfo = serverData.data; 55 | // var result = await SyFlutterAlipay.pay( 56 | // payInfo, 57 | // urlScheme: 'flutteralipay', //前面配置的urlScheme 58 | // // isSandbox: true //是否是沙箱环境,只对android有效 59 | // ); 60 | // print(result); 61 | // } 62 | // 63 | // @override 64 | // Widget build(BuildContext context) { 65 | // return Scaffold( 66 | // 67 | // body: Center( 68 | // child: Column( 69 | // mainAxisAlignment: MainAxisAlignment.center, 70 | // children: [ 71 | // RaisedButton( 72 | // child: Text('支付宝支付'), 73 | // onPressed: _doAliPay, 74 | // ), 75 | // RaisedButton( 76 | // child: Text('分享文字'), 77 | // onPressed: () async { 78 | // bool res = await SyFlutterWechat.shareText('hello world', 79 | // shareType: SyShareType.session); 80 | // print('分享文字:' + res.toString()); 81 | // }, 82 | // ), 83 | // RaisedButton( 84 | // child: Text('分享图片'), 85 | // onPressed: () async { 86 | // bool res = await SyFlutterWechat.shareImage( 87 | // 'https://avatars0.githubusercontent.com/u/10024776', 88 | // shareType: SyShareType.timeline); 89 | // print('分享图片:' + res.toString()); 90 | // }, 91 | // ), 92 | // RaisedButton( 93 | // child: Text('分享网页'), 94 | // onPressed: () async { 95 | // bool res = await SyFlutterWechat.shareWebPage( 96 | // '标题', 97 | // '描述', 98 | // 'https://avatars0.githubusercontent.com/u/10024776', 99 | // 'http://www.example.com', 100 | // shareType: SyShareType.session); 101 | // print('分享网页:' + res.toString()); 102 | // }, 103 | // ), 104 | // RaisedButton( 105 | // child: Text('支付'), 106 | // onPressed: _wxPay, 107 | // ), 108 | // ], 109 | // ), 110 | // ), 111 | // ); 112 | // } 113 | //} 114 | // 115 | // 116 | // 117 | // 118 | -------------------------------------------------------------------------------- /lib/pages/tabs/GHCategoryPage.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../../services/ScreenAdaper.dart'; 3 | import 'package:flutter_swiper/flutter_swiper.dart'; 4 | import '../../widget/LoadingWidget.dart'; 5 | import '../../services/httptool.dart'; 6 | import '../../model/GHCategoryModel.dart'; 7 | import 'dart:convert'; 8 | import 'package:transparent_image/transparent_image.dart'; 9 | import '../../widget/GHCustomAppbar.dart'; 10 | import '../../services/GHToast.dart'; 11 | //import 'package:barcode_scan/barcode_scan.dart'; 12 | 13 | /// 分类 14 | class GHCategoryPage extends StatefulWidget { 15 | GHCategoryPage({Key key}) : super(key: key); 16 | 17 | _GHCategoryPageState createState() => _GHCategoryPageState(); 18 | } 19 | 20 | class _GHCategoryPageState extends State 21 | with AutomaticKeepAliveClientMixin { 22 | 23 | /// 左侧选择序号 24 | int _selectIndex = 0; 25 | 26 | List _leftCateList = []; 27 | 28 | List _urls = []; 29 | 30 | String _firstTitle; 31 | 32 | /// 第一组商品 33 | List _firstGoods = []; 34 | 35 | String _secondTitle; 36 | 37 | /// 第二组商品 38 | List _secondGoods = []; 39 | 40 | // final picker = ImagePicker(); 41 | @override 42 | 43 | /// 保持页面状态 44 | bool get wantKeepAlive => true; 45 | 46 | void initState() { 47 | super.initState(); 48 | _getLeftCateData(); 49 | } 50 | 51 | /// 获取左侧分类 52 | _getLeftCateData() async { 53 | var url = "https://a4cj1hm5.api.lncld.net/1.1/classes/shopCategory"; 54 | await HttpRequest.request(url, method: 'GET').then((value) { 55 | var list = new GHCategoryModel.fromJson(value).results; 56 | setState(() { 57 | this._leftCateList = list; 58 | }); 59 | }); 60 | _getRightCateData(this._leftCateList[0].type); 61 | } 62 | 63 | /// 获取右侧分类 64 | _getRightCateData(type) async { 65 | var url = "https://a4cj1hm5.api.lncld.net/1.1/classes/shopSecondCategory"; 66 | //where={"type":"1"} 67 | /// urlEncode编码 68 | var actionString = {"type": type}; 69 | var jsonText = jsonEncode(actionString); 70 | var parameter = Uri.encodeFull(jsonText); 71 | 72 | /// 得到最终url 73 | url = url + '?' + "where=" + parameter; 74 | 75 | await HttpRequest.request(url, method: 'GET').then((value) { 76 | print(value); 77 | List results = value["results"]; 78 | if (results.isEmpty && results.length == 0) { 79 | GHToast.showTost("获取数据失败,请检查服务器"); 80 | return; 81 | } 82 | Map urlMap = results.first["urls"]; 83 | List urls = urlMap["url"]; 84 | List firstGoods = []; 85 | List secondGoods = []; 86 | List firstgoods = results.first["firstDict"]["goods"]; 87 | List secondgoods = results.first["secondDict"]["goods"]; 88 | String firstTitle = results.first["firstDict"]["title"]; 89 | String secondTitle = results.first["secondDict"]["title"]; 90 | 91 | for (var dict in firstgoods) { 92 | var item = new GHCategoryItemModel.fromJson(dict); 93 | firstGoods.add(item); 94 | } 95 | 96 | for (var dict in secondgoods) { 97 | var item = new GHCategoryItemModel.fromJson(dict); 98 | secondGoods.add(item); 99 | } 100 | setState(() { 101 | this._urls = urls; 102 | this._firstTitle = firstTitle; 103 | this._firstGoods = firstGoods; 104 | this._secondTitle = secondTitle; 105 | this._secondGoods = secondGoods; 106 | }); 107 | }); 108 | } 109 | 110 | /// 左侧列表Widget 111 | Widget _leftCateWidget(leftWidth) { 112 | if (this._leftCateList.length == 0) { 113 | return LoadingWidget(); 114 | } 115 | return Container( 116 | width: leftWidth, 117 | height: double.infinity, 118 | child: ListView.builder( 119 | itemCount: this._leftCateList.length, 120 | itemBuilder: (context, index) { 121 | GHCategoryItemModel itemModel = this._leftCateList[index]; 122 | return Column( 123 | mainAxisAlignment: MainAxisAlignment.center, 124 | children: [ 125 | InkWell( 126 | onTap: () { 127 | setState(() { 128 | this._selectIndex = index; 129 | this._getRightCateData(this._leftCateList[index].type); 130 | }); 131 | }, 132 | child: Stack( 133 | children: [ 134 | Container( 135 | alignment: Alignment.center, 136 | width: double.infinity, 137 | height: ScreenAdaper.height(80), 138 | color: this._selectIndex != index 139 | ? Color.fromRGBO(233, 233, 233, 0.2) 140 | : Colors.white, 141 | child: Text( 142 | "${itemModel.categoryName}", 143 | textAlign: TextAlign.center, 144 | style: TextStyle( 145 | fontSize: this._selectIndex != index ? 14 : 16, 146 | fontWeight: this._selectIndex != index 147 | ? FontWeight.normal 148 | : FontWeight.bold, 149 | ), 150 | ), 151 | ), 152 | Container( 153 | width: double.infinity, 154 | height: ScreenAdaper.height(80), 155 | child: Row( 156 | crossAxisAlignment: CrossAxisAlignment.center, 157 | mainAxisAlignment: MainAxisAlignment.start, 158 | children: [ 159 | Container( 160 | height: 18, 161 | width: 3, 162 | color: this._selectIndex != index 163 | ? Colors.transparent 164 | : Colors.red, 165 | ) 166 | ], 167 | ), 168 | ) 169 | ], 170 | )), 171 | Divider(height: 0.5), 172 | ], 173 | ); 174 | }, 175 | ), 176 | ); 177 | } 178 | 179 | /// 轮播图 180 | Widget _swiperWidget() { 181 | if (this._urls.length == 0) { 182 | return LoadingWidget(); 183 | } 184 | return Container( 185 | padding: EdgeInsets.all(10), 186 | height: 150, 187 | child: Swiper( 188 | key: UniqueKey(), 189 | itemBuilder: (BuildContext context, int index) { 190 | return InkWell( 191 | onTap: () {}, 192 | child: Image.network( 193 | this._urls[index], 194 | // pic 195 | fit: BoxFit.cover, 196 | ), 197 | ); 198 | }, 199 | itemCount: this._urls.length, 200 | pagination: new SwiperPagination(), 201 | autoplay: false), 202 | ); 203 | } 204 | 205 | Widget _categoryItem( 206 | GHCategoryItemModel categoryItemModel, BuildContext context) { 207 | return InkWell( 208 | onTap: () { 209 | Navigator.pushNamed(context, '/GHGoodsList'); 210 | }, 211 | child: Container( 212 | width: (ScreenAdaper.getScreenWidth() - 213 | ScreenAdaper.getScreenWidth() / 4 - 214 | 40) / 215 | 3.0, 216 | child: Column( 217 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 218 | children: [ 219 | Container( 220 | height: 80, 221 | padding: EdgeInsets.all(10), 222 | child: new FadeInImage.memoryNetwork( 223 | placeholder: kTransparentImage, 224 | image: categoryItemModel.url, 225 | ), 226 | ), 227 | SizedBox(height: 5), 228 | Container( 229 | child: Text( 230 | categoryItemModel.categoryName, 231 | style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14), 232 | ), 233 | ) 234 | ], 235 | ), 236 | )); 237 | } 238 | 239 | Widget _firstWidget(String title, List list, BuildContext context) { 240 | return ListView( 241 | shrinkWrap: true, 242 | physics: NeverScrollableScrollPhysics(), 243 | children: [ 244 | Container( 245 | padding: EdgeInsets.only(left: 10), 246 | alignment: Alignment.centerLeft, 247 | child: Text( 248 | title, 249 | style: TextStyle(fontWeight: FontWeight.bold), 250 | ), 251 | ), 252 | SizedBox( 253 | height: 10, 254 | ), 255 | Container( 256 | padding: EdgeInsets.only(left: 10, right: 10, bottom: 10), 257 | child: Wrap( 258 | spacing: 10, 259 | runSpacing: 10, 260 | children: list.map((value) { 261 | return _categoryItem(value, context); 262 | }).toList(), 263 | ), 264 | ) 265 | ], 266 | ); 267 | } 268 | 269 | /// 右侧分类Widget 270 | Widget _rightCateWidget(rightItemWidth, rightItemHeight, context) { 271 | return Container( 272 | height: ScreenAdaper.getScreenHeight(), 273 | width: ScreenAdaper.getScreenWidth() / 4 * 3.0, 274 | child: ListView( 275 | children: [ 276 | _swiperWidget(), 277 | this._firstTitle == null 278 | ? Text("") 279 | : _firstWidget(this._firstTitle, this._firstGoods, context), 280 | this._secondTitle == null 281 | ? Text("") 282 | : _firstWidget(this._secondTitle, this._secondGoods, context), 283 | ], 284 | ), 285 | ); 286 | } 287 | 288 | /// 相机拍照 289 | void _takePhoto() async { 290 | // final pickedFile = await picker.getImage(source: ImageSource.camera); 291 | /// 开始二维码扫描 292 | // var result = await BarcodeScanner.scan(); 293 | // print(result); 294 | } 295 | 296 | @override 297 | Widget build(BuildContext context) { 298 | ScreenAdaper.init(context); 299 | final double topPadding = MediaQuery.of(context).padding.top; 300 | 301 | var leftWidth = ScreenAdaper.getScreenWidth() / 4; 302 | var rightItemWidth = 303 | (ScreenAdaper.getScreenWidth() - leftWidth - 20 - 20) / 3; 304 | rightItemWidth = ScreenAdaper.width(rightItemWidth); 305 | var rightItemHeight = rightItemWidth + ScreenAdaper.height(28); 306 | 307 | return Scaffold( 308 | appBar: GHCustomAppbar( 309 | contentHeight: topPadding + 20, 310 | leadingWidget: Container( 311 | padding: EdgeInsets.only(left: 20), 312 | child: GestureDetector( 313 | onTap: (){ 314 | this._takePhoto(); 315 | }, 316 | child: Icon( 317 | Icons.center_focus_weak, 318 | color: Colors.black54, 319 | ), 320 | ) 321 | ), 322 | trailingWidget: IconButton(icon: Icon(Icons.inbox), onPressed: null), 323 | titleWidget: InkWell( 324 | onTap: () { 325 | Navigator.pushNamed(context, '/search'); 326 | }, 327 | child: Container( 328 | width: ScreenAdaper.getScreenWidth() - 100, 329 | height: ScreenAdaper.height(50), 330 | padding: EdgeInsets.only(left: 5), 331 | decoration: BoxDecoration( 332 | color: Color.fromRGBO(233, 233, 233, 0.5), 333 | borderRadius: BorderRadius.circular(30), 334 | ), 335 | child: Row( 336 | children: [ 337 | Icon( 338 | Icons.search, 339 | color: Colors.black12, 340 | ), 341 | Text( 342 | "618秒杀", 343 | style: TextStyle(fontSize: 14, color: Colors.black12), 344 | ), 345 | ], 346 | ), 347 | ), 348 | ), 349 | ), 350 | body: Container( 351 | width: ScreenAdaper.getScreenWidth(), 352 | height: ScreenAdaper.getScreenHeight(), 353 | child: Row( 354 | children: [ 355 | _leftCateWidget(leftWidth), 356 | Expanded( 357 | child: _rightCateWidget(rightItemWidth, rightItemHeight, context), 358 | ) 359 | ], 360 | ), 361 | ), 362 | ); 363 | } 364 | } 365 | -------------------------------------------------------------------------------- /lib/pages/tabs/GHUserPage.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../../services/gh_sqflite.dart'; 3 | import '../../services/EventBus.dart'; 4 | import '../../widget/GHButton.dart'; 5 | import '../../services/ScreenAdaper.dart'; 6 | import '../../widget/GHDialog.dart'; 7 | import '../../widget/GHLoading.dart'; 8 | import '../GHOrderList.dart'; 9 | 10 | class GHUserPage extends StatefulWidget { 11 | GHUserPage({Key key}) : super(key: key); 12 | 13 | _GHUserPageState createState() => _GHUserPageState(); 14 | } 15 | 16 | class _GHUserPageState extends State { 17 | List list = []; 18 | var actionEventBus; 19 | 20 | getUserInfo() { 21 | sq.query().then((value) { 22 | setState(() { 23 | print(value); 24 | this.list = value; 25 | }); 26 | }); 27 | } 28 | 29 | GHSqflite sq = GHSqflite(); 30 | 31 | @override 32 | void initState() { 33 | super.initState(); 34 | this.actionEventBus = eventBus.on().listen((event) { 35 | this.getUserInfo(); 36 | }); 37 | this.getUserInfo(); 38 | } 39 | 40 | void dispose() { 41 | super.dispose(); 42 | this.actionEventBus.cancel(); 43 | } 44 | 45 | Widget _header() { 46 | return Container( 47 | decoration: BoxDecoration( 48 | image: DecorationImage( 49 | fit: BoxFit.cover, 50 | image: AssetImage( 51 | "images/bg.jpg", 52 | ), 53 | )), 54 | width: double.infinity, 55 | height: 160, 56 | child: Row( 57 | crossAxisAlignment: CrossAxisAlignment.center, 58 | children: [ 59 | Container( 60 | margin: EdgeInsets.fromLTRB(20, 30, 30, 0), 61 | child: Image.asset( 62 | 'images/logo.png', 63 | fit: BoxFit.fill, 64 | width: 80, 65 | height: 60, 66 | ), 67 | ), 68 | this.list.length == 0 69 | ? Container( 70 | child: InkWell( 71 | onTap: () { 72 | Navigator.pushNamed(context, '/login'); 73 | }, 74 | child: Text( 75 | "登录/注册", 76 | style: TextStyle(fontWeight: FontWeight.bold, fontSize: 22, color: Colors.white), 77 | ), 78 | )) 79 | : Container( 80 | child: Column( 81 | mainAxisAlignment: MainAxisAlignment.center, 82 | crossAxisAlignment: CrossAxisAlignment.start, 83 | children: [ 84 | Text( 85 | "用户名${this.list.last["username"]}", 86 | style: TextStyle(color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold), 87 | ), 88 | Text( 89 | "电话${this.list.last["mobilePhone"]}", 90 | style: TextStyle(color: Colors.white, fontSize: 14), 91 | ), 92 | ], 93 | )), 94 | ], 95 | ), 96 | ); 97 | } 98 | 99 | Widget build(BuildContext context) { 100 | ScreenAdaper.init(context); 101 | return Container( 102 | child: SafeArea( 103 | top: false, 104 | child: ListView( 105 | padding: EdgeInsets.only(top: 0), 106 | children: [ 107 | _header(), 108 | Column( 109 | children: [ 110 | Container( 111 | child: ListTile( 112 | onTap: () { 113 | print("点击"); 114 | Navigator.pushNamed(context, '/GHOrderListPage'); 115 | }, 116 | leading: Icon( 117 | Icons.star_border, 118 | color: Colors.red, 119 | ), 120 | title: Text("全部订单"), 121 | ), 122 | ), 123 | ListTile( 124 | leading: Icon(Icons.collections_bookmark, color: Colors.red), 125 | title: Text("我的收藏"), 126 | ), 127 | Container( 128 | height: 10, 129 | color: Color.fromRGBO(245, 245, 245, 1), 130 | ), 131 | ListTile( 132 | leading: Icon(Icons.people, color: Colors.red), 133 | title: Text("在线客服"), 134 | ), 135 | Container( 136 | height: 10, 137 | color: Color.fromRGBO(245, 245, 245, 1), 138 | ), 139 | ListTile( 140 | onTap: () { 141 | Navigator.pushNamed(context, '/GHAddressList'); 142 | }, 143 | leading: Icon(Icons.room, color: Colors.red), 144 | title: Text("我的地址"), 145 | ), 146 | Container( 147 | height: 20, 148 | color: Color.fromRGBO(245, 245, 245, 1), 149 | ), 150 | this.list.length > 0 151 | ? Container( 152 | width: ScreenAdaper.getScreenWidth() - 60, 153 | child: GHButton( 154 | "退出", 155 | tapAction: () { 156 | showDialog( 157 | context: context, 158 | builder: (BuildContext context) { 159 | return BaseDialog( 160 | Text("22"), 161 | 140, 162 | 300, 163 | sureAction: () { 164 | sq.deletedAllData().then((value) { 165 | Navigator.of(context).pop(this); 166 | this.getUserInfo(); 167 | GHLoading.hideLoading(context); 168 | }); 169 | }, 170 | ); 171 | }); 172 | }, 173 | ), 174 | ) 175 | : Text(""), 176 | ], 177 | ) 178 | ], 179 | ), 180 | )); 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /lib/pages/tabs/Tabs.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'GHUserPage.dart'; 3 | import '../../services/ScreenAdaper.dart'; 4 | import '../../services/gh_sqflite.dart'; 5 | import 'GHHomePage.dart'; 6 | import 'GHCategoryPage.dart'; 7 | import 'GHShopCartPage.dart'; 8 | 9 | /// tab 10 | class Tabs extends StatefulWidget { 11 | Map arguments; 12 | 13 | Tabs({Key key, this.arguments}) : super(key: key); 14 | 15 | _TabsState createState() => _TabsState(); 16 | } 17 | 18 | class _TabsState extends State { 19 | int _currentIndex = 0; 20 | PageController _pageController; 21 | 22 | @override 23 | void initState() { 24 | super.initState(); 25 | 26 | if (widget.arguments != null) { 27 | this._currentIndex = widget.arguments["index"]; 28 | } else { 29 | this._currentIndex = 0; 30 | } 31 | this._pageController = new PageController(initialPage: this._currentIndex); 32 | 33 | GHSqflite sq = GHSqflite(); 34 | sq.create(); 35 | } 36 | 37 | List _pageList = [ 38 | GHHomePage(), 39 | GHCategoryPage(), 40 | GHShopCartPage(), 41 | GHUserPage() 42 | ]; 43 | 44 | @override 45 | Widget build(BuildContext context) { 46 | ScreenAdaper.init(context); 47 | return Scaffold( 48 | body: PageView( 49 | controller: this._pageController, 50 | children: this._pageList, 51 | physics: NeverScrollableScrollPhysics(), // 禁止滑动 52 | ), 53 | bottomNavigationBar: BottomNavigationBar( 54 | currentIndex: this._currentIndex, 55 | onTap: (index) { 56 | setState(() { 57 | this._currentIndex = index; 58 | this._pageController.jumpToPage(index); 59 | }); 60 | }, 61 | type: BottomNavigationBarType.fixed, 62 | fixedColor: Colors.red, 63 | items: [ 64 | BottomNavigationBarItem( 65 | icon: Icon(Icons.home), 66 | title: Text( 67 | "首页", 68 | style: TextStyle(fontSize: 12), 69 | ), 70 | ), 71 | BottomNavigationBarItem( 72 | icon: Icon(Icons.category), 73 | title: Text( 74 | "分类", 75 | style: TextStyle(fontSize: 12), 76 | ), 77 | ), 78 | BottomNavigationBarItem( 79 | icon: Icon(Icons.shopping_cart), 80 | title: Text( 81 | "购物车", 82 | style: TextStyle(fontSize: 12), 83 | ), 84 | ), 85 | BottomNavigationBarItem( 86 | icon: Icon(Icons.person), 87 | title: Text( 88 | "我的", 89 | style: TextStyle(fontSize: 12), 90 | ), 91 | ) 92 | ], 93 | ), 94 | ); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /lib/provider/Cart.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import '../services/Storage.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class Cart with ChangeNotifier { 6 | List _cartList = []; 7 | bool _isCheckAll = false; 8 | double _totalPrice = 0.0; 9 | 10 | List get cartList => this._cartList; 11 | 12 | bool get isCheckAll => this._isCheckAll; 13 | 14 | double get totalPrice => this._totalPrice; 15 | 16 | Cart() { 17 | this.init(); 18 | } 19 | 20 | init() async { 21 | try { 22 | List cartListData = json.decode(await Storage.getString('cartList')); 23 | this._cartList = cartListData; 24 | print("初始化"); 25 | print(cartListData); 26 | } catch (e) { 27 | this._cartList = []; 28 | } 29 | this.isCheckAllMember(); 30 | getTotalPrice(); 31 | notifyListeners(); 32 | } 33 | 34 | addList(value) { 35 | _cartList.add(value); 36 | notifyListeners(); 37 | } 38 | 39 | updataCartList() { 40 | this.init(); 41 | } 42 | 43 | changeCartList() { 44 | Storage.setString('cartList', json.encode(this._cartList)); 45 | getTotalPrice(); 46 | notifyListeners(); 47 | } 48 | 49 | check(value) { 50 | for (var i = 0; i < this._cartList.length; i++) { 51 | this._cartList[i]["checked"] = value; 52 | } 53 | this._isCheckAll = value; 54 | Storage.setString('cartList', json.encode(this._cartList)); 55 | isCheckAllMember(); 56 | getTotalPrice(); 57 | notifyListeners(); 58 | } 59 | 60 | /// 判断全选按钮状态 61 | isCheckAllMember() async { 62 | List cartListData = json.decode(await Storage.getString('cartList')); 63 | print(cartListData); 64 | if (cartListData.length > 0) { 65 | for (var i = 0; i < cartListData.length; i++) { 66 | if (cartListData[i]["checked"] == false) { 67 | _isCheckAll = false; 68 | print("取消"); 69 | break; 70 | } 71 | _isCheckAll = true; 72 | print("轩重工"); 73 | } 74 | } 75 | } 76 | 77 | itemChange(value) async { 78 | for (var i = 0; i < this.cartList.length; i++) { 79 | String seletecAttr = 80 | this.cartList[i]["_id"] + this.cartList[i]['seletecAttr']; 81 | String attr = value["_id"] + value['seletecAttr']; 82 | 83 | if (attr == seletecAttr) { 84 | this.cartList[i]["checked"] = value["checked"]; 85 | } 86 | } 87 | Storage.setString('cartList', json.encode(this._cartList)); 88 | isCheckAllMember(); 89 | getTotalPrice(); 90 | notifyListeners(); 91 | } 92 | 93 | removeAllData() { 94 | Storage.remove("cartList"); 95 | getTotalPrice(); 96 | this.cartList.clear(); 97 | notifyListeners(); 98 | } 99 | 100 | getTotalPrice() { 101 | double totalPrice = 0; 102 | for (var i = 0; i < this.cartList.length; i++) { 103 | if (this.cartList[i]["checked"] == true) { 104 | String price = (this.cartList[i]["price"]); 105 | int count = (this.cartList[i]["count"]); 106 | totalPrice = double.parse(price) * count + totalPrice; 107 | } 108 | } 109 | this._totalPrice = totalPrice; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /lib/routers/router.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../pages/tabs/Tabs.dart'; 3 | import '../pages/Search.dart'; 4 | import '../pages/GHLoginPage.dart'; 5 | import '../pages/GHAddressList.dart'; 6 | import '../pages/GHAddressEdit.dart'; 7 | import '../pages/GHOnlinePayments.dart'; 8 | import '../pages/GHGoodsList.dart'; 9 | import '../pages/GHGoodsDetails.dart'; 10 | import '../pages/Test.dart'; 11 | import '../pages/GHCheckOutPage.dart'; 12 | import '../pages/GHOrderList.dart'; 13 | 14 | 15 | //配置路由 16 | final routes = { 17 | '/': (context,{arguments}) => Tabs(arguments:arguments), 18 | '/search': (context) => SearchPage(), 19 | '/login': (context) => GHLoginPage(), 20 | '/GHAddressList': (context,{arguments}) => GHAddressList(), 21 | '/GHAddressEdit': (context,{arguments}) => GHAddressEdit(arguments:arguments), 22 | '/OnlinePayments': (context,{arguments}) => GHOnlinePayments(arguments:arguments), 23 | '/GHGoodsList': (context,{arguments}) => GHGoodsList(), 24 | '/GHGoodsDetails': (context,{arguments}) => GHGoodsDetails(arguments:arguments), 25 | 26 | /// 订单确认页 27 | '/GHCheckOutPage': (context,{arguments}) => GHCheckOutPage(arguments:arguments), 28 | /// 订单列表 29 | '/GHOrderListPage': (context) => GHOrderListPage(), 30 | }; 31 | 32 | /// 固定写法不需要改动 33 | var onGenerateRoute = (RouteSettings settings) { 34 | // 统一处理 35 | final String name = settings.name; 36 | final Function pageContentBuilder = routes[name]; 37 | if (pageContentBuilder != null) { 38 | if (settings.arguments != null) { 39 | final Route route = MaterialPageRoute( 40 | builder: (context) => 41 | pageContentBuilder(context, arguments: settings.arguments)); 42 | return route; 43 | } else { 44 | final Route route = 45 | MaterialPageRoute(builder: (context) => pageContentBuilder(context)); 46 | return route; 47 | } 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /lib/services/EventBus.dart: -------------------------------------------------------------------------------- 1 | import 'package:event_bus/event_bus.dart'; 2 | 3 | EventBus eventBus = EventBus(); 4 | 5 | class ProductContentEvent { 6 | String str; 7 | 8 | ProductContentEvent(String str) { 9 | this.str = str; 10 | } 11 | } 12 | 13 | 14 | class LoginSuccessEvent { 15 | String str; 16 | 17 | LoginSuccessEvent(String str) { 18 | this.str = str; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/services/GHLog.dart: -------------------------------------------------------------------------------- 1 | 2 | void GHLog(Object message, StackTrace current) { 3 | GHCustomTrace programInfo = GHCustomTrace(current); 4 | print("所在文件: ${programInfo.fileName}, 所在行: ${programInfo.lineNumber}, 打印信息: $message"); 5 | } 6 | 7 | 8 | class GHCustomTrace { 9 | final StackTrace _trace; 10 | 11 | String fileName; 12 | int lineNumber; 13 | int columnNumber; 14 | 15 | GHCustomTrace(this._trace) { 16 | _parseTrace(); 17 | } 18 | 19 | void _parseTrace() { 20 | var traceString = this._trace.toString().split("\n")[0]; 21 | var indexOfFileName = traceString.indexOf(RegExp(r'[A-Za-z_]+.dart')); 22 | var fileInfo = traceString.substring(indexOfFileName); 23 | var listOfInfos = fileInfo.split(":"); 24 | this.fileName = listOfInfos[0]; 25 | this.lineNumber = int.parse(listOfInfos[1]); 26 | var columnStr = listOfInfos[2]; 27 | columnStr = columnStr.replaceFirst(")", ""); 28 | this.columnNumber = int.parse(columnStr); 29 | } 30 | } -------------------------------------------------------------------------------- /lib/services/GHToast.dart: -------------------------------------------------------------------------------- 1 | import 'package:fluttertoast/fluttertoast.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class GHToast{ 5 | 6 | static Future showTost(String toast) { 7 | Fluttertoast.showToast( 8 | msg: toast, 9 | toastLength: Toast.LENGTH_SHORT, 10 | gravity: ToastGravity.CENTER, 11 | timeInSecForIos: 1, 12 | textColor: Colors.white, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/services/ScreenAdaper.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_screenutil/flutter_screenutil.dart'; 2 | 3 | class ScreenAdaper { 4 | static init(context) { 5 | ScreenUtil.init(context, width: 750, height: 1334); 6 | } 7 | 8 | static height(double value) { 9 | return ScreenUtil().setHeight(value); 10 | } 11 | 12 | static width(double value) { 13 | return ScreenUtil().setWidth(value); 14 | } 15 | 16 | static getScreenHeight() { 17 | return ScreenUtil.screenHeight; 18 | } 19 | 20 | static getScreenWidth() { 21 | return ScreenUtil.screenWidth; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /lib/services/SearchServices.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'Storage.dart'; 4 | 5 | class SearchServices { 6 | static setHistoryData(keywords) async { 7 | /* 8 | 1、获取本地存储里面的数据 (searchList) 9 | 10 | 2、判断本地存储是否有数据 11 | 12 | 2.1、如果有数据 13 | 14 | 1、读取本地存储的数据 15 | 2、判断本地存储中有没有当前数据, 16 | 如果有不做操作、 17 | 如果没有当前数据,本地存储的数据和当前数据拼接后重新写入 18 | 19 | 20 | 2.2、如果没有数据 21 | 22 | 直接把当前数据放在数组中写入到本地存储 23 | 24 | 25 | */ 26 | 27 | try { 28 | List searchListData = json.decode(await Storage.getString('searchList')); 29 | 30 | print(searchListData); 31 | var hasData = searchListData.any((v) { 32 | return v == keywords; 33 | }); 34 | if (!hasData) { 35 | searchListData.add(keywords); 36 | await Storage.setString('searchList', json.encode(searchListData)); 37 | } 38 | } catch (e) { 39 | List tempList = new List(); 40 | tempList.add(keywords); 41 | await Storage.setString('searchList', json.encode(tempList)); 42 | } 43 | } 44 | static getHistoryList() async{ 45 | try { 46 | List searchListData = json.decode(await Storage.getString('searchList')); 47 | return searchListData; 48 | } catch (e) { 49 | return []; 50 | } 51 | } 52 | 53 | static clearHistoryList() async{ 54 | await Storage.remove('searchList'); 55 | } 56 | static removeHistoryData(keywords) async{ 57 | List searchListData = json.decode(await Storage.getString('searchList')); 58 | searchListData.remove(keywords); 59 | await Storage.setString('searchList', json.encode(searchListData)); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /lib/services/Storage.dart: -------------------------------------------------------------------------------- 1 | import 'package:shared_preferences/shared_preferences.dart'; 2 | 3 | class Storage{ 4 | 5 | static Future setString(key,value) async{ 6 | SharedPreferences sp=await SharedPreferences.getInstance(); 7 | sp.setString(key, value); 8 | } 9 | static Future getString(key) async{ 10 | SharedPreferences sp=await SharedPreferences.getInstance(); 11 | return sp.getString(key); 12 | } 13 | static Future remove(key) async{ 14 | SharedPreferences sp=await SharedPreferences.getInstance(); 15 | sp.remove(key); 16 | } 17 | static Future clear() async{ 18 | SharedPreferences sp=await SharedPreferences.getInstance(); 19 | sp.clear(); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /lib/services/gh_sqflite.dart: -------------------------------------------------------------------------------- 1 | import 'package:sqflite/sqflite.dart'; 2 | import 'package:path/path.dart'; 3 | import 'dart:io'; 4 | 5 | String dbPath = ""; 6 | 7 | /// 数据库名称 8 | String dbName = "user.db"; 9 | 10 | /// 用户表 11 | String userTable = "user"; 12 | 13 | /// 用户表SQL 14 | String userTableSQL = 15 | "create table user (id integer primary key, objectId text, username text,mobilePhone text)"; 16 | 17 | class GHSqflite { 18 | /// 判断表是否存在 19 | Future isTableExits(String tableName) async { 20 | await getDatabasesPath(); 21 | Database db = await openDatabase(dbPath); 22 | var res = await db.rawQuery( 23 | "select * from Sqlite_master where type = 'table' and name = '$tableName'"); 24 | return res; 25 | } 26 | 27 | /// 创建数据库 28 | create() async { 29 | dbPath = await createNewDb(dbName); 30 | Database db = await openDatabase(dbPath); 31 | await this.isTableExits("user").then((value) { 32 | if (value.length == 0) { 33 | db.execute(userTableSQL); 34 | } 35 | db.close(); 36 | }); 37 | } 38 | 39 | /// 打开数据库 40 | open() async { 41 | if (null == dbPath) { 42 | var path = await getDatabasesPath(); 43 | dbPath = join(path, dbName); 44 | print('dbPath:' + dbPath); 45 | } 46 | return await openDatabase(dbPath); 47 | } 48 | 49 | /// 创建数据库 50 | Future createNewDb(String dbName) async { 51 | var dbPath = await getDatabasesPath(); 52 | String path = join(dbPath, dbName); 53 | if (await new Directory(dirname(path)).exists()) { 54 | print("存在数据库"); 55 | } else { 56 | try { 57 | await new Directory(dirname(path)).create(recursive: true); 58 | } catch (e) { 59 | print(e); 60 | } 61 | } 62 | return path; 63 | } 64 | 65 | /// 添加数据 66 | add(String objectId, String username, String mobilePhone) async { 67 | Database db = await open(); 68 | String sql = 69 | "insert into user(objectId,username,mobilePhone) values('$objectId', '$username','$mobilePhone')"; 70 | await db.transaction((txn) async { 71 | int id = await txn.rawInsert(sql); 72 | print('插入数据成功'); 73 | }); 74 | await db.close(); 75 | } 76 | 77 | /// 查询所有数据 78 | Future query() async { 79 | Database db = await open(); 80 | List list = await db.rawQuery("select * from user"); 81 | await db.close(); 82 | return list; 83 | } 84 | 85 | /// 根据id删除指定数据 86 | delete(Map info) async { 87 | var id = info["id"]; 88 | Database db = await open(); 89 | String sql = "DELETE FROM user where id = $id"; 90 | await db.rawDelete(sql); 91 | await db.close(); 92 | print('删除数据成功'); 93 | } 94 | 95 | /// 更新数据 96 | update(int id, String account, String pwd) async { 97 | Database db = await open(); 98 | String sql = "Update user set password = ?, username = ? where id = ?"; 99 | int count = await db.rawUpdate(sql, [pwd, account, id]); 100 | await db.close(); 101 | print('更新数据成功'); 102 | } 103 | 104 | /// 删除当前表所有数据 105 | Future deletedAllData() async { 106 | Database db = await open(); 107 | int count = await db.delete("user"); 108 | await db.close(); 109 | print('删除数据成功'); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /lib/services/httptool.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | 3 | class HttpRequest { 4 | static final BaseOptions options = BaseOptions(baseUrl: ""); 5 | 6 | static final Dio dio = Dio(options); 7 | 8 | static Future request(String url, 9 | {String method, Map params, Interceptor inter}) async { 10 | // 1.请求的单独配置 11 | Options options = Options(method: method); 12 | options.headers = httpHeaders; 13 | // // 2.添加第一个拦截器 14 | // Interceptor dInter = 15 | // InterceptorsWrapper(onRequest: (RequestOptions options) { 16 | // // 1.在进行任何网络请求的时候, 可以添加一个loading显示 17 | // 18 | // // 2.很多页面的访问必须要求携带Token,那么就可以在这里判断是有Token 19 | // 20 | // // 3.对参数进行一些处理,比如序列化处理等 21 | // print("拦截了请求"); 22 | // return options; 23 | // }, onResponse: (Response response) { 24 | // print("拦截了响应"); 25 | // return response; 26 | // }, onError: (DioError error) { 27 | // print("拦截了错误"); 28 | // return error; 29 | // }); 30 | // 31 | // List inters = [dInter]; 32 | // if (inter != null) { 33 | // inters.add(inter); 34 | // } 35 | // 36 | // dio.interceptors.addAll(inters); 37 | // 3.发送网络请求 38 | try { 39 | Response response = 40 | await dio.request(url, data: params, options: options); 41 | return response.data; 42 | } on DioError catch (e) { 43 | return Future.error(e); 44 | } 45 | } 46 | } 47 | 48 | const httpHeaders = { 49 | 'Content-Type': 'application/json', 50 | 'X-LC-Id': 'a4Cj1Hm5aMrdhob6xGw71B5A-gzGzoHsz', 51 | 'X-LC-Key': 'XQaL1tUQC0DCQxBA9fpoR21C', 52 | }; 53 | -------------------------------------------------------------------------------- /lib/widget/GHButton.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class GHButton extends StatelessWidget { 4 | /// 背景颜色 5 | final Color backGroudColor; 6 | 7 | /// 标题 8 | final String title; 9 | 10 | /// 点击事件 11 | final Object tapAction; 12 | 13 | @override 14 | GHButton(this.title, 15 | {Key key, this.tapAction, this.backGroudColor = Colors.red}) 16 | : super(key: key); 17 | 18 | Widget build(BuildContext context) { 19 | return Container( 20 | decoration: BoxDecoration( 21 | borderRadius: BorderRadius.circular(8), color: Colors.red), 22 | height: 50, 23 | child: TextButton( 24 | onPressed: this.tapAction, 25 | child: Text( 26 | this.title, 27 | style: TextStyle(color: Colors.white, fontSize: 16), 28 | ), 29 | ), 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/widget/GHCountItemWidget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | typedef clickCallback = void Function(int value); 4 | 5 | /// 显示数量子控件 6 | class GHCountItemWidger extends StatefulWidget { 7 | /// 数量 8 | int count; 9 | 10 | /// 是否可以点击 11 | bool isEnable; 12 | 13 | final clickCallback addClick; 14 | final clickCallback subClick; 15 | 16 | GHCountItemWidger({ 17 | Key key, 18 | this.isEnable = true, 19 | this.count, 20 | this.addClick, 21 | this.subClick, 22 | }) : super(key: key); 23 | 24 | _GHCountItemWidgerState createState() => _GHCountItemWidgerState(); 25 | } 26 | 27 | class _GHCountItemWidgerState extends State { 28 | @override 29 | 30 | /// 数量 31 | int _count; 32 | 33 | void initState() { 34 | super.initState(); 35 | this._count = widget.count; 36 | } 37 | 38 | Widget _centerNumber() { 39 | return Container( 40 | decoration: BoxDecoration( 41 | border: Border.all( 42 | width: 1, 43 | color: Colors.black12, 44 | )), 45 | child: Row( 46 | children: [ 47 | Container( 48 | alignment: Alignment.center, 49 | width: 40, 50 | height: 20, 51 | child: Text("${this._count}"), 52 | decoration: BoxDecoration( 53 | border: Border( 54 | left: BorderSide( 55 | width: 0.5, 56 | color: Colors.black12, 57 | ), 58 | right: BorderSide( 59 | width: 1, 60 | color: Colors.black12, 61 | )), 62 | ), 63 | ), 64 | ], 65 | ), 66 | ); 67 | } 68 | 69 | Widget _rightNumber() { 70 | return GestureDetector( 71 | behavior: HitTestBehavior.opaque, 72 | onTap: () { 73 | if (!widget.isEnable) { 74 | print("禁止响应"); 75 | return; 76 | } 77 | setState(() { 78 | this._count++; 79 | }); 80 | widget.addClick(this._count); 81 | }, 82 | child: Container( 83 | decoration: BoxDecoration( 84 | border: Border.all( 85 | width: 1, 86 | color: Colors.black12, 87 | )), 88 | child: Row( 89 | children: [ 90 | Container( 91 | alignment: Alignment.center, 92 | width: 20, 93 | height: 20, 94 | child: Text("+"), 95 | ), 96 | ], 97 | ), 98 | ), 99 | ); 100 | } 101 | 102 | Widget _leftNumber() { 103 | return GestureDetector( 104 | onTap: () { 105 | if (!widget.isEnable) { 106 | print("禁止响应"); 107 | return; 108 | } 109 | 110 | if (this._count > 1) { 111 | setState(() { 112 | this._count--; 113 | }); 114 | } 115 | widget.subClick(this._count); 116 | }, 117 | behavior: HitTestBehavior.opaque, 118 | child: Container( 119 | decoration: BoxDecoration( 120 | border: Border.all( 121 | width: 1, 122 | color: Colors.black12, 123 | )), 124 | child: Row( 125 | children: [ 126 | Container( 127 | alignment: Alignment.center, 128 | width: 20, 129 | height: 20, 130 | child: Text("-"), 131 | ), 132 | ], 133 | ), 134 | ), 135 | ); 136 | } 137 | 138 | Widget build(BuildContext context) { 139 | return Container( 140 | padding: EdgeInsets.all(10), 141 | child: Row( 142 | mainAxisAlignment: MainAxisAlignment.end, 143 | children: [ 144 | this._leftNumber(), 145 | this._centerNumber(), 146 | this._rightNumber(), 147 | ], 148 | ), 149 | ); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /lib/widget/GHCustomAppbar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// 这是一个可以指定SafeArea区域背景色的AppBar 4 | /// PreferredSizeWidget提供指定高度的方法 5 | /// 如果没有约束其高度,则会使用PreferredSizeWidget指定的高度 6 | 7 | class GHCustomAppbar extends StatefulWidget implements PreferredSizeWidget { 8 | final double contentHeight; //从外部指定高度 9 | Color navigationBarBackgroundColor; //设置导航栏背景的颜色 10 | Widget leadingWidget; 11 | Widget trailingWidget; 12 | Widget titleWidget; 13 | 14 | GHCustomAppbar({ 15 | @required this.leadingWidget, 16 | this.contentHeight = 44, 17 | this.navigationBarBackgroundColor = Colors.white, 18 | this.titleWidget, 19 | this.trailingWidget, 20 | }) : super(); 21 | 22 | @override 23 | State createState() { 24 | return new _GHCustomAppbarState(); 25 | } 26 | 27 | @override 28 | Size get preferredSize => new Size.fromHeight(contentHeight); 29 | } 30 | 31 | /// 这里没有直接用SafeArea,而是用Container包装了一层 32 | /// 因为直接用SafeArea,会把顶部的statusBar区域留出空白 33 | /// 外层Container会填充SafeArea,指定外层Container背景色也会覆盖原来SafeArea的颜色 34 | /// var statusheight = MediaQuery.of(context).padding.top; 获取状态栏高度 35 | 36 | class _GHCustomAppbarState extends State { 37 | @override 38 | void initState() { 39 | super.initState(); 40 | } 41 | get _drawer =>Drawer( 42 | child: Text('This is Drawer'), 43 | ); 44 | @override 45 | Widget build(BuildContext context) { 46 | return Container( 47 | decoration: new BoxDecoration( 48 | boxShadow: [ 49 | BoxShadow( 50 | color: Colors.black38, 51 | offset: Offset(0.01, 0.01), 52 | blurRadius: 10.0, 53 | spreadRadius: 0.01), 54 | BoxShadow( 55 | color: Colors.black38, 56 | offset: Offset( 57 | 0.01, 58 | 0.01, 59 | )), 60 | BoxShadow(color: Colors.white) 61 | ], 62 | ), 63 | child: SafeArea( 64 | top: true, 65 | child: Container( 66 | width: double.infinity, 67 | decoration: UnderlineTabIndicator( 68 | borderSide: BorderSide(width: 1.0, color: Color(0xFFeeeeee)), 69 | ), 70 | height: widget.contentHeight, 71 | child: Row( 72 | children: [ 73 | Container( 74 | child: Container( 75 | child: widget.leadingWidget, 76 | ), 77 | ), 78 | SizedBox( 79 | width: 5, 80 | ), 81 | Container( 82 | child: widget.titleWidget, 83 | ), 84 | Container( 85 | child: Container( 86 | child: widget.trailingWidget, 87 | ), 88 | ), 89 | ], 90 | )), 91 | ), 92 | ); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /lib/widget/GHDialog.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class BaseDialog extends Dialog { 4 | final Object cancelAction; 5 | 6 | final Object sureAction; 7 | 8 | //子控件 9 | final Widget widget; 10 | 11 | // 高 12 | final double height; 13 | 14 | //宽 15 | final double width; 16 | 17 | BaseDialog(this.widget, this.height, this.width, 18 | {Key key, this.cancelAction, this.sureAction}) 19 | : super(key: key); 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return new Center( 24 | child: Padding( 25 | padding: const EdgeInsets.all(12.0), 26 | child: new Material( 27 | type: MaterialType.transparency, 28 | child: new Container( 29 | height: this.height, 30 | width: this.width, 31 | decoration: ShapeDecoration( 32 | color: Colors.white, 33 | shape: RoundedRectangleBorder( 34 | borderRadius: BorderRadius.all( 35 | Radius.circular(8.0), 36 | ))), 37 | child: Container( 38 | padding: EdgeInsets.all(20), 39 | child: Column( 40 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 41 | children: [ 42 | Container( 43 | child: Text( 44 | "确定退出吗", 45 | style: TextStyle(fontSize: 20), 46 | )), 47 | Row( 48 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 49 | children: [ 50 | InkWell( 51 | child: Container( 52 | child: Text( 53 | "取消", 54 | style: TextStyle(fontSize: 18), 55 | ), 56 | ), 57 | onTap: () { 58 | Navigator.of(context).pop(this); 59 | }, 60 | ), 61 | InkWell( 62 | child: Container( 63 | child: Text( 64 | "确定", 65 | style: 66 | TextStyle(fontSize: 18, color: Colors.red), 67 | ), 68 | ), 69 | onTap: this.sureAction, 70 | ) 71 | ], 72 | ) 73 | ], 74 | ), 75 | ))), 76 | ), 77 | ); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /lib/widget/GHLoading.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | typedef OnSuccess = void Function(Object o); 5 | typedef OnError = void Function(Exception e); 6 | 7 | 8 | class GHLoading { 9 | 10 | static bool isShow = false; 11 | 12 | static Object dismiss; 13 | 14 | static showLoading(BuildContext context) { 15 | if (!isShow) { 16 | isShow = true; 17 | showGeneralDialog( 18 | context: context, 19 | // barrierColor: Colors.white, // 背景色 20 | barrierLabel: "加载中", 21 | barrierDismissible: false, 22 | // 是否能通过点击空白处关闭 23 | transitionDuration: const Duration(milliseconds: 150), 24 | // 动画时长 25 | pageBuilder: (BuildContext context, Animation animation, 26 | Animation secondaryAnimation) { 27 | return Align( 28 | child: Container( 29 | width: 100, 30 | height: 100, 31 | decoration: BoxDecoration( 32 | color: Colors.black54, 33 | borderRadius: BorderRadius.all(Radius.circular(10)), 34 | ), 35 | child: Theme( 36 | data: ThemeData( 37 | cupertinoOverrideTheme: CupertinoThemeData( 38 | brightness: Brightness.dark, 39 | ), 40 | ), 41 | child: CupertinoActivityIndicator( 42 | radius: 14, 43 | ), 44 | ), 45 | ), 46 | ); 47 | }).then((value) { 48 | isShow = false; 49 | }); 50 | } 51 | } 52 | 53 | static hideLoading(BuildContext context) { 54 | if (isShow) { 55 | Navigator.of(context).pop(); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /lib/widget/GHRichTextPriceWidget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class GHRichTextPriceWidget extends StatelessWidget { 4 | /// 传入价格 5 | double price = 0.0; 6 | 7 | @override 8 | GHRichTextPriceWidget(this.price, {Key key}) : super(key: key); 9 | 10 | Widget build(BuildContext context) { 11 | return Container( 12 | child: RichText( 13 | text: TextSpan( 14 | text: "¥", 15 | style: TextStyle(color: Colors.red, fontSize: 10), 16 | children: [ 17 | TextSpan( 18 | text: "${price}", 19 | style: TextStyle( 20 | color: Colors.red, 21 | fontSize: 20, 22 | fontWeight: FontWeight.bold)), 23 | TextSpan( 24 | text: ".00", 25 | style: TextStyle( 26 | color: Colors.red, 27 | fontSize: 10, 28 | fontWeight: FontWeight.bold)), 29 | ])), 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/widget/GHTextWidget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// 封装TextWidget 4 | class GHTextWidget extends StatelessWidget { 5 | /// 占位文字 6 | final String text; 7 | 8 | /// 点击事件 9 | final Object onChanged; 10 | 11 | /// 字号 12 | final double fontSize; 13 | 14 | /// 是否显示底部线条 默认显示 15 | final bool isShowBottomLine; 16 | 17 | final TextEditingController textEditingController; 18 | 19 | @override 20 | GHTextWidget(this.text, 21 | {Key key, 22 | this.onChanged = null, 23 | this.fontSize = 14, 24 | this.isShowBottomLine = true, 25 | this.textEditingController}) 26 | : super(key: key); 27 | 28 | Widget build(BuildContext context) { 29 | return Container( 30 | decoration: BoxDecoration( 31 | border: Border( 32 | bottom: BorderSide( 33 | width: 1, 34 | color: 35 | this.isShowBottomLine == true ? Colors.black12 : Colors.transparent, 36 | ))), 37 | height: 50, 38 | child: TextField( 39 | controller: this.textEditingController, 40 | style: TextStyle( 41 | fontSize: this.fontSize, 42 | ), 43 | onChanged: this.onChanged, 44 | decoration: InputDecoration( 45 | suffixIcon: InkWell( 46 | onTap: () { 47 | WidgetsBinding.instance.addPostFrameCallback( 48 | (_) => this.textEditingController.text = ""); 49 | }, 50 | child: Icon( 51 | (Icons.clear), 52 | ), 53 | ), 54 | contentPadding: EdgeInsets.only(left: 0, top: 0), 55 | hintText: this.text, 56 | border: OutlineInputBorder( 57 | borderRadius: BorderRadius.circular(30), 58 | borderSide: BorderSide.none), 59 | )), 60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /lib/widget/LoadingWidget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class LoadingWidget extends StatelessWidget { 4 | const LoadingWidget({Key key}) : super(key: key); 5 | 6 | @override 7 | Widget build(BuildContext context) { 8 | return Center( 9 | child: Padding( 10 | padding: EdgeInsets.all(10.0), 11 | child: Row( 12 | mainAxisAlignment: MainAxisAlignment.center, 13 | crossAxisAlignment: CrossAxisAlignment.center, 14 | children: [ 15 | CircularProgressIndicator( 16 | strokeWidth: 1.0, 17 | ), 18 | SizedBox(width: 10), 19 | Text( 20 | '正在加载', 21 | style: TextStyle(fontSize: 14.0), 22 | ) 23 | ], 24 | ), 25 | ), 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: ghome_project 2 | description: A new Flutter project. 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # In Android, build-name is used as versionName while build-number used as versionCode. 10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 12 | # Read more about iOS versioning at 13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 14 | version: 1.0.0+1 15 | 16 | environment: 17 | sdk: ">=2.1.0 <3.0.0" 18 | 19 | dependencies: 20 | flutter: 21 | sdk: flutter 22 | 23 | # The following adds the Cupertino Icons font to your application. 24 | # Use with the CupertinoIcons class for iOS style icons. 25 | cupertino_icons: ^0.1.2 26 | flutter_swiper: ^1.1.6 27 | flutter_screenutil: ^2.1.0 28 | dio: ^3.0.9 29 | shared_preferences: ^0.5.3+1 30 | flutter_webview_plugin: ^0.3.0 31 | # flutter_inappbrowser: 1.2.1 32 | event_bus: ^1.1.0 33 | provider: ^4.3.3 34 | fluttertoast: ^3.1.0 35 | sqflite: ^1.1.5 36 | # city_pickers: ^0.2.0 37 | common_utils: ^1.2.1 38 | flutter_easyrefresh: ^2.1.6 39 | transparent_image: ^1.0.0 40 | # image_picker: 0.6.7+2 41 | # barcode_scan: ^3.0.1 42 | tencent_im_plugin: ^0.2.33 43 | # sy_flutter_alipay: ^0.2.1 44 | # sy_flutter_wechat: ^0.2.2 45 | 46 | dev_dependencies: 47 | flutter_test: 48 | sdk: flutter 49 | 50 | 51 | # For information on the generic Dart part of this file, see the 52 | # following page: https://dart.dev/tools/pub/pubspec 53 | 54 | # The following section is specific to Flutter. 55 | flutter: 56 | 57 | # The following line ensures that the Material Icons font is 58 | # included with your application, so that you can use the icons in 59 | # the material Icons class. 60 | uses-material-design: true 61 | 62 | # To add assets to your application, add an assets section, like this: 63 | assets: 64 | - images/user_bg.jpg 65 | - images/2.0x/user_bg.jpg 66 | - images/3.0x/user_bg.jpg 67 | - images/user.png 68 | - images/2.0x/user.png 69 | - images/3.0x/user.png 70 | - images/logo.png 71 | - images/2.0x/logo.png 72 | - images/3.0x/logo.png 73 | - images/bg.jpg 74 | - images/2.0x/bg.png 75 | - images/3.0x/bg.png 76 | - images/up.png 77 | - images/down.png 78 | - images/upSeletecd.png 79 | - images/downSeletecd.png 80 | - images/price.png 81 | - images/collect.png 82 | - images/customerService.png 83 | - images/shop.png 84 | - images/shoppingCart.png 85 | - images/filter.png 86 | - images/filterSeletecd.png 87 | - images/serviceIcon.png 88 | - images/thickness.png 89 | - images/goPublic.png 90 | - images/screen.png 91 | - images/checkNormal.png 92 | - images/checkSelected.png 93 | - images/pay_alipay.png 94 | - images/pay_wechat.png 95 | 96 | # An image asset can refer to one or more resolution-specific "variants", see 97 | # https://flutter.dev/assets-and-images/#resolution-aware. 98 | 99 | # For details regarding adding assets from package dependencies, see 100 | # https://flutter.dev/assets-and-images/#from-packages 101 | 102 | # To add custom fonts to your application, add a fonts section here, 103 | # in this "flutter" section. Each entry in this list should have a 104 | # "family" key with the font family name, and a "fonts" key with a 105 | # list giving the asset and other descriptors for the font. For 106 | # example: 107 | # fonts: 108 | # - family: Schyler 109 | # fonts: 110 | # - asset: fonts/Schyler-Regular.ttf 111 | # - asset: fonts/Schyler-Italic.ttf 112 | # style: italic 113 | # - family: Trajan Pro 114 | # fonts: 115 | # - asset: fonts/TrajanPro.ttf 116 | # - asset: fonts/TrajanPro_Bold.ttf 117 | # weight: 700 118 | # 119 | # For details regarding fonts from package dependencies, 120 | # see https://flutter.dev/custom-fonts/#from-packages 121 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:ghome_project/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | --------------------------------------------------------------------------------