├── android ├── .gradle │ ├── 4.10.2 │ │ ├── gc.properties │ │ ├── fileChanges │ │ │ └── last-build.bin │ │ ├── fileHashes │ │ │ ├── fileHashes.bin │ │ │ ├── fileHashes.lock │ │ │ └── resourceHashesCache.bin │ │ ├── fileContent │ │ │ └── fileContent.lock │ │ ├── javaCompile │ │ │ ├── classAnalysis.bin │ │ │ ├── jarAnalysis.bin │ │ │ ├── javaCompile.lock │ │ │ └── taskHistory.bin │ │ └── taskHistory │ │ │ ├── taskHistory.bin │ │ │ └── taskHistory.lock │ ├── vcs-1 │ │ └── gc.properties │ └── buildOutputCleanup │ │ ├── cache.properties │ │ ├── outputFiles.bin │ │ └── buildOutputCleanup.lock ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.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 │ │ │ ├── gen │ │ │ │ └── com │ │ │ │ │ └── jingchuan │ │ │ │ │ └── imopei │ │ │ │ │ └── flutter_cli_project │ │ │ │ │ ├── R.java │ │ │ │ │ ├── Manifest.java │ │ │ │ │ └── BuildConfig.java │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── jingchuan │ │ │ │ │ └── imopei │ │ │ │ │ └── front_imopei_pda │ │ │ │ │ └── MainActivity.kt │ │ │ ├── main.iml │ │ │ ├── java │ │ │ │ └── io │ │ │ │ │ └── flutter │ │ │ │ │ └── plugins │ │ │ │ │ └── GeneratedPluginRegistrant.java │ │ │ └── AndroidManifest.xml │ │ ├── debug │ │ │ ├── gen │ │ │ │ └── com │ │ │ │ │ └── jingchuan │ │ │ │ │ └── imopei │ │ │ │ │ └── flutter_cli_project │ │ │ │ │ ├── R.java │ │ │ │ │ ├── Manifest.java │ │ │ │ │ └── BuildConfig.java │ │ │ ├── AndroidManifest.xml │ │ │ └── debug.iml │ │ └── profile │ │ │ ├── gen │ │ │ └── com │ │ │ │ └── jingchuan │ │ │ │ └── imopei │ │ │ │ └── flutter_cli_project │ │ │ │ ├── R.java │ │ │ │ ├── Manifest.java │ │ │ │ └── BuildConfig.java │ │ │ ├── AndroidManifest.xml │ │ │ └── profile.iml │ └── build.gradle ├── local.properties ├── settings.gradle ├── build.gradle ├── front_imopei_pda_android.iml ├── gradlew.bat └── gradlew ├── .idea ├── .gitignore ├── misc.xml ├── libraries │ ├── gradle_wrapper.xml │ ├── Flutter_Plugins.xml │ ├── Dart_SDK.xml │ └── Dart_Packages.xml ├── $PRODUCT_WORKSPACE_FILE$ └── modules.xml ├── .gitignore ├── ios ├── Runner │ ├── Runner-Bridging-Header.h │ ├── Assets.xcassets │ │ ├── LaunchImage.imageset │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ ├── README.md │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ └── Contents.json │ ├── GeneratedPluginRegistrant.h │ ├── AppDelegate.swift │ ├── GeneratedPluginRegistrant.m │ ├── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard │ └── Info.plist ├── Flutter │ ├── Debug.xcconfig │ ├── Release.xcconfig │ ├── Generated.xcconfig │ ├── flutter_export_environment.sh │ └── AppFrameworkInfo.plist ├── Runner.xcworkspace │ └── contents.xcworkspacedata ├── Runner.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ ├── xcshareddata │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ └── project.pbxproj └── Podfile ├── lib ├── mock │ ├── mock_data │ │ ├── mock_data.dart │ │ └── user_data.dart │ └── mock_holder.dart ├── services │ ├── check_bill │ │ ├── check_bill_routers.dart │ │ └── check_bill_index.dart │ └── deliver_bill_pick │ │ ├── deliver_bill_routers.dart │ │ ├── audit_index.dart │ │ ├── pick_index.dart │ │ └── loading_index.dart ├── infrastructure │ ├── base_model │ │ ├── PbResultDto.pbenum.dart │ │ ├── google │ │ │ └── protobuf │ │ │ │ ├── any.pbenum.dart │ │ │ │ ├── any.pbserver.dart │ │ │ │ ├── any.pbjson.dart │ │ │ │ └── any.pb.dart │ │ ├── PbResultDto.pbserver.dart │ │ ├── PbResultDto.pbjson.dart │ │ └── PbResultDto.pb.dart │ ├── toast_tool.dart │ ├── ioc_container.dart │ ├── context_util.dart │ ├── profiles_loader.dart │ ├── dialog_util.dart │ ├── i18n_box.dart │ ├── local_data_cache.dart │ └── net_tool_box.dart ├── login │ ├── dto │ │ ├── UserAuthenticateDto.pbenum.dart │ │ ├── UserAuthenticateDto.pbserver.dart │ │ ├── UserAuthenticateDto.pbjson.dart │ │ └── UserAuthenticateDto.pb.dart │ ├── login_bloc.dart │ └── login_page.dart ├── main_app │ ├── common_logo.dart │ ├── notfound_page.dart │ ├── system_bloc.dart │ ├── routes.dart │ └── authenticate_bloc.dart ├── personal │ ├── themes.dart │ ├── index.dart │ ├── theme_setting.dart │ └── dashboard_page.dart ├── components │ ├── profile_tile.dart │ └── common_scaffold.dart ├── splash_page.dart ├── repository │ └── user_repository.dart └── main.dart ├── md_assets ├── hero.gif ├── i18n_support.gif ├── permission_1.jpeg ├── permission_2.jpeg └── theme_support.gif ├── assets ├── imgs │ └── logo.jpeg ├── permission_1.jpeg ├── permission_2.jpeg ├── fonts │ ├── Quicksand_Bold.otf │ ├── Quicksand_Book.otf │ ├── Quicksand_Light.otf │ └── Quicksand-Medium.ttf ├── profile-config.json └── lang │ ├── lang_zh-CN.json │ └── lang_en-US.json ├── .flutter-plugins-dependencies ├── protol ├── PbResultDto.proto └── UserAuthenticateDto.proto ├── .flutter-plugins ├── flutter_cli_project.iml ├── pubspec.yaml ├── test ├── widget_test.dart └── net_tool_box_test.dart ├── README.md ├── .packages └── pubspec.lock /android/.gradle/4.10.2/gc.properties: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /android/.gradle/vcs-1/gc.properties: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /android/.gradle/4.10.2/fileChanges/last-build.bin: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Project exclude paths 2 | /.dart_tool/ 3 | /build/ -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" -------------------------------------------------------------------------------- /lib/mock/mock_data/mock_data.dart: -------------------------------------------------------------------------------- 1 | library mock_data; 2 | 3 | export 'user_data.dart'; 4 | -------------------------------------------------------------------------------- /md_assets/hero.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/md_assets/hero.gif -------------------------------------------------------------------------------- /assets/imgs/logo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/assets/imgs/logo.jpeg -------------------------------------------------------------------------------- /android/.gradle/buildOutputCleanup/cache.properties: -------------------------------------------------------------------------------- 1 | #Thu Apr 23 16:30:50 CST 2020 2 | gradle.version=4.10.2 3 | -------------------------------------------------------------------------------- /assets/permission_1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/assets/permission_1.jpeg -------------------------------------------------------------------------------- /assets/permission_2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/assets/permission_2.jpeg -------------------------------------------------------------------------------- /md_assets/i18n_support.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/md_assets/i18n_support.gif -------------------------------------------------------------------------------- /md_assets/permission_1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/md_assets/permission_1.jpeg -------------------------------------------------------------------------------- /md_assets/permission_2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/md_assets/permission_2.jpeg -------------------------------------------------------------------------------- /md_assets/theme_support.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/md_assets/theme_support.gif -------------------------------------------------------------------------------- /assets/fonts/Quicksand_Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/assets/fonts/Quicksand_Bold.otf -------------------------------------------------------------------------------- /assets/fonts/Quicksand_Book.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/assets/fonts/Quicksand_Book.otf -------------------------------------------------------------------------------- /assets/fonts/Quicksand_Light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/assets/fonts/Quicksand_Light.otf -------------------------------------------------------------------------------- /assets/fonts/Quicksand-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/assets/fonts/Quicksand-Medium.ttf -------------------------------------------------------------------------------- /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.enableJetifier=true 3 | android.useAndroidX=true 4 | android.enableR8=true 5 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /lib/services/check_bill/check_bill_routers.dart: -------------------------------------------------------------------------------- 1 | class CheckBillIndexConst { 2 | 3 | static const String checkBillIndexPath = '/checkBillIndex'; 4 | 5 | } -------------------------------------------------------------------------------- /android/.gradle/4.10.2/fileHashes/fileHashes.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/android/.gradle/4.10.2/fileHashes/fileHashes.bin -------------------------------------------------------------------------------- /android/.gradle/4.10.2/fileHashes/fileHashes.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/android/.gradle/4.10.2/fileHashes/fileHashes.lock -------------------------------------------------------------------------------- /android/.gradle/4.10.2/fileContent/fileContent.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/android/.gradle/4.10.2/fileContent/fileContent.lock -------------------------------------------------------------------------------- /android/.gradle/4.10.2/javaCompile/classAnalysis.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/android/.gradle/4.10.2/javaCompile/classAnalysis.bin -------------------------------------------------------------------------------- /android/.gradle/4.10.2/javaCompile/jarAnalysis.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/android/.gradle/4.10.2/javaCompile/jarAnalysis.bin -------------------------------------------------------------------------------- /android/.gradle/4.10.2/javaCompile/javaCompile.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/android/.gradle/4.10.2/javaCompile/javaCompile.lock -------------------------------------------------------------------------------- /android/.gradle/4.10.2/javaCompile/taskHistory.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/android/.gradle/4.10.2/javaCompile/taskHistory.bin -------------------------------------------------------------------------------- /android/.gradle/4.10.2/taskHistory/taskHistory.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/android/.gradle/4.10.2/taskHistory/taskHistory.bin -------------------------------------------------------------------------------- /android/.gradle/4.10.2/taskHistory/taskHistory.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/android/.gradle/4.10.2/taskHistory/taskHistory.lock -------------------------------------------------------------------------------- /android/.gradle/buildOutputCleanup/outputFiles.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/android/.gradle/buildOutputCleanup/outputFiles.bin -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/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/WeidanLi/flutter_cli_project/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/WeidanLi/flutter_cli_project/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/WeidanLi/flutter_cli_project/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/.gradle/4.10.2/fileHashes/resourceHashesCache.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/android/.gradle/4.10.2/fileHashes/resourceHashesCache.bin -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/.gradle/buildOutputCleanup/buildOutputCleanup.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeidanLi/flutter_cli_project/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /android/local.properties: -------------------------------------------------------------------------------- 1 | sdk.dir=/Users/liweidan/Develop/middleware/android-sdk-macosx 2 | flutter.sdk=/Users/liweidan/Develop/middleware/flutter 3 | flutter.buildMode=debug 4 | flutter.versionName=1.0.0 5 | flutter.versionCode=1 -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /assets/profile-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile.active": "mock", 3 | "baseURL.dev": "http://192.168.1.152:8002/", 4 | "baseURL.uat": "https://api.xxx.com/", 5 | "baseURL.prod": "https://api.xxx.com/", 6 | "baseURL.mock": "" 7 | } -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/app/src/debug/gen/com/jingchuan/imopei/flutter_cli_project/R.java: -------------------------------------------------------------------------------- 1 | /*___Generated_by_IDEA___*/ 2 | 3 | package com.jingchuan.imopei.flutter_cli_project; 4 | 5 | /* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */ 6 | public final class R { 7 | } -------------------------------------------------------------------------------- /android/app/src/main/gen/com/jingchuan/imopei/flutter_cli_project/R.java: -------------------------------------------------------------------------------- 1 | /*___Generated_by_IDEA___*/ 2 | 3 | package com.jingchuan.imopei.flutter_cli_project; 4 | 5 | /* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */ 6 | public final class R { 7 | } -------------------------------------------------------------------------------- /android/app/src/profile/gen/com/jingchuan/imopei/flutter_cli_project/R.java: -------------------------------------------------------------------------------- 1 | /*___Generated_by_IDEA___*/ 2 | 3 | package com.jingchuan.imopei.flutter_cli_project; 4 | 5 | /* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */ 6 | public final class R { 7 | } -------------------------------------------------------------------------------- /.idea/libraries/gradle_wrapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /lib/infrastructure/base_model/PbResultDto.pbenum.dart: -------------------------------------------------------------------------------- 1 | /// 2 | // Generated code. Do not modify. 3 | // source: PbResultDto.proto 4 | // 5 | // @dart = 2.3 6 | // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type 7 | 8 | -------------------------------------------------------------------------------- /lib/login/dto/UserAuthenticateDto.pbenum.dart: -------------------------------------------------------------------------------- 1 | /// 2 | // Generated code. Do not modify. 3 | // source: UserAuthenticateDto.proto 4 | // 5 | // @dart = 2.3 6 | // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/gen/com/jingchuan/imopei/flutter_cli_project/Manifest.java: -------------------------------------------------------------------------------- 1 | /*___Generated_by_IDEA___*/ 2 | 3 | package com.jingchuan.imopei.flutter_cli_project; 4 | 5 | /* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */ 6 | public final class Manifest { 7 | } -------------------------------------------------------------------------------- /lib/services/deliver_bill_pick/deliver_bill_routers.dart: -------------------------------------------------------------------------------- 1 | class DeliverBillPickIndexConst { 2 | 3 | static const String pickIndexPath = '/deliverBillIndex'; 4 | static const String loadingIndexPath = '/deliverBillLoadingIndex'; 5 | static const String auditIndexPath = '/deliverBillAuditIndex'; 6 | 7 | } -------------------------------------------------------------------------------- /android/app/src/debug/gen/com/jingchuan/imopei/flutter_cli_project/Manifest.java: -------------------------------------------------------------------------------- 1 | /*___Generated_by_IDEA___*/ 2 | 3 | package com.jingchuan.imopei.flutter_cli_project; 4 | 5 | /* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */ 6 | public final class Manifest { 7 | } -------------------------------------------------------------------------------- /android/app/src/profile/gen/com/jingchuan/imopei/flutter_cli_project/Manifest.java: -------------------------------------------------------------------------------- 1 | /*___Generated_by_IDEA___*/ 2 | 3 | package com.jingchuan.imopei.flutter_cli_project; 4 | 5 | /* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */ 6 | public final class Manifest { 7 | } -------------------------------------------------------------------------------- /lib/infrastructure/base_model/google/protobuf/any.pbenum.dart: -------------------------------------------------------------------------------- 1 | /// 2 | // Generated code. Do not modify. 3 | // source: google/protobuf/any.proto 4 | // 5 | // @dart = 2.3 6 | // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type 7 | 8 | -------------------------------------------------------------------------------- /lib/infrastructure/base_model/PbResultDto.pbserver.dart: -------------------------------------------------------------------------------- 1 | /// 2 | // Generated code. Do not modify. 3 | // source: PbResultDto.proto 4 | // 5 | // @dart = 2.3 6 | // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type 7 | 8 | export 'PbResultDto.pb.dart'; 9 | 10 | -------------------------------------------------------------------------------- /lib/infrastructure/base_model/google/protobuf/any.pbserver.dart: -------------------------------------------------------------------------------- 1 | /// 2 | // Generated code. Do not modify. 3 | // source: google/protobuf/any.proto 4 | // 5 | // @dart = 2.3 6 | // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type 7 | 8 | export 'any.pb.dart'; 9 | 10 | -------------------------------------------------------------------------------- /lib/login/dto/UserAuthenticateDto.pbserver.dart: -------------------------------------------------------------------------------- 1 | /// 2 | // Generated code. Do not modify. 3 | // source: UserAuthenticateDto.proto 4 | // 5 | // @dart = 2.3 6 | // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type 7 | 8 | export 'UserAuthenticateDto.pb.dart'; 9 | 10 | -------------------------------------------------------------------------------- /.flutter-plugins-dependencies: -------------------------------------------------------------------------------- 1 | {"_info":"// This is a generated file; do not edit or check into version control.","dependencyGraph":[{"name":"fluttertoast","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]}]} -------------------------------------------------------------------------------- /android/app/src/debug/gen/com/jingchuan/imopei/flutter_cli_project/BuildConfig.java: -------------------------------------------------------------------------------- 1 | /*___Generated_by_IDEA___*/ 2 | 3 | package com.jingchuan.imopei.flutter_cli_project; 4 | 5 | /* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */ 6 | public final class BuildConfig { 7 | public final static boolean DEBUG = Boolean.parseBoolean(null); 8 | } -------------------------------------------------------------------------------- /android/app/src/main/gen/com/jingchuan/imopei/flutter_cli_project/BuildConfig.java: -------------------------------------------------------------------------------- 1 | /*___Generated_by_IDEA___*/ 2 | 3 | package com.jingchuan.imopei.flutter_cli_project; 4 | 5 | /* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */ 6 | public final class BuildConfig { 7 | public final static boolean DEBUG = Boolean.parseBoolean(null); 8 | } -------------------------------------------------------------------------------- /android/app/src/profile/gen/com/jingchuan/imopei/flutter_cli_project/BuildConfig.java: -------------------------------------------------------------------------------- 1 | /*___Generated_by_IDEA___*/ 2 | 3 | package com.jingchuan.imopei.flutter_cli_project; 4 | 5 | /* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */ 6 | public final class BuildConfig { 7 | public final static boolean DEBUG = Boolean.parseBoolean(null); 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/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /lib/main_app/common_logo.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/src/widgets/framework.dart'; 3 | import 'package:flutter_cli_project/infrastructure/context_util.dart'; 4 | 5 | class CommonLogo extends PageStateLess { 6 | @override 7 | Widget build0(BuildContext context) { 8 | return SizedBox( 9 | width: 140.0, 10 | child: Image.asset('assets/imgs/logo.jpeg'), 11 | ); 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /protol/PbResultDto.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | import "google/protobuf/any.proto"; 3 | 4 | option java_package = "com.jingchuan.imopei.dto.proto"; 5 | option java_multiple_files = true; 6 | 7 | message PbResultDto { 8 | bool success = 1; 9 | string message = 2; 10 | string code = 3; 11 | google.protobuf.Any data = 4; 12 | map extra = 5; 13 | } 14 | 15 | message ExtraMap { 16 | map extra = 1; 17 | } -------------------------------------------------------------------------------- /protol/UserAuthenticateDto.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "com.jingchuan.imopei.dto.warehousingpda.UserAuthenticateDto"; 4 | option java_outer_classname = "UserAuthenticateDtoPB"; 5 | 6 | message UserAuthenticateReqDto { 7 | 8 | string userName = 1; 9 | string password = 2; 10 | 11 | } 12 | 13 | message UserAuthenticateRespDto { 14 | 15 | string token = 1; 16 | repeated string resourceCodes = 2; 17 | 18 | } 19 | 20 | -------------------------------------------------------------------------------- /ios/Runner/GeneratedPluginRegistrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | #ifndef GeneratedPluginRegistrant_h 6 | #define GeneratedPluginRegistrant_h 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface GeneratedPluginRegistrant : NSObject 13 | + (void)registerWithRegistry:(NSObject*)registry; 14 | @end 15 | 16 | NS_ASSUME_NONNULL_END 17 | #endif /* GeneratedPluginRegistrant_h */ 18 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/jingchuan/imopei/front_imopei_pda/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.jingchuan.imopei.flutter_cli_project 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/Flutter/Generated.xcconfig: -------------------------------------------------------------------------------- 1 | // This is a generated file; do not edit or check into version control. 2 | FLUTTER_ROOT=/Users/liweidan/Develop/middleware/flutter 3 | FLUTTER_APPLICATION_PATH=/Users/liweidan/Develop/code/imopei-project/flutter_cli_project 4 | FLUTTER_TARGET=lib/main.dart 5 | FLUTTER_BUILD_DIR=build 6 | SYMROOT=${SOURCE_ROOT}/../build/ios 7 | FLUTTER_FRAMEWORK_DIR=/Users/liweidan/Develop/middleware/flutter/bin/cache/artifacts/engine/ios 8 | FLUTTER_BUILD_NAME=1.0.0 9 | FLUTTER_BUILD_NUMBER=1 10 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /lib/infrastructure/base_model/google/protobuf/any.pbjson.dart: -------------------------------------------------------------------------------- 1 | /// 2 | // Generated code. Do not modify. 3 | // source: google/protobuf/any.proto 4 | // 5 | // @dart = 2.3 6 | // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type 7 | 8 | const Any$json = const { 9 | '1': 'Any', 10 | '2': const [ 11 | const {'1': 'type_url', '3': 1, '4': 1, '5': 9, '10': 'typeUrl'}, 12 | const {'1': 'value', '3': 2, '4': 1, '5': 12, '10': 'value'}, 13 | ], 14 | }; 15 | 16 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.idea/$PRODUCT_WORKSPACE_FILE$: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 1.8 8 | 9 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.flutter-plugins: -------------------------------------------------------------------------------- 1 | # This is a generated file; do not edit or check into version control. 2 | fluttertoast=/Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/fluttertoast-3.1.3/ 3 | shared_preferences=/Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/shared_preferences-0.5.7+1/ 4 | shared_preferences_macos=/Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/shared_preferences_macos-0.0.1+8/ 5 | shared_preferences_web=/Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/shared_preferences_web-0.1.2+5/ 6 | -------------------------------------------------------------------------------- /ios/Flutter/flutter_export_environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This is a generated file; do not edit or check into version control. 3 | export "FLUTTER_ROOT=/Users/liweidan/Develop/middleware/flutter" 4 | export "FLUTTER_APPLICATION_PATH=/Users/liweidan/Develop/code/imopei-project/flutter_cli_project" 5 | export "FLUTTER_TARGET=lib/main.dart" 6 | export "FLUTTER_BUILD_DIR=build" 7 | export "SYMROOT=${SOURCE_ROOT}/../build/ios" 8 | export "FLUTTER_FRAMEWORK_DIR=/Users/liweidan/Develop/middleware/flutter/bin/cache/artifacts/engine/ios" 9 | export "FLUTTER_BUILD_NAME=1.0.0" 10 | export "FLUTTER_BUILD_NUMBER=1" 11 | -------------------------------------------------------------------------------- /.idea/libraries/Flutter_Plugins.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /lib/personal/themes.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | final QUICKSAND_FONT_NAME = 'Quicksand'; 4 | 5 | class Themes { 6 | 7 | static final ThemeData kIOSTheme = ThemeData( 8 | primarySwatch: Colors.orange, 9 | primaryColor: Colors.grey[100], 10 | accentColor: Colors.green, 11 | primaryColorBrightness: Brightness.light, 12 | fontFamily: QUICKSAND_FONT_NAME, 13 | backgroundColor: Colors.white 14 | ); 15 | 16 | static final ThemeData blackTheme = ThemeData( 17 | primarySwatch: Colors.grey, 18 | primaryColor: Colors.black, 19 | fontFamily: QUICKSAND_FONT_NAME, 20 | backgroundColor: Colors.white, 21 | ); 22 | 23 | } -------------------------------------------------------------------------------- /android/app/src/debug/debug.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /android/app/src/profile/profile.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /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 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /lib/infrastructure/toast_tool.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_bloc/flutter_bloc.dart'; 2 | import 'package:fluttertoast/fluttertoast.dart'; 3 | import 'package:flutter_cli_project/infrastructure/context_util.dart'; 4 | import 'package:flutter_cli_project/main_app/system_bloc.dart'; 5 | 6 | class ToastTool { 7 | 8 | static short(String message) { 9 | Fluttertoast.showToast( 10 | msg: message, 11 | toastLength: Toast.LENGTH_SHORT, 12 | gravity: ToastGravity.CENTER, 13 | timeInSecForIos: 3 14 | ); 15 | } 16 | 17 | static shortOfKey(String key) { 18 | var systemBloc = BlocProvider.of(CurrentPageContext.get()); 19 | var text = systemBloc.state.i18nBox.getText(key); 20 | ToastTool.short(text); 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /android/app/src/main/main.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /lib/services/deliver_bill_pick/audit_index.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_cli_project/components/common_scaffold.dart'; 3 | import 'package:flutter_cli_project/infrastructure/context_util.dart'; 4 | import 'package:flutter_cli_project/infrastructure/i18n_box.dart'; 5 | 6 | import 'deliver_bill_routers.dart'; 7 | 8 | class LoadingIndex extends Page { 9 | 10 | LoadingIndex() : super(DeliverBillPickIndexConst.loadingIndexPath); 11 | 12 | @override 13 | Widget build0(BuildContext context) { 14 | return CommonScaffold( 15 | title: I18nBox.getTextOfContext('index.deliver.bill.audit.pageTitle'), 16 | showBackBtn: true, 17 | body: Center( 18 | child: Text('我的审核任务'), 19 | ), 20 | ); 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /flutter_cli_project.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /lib/services/deliver_bill_pick/pick_index.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/src/widgets/framework.dart'; 3 | import 'package:flutter_cli_project/components/common_scaffold.dart'; 4 | import 'package:flutter_cli_project/infrastructure/context_util.dart'; 5 | import 'package:flutter_cli_project/infrastructure/i18n_box.dart'; 6 | 7 | import 'deliver_bill_routers.dart'; 8 | 9 | class PickIndex extends Page { 10 | 11 | PickIndex() : super(DeliverBillPickIndexConst.pickIndexPath); 12 | 13 | @override 14 | Widget build0(BuildContext context) { 15 | return CommonScaffold( 16 | title: I18nBox.getTextOfContext('index.deliver.bill.pick.pageTitle'), 17 | showBackBtn: true, 18 | body: Center( 19 | child: Text('我的拣货单'), 20 | ), 21 | ); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /lib/services/check_bill/check_bill_index.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/src/widgets/framework.dart'; 3 | import 'package:flutter_cli_project/components/common_scaffold.dart'; 4 | import 'package:flutter_cli_project/infrastructure/context_util.dart'; 5 | import 'package:flutter_cli_project/infrastructure/i18n_box.dart'; 6 | 7 | import 'check_bill_routers.dart'; 8 | 9 | class CheckBillIndex extends Page { 10 | 11 | CheckBillIndex() : super(CheckBillIndexConst.checkBillIndexPath); 12 | 13 | @override 14 | Widget build0(BuildContext context) { 15 | return CommonScaffold( 16 | title: I18nBox.getTextOfContext('index.check.bill.check.pageTitle'), 17 | showBackBtn: true, 18 | body: Center( 19 | child: Text('我的盘点单页'), 20 | ), 21 | ); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /lib/services/deliver_bill_pick/loading_index.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/src/widgets/framework.dart'; 3 | import 'package:flutter_cli_project/components/common_scaffold.dart'; 4 | import 'package:flutter_cli_project/infrastructure/context_util.dart'; 5 | import 'package:flutter_cli_project/infrastructure/i18n_box.dart'; 6 | 7 | import 'deliver_bill_routers.dart'; 8 | 9 | class LoadingIndex extends Page { 10 | 11 | LoadingIndex() : super(DeliverBillPickIndexConst.loadingIndexPath); 12 | 13 | @override 14 | Widget build0(BuildContext context) { 15 | return CommonScaffold( 16 | title: I18nBox.getTextOfContext('index.deliver.bill.loading.pageTitle'), 17 | showBackBtn: true, 18 | body: Center( 19 | child: Text('我的发车任务'), 20 | ), 21 | ); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /lib/login/dto/UserAuthenticateDto.pbjson.dart: -------------------------------------------------------------------------------- 1 | /// 2 | // Generated code. Do not modify. 3 | // source: UserAuthenticateDto.proto 4 | // 5 | // @dart = 2.3 6 | // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type 7 | 8 | const UserAuthenticateReqDto$json = const { 9 | '1': 'UserAuthenticateReqDto', 10 | '2': const [ 11 | const {'1': 'userName', '3': 1, '4': 1, '5': 9, '10': 'userName'}, 12 | const {'1': 'password', '3': 2, '4': 1, '5': 9, '10': 'password'}, 13 | ], 14 | }; 15 | 16 | const UserAuthenticateRespDto$json = const { 17 | '1': 'UserAuthenticateRespDto', 18 | '2': const [ 19 | const {'1': 'token', '3': 1, '4': 1, '5': 9, '10': 'token'}, 20 | const {'1': 'resourceCodes', '3': 2, '4': 3, '5': 9, '10': 'resourceCodes'}, 21 | ], 22 | }; 23 | 24 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_cli_project 2 | description: Flutter脚手架项目. 3 | 4 | version: 1.0.0+1 5 | 6 | environment: 7 | sdk: ">=2.1.0 <3.0.0" 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | equatable: ^1.1.1 13 | shared_preferences: ^0.5.7 14 | fluttertoast: ^3.1.0 15 | dio: ^2.0.15 16 | protobuf: 1.0.1 17 | flutter_bloc: ^4.0.0 18 | 19 | dev_dependencies: 20 | flutter_test: 21 | sdk: flutter 22 | 23 | flutter: 24 | uses-material-design: true 25 | assets: 26 | - assets/imgs/ 27 | - assets/lang/lang_zh-CN.json 28 | - assets/lang/lang_en-US.json 29 | - assets/profile-config.json 30 | fonts: 31 | - family: Quicksand 32 | fonts: 33 | - asset: assets/fonts/Quicksand-Medium.ttf 34 | style: normal 35 | - asset: assets/fonts/Quicksand_Bold.otf 36 | weight: 700 37 | -------------------------------------------------------------------------------- /ios/Runner/GeneratedPluginRegistrant.m: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | #import "GeneratedPluginRegistrant.h" 6 | 7 | #if __has_include() 8 | #import 9 | #else 10 | @import fluttertoast; 11 | #endif 12 | 13 | #if __has_include() 14 | #import 15 | #else 16 | @import shared_preferences; 17 | #endif 18 | 19 | @implementation GeneratedPluginRegistrant 20 | 21 | + (void)registerWithRegistry:(NSObject*)registry { 22 | [FluttertoastPlugin registerWithRegistrar:[registry registrarForPlugin:@"FluttertoastPlugin"]]; 23 | [FLTSharedPreferencesPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTSharedPreferencesPlugin"]]; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /lib/components/profile_tile.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ProfileTile extends StatelessWidget { 4 | final title; 5 | final subtitle; 6 | final textColor; 7 | ProfileTile({this.title, this.subtitle, this.textColor = Colors.black}); 8 | @override 9 | Widget build(BuildContext context) { 10 | return Column( 11 | // crossAxisAlignment: CrossAxisAlignment.start, 12 | mainAxisAlignment: MainAxisAlignment.center, 13 | children: [ 14 | Text( 15 | title, 16 | style: TextStyle( 17 | fontSize: 20.0, fontWeight: FontWeight.w700, color: textColor), 18 | ), 19 | SizedBox( 20 | height: 5.0, 21 | ), 22 | Text( 23 | subtitle, 24 | style: TextStyle( 25 | fontSize: 15.0, fontWeight: FontWeight.normal, color: textColor), 26 | ), 27 | ], 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/splash_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter/src/widgets/framework.dart'; 4 | import 'package:flutter_cli_project/infrastructure/context_util.dart'; 5 | 6 | import 'main_app/common_logo.dart'; 7 | 8 | class SplashPage extends PageStateFul { 9 | @override 10 | State createState0() { 11 | return _SplashPageState(); 12 | } 13 | } 14 | 15 | class _SplashPageState extends State { 16 | 17 | @override 18 | void initState() { 19 | Future.delayed(Duration(milliseconds: 1500), () { 20 | Navigator.of(context) 21 | .pushNamedAndRemoveUntil("/main", (Route route) => false); 22 | }); 23 | } 24 | 25 | @override 26 | Widget build(BuildContext context) { 27 | return Scaffold( 28 | backgroundColor: Colors.white, 29 | body: Center( 30 | child: CommonLogo() 31 | ) 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /assets/lang/lang_zh-CN.json: -------------------------------------------------------------------------------- 1 | { 2 | "global.title": "Flutter脚手架模板", 3 | "global.press.back.again": "继续点击返回退出应用", 4 | "login.title": "Flutter脚手架模板", 5 | "login.input.title": "用户名", 6 | "login.input.notempty.title": "请输入用户名", 7 | "login.input.password": "密码", 8 | "login.input.notempty.password": "请输入密码", 9 | "login.btn.login": "登录", 10 | "common.drawer.theme.setting": "主题设置", 11 | "common.drawer.dashboard": "面板", 12 | "common.drawer.operator.log": "操作记录", 13 | "common.drawer.pda.setting": "设置", 14 | "common.drawer.nothing": "功能还在开发中", 15 | "common.drawer.lang.setting": "语言切换", 16 | 17 | "dashboard.deliver.bill.title": "发货单作业", 18 | "dashboard.deliver.bill.pick": "拣货作业", 19 | "dashboard.deliver.bill.deliver": "发车作业", 20 | "dashboard.deliver.bill.audit": "审核作业", 21 | "dashboard.check.bill.title": "盘点作业", 22 | "dashboard.check.bill.auditing": "盲盘作业", 23 | 24 | "index.deliver.bill.pick.pageTitle": "我的拣货单", 25 | "index.deliver.bill.loading.pageTitle": "发车单页", 26 | "index.deliver.bill.audit.pageTitle": "发货单审核", 27 | "index.check.bill.check.pageTitle": "盘点单--盲盘" 28 | } -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter_test/flutter_test.dart'; 9 | 10 | void main() { 11 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 12 | // // Build our app and trigger a frame. 13 | // await tester.pumpWidget(MyApp()); 14 | // 15 | // // Verify that our counter starts at 0. 16 | // expect(find.text('0'), findsOneWidget); 17 | // expect(find.text('1'), findsNothing); 18 | // 19 | // // Tap the '+' icon and trigger a frame. 20 | // await tester.tap(find.byIcon(Icons.add)); 21 | // await tester.pump(); 22 | // 23 | // // Verify that our counter has incremented. 24 | // expect(find.text('0'), findsNothing); 25 | // expect(find.text('1'), findsOneWidget); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java: -------------------------------------------------------------------------------- 1 | package io.flutter.plugins; 2 | 3 | import io.flutter.plugin.common.PluginRegistry; 4 | import io.github.ponnamkarthik.toast.fluttertoast.FluttertoastPlugin; 5 | import io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin; 6 | 7 | /** 8 | * Generated file. Do not edit. 9 | */ 10 | public final class GeneratedPluginRegistrant { 11 | public static void registerWith(PluginRegistry registry) { 12 | if (alreadyRegisteredWith(registry)) { 13 | return; 14 | } 15 | FluttertoastPlugin.registerWith(registry.registrarFor("io.github.ponnamkarthik.toast.fluttertoast.FluttertoastPlugin")); 16 | SharedPreferencesPlugin.registerWith(registry.registrarFor("io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin")); 17 | } 18 | 19 | private static boolean alreadyRegisteredWith(PluginRegistry registry) { 20 | final String key = GeneratedPluginRegistrant.class.getCanonicalName(); 21 | if (registry.hasPlugin(key)) { 22 | return true; 23 | } 24 | registry.registrarFor(key); 25 | return false; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lib/mock/mock_data/user_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_cli_project/infrastructure/base_model/PbResultDto.pb.dart'; 2 | import 'package:flutter_cli_project/infrastructure/base_model/google/protobuf/any.pb.dart'; 3 | import 'package:flutter_cli_project/login/dto/UserAuthenticateDto.pb.dart'; 4 | import 'package:protobuf/protobuf.dart' as $pb; 5 | 6 | PbResultDto testMock

({ 7 | P body, 8 | Map param 9 | }) { 10 | PbResultDto r = PbResultDto(); 11 | r.success = true; 12 | r.message = 'testMock'; 13 | return r; 14 | } 15 | 16 | PbResultDto userAuthenticate

({ 17 | P body, 18 | Map param 19 | }) { 20 | UserAuthenticateReqDto req = body as UserAuthenticateReqDto; 21 | UserAuthenticateRespDto r = UserAuthenticateRespDto(); 22 | if (req.userName == 'Weidan') { 23 | r.token = '112233'; 24 | r.resourceCodes.addAll(['deliverBillPick', 'deliverBillPick2']); 25 | } else { 26 | r.token = '334455'; 27 | r.resourceCodes.addAll(['deliverBillPick2']); 28 | } 29 | 30 | PbResultDto pbResultDto = PbResultDto(); 31 | pbResultDto.data = Any.pack(r); 32 | return pbResultDto; 33 | } -------------------------------------------------------------------------------- /lib/infrastructure/ioc_container.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_cli_project/infrastructure/net_tool_box.dart'; 2 | import 'package:flutter_cli_project/repository/user_repository.dart'; 3 | 4 | class IocContainer { 5 | 6 | static Map _beanMap = { 7 | 'userRepository': UserRepository(), 8 | 'INetTool': null, 9 | '_instance': IocContainer() 10 | }; 11 | 12 | static dynamic getBean(String beanName) { 13 | var bean = _beanMap[beanName]; 14 | if (bean == null) { 15 | _beanMap[beanName] = _initBean(beanName); 16 | bean = _beanMap[beanName]; 17 | if (bean == null) { 18 | throw ArgumentError('bean not found!'); 19 | } 20 | } 21 | 22 | return bean; 23 | } 24 | 25 | UserRepository get userRepository { 26 | return getBean('userRepository'); 27 | } 28 | 29 | INetTool get netTool { 30 | return getBean('INetTool'); 31 | } 32 | 33 | static instance() { 34 | return getBean('_instance'); 35 | } 36 | 37 | static dynamic _initBean(String beanName) { 38 | switch (beanName) { 39 | case 'INetTool': 40 | return NetToolFactory.create(); 41 | default: 42 | return null; 43 | } 44 | 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /assets/lang/lang_en-US.json: -------------------------------------------------------------------------------- 1 | { 2 | "global.title": "Flutter Cli Project", 3 | "global.press.back.again": "Press again to cancel the APP.", 4 | "login.title": "Flutter Cli Project", 5 | "login.input.title": "UserName", 6 | "login.input.notempty.title": "please input UserName", 7 | "login.input.password": "Password", 8 | "login.input.notempty.password": "please input Password", 9 | "login.btn.login": "Login", 10 | "common.drawer.theme.setting": "Theme Setting", 11 | "common.drawer.dashboard": "Dashboard", 12 | "common.drawer.operator.log": "Operator Log", 13 | "common.drawer.pda.setting": "Setting", 14 | "common.drawer.nothing": "Sorry, it can not service now.", 15 | "common.drawer.lang.setting": "Language Switch", 16 | 17 | 18 | "dashboard.deliver.bill.title": "Deliver Task", 19 | "dashboard.deliver.bill.pick": "Pick Task", 20 | "dashboard.deliver.bill.deliver": "Driving Task", 21 | "dashboard.deliver.bill.audit": "Audit Task", 22 | "dashboard.check.bill.title": "Check Bill Task", 23 | "dashboard.check.bill.auditing": "Check Task", 24 | 25 | "index.deliver.bill.pick.pageTitle": "My Deliver Bill", 26 | "index.deliver.bill.loading.pageTitle": "Loading Task", 27 | "index.deliver.bill.audit.pageTitle": "Deliver Bill Audit Task", 28 | "index.check.bill.check.pageTitle": "My Check Bill" 29 | } -------------------------------------------------------------------------------- /lib/main_app/notfound_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_cli_project/components/common_scaffold.dart'; 3 | import 'package:flutter_cli_project/components/profile_tile.dart'; 4 | 5 | class NotFoundPage extends StatelessWidget { 6 | final appTitle; 7 | final title; 8 | final message; 9 | final IconData icon; 10 | final String image; 11 | final iconColor; 12 | 13 | NotFoundPage( 14 | {this.appTitle = "无人区", 15 | this.title = "走丢啦~~~", 16 | this.message = "页面没有找到,可能是迷路了", 17 | this.icon = Icons.map, 18 | this.image, 19 | this.iconColor = Colors.black}); 20 | 21 | Widget bodyData() => Center( 22 | child: Column( 23 | mainAxisAlignment: MainAxisAlignment.center, 24 | children: [ 25 | Icon( 26 | icon, 27 | size: 100.0, 28 | color: iconColor, 29 | ), 30 | SizedBox( 31 | height: 20.0, 32 | ), 33 | ProfileTile( 34 | title: title, 35 | subtitle: message, 36 | ) 37 | ], 38 | ), 39 | ); 40 | 41 | @override 42 | Widget build(BuildContext context) { 43 | return CommonScaffold( 44 | body: bodyData(), 45 | showDrawer: false, 46 | title: appTitle, 47 | ); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/infrastructure/context_util.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | class CurrentPageContext { 4 | 5 | static BuildContext context; 6 | 7 | static void set(BuildContext context) { 8 | CurrentPageContext.context = context; 9 | } 10 | 11 | static BuildContext get() { 12 | return CurrentPageContext.context; 13 | } 14 | 15 | } 16 | 17 | /// 用于有状态的页面的Context父类,可以用于记录当前的BuildContext 18 | abstract class PageStateFul extends StatefulWidget { 19 | 20 | @override 21 | State createState() { 22 | State state = createState0(); 23 | CurrentPageContext.set(state.context); 24 | return state; 25 | } 26 | 27 | State createState0(); 28 | 29 | } 30 | 31 | abstract class PageStateLess extends StatelessWidget { 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | CurrentPageContext.set(context); 36 | var widget = build0(context); 37 | return widget; 38 | } 39 | 40 | Widget build0(BuildContext context); 41 | 42 | } 43 | 44 | abstract class Page extends PageStateLess { 45 | 46 | final String routerPath; 47 | 48 | Page(this.routerPath); 49 | 50 | @override 51 | Widget build(BuildContext context) { 52 | return Hero( 53 | tag: routerPath, 54 | child: super.build(context), 55 | ); 56 | } 57 | 58 | Widget build0(BuildContext context); 59 | 60 | } -------------------------------------------------------------------------------- /test/net_tool_box_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | import 'package:flutter_cli_project/infrastructure/base_model/PbResultDto.pb.dart'; 3 | import 'package:flutter_cli_project/infrastructure/net_tool_box.dart'; 4 | import 'package:flutter_cli_project/mock/mock_holder.dart'; 5 | 6 | void main() { 7 | 8 | // 需要配合后端 9 | test('GET请求测试', () async { 10 | var future = await NetTool().get('http://127.0.0.1:8205/pbtest'); 11 | print(future.success); 12 | }); 13 | 14 | // 需要配合后端 15 | test('POST请求测试', () async { 16 | var req = PbResultDto(); 17 | req.message = '测试调用POSTJSON'; 18 | 19 | var future = await NetTool().post('http://127.0.0.1:8205/pbtest', request: req); 20 | print(future.message); 21 | }); 22 | 23 | // Mock测试 24 | INetTool mockNetTool = MockNetTool(); 25 | MockData.initRouter(); 26 | 27 | test('测试Mock请求工具', () async { 28 | var result = await mockNetTool.post('/v1/user/login'); 29 | expect('testMock', result.message); 30 | 31 | result = await mockNetTool.post('/v1/user/login?b=2&a=1'); 32 | expect('testMock', result.message); 33 | 34 | result = await mockNetTool.post('/v1/user/login?a=1&b=2'); 35 | expect('testMock', result.message); 36 | 37 | result = await mockNetTool.post('/v1/user/login', queryParameters: {'a': '1', 'b': '2'}); 38 | expect('testMock', result.message); 39 | 40 | }); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /lib/main_app/system_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:bloc/bloc.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_cli_project/infrastructure/i18n_box.dart'; 6 | import 'package:flutter_cli_project/personal/themes.dart'; 7 | 8 | class SystemState{ 9 | 10 | ThemeData theme; 11 | I18nBox i18nBox; 12 | 13 | SystemState(this.theme, this.i18nBox); 14 | 15 | } 16 | 17 | enum SystemAction { toggle_lang, toggle_theme } 18 | 19 | class SystemEvent { 20 | 21 | SystemAction _action; 22 | dynamic _data; 23 | 24 | SystemEvent(this._action, this._data); 25 | 26 | dynamic get data => _data; 27 | 28 | SystemAction get action => _action; 29 | 30 | } 31 | 32 | class SystemBloc extends Bloc { 33 | 34 | @override 35 | SystemState get initialState => SystemState(Themes.blackTheme, I18nBox.emptyInstance()); 36 | 37 | @override 38 | Stream mapEventToState(SystemEvent event) async* { 39 | switch (event.action) { 40 | case SystemAction.toggle_lang: 41 | final _i18nBox = event.data as I18nBox; 42 | final _theme = state.theme; 43 | yield SystemState(_theme, _i18nBox); 44 | break; 45 | case SystemAction.toggle_theme: 46 | final _theme = event.data as ThemeData; 47 | final _i18nBox = state.i18nBox; 48 | yield SystemState(_theme, _i18nBox); 49 | break; 50 | } 51 | } 52 | 53 | 54 | } 55 | 56 | -------------------------------------------------------------------------------- /lib/infrastructure/profiles_loader.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'context_util.dart'; 6 | 7 | /// 配置文件的读取器 8 | class ProfilesLoader { 9 | 10 | static Map _profileMap = {}; 11 | static bool _isInit = false; 12 | 13 | static initProfile() async { 14 | if (!_isInit) { 15 | String profileJson = await DefaultAssetBundle 16 | .of(CurrentPageContext.get()) 17 | .loadString('assets/profile-config.json'); 18 | Map allProfile = JsonDecoder().convert(profileJson); 19 | 20 | _profileMap = Map(); 21 | final String profileActive = allProfile['profile.active']; 22 | 23 | allProfile.forEach((key, value) { 24 | if (key == 'profile.active') { 25 | _profileMap['profile'] = value; 26 | return; 27 | } 28 | if (!key.contains(profileActive)) { 29 | return; 30 | } 31 | String pKey = key.substring(0, key.indexOf('.' + profileActive)); 32 | _profileMap[pKey] = value; 33 | }); 34 | _isInit = true; 35 | } 36 | } 37 | 38 | static profileActive() { 39 | return keyOf('profile'); 40 | } 41 | 42 | static keyOf(String profileKey) { 43 | String value; 44 | do { 45 | if (_isInit) { 46 | value = _profileMap[profileKey]; 47 | } 48 | } while(!_isInit); 49 | 50 | return value; 51 | } 52 | 53 | } 54 | 55 | class ProfileKeys { 56 | static const BASE_URL = 'baseURL'; 57 | } -------------------------------------------------------------------------------- /lib/repository/user_repository.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_cli_project/infrastructure/ioc_container.dart'; 4 | import 'package:flutter_cli_project/infrastructure/net_tool_box.dart'; 5 | import 'package:flutter_cli_project/login/dto/UserAuthenticateDto.pb.dart'; 6 | 7 | /// 用户数据仓库 8 | class UserRepository { 9 | 10 | /// 认证 11 | /// @param username 用户名 12 | /// @param password 密码 13 | /// @return 返回认证信息 14 | Future authenticate({ 15 | @required String username, 16 | @required String password, 17 | }) async { 18 | INetTool netTool = IocContainer.instance().netTool; 19 | var req = UserAuthenticateReqDto(); 20 | req.userName = username; 21 | req.password = password; 22 | var pbResult = await netTool.post('/v1/authenticate/login', request: req); 23 | var userAuthenticateRespDto = pbResult.data.unpackInto(UserAuthenticateRespDto()); 24 | return userAuthenticateRespDto; 25 | } 26 | 27 | /// 删除Token 28 | Future deleteToToken() async { 29 | await Future.delayed(Duration(seconds: 1)); 30 | return ; 31 | } 32 | 33 | /// 保存Token 34 | /// @param token 令牌 35 | Future persistToken(String token) async { 36 | // 保存 37 | await Future.delayed(Duration(seconds: 1)); 38 | return ; 39 | } 40 | 41 | /// 判断是否有Token 42 | /// @return true: 有; false: 没有Token 43 | Future hasToken() async { 44 | // 读取Token 45 | await Future.delayed(Duration(seconds: 1)); 46 | return false; 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /lib/infrastructure/base_model/PbResultDto.pbjson.dart: -------------------------------------------------------------------------------- 1 | /// 2 | // Generated code. Do not modify. 3 | // source: PbResultDto.proto 4 | // 5 | // @dart = 2.3 6 | // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type 7 | 8 | const PbResultDto$json = const { 9 | '1': 'PbResultDto', 10 | '2': const [ 11 | const {'1': 'success', '3': 1, '4': 1, '5': 8, '10': 'success'}, 12 | const {'1': 'message', '3': 2, '4': 1, '5': 9, '10': 'message'}, 13 | const {'1': 'code', '3': 3, '4': 1, '5': 9, '10': 'code'}, 14 | const {'1': 'data', '3': 4, '4': 1, '5': 11, '6': '.google.protobuf.Any', '10': 'data'}, 15 | const {'1': 'extra', '3': 5, '4': 3, '5': 11, '6': '.PbResultDto.ExtraEntry', '10': 'extra'}, 16 | ], 17 | '3': const [PbResultDto_ExtraEntry$json], 18 | }; 19 | 20 | const PbResultDto_ExtraEntry$json = const { 21 | '1': 'ExtraEntry', 22 | '2': const [ 23 | const {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'}, 24 | const {'1': 'value', '3': 2, '4': 1, '5': 11, '6': '.ExtraMap', '10': 'value'}, 25 | ], 26 | '7': const {'7': true}, 27 | }; 28 | 29 | const ExtraMap$json = const { 30 | '1': 'ExtraMap', 31 | '2': const [ 32 | const {'1': 'extra', '3': 1, '4': 3, '5': 11, '6': '.ExtraMap.ExtraEntry', '10': 'extra'}, 33 | ], 34 | '3': const [ExtraMap_ExtraEntry$json], 35 | }; 36 | 37 | const ExtraMap_ExtraEntry$json = const { 38 | '1': 'ExtraEntry', 39 | '2': const [ 40 | const {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'}, 41 | const {'1': 'value', '3': 2, '4': 1, '5': 9, '10': 'value'}, 42 | ], 43 | '7': const {'7': true}, 44 | }; 45 | 46 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /android/front_imopei_pda_android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | flutter_cli_project 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /lib/personal/index.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/widgets.dart'; 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:flutter_cli_project/infrastructure/context_util.dart'; 5 | import 'package:flutter_cli_project/infrastructure/toast_tool.dart'; 6 | import 'package:flutter_cli_project/login/login_page.dart'; 7 | import 'package:flutter_cli_project/main_app/authenticate_bloc.dart'; 8 | import 'package:flutter_cli_project/personal/dashboard_page.dart'; 9 | 10 | class HomePage extends PageStateLess { 11 | 12 | @override 13 | Widget build0(BuildContext context) { 14 | return BlocBuilder( 15 | builder: (context, state) { 16 | return state is AuthenticationAuthenticated ? 17 | _dashboardPage() : LoginPage(); 18 | } 19 | ); 20 | } 21 | 22 | _dashboardPage() { 23 | return _PopContainer(); 24 | } 25 | 26 | } 27 | 28 | class _PopContainer extends PageStateFul { 29 | 30 | @override 31 | State createState0() { 32 | return _PopContainerState(); 33 | } 34 | 35 | } 36 | 37 | class _PopContainerState extends State<_PopContainer> { 38 | 39 | DateTime _lastBackDateTime; 40 | 41 | @override 42 | Widget build(BuildContext context) { 43 | return WillPopScope( 44 | onWillPop: () async { 45 | if (_lastBackDateTime == null || 46 | DateTime.now().difference(_lastBackDateTime) > Duration(seconds: 1)) { 47 | //两次点击间隔超过1秒则重新计时 48 | _lastBackDateTime = DateTime.now(); 49 | 50 | ToastTool.shortOfKey('global.press.back.again'); 51 | return false; 52 | } 53 | return true; 54 | }, 55 | child: DashboardPage() 56 | ); 57 | } 58 | 59 | } 60 | 61 | -------------------------------------------------------------------------------- /lib/infrastructure/dialog_util.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'context_util.dart'; 4 | 5 | typedef OkCallBack = void Function(); 6 | 7 | /// 弹窗工具类 8 | class DialogUtil { 9 | 10 | /// 一个简单的弹窗,一般用于完成一个命令请求后提示成功的行为. 11 | static simpleDialog(String title, String content, { 12 | BuildContext context 13 | }) { 14 | BuildContext _context = context ?? CurrentPageContext.get(); 15 | showDialog( 16 | context: _context, 17 | builder: (context) => AlertDialog( 18 | title: Text(title), 19 | content: Text(content), 20 | actions: [ 21 | FlatButton( 22 | child: Text('Ok'), 23 | onPressed: () { 24 | Navigator.of(context).pop(); 25 | }, 26 | ) 27 | ] 28 | ) 29 | ); 30 | } 31 | 32 | /// 确认弹窗,一般用于点击一个命令按钮之前的提示是否确认执行的行为. 33 | static confirmDialog( 34 | String title, 35 | String content, 36 | OkCallBack okCallBack, { 37 | BuildContext context 38 | }) { 39 | BuildContext _context = context ?? CurrentPageContext.get(); 40 | showDialog( 41 | context: _context, 42 | builder: (context) => 43 | AlertDialog( 44 | title: Text(title), 45 | content: Text(content), 46 | actions: [ 47 | FlatButton( 48 | child: Text('Ok'), 49 | onPressed: () { 50 | okCallBack(); 51 | }, 52 | ), 53 | FlatButton( 54 | child: Text('取消'), 55 | onPressed: () { 56 | Navigator.of(context).pop(); 57 | }, 58 | ) 59 | ] 60 | ) 61 | ); 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 9 | 13 | 20 | 24 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /lib/main_app/routes.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_cli_project/personal/index.dart'; 3 | import 'package:flutter_cli_project/personal/theme_setting.dart'; 4 | import 'package:flutter_cli_project/services/check_bill/check_bill_index.dart'; 5 | import 'package:flutter_cli_project/services/check_bill/check_bill_routers.dart'; 6 | import 'package:flutter_cli_project/services/deliver_bill_pick/deliver_bill_routers.dart'; 7 | import 'package:flutter_cli_project/services/deliver_bill_pick/loading_index.dart'; 8 | import 'package:flutter_cli_project/services/deliver_bill_pick/pick_index.dart'; 9 | 10 | import 'notfound_page.dart'; 11 | 12 | class Routes { 13 | 14 | /// 路由信息 15 | static final Map _routes = { 16 | '/themeSetting': (BuildContext context) => ThemeSetting(), 17 | '/main': (BuildContext context) => HomePage(), 18 | DeliverBillPickIndexConst.pickIndexPath: (BuildContext context) => PickIndex(), 19 | DeliverBillPickIndexConst.loadingIndexPath: (BuildContext context) => LoadingIndex(), 20 | DeliverBillPickIndexConst.auditIndexPath: (BuildContext context) => CheckBillIndex(), 21 | CheckBillIndexConst.checkBillIndexPath: (BuildContext context) => CheckBillIndex(), 22 | }; 23 | 24 | /// 路由拦截 25 | static Route routeGenerator(RouteSettings settings, BuildContext buildContext) { 26 | final String name = settings.name; 27 | final Function pageBuilder = _routes[name]; 28 | if (pageBuilder != null) { 29 | if (settings.arguments != null) { 30 | // 如果透传了参数 31 | return MaterialPageRoute( 32 | builder: (context) => 33 | pageBuilder(context, arguments: settings.arguments)); 34 | } else { 35 | // 没有透传参数 36 | return MaterialPageRoute(builder: (context) => pageBuilder(context)); 37 | } 38 | } 39 | return MaterialPageRoute(builder: (context) => NotFoundPage()); 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:flutter_cli_project/infrastructure/i18n_box.dart'; 4 | import 'package:flutter_cli_project/infrastructure/profiles_loader.dart'; 5 | import 'package:flutter_cli_project/main_app/routes.dart'; 6 | import 'package:flutter_cli_project/repository/user_repository.dart'; 7 | 8 | import 'infrastructure/context_util.dart'; 9 | import 'infrastructure/ioc_container.dart'; 10 | import 'main_app/authenticate_bloc.dart'; 11 | import 'main_app/system_bloc.dart'; 12 | import 'splash_page.dart'; 13 | 14 | void main() => runApp(MyApp()); 15 | 16 | class MyApp extends PageStateLess { 17 | 18 | Future setupGlobalBloc(BuildContext context) async { 19 | try { 20 | // 初始化i18n 21 | final I18nBox i18nBox = await I18nBox.getInstance(); 22 | var systemBloc = context.bloc(); 23 | systemBloc.add(SystemEvent(SystemAction.toggle_lang, i18nBox)); 24 | // 初始化 profile_loader 25 | ProfilesLoader.initProfile(); 26 | } catch (e) { 27 | } 28 | } 29 | 30 | @override 31 | Widget build0(BuildContext context) { 32 | UserRepository userRepository = IocContainer.instance().userRepository; 33 | 34 | return MultiBlocProvider( 35 | providers: [ 36 | BlocProvider( 37 | create: (BuildContext context) => SystemBloc(), 38 | ), 39 | BlocProvider( 40 | create: (BuildContext context) => AuthenticationBloc( 41 | userRepository: userRepository 42 | ), 43 | ), 44 | ], 45 | child: BlocBuilder( 46 | builder: (_, state) { 47 | setupGlobalBloc(_); 48 | return MaterialApp( 49 | theme: state.theme, 50 | home: SplashPage(), 51 | onGenerateRoute: (RouteSettings settings) { 52 | return Routes.routeGenerator(settings, _); 53 | }, 54 | ); 55 | }, 56 | ) 57 | ); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /lib/personal/theme_setting.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/src/widgets/framework.dart'; 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:flutter_cli_project/components/common_scaffold.dart'; 5 | import 'package:flutter_cli_project/infrastructure/context_util.dart'; 6 | import 'package:flutter_cli_project/main_app/system_bloc.dart'; 7 | import 'package:flutter_cli_project/personal/themes.dart'; 8 | 9 | class ThemeSetting extends PageStateLess { 10 | 11 | @override 12 | Widget build0(BuildContext context) { 13 | return BlocBuilder( 14 | builder: (_, state) { 15 | return CommonScaffold( 16 | body: ListView( 17 | children: [ 18 | ListTile( 19 | title: Text( 20 | "暗夜黑(推荐)", 21 | style: TextStyle( 22 | fontWeight: FontWeight.w100, fontSize: 18.0), 23 | ), 24 | leading: Icon( 25 | Icons.bookmark, 26 | color: Colors.blue, 27 | ), 28 | onTap: () { 29 | _switchTheme(context, Themes.blackTheme); 30 | }, 31 | ), 32 | ListTile( 33 | title: Text( 34 | "骚气白", 35 | style: TextStyle( 36 | fontWeight: FontWeight.w100, fontSize: 18.0), 37 | ), 38 | leading: Icon( 39 | Icons.collections, 40 | color: Colors.blue, 41 | ), 42 | onTap: () { 43 | _switchTheme(context, Themes.kIOSTheme); 44 | }, 45 | ), 46 | ] 47 | ), 48 | ); 49 | }, 50 | ); 51 | } 52 | 53 | void _switchTheme(BuildContext context, ThemeData themeData) { 54 | var systemBloc = context.bloc(); 55 | systemBloc.add(SystemEvent(SystemAction.toggle_theme, themeData)); 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /.idea/libraries/Dart_SDK.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 28 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | lintOptions { 36 | disable 'InvalidPackage' 37 | } 38 | 39 | defaultConfig { 40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 41 | applicationId "com.jingchuan.imopei.flutter_cli_project" 42 | minSdkVersion 16 43 | targetSdkVersion 28 44 | versionCode flutterVersionCode.toInteger() 45 | versionName flutterVersionName 46 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 47 | } 48 | 49 | buildTypes { 50 | release { 51 | // TODO: Add your own signing config for the release build. 52 | // Signing with the debug keys for now, so `flutter run --release` works. 53 | signingConfig signingConfigs.debug 54 | } 55 | } 56 | } 57 | 58 | flutter { 59 | source '../..' 60 | } 61 | 62 | dependencies { 63 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 64 | testImplementation 'junit:junit:4.12' 65 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 66 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 67 | } 68 | -------------------------------------------------------------------------------- /lib/login/login_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'package:equatable/equatable.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:flutter_cli_project/infrastructure/ioc_container.dart'; 5 | import 'package:flutter_cli_project/main_app/authenticate_bloc.dart'; 6 | import 'package:flutter_cli_project/repository/user_repository.dart'; 7 | 8 | import 'dto/UserAuthenticateDto.pb.dart'; 9 | 10 | /// 登录状态 11 | @immutable 12 | abstract class LoginState extends Equatable { 13 | 14 | const LoginState(); 15 | 16 | @override 17 | List get props => []; 18 | 19 | } 20 | 21 | /// 登录初始化状态 22 | class LoginInitial extends LoginState {} 23 | 24 | /// 正在登录中状态 25 | class LoginLoading extends LoginState {} 26 | 27 | /// 登录失败状态 28 | class LoginFailure extends LoginState { 29 | 30 | final String error; 31 | 32 | const LoginFailure({@required this.error}); 33 | 34 | @override 35 | List get props => [error]; 36 | 37 | @override 38 | String toString() => "LoginFailure { error: $error }"; 39 | 40 | } 41 | 42 | /// 登录事件 43 | @immutable 44 | abstract class LoginEvent extends Equatable{} 45 | 46 | /// 登录事件 47 | class LoginButtonPressed extends LoginEvent { 48 | /// 用户名 49 | final String username; 50 | /// 密码 51 | final String password; 52 | 53 | LoginButtonPressed({ 54 | @required this.username, 55 | @required this.password 56 | }); 57 | 58 | @override 59 | List get props => [username, password]; 60 | 61 | @override 62 | String toString() => "LoginPressed { username: $username, password: $password }"; 63 | 64 | } 65 | 66 | class LoginBloc extends Bloc { 67 | 68 | AuthenticationBloc authenticationBloc; 69 | 70 | LoginBloc({this.authenticationBloc}); 71 | 72 | @override 73 | LoginState get initialState => LoginInitial(); 74 | 75 | @override 76 | Stream mapEventToState(LoginEvent event) async* { 77 | if (event is LoginButtonPressed) { 78 | yield LoginLoading(); 79 | try { 80 | UserRepository userRepository = IocContainer.getBean('userRepository'); 81 | UserAuthenticateRespDto r = await userRepository.authenticate(username: event.username, password: event.password); 82 | authenticationBloc.add(LoginIn(token: r.token, opCodes: r.resourceCodes)); 83 | yield LoginInitial(); 84 | } catch (e) { 85 | print(e); 86 | yield LoginFailure(error: e.toString()); 87 | } 88 | } 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /lib/infrastructure/i18n_box.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/cupertino.dart'; 4 | import 'package:flutter_bloc/flutter_bloc.dart'; 5 | import 'package:flutter_cli_project/main_app/system_bloc.dart'; 6 | 7 | import 'context_util.dart'; 8 | import 'local_data_cache.dart'; 9 | 10 | /// 一个获取i18n配置语言的工具类 11 | class I18nBox { 12 | 13 | Map _lang; 14 | static I18nBox instance; 15 | List _supportLang = ['en-US', 'zh-CN']; 16 | 17 | I18nBox(this._lang); 18 | 19 | static emptyInstance() { 20 | return I18nBox({}); 21 | } 22 | 23 | static getInstance() async { 24 | var localDataCache = await LocalDataCache.getInstance(); 25 | String value = localDataCache.get(SystemCacheKey.LANG_KEY); 26 | if (value == null || value == '') { 27 | value = 'zh-CN'; 28 | localDataCache.putString(SystemCacheKey.LANG_KEY, value); 29 | } 30 | 31 | if (I18nBox.instance == null) { 32 | String langJSON = await DefaultAssetBundle.of(CurrentPageContext.get()).loadString('assets/lang/lang_$value.json'); 33 | Map lang = JsonDecoder().convert(langJSON); 34 | I18nBox.instance = I18nBox(lang); 35 | } 36 | return I18nBox.instance; 37 | } 38 | 39 | static getTextOfContext(String key) { 40 | var systemBloc = BlocProvider.of(CurrentPageContext.get()); 41 | return systemBloc.state.i18nBox.getText(key); 42 | } 43 | 44 | void switchLang(String langName) async { 45 | if (langName == null || langName == '') { 46 | return; 47 | } 48 | I18nBox ins = await I18nBox.getInstance(); 49 | try { 50 | String langJSON = await DefaultAssetBundle 51 | .of(CurrentPageContext.get()) 52 | .loadString('assets/lang/lang_$langName.json'); 53 | Map lang = JsonDecoder().convert(langJSON); 54 | ins._lang = lang; 55 | 56 | var localDataCache = await LocalDataCache.getInstance(); 57 | localDataCache.putString(SystemCacheKey.LANG_KEY, langName); 58 | } catch (e) { 59 | print(e); 60 | 61 | } 62 | } 63 | 64 | /// 按顺序切换语言 65 | Future switchLangList() async { 66 | var localDataCache = await LocalDataCache.getInstance(); 67 | String value = localDataCache.get(SystemCacheKey.LANG_KEY); 68 | String nextLang = ''; 69 | if (_supportLang.indexOf(value) ==(_supportLang.length - 1)) { 70 | nextLang = _supportLang[0]; 71 | } else { 72 | nextLang = _supportLang[_supportLang.indexOf(value) + 1]; 73 | } 74 | localDataCache.putString(SystemCacheKey.LANG_KEY, nextLang); 75 | 76 | switchLang(nextLang); 77 | } 78 | 79 | String getText(String key) { 80 | if (this._lang == null) { 81 | return ''; 82 | } 83 | var text = this._lang[key]; 84 | return text == null ? '' : text.toString(); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Using a CDN with CocoaPods 1.7.2 or later can save a lot of time on pod installation, but it's experimental rather than the default. 2 | # source 'https://cdn.cocoapods.org/' 3 | 4 | # Uncomment this line to define a global platform for your project 5 | # platform :ios, '9.0' 6 | 7 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 8 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 9 | 10 | project 'Runner', { 11 | 'Debug' => :debug, 12 | 'Profile' => :release, 13 | 'Release' => :release, 14 | } 15 | 16 | def parse_KV_file(file, separator='=') 17 | file_abs_path = File.expand_path(file) 18 | if !File.exists? file_abs_path 19 | return []; 20 | end 21 | pods_ary = [] 22 | skip_line_start_symbols = ["#", "/"] 23 | File.foreach(file_abs_path) { |line| 24 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } 25 | plugin = line.split(pattern=separator) 26 | if plugin.length == 2 27 | podname = plugin[0].strip() 28 | path = plugin[1].strip() 29 | podpath = File.expand_path("#{path}", file_abs_path) 30 | pods_ary.push({:name => podname, :path => podpath}); 31 | else 32 | puts "Invalid plugin specification: #{line}" 33 | end 34 | } 35 | return pods_ary 36 | end 37 | 38 | target 'Runner' do 39 | use_frameworks! 40 | 41 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock 42 | # referring to absolute paths on developers' machines. 43 | system('rm -rf .symlinks') 44 | system('mkdir -p .symlinks/plugins') 45 | 46 | # Flutter Pods 47 | generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') 48 | if generated_xcode_build_settings.empty? 49 | puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first." 50 | end 51 | generated_xcode_build_settings.map { |p| 52 | if p[:name] == 'FLUTTER_FRAMEWORK_DIR' 53 | symlink = File.join('.symlinks', 'flutter') 54 | File.symlink(File.dirname(p[:path]), symlink) 55 | pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) 56 | end 57 | } 58 | 59 | # Plugin Pods 60 | plugin_pods = parse_KV_file('../.flutter-plugins') 61 | plugin_pods.map { |p| 62 | symlink = File.join('.symlinks', 'plugins', p[:name]) 63 | File.symlink(p[:path], symlink) 64 | pod p[:name], :path => File.join(symlink, 'ios') 65 | } 66 | end 67 | 68 | # Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system. 69 | install! 'cocoapods', :disable_input_output_paths => true 70 | 71 | post_install do |installer| 72 | installer.pods_project.targets.each do |target| 73 | target.build_configurations.each do |config| 74 | config.build_settings['ENABLE_BITCODE'] = 'NO' 75 | end 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /lib/infrastructure/base_model/google/protobuf/any.pb.dart: -------------------------------------------------------------------------------- 1 | /// 2 | // Generated code. Do not modify. 3 | // source: google/protobuf/any.proto 4 | // 5 | // @dart = 2.3 6 | // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type 7 | 8 | import 'dart:core' as $core; 9 | 10 | import 'package:protobuf/protobuf.dart' as $pb; 11 | 12 | import 'package:protobuf/src/protobuf/mixins/well_known.dart' as $mixin; 13 | 14 | class Any extends $pb.GeneratedMessage with $mixin.AnyMixin { 15 | static final $pb.BuilderInfo _i = $pb.BuilderInfo('Any', package: const $pb.PackageName('google.protobuf'), createEmptyInstance: create, toProto3Json: $mixin.AnyMixin.toProto3JsonHelper, fromProto3Json: $mixin.AnyMixin.fromProto3JsonHelper) 16 | ..aOS(1, 'typeUrl') 17 | ..a<$core.List<$core.int>>(2, 'value', $pb.PbFieldType.OY) 18 | ..hasRequiredFields = false 19 | ; 20 | 21 | Any._() : super(); 22 | factory Any() => create(); 23 | factory Any.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); 24 | factory Any.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); 25 | Any clone() => Any()..mergeFromMessage(this); 26 | Any copyWith(void Function(Any) updates) => super.copyWith((message) => updates(message as Any)); 27 | $pb.BuilderInfo get info_ => _i; 28 | @$core.pragma('dart2js:noInline') 29 | static Any create() => Any._(); 30 | Any createEmptyInstance() => create(); 31 | static $pb.PbList createRepeated() => $pb.PbList(); 32 | @$core.pragma('dart2js:noInline') 33 | static Any getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); 34 | static Any _defaultInstance; 35 | 36 | @$pb.TagNumber(1) 37 | $core.String get typeUrl => $_getSZ(0); 38 | @$pb.TagNumber(1) 39 | set typeUrl($core.String v) { $_setString(0, v); } 40 | @$pb.TagNumber(1) 41 | $core.bool hasTypeUrl() => $_has(0); 42 | @$pb.TagNumber(1) 43 | void clearTypeUrl() => clearField(1); 44 | 45 | @$pb.TagNumber(2) 46 | $core.List<$core.int> get value => $_getN(1); 47 | @$pb.TagNumber(2) 48 | set value($core.List<$core.int> v) { $_setBytes(1, v); } 49 | @$pb.TagNumber(2) 50 | $core.bool hasValue() => $_has(1); 51 | @$pb.TagNumber(2) 52 | void clearValue() => clearField(2); 53 | /// Creates a new [Any] encoding [message]. 54 | /// 55 | /// The [typeUrl] will be [typeUrlPrefix]/`fullName` where `fullName` is 56 | /// the fully qualified name of the type of [message]. 57 | static Any pack($pb.GeneratedMessage message, 58 | {$core.String typeUrlPrefix = 'type.googleapis.com'}) { 59 | final result = create(); 60 | $mixin.AnyMixin.packIntoAny(result, message, 61 | typeUrlPrefix: typeUrlPrefix); 62 | return result; 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /lib/main_app/authenticate_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'package:equatable/equatable.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:flutter_cli_project/repository/user_repository.dart'; 5 | 6 | /// 认证状态 7 | abstract class AuthenticationState extends Equatable { 8 | @override 9 | List get props => []; 10 | } 11 | 12 | /// - uninitialized - 身份验证未初始化 13 | class AuthenticationUninitialized extends AuthenticationState {} 14 | /// - loading - 等待保存/删除Token 15 | class AuthenticationLoading extends AuthenticationState {} 16 | /// - authenticated - 认证成功 17 | class AuthenticationAuthenticated extends AuthenticationState { 18 | 19 | String _token; 20 | List _resourceCodes; 21 | 22 | AuthenticationAuthenticated(this._token, this._resourceCodes): 23 | assert(_token != null),assert(_resourceCodes != null); 24 | 25 | @override 26 | List get props => [_token, _resourceCodes]; 27 | 28 | List get resourceCodes => _resourceCodes; 29 | 30 | String get token => _token; 31 | 32 | String userName() { 33 | /// TODO 34 | return '张三'; 35 | } 36 | 37 | 38 | } 39 | /// - unauthenticated - 未认证 40 | class AuthenticationUnauthenticated extends AuthenticationState {} 41 | 42 | /// 认证事件 43 | abstract class AuthenticationEvent extends Equatable { 44 | 45 | const AuthenticationEvent(); 46 | 47 | @override 48 | List get props => []; 49 | 50 | } 51 | 52 | /// APP 启动事件 53 | class AppStart extends AuthenticationEvent {} 54 | 55 | /// APP 登录事件 56 | class LoginIn extends AuthenticationEvent { 57 | 58 | final String token; 59 | final List opCodes; 60 | 61 | LoginIn({this.token, this.opCodes}); 62 | 63 | @override 64 | List get props => [token, opCodes]; 65 | 66 | } 67 | 68 | /// APP 退出登录事件 69 | class LoginOut extends AuthenticationEvent {} 70 | 71 | /// 认证Bloc 72 | class AuthenticationBloc extends Bloc { 73 | // 用户仓库 74 | final UserRepository userRepository; 75 | 76 | AuthenticationBloc({@required this.userRepository}): assert(userRepository != null); 77 | 78 | @override 79 | AuthenticationState get initialState => AuthenticationUninitialized(); 80 | 81 | @override 82 | Stream mapEventToState(AuthenticationEvent event) async* { 83 | if (event is AppStart) { 84 | // 判断是否有Token 85 | final bool hasToken = await userRepository.hasToken(); 86 | if (hasToken) { 87 | yield AuthenticationAuthenticated('', []); 88 | } else { 89 | yield AuthenticationUnauthenticated(); 90 | } 91 | } else if (event is LoginIn) { 92 | yield AuthenticationLoading(); 93 | yield AuthenticationAuthenticated(event.token, event.opCodes); 94 | } else if (event is LoginOut) { 95 | yield AuthenticationLoading(); 96 | await userRepository.deleteToToken(); 97 | yield AuthenticationUnauthenticated(); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /lib/infrastructure/local_data_cache.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:shared_preferences/shared_preferences.dart'; 4 | 5 | /// 用于存储本地缓存数据的底层工具类 6 | /// 采用 SharedPreferences 实现 7 | /// Copy from flutter-go 8 | class LocalDataCache { 9 | static LocalDataCache _instance; 10 | static Future get instance async { 11 | return await getInstance(); 12 | } 13 | 14 | static SharedPreferences _spf; 15 | 16 | LocalDataCache._(); 17 | 18 | Future _init() async { 19 | _spf = await SharedPreferences.getInstance(); 20 | } 21 | 22 | static Future getInstance() async { 23 | if (_instance == null) { 24 | _instance = new LocalDataCache._(); 25 | } 26 | if (_spf == null) { 27 | await _instance._init(); 28 | } 29 | return _instance; 30 | } 31 | 32 | static bool _beforeCheck() { 33 | if (_spf == null) { 34 | return true; 35 | } 36 | return false; 37 | } 38 | 39 | // 判断是否存在数据 40 | bool hasKey(String key) { 41 | Set keys = getKeys(); 42 | return keys.contains(key); 43 | } 44 | 45 | Set getKeys() { 46 | if (_beforeCheck()) return null; 47 | return _spf.getKeys(); 48 | } 49 | 50 | get(String key) { 51 | if (_beforeCheck()) return null; 52 | return _spf.get(key); 53 | } 54 | 55 | getString(String key) { 56 | if (_beforeCheck()) return null; 57 | return _spf.getString(key); 58 | } 59 | 60 | Future putString(String key, String value) { 61 | if (_beforeCheck()) return null; 62 | return _spf.setString(key, value); 63 | } 64 | 65 | bool getBool(String key) { 66 | if (_beforeCheck()) return null; 67 | return _spf.getBool(key); 68 | } 69 | 70 | Future putBool(String key, bool value) { 71 | if (_beforeCheck()) return null; 72 | return _spf.setBool(key, value); 73 | } 74 | 75 | int getInt(String key) { 76 | if (_beforeCheck()) return null; 77 | return _spf.getInt(key); 78 | } 79 | 80 | Future putInt(String key, int value) { 81 | if (_beforeCheck()) return null; 82 | return _spf.setInt(key, value); 83 | } 84 | 85 | double getDouble(String key) { 86 | if (_beforeCheck()) return null; 87 | return _spf.getDouble(key); 88 | } 89 | 90 | Future putDouble(String key, double value) { 91 | if (_beforeCheck()) return null; 92 | return _spf.setDouble(key, value); 93 | } 94 | 95 | List getStringList(String key) { 96 | return _spf.getStringList(key); 97 | } 98 | 99 | Future putStringList(String key, List value) { 100 | if (_beforeCheck()) return null; 101 | return _spf.setStringList(key, value); 102 | } 103 | 104 | dynamic getDynamic(String key) { 105 | if (_beforeCheck()) return null; 106 | return _spf.get(key); 107 | } 108 | 109 | Future remove(String key) { 110 | if (_beforeCheck()) return null; 111 | return _spf.remove(key); 112 | } 113 | 114 | Future clear() { 115 | if (_beforeCheck()) return null; 116 | return _spf.clear(); 117 | } 118 | 119 | } 120 | 121 | class SystemCacheKey { 122 | 123 | static final LANG_KEY = '__lang'; 124 | 125 | } 126 | -------------------------------------------------------------------------------- /lib/infrastructure/net_tool_box.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:dio/dio.dart'; 4 | import 'package:flutter_cli_project/infrastructure/base_model/PbResultDto.pb.dart'; 5 | import 'package:flutter_cli_project/infrastructure/profiles_loader.dart'; 6 | import 'package:flutter_cli_project/mock/mock_holder.dart'; 7 | import 'package:protobuf/protobuf.dart' as $pb; 8 | 9 | Map optHeader = { 10 | 'accept-language': 'zh-cn', 11 | 'Accept': 'application/x-protobuf;charset=UTF-8' 12 | }; 13 | 14 | var dio = new Dio(BaseOptions( 15 | connectTimeout: 60000, 16 | headers: optHeader, 17 | responseType: ResponseType.bytes, 18 | contentType: new ContentType("application", "x-protobuf"), 19 | baseUrl: ProfileKeys.BASE_URL, 20 | requestEncoder: (r, o) { 21 | var resp_ = o.data as $pb.GeneratedMessage; 22 | return resp_.writeToBuffer(); 23 | }) 24 | ); 25 | 26 | class NetToolFactory { 27 | 28 | static bool _isInit = false; 29 | 30 | static create() { 31 | if (!_isInit) { 32 | _isInit = true; 33 | switch (ProfilesLoader.profileActive()) { 34 | case 'mock': 35 | return MockNetTool(); 36 | default: 37 | return NetTool(); 38 | } 39 | } 40 | } 41 | } 42 | 43 | abstract class INetTool { 44 | 45 | Future post( 46 | String url, { 47 | P request, 48 | Map queryParameters 49 | }); 50 | 51 | Future get ( 52 | String url, { 53 | Map queryParameters 54 | }); 55 | 56 | } 57 | 58 | class NetTool extends INetTool { 59 | 60 | /// Post请求,通过传递请求体 [request] 远程服务响应 61 | /// 数据的形式,响应提要求传递一个空的 [resp] 62 | Future post( 63 | String url, { 64 | P request, 65 | Map queryParameters 66 | }) async { 67 | // 请求远程 68 | Response response = await dio.post( 69 | url, 70 | data: request, 71 | queryParameters: queryParameters 72 | ); 73 | // 获取响应体 74 | var respBody = response.data; 75 | // 开始反序列化 76 | PbResultDto resp = PbResultDto(); 77 | resp.mergeFromBuffer(respBody); 78 | 79 | return resp; 80 | } 81 | 82 | /// GET请求 83 | Future get ( 84 | String url, { 85 | Map queryParameters 86 | }) async { 87 | Response response = await dio.get(url); 88 | // 获取响应体 89 | List respBody = response.data; 90 | // 开始反序列化 91 | PbResultDto resp = PbResultDto(); 92 | resp.mergeFromBuffer(respBody); 93 | 94 | return resp; 95 | } 96 | 97 | } 98 | 99 | class MockNetTool extends INetTool { 100 | 101 | MockNetTool() { 102 | MockData.initRouter(); 103 | } 104 | 105 | @override 106 | Future get( 107 | String url, 108 | {Map queryParameters}) { 109 | return MockData.fetch(url, 'get'); 110 | } 111 | 112 | @override 113 | Future post( 114 | String url, 115 | { 116 | P request, 117 | Map queryParameters 118 | }) { 119 | return MockData.fetch(url, 'post', body: request, uriParam: queryParameters); 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Flutter脚手架模板 2 | 3 | `flutter_cli_project` 是由于我最近需要开发 `Flutter` 相关 `APP` 搭建出来的架构底座,可用于所有的程序,该底座集成了一些功能: 4 | 5 | 1. `BloC` 状态管理; 6 | 2. `i18n` 配置与切换; 7 | 3. `profile` 环境配置; 8 | 4. `MockData` 程序,懒加载,常用于开发的时候使用; 9 | 5. `dio` + `protolbuf` 数据传输协议; 10 | 6. 路由跳转动画过度(`Hero` 动画); 11 | 7. `Toast` 工具包 12 | 8. 用户权限管理; 13 | 14 | 开发了一些通用的核心类,可用于实现以上的功能。 15 | 16 | ## i18n工具包 17 | 18 | 核心工具包:`I18nBox`,通过程序启动,加载 `assets/lang` 对应的语言配置,放置于全局的 `BloC` 状态中,可以随时切换: 19 | 20 | ![](md_assets/i18n_support.gif) 21 | 22 | ## 主题切换 23 | 24 | 原理同上,交由系统状态器管理,可以在 `lib/personal/theme_setting.dart` 以及 `lib/personal/themes.dart` 配置满足需求的主题数据: 25 | 26 | ![](md_assets/theme_support.gif) 27 | 28 | ## 路由动画切换 29 | 30 | 这个就是简单的使用 `Hero` 动画,感觉还是蛮好看的,在 `dashboard` 进行渲染菜单的时候,使用跳转的路由路径作为 `Hero` 的 `tag`,对应的页面继承封装的 `Page` 对象进行路由路径注入,从而形成相同的 `Hero` `tage` 即可完成路由切换。 31 | 32 | ![](md_assets/hero.gif) 33 | 34 | ## Profile配置管理 35 | 36 | 经常的我们需要多个环境进行 `APP` 的开发,这就涉及到了 `prod` `test` 以及 `uat` 环境: 37 | 38 | ```json 39 | assets/profile-config.json 40 | { 41 | "profile.active": "mock", 42 | "baseURL.dev": "http://192.168.1.152:8002/", 43 | "baseURL.uat": "https://api.xxx.com/", 44 | "baseURL.prod": "https://api.xxx.com/", 45 | "baseURL.mock": "" // mock不需要url 46 | } 47 | ``` 48 | 49 | 那么我们项目中只需要通过 `ProfilesLoader.keyOf('baseURL;)` 即可获取到 `baseURL` 在配置的 `profile.active` 下对应的值。 50 | 51 | ## Ioc容器 52 | 53 | 借用后端的思路,把常用的对象放在一个容器中,以便让全局程序使用同一个单例。 54 | 55 | 路径:`lib/infrastructure/ioc_container.dart` 56 | 57 | ## 权限管理和Mock数据 58 | 59 | `Mock` 数据集:`lib/mock/mock_holder.dart` 60 | 61 | 支持 `URL` 参数区分不同 `Handler`(类似于 `SpringMVC` 的 `params` 属性),注册 `URL` 信息到上面的类中,在开发使用 `mock` 的 `profile` 的时候,`NetTool` 即可查找到对应的 `Handler` 继而返回需要的数据。 62 | 63 | 测试用例:`test/net_tool_box_test.dart` 64 | 65 | 类似于用户登录授权: 66 | 67 | ```dart 68 | lib/mock/mock_data/user_data.dart 69 | PbResultDto userAuthenticate

({ 70 | P body, 71 | Map param 72 | }) { 73 | UserAuthenticateReqDto req = body as UserAuthenticateReqDto; 74 | UserAuthenticateRespDto r = UserAuthenticateRespDto(); 75 | if (req.userName == 'Weidan') { 76 | r.token = '112233'; 77 | r.resourceCodes.addAll(['deliverBillPick', 'deliverBillPick2']); 78 | } else { 79 | r.token = '334455'; 80 | r.resourceCodes.addAll(['deliverBillPick2']); 81 | } 82 | 83 | PbResultDto pbResultDto = PbResultDto(); 84 | pbResultDto.data = Any.pack(r); 85 | return pbResultDto; 86 | } 87 | ``` 88 | 89 | ## dashboard和权限管理 90 | 91 | 可以从上面看到,不同的登陆用户名有不同的权限集: 92 | 93 | `Weidan` 账号登陆: 94 | 95 | ![](assets/permission_1.jpeg) 96 | 97 | `其他登陆`: 98 | 99 | ![](assets/permission_2.jpeg) 100 | 101 | 可在 `dashboard` 中注册菜单、图表、路由以及需要的权限,`dashboard` 将会自动按需求渲染入口: 102 | 103 | ```dart 104 | lib/personal/dashboard_page.dart:14 105 | class DashboardPage extends PageStateLess { 106 | 107 | List _menuList(SystemState systemState, AuthenticationAuthenticated state, BuildContext buildContext) { 108 | List<_MenuBtn> menuBtns = []; 109 | /// 开始定义面板的功能按钮,第一个参数是以及标题,将会自动分类 110 | /// 第二个是对应的菜单名字的 i18n-key 111 | /// 第三个图表,第四个入口需要的权限 112 | menuBtns.add(_MenuBtn( 113 | 'dashboard.deliver.bill.title', 'dashboard.deliver.bill.pick', 114 | Icons.add_shopping_cart, 'deliverBillPick', DeliverBillPickIndexConst.pickIndexPath)); 115 | menuBtns.add(_MenuBtn( 116 | 'dashboard.deliver.bill.title', 'dashboard.deliver.bill.deliver', 117 | Icons.directions_car, 'deliverBillPick', DeliverBillPickIndexConst.loadingIndexPath)); 118 | menuBtns.add(_MenuBtn( 119 | 'dashboard.deliver.bill.title', 'dashboard.deliver.bill.audit', 120 | Icons.event, 'deliverBillPick', DeliverBillPickIndexConst.auditIndexPath)); 121 | menuBtns.add(_MenuBtn( 122 | 'dashboard.check.bill.title', 'dashboard.check.bill.auditing', 123 | Icons.assignment, 'deliverBillPick2', CheckBillIndexConst.checkBillIndexPath)); 124 | return _caculateMenuRow(systemState, state, menuBtns, buildContext); 125 | } 126 | //... 127 | } 128 | ``` 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /lib/mock/mock_holder.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter_cli_project/infrastructure/base_model/PbResultDto.pb.dart'; 4 | import 'package:protobuf/protobuf.dart' as $pb; 5 | 6 | import './mock_data/mock_data.dart' deferred as data; 7 | 8 | class MockData { 9 | 10 | static Map> uriRouter; 11 | static final Error NOT_FOUND_ERR = ArgumentError('resolve function not found!'); 12 | 13 | /// 只需要关注数据处理器即可 14 | static initRouter() async { 15 | // 惰性加载 16 | await data.loadLibrary(); 17 | uriRouter = Map>(); 18 | // Mock测试用例使用的数据 19 | _register('/v1/user/login', 'POST', data.testMock); 20 | _register('/v1/user/login?a=1', 'POST', data.testMock); 21 | _register( 22 | '/v1/user/login?a=1', 'POST', data.testMock, routeParam: {'b': '2'}); 23 | _register('/v1/authenticate/login', 'POST', data.userAuthenticate); 24 | } 25 | 26 | static _register( 27 | String uri, 28 | String method, 29 | Function mockFunction, 30 | { 31 | Map routeParam 32 | }) { 33 | 34 | String uriInfo = method.toUpperCase() + ' ' + uri; 35 | uriRouter[uriInfo] = Map(); 36 | Map p = Map(); 37 | if (routeParam != null) { 38 | routeParam.forEach((k, v) { 39 | p[k] = v; 40 | }); 41 | } 42 | if (uriInfo.contains('?')) { 43 | String uriParam = uriInfo.substring(uriInfo.indexOf('?') + 1); 44 | uriInfo = uriInfo.substring(0, uriInfo.indexOf('?')); 45 | for (var keyValue in uriParam.split('&')) { 46 | var value = keyValue.split('='); 47 | p[value[0]] = value[1]; 48 | } 49 | } 50 | if (p.isEmpty) { 51 | p['-'] = '-'; 52 | } 53 | 54 | var keySort = p.keys.toList(); 55 | keySort.sort(); 56 | String paramString = ''; 57 | for (var o in keySort) { 58 | final String val = p[o]; 59 | if (paramString != '') { 60 | paramString += '&'; 61 | } 62 | paramString += (o + '=' + val); 63 | } 64 | 65 | uriRouter[uriInfo][paramString] = mockFunction; 66 | } 67 | 68 | static Future fetch

(String uri, 69 | String method, { 70 | P body, 71 | Map uriParam 72 | }) async { 73 | await Future.delayed(Duration(seconds: _randomSecond())); 74 | 75 | // 拿到URI对应的参数以及处理器 76 | String uriInfo = method.toUpperCase() + ' ' + uri; 77 | // 解析上面的参数,拿到参数Map 78 | Map p = Map(); 79 | if (uriInfo.contains('?')) { 80 | String uriParam = uriInfo.substring(uriInfo.indexOf('?') + 1); 81 | uriInfo = uriInfo.substring(0, uriInfo.indexOf('?')); 82 | for (var keyValue in uriParam.split('&')) { 83 | var value = keyValue.split('='); 84 | p[value[0]] = value[1]; 85 | } 86 | } 87 | // 如果传递的参数Map不为空,继续插入上面的参数Map 88 | if (null != uriParam) { 89 | uriParam.forEach((key, value) { 90 | p[key] = value.toString(); 91 | }); 92 | } 93 | 94 | var uriParamFunction = uriRouter[uriInfo]; 95 | if (p.isEmpty) { 96 | var function = uriParamFunction['-=-']; 97 | if (function == null) { 98 | throw NOT_FOUND_ERR; 99 | } 100 | return function(body: body, param: p); 101 | } 102 | 103 | // 注册的时候必要的参数Map 104 | var keySort = p.keys.toList(); 105 | keySort.sort(); 106 | String _findParamString = ''; 107 | for (var o in keySort) { 108 | final String val = p[o]; 109 | if (_findParamString != '') { 110 | _findParamString += '&'; 111 | } 112 | _findParamString += (o + '=' + val); 113 | } 114 | 115 | if (null == _findParamString || null == uriParamFunction[_findParamString]) { 116 | throw NOT_FOUND_ERR; 117 | } 118 | return uriParamFunction[_findParamString](body: body, param: p); 119 | } 120 | 121 | static _randomSecond() { 122 | var waitSeconds = [1, 2, 3, 4, 5]; 123 | return waitSeconds[Random().nextInt(waitSeconds.length)]; 124 | } 125 | 126 | } -------------------------------------------------------------------------------- /lib/login/dto/UserAuthenticateDto.pb.dart: -------------------------------------------------------------------------------- 1 | /// 2 | // Generated code. Do not modify. 3 | // source: UserAuthenticateDto.proto 4 | // 5 | // @dart = 2.3 6 | // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type 7 | 8 | import 'dart:core' as $core; 9 | 10 | import 'package:protobuf/protobuf.dart' as $pb; 11 | 12 | class UserAuthenticateReqDto extends $pb.GeneratedMessage { 13 | static final $pb.BuilderInfo _i = $pb.BuilderInfo('UserAuthenticateReqDto', createEmptyInstance: create) 14 | ..aOS(1, 'userName', protoName: 'userName') 15 | ..aOS(2, 'password') 16 | ..hasRequiredFields = false 17 | ; 18 | 19 | UserAuthenticateReqDto._() : super(); 20 | factory UserAuthenticateReqDto() => create(); 21 | factory UserAuthenticateReqDto.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); 22 | factory UserAuthenticateReqDto.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); 23 | UserAuthenticateReqDto clone() => UserAuthenticateReqDto()..mergeFromMessage(this); 24 | UserAuthenticateReqDto copyWith(void Function(UserAuthenticateReqDto) updates) => super.copyWith((message) => updates(message as UserAuthenticateReqDto)); 25 | $pb.BuilderInfo get info_ => _i; 26 | @$core.pragma('dart2js:noInline') 27 | static UserAuthenticateReqDto create() => UserAuthenticateReqDto._(); 28 | UserAuthenticateReqDto createEmptyInstance() => create(); 29 | static $pb.PbList createRepeated() => $pb.PbList(); 30 | @$core.pragma('dart2js:noInline') 31 | static UserAuthenticateReqDto getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); 32 | static UserAuthenticateReqDto _defaultInstance; 33 | 34 | @$pb.TagNumber(1) 35 | $core.String get userName => $_getSZ(0); 36 | @$pb.TagNumber(1) 37 | set userName($core.String v) { $_setString(0, v); } 38 | @$pb.TagNumber(1) 39 | $core.bool hasUserName() => $_has(0); 40 | @$pb.TagNumber(1) 41 | void clearUserName() => clearField(1); 42 | 43 | @$pb.TagNumber(2) 44 | $core.String get password => $_getSZ(1); 45 | @$pb.TagNumber(2) 46 | set password($core.String v) { $_setString(1, v); } 47 | @$pb.TagNumber(2) 48 | $core.bool hasPassword() => $_has(1); 49 | @$pb.TagNumber(2) 50 | void clearPassword() => clearField(2); 51 | } 52 | 53 | class UserAuthenticateRespDto extends $pb.GeneratedMessage { 54 | static final $pb.BuilderInfo _i = $pb.BuilderInfo('UserAuthenticateRespDto', createEmptyInstance: create) 55 | ..aOS(1, 'token') 56 | ..pPS(2, 'resourceCodes', protoName: 'resourceCodes') 57 | ..hasRequiredFields = false 58 | ; 59 | 60 | UserAuthenticateRespDto._() : super(); 61 | factory UserAuthenticateRespDto() => create(); 62 | factory UserAuthenticateRespDto.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); 63 | factory UserAuthenticateRespDto.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); 64 | UserAuthenticateRespDto clone() => UserAuthenticateRespDto()..mergeFromMessage(this); 65 | UserAuthenticateRespDto copyWith(void Function(UserAuthenticateRespDto) updates) => super.copyWith((message) => updates(message as UserAuthenticateRespDto)); 66 | $pb.BuilderInfo get info_ => _i; 67 | @$core.pragma('dart2js:noInline') 68 | static UserAuthenticateRespDto create() => UserAuthenticateRespDto._(); 69 | UserAuthenticateRespDto createEmptyInstance() => create(); 70 | static $pb.PbList createRepeated() => $pb.PbList(); 71 | @$core.pragma('dart2js:noInline') 72 | static UserAuthenticateRespDto getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); 73 | static UserAuthenticateRespDto _defaultInstance; 74 | 75 | @$pb.TagNumber(1) 76 | $core.String get token => $_getSZ(0); 77 | @$pb.TagNumber(1) 78 | set token($core.String v) { $_setString(0, v); } 79 | @$pb.TagNumber(1) 80 | $core.bool hasToken() => $_has(0); 81 | @$pb.TagNumber(1) 82 | void clearToken() => clearField(1); 83 | 84 | @$pb.TagNumber(2) 85 | $core.List<$core.String> get resourceCodes => $_getList(1); 86 | } 87 | 88 | -------------------------------------------------------------------------------- /lib/infrastructure/base_model/PbResultDto.pb.dart: -------------------------------------------------------------------------------- 1 | /// 2 | // Generated code. Do not modify. 3 | // source: PbResultDto.proto 4 | // 5 | // @dart = 2.3 6 | // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type 7 | 8 | import 'dart:core' as $core; 9 | 10 | import 'package:protobuf/protobuf.dart' as $pb; 11 | 12 | import 'google/protobuf/any.pb.dart' as $0; 13 | 14 | class PbResultDto extends $pb.GeneratedMessage { 15 | static final $pb.BuilderInfo _i = $pb.BuilderInfo('PbResultDto', createEmptyInstance: create) 16 | ..aOB(1, 'success') 17 | ..aOS(2, 'message') 18 | ..aOS(3, 'code') 19 | ..aOM<$0.Any>(4, 'data', subBuilder: $0.Any.create) 20 | ..m<$core.String, ExtraMap>(5, 'extra', entryClassName: 'PbResultDto.ExtraEntry', keyFieldType: $pb.PbFieldType.OS, valueFieldType: $pb.PbFieldType.OM, valueCreator: ExtraMap.create) 21 | ..hasRequiredFields = false 22 | ; 23 | 24 | PbResultDto._() : super(); 25 | factory PbResultDto() => create(); 26 | factory PbResultDto.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); 27 | factory PbResultDto.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); 28 | PbResultDto clone() => PbResultDto()..mergeFromMessage(this); 29 | PbResultDto copyWith(void Function(PbResultDto) updates) => super.copyWith((message) => updates(message as PbResultDto)); 30 | $pb.BuilderInfo get info_ => _i; 31 | @$core.pragma('dart2js:noInline') 32 | static PbResultDto create() => PbResultDto._(); 33 | PbResultDto createEmptyInstance() => create(); 34 | static $pb.PbList createRepeated() => $pb.PbList(); 35 | @$core.pragma('dart2js:noInline') 36 | static PbResultDto getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); 37 | static PbResultDto _defaultInstance; 38 | 39 | @$pb.TagNumber(1) 40 | $core.bool get success => $_getBF(0); 41 | @$pb.TagNumber(1) 42 | set success($core.bool v) { $_setBool(0, v); } 43 | @$pb.TagNumber(1) 44 | $core.bool hasSuccess() => $_has(0); 45 | @$pb.TagNumber(1) 46 | void clearSuccess() => clearField(1); 47 | 48 | @$pb.TagNumber(2) 49 | $core.String get message => $_getSZ(1); 50 | @$pb.TagNumber(2) 51 | set message($core.String v) { $_setString(1, v); } 52 | @$pb.TagNumber(2) 53 | $core.bool hasMessage() => $_has(1); 54 | @$pb.TagNumber(2) 55 | void clearMessage() => clearField(2); 56 | 57 | @$pb.TagNumber(3) 58 | $core.String get code => $_getSZ(2); 59 | @$pb.TagNumber(3) 60 | set code($core.String v) { $_setString(2, v); } 61 | @$pb.TagNumber(3) 62 | $core.bool hasCode() => $_has(2); 63 | @$pb.TagNumber(3) 64 | void clearCode() => clearField(3); 65 | 66 | @$pb.TagNumber(4) 67 | $0.Any get data => $_getN(3); 68 | @$pb.TagNumber(4) 69 | set data($0.Any v) { setField(4, v); } 70 | @$pb.TagNumber(4) 71 | $core.bool hasData() => $_has(3); 72 | @$pb.TagNumber(4) 73 | void clearData() => clearField(4); 74 | @$pb.TagNumber(4) 75 | $0.Any ensureData() => $_ensure(3); 76 | 77 | @$pb.TagNumber(5) 78 | $core.Map<$core.String, ExtraMap> get extra => $_getMap(4); 79 | } 80 | 81 | class ExtraMap extends $pb.GeneratedMessage { 82 | static final $pb.BuilderInfo _i = $pb.BuilderInfo('ExtraMap', createEmptyInstance: create) 83 | ..m<$core.String, $core.String>(1, 'extra', entryClassName: 'ExtraMap.ExtraEntry', keyFieldType: $pb.PbFieldType.OS, valueFieldType: $pb.PbFieldType.OS) 84 | ..hasRequiredFields = false 85 | ; 86 | 87 | ExtraMap._() : super(); 88 | factory ExtraMap() => create(); 89 | factory ExtraMap.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); 90 | factory ExtraMap.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); 91 | ExtraMap clone() => ExtraMap()..mergeFromMessage(this); 92 | ExtraMap copyWith(void Function(ExtraMap) updates) => super.copyWith((message) => updates(message as ExtraMap)); 93 | $pb.BuilderInfo get info_ => _i; 94 | @$core.pragma('dart2js:noInline') 95 | static ExtraMap create() => ExtraMap._(); 96 | ExtraMap createEmptyInstance() => create(); 97 | static $pb.PbList createRepeated() => $pb.PbList(); 98 | @$core.pragma('dart2js:noInline') 99 | static ExtraMap getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); 100 | static ExtraMap _defaultInstance; 101 | 102 | @$pb.TagNumber(1) 103 | $core.Map<$core.String, $core.String> get extra => $_getMap(0); 104 | } 105 | 106 | -------------------------------------------------------------------------------- /.packages: -------------------------------------------------------------------------------- 1 | # Generated by pub on 2020-05-06 15:13:17.806343. 2 | archive:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/archive-2.0.11/lib/ 3 | args:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/args-1.5.2/lib/ 4 | async:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/async-2.4.0/lib/ 5 | bloc:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/bloc-4.0.0/lib/ 6 | boolean_selector:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/boolean_selector-1.0.5/lib/ 7 | charcode:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/charcode-1.1.2/lib/ 8 | collection:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/collection-1.14.11/lib/ 9 | convert:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/convert-2.1.1/lib/ 10 | cookie_jar:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/cookie_jar-1.0.1/lib/ 11 | crypto:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/crypto-2.1.3/lib/ 12 | dio:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/dio-2.2.2/lib/ 13 | equatable:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/equatable-1.1.1/lib/ 14 | fixnum:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/fixnum-0.10.11/lib/ 15 | flutter:file:///Users/liweidan/Develop/middleware/flutter/packages/flutter/lib/ 16 | flutter_bloc:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/flutter_bloc-4.0.0/lib/ 17 | flutter_test:file:///Users/liweidan/Develop/middleware/flutter/packages/flutter_test/lib/ 18 | flutter_web_plugins:file:///Users/liweidan/Develop/middleware/flutter/packages/flutter_web_plugins/lib/ 19 | fluttertoast:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/fluttertoast-3.1.3/lib/ 20 | image:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/image-2.1.4/lib/ 21 | matcher:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/matcher-0.12.6/lib/ 22 | meta:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/meta-1.1.8/lib/ 23 | nested:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/nested-0.0.4/lib/ 24 | path:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/path-1.6.4/lib/ 25 | pedantic:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/pedantic-1.8.0+1/lib/ 26 | petitparser:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/petitparser-2.4.0/lib/ 27 | protobuf:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/protobuf-1.0.1/lib/ 28 | provider:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/provider-4.0.5+1/lib/ 29 | quiver:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/quiver-2.0.5/lib/ 30 | shared_preferences:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/shared_preferences-0.5.7+1/lib/ 31 | shared_preferences_macos:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/shared_preferences_macos-0.0.1+8/lib/ 32 | shared_preferences_platform_interface:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/shared_preferences_platform_interface-1.0.3/lib/ 33 | shared_preferences_web:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/shared_preferences_web-0.1.2+5/lib/ 34 | sky_engine:file:///Users/liweidan/Develop/middleware/flutter/bin/cache/pkg/sky_engine/lib/ 35 | source_span:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/source_span-1.5.5/lib/ 36 | stack_trace:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/stack_trace-1.9.3/lib/ 37 | stream_channel:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/stream_channel-2.0.0/lib/ 38 | string_scanner:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/string_scanner-1.0.5/lib/ 39 | term_glyph:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/term_glyph-1.1.0/lib/ 40 | test_api:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/test_api-0.2.11/lib/ 41 | typed_data:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/typed_data-1.1.6/lib/ 42 | vector_math:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/vector_math-2.0.8/lib/ 43 | xml:file:///Users/liweidan/Develop/middleware/flutter/.pub-cache/hosted/pub.flutter-io.cn/xml-3.5.0/lib/ 44 | flutter_cli_project:lib/ 45 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /lib/components/common_scaffold.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/src/widgets/framework.dart'; 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:flutter_cli_project/infrastructure/context_util.dart'; 5 | import 'package:flutter_cli_project/infrastructure/toast_tool.dart'; 6 | import 'package:flutter_cli_project/main_app/authenticate_bloc.dart'; 7 | import 'package:flutter_cli_project/main_app/system_bloc.dart'; 8 | 9 | class CommonScaffold extends PageStateLess { 10 | 11 | final title; 12 | final Widget body; 13 | final bool showDrawer; 14 | final bool showBackBtn; 15 | 16 | CommonScaffold({ 17 | @required this.body, 18 | this.title, 19 | this.showDrawer = true, 20 | this.showBackBtn = false 21 | }); 22 | 23 | @override 24 | Widget build0(BuildContext context) { 25 | return BlocBuilder( 26 | builder: (_, state) { 27 | var title = this.title == null 28 | ? state.i18nBox.getText('global.title') 29 | : this.title; 30 | return Scaffold( 31 | backgroundColor: state.theme.backgroundColor, 32 | appBar: AppBar( 33 | title: Text(title), 34 | leading: showBackBtn ? IconButton( 35 | icon: Icon(Icons.arrow_back_ios, color: Colors.white), //自定义图标 36 | onPressed: () { 37 | // 打开抽屉菜单 38 | Navigator.of(context).pop(); 39 | }, 40 | ) : null, 41 | ), 42 | body: this.body, 43 | drawer: showDrawer ? AppDrawer() : null 44 | ); 45 | }, 46 | ); 47 | } 48 | 49 | } 50 | 51 | class AppDrawer extends PageStateLess { 52 | 53 | @override 54 | Widget build0(BuildContext context) { 55 | return Drawer( 56 | child: ListView( 57 | padding: EdgeInsets.zero, 58 | children: [ 59 | BlocBuilder( 60 | builder: (_, state) { 61 | final s = state as AuthenticationAuthenticated; 62 | return UserAccountsDrawerHeader( 63 | accountName: Text(s.userName()), 64 | accountEmail: Text(""), 65 | currentAccountPicture: CircleAvatar( 66 | backgroundImage: AssetImage('assets/imgs/logo.jpeg'), 67 | ), 68 | ); 69 | }, 70 | ), 71 | ListTile( 72 | title: BlocBuilder( 73 | builder: (_, state) { 74 | return Text( 75 | state.i18nBox.getText('common.drawer.theme.setting'), 76 | style: TextStyle(fontWeight: FontWeight.w100, fontSize: 18.0), 77 | ); 78 | }, 79 | ), 80 | leading: Icon( 81 | Icons.collections, 82 | color: Colors.blue, 83 | ), 84 | onTap: () { 85 | // 弹出themeSetting的之前的路由信息 86 | Navigator.of(context).pushNamedAndRemoveUntil('/themeSetting', (Route route) { 87 | return route.settings.name == '/'||route.settings.name == '/main'; 88 | }); 89 | }, 90 | ), 91 | ListTile( 92 | title: BlocBuilder( 93 | builder: (_, state) { 94 | return Text( 95 | state.i18nBox.getText('common.drawer.dashboard'), 96 | style: TextStyle(fontWeight: FontWeight.w100, fontSize: 18.0), 97 | ); 98 | }, 99 | ), 100 | leading: Icon( 101 | Icons.dashboard, 102 | color: Colors.red, 103 | ), 104 | onTap: () { 105 | // 路由到面板的时候永远是路由的顶层 106 | Navigator.of(context).pushNamedAndRemoveUntil("/main", (Route route) => false); 107 | }, 108 | ), 109 | ListTile( 110 | title: BlocBuilder( 111 | builder: (_, state) { 112 | return Text( 113 | state.i18nBox.getText('common.drawer.operator.log'), 114 | style: TextStyle(fontWeight: FontWeight.w100, fontSize: 18.0), 115 | ); 116 | }, 117 | ), 118 | leading: Icon( 119 | Icons.timeline, 120 | color: Colors.cyan, 121 | ), 122 | onTap: () { 123 | ToastTool.shortOfKey('common.drawer.nothing'); 124 | }, 125 | ), 126 | Divider(), 127 | ListTile( 128 | title: BlocBuilder( 129 | builder: (_, state) { 130 | return Text( 131 | state.i18nBox.getText('common.drawer.pda.setting'), 132 | style: TextStyle(fontWeight: FontWeight.w100, fontSize: 18.0), 133 | ); 134 | }, 135 | ), 136 | leading: Icon( 137 | Icons.settings, 138 | color: Colors.brown, 139 | ), 140 | onTap: () { 141 | ToastTool.shortOfKey('common.drawer.nothing'); 142 | }, 143 | ), 144 | Divider(), 145 | ListTile( 146 | title: BlocBuilder( 147 | builder: (_, state) { 148 | return Text( 149 | state.i18nBox.getText('common.drawer.lang.setting'), 150 | style: TextStyle(fontWeight: FontWeight.w100, fontSize: 18.0), 151 | ); 152 | }, 153 | ), 154 | leading: Icon( 155 | Icons.golf_course, 156 | color: Colors.brown, 157 | ), 158 | onTap: () { 159 | _switchSystemLang(context); 160 | }, 161 | ), 162 | ], 163 | ), 164 | ); 165 | } 166 | 167 | void _switchSystemLang(BuildContext context) { 168 | var systemBloc = BlocProvider.of(context); 169 | systemBloc.state.i18nBox.switchLangList(); 170 | } 171 | 172 | } -------------------------------------------------------------------------------- /lib/login/login_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/src/widgets/framework.dart'; 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:flutter_cli_project/infrastructure/context_util.dart'; 5 | import 'package:flutter_cli_project/infrastructure/profiles_loader.dart'; 6 | import 'package:flutter_cli_project/login/login_bloc.dart'; 7 | import 'package:flutter_cli_project/main_app/authenticate_bloc.dart'; 8 | import 'package:flutter_cli_project/main_app/common_logo.dart'; 9 | import 'package:flutter_cli_project/main_app/system_bloc.dart'; 10 | 11 | class LoginPage extends PageStateFul { 12 | 13 | @override 14 | State createState0() { 15 | return _LoginState(); 16 | } 17 | 18 | } 19 | 20 | class _LoginState extends State { 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | return build0(context); 25 | } 26 | 27 | final TextEditingController _unameController = new TextEditingController(); 28 | final TextEditingController _pwdController = new TextEditingController(); 29 | GlobalKey _formKey = new GlobalKey(); 30 | 31 | Widget build0(BuildContext context) { 32 | return BlocBuilder( 33 | builder: (_, state) { 34 | return Scaffold( 35 | backgroundColor: Colors.white, 36 | body: Center( 37 | child: loginBody(_), 38 | ), 39 | ); 40 | }, 41 | ); 42 | } 43 | 44 | loginBody(BuildContext context) => SingleChildScrollView( 45 | child: SingleChildScrollView( 46 | child: Column( 47 | mainAxisAlignment: MainAxisAlignment.spaceAround, 48 | children: [loginHeader(context), loginFields(context)], 49 | ), 50 | ) 51 | ); 52 | 53 | loginHeader(BuildContext context) { 54 | var systemState = context.bloc().state; 55 | String loginTitle = systemState.i18nBox.getText('login.title'); 56 | 57 | return Column( 58 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 59 | children: [ 60 | CommonLogo(), 61 | Text( 62 | loginTitle, 63 | style: TextStyle(fontWeight: FontWeight.w300, color: Colors.grey), 64 | ), 65 | SizedBox( 66 | height: 30.0, 67 | ), 68 | ], 69 | ); 70 | } 71 | 72 | loginFields(BuildContext context) { 73 | var systemState = context.bloc().state; 74 | var authenticationBloc = context.bloc(); 75 | String uNameTitle = systemState.i18nBox.getText('login.input.title'); 76 | String pwdTitle = systemState.i18nBox.getText('login.input.password'); 77 | String loginBtnTitle = systemState.i18nBox.getText('login.btn.login'); 78 | String nameEmptyMsg = systemState.i18nBox.getText('login.input.notempty.title'); 79 | String passwordEmptyMsg = systemState.i18nBox.getText('login.input.notempty.password'); 80 | return BlocProvider( 81 | create: (BuildContext context) => LoginBloc(authenticationBloc: authenticationBloc), 82 | child: Form( 83 | key: _formKey, 84 | child: Column( 85 | mainAxisAlignment: MainAxisAlignment.spaceAround, 86 | mainAxisSize: MainAxisSize.min, 87 | children: [ 88 | Container( 89 | padding: EdgeInsets.symmetric(vertical: 16.0, horizontal: 30.0), 90 | child: TextFormField( 91 | controller: _unameController, 92 | decoration: InputDecoration( 93 | labelText: uNameTitle, 94 | hintText: uNameTitle, 95 | prefixIcon: Icon(Icons.person), 96 | ), 97 | validator: (v) { 98 | return v.isNotEmpty ? null : nameEmptyMsg; 99 | } 100 | ), 101 | ), 102 | Container( 103 | padding: EdgeInsets.symmetric(vertical: 0.0, horizontal: 30.0), 104 | child: TextFormField( 105 | maxLines: 1, 106 | obscureText: true, 107 | decoration: InputDecoration( 108 | hintText: pwdTitle, 109 | labelText: pwdTitle, 110 | prefixIcon: Icon(Icons.lock), 111 | ), 112 | controller: _pwdController, 113 | validator: (v) { 114 | return v.isNotEmpty ? null : passwordEmptyMsg; 115 | }, 116 | ), 117 | ), 118 | SizedBox( 119 | height: 20.0, 120 | ), 121 | BlocBuilder( 122 | builder: (context, state) { 123 | return state is LoginLoading ? _loginingProgress():Container( 124 | padding: EdgeInsets.symmetric( 125 | vertical: 0.0, horizontal: 30.0), 126 | width: double.infinity, 127 | child: _loginButton(loginBtnTitle, context) 128 | ); 129 | }, 130 | ), 131 | 132 | ], 133 | ), 134 | ), 135 | ); 136 | } 137 | 138 | CircularProgressIndicator _loginingProgress() { 139 | return CircularProgressIndicator( 140 | backgroundColor: Colors.grey[200], 141 | valueColor: AlwaysStoppedAnimation(Colors.blue), 142 | ); 143 | } 144 | 145 | RaisedButton _loginButton(String loginBtnTitle, BuildContext context) { 146 | return RaisedButton( 147 | padding: EdgeInsets.all(12.0), 148 | shape: StadiumBorder(), 149 | child: Text( 150 | loginBtnTitle, 151 | style: TextStyle(color: Colors.white), 152 | ), 153 | color: Colors.blue, 154 | onPressed: () { 155 | _onLoginBtnClick(context); 156 | }, 157 | ); 158 | } 159 | 160 | _onLoginBtnClick(BuildContext context) { 161 | var currentState = _formKey.currentState as FormState; 162 | var loginBloc = BlocProvider.of(context); 163 | print(ProfilesLoader.keyOf('baseURL')); 164 | 165 | if (currentState.validate()) { 166 | loginBloc.add( 167 | LoginButtonPressed( 168 | username: _unameController.text, 169 | password: _pwdController.text 170 | ) 171 | ); 172 | } 173 | } 174 | 175 | } 176 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | archive: 5 | dependency: transitive 6 | description: 7 | name: archive 8 | url: "https://pub.flutter-io.cn" 9 | source: hosted 10 | version: "2.0.11" 11 | args: 12 | dependency: transitive 13 | description: 14 | name: args 15 | url: "https://pub.flutter-io.cn" 16 | source: hosted 17 | version: "1.5.2" 18 | async: 19 | dependency: transitive 20 | description: 21 | name: async 22 | url: "https://pub.flutter-io.cn" 23 | source: hosted 24 | version: "2.4.0" 25 | bloc: 26 | dependency: transitive 27 | description: 28 | name: bloc 29 | url: "https://pub.flutter-io.cn" 30 | source: hosted 31 | version: "4.0.0" 32 | boolean_selector: 33 | dependency: transitive 34 | description: 35 | name: boolean_selector 36 | url: "https://pub.flutter-io.cn" 37 | source: hosted 38 | version: "1.0.5" 39 | charcode: 40 | dependency: transitive 41 | description: 42 | name: charcode 43 | url: "https://pub.flutter-io.cn" 44 | source: hosted 45 | version: "1.1.2" 46 | collection: 47 | dependency: transitive 48 | description: 49 | name: collection 50 | url: "https://pub.flutter-io.cn" 51 | source: hosted 52 | version: "1.14.11" 53 | convert: 54 | dependency: transitive 55 | description: 56 | name: convert 57 | url: "https://pub.flutter-io.cn" 58 | source: hosted 59 | version: "2.1.1" 60 | cookie_jar: 61 | dependency: transitive 62 | description: 63 | name: cookie_jar 64 | url: "https://pub.flutter-io.cn" 65 | source: hosted 66 | version: "1.0.1" 67 | crypto: 68 | dependency: transitive 69 | description: 70 | name: crypto 71 | url: "https://pub.flutter-io.cn" 72 | source: hosted 73 | version: "2.1.3" 74 | dio: 75 | dependency: "direct main" 76 | description: 77 | name: dio 78 | url: "https://pub.flutter-io.cn" 79 | source: hosted 80 | version: "2.2.2" 81 | equatable: 82 | dependency: "direct main" 83 | description: 84 | name: equatable 85 | url: "https://pub.flutter-io.cn" 86 | source: hosted 87 | version: "1.1.1" 88 | fixnum: 89 | dependency: transitive 90 | description: 91 | name: fixnum 92 | url: "https://pub.flutter-io.cn" 93 | source: hosted 94 | version: "0.10.11" 95 | flutter: 96 | dependency: "direct main" 97 | description: flutter 98 | source: sdk 99 | version: "0.0.0" 100 | flutter_bloc: 101 | dependency: "direct main" 102 | description: 103 | name: flutter_bloc 104 | url: "https://pub.flutter-io.cn" 105 | source: hosted 106 | version: "4.0.0" 107 | flutter_test: 108 | dependency: "direct dev" 109 | description: flutter 110 | source: sdk 111 | version: "0.0.0" 112 | flutter_web_plugins: 113 | dependency: transitive 114 | description: flutter 115 | source: sdk 116 | version: "0.0.0" 117 | fluttertoast: 118 | dependency: "direct main" 119 | description: 120 | name: fluttertoast 121 | url: "https://pub.flutter-io.cn" 122 | source: hosted 123 | version: "3.1.3" 124 | image: 125 | dependency: transitive 126 | description: 127 | name: image 128 | url: "https://pub.flutter-io.cn" 129 | source: hosted 130 | version: "2.1.4" 131 | matcher: 132 | dependency: transitive 133 | description: 134 | name: matcher 135 | url: "https://pub.flutter-io.cn" 136 | source: hosted 137 | version: "0.12.6" 138 | meta: 139 | dependency: transitive 140 | description: 141 | name: meta 142 | url: "https://pub.flutter-io.cn" 143 | source: hosted 144 | version: "1.1.8" 145 | nested: 146 | dependency: transitive 147 | description: 148 | name: nested 149 | url: "https://pub.flutter-io.cn" 150 | source: hosted 151 | version: "0.0.4" 152 | path: 153 | dependency: transitive 154 | description: 155 | name: path 156 | url: "https://pub.flutter-io.cn" 157 | source: hosted 158 | version: "1.6.4" 159 | pedantic: 160 | dependency: transitive 161 | description: 162 | name: pedantic 163 | url: "https://pub.flutter-io.cn" 164 | source: hosted 165 | version: "1.8.0+1" 166 | petitparser: 167 | dependency: transitive 168 | description: 169 | name: petitparser 170 | url: "https://pub.flutter-io.cn" 171 | source: hosted 172 | version: "2.4.0" 173 | protobuf: 174 | dependency: "direct main" 175 | description: 176 | name: protobuf 177 | url: "https://pub.flutter-io.cn" 178 | source: hosted 179 | version: "1.0.1" 180 | provider: 181 | dependency: transitive 182 | description: 183 | name: provider 184 | url: "https://pub.flutter-io.cn" 185 | source: hosted 186 | version: "4.0.5+1" 187 | quiver: 188 | dependency: transitive 189 | description: 190 | name: quiver 191 | url: "https://pub.flutter-io.cn" 192 | source: hosted 193 | version: "2.0.5" 194 | shared_preferences: 195 | dependency: "direct main" 196 | description: 197 | name: shared_preferences 198 | url: "https://pub.flutter-io.cn" 199 | source: hosted 200 | version: "0.5.7+1" 201 | shared_preferences_macos: 202 | dependency: transitive 203 | description: 204 | name: shared_preferences_macos 205 | url: "https://pub.flutter-io.cn" 206 | source: hosted 207 | version: "0.0.1+8" 208 | shared_preferences_platform_interface: 209 | dependency: transitive 210 | description: 211 | name: shared_preferences_platform_interface 212 | url: "https://pub.flutter-io.cn" 213 | source: hosted 214 | version: "1.0.3" 215 | shared_preferences_web: 216 | dependency: transitive 217 | description: 218 | name: shared_preferences_web 219 | url: "https://pub.flutter-io.cn" 220 | source: hosted 221 | version: "0.1.2+5" 222 | sky_engine: 223 | dependency: transitive 224 | description: flutter 225 | source: sdk 226 | version: "0.0.99" 227 | source_span: 228 | dependency: transitive 229 | description: 230 | name: source_span 231 | url: "https://pub.flutter-io.cn" 232 | source: hosted 233 | version: "1.5.5" 234 | stack_trace: 235 | dependency: transitive 236 | description: 237 | name: stack_trace 238 | url: "https://pub.flutter-io.cn" 239 | source: hosted 240 | version: "1.9.3" 241 | stream_channel: 242 | dependency: transitive 243 | description: 244 | name: stream_channel 245 | url: "https://pub.flutter-io.cn" 246 | source: hosted 247 | version: "2.0.0" 248 | string_scanner: 249 | dependency: transitive 250 | description: 251 | name: string_scanner 252 | url: "https://pub.flutter-io.cn" 253 | source: hosted 254 | version: "1.0.5" 255 | term_glyph: 256 | dependency: transitive 257 | description: 258 | name: term_glyph 259 | url: "https://pub.flutter-io.cn" 260 | source: hosted 261 | version: "1.1.0" 262 | test_api: 263 | dependency: transitive 264 | description: 265 | name: test_api 266 | url: "https://pub.flutter-io.cn" 267 | source: hosted 268 | version: "0.2.11" 269 | typed_data: 270 | dependency: transitive 271 | description: 272 | name: typed_data 273 | url: "https://pub.flutter-io.cn" 274 | source: hosted 275 | version: "1.1.6" 276 | vector_math: 277 | dependency: transitive 278 | description: 279 | name: vector_math 280 | url: "https://pub.flutter-io.cn" 281 | source: hosted 282 | version: "2.0.8" 283 | xml: 284 | dependency: transitive 285 | description: 286 | name: xml 287 | url: "https://pub.flutter-io.cn" 288 | source: hosted 289 | version: "3.5.0" 290 | sdks: 291 | dart: ">=2.6.0 <3.0.0" 292 | flutter: ">=1.12.13+hotfix.5 <2.0.0" 293 | -------------------------------------------------------------------------------- /lib/personal/dashboard_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:collection'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/src/widgets/framework.dart'; 5 | import 'package:flutter_bloc/flutter_bloc.dart'; 6 | import 'package:flutter_cli_project/components/common_scaffold.dart'; 7 | import 'package:flutter_cli_project/infrastructure/context_util.dart'; 8 | import 'package:flutter_cli_project/infrastructure/toast_tool.dart'; 9 | import 'package:flutter_cli_project/main_app/authenticate_bloc.dart'; 10 | import 'package:flutter_cli_project/main_app/system_bloc.dart'; 11 | import 'package:flutter_cli_project/services/check_bill/check_bill_routers.dart'; 12 | import 'package:flutter_cli_project/services/deliver_bill_pick/deliver_bill_routers.dart'; 13 | 14 | class DashboardPage extends PageStateLess { 15 | 16 | List _menuList(SystemState systemState, AuthenticationAuthenticated state, BuildContext buildContext) { 17 | List<_MenuBtn> menuBtns = []; 18 | /// 开始定义面板的功能按钮 19 | menuBtns.add(_MenuBtn( 20 | 'dashboard.deliver.bill.title', 'dashboard.deliver.bill.pick', 21 | Icons.add_shopping_cart, 'deliverBillPick', DeliverBillPickIndexConst.pickIndexPath)); 22 | menuBtns.add(_MenuBtn( 23 | 'dashboard.deliver.bill.title', 'dashboard.deliver.bill.deliver', 24 | Icons.directions_car, 'deliverBillPick', DeliverBillPickIndexConst.loadingIndexPath)); 25 | menuBtns.add(_MenuBtn( 26 | 'dashboard.deliver.bill.title', 'dashboard.deliver.bill.audit', 27 | Icons.event, 'deliverBillPick', DeliverBillPickIndexConst.auditIndexPath)); 28 | menuBtns.add(_MenuBtn( 29 | 'dashboard.check.bill.title', 'dashboard.check.bill.auditing', 30 | Icons.assignment, 'deliverBillPick2', CheckBillIndexConst.checkBillIndexPath)); 31 | return _caculateMenuRow(systemState, state, menuBtns, buildContext); 32 | } 33 | 34 | @override 35 | Widget build0(BuildContext context) { 36 | return CommonScaffold( 37 | body: BlocBuilder ( 38 | builder: (_, state) { 39 | var authBloc = BlocProvider.of(context); 40 | return SingleChildScrollView( 41 | child: Padding( 42 | padding: const EdgeInsets.all(8.0), 43 | child: Column( 44 | children: _menuList(state, authBloc.state, _), 45 | ) 46 | ), 47 | ); 48 | }, 49 | ) 50 | ); 51 | 52 | } 53 | 54 | /// 根据注册的MenuBtn,结合一级标题和权限代码决定是否给予渲染. 55 | List _caculateMenuRow(SystemState systemState, 56 | AuthenticationAuthenticated state, List<_MenuBtn> menuBtns, BuildContext buildContext) { 57 | /// 按一级标题分组 58 | Map> first2Btn = LinkedHashMap>(); 59 | for (var value in menuBtns) { 60 | var first2btns = first2Btn[value.firstTitle]; 61 | if (null == first2btns) { 62 | first2Btn[value.firstTitle] = [value]; 63 | } else { 64 | first2btns.add(value); 65 | } 66 | } 67 | 68 | List wgts = []; 69 | var resourceCode = state.resourceCodes; 70 | for (var entry in first2Btn.entries) { 71 | List<_MenuBtn> list = List.from(entry.value); 72 | list.retainWhere((menuBtn) => resourceCode.contains(menuBtn.resourceCode)); 73 | if (list.isEmpty) { 74 | continue; 75 | } 76 | 77 | if (wgts.isNotEmpty) { 78 | wgts.add(SizedBox(height: 10.0)); 79 | } 80 | 81 | wgts.add( 82 | Padding( 83 | padding: const EdgeInsets.all(8.0), 84 | child: Center( 85 | child: Text( 86 | systemState.i18nBox.getText(entry.key), 87 | style: 88 | TextStyle(fontWeight: FontWeight.w700, fontSize: 20.0), 89 | ), 90 | ), 91 | ) 92 | ); 93 | wgts.add( 94 | SizedBox( 95 | height: 10.0, 96 | ) 97 | ); 98 | 99 | int prevRow = (0 ~/ 3).toInt(); 100 | List<_MenuBtn> _temp = []; 101 | for (int i = 0; i < list.length; i++) { 102 | // 换行,把之前的放进去,然后清空 103 | if ((i ~/ 3).toInt() != prevRow) { 104 | _addMenuRow(wgts, systemState, _temp, buildContext); 105 | prevRow = (i ~/ 3).toInt(); 106 | } 107 | 108 | _temp.add(list[i]); 109 | 110 | if (i == list.length - 1) { 111 | _addMenuRow(wgts, systemState, _temp, buildContext); 112 | } 113 | } 114 | } 115 | return wgts; 116 | } 117 | 118 | void _addMenuRow(List wgts, SystemState systemState, List<_MenuBtn> _temp, BuildContext buildContext) { 119 | wgts.add( 120 | _DashboardMenuRow( 121 | firstIcon: _temp.length > 0 ? _temp[0].icon : null, 122 | firstLabel: _temp.length > 0 ? systemState.i18nBox 123 | .getText(_temp[0].label) : null, 124 | firstPath: _temp.length > 0 ? _temp[0].routePath : null, 125 | secondIcon: _temp.length > 1 ? _temp[1].icon : null, 126 | secondLabel: _temp.length > 1 ? systemState.i18nBox 127 | .getText(_temp[1].label) : null, 128 | secondPath: _temp.length > 1 ? _temp[1].routePath : null, 129 | thirdIcon: _temp.length > 2 ? _temp[2].icon : null, 130 | thirdLabel: _temp.length > 2 ? systemState.i18nBox 131 | .getText(_temp[2].label) : null, 132 | thirdPath: _temp.length > 2 ? _temp[2].routePath : null, 133 | ) 134 | ); 135 | _temp.clear(); 136 | } 137 | 138 | } 139 | 140 | class _MenuBtn { 141 | /// 一级标题 142 | final firstTitle; 143 | final label; 144 | final IconData icon; 145 | final resourceCode; 146 | final routePath; 147 | 148 | _MenuBtn(this.firstTitle, this.label, this.icon, this.resourceCode, 149 | this.routePath); 150 | 151 | } 152 | 153 | class _DashboardMenuRow extends PageStateLess { 154 | final firstLabel; 155 | final IconData firstIcon; 156 | final firstPath; 157 | final secondLabel; 158 | final IconData secondIcon; 159 | final secondPath; 160 | final thirdLabel; 161 | final IconData thirdIcon; 162 | final thirdPath; 163 | 164 | 165 | _DashboardMenuRow({this.firstLabel, this.firstIcon, this.firstPath, 166 | this.secondLabel, this.secondIcon, this.secondPath, this.thirdLabel, 167 | this.thirdIcon, this.thirdPath}); 168 | 169 | @override 170 | Widget build0(BuildContext context) { 171 | Size deviceSize = MediaQuery.of(context).size; 172 | List widgets = []; 173 | if (firstIcon != null && firstLabel != null) { 174 | widgets.add(SizedBox.fromSize( 175 | size: Size.square(deviceSize.width / 3.3), 176 | child: Hero( 177 | tag: firstPath, 178 | child: LabelBelowIcon( 179 | betweenHeight: 15.0, 180 | icon: firstIcon, 181 | label: firstLabel, 182 | iconColor: Colors.indigo.shade800, 183 | isCircleEnabled: false, 184 | onPressed: () { 185 | _toPage(context, firstPath); 186 | }, 187 | ), 188 | ) 189 | )); 190 | } 191 | if (secondIcon != null && secondLabel != null) { 192 | widgets.add(SizedBox.fromSize( 193 | size: Size.square(deviceSize.width / 3.3), 194 | child: Hero( 195 | tag: secondPath, 196 | child: LabelBelowIcon( 197 | betweenHeight: 15.0, 198 | icon: secondIcon, 199 | label: secondLabel, 200 | iconColor: Colors.indigo.shade800, 201 | isCircleEnabled: false, 202 | onPressed: () { 203 | _toPage(context, secondPath); 204 | }, 205 | ), 206 | ) 207 | )); 208 | } 209 | if (thirdIcon != null && thirdLabel != null) { 210 | widgets.add(SizedBox.fromSize( 211 | size: Size.square(deviceSize.width / 3.3), 212 | child: Hero( 213 | tag: thirdPath, 214 | child: LabelBelowIcon( 215 | betweenHeight: 15.0, 216 | icon: thirdIcon, 217 | label: thirdLabel, 218 | iconColor: Colors.indigo.shade800, 219 | isCircleEnabled: false, 220 | onPressed: () { 221 | _toPage(context, thirdPath); 222 | }, 223 | ), 224 | ) 225 | )); 226 | } 227 | 228 | return Padding( 229 | padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 2.0), 230 | child: Row( 231 | mainAxisSize: MainAxisSize.max, 232 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 233 | crossAxisAlignment: CrossAxisAlignment.center, 234 | children: widgets, 235 | ), 236 | ); 237 | } 238 | 239 | void _toPage(BuildContext context, String path) { 240 | if (path != null && path != '') { 241 | Navigator.of(context).pushNamed(path); 242 | } else { 243 | ToastTool.shortOfKey('common.drawer.nothing'); 244 | } 245 | } 246 | } 247 | 248 | class LabelBelowIcon extends PageStateLess { 249 | final label; 250 | final IconData icon; 251 | final iconColor; 252 | final onPressed; 253 | final circleColor; 254 | final isCircleEnabled; 255 | final betweenHeight; 256 | 257 | LabelBelowIcon( 258 | {this.label, 259 | this.icon, 260 | this.onPressed, 261 | this.iconColor = Colors.white, 262 | this.circleColor, 263 | this.isCircleEnabled = true, 264 | this.betweenHeight = 5.0}); 265 | @override 266 | Widget build0(BuildContext context) { 267 | return Card( 268 | child: Padding( 269 | padding: EdgeInsets.all(0.0), 270 | child: InkWell( 271 | onTap: onPressed, 272 | child: Column( 273 | mainAxisAlignment: MainAxisAlignment.center, 274 | crossAxisAlignment: CrossAxisAlignment.center, 275 | children: [ 276 | isCircleEnabled 277 | ? CircleAvatar( 278 | backgroundColor: circleColor, 279 | radius: 20.0, 280 | child: Icon( 281 | icon, 282 | size: 12.0, 283 | color: iconColor, 284 | ), 285 | ) 286 | : Icon( 287 | icon, 288 | size: 23.0, 289 | color: iconColor, 290 | ), 291 | SizedBox( 292 | height: betweenHeight, 293 | ), 294 | Text( 295 | label, 296 | textAlign: TextAlign.center, 297 | ) 298 | ], 299 | ), 300 | ), 301 | ), 302 | ); 303 | } 304 | } 305 | -------------------------------------------------------------------------------- /.idea/libraries/Dart_Packages.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 13 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 14 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 15 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 16 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 17 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 18 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 19 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 20 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXCopyFilesBuildPhase section */ 24 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 25 | isa = PBXCopyFilesBuildPhase; 26 | buildActionMask = 2147483647; 27 | dstPath = ""; 28 | dstSubfolderSpec = 10; 29 | files = ( 30 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, 31 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, 32 | ); 33 | name = "Embed Frameworks"; 34 | runOnlyForDeploymentPostprocessing = 0; 35 | }; 36 | /* End PBXCopyFilesBuildPhase section */ 37 | 38 | /* Begin PBXFileReference section */ 39 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 40 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 41 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 42 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 43 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 44 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 45 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 46 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 47 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 48 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 49 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 50 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 51 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 52 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 53 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 54 | /* End PBXFileReference section */ 55 | 56 | /* Begin PBXFrameworksBuildPhase section */ 57 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 58 | isa = PBXFrameworksBuildPhase; 59 | buildActionMask = 2147483647; 60 | files = ( 61 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 62 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXFrameworksBuildPhase section */ 67 | 68 | /* Begin PBXGroup section */ 69 | 9740EEB11CF90186004384FC /* Flutter */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | 3B80C3931E831B6300D905FE /* App.framework */, 73 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 74 | 9740EEBA1CF902C7004384FC /* Flutter.framework */, 75 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 76 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 77 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 78 | ); 79 | name = Flutter; 80 | sourceTree = ""; 81 | }; 82 | 97C146E51CF9000F007C117D = { 83 | isa = PBXGroup; 84 | children = ( 85 | 9740EEB11CF90186004384FC /* Flutter */, 86 | 97C146F01CF9000F007C117D /* Runner */, 87 | 97C146EF1CF9000F007C117D /* Products */, 88 | ); 89 | sourceTree = ""; 90 | }; 91 | 97C146EF1CF9000F007C117D /* Products */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 97C146EE1CF9000F007C117D /* Runner.app */, 95 | ); 96 | name = Products; 97 | sourceTree = ""; 98 | }; 99 | 97C146F01CF9000F007C117D /* Runner */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 103 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 104 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 105 | 97C147021CF9000F007C117D /* Info.plist */, 106 | 97C146F11CF9000F007C117D /* Supporting Files */, 107 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 108 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 109 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 110 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 111 | ); 112 | path = Runner; 113 | sourceTree = ""; 114 | }; 115 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | ); 119 | name = "Supporting Files"; 120 | sourceTree = ""; 121 | }; 122 | /* End PBXGroup section */ 123 | 124 | /* Begin PBXNativeTarget section */ 125 | 97C146ED1CF9000F007C117D /* Runner */ = { 126 | isa = PBXNativeTarget; 127 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 128 | buildPhases = ( 129 | 9740EEB61CF901F6004384FC /* Run Script */, 130 | 97C146EA1CF9000F007C117D /* Sources */, 131 | 97C146EB1CF9000F007C117D /* Frameworks */, 132 | 97C146EC1CF9000F007C117D /* Resources */, 133 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 134 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 135 | ); 136 | buildRules = ( 137 | ); 138 | dependencies = ( 139 | ); 140 | name = Runner; 141 | productName = Runner; 142 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 143 | productType = "com.apple.product-type.application"; 144 | }; 145 | /* End PBXNativeTarget section */ 146 | 147 | /* Begin PBXProject section */ 148 | 97C146E61CF9000F007C117D /* Project object */ = { 149 | isa = PBXProject; 150 | attributes = { 151 | LastUpgradeCheck = 1020; 152 | ORGANIZATIONNAME = "The Chromium Authors"; 153 | TargetAttributes = { 154 | 97C146ED1CF9000F007C117D = { 155 | CreatedOnToolsVersion = 7.3.1; 156 | LastSwiftMigration = 0910; 157 | }; 158 | }; 159 | }; 160 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 161 | compatibilityVersion = "Xcode 3.2"; 162 | developmentRegion = en; 163 | hasScannedForEncodings = 0; 164 | knownRegions = ( 165 | en, 166 | Base, 167 | ); 168 | mainGroup = 97C146E51CF9000F007C117D; 169 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 170 | projectDirPath = ""; 171 | projectRoot = ""; 172 | targets = ( 173 | 97C146ED1CF9000F007C117D /* Runner */, 174 | ); 175 | }; 176 | /* End PBXProject section */ 177 | 178 | /* Begin PBXResourcesBuildPhase section */ 179 | 97C146EC1CF9000F007C117D /* Resources */ = { 180 | isa = PBXResourcesBuildPhase; 181 | buildActionMask = 2147483647; 182 | files = ( 183 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 184 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 185 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 186 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 187 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 188 | ); 189 | runOnlyForDeploymentPostprocessing = 0; 190 | }; 191 | /* End PBXResourcesBuildPhase section */ 192 | 193 | /* Begin PBXShellScriptBuildPhase section */ 194 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 195 | isa = PBXShellScriptBuildPhase; 196 | buildActionMask = 2147483647; 197 | files = ( 198 | ); 199 | inputPaths = ( 200 | ); 201 | name = "Thin Binary"; 202 | outputPaths = ( 203 | ); 204 | runOnlyForDeploymentPostprocessing = 0; 205 | shellPath = /bin/sh; 206 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; 207 | }; 208 | 9740EEB61CF901F6004384FC /* Run Script */ = { 209 | isa = PBXShellScriptBuildPhase; 210 | buildActionMask = 2147483647; 211 | files = ( 212 | ); 213 | inputPaths = ( 214 | ); 215 | name = "Run Script"; 216 | outputPaths = ( 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | shellPath = /bin/sh; 220 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 221 | }; 222 | /* End PBXShellScriptBuildPhase section */ 223 | 224 | /* Begin PBXSourcesBuildPhase section */ 225 | 97C146EA1CF9000F007C117D /* Sources */ = { 226 | isa = PBXSourcesBuildPhase; 227 | buildActionMask = 2147483647; 228 | files = ( 229 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 230 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 231 | ); 232 | runOnlyForDeploymentPostprocessing = 0; 233 | }; 234 | /* End PBXSourcesBuildPhase section */ 235 | 236 | /* Begin PBXVariantGroup section */ 237 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 238 | isa = PBXVariantGroup; 239 | children = ( 240 | 97C146FB1CF9000F007C117D /* Base */, 241 | ); 242 | name = Main.storyboard; 243 | sourceTree = ""; 244 | }; 245 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 246 | isa = PBXVariantGroup; 247 | children = ( 248 | 97C147001CF9000F007C117D /* Base */, 249 | ); 250 | name = LaunchScreen.storyboard; 251 | sourceTree = ""; 252 | }; 253 | /* End PBXVariantGroup section */ 254 | 255 | /* Begin XCBuildConfiguration section */ 256 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 257 | isa = XCBuildConfiguration; 258 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 259 | buildSettings = { 260 | ALWAYS_SEARCH_USER_PATHS = NO; 261 | CLANG_ANALYZER_NONNULL = YES; 262 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 263 | CLANG_CXX_LIBRARY = "libc++"; 264 | CLANG_ENABLE_MODULES = YES; 265 | CLANG_ENABLE_OBJC_ARC = YES; 266 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 267 | CLANG_WARN_BOOL_CONVERSION = YES; 268 | CLANG_WARN_COMMA = YES; 269 | CLANG_WARN_CONSTANT_CONVERSION = YES; 270 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 271 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 272 | CLANG_WARN_EMPTY_BODY = YES; 273 | CLANG_WARN_ENUM_CONVERSION = YES; 274 | CLANG_WARN_INFINITE_RECURSION = YES; 275 | CLANG_WARN_INT_CONVERSION = YES; 276 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 277 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 278 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 279 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 280 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 281 | CLANG_WARN_STRICT_PROTOTYPES = YES; 282 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 283 | CLANG_WARN_UNREACHABLE_CODE = YES; 284 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 285 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 286 | COPY_PHASE_STRIP = NO; 287 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 288 | ENABLE_NS_ASSERTIONS = NO; 289 | ENABLE_STRICT_OBJC_MSGSEND = YES; 290 | GCC_C_LANGUAGE_STANDARD = gnu99; 291 | GCC_NO_COMMON_BLOCKS = YES; 292 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 293 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 294 | GCC_WARN_UNDECLARED_SELECTOR = YES; 295 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 296 | GCC_WARN_UNUSED_FUNCTION = YES; 297 | GCC_WARN_UNUSED_VARIABLE = YES; 298 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 299 | MTL_ENABLE_DEBUG_INFO = NO; 300 | SDKROOT = iphoneos; 301 | TARGETED_DEVICE_FAMILY = "1,2"; 302 | VALIDATE_PRODUCT = YES; 303 | }; 304 | name = Profile; 305 | }; 306 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 307 | isa = XCBuildConfiguration; 308 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 309 | buildSettings = { 310 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 311 | CLANG_ENABLE_MODULES = YES; 312 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 313 | ENABLE_BITCODE = NO; 314 | FRAMEWORK_SEARCH_PATHS = ( 315 | "$(inherited)", 316 | "$(PROJECT_DIR)/Flutter", 317 | ); 318 | INFOPLIST_FILE = Runner/Info.plist; 319 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 320 | LIBRARY_SEARCH_PATHS = ( 321 | "$(inherited)", 322 | "$(PROJECT_DIR)/Flutter", 323 | ); 324 | PRODUCT_BUNDLE_IDENTIFIER = com.jingchuan.imopei.frontImopeiPda; 325 | PRODUCT_NAME = "$(TARGET_NAME)"; 326 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 327 | SWIFT_VERSION = 4.0; 328 | VERSIONING_SYSTEM = "apple-generic"; 329 | }; 330 | name = Profile; 331 | }; 332 | 97C147031CF9000F007C117D /* Debug */ = { 333 | isa = XCBuildConfiguration; 334 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 335 | buildSettings = { 336 | ALWAYS_SEARCH_USER_PATHS = NO; 337 | CLANG_ANALYZER_NONNULL = YES; 338 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 339 | CLANG_CXX_LIBRARY = "libc++"; 340 | CLANG_ENABLE_MODULES = YES; 341 | CLANG_ENABLE_OBJC_ARC = YES; 342 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 343 | CLANG_WARN_BOOL_CONVERSION = YES; 344 | CLANG_WARN_COMMA = YES; 345 | CLANG_WARN_CONSTANT_CONVERSION = YES; 346 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 347 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 348 | CLANG_WARN_EMPTY_BODY = YES; 349 | CLANG_WARN_ENUM_CONVERSION = YES; 350 | CLANG_WARN_INFINITE_RECURSION = YES; 351 | CLANG_WARN_INT_CONVERSION = YES; 352 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 353 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 354 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 355 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 356 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 357 | CLANG_WARN_STRICT_PROTOTYPES = YES; 358 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 359 | CLANG_WARN_UNREACHABLE_CODE = YES; 360 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 361 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 362 | COPY_PHASE_STRIP = NO; 363 | DEBUG_INFORMATION_FORMAT = dwarf; 364 | ENABLE_STRICT_OBJC_MSGSEND = YES; 365 | ENABLE_TESTABILITY = YES; 366 | GCC_C_LANGUAGE_STANDARD = gnu99; 367 | GCC_DYNAMIC_NO_PIC = NO; 368 | GCC_NO_COMMON_BLOCKS = YES; 369 | GCC_OPTIMIZATION_LEVEL = 0; 370 | GCC_PREPROCESSOR_DEFINITIONS = ( 371 | "DEBUG=1", 372 | "$(inherited)", 373 | ); 374 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 375 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 376 | GCC_WARN_UNDECLARED_SELECTOR = YES; 377 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 378 | GCC_WARN_UNUSED_FUNCTION = YES; 379 | GCC_WARN_UNUSED_VARIABLE = YES; 380 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 381 | MTL_ENABLE_DEBUG_INFO = YES; 382 | ONLY_ACTIVE_ARCH = YES; 383 | SDKROOT = iphoneos; 384 | TARGETED_DEVICE_FAMILY = "1,2"; 385 | }; 386 | name = Debug; 387 | }; 388 | 97C147041CF9000F007C117D /* Release */ = { 389 | isa = XCBuildConfiguration; 390 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 391 | buildSettings = { 392 | ALWAYS_SEARCH_USER_PATHS = NO; 393 | CLANG_ANALYZER_NONNULL = YES; 394 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 395 | CLANG_CXX_LIBRARY = "libc++"; 396 | CLANG_ENABLE_MODULES = YES; 397 | CLANG_ENABLE_OBJC_ARC = YES; 398 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 399 | CLANG_WARN_BOOL_CONVERSION = YES; 400 | CLANG_WARN_COMMA = YES; 401 | CLANG_WARN_CONSTANT_CONVERSION = YES; 402 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 403 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 404 | CLANG_WARN_EMPTY_BODY = YES; 405 | CLANG_WARN_ENUM_CONVERSION = YES; 406 | CLANG_WARN_INFINITE_RECURSION = YES; 407 | CLANG_WARN_INT_CONVERSION = YES; 408 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 409 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 410 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 411 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 412 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 413 | CLANG_WARN_STRICT_PROTOTYPES = YES; 414 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 415 | CLANG_WARN_UNREACHABLE_CODE = YES; 416 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 417 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 418 | COPY_PHASE_STRIP = NO; 419 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 420 | ENABLE_NS_ASSERTIONS = NO; 421 | ENABLE_STRICT_OBJC_MSGSEND = YES; 422 | GCC_C_LANGUAGE_STANDARD = gnu99; 423 | GCC_NO_COMMON_BLOCKS = YES; 424 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 425 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 426 | GCC_WARN_UNDECLARED_SELECTOR = YES; 427 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 428 | GCC_WARN_UNUSED_FUNCTION = YES; 429 | GCC_WARN_UNUSED_VARIABLE = YES; 430 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 431 | MTL_ENABLE_DEBUG_INFO = NO; 432 | SDKROOT = iphoneos; 433 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 434 | TARGETED_DEVICE_FAMILY = "1,2"; 435 | VALIDATE_PRODUCT = YES; 436 | }; 437 | name = Release; 438 | }; 439 | 97C147061CF9000F007C117D /* Debug */ = { 440 | isa = XCBuildConfiguration; 441 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 442 | buildSettings = { 443 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 444 | CLANG_ENABLE_MODULES = YES; 445 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 446 | ENABLE_BITCODE = NO; 447 | FRAMEWORK_SEARCH_PATHS = ( 448 | "$(inherited)", 449 | "$(PROJECT_DIR)/Flutter", 450 | ); 451 | INFOPLIST_FILE = Runner/Info.plist; 452 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 453 | LIBRARY_SEARCH_PATHS = ( 454 | "$(inherited)", 455 | "$(PROJECT_DIR)/Flutter", 456 | ); 457 | PRODUCT_BUNDLE_IDENTIFIER = com.jingchuan.imopei.frontImopeiPda; 458 | PRODUCT_NAME = "$(TARGET_NAME)"; 459 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 460 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 461 | SWIFT_VERSION = 4.0; 462 | VERSIONING_SYSTEM = "apple-generic"; 463 | }; 464 | name = Debug; 465 | }; 466 | 97C147071CF9000F007C117D /* Release */ = { 467 | isa = XCBuildConfiguration; 468 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 469 | buildSettings = { 470 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 471 | CLANG_ENABLE_MODULES = YES; 472 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 473 | ENABLE_BITCODE = NO; 474 | FRAMEWORK_SEARCH_PATHS = ( 475 | "$(inherited)", 476 | "$(PROJECT_DIR)/Flutter", 477 | ); 478 | INFOPLIST_FILE = Runner/Info.plist; 479 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 480 | LIBRARY_SEARCH_PATHS = ( 481 | "$(inherited)", 482 | "$(PROJECT_DIR)/Flutter", 483 | ); 484 | PRODUCT_BUNDLE_IDENTIFIER = com.jingchuan.imopei.frontImopeiPda; 485 | PRODUCT_NAME = "$(TARGET_NAME)"; 486 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 487 | SWIFT_VERSION = 4.0; 488 | VERSIONING_SYSTEM = "apple-generic"; 489 | }; 490 | name = Release; 491 | }; 492 | /* End XCBuildConfiguration section */ 493 | 494 | /* Begin XCConfigurationList section */ 495 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 496 | isa = XCConfigurationList; 497 | buildConfigurations = ( 498 | 97C147031CF9000F007C117D /* Debug */, 499 | 97C147041CF9000F007C117D /* Release */, 500 | 249021D3217E4FDB00AE95B9 /* Profile */, 501 | ); 502 | defaultConfigurationIsVisible = 0; 503 | defaultConfigurationName = Release; 504 | }; 505 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 506 | isa = XCConfigurationList; 507 | buildConfigurations = ( 508 | 97C147061CF9000F007C117D /* Debug */, 509 | 97C147071CF9000F007C117D /* Release */, 510 | 249021D4217E4FDB00AE95B9 /* Profile */, 511 | ); 512 | defaultConfigurationIsVisible = 0; 513 | defaultConfigurationName = Release; 514 | }; 515 | /* End XCConfigurationList section */ 516 | 517 | }; 518 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 519 | } 520 | --------------------------------------------------------------------------------