├── ios ├── Runner │ ├── Runner-Bridging-Header.h │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── icon_1024.png │ │ │ ├── icon_20@1x.png │ │ │ ├── icon_20@2x.png │ │ │ ├── icon_20@3x.png │ │ │ ├── icon_29@1x.png │ │ │ ├── icon_29@2x.png │ │ │ ├── icon_29@3x.png │ │ │ ├── icon_40@1x.png │ │ │ ├── icon_40@2x.png │ │ │ ├── icon_40@3x.png │ │ │ ├── icon_60@2x.png │ │ │ ├── icon_60@3x.png │ │ │ ├── icon_76@1x.png │ │ │ ├── icon_76@2x.png │ │ │ ├── icon_20@2x-1.png │ │ │ ├── icon_29@2x-1.png │ │ │ ├── icon_40@2x-1.png │ │ │ ├── icon_83.5@2x.png │ │ │ └── Contents.json │ │ └── LaunchImage.imageset │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ ├── README.md │ │ │ └── Contents.json │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard │ └── Info.plist ├── Flutter │ ├── Debug.xcconfig │ ├── Release.xcconfig │ └── AppFrameworkInfo.plist ├── Runner.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme └── Runner.xcworkspace │ └── contents.xcworkspacedata ├── 示例图 ├── 伙伴.png ├── 启动图.png ├── 商店.png ├── 我的.png ├── 首页.png └── 首页推上.png ├── android ├── key.properties ├── minic_applicaion.jks ├── gradle.properties ├── app │ ├── src │ │ ├── main │ │ │ ├── res │ │ │ │ ├── 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 │ │ │ │ └── drawable │ │ │ │ │ └── launch_background.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── boohee │ │ │ │ │ └── one │ │ │ │ │ └── boohee_flutter │ │ │ │ │ └── MainActivity.kt │ │ │ └── AndroidManifest.xml │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── proguard-rules.pro │ └── build.gradle ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── settings.gradle └── build.gradle ├── images ├── ic_arrow_grey.png ├── ic_home_baby.png ├── ic_home_habit.png ├── ic_home_sleep.png ├── ic_home_sport.png ├── ic_home_step.png ├── ic_me_address.png ├── ic_me_order.png ├── ic_me_ticket.png ├── ic_boohee_logo.png ├── ic_home_calorie.png ├── ic_home_weight.png ├── ic_message_grey.png ├── ic_search_grey.png ├── ic_search_white.png ├── ic_dietician_logo.png ├── ic_home_dietician.png ├── ic_home_food_plan.png ├── ic_message_white.png ├── ic_settings_white.png ├── ic_shop_cart_white.png ├── ic_tab_bar_me_grey.png ├── ic_home_menstruation.png ├── ic_home_tabbar_plus.png ├── ic_me_shopping_cart.png ├── ic_tab_bar_home_grey.png ├── ic_tab_bar_me_green.png ├── ic_tab_bar_shop_grey.png ├── ic_arrow_light_yellow.png ├── ic_home_circumference.png ├── ic_tab_bar_home_green.png ├── ic_tab_bar_partner_grey.png ├── ic_tab_bar_shop_green.png ├── ic_tab_bar_partner_green.png └── ic_home_default_wallpaper.webp ├── fonts └── Montserrat-Bold.otf ├── lib ├── app │ └── route │ │ ├── application.dart │ │ ├── route_handlers.dart │ │ ├── routes.dart │ │ └── fluro_navigator.dart ├── main.dart ├── utils │ ├── toast_utils.dart │ ├── utils.dart │ ├── repository_utils.dart │ ├── account_utils.dart │ ├── base64_utils.dart │ └── browser_url.dart ├── common │ ├── colors.dart │ ├── view_factory.dart │ └── constant.dart ├── widget │ ├── top_bottom_widget.dart │ ├── card_view.dart │ ├── round_button.dart │ ├── tool_bar.dart │ ├── home_common_card.dart │ ├── md2_tab_indicator.dart │ ├── header │ │ └── home_wallpaper_header.dart │ └── common_search_bar.dart ├── model │ ├── splash_ad.dart │ ├── splash_ad.g.dart │ ├── mine_cards.dart │ ├── home_tools.dart │ ├── mine_cards.g.dart │ ├── home_wall_paper.dart │ ├── home_tools.g.dart │ ├── login_user.dart │ ├── home_wall_paper.g.dart │ ├── login_user.g.dart │ ├── discover │ │ ├── sub_discover.dart │ │ └── sub_discover.g.dart │ ├── ShopRecommendList.dart │ ├── ShopRecommendList.g.dart │ ├── ShopBanner.dart │ └── ShopBanner.g.dart ├── views │ ├── route_component.dart │ ├── common │ │ ├── wallpaper_page.dart │ │ └── browser_page.dart │ ├── discover_page.dart │ ├── main_page.dart │ ├── login │ │ └── login_page.dart │ ├── discover │ │ └── discover_child_page.dart │ ├── mine_page.dart │ ├── shop_pages │ │ └── shop_page.dart │ └── home_page.dart ├── res │ └── styles.dart └── splash_page.dart ├── .metadata ├── assets └── json │ ├── user │ └── login_user.json │ ├── common │ └── splash_ad.json │ ├── me │ └── mine_cards.json │ ├── home │ ├── home_health_tools.json │ └── home_wallpaper.json │ ├── discover │ └── discover_sub.json │ └── shop │ └── shop_banner.json ├── test └── widget_test.dart ├── README.md ├── .gitignore ├── pubspec.yaml └── pubspec.lock /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" -------------------------------------------------------------------------------- /示例图/伙伴.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/示例图/伙伴.png -------------------------------------------------------------------------------- /示例图/启动图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/示例图/启动图.png -------------------------------------------------------------------------------- /示例图/商店.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/示例图/商店.png -------------------------------------------------------------------------------- /示例图/我的.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/示例图/我的.png -------------------------------------------------------------------------------- /示例图/首页.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/示例图/首页.png -------------------------------------------------------------------------------- /示例图/首页推上.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/示例图/首页推上.png -------------------------------------------------------------------------------- /android/key.properties: -------------------------------------------------------------------------------- 1 | storePassword=qq123456 2 | keyPassword=qq123456 3 | keyAlias=chenyy 4 | -------------------------------------------------------------------------------- /images/ic_arrow_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_arrow_grey.png -------------------------------------------------------------------------------- /images/ic_home_baby.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_home_baby.png -------------------------------------------------------------------------------- /images/ic_home_habit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_home_habit.png -------------------------------------------------------------------------------- /images/ic_home_sleep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_home_sleep.png -------------------------------------------------------------------------------- /images/ic_home_sport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_home_sport.png -------------------------------------------------------------------------------- /images/ic_home_step.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_home_step.png -------------------------------------------------------------------------------- /images/ic_me_address.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_me_address.png -------------------------------------------------------------------------------- /images/ic_me_order.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_me_order.png -------------------------------------------------------------------------------- /images/ic_me_ticket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_me_ticket.png -------------------------------------------------------------------------------- /fonts/Montserrat-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/fonts/Montserrat-Bold.otf -------------------------------------------------------------------------------- /images/ic_boohee_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_boohee_logo.png -------------------------------------------------------------------------------- /images/ic_home_calorie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_home_calorie.png -------------------------------------------------------------------------------- /images/ic_home_weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_home_weight.png -------------------------------------------------------------------------------- /images/ic_message_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_message_grey.png -------------------------------------------------------------------------------- /images/ic_search_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_search_grey.png -------------------------------------------------------------------------------- /images/ic_search_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_search_white.png -------------------------------------------------------------------------------- /android/minic_applicaion.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/android/minic_applicaion.jks -------------------------------------------------------------------------------- /images/ic_dietician_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_dietician_logo.png -------------------------------------------------------------------------------- /images/ic_home_dietician.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_home_dietician.png -------------------------------------------------------------------------------- /images/ic_home_food_plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_home_food_plan.png -------------------------------------------------------------------------------- /images/ic_message_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_message_white.png -------------------------------------------------------------------------------- /images/ic_settings_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_settings_white.png -------------------------------------------------------------------------------- /images/ic_shop_cart_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_shop_cart_white.png -------------------------------------------------------------------------------- /images/ic_tab_bar_me_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_tab_bar_me_grey.png -------------------------------------------------------------------------------- /images/ic_home_menstruation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_home_menstruation.png -------------------------------------------------------------------------------- /images/ic_home_tabbar_plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_home_tabbar_plus.png -------------------------------------------------------------------------------- /images/ic_me_shopping_cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_me_shopping_cart.png -------------------------------------------------------------------------------- /images/ic_tab_bar_home_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_tab_bar_home_grey.png -------------------------------------------------------------------------------- /images/ic_tab_bar_me_green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_tab_bar_me_green.png -------------------------------------------------------------------------------- /images/ic_tab_bar_shop_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_tab_bar_shop_grey.png -------------------------------------------------------------------------------- /images/ic_arrow_light_yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_arrow_light_yellow.png -------------------------------------------------------------------------------- /images/ic_home_circumference.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_home_circumference.png -------------------------------------------------------------------------------- /images/ic_tab_bar_home_green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_tab_bar_home_green.png -------------------------------------------------------------------------------- /images/ic_tab_bar_partner_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_tab_bar_partner_grey.png -------------------------------------------------------------------------------- /images/ic_tab_bar_shop_green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_tab_bar_shop_green.png -------------------------------------------------------------------------------- /images/ic_tab_bar_partner_green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_tab_bar_partner_green.png -------------------------------------------------------------------------------- /images/ic_home_default_wallpaper.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/images/ic_home_default_wallpaper.webp -------------------------------------------------------------------------------- /lib/app/route/application.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:fluro/fluro.dart'; 3 | 4 | class Application { 5 | static Router router; 6 | } 7 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_1024.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_20@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_20@2x-1.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_29@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_29@2x-1.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_40@2x-1.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon_83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenyy0708/BooheeFlutter/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:auto_size/auto_size.dart'; 2 | import 'package:boohee_flutter/views/route_component.dart'; 3 | 4 | void main() { 5 | runAutoSizeApp(RouteComponent(), width: 375, height: 667); 6 | } 7 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | #Flutter Wrapper 2 | -keep class io.flutter.app.** { *; } 3 | -keep class io.flutter.plugin.** { *; } 4 | -keep class io.flutter.util.** { *; } 5 | -keep class io.flutter.view.** { *; } 6 | -keep class io.flutter.** { *; } 7 | -keep class io.flutter.plugins.** { *; } -------------------------------------------------------------------------------- /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-4.10.2-all.zip 7 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /lib/utils/toast_utils.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:toast/toast.dart'; 3 | 4 | class ToastUtils { 5 | static void showToast(BuildContext context, String msg, 6 | {int duration, int gravity}) { 7 | Toast.show(msg, context, duration: duration, gravity: gravity); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.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: 7a4c33425ddd78c54aba07d86f3f9a4a0051769b 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /lib/common/colors.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | Color mainColor = const Color(0xFF31D1AD); 4 | Color color373D52 = const Color(0xFF373D52); 5 | Color colorA8ACBC = const Color(0xFFA8ACBC); 6 | Color colorFF6C65 = const Color(0xFFFF6C65); 7 | Color color00CDA2 = const Color(0xFF00CDA2); 8 | Color colorEEEFF3 = const Color(0xFFEEEFF3); 9 | Color color0EB794 = const Color(0xFF0EB794); 10 | Color colorFEBB07 = const Color(0xFFFEBB07); 11 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/boohee/one/boohee_flutter/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.boohee.one.boohee_flutter 2 | 3 | import android.os.Bundle 4 | 5 | import io.flutter.app.FlutterActivity 6 | import io.flutter.plugins.GeneratedPluginRegistrant 7 | 8 | class MainActivity: FlutterActivity() { 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | GeneratedPluginRegistrant.registerWith(this) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /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: [UIApplicationLaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /lib/utils/utils.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/cupertino.dart'; 4 | 5 | class Utils { 6 | static String getImgPath(String name, {String format: 'png'}) { 7 | return 'images/$name.$format'; 8 | } 9 | 10 | static Color nameToColor(String name) { 11 | // assert(name.length > 1); 12 | final int hash = name.hashCode & 0xffff; 13 | final double hue = (360.0 * hash / (1 << 15)) % 360.0; 14 | return HSVColor.fromAHSV(1.0, hue, 0.4, 0.90).toColor(); 15 | } 16 | } -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /lib/widget/top_bottom_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:boohee_flutter/res/styles.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class TopBottom extends StatelessWidget { 5 | final Widget top; 6 | final Widget bottom; 7 | final double margin; 8 | 9 | TopBottom({ 10 | this.top, 11 | this.bottom, 12 | this.margin, 13 | }); 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return Column( 18 | children: [ 19 | top, 20 | SizeBoxFactory.getVerticalSizeBox(margin), 21 | bottom 22 | ], 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /assets/json/user/login_user.json: -------------------------------------------------------------------------------- 1 | { 2 | "user": { 3 | "user_key": "3ad64cc4-ed8e-45b2-9a8a-125577b3e71e", 4 | "user_name": "薄荷测试账号", 5 | "email": null, 6 | "cellphone": "18370622030", 7 | "cellphone_state": true, 8 | "user_type": 0, 9 | "created_at": "2019-02-28T00:10:09.000+08:00", 10 | "nick_name": null, 11 | "gender": null, 12 | "birthday": null, 13 | "height": null, 14 | "avatar_url": "https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3607875829,3212684153&fm=26&gp=0.jpg", 15 | "at_coin_balance": 0 16 | }, 17 | "token": "hAw338p5x4xsGxK6hqHCN8zb8xMrpW8n" 18 | } -------------------------------------------------------------------------------- /lib/common/view_factory.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ViewFactory { 4 | // 创建通用的CardView 5 | static Card createCard( 6 | Widget child, 7 | EdgeInsetsGeometry margin, 8 | double height, { 9 | double elevation: 1, 10 | double radius: 12, 11 | }) { 12 | return Card( 13 | shape: // 圆角 14 | RoundedRectangleBorder(borderRadius: BorderRadius.circular(radius)), 15 | margin: margin, 16 | elevation: elevation, 17 | child: Container( 18 | width: double.infinity, 19 | height: height, 20 | child: child, 21 | ), 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/utils/repository_utils.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:math'; 3 | 4 | import 'package:flutter/services.dart'; 5 | 6 | class Repository { 7 | static Future loadAsset(String fileName, 8 | {String fileDir: 'common'}) async { 9 | return await rootBundle.loadString('assets/json/$fileDir/$fileName.json'); 10 | } 11 | 12 | static Map toMap(String json) { 13 | return jsonDecode(json); 14 | } 15 | 16 | /// 获取json集合中随机一个数据 17 | static Map toMapForList(String json) { 18 | List mLists = jsonDecode(json); 19 | return mLists[Random().nextInt(mLists.length)]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /lib/utils/account_utils.dart: -------------------------------------------------------------------------------- 1 | import 'package:boohee_flutter/common/constant.dart'; 2 | import 'package:boohee_flutter/model/login_user.dart'; 3 | import 'package:flustars/flustars.dart'; 4 | 5 | class AccountUtils { 6 | static User mUser; 7 | 8 | static bool isLogin() { 9 | String token = SpUtil.getString(Constant.token, defValue: ""); 10 | return token.isNotEmpty; 11 | } 12 | 13 | static void saveUser(LoginUser user) { 14 | SpUtil.putObject(Constant.login_user, user); 15 | } 16 | 17 | static User getUser() { 18 | if (mUser == null) { 19 | mUser = 20 | SpUtil.getObj(Constant.login_user, (v) => LoginUser.fromJson(v)).user; 21 | } 22 | return mUser; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/model/splash_ad.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'splash_ad.g.dart'; 4 | 5 | 6 | @JsonSerializable() 7 | class SplashAd extends Object { 8 | 9 | @JsonKey(name: 'id') 10 | int id; 11 | 12 | @JsonKey(name: 'start_up_url') 13 | String startUpUrl; 14 | 15 | @JsonKey(name: 'is_ad') 16 | bool isAd; 17 | 18 | @JsonKey(name: 'text') 19 | String text; 20 | 21 | @JsonKey(name: 'link') 22 | String link; 23 | 24 | SplashAd(this.id,this.startUpUrl,this.isAd,this.text,this.link,); 25 | 26 | factory SplashAd.fromJson(Map srcJson) => _$SplashAdFromJson(srcJson); 27 | 28 | Map toJson() => _$SplashAdToJson(this); 29 | 30 | } 31 | 32 | 33 | -------------------------------------------------------------------------------- /assets/json/common/splash_ad.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 236, 4 | "start_up_url": "http://up.boohee.cn/house/u/shop/ad_page/0812/jrw.jpg", 5 | "is_ad": true, 6 | "text": "低脂鸡胸肉丸新上市!自营满200返200", 7 | "link": "https://one.boohee.com/store/pages/august_week3?page_from=launch_screen", 8 | "pop_ads": [] 9 | }, 10 | { 11 | "id": 237, 12 | "start_up_url": "http://up.boohee.cn/house/u/shop/ad_page/0812/cc.jpg", 13 | "is_ad": true, 14 | "text": "5/7日体重突击,另返100元代金券", 15 | "link": "https://one.boohee.com/store/pages/august_week3?page_from=launch_screen", 16 | "pop_ads": [] 17 | }, 18 | { 19 | "id": 3, 20 | "start_up_url": "http://up.boohee.cn/house/u/one/screen/summer_kp.jpg", 21 | "is_ad": false, 22 | "text": "", 23 | "link": "", 24 | "pop_ads": [] 25 | } 26 | ] -------------------------------------------------------------------------------- /lib/model/splash_ad.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'splash_ad.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | SplashAd _$SplashAdFromJson(Map json) { 10 | return SplashAd( 11 | json['id'] as int, 12 | json['start_up_url'] as String, 13 | json['is_ad'] as bool, 14 | json['text'] as String, 15 | json['link'] as String, 16 | ); 17 | } 18 | 19 | Map _$SplashAdToJson(SplashAd instance) => { 20 | 'id': instance.id, 21 | 'start_up_url': instance.startUpUrl, 22 | 'is_ad': instance.isAd, 23 | 'text': instance.text, 24 | 'link': instance.link, 25 | }; 26 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | -------------------------------------------------------------------------------- /lib/widget/card_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | /// 全局Card,统一Card样式便于全局修改 5 | class CardView extends StatelessWidget { 6 | final EdgeInsetsGeometry margin; 7 | final Widget child; 8 | final double elevation; 9 | final double radius; 10 | final Function onPressed; 11 | 12 | CardView( 13 | {Key key, 14 | this.margin, 15 | this.child, 16 | this.onPressed, 17 | this.elevation: 1, 18 | this.radius: 12}) 19 | : super(key: key); 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return Card( 24 | shape: // 圆角 25 | RoundedRectangleBorder(borderRadius: BorderRadius.circular(radius)), 26 | margin: margin, 27 | elevation: elevation, 28 | child: InkWell( 29 | onTap: onPressed, 30 | child: child, 31 | ), 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/views/route_component.dart: -------------------------------------------------------------------------------- 1 | import 'package:boohee_flutter/app/route/application.dart'; 2 | import 'package:boohee_flutter/app/route/routes.dart'; 3 | import 'package:fluro/fluro.dart'; 4 | import 'package:flutter/cupertino.dart'; 5 | import 'package:flutter/material.dart'; 6 | 7 | import '../splash_page.dart'; 8 | 9 | class RouteComponent extends StatefulWidget { 10 | @override 11 | _RouteComponentState createState() => _RouteComponentState(); 12 | } 13 | 14 | class _RouteComponentState extends State { 15 | _RouteComponentState() { 16 | final router = new Router(); 17 | Routes.configureRoutes(router); 18 | Application.router = router; 19 | } 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return MaterialApp( 24 | theme: ThemeData( 25 | primarySwatch: Colors.blue, scaffoldBackgroundColor: Colors.white), 26 | home: SplashPage(), 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/utils/base64_utils.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:crypto/crypto.dart'; 4 | 5 | class Base64 { 6 | static const String HMAC_SHA1 = "HmacSHA1"; 7 | 8 | /* 9 | * Base64加密 10 | */ 11 | static String encodeBase64(String data) { 12 | var content = utf8.encode(data); 13 | var digest = base64Encode(content); 14 | return digest; 15 | } 16 | 17 | /* 18 | * Base64加密 19 | */ 20 | static String encodeBase64ForBytes(List data) { 21 | var digest = base64Encode(data); 22 | return digest; 23 | } 24 | 25 | /* 26 | * Base64解密 27 | */ 28 | static String decodeBase64(String data) { 29 | return String.fromCharCodes(base64Decode(data)); 30 | } 31 | 32 | /* 33 | * HMAC加密 34 | */ 35 | static String encryptHMAC(String data, String key) { 36 | var _key = utf8.encode(key); 37 | var bytes = utf8.encode(data); 38 | 39 | var hmacSha256 = new Hmac(sha1, _key); // HMAC-SHA256 40 | var digest = hmacSha256.convert(bytes); 41 | String content = encodeBase64ForBytes(digest.bytes); 42 | return content; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/model/mine_cards.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'mine_cards.g.dart'; 4 | 5 | 6 | @JsonSerializable() 7 | class MineCards extends Object { 8 | 9 | @JsonKey(name: 'success') 10 | bool success; 11 | 12 | @JsonKey(name: 'msg') 13 | String msg; 14 | 15 | @JsonKey(name: 'data') 16 | List data; 17 | 18 | MineCards(this.success,this.msg,this.data,); 19 | 20 | factory MineCards.fromJson(Map srcJson) => _$MineCardsFromJson(srcJson); 21 | 22 | Map toJson() => _$MineCardsToJson(this); 23 | 24 | } 25 | 26 | 27 | @JsonSerializable() 28 | class Data extends Object { 29 | 30 | @JsonKey(name: 'id') 31 | int id; 32 | 33 | @JsonKey(name: 'name') 34 | String name; 35 | 36 | @JsonKey(name: 'icon_url') 37 | String iconUrl; 38 | 39 | @JsonKey(name: 'url') 40 | String url; 41 | 42 | Data(this.id,this.name,this.iconUrl,this.url,); 43 | 44 | factory Data.fromJson(Map srcJson) => _$DataFromJson(srcJson); 45 | 46 | Map toJson() => _$DataToJson(this); 47 | 48 | } 49 | 50 | 51 | -------------------------------------------------------------------------------- /lib/model/home_tools.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'home_tools.g.dart'; 4 | 5 | 6 | @JsonSerializable() 7 | class HomeTools extends Object { 8 | 9 | @JsonKey(name: 'success') 10 | bool success; 11 | 12 | @JsonKey(name: 'msg') 13 | String msg; 14 | 15 | @JsonKey(name: 'data') 16 | List data; 17 | 18 | HomeTools(this.success,this.msg,this.data,); 19 | 20 | factory HomeTools.fromJson(Map srcJson) => _$HomeToolsFromJson(srcJson); 21 | 22 | Map toJson() => _$HomeToolsToJson(this); 23 | 24 | } 25 | 26 | 27 | @JsonSerializable() 28 | class Data extends Object { 29 | 30 | @JsonKey(name: 'id') 31 | int id; 32 | 33 | @JsonKey(name: 'name') 34 | String name; 35 | 36 | @JsonKey(name: 'code') 37 | String code; 38 | 39 | @JsonKey(name: 'visible') 40 | bool visible; 41 | 42 | @JsonKey(name: 'editable') 43 | bool editable; 44 | 45 | Data(this.id,this.name,this.code,this.visible,this.editable,); 46 | 47 | factory Data.fromJson(Map srcJson) => _$DataFromJson(srcJson); 48 | 49 | Map toJson() => _$DataToJson(this); 50 | 51 | } 52 | 53 | 54 | -------------------------------------------------------------------------------- /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:boohee_flutter/views/route_component.dart'; 9 | import 'package:flutter/material.dart'; 10 | import 'package:flutter_test/flutter_test.dart'; 11 | 12 | void main() { 13 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 14 | // Build our app and trigger a frame. 15 | await tester.pumpWidget(RouteComponent()); 16 | 17 | // Verify that our counter starts at 0. 18 | expect(find.text('0'), findsOneWidget); 19 | expect(find.text('1'), findsNothing); 20 | 21 | // Tap the '+' icon and trigger a frame. 22 | await tester.tap(find.byIcon(Icons.add)); 23 | await tester.pump(); 24 | 25 | // Verify that our counter has incremented. 26 | expect(find.text('0'), findsNothing); 27 | expect(find.text('1'), findsOneWidget); 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /lib/common/constant.dart: -------------------------------------------------------------------------------- 1 | class Constant { 2 | static const String login_user = "login_user"; 3 | static const String token = "token"; 4 | static const String user_key = "user_key"; 5 | static const String y_mo_d_v2 = "yyyy/MM/dd"; 6 | } 7 | 8 | class HomeCard { 9 | // 减肥环和健康习惯 10 | static const String HEALTH_WEIGHT = "减肥环和健康习惯"; 11 | 12 | // 饮食&运动记录 13 | static const String DIET_SPORT_RECORD = "diet_exercise_record"; 14 | 15 | // 体重记录 16 | static const String WEIGHT_RECORD = "weight_record"; 17 | 18 | // 智慧营养师 19 | static const String WISDOM = "wisdom"; 20 | 21 | // 健康习惯 22 | static const String HEALTH_HABITS = "health_habits"; 23 | 24 | // 步数统计 25 | static const String STEPS_RECORD = "steps_record"; 26 | 27 | // 生理期记录 28 | static const String PERIODS_RECORD = "periods_record"; 29 | 30 | // 睡眠记录 31 | static const String SLEEP_RECORD = "sleep_record"; 32 | 33 | // 宝宝计划 34 | static const String BABY = "baby"; 35 | 36 | // 饮食计划 37 | static const String DIET_PLAN = "diet_plan"; 38 | 39 | // 运动训练 40 | static const String EXERCISE = "exercise"; 41 | 42 | // 围度记录 43 | static const String MEASURE_RECORD = "measure_record"; 44 | 45 | // 底部可定制TAB 46 | static const String SMART_CARD = "SMART_CARD"; 47 | } 48 | -------------------------------------------------------------------------------- /lib/model/mine_cards.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'mine_cards.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | MineCards _$MineCardsFromJson(Map json) { 10 | return MineCards( 11 | json['success'] as bool, 12 | json['msg'] as String, 13 | (json['data'] as List) 14 | ?.map( 15 | (e) => e == null ? null : Data.fromJson(e as Map)) 16 | ?.toList(), 17 | ); 18 | } 19 | 20 | Map _$MineCardsToJson(MineCards instance) => { 21 | 'success': instance.success, 22 | 'msg': instance.msg, 23 | 'data': instance.data, 24 | }; 25 | 26 | Data _$DataFromJson(Map json) { 27 | return Data( 28 | json['id'] as int, 29 | json['name'] as String, 30 | json['icon_url'] as String, 31 | json['url'] as String, 32 | ); 33 | } 34 | 35 | Map _$DataToJson(Data instance) => { 36 | 'id': instance.id, 37 | 'name': instance.name, 38 | 'icon_url': instance.iconUrl, 39 | 'url': instance.url, 40 | }; 41 | -------------------------------------------------------------------------------- /lib/model/home_wall_paper.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'home_wall_paper.g.dart'; 4 | 5 | 6 | @JsonSerializable() 7 | class HomeWallPaper extends Object { 8 | 9 | @JsonKey(name: 'welcome_img') 10 | Welcome_img welcomeImg; 11 | 12 | HomeWallPaper(this.welcomeImg,); 13 | 14 | factory HomeWallPaper.fromJson(Map srcJson) => _$HomeWallPaperFromJson(srcJson); 15 | 16 | Map toJson() => _$HomeWallPaperToJson(this); 17 | 18 | } 19 | 20 | 21 | @JsonSerializable() 22 | class Welcome_img extends Object { 23 | 24 | @JsonKey(name: 'hello_text') 25 | String helloText; 26 | 27 | @JsonKey(name: 'back_img') 28 | String backImg; 29 | 30 | @JsonKey(name: 'back_img_small') 31 | String backImgSmall; 32 | 33 | @JsonKey(name: 'back_img_x') 34 | String backImgX; 35 | 36 | @JsonKey(name: 'video_url') 37 | String videoUrl; 38 | 39 | @JsonKey(name: 'link') 40 | String link; 41 | 42 | @JsonKey(name: 'date') 43 | String date; 44 | 45 | Welcome_img(this.helloText,this.backImg,this.backImgSmall,this.backImgX,this.videoUrl,this.link,this.date,); 46 | 47 | factory Welcome_img.fromJson(Map srcJson) => _$Welcome_imgFromJson(srcJson); 48 | 49 | Map toJson() => _$Welcome_imgToJson(this); 50 | 51 | } 52 | 53 | 54 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.2.71' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.2.1' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | 13 | subprojects { 14 | project.configurations.all { 15 | resolutionStrategy.eachDependency { details -> 16 | if (details.requested.group == 'com.android.support' 17 | && !details.requested.name.contains('multidex') ) { 18 | details.useVersion "28.0.0" 19 | } 20 | 21 | if (details.requested.group == 'androidx.core' 22 | && !details.requested.name.contains('androidx') ) { 23 | details.useVersion "1.0.0" 24 | } 25 | } 26 | } 27 | } 28 | } 29 | 30 | allprojects { 31 | repositories { 32 | google() 33 | jcenter() 34 | } 35 | } 36 | 37 | rootProject.buildDir = '../build' 38 | subprojects { 39 | project.buildDir = "${rootProject.buildDir}/${project.name}" 40 | } 41 | subprojects { 42 | project.evaluationDependsOn(':app') 43 | } 44 | 45 | task clean(type: Delete) { 46 | delete rootProject.buildDir 47 | } 48 | -------------------------------------------------------------------------------- /lib/model/home_tools.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'home_tools.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | HomeTools _$HomeToolsFromJson(Map json) { 10 | return HomeTools( 11 | json['success'] as bool, 12 | json['msg'] as String, 13 | (json['data'] as List) 14 | ?.map( 15 | (e) => e == null ? null : Data.fromJson(e as Map)) 16 | ?.toList(), 17 | ); 18 | } 19 | 20 | Map _$HomeToolsToJson(HomeTools instance) => { 21 | 'success': instance.success, 22 | 'msg': instance.msg, 23 | 'data': instance.data, 24 | }; 25 | 26 | Data _$DataFromJson(Map json) { 27 | return Data( 28 | json['id'] as int, 29 | json['name'] as String, 30 | json['code'] as String, 31 | json['visible'] as bool, 32 | json['editable'] as bool, 33 | ); 34 | } 35 | 36 | Map _$DataToJson(Data instance) => { 37 | 'id': instance.id, 38 | 'name': instance.name, 39 | 'code': instance.code, 40 | 'visible': instance.visible, 41 | 'editable': instance.editable, 42 | }; 43 | -------------------------------------------------------------------------------- /lib/widget/round_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:boohee_flutter/common/colors.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | /// 通用的圆角button按钮 5 | class RoundButton extends StatelessWidget { 6 | final Color backgroundColor; 7 | final Text buttonText; 8 | final Function onPressed; 9 | final String text; 10 | final EdgeInsetsGeometry padding; 11 | final double radius; 12 | 13 | RoundButton( 14 | {this.backgroundColor, 15 | this.buttonText, 16 | this.onPressed, 17 | this.padding, 18 | this.radius: 20, 19 | this.text}); 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return ButtonTheme( 24 | materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, 25 | padding: EdgeInsets.all(0), 26 | height: 1, 27 | minWidth: 1, 28 | child: FlatButton( 29 | padding: 30 | padding ?? EdgeInsets.only(left: 7, right: 7, top: 4, bottom: 4), 31 | shape: new RoundedRectangleBorder( 32 | borderRadius: new BorderRadius.circular(radius)), 33 | color: this.backgroundColor ?? color00CDA2, 34 | child: buttonText ?? 35 | Text( 36 | text, 37 | style: TextStyle(fontSize: 10, color: Colors.white), 38 | ), 39 | onPressed: onPressed ?? () {}, 40 | ), 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/app/route/route_handlers.dart: -------------------------------------------------------------------------------- 1 | /* 2 | * fluro 3 | * Created by Yakka 4 | * https://theyakka.com 5 | * 6 | * Copyright (c) 2019 Yakka, LLC. All rights reserved. 7 | * See LICENSE for distribution and usage details. 8 | */ 9 | import 'package:boohee_flutter/views/common/browser_page.dart'; 10 | import 'package:boohee_flutter/views/common/wallpaper_page.dart'; 11 | import 'package:boohee_flutter/views/login/login_page.dart'; 12 | import 'package:boohee_flutter/views/main_page.dart'; 13 | import 'package:fluro/fluro.dart'; 14 | import 'package:flutter/material.dart'; 15 | 16 | var rootHandler = new Handler( 17 | handlerFunc: (BuildContext context, Map> params) { 18 | return new MainPage(); 19 | }); 20 | 21 | var loginHandler = new Handler( 22 | handlerFunc: (BuildContext context, Map> params) { 23 | return new LoginPage(); 24 | }); 25 | 26 | var webViewHandler = new Handler( 27 | handlerFunc: (BuildContext context, Map> params) { 28 | String param = params["web_url"]?.first; 29 | return new BrowserPage( 30 | webViewUrl: param, 31 | ); 32 | }); 33 | 34 | var wallPaperHandler = new Handler( 35 | handlerFunc: (BuildContext context, Map> params) { 36 | String param = params["image_url"]?.first; 37 | return new WallPaperPage( 38 | wallPaperImageUrl: param, 39 | ); 40 | }); 41 | -------------------------------------------------------------------------------- /lib/model/login_user.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'login_user.g.dart'; 4 | 5 | 6 | @JsonSerializable() 7 | class LoginUser extends Object { 8 | 9 | @JsonKey(name: 'user') 10 | User user; 11 | 12 | @JsonKey(name: 'token') 13 | String token; 14 | 15 | LoginUser(this.user,this.token,); 16 | 17 | factory LoginUser.fromJson(Map srcJson) => _$LoginUserFromJson(srcJson); 18 | 19 | Map toJson() => _$LoginUserToJson(this); 20 | 21 | } 22 | 23 | 24 | @JsonSerializable() 25 | class User extends Object { 26 | 27 | @JsonKey(name: 'user_key') 28 | String userKey; 29 | 30 | @JsonKey(name: 'user_name') 31 | String userName; 32 | 33 | @JsonKey(name: 'cellphone') 34 | String cellphone; 35 | 36 | @JsonKey(name: 'cellphone_state') 37 | bool cellphoneState; 38 | 39 | @JsonKey(name: 'user_type') 40 | int userType; 41 | 42 | @JsonKey(name: 'created_at') 43 | String createdAt; 44 | 45 | @JsonKey(name: 'avatar_url') 46 | String avatarUrl; 47 | 48 | @JsonKey(name: 'at_coin_balance') 49 | int atCoinBalance; 50 | 51 | User(this.userKey,this.userName,this.cellphone,this.cellphoneState,this.userType,this.createdAt,this.avatarUrl,this.atCoinBalance,); 52 | 53 | factory User.fromJson(Map srcJson) => _$UserFromJson(srcJson); 54 | 55 | Map toJson() => _$UserToJson(this); 56 | 57 | } 58 | 59 | 60 | -------------------------------------------------------------------------------- /lib/model/home_wall_paper.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'home_wall_paper.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | HomeWallPaper _$HomeWallPaperFromJson(Map json) { 10 | return HomeWallPaper( 11 | json['welcome_img'] == null 12 | ? null 13 | : Welcome_img.fromJson(json['welcome_img'] as Map), 14 | ); 15 | } 16 | 17 | Map _$HomeWallPaperToJson(HomeWallPaper instance) => 18 | { 19 | 'welcome_img': instance.welcomeImg, 20 | }; 21 | 22 | Welcome_img _$Welcome_imgFromJson(Map json) { 23 | return Welcome_img( 24 | json['hello_text'] as String, 25 | json['back_img'] as String, 26 | json['back_img_small'] as String, 27 | json['back_img_x'] as String, 28 | json['video_url'] as String, 29 | json['link'] as String, 30 | json['date'] as String, 31 | ); 32 | } 33 | 34 | Map _$Welcome_imgToJson(Welcome_img instance) => 35 | { 36 | 'hello_text': instance.helloText, 37 | 'back_img': instance.backImg, 38 | 'back_img_small': instance.backImgSmall, 39 | 'back_img_x': instance.backImgX, 40 | 'video_url': instance.videoUrl, 41 | 'link': instance.link, 42 | 'date': instance.date, 43 | }; 44 | -------------------------------------------------------------------------------- /lib/app/route/routes.dart: -------------------------------------------------------------------------------- 1 | /* 2 | * fluro 3 | * Created by Yakka 4 | * https://theyakka.com 5 | * 6 | * Copyright (c) 2019 Yakka, LLC. All rights reserved. 7 | * See LICENSE for distribution and usage details. 8 | */ 9 | import 'package:fluro/fluro.dart'; 10 | import 'package:flutter/cupertino.dart'; 11 | 12 | import './route_handlers.dart'; 13 | 14 | class Routes { 15 | /// 首页 16 | static String root = "/home"; 17 | 18 | /// 登陆 19 | static String login = "/login"; 20 | 21 | /// WebView 22 | static String webView = "/browserweb"; 23 | 24 | /// 壁纸 25 | static String wallPaper = "/wallPaper"; 26 | 27 | static void configureRoutes(Router router) { 28 | router.define(root, handler: rootHandler); 29 | router.define(login, handler: loginHandler); 30 | router.define(webView, handler: webViewHandler); 31 | router.define(wallPaper, handler: wallPaperHandler); 32 | } 33 | 34 | /// 从顶部弹出动画 35 | static RouteTransitionsBuilder transitionTopToBottom() { 36 | return (BuildContext context, Animation animation, 37 | Animation secondaryAnimation, Widget child) { 38 | /// x,y代表是的相对自己x轴移动一倍的自己 y轴移动2倍的自己 39 | const Offset begin = const Offset(0.0, -1.0); 40 | const Offset end = const Offset(0.0, 0.0); 41 | 42 | /// 相对自己移动的动画 43 | return SlideTransition( 44 | position: Tween( 45 | begin: begin, 46 | end: end, 47 | ).animate(animation), 48 | child: child, 49 | ); 50 | }; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/model/login_user.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'login_user.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | LoginUser _$LoginUserFromJson(Map json) { 10 | return LoginUser( 11 | json['user'] == null 12 | ? null 13 | : User.fromJson(json['user'] as Map), 14 | json['token'] as String, 15 | ); 16 | } 17 | 18 | Map _$LoginUserToJson(LoginUser instance) => { 19 | 'user': instance.user, 20 | 'token': instance.token, 21 | }; 22 | 23 | User _$UserFromJson(Map json) { 24 | return User( 25 | json['user_key'] as String, 26 | json['user_name'] as String, 27 | json['cellphone'] as String, 28 | json['cellphone_state'] as bool, 29 | json['user_type'] as int, 30 | json['created_at'] as String, 31 | json['avatar_url'] as String, 32 | json['at_coin_balance'] as int, 33 | ); 34 | } 35 | 36 | Map _$UserToJson(User instance) => { 37 | 'user_key': instance.userKey, 38 | 'user_name': instance.userName, 39 | 'cellphone': instance.cellphone, 40 | 'cellphone_state': instance.cellphoneState, 41 | 'user_type': instance.userType, 42 | 'created_at': instance.createdAt, 43 | 'avatar_url': instance.avatarUrl, 44 | 'at_coin_balance': instance.atCoinBalance, 45 | }; 46 | -------------------------------------------------------------------------------- /assets/json/me/mine_cards.json: -------------------------------------------------------------------------------- 1 | { 2 | "success": true, 3 | "msg": "", 4 | "data": [ 5 | { 6 | "id": 7, 7 | "name": "健康报告", 8 | "icon_url": "https://up.boohee.cn/house/u/mycard/report.png", 9 | "url": "boohee://new_health_report/mine_health_report" 10 | }, 11 | { 12 | "id": 1, 13 | "name": "NICE服务", 14 | "icon_url": "https://up.boohee.cn/house/u/mycard/NICE.png", 15 | "url": "https://nice.boohee.cn/api/v1/contracts.html" 16 | }, 17 | { 18 | "id": 3, 19 | "name": "智能设备", 20 | "icon_url": "https://up.boohee.cn/house/u/mycard/facility.png", 21 | "url": "boohee://new_hardware_activity" 22 | }, 23 | { 24 | "id": 5, 25 | "name": "我的收藏", 26 | "icon_url": "https://up.boohee.cn/house/u/mycard/mycollection.png", 27 | "url": "boohee://new_my_collection" 28 | }, 29 | { 30 | "id": 6, 31 | "name": "我的食物", 32 | "icon_url": "https://up.boohee.cn/house/u/mycard/myfood.png", 33 | "url": "boohee://new_my_food" 34 | }, 35 | { 36 | "id": 2, 37 | "name": "挑战赛", 38 | "icon_url": "https://up.boohee.cn/house/u/mycard/challenge.png", 39 | "url": "boohee://new_challenge" 40 | }, 41 | { 42 | "id": 4, 43 | "name": "打卡群", 44 | "icon_url": "https://up.boohee.cn/house/u/mycard/group.png", 45 | "url": "boohee://new_clock_in_group" 46 | }, 47 | { 48 | "id": 8, 49 | "name": "兑换", 50 | "icon_url": "https://up.boohee.cn/house/u/mycard/exchange.png", 51 | "url": "https://truck.boohee.com/wisdom/exchange" 52 | } 53 | ] 54 | } -------------------------------------------------------------------------------- /lib/utils/browser_url.dart: -------------------------------------------------------------------------------- 1 | import 'package:boohee_flutter/common/constant.dart'; 2 | import 'package:flustars/flustars.dart'; 3 | 4 | class BrowserUrlManager { 5 | static const String URL_BASE = "https://pixiu.boohee.com/"; 6 | 7 | // static const String URL_BASE = "https://pixiu.iboohee.cn/"; 8 | 9 | /// 智慧营养师首页 10 | static const String URL_PAY_SMART_ANALYSIS = URL_BASE + "recipe-detail?date="; 11 | 12 | /// 饮食运动记录h5 13 | static const String URL_CALORY = "https://calory.boohee.com/"; 14 | 15 | static String getSmartAnalysisUrl() { 16 | return URL_PAY_SMART_ANALYSIS + 17 | DateUtil.formatDate(DateTime.now(), format: Constant.y_mo_d_v2); 18 | } 19 | 20 | static Future handleUrl(String url) async { 21 | await SpUtil.getInstance(); 22 | if (url.isEmpty) { 23 | return null; 24 | } 25 | url = appendBaseParams(url); 26 | url = appendToken(url); 27 | return url; 28 | } 29 | 30 | /// 为所有url添加基本参数 31 | static String appendBaseParams(String url) { 32 | if (url.contains("?")) { 33 | url += "&app_device=Android"; 34 | } else { 35 | url += "?app_device=Android"; 36 | } 37 | url += "&channel=" + "boohee"; 38 | url += "&app_key=" + "one"; 39 | return url; 40 | } 41 | 42 | /// 来自薄荷的url会加上token 43 | static String appendToken(String url) { 44 | if (url.contains("boohee.com") || 45 | url.contains("boohee.cn") || 46 | url.contains("iboohee.cn")) { 47 | if (url.contains("?")) { 48 | url += "&token="; 49 | } else { 50 | url += "?token="; 51 | } 52 | url += SpUtil.getString(Constant.token, defValue: ""); 53 | } 54 | return url; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 薄荷APP Flutter 2 | 3 | 4 | ### [Flutter构建首页解析](http://note.youdao.com/noteshare?id=461c33405d38b4877291cfa08f59c48e) 5 | 6 | 7 | ### [下载地址](https://fir.im/nf8x) 8 | 9 | 10 |

11 | Sample 12 |

13 | 启动页 14 |

15 |

16 | 17 |

18 | Sample 19 |

20 | 首页 21 |

22 |

23 | 24 |

25 | Sample 26 |

27 | 首页推上 28 |

29 |

30 | 31 | 32 |

33 | Sample 34 |

35 | 伙伴 36 |

37 |

38 | 39 | 40 |

41 | Sample 42 |

43 | 商店 44 |

45 |

46 | 47 | 48 |

49 | Sample 50 |

51 | 我的 52 |

53 |

54 | 55 | -------------------------------------------------------------------------------- /lib/widget/tool_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:boohee_flutter/common/colors.dart'; 2 | import 'package:boohee_flutter/res/styles.dart'; 3 | import 'package:boohee_flutter/utils/utils.dart'; 4 | import 'package:flustars/flustars.dart'; 5 | import 'package:flutter/material.dart'; 6 | 7 | /// 通用的顶部标题栏 8 | class Toolbar extends StatelessWidget implements PreferredSizeWidget { 9 | final String text; 10 | final Function onTabRightOne; 11 | 12 | Toolbar({this.text, this.onTabRightOne}); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return Container( 17 | color: color00CDA2, 18 | padding: EdgeInsets.only( 19 | left: 17, 20 | right: 17, 21 | top: ScreenUtil.getStatusBarH(context) + 17, 22 | bottom: 17), 23 | child: Row( 24 | children: [ 25 | Expanded( 26 | child: Container( 27 | margin: EdgeInsets.only(top: 11, bottom: 11), 28 | child: Text(text ?? "", 29 | style: TextStyle(fontSize: 14, color: Colors.white)), 30 | )), 31 | PaddingStyles.getPadding(14), 32 | InkWell( 33 | child: Image.asset( 34 | Utils.getImgPath("ic_settings_white"), 35 | width: 24, 36 | height: 24, 37 | ), 38 | onTap: onTabRightOne ?? () {}, 39 | ), 40 | PaddingStyles.getPadding(14), 41 | Image.asset( 42 | Utils.getImgPath("ic_message_white"), 43 | width: 24, 44 | height: 24, 45 | ) 46 | ], 47 | ), 48 | ); 49 | } 50 | 51 | @override 52 | Size get preferredSize => Size.fromHeight(200); 53 | } 54 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /assets/json/home/home_health_tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "success": true, 3 | "msg": "", 4 | "data": [ 5 | { 6 | "id": 1, 7 | "name": "饮食&运动记录", 8 | "code": "diet_exercise_record", 9 | "visible": true, 10 | "editable": true 11 | }, 12 | { 13 | "id": 3, 14 | "name": "饮食计划", 15 | "code": "wisdom", 16 | "visible": true, 17 | "editable": true 18 | }, 19 | { 20 | "id": 2, 21 | "name": "体重记录", 22 | "code": "weight_record", 23 | "visible": true, 24 | "editable": true 25 | }, 26 | { 27 | "id": 4, 28 | "name": "健康习惯", 29 | "code": "health_habits", 30 | "visible": true, 31 | "editable": true 32 | }, 33 | { 34 | "id": 5, 35 | "name": "运动训练", 36 | "code": "exercise", 37 | "visible": true, 38 | "editable": true 39 | }, 40 | { 41 | "id": 6, 42 | "name": "围度记录", 43 | "code": "measure_record", 44 | "visible": true, 45 | "editable": true 46 | }, 47 | { 48 | "id": 7, 49 | "name": "经期记录", 50 | "code": "periods_record", 51 | "visible": true, 52 | "editable": true 53 | }, 54 | { 55 | "id": 9, 56 | "name": "步数记录", 57 | "code": "steps_record", 58 | "visible": true, 59 | "editable": true 60 | }, 61 | { 62 | "id": 10, 63 | "name": "睡眠记录", 64 | "code": "sleep_record", 65 | "visible": true, 66 | "editable": true 67 | }, 68 | { 69 | "id": 11, 70 | "name": "宝宝记录", 71 | "code": "baby", 72 | "visible": true, 73 | "editable": true 74 | } 75 | ], 76 | "extra": { 77 | "wisdom": { 78 | "bought": true, 79 | "show": true, 80 | "name": "饮食计划" 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # Visual Studio Code related 19 | .vscode/ 20 | 21 | # Flutter/Dart/Pub related 22 | **/doc/api/ 23 | .dart_tool/ 24 | .flutter-plugins 25 | .flutter-plugins-dependencies 26 | .packages 27 | .pub-cache/ 28 | .pub/ 29 | /build/ 30 | 31 | # Android related 32 | **/android/**/gradle-wrapper.jar 33 | **/android/.gradle 34 | **/android/captures/ 35 | **/android/gradlew 36 | **/android/gradlew.bat 37 | **/android/local.properties 38 | **/android/**/GeneratedPluginRegistrant.java 39 | 40 | # iOS/XCode related 41 | **/ios/**/*.mode1v3 42 | **/ios/**/*.mode2v3 43 | **/ios/**/*.moved-aside 44 | **/ios/**/*.pbxuser 45 | **/ios/**/*.perspectivev3 46 | **/ios/**/*sync/ 47 | **/ios/**/.sconsign.dblite 48 | **/ios/**/.tags* 49 | **/ios/**/.vagrant/ 50 | **/ios/**/DerivedData/ 51 | **/ios/**/Icon? 52 | **/ios/**/Pods/ 53 | **/ios/**/.symlinks/ 54 | **/ios/**/profile 55 | **/ios/**/xcuserdata 56 | **/ios/.generated/ 57 | **/ios/Flutter/App.framework 58 | **/ios/Flutter/Flutter.framework 59 | **/ios/Flutter/Generated.xcconfig 60 | **/ios/Flutter/app.flx 61 | **/ios/Flutter/app.zip 62 | **/ios/Flutter/flutter_assets/ 63 | **/ios/ServiceDefinitions.json 64 | **/ios/Runner/GeneratedPluginRegistrant.* 65 | 66 | # Exceptions to above rules. 67 | !**/ios/**/default.mode1v3 68 | !**/ios/**/default.mode2v3 69 | !**/ios/**/default.pbxuser 70 | !**/ios/**/default.perspectivev3 71 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 72 | ios/Podfile 73 | ios/Podfile.lock 74 | ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist 75 | ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist 76 | 77 | 78 | -------------------------------------------------------------------------------- /lib/widget/home_common_card.dart: -------------------------------------------------------------------------------- 1 | import 'package:boohee_flutter/res/styles.dart'; 2 | import 'package:boohee_flutter/utils/utils.dart'; 3 | import 'package:flutter/cupertino.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | /// 首页通用卡片样式 7 | class CommonCard extends StatelessWidget { 8 | final String iconUrl; 9 | final String title; 10 | final Widget subWidget; 11 | final Function onPressed; 12 | 13 | CommonCard({ 14 | this.iconUrl, 15 | this.title, 16 | this.subWidget, 17 | this.onPressed, 18 | }); 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | return InkWell( 23 | onTap: onPressed, 24 | child: Container( 25 | margin: EdgeInsets.only(top: 19, bottom: 19), 26 | padding: EdgeInsets.only(left: 15, right: 15), 27 | child: Row( 28 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 29 | children: [ 30 | Row( 31 | children: [ 32 | Image.asset( 33 | Utils.getImgPath(iconUrl), 34 | height: 18, 35 | width: 18, 36 | ), 37 | PaddingStyles.getPadding(6), 38 | Text( 39 | title, 40 | style: TextStyles.get14TextBold_373D52(), 41 | ) 42 | ], 43 | ), 44 | Row( 45 | children: [ 46 | subWidget == null ? Text("") : subWidget, 47 | Image.asset( 48 | Utils.getImgPath( 49 | "ic_arrow_grey", 50 | ), 51 | height: 18, 52 | width: 18, 53 | ) 54 | ], 55 | ) 56 | ], 57 | ), 58 | ), 59 | ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/views/common/wallpaper_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:boohee_flutter/app/route/fluro_navigator.dart'; 2 | import 'package:boohee_flutter/utils/base64_utils.dart'; 3 | import 'package:extended_image/extended_image.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | /// 壁纸 7 | class WallPaperPage extends StatefulWidget { 8 | final String wallPaperImageUrl; 9 | 10 | WallPaperPage({this.wallPaperImageUrl}); 11 | 12 | @override 13 | _WallPaperPageState createState() => _WallPaperPageState(wallPaperImageUrl); 14 | } 15 | 16 | class _WallPaperPageState extends State { 17 | String wallPaperImageUrl; 18 | 19 | _WallPaperPageState(String wallPaperImageUrl) { 20 | this.wallPaperImageUrl = 21 | Base64.decodeBase64(wallPaperImageUrl.replaceAll("Chen*boohee", "/")); 22 | } 23 | 24 | double _top; 25 | 26 | @override 27 | Widget build(BuildContext context) { 28 | return Scaffold( 29 | body: Container( 30 | color: Colors.black, 31 | height: double.infinity, 32 | width: double.infinity, 33 | child: GestureDetector( 34 | child: ExtendedImage.network( 35 | wallPaperImageUrl, 36 | cache: true, 37 | fit: BoxFit.cover, 38 | ), 39 | //垂直方向拖动事件 40 | onVerticalDragUpdate: (DragUpdateDetails details) { 41 | _top += details.delta.dy; 42 | }, 43 | onVerticalDragDown: (DragDownDetails details) { 44 | _top = 0; 45 | }, 46 | onVerticalDragEnd: (DragEndDetails details) { 47 | if (details.velocity.pixelsPerSecond.dy < 0 && _top <= -150) { 48 | // 向上滑 49 | NavigatorUtils.goBack(context); 50 | } 51 | // 重置滑动值 52 | _top = 0; 53 | }, 54 | ), 55 | ), 56 | ); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | io.flutter.embedded_views_preview 6 | 7 | NSAppTransportSecurity 8 | 9 | NSAllowsArbitraryLoads 10 | 11 | 12 | CFBundleDevelopmentRegion 13 | en 14 | CFBundleExecutable 15 | $(EXECUTABLE_NAME) 16 | CFBundleIdentifier 17 | $(PRODUCT_BUNDLE_IDENTIFIER) 18 | CFBundleInfoDictionaryVersion 19 | 6.0 20 | CFBundleName 21 | 薄荷flutter 22 | CFBundlePackageType 23 | APPL 24 | CFBundleShortVersionString 25 | $(FLUTTER_BUILD_NAME) 26 | CFBundleSignature 27 | ???? 28 | CFBundleVersion 29 | $(FLUTTER_BUILD_NUMBER) 30 | LSRequiresIPhoneOS 31 | 32 | UILaunchStoryboardName 33 | LaunchScreen 34 | UIMainStoryboardFile 35 | Main 36 | UISupportedInterfaceOrientations 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UISupportedInterfaceOrientations~ipad 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationPortraitUpsideDown 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | UIViewControllerBasedStatusBarAppearance 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 11 | 15 | 22 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /lib/res/styles.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:boohee_flutter/common/colors.dart'; 4 | import 'package:flutter/cupertino.dart'; 5 | import 'package:flutter/material.dart'; 6 | 7 | class TextStyles { 8 | static TextStyle get11Text_00CDA2() { 9 | return TextStyle(fontSize: 11, color: color00CDA2); 10 | } 11 | 12 | static TextStyle get11TextA8ACBC() { 13 | return TextStyle(fontSize: 11, color: colorA8ACBC); 14 | } 15 | 16 | static TextStyle get14TextBold_373D52() { 17 | return TextStyle( 18 | fontSize: 14, color: color373D52, fontWeight: FontWeight.w700); 19 | } 20 | 21 | static TextStyle get15Text_373D52() { 22 | return TextStyle(fontSize: 15, color: color373D52); 23 | } 24 | 25 | static TextStyle get15TextBold_373D52() { 26 | return TextStyle( 27 | fontSize: 15, color: color373D52, fontWeight: FontWeight.w700); 28 | } 29 | 30 | static TextStyle get14Text_373D52() { 31 | return TextStyle(fontSize: 14, color: color373D52); 32 | } 33 | 34 | static TextStyle get14TextA8ACBC() { 35 | return TextStyle(fontSize: 14, color: colorA8ACBC); 36 | } 37 | 38 | static TextStyle get12TextA8ACBC() { 39 | return TextStyle(fontSize: 12, color: colorA8ACBC); 40 | } 41 | 42 | static TextStyle get12Text_373D52() { 43 | return TextStyle(fontSize: 12, color: color373D52); 44 | } 45 | 46 | static TextStyle get10TextA8ACBC() { 47 | return TextStyle(fontSize: 10, color: colorA8ACBC); 48 | } 49 | 50 | static TextStyle get15White() { 51 | return TextStyle(fontSize: 15, color: Colors.white); 52 | } 53 | } 54 | 55 | class PaddingStyles { 56 | static Padding getPadding(double padding) { 57 | return Padding( 58 | padding: EdgeInsets.only( 59 | top: 0, left: padding / 2, right: padding / 2, bottom: 0)); 60 | } 61 | } 62 | 63 | class SizeBoxFactory { 64 | /// 垂直间距 65 | static SizedBox getVerticalSizeBox(double height) { 66 | return SizedBox(height: height); 67 | } 68 | 69 | /// 水平间隔 70 | static SizedBox getHorizontalSizeBox(double width) { 71 | return SizedBox(width: width); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /lib/app/route/fluro_navigator.dart: -------------------------------------------------------------------------------- 1 | import 'package:boohee_flutter/app/route/routes.dart'; 2 | import 'package:boohee_flutter/utils/base64_utils.dart'; 3 | import 'package:fluro/fluro.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | import 'application.dart'; 7 | 8 | /// fluro的路由跳转工具类 9 | class NavigatorUtils { 10 | static push(BuildContext context, String path, 11 | {bool replace = false, bool clearStack = false}) { 12 | Application.router.navigateTo(context, path, 13 | replace: replace, 14 | clearStack: clearStack, 15 | transition: TransitionType.native); 16 | } 17 | 18 | static pushResult( 19 | BuildContext context, String path, Function(Object) function, 20 | {bool replace = false, bool clearStack = false}) { 21 | Application.router 22 | .navigateTo(context, path, 23 | replace: replace, 24 | clearStack: clearStack, 25 | transition: TransitionType.native) 26 | .then((result) { 27 | // 页面返回result为null 28 | if (result == null) { 29 | return; 30 | } 31 | function(result); 32 | }).catchError((error) { 33 | print("$error"); 34 | }); 35 | } 36 | 37 | /// 返回 38 | static void goBack(BuildContext context) { 39 | Navigator.pop(context); 40 | } 41 | 42 | /// 通用的浏览器page 43 | static void goBrowserPage(BuildContext context, String url) { 44 | /// 这里使用替换/主要是路由不支持链接中带有/和&,否则会出错 45 | url = Base64.encodeBase64(url).replaceAll("/", "Chen*boohee"); 46 | Application.router.navigateTo(context, '${Routes.webView}?web_url=$url', 47 | replace: false, 48 | clearStack: false, 49 | transition: TransitionType.inFromBottom); 50 | } 51 | 52 | /// 壁纸 53 | static void goWallPaper(BuildContext context, String imageUrl) { 54 | /// 这里使用替换/主要是路由不支持链接中带有/和&,否则会出错 55 | imageUrl = Base64.encodeBase64(imageUrl).replaceAll("/", "Chen*boohee"); 56 | Application.router.navigateTo( 57 | context, '${Routes.wallPaper}?image_url=$imageUrl', 58 | replace: false, 59 | clearStack: false, 60 | transition: TransitionType.custom, 61 | transitionBuilder: Routes.transitionTopToBottom()); 62 | } 63 | 64 | /// 带参数返回 65 | static void goBackWithParams(BuildContext context, result) { 66 | Navigator.pop(context, result); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /lib/views/common/browser_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:boohee_flutter/common/colors.dart'; 4 | import 'package:boohee_flutter/utils/base64_utils.dart'; 5 | import 'package:flutter/cupertino.dart'; 6 | import 'package:flutter/material.dart'; 7 | import 'package:webview_flutter/webview_flutter.dart'; 8 | 9 | class BrowserPage extends StatefulWidget { 10 | final String webViewUrl; 11 | 12 | BrowserPage( {this.webViewUrl}); 13 | 14 | @override 15 | _BrowserPageState createState() => _BrowserPageState(webViewUrl); 16 | } 17 | 18 | class _BrowserPageState extends State { 19 | final Completer _controller = 20 | Completer(); 21 | String webViewUrl; 22 | String title; 23 | 24 | _BrowserPageState(String url) { 25 | // 解析路由传递的参数 26 | webViewUrl = Base64.decodeBase64(url.replaceAll("Chen*boohee", "/")); 27 | } 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | return WillPopScope( 32 | child: Scaffold( 33 | appBar: AppBar( 34 | backgroundColor: mainColor, 35 | title: Text(title ?? "薄荷"), 36 | ), 37 | body: WebView( 38 | initialUrl: webViewUrl, 39 | javascriptMode: JavascriptMode.unrestricted, 40 | onWebViewCreated: (WebViewController webViewController) { 41 | _controller.complete(webViewController); 42 | }, 43 | javascriptChannels: [ 44 | _toasterJavascriptChannel(context), 45 | ].toSet(), 46 | onPageFinished: (String url) {}, 47 | ), 48 | ), 49 | onWillPop: () async { 50 | var controller = await _controller.future; 51 | if (await controller.canGoBack()) { 52 | // 是否可以回退到上一步 53 | controller.goBack(); 54 | return false; 55 | } else { 56 | return true; 57 | } 58 | }); 59 | } 60 | 61 | JavascriptChannel _toasterJavascriptChannel(BuildContext context) { 62 | return JavascriptChannel( 63 | name: 'Toaster', 64 | onMessageReceived: (JavascriptMessage message) { 65 | Scaffold.of(context).showSnackBar( 66 | SnackBar(content: Text(message.message)), 67 | ); 68 | }); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /lib/views/discover_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:boohee_flutter/common/colors.dart'; 2 | import 'package:boohee_flutter/views/discover/discover_child_page.dart'; 3 | import 'package:boohee_flutter/widget/common_search_bar.dart'; 4 | import 'package:boohee_flutter/widget/md2_tab_indicator.dart'; 5 | import 'package:flutter/material.dart'; 6 | 7 | class DiscoverPage extends StatefulWidget { 8 | @override 9 | State createState() => _DiscoverPageState(); 10 | } 11 | 12 | class _DiscoverPageState extends State 13 | with SingleTickerProviderStateMixin { 14 | TabController _tabController; 15 | var mTabs = ["发现", "精选", "好友圈"]; 16 | 17 | @override 18 | void initState() { 19 | super.initState(); 20 | // 创建Controller 21 | _tabController = TabController(length: mTabs.length, vsync: this); 22 | _tabController.addListener(() { 23 | switch (_tabController.index) { 24 | } 25 | }); 26 | } 27 | 28 | @override 29 | Widget build(BuildContext context) { 30 | return Scaffold( 31 | appBar: SearchBar( 32 | text: "搜索动态、文章、话题、用户", 33 | ), 34 | body: DefaultTabController( 35 | length: mTabs.length, 36 | child: Column( 37 | crossAxisAlignment: CrossAxisAlignment.start, 38 | children: [ 39 | TabBar( 40 | controller: _tabController, 41 | labelStyle: 42 | TextStyle(fontSize: 17, fontWeight: FontWeight.w700), 43 | indicatorSize: TabBarIndicatorSize.label, 44 | labelColor: mainColor, 45 | unselectedLabelColor: color373D52, 46 | isScrollable: true, 47 | indicator: MD2Indicator( 48 | indicatorHeight: 5, 49 | indicatorColor: mainColor, 50 | indicatorSize: MD2IndicatorSize.tiny, 51 | ), 52 | tabs: mTabs.map((e) => Tab(text: e)).toList(), 53 | ), 54 | Expanded( 55 | child: TabBarView( 56 | controller: _tabController, 57 | children: [ 58 | DiscoverChildPage(), 59 | new Center(child: new Text('精选')), 60 | new Center(child: new Text('好友圈')), 61 | ], 62 | )) 63 | ], 64 | )), 65 | ); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /lib/widget/md2_tab_indicator.dart: -------------------------------------------------------------------------------- 1 | library md2_tab_indicator; 2 | 3 | import 'package:flutter/widgets.dart'; 4 | 5 | enum MD2IndicatorSize { 6 | tiny, 7 | normal, 8 | full, 9 | } 10 | 11 | /// 自定义indicator 12 | class MD2Indicator extends Decoration { 13 | final double indicatorHeight; 14 | final Color indicatorColor; 15 | final MD2IndicatorSize indicatorSize; 16 | 17 | const MD2Indicator( 18 | {@required this.indicatorHeight, 19 | @required this.indicatorColor, 20 | @required this.indicatorSize}); 21 | 22 | @override 23 | _MD2Painter createBoxPainter([VoidCallback onChanged]) { 24 | return new _MD2Painter(this, onChanged); 25 | } 26 | } 27 | 28 | class _MD2Painter extends BoxPainter { 29 | final MD2Indicator decoration; 30 | 31 | _MD2Painter(this.decoration, VoidCallback onChanged) 32 | : assert(decoration != null), 33 | super(onChanged); 34 | 35 | @override 36 | void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) { 37 | assert(configuration != null); 38 | assert(configuration.size != null); 39 | 40 | Rect rect; 41 | if (decoration.indicatorSize == MD2IndicatorSize.full) { 42 | rect = Offset(offset.dx, 43 | (configuration.size.height - decoration.indicatorHeight ?? 3)) & 44 | Size(configuration.size.width, decoration.indicatorHeight ?? 3); 45 | } else if (decoration.indicatorSize == MD2IndicatorSize.normal) { 46 | rect = Offset(offset.dx + 6, 47 | (configuration.size.height - decoration.indicatorHeight ?? 3)) & 48 | Size(configuration.size.width - 12, decoration.indicatorHeight ?? 3); 49 | } else if (decoration.indicatorSize == MD2IndicatorSize.tiny) { 50 | rect = Offset( 51 | offset.dx + configuration.size.width / 2 - 8, 52 | (configuration.size.height - decoration.indicatorHeight - 5 ?? 53 | 3)) & 54 | Size(12, decoration.indicatorHeight ?? 3); 55 | } 56 | 57 | final Paint paint = Paint(); 58 | paint.color = decoration.indicatorColor ?? Color(0xff1967d2); 59 | paint.style = PaintingStyle.fill; 60 | canvas.drawRRect( 61 | RRect.fromRectAndCorners(rect, 62 | topRight: Radius.circular(8), 63 | topLeft: Radius.circular(8), 64 | bottomRight: Radius.circular(8), 65 | bottomLeft: Radius.circular(8)), 66 | paint); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /lib/widget/header/home_wallpaper_header.dart: -------------------------------------------------------------------------------- 1 | import 'package:extended_image/extended_image.dart'; 2 | import 'package:flutter/cupertino.dart'; 3 | import 'package:flutter/src/painting/basic_types.dart'; 4 | import 'package:flutter/src/widgets/framework.dart'; 5 | import 'package:flutter_easyrefresh/easy_refresh.dart'; 6 | 7 | class WallPaperHeader extends Header { 8 | final Key key; 9 | final String wallPaperUrl; 10 | 11 | final LinkHeaderNotifier linkNotifier = LinkHeaderNotifier(); 12 | 13 | WallPaperHeader({ 14 | this.key, 15 | this.wallPaperUrl, 16 | bool enableHapticFeedback = false, 17 | }) : super( 18 | extent: 120, 19 | triggerDistance: 120, 20 | float: false, 21 | enableHapticFeedback: enableHapticFeedback, 22 | enableInfiniteRefresh: false, 23 | ); 24 | 25 | @override 26 | Widget contentBuilder( 27 | BuildContext context, 28 | RefreshMode refreshState, 29 | double pulledExtent, 30 | double refreshTriggerPullDistance, 31 | double refreshIndicatorExtent, 32 | AxisDirection axisDirection, 33 | bool float, 34 | Duration completeDuration, 35 | bool enableInfiniteRefresh, 36 | bool success, 37 | bool noMore) { 38 | linkNotifier.contentBuilder( 39 | context, 40 | refreshState, 41 | pulledExtent, 42 | refreshTriggerPullDistance, 43 | refreshIndicatorExtent, 44 | axisDirection, 45 | float, 46 | completeDuration, 47 | enableInfiniteRefresh, 48 | success, 49 | noMore); 50 | 51 | return WallPaperHeaderPage( 52 | wallPaperUrl: wallPaperUrl, 53 | linkNotifier: linkNotifier, 54 | key: key, 55 | ); 56 | } 57 | } 58 | 59 | class WallPaperHeaderPage extends StatefulWidget { 60 | final String wallPaperUrl; 61 | final LinkHeaderNotifier linkNotifier; 62 | 63 | WallPaperHeaderPage({this.wallPaperUrl, Key key, this.linkNotifier}) 64 | : super(key: key); 65 | 66 | @override 67 | _WallPaperHeaderPageState createState() => _WallPaperHeaderPageState(); 68 | } 69 | 70 | class _WallPaperHeaderPageState extends State { 71 | RefreshMode get _refreshState => widget.linkNotifier.refreshState; 72 | 73 | double get _pulledExtent => widget.linkNotifier.pulledExtent; 74 | 75 | double get _indicatorExtent => widget.linkNotifier.refreshIndicatorExtent; 76 | 77 | @override 78 | Widget build(BuildContext context) { 79 | return ExtendedImage.network( 80 | widget.wallPaperUrl, 81 | cache: true, 82 | fit: BoxFit.fitWidth, 83 | ); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /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 | def keystorePropertiesFile = rootProject.file("key.properties") 29 | def keystoreProperties = new Properties() 30 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 31 | 32 | android { 33 | compileSdkVersion 28 34 | 35 | sourceSets { 36 | main.java.srcDirs += 'src/main/kotlin' 37 | } 38 | 39 | lintOptions { 40 | disable 'InvalidPackage' 41 | } 42 | 43 | defaultConfig { 44 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 45 | applicationId "com.boohee.one.boohee_flutter" 46 | minSdkVersion 16 47 | targetSdkVersion 28 48 | versionCode flutterVersionCode.toInteger() 49 | versionName flutterVersionName 50 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 51 | } 52 | 53 | signingConfigs { 54 | release { 55 | keyAlias keystoreProperties['keyAlias'] 56 | keyPassword keystoreProperties['keyPassword'] 57 | storePassword keystoreProperties['storePassword'] 58 | // 适配不同os上需要配置不同的jks的路径 59 | storeFile file("../minic_applicaion.jks") 60 | } 61 | } 62 | buildTypes { 63 | release { 64 | signingConfig signingConfigs.release 65 | } 66 | } 67 | } 68 | 69 | flutter { 70 | source '../..' 71 | } 72 | 73 | dependencies { 74 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 75 | testImplementation 'junit:junit:4.12' 76 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 77 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 78 | } 79 | -------------------------------------------------------------------------------- /lib/model/discover/sub_discover.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'sub_discover.g.dart'; 4 | 5 | 6 | @JsonSerializable() 7 | class SubDiscover extends Object { 8 | 9 | @JsonKey(name: 'banners') 10 | List banners; 11 | 12 | @JsonKey(name: 'labels') 13 | List labels; 14 | 15 | @JsonKey(name: 'sections') 16 | List sections; 17 | 18 | SubDiscover(this.banners,this.labels,this.sections,); 19 | 20 | factory SubDiscover.fromJson(Map srcJson) => _$SubDiscoverFromJson(srcJson); 21 | 22 | Map toJson() => _$SubDiscoverToJson(this); 23 | 24 | } 25 | 26 | 27 | @JsonSerializable() 28 | class Banners extends Object { 29 | 30 | @JsonKey(name: 'id') 31 | int id; 32 | 33 | @JsonKey(name: 'title') 34 | String title; 35 | 36 | @JsonKey(name: 'link') 37 | String link; 38 | 39 | @JsonKey(name: 'pic_url') 40 | String picUrl; 41 | 42 | Banners(this.id,this.title,this.link,this.picUrl,); 43 | 44 | factory Banners.fromJson(Map srcJson) => _$BannersFromJson(srcJson); 45 | 46 | Map toJson() => _$BannersToJson(this); 47 | 48 | } 49 | 50 | 51 | @JsonSerializable() 52 | class Labels extends Object { 53 | 54 | @JsonKey(name: 'title') 55 | String title; 56 | 57 | @JsonKey(name: 'url') 58 | String url; 59 | 60 | @JsonKey(name: 'pic_url') 61 | String picUrl; 62 | 63 | Labels(this.title,this.url,this.picUrl,); 64 | 65 | factory Labels.fromJson(Map srcJson) => _$LabelsFromJson(srcJson); 66 | 67 | Map toJson() => _$LabelsToJson(this); 68 | 69 | } 70 | 71 | 72 | @JsonSerializable() 73 | class Sections extends Object { 74 | 75 | @JsonKey(name: 'name') 76 | String name; 77 | 78 | @JsonKey(name: 'sub_contents') 79 | List subContents; 80 | 81 | Sections(this.name,this.subContents,); 82 | 83 | factory Sections.fromJson(Map srcJson) => _$SectionsFromJson(srcJson); 84 | 85 | Map toJson() => _$SectionsToJson(this); 86 | 87 | } 88 | 89 | 90 | @JsonSerializable() 91 | class Sub_contents extends Object { 92 | 93 | @JsonKey(name: 'title') 94 | String title; 95 | 96 | @JsonKey(name: 'sub_title') 97 | String subTitle; 98 | 99 | @JsonKey(name: 'img_url') 100 | String imgUrl; 101 | 102 | @JsonKey(name: 'redirect_url') 103 | String redirectUrl; 104 | 105 | Sub_contents(this.title,this.subTitle,this.imgUrl,this.redirectUrl,); 106 | 107 | factory Sub_contents.fromJson(Map srcJson) => _$Sub_contentsFromJson(srcJson); 108 | 109 | Map toJson() => _$Sub_contentsToJson(this); 110 | 111 | } 112 | 113 | 114 | -------------------------------------------------------------------------------- /lib/model/ShopRecommendList.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'ShopRecommendList.g.dart'; 4 | 5 | 6 | @JsonSerializable() 7 | class ShopRecommendList extends Object { 8 | 9 | @JsonKey(name: 'id') 10 | int id; 11 | 12 | @JsonKey(name: 'name') 13 | String name; 14 | 15 | @JsonKey(name: 'description') 16 | String description; 17 | 18 | @JsonKey(name: 'sub_labels') 19 | List subLabels; 20 | 21 | @JsonKey(name: 'banner_showcases') 22 | List bannerShowcases; 23 | 24 | @JsonKey(name: 'goods') 25 | List goods; 26 | 27 | @JsonKey(name: 'page') 28 | int page; 29 | 30 | @JsonKey(name: 'total_pages') 31 | int totalPages; 32 | 33 | ShopRecommendList(this.id,this.name,this.description,this.subLabels,this.bannerShowcases,this.goods,this.page,this.totalPages,); 34 | 35 | factory ShopRecommendList.fromJson(Map srcJson) => _$ShopRecommendListFromJson(srcJson); 36 | 37 | Map toJson() => _$ShopRecommendListToJson(this); 38 | 39 | } 40 | 41 | 42 | @JsonSerializable() 43 | class Sub_labels extends Object { 44 | 45 | @JsonKey(name: 'id') 46 | int id; 47 | 48 | @JsonKey(name: 'name') 49 | String name; 50 | 51 | Sub_labels(this.id,this.name,); 52 | 53 | factory Sub_labels.fromJson(Map srcJson) => _$Sub_labelsFromJson(srcJson); 54 | 55 | Map toJson() => _$Sub_labelsToJson(this); 56 | 57 | } 58 | 59 | 60 | @JsonSerializable() 61 | class Goods extends Object { 62 | 63 | @JsonKey(name: 'id') 64 | int id; 65 | 66 | @JsonKey(name: 'title') 67 | String title; 68 | 69 | @JsonKey(name: 'total_quantity') 70 | int totalQuantity; 71 | 72 | @JsonKey(name: 'category_name') 73 | String categoryName; 74 | 75 | @JsonKey(name: 'thumb_photo_url') 76 | String thumbPhotoUrl; 77 | 78 | @JsonKey(name: 'big_photo_url') 79 | String bigPhotoUrl; 80 | 81 | @JsonKey(name: 'flag_url') 82 | String flagUrl; 83 | 84 | @JsonKey(name: 'flag_name') 85 | String flagName; 86 | 87 | @JsonKey(name: 'state') 88 | String state; 89 | 90 | @JsonKey(name: 'buy_url') 91 | String buyUrl; 92 | 93 | @JsonKey(name: 'has_video_thumb') 94 | bool hasVideoThumb; 95 | 96 | @JsonKey(name: 'base_price') 97 | int basePrice; 98 | 99 | @JsonKey(name: 'market_price') 100 | int marketPrice; 101 | 102 | Goods(this.id,this.title,this.totalQuantity,this.categoryName,this.thumbPhotoUrl,this.bigPhotoUrl,this.flagUrl,this.flagName,this.state,this.buyUrl,this.hasVideoThumb,this.basePrice,this.marketPrice,); 103 | 104 | factory Goods.fromJson(Map srcJson) => _$GoodsFromJson(srcJson); 105 | 106 | Map toJson() => _$GoodsToJson(this); 107 | 108 | } 109 | 110 | 111 | -------------------------------------------------------------------------------- /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@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "icon_29@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "icon_40@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "icon_40@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "icon_60@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "icon_60@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "20x20", 53 | "idiom" : "ipad", 54 | "filename" : "icon_20@1x.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "icon_20@2x-1.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "icon_29@1x.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "icon_29@2x-1.png", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "icon_40@1x.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "icon_40@2x-1.png", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "size" : "76x76", 89 | "idiom" : "ipad", 90 | "filename" : "icon_76@1x.png", 91 | "scale" : "1x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "icon_76@2x.png", 97 | "scale" : "2x" 98 | }, 99 | { 100 | "size" : "83.5x83.5", 101 | "idiom" : "ipad", 102 | "filename" : "icon_83.5@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "1024x1024", 107 | "idiom" : "ios-marketing", 108 | "filename" : "icon_1024.png", 109 | "scale" : "1x" 110 | } 111 | ], 112 | "info" : { 113 | "version" : 1, 114 | "author" : "xcode" 115 | } 116 | } -------------------------------------------------------------------------------- /lib/model/ShopRecommendList.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'ShopRecommendList.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | ShopRecommendList _$ShopRecommendListFromJson(Map json) { 10 | return ShopRecommendList( 11 | json['id'] as int, 12 | json['name'] as String, 13 | json['description'] as String, 14 | (json['sub_labels'] as List) 15 | ?.map((e) => 16 | e == null ? null : Sub_labels.fromJson(e as Map)) 17 | ?.toList(), 18 | json['banner_showcases'] as List, 19 | (json['goods'] as List) 20 | ?.map( 21 | (e) => e == null ? null : Goods.fromJson(e as Map)) 22 | ?.toList(), 23 | json['page'] as int, 24 | json['total_pages'] as int, 25 | ); 26 | } 27 | 28 | Map _$ShopRecommendListToJson(ShopRecommendList instance) => 29 | { 30 | 'id': instance.id, 31 | 'name': instance.name, 32 | 'description': instance.description, 33 | 'sub_labels': instance.subLabels, 34 | 'banner_showcases': instance.bannerShowcases, 35 | 'goods': instance.goods, 36 | 'page': instance.page, 37 | 'total_pages': instance.totalPages, 38 | }; 39 | 40 | Sub_labels _$Sub_labelsFromJson(Map json) { 41 | return Sub_labels( 42 | json['id'] as int, 43 | json['name'] as String, 44 | ); 45 | } 46 | 47 | Map _$Sub_labelsToJson(Sub_labels instance) => 48 | { 49 | 'id': instance.id, 50 | 'name': instance.name, 51 | }; 52 | 53 | Goods _$GoodsFromJson(Map json) { 54 | return Goods( 55 | json['id'] as int, 56 | json['title'] as String, 57 | json['total_quantity'] as int, 58 | json['category_name'] as String, 59 | json['thumb_photo_url'] as String, 60 | json['big_photo_url'] as String, 61 | json['flag_url'] as String, 62 | json['flag_name'] as String, 63 | json['state'] as String, 64 | json['buy_url'] as String, 65 | json['has_video_thumb'] as bool, 66 | json['base_price'] as int, 67 | json['market_price'] as int, 68 | ); 69 | } 70 | 71 | Map _$GoodsToJson(Goods instance) => { 72 | 'id': instance.id, 73 | 'title': instance.title, 74 | 'total_quantity': instance.totalQuantity, 75 | 'category_name': instance.categoryName, 76 | 'thumb_photo_url': instance.thumbPhotoUrl, 77 | 'big_photo_url': instance.bigPhotoUrl, 78 | 'flag_url': instance.flagUrl, 79 | 'flag_name': instance.flagName, 80 | 'state': instance.state, 81 | 'buy_url': instance.buyUrl, 82 | 'has_video_thumb': instance.hasVideoThumb, 83 | 'base_price': instance.basePrice, 84 | 'market_price': instance.marketPrice, 85 | }; 86 | -------------------------------------------------------------------------------- /assets/json/home/home_wallpaper.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "welcome_img": { 4 | "hello_text": "我的目标就在下个路口 现在要做的就是加点油门", 5 | "back_img": "http://up.boohee.cn/house/u/one/wallpaper/1664_big.jpg", 6 | "back_img_small": "http://up.boohee.cn/house/u/one/wallpaper/1664_small.jpg", 7 | "back_img_x": "http://up.boohee.cn/house/u/one/wallpaper/1664_x.jpg", 8 | "video_url": "", 9 | "link": "", 10 | "date": "2019-08-17" 11 | } 12 | }, 13 | { 14 | "welcome_img": { 15 | "hello_text": "我的目标就在下个路口 现在要做的就是加点油门", 16 | "back_img": "http://up.boohee.cn/house/u/one/wallpaper/1665_big.jpg", 17 | "back_img_small": "http://up.boohee.cn/house/u/one/wallpaper/1665_small.jpg", 18 | "back_img_x": "http://up.boohee.cn/house/u/one/wallpaper/1665_x.jpg", 19 | "video_url": "", 20 | "link": "", 21 | "date": "2019-08-17" 22 | } 23 | }, 24 | { 25 | "welcome_img": { 26 | "hello_text": "我的目标就在下个路口 现在要做的就是加点油门", 27 | "back_img": "http://up.boohee.cn/house/u/one/wallpaper/1666_big.jpg", 28 | "back_img_small": "http://up.boohee.cn/house/u/one/wallpaper/1666_small.jpg", 29 | "back_img_x": "http://up.boohee.cn/house/u/one/wallpaper/1666_x.jpg", 30 | "video_url": "", 31 | "link": "", 32 | "date": "2019-08-17" 33 | } 34 | }, 35 | { 36 | "welcome_img": { 37 | "hello_text": "我的目标就在下个路口 现在要做的就是加点油门", 38 | "back_img": "http://up.boohee.cn/house/u/one/wallpaper/1667_big.jpg", 39 | "back_img_small": "http://up.boohee.cn/house/u/one/wallpaper/1667_small.jpg", 40 | "back_img_x": "http://up.boohee.cn/house/u/one/wallpaper/1667_x.jpg", 41 | "video_url": "", 42 | "link": "", 43 | "date": "2019-08-17" 44 | } 45 | }, 46 | { 47 | "welcome_img": { 48 | "hello_text": "我的目标就在下个路口 现在要做的就是加点油门", 49 | "back_img": "http://up.boohee.cn/house/u/one/wallpaper/1668_big.jpg", 50 | "back_img_small": "http://up.boohee.cn/house/u/one/wallpaper/1668_small.jpg", 51 | "back_img_x": "http://up.boohee.cn/house/u/one/wallpaper/1668_x.jpg", 52 | "video_url": "", 53 | "link": "", 54 | "date": "2019-08-17" 55 | } 56 | }, 57 | { 58 | "welcome_img": { 59 | "hello_text": "我的目标就在下个路口 现在要做的就是加点油门", 60 | "back_img": "http://up.boohee.cn/house/u/one/wallpaper/1669_big.jpg", 61 | "back_img_small": "http://up.boohee.cn/house/u/one/wallpaper/1669_small.jpg", 62 | "back_img_x": "http://up.boohee.cn/house/u/one/wallpaper/1669_x.jpg", 63 | "video_url": "", 64 | "link": "", 65 | "date": "2019-08-17" 66 | } 67 | }, 68 | { 69 | "welcome_img": { 70 | "hello_text": "我的目标就在下个路口 现在要做的就是加点油门", 71 | "back_img": "http://up.boohee.cn/house/u/one/wallpaper/1671_big.jpg", 72 | "back_img_small": "http://up.boohee.cn/house/u/one/wallpaper/1671_small.jpg", 73 | "back_img_x": "http://up.boohee.cn/house/u/one/wallpaper/1671_x.jpg", 74 | "video_url": "", 75 | "link": "", 76 | "date": "2019-08-17" 77 | } 78 | } 79 | ] -------------------------------------------------------------------------------- /lib/model/discover/sub_discover.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'sub_discover.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | SubDiscover _$SubDiscoverFromJson(Map json) { 10 | return SubDiscover( 11 | (json['banners'] as List) 12 | ?.map((e) => 13 | e == null ? null : Banners.fromJson(e as Map)) 14 | ?.toList(), 15 | (json['labels'] as List) 16 | ?.map((e) => 17 | e == null ? null : Labels.fromJson(e as Map)) 18 | ?.toList(), 19 | (json['sections'] as List) 20 | ?.map((e) => 21 | e == null ? null : Sections.fromJson(e as Map)) 22 | ?.toList(), 23 | ); 24 | } 25 | 26 | Map _$SubDiscoverToJson(SubDiscover instance) => 27 | { 28 | 'banners': instance.banners, 29 | 'labels': instance.labels, 30 | 'sections': instance.sections, 31 | }; 32 | 33 | Banners _$BannersFromJson(Map json) { 34 | return Banners( 35 | json['id'] as int, 36 | json['title'] as String, 37 | json['link'] as String, 38 | json['pic_url'] as String, 39 | ); 40 | } 41 | 42 | Map _$BannersToJson(Banners instance) => { 43 | 'id': instance.id, 44 | 'title': instance.title, 45 | 'link': instance.link, 46 | 'pic_url': instance.picUrl, 47 | }; 48 | 49 | Labels _$LabelsFromJson(Map json) { 50 | return Labels( 51 | json['title'] as String, 52 | json['url'] as String, 53 | json['pic_url'] as String, 54 | ); 55 | } 56 | 57 | Map _$LabelsToJson(Labels instance) => { 58 | 'title': instance.title, 59 | 'url': instance.url, 60 | 'pic_url': instance.picUrl, 61 | }; 62 | 63 | Sections _$SectionsFromJson(Map json) { 64 | return Sections( 65 | json['name'] as String, 66 | (json['sub_contents'] as List) 67 | ?.map((e) => 68 | e == null ? null : Sub_contents.fromJson(e as Map)) 69 | ?.toList(), 70 | ); 71 | } 72 | 73 | Map _$SectionsToJson(Sections instance) => { 74 | 'name': instance.name, 75 | 'sub_contents': instance.subContents, 76 | }; 77 | 78 | Sub_contents _$Sub_contentsFromJson(Map json) { 79 | return Sub_contents( 80 | json['title'] as String, 81 | json['sub_title'] as String, 82 | json['img_url'] as String, 83 | json['redirect_url'] as String, 84 | ); 85 | } 86 | 87 | Map _$Sub_contentsToJson(Sub_contents instance) => 88 | { 89 | 'title': instance.title, 90 | 'sub_title': instance.subTitle, 91 | 'img_url': instance.imgUrl, 92 | 'redirect_url': instance.redirectUrl, 93 | }; 94 | -------------------------------------------------------------------------------- /lib/model/ShopBanner.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'ShopBanner.g.dart'; 4 | 5 | 6 | @JsonSerializable() 7 | class ShopBanner extends Object { 8 | 9 | @JsonKey(name: 'banner_showcases') 10 | List bannerShowcases; 11 | 12 | @JsonKey(name: 'shop_modules') 13 | List shopModules; 14 | 15 | @JsonKey(name: 'categories') 16 | List categories; 17 | 18 | ShopBanner(this.bannerShowcases,this.shopModules,this.categories,); 19 | 20 | factory ShopBanner.fromJson(Map srcJson) => _$ShopBannerFromJson(srcJson); 21 | 22 | Map toJson() => _$ShopBannerToJson(this); 23 | 24 | } 25 | 26 | 27 | @JsonSerializable() 28 | class Banner_showcases extends Object { 29 | 30 | @JsonKey(name: 'id') 31 | int id; 32 | 33 | @JsonKey(name: 'exhibit') 34 | String exhibit; 35 | 36 | @JsonKey(name: 'default_photo_url') 37 | String defaultPhotoUrl; 38 | 39 | @JsonKey(name: 'default_photo_height') 40 | int defaultPhotoHeight; 41 | 42 | @JsonKey(name: 'default_photo_width') 43 | int defaultPhotoWidth; 44 | 45 | @JsonKey(name: 'exhibit_type') 46 | String exhibitType; 47 | 48 | @JsonKey(name: 'page_title') 49 | String pageTitle; 50 | 51 | Banner_showcases(this.id,this.exhibit,this.defaultPhotoUrl,this.defaultPhotoHeight,this.defaultPhotoWidth,this.exhibitType,this.pageTitle,); 52 | 53 | factory Banner_showcases.fromJson(Map srcJson) => _$Banner_showcasesFromJson(srcJson); 54 | 55 | Map toJson() => _$Banner_showcasesToJson(this); 56 | 57 | } 58 | 59 | 60 | @JsonSerializable() 61 | class Shop_modules extends Object { 62 | 63 | @JsonKey(name: 'position') 64 | int position; 65 | 66 | @JsonKey(name: 'title') 67 | String title; 68 | 69 | @JsonKey(name: 'sub_title') 70 | String subTitle; 71 | 72 | @JsonKey(name: 'picture_url1') 73 | String pictureUrl1; 74 | 75 | @JsonKey(name: 'picture_url2') 76 | String pictureUrl2; 77 | 78 | @JsonKey(name: 'redirect_url') 79 | String redirectUrl; 80 | 81 | @JsonKey(name: 'display') 82 | bool display; 83 | 84 | @JsonKey(name: 'new_tag') 85 | String newTag; 86 | 87 | Shop_modules(this.position,this.title,this.subTitle,this.pictureUrl1,this.pictureUrl2,this.redirectUrl,this.display,this.newTag,); 88 | 89 | factory Shop_modules.fromJson(Map srcJson) => _$Shop_modulesFromJson(srcJson); 90 | 91 | Map toJson() => _$Shop_modulesToJson(this); 92 | 93 | } 94 | 95 | 96 | @JsonSerializable() 97 | class Categories extends Object { 98 | 99 | @JsonKey(name: 'id') 100 | int id; 101 | 102 | @JsonKey(name: 'name') 103 | String name; 104 | 105 | @JsonKey(name: 'description') 106 | String description; 107 | 108 | @JsonKey(name: 'icon_url') 109 | String iconUrl; 110 | 111 | Categories(this.id,this.name,this.description,this.iconUrl,); 112 | 113 | factory Categories.fromJson(Map srcJson) => _$CategoriesFromJson(srcJson); 114 | 115 | Map toJson() => _$CategoriesToJson(this); 116 | 117 | } 118 | 119 | 120 | -------------------------------------------------------------------------------- /lib/model/ShopBanner.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'ShopBanner.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | ShopBanner _$ShopBannerFromJson(Map json) { 10 | return ShopBanner( 11 | (json['banner_showcases'] as List) 12 | ?.map((e) => e == null 13 | ? null 14 | : Banner_showcases.fromJson(e as Map)) 15 | ?.toList(), 16 | (json['shop_modules'] as List) 17 | ?.map((e) => 18 | e == null ? null : Shop_modules.fromJson(e as Map)) 19 | ?.toList(), 20 | (json['categories'] as List) 21 | ?.map((e) => 22 | e == null ? null : Categories.fromJson(e as Map)) 23 | ?.toList(), 24 | ); 25 | } 26 | 27 | Map _$ShopBannerToJson(ShopBanner instance) => 28 | { 29 | 'banner_showcases': instance.bannerShowcases, 30 | 'shop_modules': instance.shopModules, 31 | 'categories': instance.categories, 32 | }; 33 | 34 | Banner_showcases _$Banner_showcasesFromJson(Map json) { 35 | return Banner_showcases( 36 | json['id'] as int, 37 | json['exhibit'] as String, 38 | json['default_photo_url'] as String, 39 | json['default_photo_height'] as int, 40 | json['default_photo_width'] as int, 41 | json['exhibit_type'] as String, 42 | json['page_title'] as String, 43 | ); 44 | } 45 | 46 | Map _$Banner_showcasesToJson(Banner_showcases instance) => 47 | { 48 | 'id': instance.id, 49 | 'exhibit': instance.exhibit, 50 | 'default_photo_url': instance.defaultPhotoUrl, 51 | 'default_photo_height': instance.defaultPhotoHeight, 52 | 'default_photo_width': instance.defaultPhotoWidth, 53 | 'exhibit_type': instance.exhibitType, 54 | 'page_title': instance.pageTitle, 55 | }; 56 | 57 | Shop_modules _$Shop_modulesFromJson(Map json) { 58 | return Shop_modules( 59 | json['position'] as int, 60 | json['title'] as String, 61 | json['sub_title'] as String, 62 | json['picture_url1'] as String, 63 | json['picture_url2'] as String, 64 | json['redirect_url'] as String, 65 | json['display'] as bool, 66 | json['new_tag'] as String, 67 | ); 68 | } 69 | 70 | Map _$Shop_modulesToJson(Shop_modules instance) => 71 | { 72 | 'position': instance.position, 73 | 'title': instance.title, 74 | 'sub_title': instance.subTitle, 75 | 'picture_url1': instance.pictureUrl1, 76 | 'picture_url2': instance.pictureUrl2, 77 | 'redirect_url': instance.redirectUrl, 78 | 'display': instance.display, 79 | 'new_tag': instance.newTag, 80 | }; 81 | 82 | Categories _$CategoriesFromJson(Map json) { 83 | return Categories( 84 | json['id'] as int, 85 | json['name'] as String, 86 | json['description'] as String, 87 | json['icon_url'] as String, 88 | ); 89 | } 90 | 91 | Map _$CategoriesToJson(Categories instance) => 92 | { 93 | 'id': instance.id, 94 | 'name': instance.name, 95 | 'description': instance.description, 96 | 'icon_url': instance.iconUrl, 97 | }; 98 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /lib/views/main_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:boohee_flutter/common/colors.dart'; 2 | import 'package:boohee_flutter/utils/toast_utils.dart'; 3 | import 'package:boohee_flutter/views/shop_pages/shop_page.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | import 'discover_page.dart'; 7 | import 'home_page.dart'; 8 | import 'mine_page.dart'; 9 | 10 | class MainPage extends StatefulWidget { 11 | @override 12 | State createState() => _MainPageState(); 13 | } 14 | 15 | class _MainPageState extends State 16 | with SingleTickerProviderStateMixin { 17 | DateTime _lastPressedAt; //上次点击时间 18 | 19 | int _selectedIndex = 0; 20 | List _list = List(); 21 | List _selectIcon = [ 22 | Image.asset( 23 | "images/ic_tab_bar_home_green.png", 24 | width: 22, 25 | height: 22, 26 | ), 27 | Image.asset( 28 | "images/ic_tab_bar_partner_green.png", 29 | width: 22, 30 | height: 22, 31 | ), 32 | Image.asset( 33 | "images/ic_home_tabbar_plus.png", 34 | width: 36, 35 | height: 36, 36 | ), 37 | Image.asset( 38 | "images/ic_tab_bar_shop_green.png", 39 | width: 22, 40 | height: 22, 41 | ), 42 | Image.asset( 43 | "images/ic_tab_bar_me_green.png", 44 | width: 22, 45 | height: 22, 46 | ), 47 | ]; 48 | List _unselectIcon = [ 49 | Image.asset( 50 | "images/ic_tab_bar_home_grey.png", 51 | width: 22, 52 | height: 22, 53 | ), 54 | Image.asset( 55 | "images/ic_tab_bar_partner_grey.png", 56 | width: 22, 57 | height: 22, 58 | ), 59 | Image.asset( 60 | "images/ic_home_tabbar_plus.png", 61 | width: 36, 62 | height: 36, 63 | ), 64 | Image.asset( 65 | "images/ic_tab_bar_shop_grey.png", 66 | width: 22, 67 | height: 22, 68 | ), 69 | Image.asset( 70 | "images/ic_tab_bar_me_grey.png", 71 | width: 22, 72 | height: 22, 73 | ), 74 | ]; 75 | static List tabData = [ 76 | "首页", 77 | "伙伴", 78 | "", 79 | "商店", 80 | "我", 81 | ]; 82 | List _myTabs = []; 83 | 84 | @override 85 | void initState() { 86 | super.initState(); 87 | for (int i = 0; i < tabData.length; i++) { 88 | // 初始化底部Tab 89 | _myTabs.add(BottomNavigationBarItem( 90 | icon: _unselectIcon[i], 91 | activeIcon: _selectIcon[i], 92 | title: Text( 93 | tabData[i], 94 | ), 95 | )); 96 | } 97 | _list 98 | ..add(HomePage()) 99 | ..add(DiscoverPage()) 100 | ..add(ShopPage()) 101 | ..add(MinePage()); 102 | } 103 | 104 | @override 105 | void dispose() { 106 | super.dispose(); 107 | } 108 | 109 | @override 110 | Widget build(BuildContext context) { 111 | return WillPopScope( 112 | child: Scaffold( 113 | body: IndexedStack( 114 | // --是因为页面只有4个,但是底部tab的index是5个导致tab索引混乱 115 | index: _selectedIndex > 2 ? _selectedIndex - 1 : _selectedIndex, 116 | children: _list, 117 | ), 118 | bottomNavigationBar: BottomNavigationBar( 119 | selectedFontSize: 10, 120 | unselectedFontSize: 10, 121 | backgroundColor: Colors.white, 122 | items: _myTabs, 123 | currentIndex: _selectedIndex, 124 | onTap: _onItemTapped, 125 | type: BottomNavigationBarType.fixed, 126 | fixedColor: mainColor, 127 | ), 128 | ), 129 | onWillPop: () async { 130 | if (_lastPressedAt == null || 131 | DateTime.now().difference(_lastPressedAt) > 132 | Duration(seconds: 2)) { 133 | //两次点击间隔超过1秒则重新计时 134 | _lastPressedAt = DateTime.now(); 135 | ToastUtils.showToast(context, "再按一次返回退出APP"); 136 | return false; 137 | } 138 | return true; 139 | }); 140 | } 141 | 142 | // 导航tab 点击回调 143 | void _onItemTapped(int index) { 144 | if (index == 2) { 145 | ToastUtils.showToast(context, "暂无"); 146 | return; 147 | } 148 | // 刷新widget 149 | setState(() { 150 | _selectedIndex = index; 151 | }); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /lib/widget/common_search_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:boohee_flutter/common/colors.dart'; 2 | import 'package:boohee_flutter/res/styles.dart'; 3 | import 'package:boohee_flutter/utils/utils.dart'; 4 | import 'package:flustars/flustars.dart'; 5 | import 'package:flutter/material.dart'; 6 | 7 | /// 通用的搜索头部Widget 8 | class SearchBar extends StatefulWidget implements PreferredSizeWidget { 9 | final Key key; 10 | final Function onPressed; 11 | final String text; 12 | final bool isShowCartIcon; 13 | final SearchBarController controller; 14 | 15 | SearchBar( 16 | {this.onPressed, 17 | this.controller, 18 | this.key, 19 | this.isShowCartIcon: false, 20 | @required this.text}) 21 | : super(key: key); 22 | 23 | @override 24 | SearchBarState createState() => SearchBarState(); 25 | 26 | @override 27 | Size get preferredSize => Size.fromHeight(200); 28 | } 29 | 30 | class SearchBarState extends State { 31 | SearchBarController _controller; 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | if (widget.controller == null) { 36 | _controller = new SearchBarController(); 37 | _controller.value.alpha = 255; 38 | _controller.value.searchBarBg = color0EB794; 39 | _controller.value.appbarTitleColor = Colors.white; 40 | _controller.value.appbarLeftIcon = "ic_search_white"; 41 | _controller.value.appbarRightIcon = "ic_message_white"; 42 | } else { 43 | _controller = widget.controller; 44 | } 45 | return Container( 46 | color: Color.fromARGB(_controller.value.alpha, 0, 205, 162), 47 | padding: EdgeInsets.only( 48 | left: 17, 49 | right: 17, 50 | top: ScreenUtil.getStatusBarH(context) + 17, 51 | bottom: 17), 52 | child: Row( 53 | children: [ 54 | Expanded( 55 | child: Container( 56 | child: DecoratedBox( 57 | decoration: BoxDecoration( 58 | color: _controller.value.searchBarBg, 59 | borderRadius: BorderRadius.circular(100), 60 | ), 61 | child: Padding( 62 | padding: EdgeInsets.only(top: 7, bottom: 7), 63 | child: Row( 64 | children: [ 65 | PaddingStyles.getPadding(14), 66 | Image.asset( 67 | Utils.getImgPath(_controller.value.appbarLeftIcon), 68 | width: 24, 69 | height: 24, 70 | ), 71 | PaddingStyles.getPadding(7), 72 | Text( 73 | widget.text, 74 | style: TextStyle( 75 | fontSize: 14, 76 | color: _controller.value.appbarTitleColor), 77 | ) 78 | ], 79 | ), 80 | ), 81 | ), 82 | )), 83 | Offstage( 84 | child: SizeBoxFactory.getHorizontalSizeBox(14), 85 | offstage: !widget.isShowCartIcon, 86 | ), 87 | Offstage( 88 | offstage: !widget.isShowCartIcon, 89 | child: Image.asset( 90 | Utils.getImgPath("ic_shop_cart_white"), 91 | width: 24, 92 | height: 24, 93 | ), 94 | ), 95 | SizeBoxFactory.getHorizontalSizeBox(14), 96 | Image.asset( 97 | Utils.getImgPath(_controller.value.appbarRightIcon), 98 | width: 24, 99 | height: 24, 100 | ) 101 | ], 102 | ), 103 | ); 104 | } 105 | } 106 | 107 | class SearchBarController extends ValueNotifier { 108 | int alpha; 109 | Color searchBarBg; 110 | Color appbarTitleColor; 111 | String appbarLeftIcon; 112 | String appbarRightIcon; 113 | 114 | SearchBarController({ 115 | this.alpha, 116 | this.searchBarBg, 117 | this.appbarTitleColor, 118 | this.appbarLeftIcon, 119 | this.appbarRightIcon, 120 | }) : super(new SearchBarAlphaValue( 121 | alpha: alpha, 122 | searchBarBg: searchBarBg, 123 | appbarTitleColor: appbarTitleColor, 124 | appbarLeftIcon: appbarLeftIcon, 125 | appbarRightIcon: appbarRightIcon)); 126 | } 127 | 128 | class SearchBarAlphaValue { 129 | int alpha; 130 | Color searchBarBg; 131 | 132 | Color appbarTitleColor; 133 | String appbarLeftIcon; 134 | String appbarRightIcon; 135 | 136 | SearchBarAlphaValue({ 137 | this.alpha, 138 | this.searchBarBg, 139 | this.appbarTitleColor, 140 | this.appbarLeftIcon, 141 | this.appbarRightIcon, 142 | }); 143 | } 144 | -------------------------------------------------------------------------------- /lib/views/login/login_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:boohee_flutter/app/route/fluro_navigator.dart'; 2 | import 'package:boohee_flutter/app/route/routes.dart'; 3 | import 'package:boohee_flutter/common/Colors.dart'; 4 | import 'package:boohee_flutter/common/constant.dart'; 5 | import 'package:boohee_flutter/model/login_user.dart'; 6 | import 'package:boohee_flutter/res/styles.dart'; 7 | import 'package:boohee_flutter/utils/account_utils.dart'; 8 | import 'package:boohee_flutter/utils/repository_utils.dart'; 9 | import 'package:boohee_flutter/utils/toast_utils.dart'; 10 | import 'package:boohee_flutter/utils/utils.dart'; 11 | import 'package:flustars/flustars.dart'; 12 | import 'package:flutter/cupertino.dart'; 13 | import 'package:flutter/material.dart'; 14 | 15 | class LoginPage extends StatefulWidget { 16 | @override 17 | _LoginPageState createState() => _LoginPageState(); 18 | } 19 | 20 | class _LoginPageState extends State { 21 | var leftRightPadding = 30.0; 22 | var topBottomPadding = 4.0; 23 | 24 | var _userPassController = new TextEditingController(); 25 | var _userNameController = new TextEditingController(); 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | return new Scaffold( 30 | backgroundColor: Colors.white, 31 | appBar: new AppBar( 32 | backgroundColor: mainColor, 33 | title: Text("账号登陆"), 34 | ), 35 | body: SingleChildScrollView( 36 | child: new Column( 37 | mainAxisSize: MainAxisSize.max, 38 | mainAxisAlignment: MainAxisAlignment.start, 39 | children: [ 40 | Padding( 41 | padding: EdgeInsets.only(top: 80), 42 | child: Row( 43 | mainAxisAlignment: MainAxisAlignment.center, 44 | children: [ 45 | Image.asset( 46 | Utils.getImgPath("ic_boohee_logo"), 47 | height: 35, 48 | width: 35, 49 | ), 50 | SizeBoxFactory.getHorizontalSizeBox(20), 51 | Text( 52 | "薄荷健康", 53 | style: TextStyle( 54 | color: color373D52, 55 | fontSize: 23, 56 | fontWeight: FontWeight.w600), 57 | ) 58 | ], 59 | ), 60 | ), 61 | new Padding( 62 | padding: new EdgeInsets.fromLTRB( 63 | leftRightPadding, 50.0, leftRightPadding, topBottomPadding), 64 | child: new TextField( 65 | style: new TextStyle(fontSize: 16.0, color: color373D52), 66 | controller: _userNameController, 67 | decoration: new InputDecoration( 68 | hintText: "用户名/手机号/邮箱", 69 | hintStyle: TextStyle(fontSize: 16, color: colorA8ACBC)), 70 | ), 71 | ), 72 | new Padding( 73 | padding: new EdgeInsets.fromLTRB( 74 | leftRightPadding, 30.0, leftRightPadding, topBottomPadding), 75 | child: new TextField( 76 | style: TextStyle(fontSize: 16.0, color: color373D52), 77 | controller: _userPassController, 78 | decoration: new InputDecoration( 79 | hintText: "密码", 80 | hintStyle: TextStyle(fontSize: 16, color: colorA8ACBC)), 81 | obscureText: true, 82 | ), 83 | ), 84 | new Container( 85 | width: 360.0, 86 | margin: new EdgeInsets.fromLTRB(10.0, 80, 10.0, 0.0), 87 | padding: new EdgeInsets.fromLTRB(leftRightPadding, 88 | topBottomPadding, leftRightPadding, topBottomPadding), 89 | child: new Card( 90 | color: mainColor, 91 | elevation: 6.0, 92 | child: new FlatButton( 93 | onPressed: () { 94 | login(); 95 | }, 96 | child: new Padding( 97 | padding: new EdgeInsets.all(10.0), 98 | child: new Text( 99 | '登录', 100 | style: new TextStyle( 101 | color: Colors.white, fontSize: 16.0), 102 | ), 103 | )), 104 | ), 105 | ) 106 | ], 107 | ), 108 | )); 109 | } 110 | 111 | void login() async { 112 | if (_userNameController.text.isEmpty || _userPassController.text.isEmpty) { 113 | ToastUtils.showToast(context, "用户名或密码不能为空"); 114 | return; 115 | } 116 | Repository.loadAsset("login_user", fileDir: "user").then((json) async { 117 | LoginUser loginUser = LoginUser.fromJson(Repository.toMap(json)); 118 | await SpUtil.getInstance(); 119 | AccountUtils.saveUser(loginUser); 120 | SpUtil.putString(Constant.token, loginUser.token); 121 | SpUtil.putString(Constant.user_key, loginUser.user.userKey); 122 | if (loginUser != null && loginUser.token.isNotEmpty) { 123 | // 登录成功,跳转首页 124 | NavigatorUtils.push(context, Routes.root, replace: true); 125 | } 126 | }); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: boohee_flutter 2 | description: A new Flutter application. 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 | cupertino_icons: ^0.1.2 24 | # 网络请求库 25 | dio: 2.1.7 26 | # bean对象 27 | json_annotation: ^3.0.0 28 | # 轮播图 29 | # banner: ^0.1.3 30 | banner_view: ^1.1.2 31 | # 刷新控件 32 | flutter_easyrefresh: ^2.0.4 33 | # 聚合工具类 34 | # flustars: ^0.2.6+1 35 | # 路由 36 | fluro: ^1.5.1 37 | # toast 38 | toast: ^0.1.5 39 | # 进度条 40 | percent_indicator: ^2.1.1+1 41 | # webview 42 | webview_flutter: ^0.3.14+1 43 | # flutter_webview_plugin: ^0.3.5 44 | # 折线图 45 | fl_chart: ^0.2.2 46 | # Image Cache 47 | extended_image: ^0.6.8 48 | flustars: ^0.2.6+1 49 | auto_size: 50 | git: 51 | url: git://github.com/flutterchina/auto_size.git 52 | 53 | dev_dependencies: 54 | flutter_test: 55 | sdk: flutter 56 | build_runner: ^1.7.0 57 | json_serializable: ^3.2.2 58 | # shared_preferences: '>=0.1.1 <3.0.0' 59 | synchronized: '>=0.1.0 <3.0.0' 60 | rxdart: ^0.22.2 61 | crypto: ^2.1.3 62 | 63 | # For information on the generic Dart part of this file, see the 64 | # following page: https://www.dartlang.org/tools/pub/pubspec 65 | 66 | # The following section is specific to Flutter. 67 | flutter: 68 | 69 | # The following line ensures that the Material Icons font is 70 | # included with your application, so that you can use the icons in 71 | # the material Icons class. 72 | uses-material-design: true 73 | 74 | assets: 75 | - assets/json/discover/discover_sub.json 76 | - assets/json/common/splash_ad.json 77 | - assets/json/home/home_health_tools.json 78 | - assets/json/home/home_wallpaper.json 79 | - assets/json/shop/shop_banner.json 80 | - assets/json/shop/shop_recommend_list.json 81 | - assets/json/me/mine_cards.json 82 | - assets/json/user/login_user.json 83 | - images/ic_tab_bar_home_grey.png 84 | - images/ic_tab_bar_me_grey.png 85 | - images/ic_tab_bar_partner_grey.png 86 | - images/ic_tab_bar_shop_grey.png 87 | - images/ic_tab_bar_home_green.png 88 | - images/ic_tab_bar_me_green.png 89 | - images/ic_tab_bar_partner_green.png 90 | - images/ic_tab_bar_shop_green.png 91 | - images/ic_boohee_logo.png 92 | - images/ic_home_calorie.png 93 | - images/ic_home_sleep.png 94 | - images/ic_home_sport.png 95 | - images/ic_home_step.png 96 | - images/ic_home_weight.png 97 | - images/ic_home_dietician.png 98 | - images/ic_arrow_grey.png 99 | - images/ic_home_habit.png 100 | - images/ic_home_circumference.png 101 | - images/ic_home_baby.png 102 | - images/ic_home_food_plan.png 103 | - images/ic_home_menstruation.png 104 | - images/ic_message_grey.png 105 | - images/ic_search_grey.png 106 | - images/ic_message_white.png 107 | - images/ic_search_white.png 108 | - images/ic_shop_cart_white.png 109 | - images/ic_settings_white.png 110 | - images/ic_me_address.png 111 | - images/ic_me_order.png 112 | - images/ic_me_shopping_cart.png 113 | - images/ic_me_ticket.png 114 | - images/ic_home_tabbar_plus.png 115 | - images/ic_arrow_light_yellow.png 116 | - images/ic_dietician_logo.png 117 | - images/ic_home_default_wallpaper.webp 118 | # To add assets to your application, add an assets section, like this: 119 | # assets: 120 | # - images/a_dot_burr.jpeg 121 | # - images/a_dot_ham.jpeg 122 | 123 | # An image asset can refer to one or more resolution-specific "variants", see 124 | # https://flutter.dev/assets-and-images/#resolution-aware. 125 | 126 | # For details regarding adding assets from package dependencies, see 127 | # https://flutter.dev/assets-and-images/#from-packages 128 | 129 | # To add custom fonts to your application, add a fonts section here, 130 | # in this "flutter" section. Each entry in this list should have a 131 | # "family" key with the font family name, and a "fonts" key with a 132 | # list giving the asset and other descriptors for the font. For 133 | # example: 134 | # fonts: 135 | # - family: Schyler 136 | # fonts: 137 | # - asset: fonts/Schyler-Regular.ttf 138 | # - asset: fonts/Schyler-Italic.ttf 139 | # style: italic 140 | # - family: Trajan Pro 141 | # fonts: 142 | # - asset: fonts/TrajanPro.ttf 143 | # - asset: fonts/TrajanPro_Bold.ttf 144 | # weight: 700 145 | # 146 | # For details regarding fonts from package dependencies, 147 | # see https://flutter.dev/custom-fonts/#from-packages 148 | 149 | fonts: 150 | - family: Montserrat 151 | fonts: 152 | - asset: fonts/Montserrat-Bold.otf 153 | -------------------------------------------------------------------------------- /lib/splash_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:boohee_flutter/res/styles.dart'; 2 | import 'package:boohee_flutter/utils/repository_utils.dart'; 3 | import 'package:boohee_flutter/utils/utils.dart'; 4 | import 'package:boohee_flutter/widget/round_button.dart'; 5 | import 'package:extended_image/extended_image.dart'; 6 | import 'package:fluro/fluro.dart'; 7 | import 'package:flustars/flustars.dart'; 8 | import 'package:flutter/cupertino.dart'; 9 | import 'package:flutter/material.dart'; 10 | 11 | import 'app/route/application.dart'; 12 | import 'app/route/fluro_navigator.dart'; 13 | import 'app/route/routes.dart'; 14 | import 'common/colors.dart'; 15 | import 'common/constant.dart'; 16 | import 'model/splash_ad.dart'; 17 | 18 | class SplashPage extends StatefulWidget { 19 | @override 20 | _SplashPageState createState() => _SplashPageState(); 21 | } 22 | 23 | class _SplashPageState extends State { 24 | _SplashPageState() { 25 | final router = new Router(); 26 | Routes.configureRoutes(router); 27 | Application.router = router; 28 | } 29 | 30 | bool isLogin = false; 31 | 32 | // 因为offstage属性为true是隐藏,false为显示,所以默认属性为true 33 | bool inVisible = true; 34 | SplashAd splashAd; 35 | TimerUtil _timerUtil; 36 | int countdownTime = 3 * 1000; 37 | int currentTime = 3; 38 | 39 | @override 40 | void initState() { 41 | super.initState(); 42 | _loadLoginStatus(); 43 | } 44 | 45 | @override 46 | Widget build(BuildContext context) { 47 | return MaterialApp( 48 | home: Scaffold( 49 | body: Container( 50 | height: double.infinity, 51 | child: Column( 52 | children: [ 53 | Expanded( 54 | child: Stack( 55 | alignment: Alignment.bottomCenter, 56 | children: [ 57 | ExtendedImage.network( 58 | splashAd == null ? "" : splashAd.startUpUrl, 59 | width: double.infinity, 60 | height: double.infinity, 61 | fit: BoxFit.cover, 62 | cache: true, 63 | enableLoadState: false, 64 | ), 65 | Offstage( 66 | offstage: inVisible, 67 | child: Container( 68 | height: 50, 69 | width: double.infinity, 70 | color: Colors.black38, 71 | child: Center( 72 | child: Text( 73 | splashAd == null ? "" : splashAd.text, 74 | style: TextStyle(color: Colors.white, fontSize: 15), 75 | ), 76 | ), 77 | ), 78 | ) 79 | ], 80 | )), 81 | Stack( 82 | alignment: Alignment.center, 83 | children: [ 84 | Container( 85 | height: 105, 86 | width: double.infinity, 87 | child: Row( 88 | mainAxisAlignment: MainAxisAlignment.center, 89 | children: [ 90 | Image.asset( 91 | Utils.getImgPath("ic_boohee_logo"), 92 | height: 35, 93 | width: 35, 94 | ), 95 | PaddingStyles.getPadding(10), 96 | Text( 97 | "薄荷健康", 98 | style: TextStyle( 99 | color: color373D52, 100 | fontSize: 18, 101 | fontWeight: FontWeight.w600), 102 | ) 103 | ], 104 | ), 105 | ), 106 | Padding( 107 | padding: EdgeInsets.only(right: 10), 108 | child: Align( 109 | alignment: Alignment.centerRight, 110 | child: Offstage( 111 | offstage: inVisible, 112 | child: RoundButton( 113 | padding: EdgeInsets.only( 114 | left: 5, right: 5, top: 2, bottom: 2), 115 | backgroundColor: Colors.black45, 116 | radius: 2, 117 | buttonText: Text( 118 | "跳过广告 $currentTime", 119 | style: 120 | TextStyle(fontSize: 12, color: Colors.white), 121 | ), 122 | onPressed: () { 123 | _timerUtil.cancel(); 124 | goHome(); 125 | }, 126 | ), 127 | )), 128 | ) 129 | ], 130 | ) 131 | ], 132 | ), 133 | ), 134 | ), 135 | ); 136 | } 137 | 138 | void _loadLoginStatus() async { 139 | await SpUtil.getInstance(); 140 | if (!mounted) return; 141 | _loadLocale(); 142 | _loadSplashAd(); 143 | } 144 | 145 | void _loadLocale() { 146 | setState(() { 147 | String token = SpUtil.getString(Constant.token, defValue: ""); 148 | if (token.isNotEmpty) { 149 | isLogin = true; 150 | } 151 | }); 152 | } 153 | 154 | void _loadSplashAd() { 155 | Repository.loadAsset("splash_ad").then((json) { 156 | splashAd = SplashAd.fromJson(Repository.toMapForList(json)); 157 | inVisible = !splashAd.isAd; 158 | if (inVisible) { 159 | // 没有广告,倒计时1s 160 | countdownTime = 1 * 1000; 161 | } 162 | initCountDown(countdownTime); 163 | // 开始倒计时 164 | _timerUtil.startCountDown(); 165 | setState(() {}); 166 | }); 167 | } 168 | 169 | @override 170 | void dispose() { 171 | super.dispose(); 172 | if (_timerUtil != null) _timerUtil.cancel(); //记得中dispose里面把timer cancel。 173 | } 174 | 175 | void goHome() { 176 | if (isLogin) { 177 | NavigatorUtils.push(context, Routes.root, replace: true); 178 | } else { 179 | NavigatorUtils.push(context, Routes.login, replace: true); 180 | } 181 | } 182 | 183 | /// 初始化倒计时 184 | void initCountDown(int countdownTime) { 185 | _timerUtil = new TimerUtil(mTotalTime: countdownTime); 186 | _timerUtil.setOnTimerTickCallback((int tick) { 187 | double _tick = tick / 1000; 188 | setState(() { 189 | currentTime = _tick.toInt(); 190 | }); 191 | if (_tick == 0) { 192 | goHome(); 193 | } 194 | }); 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /assets/json/discover/discover_sub.json: -------------------------------------------------------------------------------- 1 | { 2 | "banners": [ 3 | { 4 | "id": 192, 5 | "title": "薄荷×雀巢 3周群服务", 6 | "link": "https://truck.boohee.com/nice/collections/29/apply", 7 | "pic_url": "http://up.boohee.cn/house/u/shop/ad_page/20190820/OPbanner240.jpg" 8 | }, 9 | { 10 | "id": 172, 11 | "title": "甩掉秋膘,满200返200", 12 | "link": "https://one.boohee.com/store/pages/august_week3?page_from=community", 13 | "pic_url": "http://up.boohee.cn/house/u/shop/ad_page/0812/banner250.jpg" 14 | }, 15 | { 16 | "id": 176, 17 | "title": "成功故事0814", 18 | "link": "https://status.boohee.com/story/new%20story190813?page_from=course", 19 | "pic_url": "http://up.boohee.cn/house/u/shop/ad_page/0813/banner.jpg" 20 | }, 21 | { 22 | "id": 169, 23 | "title": "NICE服务(八月新的)", 24 | "link": "https://bhapp.boohee.com/webapp/virtual_goods/nice_2019/intro?type=nice&source=faxianbanner", 25 | "pic_url": "http://up.boohee.cn/house/u/shop/ad_page/20190819/banner240.jpg" 26 | }, 27 | { 28 | "id": 157, 29 | "title": "生蚝队长", 30 | "link": "boohee://comments/67314724", 31 | "pic_url": "http://up.boohee.cn/house/u/one/slider/20190819/guide_vol399_banner.jpg" 32 | }, 33 | { 34 | "id": 162, 35 | "title": "怡文好好吃", 36 | "link": "boohee://comments/67111786", 37 | "pic_url": "http://up.boohee.cn/house/u/one/slider/20190813/guide_vol397_banner.jpg" 38 | }, 39 | { 40 | "id": 194, 41 | "title": "雅琪", 42 | "link": "boohee://comments/6912249", 43 | "pic_url": "http://up.boohee.cn/house/u/one/slider/20190807/guide_vol395_banner.jpg" 44 | } 45 | ], 46 | 47 | "labels": [ 48 | { 49 | "title": "减肥知识", 50 | "url": "boohee://status_knowledge", 51 | "pic_url": "http://up.boohee.cn/house/u/shop/ad_page/0505/ss.png" 52 | }, 53 | { 54 | "title": "饮食广场", 55 | "url": "boohee://meal_square", 56 | "pic_url": "http://up.boohee.cn/house/u/shop/ad_page/0505/food.png" 57 | }, 58 | { 59 | "title": "瘦身定制", 60 | "url": "https://bhapp.boohee.com/webapp/virtual_goods/nice_2019/intro?type=nice&source=labels", 61 | "pic_url": "http://up.boohee.cn/house/u/shop/ad_page/0505/zhishi.png" 62 | } 63 | ] 64 | 65 | , 66 | "sections": [ 67 | { 68 | "name": "微信群", 69 | "more_content_text": null, 70 | "more_content_url": null, 71 | "sub_contents": [ 72 | { 73 | "title": "食物 值得认真对待", 74 | "sub_title": "薄荷智慧营养师 7天群", 75 | "img_url": "http://up.boohee.cn/house/u/one/slider/20190705/yys.png", 76 | "redirect_url": "boohee://dietitian_purchase" 77 | }, 78 | { 79 | "title": "拿出超模的态度", 80 | "sub_title": "超模25代餐 3周减重群", 81 | "img_url": "http://up.boohee.cn/house/u/one/slider/20190705/qun.png", 82 | "redirect_url": "boohee://goods/3751" 83 | }, 84 | { 85 | "title": "限制热量 平衡饮食", 86 | "sub_title": "21天10斤挑战+群服务", 87 | "img_url": "http://up.boohee.cn/house/u/shop/ad_page/20190212/mai.jpg", 88 | "redirect_url": "boohee://goods/3863" 89 | } 90 | ] 91 | }, 92 | { 93 | "name": "成功故事", 94 | "more_content_text": null, 95 | "more_content_url": null, 96 | "sub_contents": [ 97 | { 98 | "title": "圆脸阿姨变美少女", 99 | "sub_title": "(55.4-49.35)KG", 100 | "img_url": "http://up.boohee.cn/house/u/one/slider/20190717/1.png", 101 | "redirect_url": "https://status.boohee.com/story/new%20story190813?page_from=hbstory" 102 | }, 103 | { 104 | "title": "小肚子变马甲线!", 105 | "sub_title": "(50-46.1)KG", 106 | "img_url": "http://up.boohee.cn/house/u/shop/ad_page/20190627/88.jpg", 107 | "redirect_url": "https://status.boohee.com/story/new%20story190806?page_from=hbstory" 108 | }, 109 | { 110 | "title": "穿上24码裤子不是梦", 111 | "sub_title": "(64.7-54)KG", 112 | "img_url": "http://up.boohee.cn/house/u/shop/ad_page/20190627/731.png", 113 | "redirect_url": "https://status.boohee.com/story/new%20story190730?page_from=hbstory" 114 | }, 115 | { 116 | "title": "告别反弹,健康减重", 117 | "sub_title": "(55-46.5)KG", 118 | "img_url": "http://up.boohee.cn/house/u/shop/ad_page/20190627/724.png", 119 | "redirect_url": "https://status.boohee.com/story/new%20story190723?page_from=hbstory" 120 | }, 121 | { 122 | "title": "更多成功故事", 123 | "sub_title": "戳这里→", 124 | "img_url": "http://up.boohee.cn/house/u/shop/ad_page/20190505/more.jpg", 125 | "redirect_url": "https://one.boohee.com/store/pages/nice_story_list" 126 | } 127 | ] 128 | }, 129 | { 130 | "name": "推荐达人", 131 | "more_content_text": null, 132 | "more_content_url": null, 133 | "sub_contents": [ 134 | { 135 | "title": " 群星直播间", 136 | "sub_title": "带你探索健康好物", 137 | "img_url": "http://up.boohee.cn/house/u/shop/ad_page/0722/lab.jpg", 138 | "redirect_url": "https://one.boohee.com/store/pages/boheezbj" 139 | }, 140 | { 141 | "title": "薄荷首席营养师", 142 | "sub_title": "怡文好好吃", 143 | "img_url": "http://up.boohee.cn/house/u/shop/ad_page/20190212/yw.jpg", 144 | "redirect_url": "boohee://channel/vlog_yiwen" 145 | }, 146 | { 147 | "title": "爱吃爱笑的台湾营养师", 148 | "sub_title": "雅琪的万事屋", 149 | "img_url": "http://up.boohee.cn/house/u/shop/ad_page/20190212/yq.jpg", 150 | "redirect_url": "boohee://channel/vlog_yaqi" 151 | }, 152 | { 153 | "title": "热爱嘻哈的健身小钢炮", 154 | "sub_title": "生蚝队长", 155 | "img_url": "http://up.boohee.cn/house/u/shop/ad_page/20190212/sh.jpg", 156 | "redirect_url": "boohee://channel/vlog_oasher" 157 | }, 158 | { 159 | "title": "管不住嘴的减肥戏精", 160 | "sub_title": "大圣好瘦", 161 | "img_url": "http://up.boohee.cn/house/u/shop/ad_page/20190212/ds.jpg", 162 | "redirect_url": "boohee://channel/vlog_dasheng" 163 | } 164 | ] 165 | }, 166 | { 167 | "name": "推荐课程", 168 | "more_content_text": "更多课程", 169 | "more_content_url": "boohee://recommond_courses", 170 | "sub_contents": [ 171 | { 172 | "title": "最科学的减肥", 173 | "sub_title": "减肥必学的基础课知识", 174 | "img_url": "http://up.boohee.cn/house/u/shop/ad_page/20190212/class_1.jpg", 175 | "redirect_url": "boohee://training_course/1" 176 | }, 177 | { 178 | "title": "明星营养师教你怎么吃", 179 | "sub_title": "这么吃才能瘦", 180 | "img_url": "http://up.boohee.cn/house/u/shop/ad_page/20190212/class_2.jpg", 181 | "redirect_url": "boohee://training_course/2" 182 | }, 183 | { 184 | "title": "让你吃饱又能瘦", 185 | "sub_title": "减肥怎么吃主食", 186 | "img_url": "http://up.boohee.cn/house/u/shop/ad_page/20190212/class_3.jpg", 187 | "redirect_url": "boohee://training_course/3" 188 | }, 189 | { 190 | "title": "怎么运动才减得快?", 191 | "sub_title": "运动减肥必学的基础课", 192 | "img_url": "http://up.boohee.cn/house/u/shop/ad_page/20190212/class_4.jpg", 193 | "redirect_url": "boohee://training_course/15" 194 | } 195 | ] 196 | } 197 | ] 198 | } -------------------------------------------------------------------------------- /assets/json/shop/shop_banner.json: -------------------------------------------------------------------------------- 1 | { 2 | "banner_showcases": [ 3 | { 4 | "id": 1961, 5 | "exhibit": "3847", 6 | "default_photo_url": "http://up.boohee.cn/house/u/shop/ad_page/0618/k375.jpg", 7 | "default_photo_height": 375, 8 | "default_photo_width": 750, 9 | "exhibit_type": "goods", 10 | "page_title": "" 11 | }, 12 | { 13 | "id": 1630, 14 | "exhibit": "3746", 15 | "default_photo_url": "http://up.boohee.cn/house/u/shop/ad_page/20180731/naidong375.jpg", 16 | "default_photo_height": 375, 17 | "default_photo_width": 700, 18 | "exhibit_type": "goods", 19 | "page_title": "" 20 | }, 21 | { 22 | "id": 2016, 23 | "exhibit": "3100", 24 | "default_photo_url": "http://up.boohee.cn/house/u/shop/ad_page/0812/mp.jpg", 25 | "default_photo_height": 340, 26 | "default_photo_width": 640, 27 | "exhibit_type": "goods", 28 | "page_title": "" 29 | }, 30 | { 31 | "id": 1904, 32 | "exhibit": "3609", 33 | "default_photo_url": "http://up.boohee.cn/house/u/shop/ad_page/0422/mm.jpg", 34 | "default_photo_height": 375, 35 | "default_photo_width": 750, 36 | "exhibit_type": "goods", 37 | "page_title": "" 38 | }, 39 | { 40 | "id": 2011, 41 | "exhibit": "https://one.boohee.com/store/pages/august_week3?page_from=shopbanner", 42 | "default_photo_url": "http://up.boohee.cn/house/u/shop/ad_page/0812/banner750.jpg", 43 | "default_photo_height": 375, 44 | "default_photo_width": 750, 45 | "exhibit_type": "page", 46 | "page_title": "查看" 47 | }, 48 | { 49 | "id": 1753, 50 | "exhibit": "3216", 51 | "default_photo_url": "http://up.boohee.cn/house/u/shop/ad_page/0812/dg.jpg", 52 | "default_photo_height": 375, 53 | "default_photo_width": 750, 54 | "exhibit_type": "goods", 55 | "page_title": "" 56 | }, 57 | { 58 | "id": 1948, 59 | "exhibit": "https://bhapp.boohee.com/webapp/virtual_goods/nice_2019/intro?type=nice&source=store_home_banner", 60 | "default_photo_url": "http://up.boohee.cn/house/u/shop/ad_page/20190813/banner375.jpg", 61 | "default_photo_height": 375, 62 | "default_photo_width": 750, 63 | "exhibit_type": "page", 64 | "page_title": "查看" 65 | }, 66 | { 67 | "id": 1934, 68 | "exhibit": "https://truck.boohee.com/nice/collections/29/apply?page_from=shopbanner", 69 | "default_photo_url": "http://up.boohee.cn/house/u/shop/ad_page/20190812/banner375.jpg", 70 | "default_photo_height": 375, 71 | "default_photo_width": 750, 72 | "exhibit_type": "page", 73 | "page_title": "查看" 74 | } 75 | ], 76 | "shop_modules": [ 77 | { 78 | "position": 1, 79 | "display": true, 80 | "title": "❤️满200返200", 81 | "sub_title": "鸡肉肠新包装>>", 82 | "picture_url1": "http://up.boohee.cn/house/u/20190121spsl/160_CHANG.png", 83 | "picture_url2": "http://up.boohee.cn/house/u/shop/ad_page/0513/sss.png", 84 | "redirect_url": "https://one.boohee.com/store/pages/august_week3", 85 | "new_tag": "2019-08-17 16:00:00" 86 | }, 87 | { 88 | "position": 2, 89 | "display": true, 90 | "title": "😊薄荷新人推荐", 91 | "sub_title": "人气榜单在此>>", 92 | "picture_url1": "http://up.boohee.cn/house/u/shop/ad_page/0722/bang.jpg", 93 | "picture_url2": "http://up.boohee.cn/house/u/shop/ad_page/0422/c.png", 94 | "redirect_url": "boohee://goods_list/86", 95 | "new_tag": "2019-07-29 15:00:00" 96 | }, 97 | { 98 | "position": 3, 99 | "display": true, 100 | "title": "限时抢购", 101 | "start_time": "2019-08-12T16:00:00.000+00:00", 102 | "end_time": "2019-08-19T16:00:00.000+00:00", 103 | "picture_url1": "http://up.boohee.cn/house/u/20190121spsl/zs_new.png", 104 | "picture_url2": "http://up.boohee.cn/house/u/20190121spsl/kfdb1_1601.jpg", 105 | "redirect_url": "https://truck.boohee.com/promotion", 106 | "new_tag": "2019-07-08 00:00:00" 107 | }, 108 | { 109 | "position": 4, 110 | "display": true, 111 | "title": "顾问陪你瘦", 112 | "sub_title": "送267元减脂包>>>", 113 | "picture_url1": "http://up.boohee.cn/house/u/shop/ad_page/0806/160-160.png", 114 | "picture_url2": "http://up.boohee.cn/house/u/shop/ad_page/0806/160-160l.png", 115 | "redirect_url": "https://bhapp.boohee.com/webapp/virtual_goods/nice_2019/intro?type=nice&source=store_homepage_promotion", 116 | "new_tag": "" 117 | }, 118 | { 119 | "position": 5, 120 | "display": false, 121 | "title": "春季礼包精选", 122 | "picture_url1": "http://up.boohee.cn/house/u/shop/ad_page/0225/3.jpg", 123 | "redirect_url": "boohee://goods_list/277", 124 | "sub_title": "打包起来折扣更大", 125 | "new_tag": "" 126 | }, 127 | { 128 | "position": 6, 129 | "display": true, 130 | "title": "节后减肥", 131 | "sub_title": "进群更好瘦!", 132 | "picture_url1": "http://up.boohee.cn/house/u/shop/ad_page/0221/yt.jpg", 133 | "redirect_url": "http://nice.boohee.com/webapp/collections/19", 134 | "new_tag": "2019-2-21" 135 | }, 136 | { 137 | "position": 7, 138 | "display": true, 139 | "title": "商品福利", 140 | "sub_title": "入群早知道", 141 | "picture_url1": "http://up.boohee.cn/house/u/shop/ad_page/20180806/libao1.jpg", 142 | "redirect_url": "https://beauty.boohee.com/webapp/ice_room_banners/home?group_id=5", 143 | "new_tag": "" 144 | } 145 | ], 146 | "categories": [ 147 | { 148 | "id": 9, 149 | "name": "新品购", 150 | "description": "所有商品按上新排序", 151 | "icon_url": "http://one.boohee.cn/uploads%2Fcategory%2Ficon%2F9%2Fxin.png" 152 | }, 153 | { 154 | "id": 17, 155 | "name": "控卡餐", 156 | "description": "正餐", 157 | "icon_url": "http://one.boohee.cn/uploads%2Fcategory%2Ficon%2F17%2Fmeal.png" 158 | }, 159 | { 160 | "id": 28, 161 | "name": "高蛋白", 162 | "description": "高蛋白", 163 | "icon_url": "http://one.boohee.cn/uploads%2Fcategory%2Ficon%2F28%2Fgao.png" 164 | }, 165 | { 166 | "id": 27, 167 | "name": "燃燃燃", 168 | "description": "加强", 169 | "icon_url": "http://one.boohee.cn/uploads%2Fcategory%2Ficon%2F27%2Fxiao.png" 170 | }, 171 | { 172 | "id": 25, 173 | "name": "瘦身定制", 174 | "description": "瘦身定制", 175 | "icon_url": "http://one.boohee.cn/uploads%2Fcategory%2Ficon%2F25%2Fshou.png" 176 | }, 177 | { 178 | "id": 7, 179 | "name": "人气秤", 180 | "description": "硬件", 181 | "icon_url": "http://one.boohee.cn/uploads%2Fcategory%2Ficon%2F7%2Fcheng.png" 182 | }, 183 | { 184 | "id": 18, 185 | "name": "轻零食", 186 | "description": "零食", 187 | "icon_url": "http://one.boohee.cn/uploads%2Fcategory%2Ficon%2F18%2Fqing.png" 188 | }, 189 | { 190 | "id": 29, 191 | "name": "低脂肪", 192 | "description": "低脂肪", 193 | "icon_url": "http://one.boohee.cn/uploads%2Fcategory%2Ficon%2F29%2Ffat.png" 194 | }, 195 | { 196 | "id": 13, 197 | "name": "好喝的", 198 | "description": "湿泡", 199 | "icon_url": "http://one.boohee.cn/uploads%2Fcategory%2Ficon%2F13%2Fhao.png" 200 | }, 201 | { 202 | "id": 23, 203 | "name": "BR肌密", 204 | "description": "BR肌密", 205 | "icon_url": "http://one.boohee.cn/uploads%2Fcategory%2Ficon%2F23%2Fa.png" 206 | }, 207 | { 208 | "id": 26, 209 | "name": "其它", 210 | "description": "其它", 211 | "icon_url": "http://one.boohee.cn/uploads%2Fcategory%2Ficon%2F26%2Fa.png" 212 | } 213 | ] 214 | } -------------------------------------------------------------------------------- /lib/views/discover/discover_child_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:banner_view/banner_view.dart'; 2 | import 'package:boohee_flutter/common/colors.dart'; 3 | import 'package:boohee_flutter/model/discover/sub_discover.dart'; 4 | import 'package:boohee_flutter/res/styles.dart'; 5 | import 'package:boohee_flutter/utils/repository_utils.dart'; 6 | import 'package:boohee_flutter/widget/top_bottom_widget.dart'; 7 | import 'package:extended_image/extended_image.dart'; 8 | import 'package:flustars/flustars.dart'; 9 | import 'package:flutter/cupertino.dart'; 10 | import 'package:flutter/material.dart'; 11 | import 'package:flutter_easyrefresh/easy_refresh.dart'; 12 | import 'package:flutter_easyrefresh/material_header.dart'; 13 | 14 | class DiscoverChildPage extends StatefulWidget { 15 | @override 16 | _DiscoverChildPageState createState() => _DiscoverChildPageState(); 17 | } 18 | 19 | class _DiscoverChildPageState extends State { 20 | EasyRefreshController _controller = EasyRefreshController(); 21 | SubDiscover _subDiscover; 22 | 23 | /// tab、列表集合合集 24 | var mList = []; 25 | 26 | @override 27 | void initState() { 28 | super.initState(); 29 | loadData(); 30 | } 31 | 32 | @override 33 | Widget build(BuildContext context) { 34 | return EasyRefresh.custom( 35 | slivers: [ 36 | createBannerView(), 37 | SliverList( 38 | delegate: 39 | SliverChildBuilderDelegate((BuildContext context, int index) { 40 | Widget widget; 41 | if (mList[index] is List) { 42 | var list = (mList[index] as List); 43 | 44 | /// tab 45 | widget = createTabView(list); 46 | } else if (mList[index] is Sections) { 47 | /// 列表 48 | widget = createListChild(mList[index] as Sections); 49 | } 50 | return widget; 51 | }, childCount: mList.length)) 52 | ], 53 | header: MaterialHeader( 54 | valueColor: AlwaysStoppedAnimation(mainColor), 55 | ), 56 | controller: _controller, 57 | onRefresh: () async { 58 | loadData(); 59 | _controller.finishRefresh(); 60 | setState(() {}); 61 | }, 62 | ); 63 | } 64 | 65 | Widget createBannerView() { 66 | return SliverToBoxAdapter( 67 | child: Container( 68 | height: ScreenUtil.getScreenW(context) * (250 / 750 * 1.0).toDouble(), 69 | child: BannerView( 70 | _subDiscover.banners 71 | .map((bean) => (createBannerChildView(bean))) 72 | .toList(), 73 | intervalDuration: Duration(seconds: 3), 74 | indicatorMargin: 5, 75 | indicatorNormal: new Container( 76 | width: 8.0, 77 | height: 5.0, 78 | decoration: new BoxDecoration( 79 | color: Colors.white, 80 | shape: BoxShape.rectangle, 81 | borderRadius: new BorderRadius.all( 82 | new Radius.circular(20.0), 83 | ), 84 | ), 85 | ), 86 | indicatorSelected: new Container( 87 | width: 15.0, 88 | height: 5.0, 89 | decoration: new BoxDecoration( 90 | color: Color(0xFFEEEFF3), 91 | shape: BoxShape.rectangle, 92 | borderRadius: new BorderRadius.all( 93 | new Radius.circular(20.0), 94 | ), 95 | ), 96 | ), 97 | indicatorBuilder: (context, indicator) { 98 | Widget cc = new Container( 99 | margin: EdgeInsets.only(bottom: 8), 100 | alignment: Alignment.bottomCenter, 101 | height: double.infinity, 102 | child: indicator, 103 | ); 104 | return cc; 105 | }, 106 | ), 107 | ), 108 | ); 109 | } 110 | 111 | /// 发现页数据 banner、tab、列表数据 112 | void loadData() { 113 | Repository.loadAsset("discover_sub", fileDir: "discover").then((response) { 114 | _subDiscover = SubDiscover.fromJson(Repository.toMap(response)); 115 | mList.clear(); 116 | mList.add(_subDiscover.labels); 117 | mList.addAll(_subDiscover.sections); 118 | setState(() {}); 119 | }); 120 | } 121 | 122 | Widget createBannerChildView(Banners data) { 123 | return Container( 124 | margin: EdgeInsets.only(top: 13.0, left: 17, right: 17), 125 | decoration: BoxDecoration( 126 | image: DecorationImage( 127 | image: ExtendedNetworkImageProvider(data.picUrl, cache: true), 128 | fit: BoxFit.cover, 129 | ), 130 | borderRadius: BorderRadius.all( 131 | Radius.circular(12.0), 132 | ), 133 | ), 134 | ); 135 | } 136 | 137 | /// Tab 138 | Widget createTabView(List list) { 139 | return Container( 140 | padding: EdgeInsets.only(top: 20), 141 | child: GridView.builder( 142 | shrinkWrap: true, 143 | physics: NeverScrollableScrollPhysics(), 144 | // 禁用GradView滚动事件 145 | itemCount: list.length, 146 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( 147 | crossAxisCount: 3, childAspectRatio: 2.2), 148 | itemBuilder: (BuildContext context, int index) { 149 | return TopBottom( 150 | margin: 5, 151 | top: ExtendedImage.network( 152 | list[index].picUrl, 153 | enableLoadState: false, 154 | height: 34, 155 | width: 34, 156 | ), 157 | bottom: Text( 158 | list[index].title, 159 | style: TextStyles.get12Text_373D52(), 160 | ), 161 | ); 162 | }), 163 | ); 164 | } 165 | 166 | /// 列表 167 | Widget createListChild(Sections sections) { 168 | return Container( 169 | height: 172, 170 | margin: EdgeInsets.only(top: 33), 171 | padding: EdgeInsets.only(left: 17), 172 | child: Column( 173 | crossAxisAlignment: CrossAxisAlignment.start, 174 | children: [ 175 | Text( 176 | sections.name, 177 | style: TextStyles.get15TextBold_373D52(), 178 | ), 179 | _getHorizontalListView(sections.subContents) 180 | ], 181 | ), 182 | ); 183 | } 184 | 185 | /// 横向列表 186 | Widget _getHorizontalListView(List subContents) { 187 | var horizontalList = ListView.builder( 188 | scrollDirection: Axis.horizontal, 189 | itemBuilder: (context, index) { 190 | return Column( 191 | crossAxisAlignment: CrossAxisAlignment.start, 192 | children: [ 193 | Container( 194 | margin: EdgeInsets.only(right: 11, top: 14, bottom: 10), 195 | height: 92, 196 | width: 144, 197 | decoration: BoxDecoration( 198 | image: DecorationImage( 199 | image: ExtendedNetworkImageProvider( 200 | subContents[index].imgUrl, 201 | cache: true), 202 | fit: BoxFit.cover, 203 | ), 204 | borderRadius: BorderRadius.all( 205 | Radius.circular(12.0), 206 | ), 207 | ), 208 | ), 209 | Text( 210 | subContents[index].title, 211 | style: TextStyle(fontSize: 13, color: color373D52), 212 | maxLines: 1, 213 | overflow: TextOverflow.ellipsis, 214 | ), 215 | SizeBoxFactory.getVerticalSizeBox(1), 216 | Text( 217 | subContents[index].subTitle, 218 | style: TextStyle(fontSize: 11, color: colorA8ACBC), 219 | maxLines: 1, 220 | overflow: TextOverflow.ellipsis, 221 | ) 222 | ], 223 | ); 224 | }, 225 | itemCount: subContents.length); 226 | 227 | return Expanded( 228 | child: Container(width: double.infinity, child: horizontalList)); 229 | } 230 | } 231 | -------------------------------------------------------------------------------- /lib/views/mine_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:boohee_flutter/app/route/fluro_navigator.dart'; 2 | import 'package:boohee_flutter/app/route/routes.dart'; 3 | import 'package:boohee_flutter/common/colors.dart'; 4 | import 'package:boohee_flutter/model/login_user.dart'; 5 | import 'package:boohee_flutter/model/mine_cards.dart'; 6 | import 'package:boohee_flutter/res/styles.dart'; 7 | import 'package:boohee_flutter/utils/account_utils.dart'; 8 | import 'package:boohee_flutter/utils/repository_utils.dart'; 9 | import 'package:boohee_flutter/utils/utils.dart'; 10 | import 'package:boohee_flutter/widget/card_view.dart'; 11 | import 'package:boohee_flutter/widget/tool_bar.dart'; 12 | import 'package:boohee_flutter/widget/top_bottom_widget.dart'; 13 | import 'package:extended_image/extended_image.dart'; 14 | import 'package:flustars/flustars.dart'; 15 | import 'package:flutter/cupertino.dart'; 16 | import 'package:flutter/material.dart'; 17 | 18 | class MinePage extends StatefulWidget { 19 | @override 20 | State createState() => _MinePageState(); 21 | } 22 | 23 | class _MinePageState extends State { 24 | User mUser; 25 | List mCards = []; 26 | 27 | @override 28 | void initState() { 29 | super.initState(); 30 | mUser = AccountUtils.getUser(); 31 | getMineCards(); 32 | setState(() {}); 33 | } 34 | 35 | @override 36 | Widget build(BuildContext context) { 37 | return Scaffold( 38 | appBar: Toolbar( 39 | onTabRightOne: () { 40 | settingClick(); 41 | }, 42 | ), 43 | body: CustomScrollView( 44 | physics: BouncingScrollPhysics(), 45 | slivers: [ 46 | SliverToBoxAdapter(child: createMineHeader()), 47 | createMenuTab() 48 | ], 49 | ), 50 | ); 51 | } 52 | 53 | /// 我的页面头部 54 | Widget createMineHeader() { 55 | return Stack( 56 | children: [ 57 | Container( 58 | padding: EdgeInsets.only(top: 10, bottom: 47), 59 | color: color00CDA2, 60 | child: Column( 61 | crossAxisAlignment: CrossAxisAlignment.start, 62 | children: [ 63 | Row( 64 | crossAxisAlignment: CrossAxisAlignment.center, 65 | children: [ 66 | PaddingStyles.getPadding(17), 67 | new ClipOval( 68 | child: ExtendedImage.network( 69 | mUser.avatarUrl, 70 | fit: BoxFit.cover, 71 | height: 60, 72 | width: 60, 73 | ), 74 | ), 75 | PaddingStyles.getPadding(13), 76 | Column( 77 | crossAxisAlignment: CrossAxisAlignment.start, 78 | children: [ 79 | Text( 80 | mUser.userName, 81 | style: TextStyle( 82 | fontSize: 17, 83 | color: Colors.white, 84 | fontWeight: FontWeight.w700), 85 | ), 86 | Text( 87 | "修改个人资料", 88 | style: TextStyle( 89 | fontSize: 12, 90 | color: Colors.white, 91 | ), 92 | ) 93 | ], 94 | ) 95 | ], 96 | ), 97 | SizeBoxFactory.getVerticalSizeBox(25), 98 | Row( 99 | mainAxisAlignment: MainAxisAlignment.spaceAround, 100 | mainAxisSize: MainAxisSize.max, 101 | children: [ 102 | TopBottom( 103 | top: Text( 104 | "57", 105 | style: TextStyles.get15White(), 106 | ), 107 | bottom: Text( 108 | "动态", 109 | style: TextStyle(fontSize: 12, color: Color(0x9EFFFFFF)), 110 | ), 111 | margin: 2, 112 | ), 113 | TopBottom( 114 | top: Text( 115 | "74", 116 | style: TextStyles.get15White(), 117 | ), 118 | bottom: Text( 119 | "关注", 120 | style: TextStyle(fontSize: 12, color: Color(0x9EFFFFFF)), 121 | ), 122 | margin: 2, 123 | ), 124 | TopBottom( 125 | top: Text( 126 | "423", 127 | style: TextStyles.get15White(), 128 | ), 129 | bottom: Text( 130 | "粉丝", 131 | style: TextStyle(fontSize: 12, color: Color(0x9EFFFFFF)), 132 | ), 133 | margin: 2, 134 | ) 135 | ], 136 | ), 137 | ], 138 | ), 139 | ), 140 | CardView( 141 | margin: EdgeInsets.only(left: 17, right: 17, top: 160), 142 | child: Padding( 143 | padding: EdgeInsets.only(top: 22, bottom: 22, left: 30, right: 30), 144 | child: Row( 145 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 146 | children: [ 147 | TopBottom( 148 | top: Image.asset( 149 | Utils.getImgPath("ic_me_order"), 150 | width: 34, 151 | height: 34, 152 | ), 153 | bottom: Text( 154 | "订单", 155 | style: TextStyles.get12Text_373D52(), 156 | ), 157 | margin: 5, 158 | ), 159 | TopBottom( 160 | top: Image.asset( 161 | Utils.getImgPath("ic_me_shopping_cart"), 162 | width: 34, 163 | height: 34, 164 | ), 165 | bottom: Text( 166 | "购物车", 167 | style: TextStyles.get12Text_373D52(), 168 | ), 169 | margin: 5, 170 | ), 171 | TopBottom( 172 | top: Image.asset( 173 | Utils.getImgPath("ic_me_ticket"), 174 | width: 34, 175 | height: 34, 176 | ), 177 | bottom: Text( 178 | "优惠券", 179 | style: TextStyles.get12Text_373D52(), 180 | ), 181 | margin: 5, 182 | ), 183 | TopBottom( 184 | top: Image.asset( 185 | Utils.getImgPath("ic_me_address"), 186 | width: 34, 187 | height: 34, 188 | ), 189 | bottom: Text( 190 | "收货地址", 191 | style: TextStyles.get12Text_373D52(), 192 | ), 193 | margin: 5, 194 | ) 195 | ], 196 | ), 197 | ), 198 | ) 199 | ], 200 | ); 201 | } 202 | 203 | /// 分类 204 | Widget createMenuTab() { 205 | return SliverToBoxAdapter( 206 | child: Container( 207 | height: 176, 208 | child: CardView( 209 | margin: EdgeInsets.only(left: 17, right: 17, top: 14), 210 | child: Padding( 211 | padding: EdgeInsets.only(top: 20, left: 10, right: 10), 212 | child: GridView.builder( 213 | physics: NeverScrollableScrollPhysics(), // 禁用GradView滚动事件 214 | itemCount: mCards.length, 215 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( 216 | crossAxisCount: 4, 217 | ), 218 | itemBuilder: (BuildContext context, int index) { 219 | return createCard(mCards[index]); 220 | }), 221 | ), 222 | ), 223 | ), 224 | ); 225 | } 226 | 227 | /// 卡片,后台配置 228 | void getMineCards() { 229 | Repository.loadAsset("mine_cards", fileDir: "me").then((json) { 230 | MineCards mineCards = MineCards.fromJson(Repository.toMap(json)); 231 | mCards = mineCards.data; 232 | setState(() {}); 233 | }); 234 | } 235 | 236 | /// 菜单卡片 237 | Widget createCard(Data mCard) { 238 | return TopBottom( 239 | top: ExtendedImage.network( 240 | mCard.iconUrl, 241 | width: 22, 242 | height: 22, 243 | ), 244 | bottom: Text( 245 | mCard.name, 246 | style: TextStyles.get12Text_373D52(), 247 | ), 248 | margin: 6, 249 | ); 250 | } 251 | 252 | /// 退出登陆弹框 253 | void settingClick() { 254 | showDialog( 255 | context: context, 256 | builder: (context) { 257 | return new AlertDialog( 258 | content: Text( 259 | "是否确认退出登录?", 260 | style: TextStyles.get15Text_373D52(), 261 | ), 262 | actions: [ 263 | FlatButton( 264 | onPressed: () async { 265 | // 清空登陆信息 266 | SpUtil.clear(); 267 | // 关闭弹框 268 | Navigator.of(context).pop(); 269 | // 打开登陆页面 270 | NavigatorUtils.push(context, Routes.login, 271 | replace: true, clearStack: true); 272 | }, 273 | child: new Text( 274 | "确定", 275 | style: TextStyle(color: mainColor), 276 | ), 277 | ), 278 | FlatButton( 279 | onPressed: () { 280 | Navigator.of(context).pop(); 281 | }, 282 | child: new Text("取消", style: TextStyle(color: mainColor)), 283 | ), 284 | ], 285 | ); 286 | }); 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /lib/views/shop_pages/shop_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:banner_view/banner_view.dart'; 2 | import 'package:boohee_flutter/common/colors.dart'; 3 | import 'package:boohee_flutter/model/ShopBanner.dart'; 4 | import 'package:boohee_flutter/model/ShopRecommendList.dart'; 5 | import 'package:boohee_flutter/res/styles.dart'; 6 | import 'package:boohee_flutter/utils/repository_utils.dart'; 7 | import 'package:boohee_flutter/widget/card_view.dart'; 8 | import 'package:boohee_flutter/widget/common_search_bar.dart'; 9 | import 'package:extended_image/extended_image.dart'; 10 | import 'package:flutter/material.dart'; 11 | import 'package:flutter_easyrefresh/easy_refresh.dart'; 12 | import 'package:flutter_easyrefresh/material_header.dart'; 13 | 14 | class ShopPage extends StatefulWidget { 15 | @override 16 | State createState() => _ShopPageState(); 17 | } 18 | 19 | class _ShopPageState extends State { 20 | List _bannerList = []; 21 | List _categoriseList = []; 22 | List _goodsList = []; 23 | double bannerHeight = 200; 24 | EasyRefreshController _controller = EasyRefreshController(); 25 | 26 | @override 27 | void initState() { 28 | // TODO: implement initState 29 | super.initState(); 30 | loadData(); 31 | } 32 | 33 | /// 加载数据 34 | void loadData() { 35 | /// 商店Banner 36 | Repository.loadAsset("shop_banner", fileDir: "shop").then((json) { 37 | _categoriseList.clear(); 38 | ShopBanner data = ShopBanner.fromJson(Repository.toMap(json)); 39 | _bannerList = data.bannerShowcases; 40 | // 保证数据最多为10条 41 | data.categories.forEach((it) { 42 | // 默认第一个分类 43 | if (data.categories.indexOf(it) < 10) { 44 | _categoriseList.add(it); 45 | } 46 | }); 47 | // 计算Banner的高度 48 | double screenWidth = MediaQuery.of(context).size.width; 49 | if (_bannerList.length > 0) { 50 | bannerHeight = (screenWidth - 2 * 17) * 51 | (_bannerList[0].defaultPhotoHeight / 52 | _bannerList[0].defaultPhotoWidth); 53 | } 54 | _controller.finishRefresh(); 55 | setState(() {}); 56 | }); 57 | 58 | /// 商店推荐商品 59 | Repository.loadAsset("shop_recommend_list", fileDir: "shop").then((json) { 60 | ShopRecommendList data = 61 | ShopRecommendList.fromJson(Repository.toMap(json)); 62 | _goodsList.clear(); 63 | _goodsList.addAll(data.goods); 64 | setState(() {}); 65 | }); 66 | } 67 | 68 | @override 69 | Widget build(BuildContext context) { 70 | return Scaffold( 71 | appBar: SearchBar( 72 | isShowCartIcon: true, 73 | text: "商店搜索", 74 | ), 75 | body: EasyRefresh.custom( 76 | slivers: [ 77 | createBannerView(), 78 | createCategoryGridView(), 79 | createGoodsGridView(), 80 | ], 81 | header: MaterialHeader( 82 | valueColor: AlwaysStoppedAnimation(mainColor), 83 | ), 84 | taskIndependence: true, 85 | enableControlFinishRefresh: true, 86 | firstRefresh: true, 87 | controller: _controller, 88 | onRefresh: () async { 89 | loadData(); 90 | }, 91 | )); 92 | } 93 | 94 | Widget createBannerView() { 95 | return SliverToBoxAdapter( 96 | child: Container( 97 | height: bannerHeight, 98 | child: BannerView( 99 | _bannerList.map((bean) => (createBannerChildView(bean))).toList(), 100 | intervalDuration: Duration(seconds: 3), 101 | indicatorMargin: 5, 102 | indicatorNormal: new Container( 103 | width: 8.0, 104 | height: 5.0, 105 | decoration: new BoxDecoration( 106 | color: Colors.white, 107 | shape: BoxShape.rectangle, 108 | borderRadius: new BorderRadius.all( 109 | new Radius.circular(20.0), 110 | ), 111 | ), 112 | ), 113 | indicatorSelected: new Container( 114 | width: 15.0, 115 | height: 5.0, 116 | decoration: new BoxDecoration( 117 | color: Color(0xFFEEEFF3), 118 | shape: BoxShape.rectangle, 119 | borderRadius: new BorderRadius.all( 120 | new Radius.circular(20.0), 121 | ), 122 | ), 123 | ), 124 | indicatorBuilder: (context, indicator) { 125 | Widget cc = new Container( 126 | margin: EdgeInsets.only(bottom: 8), 127 | alignment: Alignment.bottomCenter, 128 | height: double.infinity, 129 | child: indicator, 130 | ); 131 | return cc; 132 | }, 133 | ), 134 | ), 135 | ); 136 | } 137 | 138 | Widget createBannerChildView(Banner_showcases data) { 139 | return Container( 140 | margin: EdgeInsets.only(top: 13.0, left: 17, right: 17), 141 | decoration: BoxDecoration( 142 | image: DecorationImage( 143 | image: 144 | ExtendedNetworkImageProvider(data.defaultPhotoUrl, cache: true), 145 | fit: BoxFit.cover, 146 | ), 147 | borderRadius: BorderRadius.all( 148 | Radius.circular(12.0), 149 | ), 150 | ), 151 | ); 152 | } 153 | 154 | // 分类 155 | Widget createCategoryGridView() { 156 | return SliverToBoxAdapter( 157 | child: Container( 158 | child: CardView( 159 | margin: EdgeInsets.only(left: 17, right: 17, top: 13), 160 | child: Padding( 161 | padding: EdgeInsets.only(top: 13, left: 10, right: 10), 162 | child: GridView.builder( 163 | shrinkWrap: true, 164 | physics: NeverScrollableScrollPhysics(), 165 | // 禁用GradView滚动事件 166 | itemCount: _categoriseList.length, 167 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( 168 | crossAxisCount: 5), 169 | itemBuilder: (BuildContext context, int index) { 170 | return getCategoryItemContainer(_categoriseList[index]); 171 | }), 172 | ), 173 | ), 174 | ), 175 | ); 176 | } 177 | 178 | Widget getCategoryItemContainer(Categories item) { 179 | return Column( 180 | mainAxisAlignment: MainAxisAlignment.start, 181 | children: [ 182 | ExtendedImage.network( 183 | item.iconUrl, 184 | width: 35, 185 | cache: true, 186 | height: 35, 187 | ), 188 | Text( 189 | item.name, 190 | style: TextStyle(fontSize: 12, color: color373D52), 191 | ), 192 | ], 193 | ); 194 | } 195 | 196 | Widget createGoodsGridView() { 197 | return SliverPadding( 198 | padding: EdgeInsets.only(top: 13.0, bottom: 13, left: 17.0, right: 17), 199 | sliver: SliverGrid( 200 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( 201 | crossAxisCount: 2, 202 | mainAxisSpacing: 10, 203 | crossAxisSpacing: 8, 204 | childAspectRatio: 0.68), 205 | delegate: new SliverChildBuilderDelegate( 206 | (BuildContext context, int index) { 207 | return getGoodsItemContainer(_goodsList[index]); 208 | }, 209 | childCount: _goodsList.length, 210 | )), 211 | ); 212 | } 213 | 214 | Widget getGoodsItemContainer(Goods item) { 215 | return CardView( 216 | margin: EdgeInsets.all(0.0), 217 | child: Column( 218 | crossAxisAlignment: CrossAxisAlignment.start, 219 | children: [ 220 | Container( 221 | height: 150, 222 | decoration: BoxDecoration( 223 | image: DecorationImage( 224 | image: 225 | ExtendedNetworkImageProvider(item.bigPhotoUrl, cache: true), 226 | fit: BoxFit.cover, 227 | ), 228 | borderRadius: BorderRadius.only( 229 | topLeft: Radius.circular(10.0), 230 | topRight: Radius.circular(10.0)), 231 | ), 232 | ), 233 | Expanded( 234 | child: Column( 235 | crossAxisAlignment: CrossAxisAlignment.start, 236 | children: [ 237 | Padding( 238 | padding: EdgeInsets.only(left: 10, right: 10, top: 8), 239 | child: Text( 240 | item.title.split("|")[0] ?? "", 241 | style: TextStyle(fontSize: 13, color: color373D52), 242 | maxLines: 1, 243 | overflow: TextOverflow.ellipsis, 244 | ), 245 | ), 246 | Padding( 247 | padding: EdgeInsets.only(left: 10, right: 10, top: 1), 248 | child: Text( 249 | item.title.split("|").length > 1 250 | ? item.title.split("|")[1] 251 | : "", 252 | style: TextStyle(fontSize: 11, color: colorA8ACBC), 253 | maxLines: 2, 254 | overflow: TextOverflow.ellipsis, 255 | ), 256 | ), 257 | Padding( 258 | padding: 259 | EdgeInsets.only(left: 10, right: 10, top: 12, bottom: 12), 260 | child: Row( 261 | children: [ 262 | Text( 263 | "¥" + item.basePrice.toString(), 264 | style: TextStyle(fontSize: 11, color: colorFF6C65), 265 | ), 266 | SizeBoxFactory.getHorizontalSizeBox(8), 267 | Text( 268 | "¥" + item.marketPrice.toString(), 269 | style: TextStyle( 270 | fontSize: 11, 271 | color: colorA8ACBC, 272 | decoration: TextDecoration.lineThrough), 273 | ) 274 | ], 275 | ), 276 | ) 277 | ], 278 | )) 279 | ], 280 | ), 281 | ); 282 | } 283 | } 284 | -------------------------------------------------------------------------------- /lib/views/home_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:boohee_flutter/app/route/fluro_navigator.dart'; 4 | import 'package:boohee_flutter/common/colors.dart'; 5 | import 'package:boohee_flutter/common/constant.dart'; 6 | import 'package:boohee_flutter/model/home_tools.dart'; 7 | import 'package:boohee_flutter/model/home_wall_paper.dart'; 8 | import 'package:boohee_flutter/res/styles.dart'; 9 | import 'package:boohee_flutter/utils/repository_utils.dart'; 10 | import 'package:boohee_flutter/utils/toast_utils.dart'; 11 | import 'package:boohee_flutter/widget/card_view.dart'; 12 | import 'package:boohee_flutter/widget/common_search_bar.dart'; 13 | import 'package:boohee_flutter/widget/header/home_wallpaper_header.dart'; 14 | import 'package:boohee_flutter/widget/home_common_card.dart'; 15 | import 'package:boohee_flutter/widget/main/main_widgets.dart'; 16 | import 'package:flutter/material.dart'; 17 | import 'package:flutter_easyrefresh/easy_refresh.dart'; 18 | import 'package:rxdart/rxdart.dart'; 19 | 20 | class HomePage extends StatefulWidget { 21 | @override 22 | State createState() => _HomePageState(); 23 | } 24 | 25 | class _HomePageState extends State { 26 | /// 控制顶部搜索框的颜色 27 | SearchBarController _searchBarController = new SearchBarController( 28 | alpha: 0, 29 | searchBarBg: Color(0x1FFFFFFF), 30 | appbarTitleColor: colorA8ACBC, 31 | appbarLeftIcon: "ic_search_grey", 32 | appbarRightIcon: "ic_message_grey"); 33 | 34 | /// 是否需要设置渐变色 35 | bool _isNeedSetAlpha = false; 36 | 37 | /// 用于单独控制搜索框的状态 38 | GlobalKey _mTitleKey = new GlobalKey(); 39 | 40 | /// 顶部卡片 41 | List topCards = List(); 42 | List bottomCards = List(); 43 | List topCardItems = [ 44 | HomeCard.DIET_SPORT_RECORD, 45 | HomeCard.WISDOM, 46 | HomeCard.HEALTH_HABITS, 47 | HomeCard.WEIGHT_RECORD, 48 | ]; 49 | 50 | /// 滑动监听 51 | ScrollController _controller = new ScrollController(); 52 | 53 | double percent = 0.0; 54 | 55 | @override 56 | void initState() { 57 | super.initState(); 58 | loadData(); 59 | //监听滚动事件,打印滚动位置 60 | _searchBarController.value.alpha = 0; 61 | _controller.addListener(() { 62 | if (_controller.offset < 0) { 63 | return; 64 | } 65 | if (_controller.offset < 100) { 66 | // 变化头部颜色 67 | _isNeedSetAlpha = true; 68 | double alpha = _controller.offset / 100; 69 | _searchBarController.value.alpha = (255 * alpha).toInt(); 70 | _searchBarController.value.appbarTitleColor = colorA8ACBC; 71 | _searchBarController.value.searchBarBg = Color(0x1FFFFFFF); 72 | _searchBarController.value.appbarLeftIcon = "ic_search_grey"; 73 | _searchBarController.value.appbarRightIcon = "ic_message_grey"; 74 | _mTitleKey.currentState.setState(() {}); // 刷新单个控件的状态,防止卡顿 75 | } else { 76 | /// 防止多次渲染 77 | if (_isNeedSetAlpha) { 78 | _searchBarController.value.appbarLeftIcon = "ic_search_white"; 79 | _searchBarController.value.appbarRightIcon = "ic_message_white"; 80 | _searchBarController.value.appbarTitleColor = Colors.white; 81 | _searchBarController.value.searchBarBg = color0EB794; 82 | _searchBarController.value.alpha = 255; 83 | _mTitleKey.currentState.setState(() {}); 84 | _isNeedSetAlpha = false; 85 | } 86 | } 87 | }); 88 | } 89 | 90 | @override 91 | Widget build(BuildContext context) { 92 | return Stack( 93 | children: [ 94 | EasyRefresh.custom( 95 | header: WallPaperHeader( 96 | wallPaperUrl: 97 | wallPaper != null ? wallPaper.welcomeImg.backImg : ""), 98 | scrollController: _controller, 99 | onRefresh: () async { 100 | NavigatorUtils.goWallPaper( 101 | context, wallPaper != null ? wallPaper.welcomeImg.backImg : ""); 102 | }, 103 | slivers: [ 104 | SliverToBoxAdapter( 105 | child: HomeHeaderWidget( 106 | /// 壁纸+减肥进度条Widget 107 | wallImg: 108 | wallPaper != null ? wallPaper.welcomeImg.backImgSmall : "", 109 | progressPercent: percent, 110 | )), 111 | SliverList( 112 | delegate: SliverChildBuilderDelegate( 113 | (BuildContext context, int index) { 114 | Widget widget; 115 | if (topCards[index].code == HomeCard.DIET_SPORT_RECORD) { 116 | /// 饮食运动记录 117 | widget = DietSportRecordWidget( 118 | topCard: topCards[index], 119 | ); 120 | } else if (topCards[index].code == HomeCard.WISDOM) { 121 | /// 智慧营养师 122 | widget = WisdomWidget( 123 | topCard: topCards[index], 124 | ); 125 | } else if (topCards[index].code == HomeCard.WEIGHT_RECORD) { 126 | /// 体重记录 127 | widget = WeightRecordWidget( 128 | topCard: topCards[index], 129 | ); 130 | } else if (topCards[index].code == HomeCard.HEALTH_HABITS) { 131 | widget = HealthHabitsWidget( 132 | iconUrl: "ic_home_habit", 133 | title: "健康习惯", 134 | ); 135 | } 136 | return widget; 137 | }, childCount: topCards.length)), 138 | createToolsCards() 139 | ], 140 | ), 141 | SearchBar( 142 | text: "搜索食物和热量", 143 | controller: _searchBarController, 144 | key: _mTitleKey, 145 | ) 146 | ], 147 | ); 148 | } 149 | 150 | /// 壁纸、底部定制tab数据 151 | void loadData() { 152 | Repository.loadAsset("home_health_tools", fileDir: "home").then((json) { 153 | HomeTools homeTools = HomeTools.fromJson(Repository.toMap(json)); 154 | topCards = homeTools.data 155 | .where((item) => item.visible && topCardItems.contains(item.code)) 156 | .toList(); 157 | bottomCards = homeTools.data 158 | .where((item) => item.visible && !topCardItems.contains(item.code)) 159 | .toList(); 160 | setState(() {}); 161 | }); 162 | Repository.loadAsset("home_wallpaper", fileDir: "home").then((json) { 163 | wallPaper = HomeWallPaper.fromJson(Repository.toMapForList(json)); 164 | setState(() {}); 165 | }); 166 | // 体重记录圆环动画 167 | Observable.just(3).delay(new Duration(milliseconds: 3 * 1000)).listen((_) { 168 | percent = 0.8; 169 | setState(() {}); 170 | }); 171 | } 172 | 173 | HomeWallPaper wallPaper; 174 | 175 | /// 底部健康工具列表 176 | Widget createToolsCards() { 177 | return SliverToBoxAdapter( 178 | child: Container( 179 | margin: EdgeInsets.only(top: 13, bottom: 30), 180 | child: CardView( 181 | margin: EdgeInsets.only( 182 | left: 17, 183 | right: 17, 184 | ), 185 | child: ListView.separated( 186 | shrinkWrap: true, 187 | separatorBuilder: (BuildContext context, int index) { 188 | return Container( 189 | height: 0.0, 190 | margin: EdgeInsetsDirectional.only(start: 16, end: 16), 191 | decoration: BoxDecoration( 192 | border: Border( 193 | bottom: 194 | Divider.createBorderSide(context, color: colorEEEFF3), 195 | ), 196 | ), 197 | ); 198 | }, 199 | padding: EdgeInsets.only(top: 0), 200 | physics: NeverScrollableScrollPhysics(), 201 | itemBuilder: (BuildContext context, int index) { 202 | Widget widget; 203 | if (bottomCards[index].code == HomeCard.EXERCISE) { 204 | // 运动训练 205 | widget = CommonCard( 206 | onPressed: () { 207 | ToastUtils.showToast(context, bottomCards[index].name); 208 | }, 209 | title: bottomCards[index].name, 210 | iconUrl: "ic_home_sport", 211 | subWidget: RichText( 212 | text: TextSpan(children: [ 213 | TextSpan( 214 | text: "35 ", style: TextStyles.get11Text_00CDA2()), 215 | TextSpan( 216 | text: "分钟", style: TextStyles.get11TextA8ACBC()), 217 | ]), 218 | )); 219 | } else if (bottomCards[index].code == HomeCard.MEASURE_RECORD) { 220 | // 围度记录 221 | widget = CommonCard( 222 | onPressed: () { 223 | ToastUtils.showToast(context, bottomCards[index].name); 224 | }, 225 | iconUrl: "ic_home_circumference", 226 | title: bottomCards[index].name); 227 | } else if (bottomCards[index].code == HomeCard.STEPS_RECORD) { 228 | // 步数记录 229 | widget = CommonCard( 230 | onPressed: () { 231 | ToastUtils.showToast(context, bottomCards[index].name); 232 | }, 233 | iconUrl: "ic_home_step", 234 | title: bottomCards[index].name); 235 | } else if (bottomCards[index].code == HomeCard.BABY) { 236 | // 宝宝记录 237 | widget = CommonCard( 238 | onPressed: () { 239 | ToastUtils.showToast(context, bottomCards[index].name); 240 | }, 241 | iconUrl: "ic_home_baby", 242 | title: bottomCards[index].name); 243 | } else if (bottomCards[index].code == HomeCard.DIET_PLAN) { 244 | // 饮食计划 245 | widget = CommonCard( 246 | onPressed: () { 247 | ToastUtils.showToast(context, bottomCards[index].name); 248 | }, 249 | iconUrl: "ic_home_food_plan", 250 | title: bottomCards[index].name); 251 | } else if (bottomCards[index].code == HomeCard.SLEEP_RECORD) { 252 | // 睡眠记录 253 | widget = CommonCard( 254 | onPressed: () { 255 | ToastUtils.showToast(context, bottomCards[index].name); 256 | }, 257 | iconUrl: "ic_home_sleep", 258 | title: bottomCards[index].name); 259 | } else if (bottomCards[index].code == HomeCard.PERIODS_RECORD) { 260 | // 经期记录 261 | widget = CommonCard( 262 | onPressed: () { 263 | ToastUtils.showToast(context, bottomCards[index].name); 264 | }, 265 | iconUrl: "ic_home_menstruation", 266 | title: bottomCards[index].name); 267 | } 268 | return widget; 269 | }, 270 | itemCount: bottomCards.length, 271 | ), 272 | ), 273 | ), 274 | ); 275 | } 276 | 277 | @override 278 | void dispose() { 279 | //为了避免内存泄露,需要调用_controller.dispose 280 | _controller.dispose(); 281 | _searchBarController.dispose(); 282 | super.dispose(); 283 | } 284 | } 285 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | analyzer: 5 | dependency: transitive 6 | description: 7 | name: analyzer 8 | url: "https://pub.flutter-io.cn" 9 | source: hosted 10 | version: "0.38.2" 11 | archive: 12 | dependency: transitive 13 | description: 14 | name: archive 15 | url: "https://pub.flutter-io.cn" 16 | source: hosted 17 | version: "2.0.11" 18 | args: 19 | dependency: transitive 20 | description: 21 | name: args 22 | url: "https://pub.flutter-io.cn" 23 | source: hosted 24 | version: "1.5.2" 25 | async: 26 | dependency: transitive 27 | description: 28 | name: async 29 | url: "https://pub.flutter-io.cn" 30 | source: hosted 31 | version: "2.4.0" 32 | auto_size: 33 | dependency: "direct main" 34 | description: 35 | path: "." 36 | ref: HEAD 37 | resolved-ref: "8fad57098f2852e7f220a6764e2eb1ff1f7dc5ad" 38 | url: "git://github.com/flutterchina/auto_size.git" 39 | source: git 40 | version: "0.0.1" 41 | banner_view: 42 | dependency: "direct main" 43 | description: 44 | name: banner_view 45 | url: "https://pub.flutter-io.cn" 46 | source: hosted 47 | version: "1.1.2" 48 | boolean_selector: 49 | dependency: transitive 50 | description: 51 | name: boolean_selector 52 | url: "https://pub.flutter-io.cn" 53 | source: hosted 54 | version: "1.0.5" 55 | build: 56 | dependency: transitive 57 | description: 58 | name: build 59 | url: "https://pub.flutter-io.cn" 60 | source: hosted 61 | version: "1.1.6" 62 | build_config: 63 | dependency: transitive 64 | description: 65 | name: build_config 66 | url: "https://pub.flutter-io.cn" 67 | source: hosted 68 | version: "0.4.1+1" 69 | build_daemon: 70 | dependency: transitive 71 | description: 72 | name: build_daemon 73 | url: "https://pub.flutter-io.cn" 74 | source: hosted 75 | version: "2.1.0" 76 | build_resolvers: 77 | dependency: transitive 78 | description: 79 | name: build_resolvers 80 | url: "https://pub.flutter-io.cn" 81 | source: hosted 82 | version: "1.0.7" 83 | build_runner: 84 | dependency: "direct dev" 85 | description: 86 | name: build_runner 87 | url: "https://pub.flutter-io.cn" 88 | source: hosted 89 | version: "1.7.0" 90 | build_runner_core: 91 | dependency: transitive 92 | description: 93 | name: build_runner_core 94 | url: "https://pub.flutter-io.cn" 95 | source: hosted 96 | version: "4.0.0" 97 | built_collection: 98 | dependency: transitive 99 | description: 100 | name: built_collection 101 | url: "https://pub.flutter-io.cn" 102 | source: hosted 103 | version: "4.2.2" 104 | built_value: 105 | dependency: transitive 106 | description: 107 | name: built_value 108 | url: "https://pub.flutter-io.cn" 109 | source: hosted 110 | version: "6.7.1" 111 | charcode: 112 | dependency: transitive 113 | description: 114 | name: charcode 115 | url: "https://pub.flutter-io.cn" 116 | source: hosted 117 | version: "1.1.2" 118 | checked_yaml: 119 | dependency: transitive 120 | description: 121 | name: checked_yaml 122 | url: "https://pub.flutter-io.cn" 123 | source: hosted 124 | version: "1.0.2" 125 | code_builder: 126 | dependency: transitive 127 | description: 128 | name: code_builder 129 | url: "https://pub.flutter-io.cn" 130 | source: hosted 131 | version: "3.2.0" 132 | collection: 133 | dependency: transitive 134 | description: 135 | name: collection 136 | url: "https://pub.flutter-io.cn" 137 | source: hosted 138 | version: "1.14.11" 139 | common_utils: 140 | dependency: transitive 141 | description: 142 | name: common_utils 143 | url: "https://pub.flutter-io.cn" 144 | source: hosted 145 | version: "1.1.3" 146 | convert: 147 | dependency: transitive 148 | description: 149 | name: convert 150 | url: "https://pub.flutter-io.cn" 151 | source: hosted 152 | version: "2.1.1" 153 | cookie_jar: 154 | dependency: transitive 155 | description: 156 | name: cookie_jar 157 | url: "https://pub.flutter-io.cn" 158 | source: hosted 159 | version: "1.0.1" 160 | crypto: 161 | dependency: "direct dev" 162 | description: 163 | name: crypto 164 | url: "https://pub.flutter-io.cn" 165 | source: hosted 166 | version: "2.1.3" 167 | csslib: 168 | dependency: transitive 169 | description: 170 | name: csslib 171 | url: "https://pub.flutter-io.cn" 172 | source: hosted 173 | version: "0.16.1" 174 | cupertino_icons: 175 | dependency: "direct main" 176 | description: 177 | name: cupertino_icons 178 | url: "https://pub.flutter-io.cn" 179 | source: hosted 180 | version: "0.1.2" 181 | dart_style: 182 | dependency: transitive 183 | description: 184 | name: dart_style 185 | url: "https://pub.flutter-io.cn" 186 | source: hosted 187 | version: "1.2.10" 188 | decimal: 189 | dependency: transitive 190 | description: 191 | name: decimal 192 | url: "https://pub.flutter-io.cn" 193 | source: hosted 194 | version: "0.3.5" 195 | dio: 196 | dependency: "direct main" 197 | description: 198 | name: dio 199 | url: "https://pub.flutter-io.cn" 200 | source: hosted 201 | version: "2.1.7" 202 | extended_image: 203 | dependency: "direct main" 204 | description: 205 | name: extended_image 206 | url: "https://pub.flutter-io.cn" 207 | source: hosted 208 | version: "0.6.8" 209 | extended_image_library: 210 | dependency: transitive 211 | description: 212 | name: extended_image_library 213 | url: "https://pub.flutter-io.cn" 214 | source: hosted 215 | version: "0.1.9" 216 | fixnum: 217 | dependency: transitive 218 | description: 219 | name: fixnum 220 | url: "https://pub.flutter-io.cn" 221 | source: hosted 222 | version: "0.10.9" 223 | fl_chart: 224 | dependency: "direct main" 225 | description: 226 | name: fl_chart 227 | url: "https://pub.flutter-io.cn" 228 | source: hosted 229 | version: "0.2.2" 230 | fluro: 231 | dependency: "direct main" 232 | description: 233 | name: fluro 234 | url: "https://pub.flutter-io.cn" 235 | source: hosted 236 | version: "1.5.1" 237 | flustars: 238 | dependency: "direct main" 239 | description: 240 | name: flustars 241 | url: "https://pub.flutter-io.cn" 242 | source: hosted 243 | version: "0.2.6+1" 244 | flutter: 245 | dependency: "direct main" 246 | description: flutter 247 | source: sdk 248 | version: "0.0.0" 249 | flutter_easyrefresh: 250 | dependency: "direct main" 251 | description: 252 | name: flutter_easyrefresh 253 | url: "https://pub.flutter-io.cn" 254 | source: hosted 255 | version: "2.0.4" 256 | flutter_test: 257 | dependency: "direct dev" 258 | description: flutter 259 | source: sdk 260 | version: "0.0.0" 261 | front_end: 262 | dependency: transitive 263 | description: 264 | name: front_end 265 | url: "https://pub.flutter-io.cn" 266 | source: hosted 267 | version: "0.1.24" 268 | glob: 269 | dependency: transitive 270 | description: 271 | name: glob 272 | url: "https://pub.flutter-io.cn" 273 | source: hosted 274 | version: "1.1.7" 275 | graphs: 276 | dependency: transitive 277 | description: 278 | name: graphs 279 | url: "https://pub.flutter-io.cn" 280 | source: hosted 281 | version: "0.2.0" 282 | html: 283 | dependency: transitive 284 | description: 285 | name: html 286 | url: "https://pub.flutter-io.cn" 287 | source: hosted 288 | version: "0.14.0+2" 289 | http: 290 | dependency: transitive 291 | description: 292 | name: http 293 | url: "https://pub.flutter-io.cn" 294 | source: hosted 295 | version: "0.12.0+2" 296 | http_client_helper: 297 | dependency: transitive 298 | description: 299 | name: http_client_helper 300 | url: "https://pub.flutter-io.cn" 301 | source: hosted 302 | version: "0.2.1" 303 | http_multi_server: 304 | dependency: transitive 305 | description: 306 | name: http_multi_server 307 | url: "https://pub.flutter-io.cn" 308 | source: hosted 309 | version: "2.1.0" 310 | http_parser: 311 | dependency: transitive 312 | description: 313 | name: http_parser 314 | url: "https://pub.flutter-io.cn" 315 | source: hosted 316 | version: "3.1.3" 317 | image: 318 | dependency: transitive 319 | description: 320 | name: image 321 | url: "https://pub.flutter-io.cn" 322 | source: hosted 323 | version: "2.1.4" 324 | io: 325 | dependency: transitive 326 | description: 327 | name: io 328 | url: "https://pub.flutter-io.cn" 329 | source: hosted 330 | version: "0.3.3" 331 | js: 332 | dependency: transitive 333 | description: 334 | name: js 335 | url: "https://pub.flutter-io.cn" 336 | source: hosted 337 | version: "0.6.1+1" 338 | json_annotation: 339 | dependency: "direct main" 340 | description: 341 | name: json_annotation 342 | url: "https://pub.flutter-io.cn" 343 | source: hosted 344 | version: "3.0.0" 345 | json_serializable: 346 | dependency: "direct dev" 347 | description: 348 | name: json_serializable 349 | url: "https://pub.flutter-io.cn" 350 | source: hosted 351 | version: "3.2.2" 352 | kernel: 353 | dependency: transitive 354 | description: 355 | name: kernel 356 | url: "https://pub.flutter-io.cn" 357 | source: hosted 358 | version: "0.3.24" 359 | logging: 360 | dependency: transitive 361 | description: 362 | name: logging 363 | url: "https://pub.flutter-io.cn" 364 | source: hosted 365 | version: "0.11.3+2" 366 | matcher: 367 | dependency: transitive 368 | description: 369 | name: matcher 370 | url: "https://pub.flutter-io.cn" 371 | source: hosted 372 | version: "0.12.6" 373 | meta: 374 | dependency: transitive 375 | description: 376 | name: meta 377 | url: "https://pub.flutter-io.cn" 378 | source: hosted 379 | version: "1.1.8" 380 | mime: 381 | dependency: transitive 382 | description: 383 | name: mime 384 | url: "https://pub.flutter-io.cn" 385 | source: hosted 386 | version: "0.9.6+3" 387 | package_config: 388 | dependency: transitive 389 | description: 390 | name: package_config 391 | url: "https://pub.flutter-io.cn" 392 | source: hosted 393 | version: "1.1.0" 394 | package_resolver: 395 | dependency: transitive 396 | description: 397 | name: package_resolver 398 | url: "https://pub.flutter-io.cn" 399 | source: hosted 400 | version: "1.0.10" 401 | path: 402 | dependency: transitive 403 | description: 404 | name: path 405 | url: "https://pub.flutter-io.cn" 406 | source: hosted 407 | version: "1.6.4" 408 | path_provider: 409 | dependency: transitive 410 | description: 411 | name: path_provider 412 | url: "https://pub.flutter-io.cn" 413 | source: hosted 414 | version: "1.3.0" 415 | pedantic: 416 | dependency: transitive 417 | description: 418 | name: pedantic 419 | url: "https://pub.flutter-io.cn" 420 | source: hosted 421 | version: "1.8.0+1" 422 | percent_indicator: 423 | dependency: "direct main" 424 | description: 425 | name: percent_indicator 426 | url: "https://pub.flutter-io.cn" 427 | source: hosted 428 | version: "2.1.1+1" 429 | petitparser: 430 | dependency: transitive 431 | description: 432 | name: petitparser 433 | url: "https://pub.flutter-io.cn" 434 | source: hosted 435 | version: "2.4.0" 436 | platform: 437 | dependency: transitive 438 | description: 439 | name: platform 440 | url: "https://pub.flutter-io.cn" 441 | source: hosted 442 | version: "2.2.1" 443 | pool: 444 | dependency: transitive 445 | description: 446 | name: pool 447 | url: "https://pub.flutter-io.cn" 448 | source: hosted 449 | version: "1.4.0" 450 | pub_semver: 451 | dependency: transitive 452 | description: 453 | name: pub_semver 454 | url: "https://pub.flutter-io.cn" 455 | source: hosted 456 | version: "1.4.2" 457 | pubspec_parse: 458 | dependency: transitive 459 | description: 460 | name: pubspec_parse 461 | url: "https://pub.flutter-io.cn" 462 | source: hosted 463 | version: "0.1.5" 464 | quiver: 465 | dependency: transitive 466 | description: 467 | name: quiver 468 | url: "https://pub.flutter-io.cn" 469 | source: hosted 470 | version: "2.0.5" 471 | rational: 472 | dependency: transitive 473 | description: 474 | name: rational 475 | url: "https://pub.flutter-io.cn" 476 | source: hosted 477 | version: "0.3.6" 478 | rxdart: 479 | dependency: "direct dev" 480 | description: 481 | name: rxdart 482 | url: "https://pub.flutter-io.cn" 483 | source: hosted 484 | version: "0.22.2" 485 | shared_preferences: 486 | dependency: transitive 487 | description: 488 | name: shared_preferences 489 | url: "https://pub.flutter-io.cn" 490 | source: hosted 491 | version: "0.5.3+4" 492 | shelf: 493 | dependency: transitive 494 | description: 495 | name: shelf 496 | url: "https://pub.flutter-io.cn" 497 | source: hosted 498 | version: "0.7.5" 499 | shelf_web_socket: 500 | dependency: transitive 501 | description: 502 | name: shelf_web_socket 503 | url: "https://pub.flutter-io.cn" 504 | source: hosted 505 | version: "0.2.3" 506 | sky_engine: 507 | dependency: transitive 508 | description: flutter 509 | source: sdk 510 | version: "0.0.99" 511 | source_gen: 512 | dependency: transitive 513 | description: 514 | name: source_gen 515 | url: "https://pub.flutter-io.cn" 516 | source: hosted 517 | version: "0.9.4+4" 518 | source_span: 519 | dependency: transitive 520 | description: 521 | name: source_span 522 | url: "https://pub.flutter-io.cn" 523 | source: hosted 524 | version: "1.5.5" 525 | stack_trace: 526 | dependency: transitive 527 | description: 528 | name: stack_trace 529 | url: "https://pub.flutter-io.cn" 530 | source: hosted 531 | version: "1.9.3" 532 | stream_channel: 533 | dependency: transitive 534 | description: 535 | name: stream_channel 536 | url: "https://pub.flutter-io.cn" 537 | source: hosted 538 | version: "2.0.0" 539 | stream_transform: 540 | dependency: transitive 541 | description: 542 | name: stream_transform 543 | url: "https://pub.flutter-io.cn" 544 | source: hosted 545 | version: "0.0.19" 546 | string_scanner: 547 | dependency: transitive 548 | description: 549 | name: string_scanner 550 | url: "https://pub.flutter-io.cn" 551 | source: hosted 552 | version: "1.0.5" 553 | synchronized: 554 | dependency: "direct dev" 555 | description: 556 | name: synchronized 557 | url: "https://pub.flutter-io.cn" 558 | source: hosted 559 | version: "2.1.0+1" 560 | term_glyph: 561 | dependency: transitive 562 | description: 563 | name: term_glyph 564 | url: "https://pub.flutter-io.cn" 565 | source: hosted 566 | version: "1.1.0" 567 | test_api: 568 | dependency: transitive 569 | description: 570 | name: test_api 571 | url: "https://pub.flutter-io.cn" 572 | source: hosted 573 | version: "0.2.11" 574 | timing: 575 | dependency: transitive 576 | description: 577 | name: timing 578 | url: "https://pub.flutter-io.cn" 579 | source: hosted 580 | version: "0.1.1+2" 581 | toast: 582 | dependency: "direct main" 583 | description: 584 | name: toast 585 | url: "https://pub.flutter-io.cn" 586 | source: hosted 587 | version: "0.1.5" 588 | typed_data: 589 | dependency: transitive 590 | description: 591 | name: typed_data 592 | url: "https://pub.flutter-io.cn" 593 | source: hosted 594 | version: "1.1.6" 595 | vector_math: 596 | dependency: transitive 597 | description: 598 | name: vector_math 599 | url: "https://pub.flutter-io.cn" 600 | source: hosted 601 | version: "2.0.8" 602 | watcher: 603 | dependency: transitive 604 | description: 605 | name: watcher 606 | url: "https://pub.flutter-io.cn" 607 | source: hosted 608 | version: "0.9.7+12" 609 | web_socket_channel: 610 | dependency: transitive 611 | description: 612 | name: web_socket_channel 613 | url: "https://pub.flutter-io.cn" 614 | source: hosted 615 | version: "1.0.15" 616 | webview_flutter: 617 | dependency: "direct main" 618 | description: 619 | name: webview_flutter 620 | url: "https://pub.flutter-io.cn" 621 | source: hosted 622 | version: "0.3.14+1" 623 | xml: 624 | dependency: transitive 625 | description: 626 | name: xml 627 | url: "https://pub.flutter-io.cn" 628 | source: hosted 629 | version: "3.5.0" 630 | yaml: 631 | dependency: transitive 632 | description: 633 | name: yaml 634 | url: "https://pub.flutter-io.cn" 635 | source: hosted 636 | version: "2.1.16" 637 | sdks: 638 | dart: ">=2.4.0 <3.0.0" 639 | flutter: ">=1.5.0 <2.0.0" 640 | --------------------------------------------------------------------------------