├── .gitignore
├── .metadata
├── README.md
├── analysis_options.yaml
├── android
├── .gitignore
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── flutter_jdshop_mvvm
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── drawable-v21
│ │ │ └── launch_background.xml
│ │ │ ├── drawable
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-night
│ │ │ └── styles.xml
│ │ │ └── values
│ │ │ └── styles.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── assets
├── fonts
│ ├── MyFlutterApp.ttf
│ ├── iconfont.ttf
│ ├── iconfont2.ttf
│ ├── iconfont3.ttf
│ └── iconpay.ttf
└── images
│ ├── 2.0x
│ ├── login.png
│ ├── user.png
│ └── user_bg.jpg
│ ├── 3.0x
│ ├── login.png
│ ├── user.png
│ └── user_bg.jpg
│ ├── app_start_1.png
│ ├── app_start_2.png
│ ├── app_start_3.png
│ ├── banner.jpg
│ ├── dps_n.png
│ ├── dwc_s.png
│ ├── ic_empty.png
│ ├── ic_empty_shop.png
│ ├── icon_address.png
│ ├── icon_dps_n.png
│ ├── icon_dps_s.png
│ ├── icon_dwc_n.png
│ ├── icon_dwc_s.png
│ ├── icon_phone.png
│ ├── icon_search.png
│ ├── icon_selected.png
│ ├── icon_user.png
│ ├── icon_xdd_n.png
│ ├── icon_xdd_s.png
│ ├── icon_yqx_n.png
│ ├── icon_yqx_s.png
│ ├── icon_ywc_n.png
│ ├── icon_ywc_s.png
│ ├── load_error_view.png
│ ├── login.png
│ ├── login
│ ├── qyg_shop_icon_delete.png
│ ├── qyg_shop_icon_display.png
│ └── qyg_shop_icon_hide.png
│ ├── none.png
│ ├── order_bg.png
│ ├── order_bg1.png
│ ├── user.png
│ ├── user_bg.jpg
│ ├── xdd_n.png
│ ├── xdd_s.png
│ ├── ydss.png
│ ├── yqx_n.png
│ ├── yqx_s.png
│ ├── ywc_n.png
│ └── ywc_s.png
├── ios
├── .gitignore
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
├── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ ├── 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-83.5x83.5@2x.png
│ │ └── LaunchImage.imageset
│ │ │ ├── Contents.json
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ └── README.md
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── Info.plist
│ └── Runner-Bridging-Header.h
└── RunnerTests
│ └── RunnerTests.swift
├── l10n.yaml
├── lib
├── api
│ └── model
│ │ ├── CateModel.dart
│ │ ├── FocusModel.dart
│ │ ├── OrderModel.dart
│ │ ├── ProductContentModel.dart
│ │ ├── ProductModel.dart
│ │ ├── cate_view_model.dart
│ │ ├── focus_view_model.dart
│ │ ├── list_view_model.dart
│ │ ├── product_view_model.dart
│ │ ├── void_modle.dart
│ │ └── void_view_model.dart
├── base
│ └── base_page_state.dart
├── bean
│ └── option_bean.dart
├── common
│ ├── api_exception.dart
│ ├── check.dart
│ ├── common.dart
│ ├── date.dart
│ ├── file_util.dart
│ ├── functions.dart
│ ├── shared_util.dart
│ ├── ui.dart
│ └── win_media.dart
├── config
│ ├── api.dart
│ ├── config.dart
│ ├── const.dart
│ ├── keys.dart
│ ├── storage_manager.dart
│ └── user_info_data.dart
├── http
│ ├── base_response.dart
│ ├── dio_utils.dart
│ ├── intercept.dart
│ ├── mvvms.dart
│ ├── req_model.dart
│ ├── request_listener.dart
│ └── view_model.dart
├── l10n
│ ├── app_en.arb
│ └── app_zh.arb
├── main.dart
├── page
│ ├── cart
│ │ ├── CartItem.dart
│ │ ├── CartNum.dart
│ │ └── cart_page.dart
│ ├── category
│ │ └── category_page.dart
│ ├── demo
│ │ ├── ai_progress
│ │ │ ├── ai_progress_demo.dart
│ │ │ ├── circular_state_progress_indicator.dart
│ │ │ ├── progress_mixin.dart
│ │ │ └── yuanxing
│ │ │ │ ├── one_circle.dart
│ │ │ │ └── two_circle.dart
│ │ ├── animation_page.dart
│ │ ├── animation_three.dart
│ │ ├── animation_two.dart
│ │ ├── boundary.dart
│ │ ├── canvas_paint.dart
│ │ ├── customcheckbox
│ │ │ └── my_check_box.dart
│ │ ├── demo_list.dart
│ │ ├── divider_study.dart
│ │ ├── flutter_Inheritedwidget.dart
│ │ ├── flutter_barcode.dart
│ │ ├── flutter_locatal_global.dart
│ │ ├── flutter_overlay.dart
│ │ ├── flutter_selector.dart
│ │ ├── flutter_simple.dart
│ │ ├── keyboard_demo_page.dart
│ │ ├── my_custompainter.dart
│ │ ├── my_custompainter2.dart
│ │ ├── path_custompainter.dart
│ │ ├── path_study.dart
│ │ ├── share_data_widget.dart
│ │ ├── sliver_tabs
│ │ │ ├── page.dart
│ │ │ ├── page2.dart
│ │ │ └── page_state.dart
│ │ ├── study.dart
│ │ ├── study_repaintboundary.dart
│ │ └── timeclock
│ │ │ ├── clock.dart
│ │ │ └── thermometer.dart
│ ├── guide_page.dart
│ ├── home
│ │ ├── ProductList.dart
│ │ ├── home_page.dart
│ │ ├── product_detail.dart
│ │ ├── product_detail2.dart
│ │ ├── product_detail3.dart
│ │ └── productdetail
│ │ │ ├── CartNum.dart
│ │ │ ├── ProductContent.dart
│ │ │ ├── ProductContentSecond.dart
│ │ │ ├── ProductContentThird.dart
│ │ │ └── productcontent_first.dart
│ ├── root
│ │ └── root_page.dart
│ ├── splash_page.dart
│ ├── user
│ │ ├── address
│ │ │ ├── address_add_edit.dart
│ │ │ └── address_list.dart
│ │ ├── loginregister
│ │ │ ├── login.dart
│ │ │ ├── register_first.dart
│ │ │ ├── register_second.dart
│ │ │ └── register_third.dart
│ │ ├── order
│ │ │ ├── CheckOut.dart
│ │ │ ├── Order.dart
│ │ │ ├── OrderInfo.dart
│ │ │ ├── Pay.dart
│ │ │ └── Search.dart
│ │ └── user_page.dart
│ └── web_page.dart
├── provider
│ ├── Cart.dart
│ ├── CheckOut.dart
│ ├── counter_provider.dart
│ ├── order_page_provider.dart
│ ├── theme_provider.dart
│ └── user_provider.dart
├── receiver
│ └── event_bus.dart
├── res
│ ├── colors.dart
│ ├── colours.dart
│ ├── dimens.dart
│ ├── gaps.dart
│ ├── resources.dart
│ └── styles.dart
├── routes
│ ├── 404.dart
│ ├── application.dart
│ ├── demo_router.dart
│ ├── fluro_navigator.dart
│ ├── my_navigator_observer.dart
│ ├── router_init.dart
│ ├── routers.dart
│ └── shop_router.dart
├── utils
│ ├── CartServices.dart
│ ├── CheckOutServices.dart
│ ├── SearchServices.dart
│ ├── app_size.dart
│ ├── bottom_dialog.dart
│ ├── dialog_utils.dart
│ ├── double_tap_back_exit_app.dart
│ ├── image_utils.dart
│ ├── log_utils.dart
│ ├── number_text_input_formatter.dart
│ ├── theme_utils.dart
│ ├── utils.dart
│ └── view_utils.dart
├── view
│ ├── CustomSliverPersistentHeaderDelegate.dart
│ ├── app_topbar.dart
│ ├── custom_view.dart
│ ├── customize_appbar.dart
│ ├── flutter_icon_data.dart
│ ├── flutter_iconfont.dart
│ ├── my_icons.dart.dart
│ ├── ratingbar.dart
│ └── theme_ui.dart
└── widget
│ ├── dialog
│ ├── remind_dialog.dart
│ └── update_dialog.dart
│ ├── load_image.dart
│ ├── my_iframe
│ ├── my_iframe.dart
│ ├── my_iframe_other.dart
│ └── my_iframe_web.dart
│ ├── root_tabbar.dart
│ ├── scroll
│ └── my_behavior.dart
│ └── view
│ ├── LoadingWidget.dart
│ ├── base_dialog.dart
│ ├── keyboard_detector.dart
│ ├── load_image.dart
│ ├── load_state_layout.dart
│ ├── my_button.dart
│ ├── my_card.dart
│ ├── my_flexible_space_bar.dart
│ ├── my_refresh_list.dart
│ ├── my_sliver_appbar.dart
│ ├── popup_window.dart
│ ├── search_bar.dart
│ ├── text_field.dart
│ └── text_field_item.dart
├── pubspec.lock
├── pubspec.yaml
└── test
└── widget_test.dart
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | migrate_working_dir/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # The .vscode folder contains launch configuration and tasks you configure in
20 | # VS Code which you may wish to be included in version control, so this line
21 | # is commented out by default.
22 | #.vscode/
23 |
24 | # Flutter/Dart/Pub related
25 | **/doc/api/
26 | **/ios/Flutter/.last_build_id
27 | .dart_tool/
28 | .flutter-plugins
29 | .flutter-plugins-dependencies
30 | .pub-cache/
31 | .pub/
32 | /build/
33 |
34 | # Symbolication related
35 | app.*.symbols
36 |
37 | # Obfuscation related
38 | app.*.map.json
39 |
40 | # Android Studio will place build artifacts here
41 | /android/app/debug
42 | /android/app/profile
43 | /android/app/release
44 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: "78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9"
8 | channel: "stable"
9 |
10 | project_type: app
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9
17 | base_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9
18 | - platform: android
19 | create_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9
20 | base_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9
21 | - platform: ios
22 | create_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9
23 | base_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9
24 |
25 | # User provided section
26 |
27 | # List of Local paths (relative to this file) that should be
28 | # ignored by the migrate tool.
29 | #
30 | # Files that are not part of the templates will be ignored by default.
31 | unmanaged_files:
32 | - 'lib/main.dart'
33 | - 'ios/Runner.xcodeproj/project.pbxproj'
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 大地京东商城 Flutter 版
2 |
3 | ## screen shot for iOS
4 |
5 | 
6 |
7 | .png)
8 |
9 | 
10 |
11 |
12 | ## Setup
13 |
14 | 1. **Clone the repo**
15 |
16 | ```
17 | $ git clone https://github.com/githubityu/flutter_jdshop_mvvm.git
18 | $ cd flutter_jdshop_mvvm
19 | ```
20 |
21 | 2. **Running:**
22 |
23 | ```
24 | $ flutter run
25 | ```
26 |
27 |
28 |
29 |
30 | ## 简介
31 |
32 | 这是一个用Flutter写的简易商城APP
33 |
34 |
35 | ## 第三方依赖
36 |
37 | | 名称 | 作用 |
38 | |------------------------------|:-------------:|
39 | | intl | 多语言 |
40 | | flutter_hooks | 钩子 |
41 | | hooks_riverpod | 状态管理 |
42 | | riverpod_annotation | 状态管理 |
43 | | retrofit | 网络请求 |
44 | | dio | 网络请求 |
45 | | logger | 日志 |
46 | | go_router | 路由 |
47 | | hive_flutter | 本地存储 |
48 | | cached_network_image | 图片加载 |
49 | | tuple | 元数组 |
50 | | permission_handler | 权限 |
51 | | flutter_smart_dialog | toast和dialog |
52 | | flextras | 扩展的row和column |
53 | | url_launcher | 通过url启动插件 |
54 | | webview_flutter | 加载网页 |
55 |
56 |
57 |
58 |
59 |
60 | ## Contact
61 |
62 | If you have any suggestions, leave a message here
63 | [CSDN](https://blog.csdn.net/yujunlong3919)
64 |
65 |
66 | ## License
67 |
68 | MIT
69 |
70 | ## 最后
71 |
72 | 如果你喜欢这个项目,欢迎给我一个star。里面可能还有许多需要修改的bug,欢迎大家提出来,我将持续更新这个项目)
73 |
74 |
75 | ## 感谢qpc2015 复制了README.md
76 | [qpc2015](https://github.com/qpc2015/flutter_shop)
77 |
78 |
79 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # This file configures the analyzer, which statically analyzes Dart code to
2 | # check for errors, warnings, and lints.
3 | #
4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled
5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
6 | # invoked from the command line by running `flutter analyze`.
7 |
8 | # The following line activates a set of recommended lints for Flutter apps,
9 | # packages, and plugins designed to encourage good coding practices.
10 | include: package:flutter_lints/flutter.yaml
11 |
12 | linter:
13 | # The lint rules applied to this project can be customized in the
14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml`
15 | # included above or to enable additional rules. A list of all available lints
16 | # and their documentation is published at https://dart.dev/lints.
17 | #
18 | # Instead of disabling a lint rule for the entire project in the
19 | # section below, it can also be suppressed for a single line of code
20 | # or a specific dart file by using the `// ignore: name_of_lint` and
21 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file
22 | # producing the lint.
23 | rules:
24 | # avoid_print: false # Uncomment to disable the `avoid_print` rule
25 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
26 |
27 | # Additional information about this file can be found at
28 | # https://dart.dev/guides/language/analysis-options
29 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id "com.android.application"
3 | id "kotlin-android"
4 | id "dev.flutter.flutter-gradle-plugin"
5 | }
6 |
7 | def localProperties = new Properties()
8 | def localPropertiesFile = rootProject.file('local.properties')
9 | if (localPropertiesFile.exists()) {
10 | localPropertiesFile.withReader('UTF-8') { reader ->
11 | localProperties.load(reader)
12 | }
13 | }
14 |
15 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
16 | if (flutterVersionCode == null) {
17 | flutterVersionCode = '1'
18 | }
19 |
20 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
21 | if (flutterVersionName == null) {
22 | flutterVersionName = '1.0'
23 | }
24 |
25 | android {
26 | namespace "com.example.flutter_jdshop_mvvm"
27 | compileSdkVersion flutter.compileSdkVersion
28 | ndkVersion flutter.ndkVersion
29 |
30 | compileOptions {
31 | sourceCompatibility JavaVersion.VERSION_1_8
32 | targetCompatibility JavaVersion.VERSION_1_8
33 | }
34 |
35 | kotlinOptions {
36 | jvmTarget = '1.8'
37 | }
38 |
39 | sourceSets {
40 | main.java.srcDirs += 'src/main/kotlin'
41 | }
42 |
43 | defaultConfig {
44 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
45 | applicationId "com.example.flutter_jdshop_mvvm"
46 | // You can update the following values to match your application needs.
47 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
48 | minSdkVersion 24
49 | targetSdkVersion flutter.targetSdkVersion
50 | versionCode flutterVersionCode.toInteger()
51 | versionName flutterVersionName
52 | }
53 |
54 | buildTypes {
55 | release {
56 | // TODO: Add your own signing config for the release build.
57 | // Signing with the debug keys for now, so `flutter run --release` works.
58 | signingConfig signingConfigs.debug
59 | }
60 | }
61 | }
62 |
63 | flutter {
64 | source '../..'
65 | }
66 |
67 | dependencies {}
68 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
14 |
18 |
22 |
23 |
24 |
25 |
26 |
27 |
29 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/example/flutter_jdshop_mvvm/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.flutter_jdshop_mvvm
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.7.10'
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 |
8 | dependencies {
9 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
10 | }
11 | }
12 |
13 | allprojects {
14 | repositories {
15 | google()
16 | mavenCentral()
17 | }
18 | }
19 |
20 | rootProject.buildDir = '../build'
21 | subprojects {
22 | project.buildDir = "${rootProject.buildDir}/${project.name}"
23 | }
24 | subprojects {
25 | project.evaluationDependsOn(':app')
26 | }
27 |
28 | tasks.register("clean", Delete) {
29 | delete rootProject.buildDir
30 | }
31 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx4G
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
6 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | def flutterSdkPath = {
3 | def properties = new Properties()
4 | file("local.properties").withInputStream { properties.load(it) }
5 | def flutterSdkPath = properties.getProperty("flutter.sdk")
6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
7 | return flutterSdkPath
8 | }
9 | settings.ext.flutterSdkPath = flutterSdkPath()
10 |
11 | includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
12 |
13 | repositories {
14 | google()
15 | mavenCentral()
16 | gradlePluginPortal()
17 | }
18 |
19 | plugins {
20 | id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false
21 | }
22 | }
23 |
24 | plugins {
25 | id "dev.flutter.flutter-plugin-loader" version "1.0.0"
26 | id "com.android.application" version "7.3.0" apply false
27 | }
28 |
29 | include ":app"
30 |
--------------------------------------------------------------------------------
/assets/fonts/MyFlutterApp.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/fonts/MyFlutterApp.ttf
--------------------------------------------------------------------------------
/assets/fonts/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/fonts/iconfont.ttf
--------------------------------------------------------------------------------
/assets/fonts/iconfont2.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/fonts/iconfont2.ttf
--------------------------------------------------------------------------------
/assets/fonts/iconfont3.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/fonts/iconfont3.ttf
--------------------------------------------------------------------------------
/assets/fonts/iconpay.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/fonts/iconpay.ttf
--------------------------------------------------------------------------------
/assets/images/2.0x/login.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/2.0x/login.png
--------------------------------------------------------------------------------
/assets/images/2.0x/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/2.0x/user.png
--------------------------------------------------------------------------------
/assets/images/2.0x/user_bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/2.0x/user_bg.jpg
--------------------------------------------------------------------------------
/assets/images/3.0x/login.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/3.0x/login.png
--------------------------------------------------------------------------------
/assets/images/3.0x/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/3.0x/user.png
--------------------------------------------------------------------------------
/assets/images/3.0x/user_bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/3.0x/user_bg.jpg
--------------------------------------------------------------------------------
/assets/images/app_start_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/app_start_1.png
--------------------------------------------------------------------------------
/assets/images/app_start_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/app_start_2.png
--------------------------------------------------------------------------------
/assets/images/app_start_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/app_start_3.png
--------------------------------------------------------------------------------
/assets/images/banner.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/banner.jpg
--------------------------------------------------------------------------------
/assets/images/dps_n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/dps_n.png
--------------------------------------------------------------------------------
/assets/images/dwc_s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/dwc_s.png
--------------------------------------------------------------------------------
/assets/images/ic_empty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/ic_empty.png
--------------------------------------------------------------------------------
/assets/images/ic_empty_shop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/ic_empty_shop.png
--------------------------------------------------------------------------------
/assets/images/icon_address.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/icon_address.png
--------------------------------------------------------------------------------
/assets/images/icon_dps_n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/icon_dps_n.png
--------------------------------------------------------------------------------
/assets/images/icon_dps_s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/icon_dps_s.png
--------------------------------------------------------------------------------
/assets/images/icon_dwc_n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/icon_dwc_n.png
--------------------------------------------------------------------------------
/assets/images/icon_dwc_s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/icon_dwc_s.png
--------------------------------------------------------------------------------
/assets/images/icon_phone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/icon_phone.png
--------------------------------------------------------------------------------
/assets/images/icon_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/icon_search.png
--------------------------------------------------------------------------------
/assets/images/icon_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/icon_selected.png
--------------------------------------------------------------------------------
/assets/images/icon_user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/icon_user.png
--------------------------------------------------------------------------------
/assets/images/icon_xdd_n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/icon_xdd_n.png
--------------------------------------------------------------------------------
/assets/images/icon_xdd_s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/icon_xdd_s.png
--------------------------------------------------------------------------------
/assets/images/icon_yqx_n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/icon_yqx_n.png
--------------------------------------------------------------------------------
/assets/images/icon_yqx_s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/icon_yqx_s.png
--------------------------------------------------------------------------------
/assets/images/icon_ywc_n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/icon_ywc_n.png
--------------------------------------------------------------------------------
/assets/images/icon_ywc_s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/icon_ywc_s.png
--------------------------------------------------------------------------------
/assets/images/load_error_view.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/load_error_view.png
--------------------------------------------------------------------------------
/assets/images/login.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/login.png
--------------------------------------------------------------------------------
/assets/images/login/qyg_shop_icon_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/login/qyg_shop_icon_delete.png
--------------------------------------------------------------------------------
/assets/images/login/qyg_shop_icon_display.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/login/qyg_shop_icon_display.png
--------------------------------------------------------------------------------
/assets/images/login/qyg_shop_icon_hide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/login/qyg_shop_icon_hide.png
--------------------------------------------------------------------------------
/assets/images/none.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/none.png
--------------------------------------------------------------------------------
/assets/images/order_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/order_bg.png
--------------------------------------------------------------------------------
/assets/images/order_bg1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/order_bg1.png
--------------------------------------------------------------------------------
/assets/images/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/user.png
--------------------------------------------------------------------------------
/assets/images/user_bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/user_bg.jpg
--------------------------------------------------------------------------------
/assets/images/xdd_n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/xdd_n.png
--------------------------------------------------------------------------------
/assets/images/xdd_s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/xdd_s.png
--------------------------------------------------------------------------------
/assets/images/ydss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/ydss.png
--------------------------------------------------------------------------------
/assets/images/yqx_n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/yqx_n.png
--------------------------------------------------------------------------------
/assets/images/yqx_s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/yqx_s.png
--------------------------------------------------------------------------------
/assets/images/ywc_n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/ywc_n.png
--------------------------------------------------------------------------------
/assets/images/ywc_s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/assets/images/ywc_s.png
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | **/dgph
2 | *.mode1v3
3 | *.mode2v3
4 | *.moved-aside
5 | *.pbxuser
6 | *.perspectivev3
7 | **/*sync/
8 | .sconsign.dblite
9 | .tags*
10 | **/.vagrant/
11 | **/DerivedData/
12 | Icon?
13 | **/Pods/
14 | **/.symlinks/
15 | profile
16 | xcuserdata
17 | **/.generated/
18 | Flutter/App.framework
19 | Flutter/Flutter.framework
20 | Flutter/Flutter.podspec
21 | Flutter/Generated.xcconfig
22 | Flutter/ephemeral/
23 | Flutter/app.flx
24 | Flutter/app.zip
25 | Flutter/flutter_assets/
26 | Flutter/flutter_export_environment.sh
27 | ServiceDefinitions.json
28 | Runner/GeneratedPluginRegistrant.*
29 |
30 | # Exceptions to above rules.
31 | !default.mode1v3
32 | !default.mode2v3
33 | !default.pbxuser
34 | !default.perspectivev3
35 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 11.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-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 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/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/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/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/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/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/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/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/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/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/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/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/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/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/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/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/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/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/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/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/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/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/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/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/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubityu/flutter_jdshop_mvvm/35f4facaef3edf250031f08d85c438fb9c130f9e/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | Flutter Jdshop Mvvm
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | flutter_jdshop_mvvm
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(FLUTTER_BUILD_NUMBER)
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 | CADisableMinimumFrameDurationOnPhone
45 |
46 | UIApplicationSupportsIndirectInputEvents
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/ios/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 | import UIKit
3 | import XCTest
4 |
5 | class RunnerTests: XCTestCase {
6 |
7 | func testExample() {
8 | // If you add code to the Runner application, consider adding tests here.
9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/l10n.yaml:
--------------------------------------------------------------------------------
1 | arb-dir: lib/l10n
2 | template-arb-file: app_en.arb
3 | output-localization-file: app_localizations.dart
--------------------------------------------------------------------------------
/lib/api/model/CateModel.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutterjdshop/config/api.dart';
2 | import 'package:flutterjdshop/http/req_model.dart';
3 |
4 | class CateModel2 extends ReqModel {
5 | int type = 0;
6 | String? pid;
7 |
8 | @override
9 | String url() => "${API.pcate}";
10 |
11 | Map params() {
12 | return type == 1 ? {"pid": "$pid"} : {};
13 | }
14 |
15 | Future data(pid, type) {
16 | this.type = type;
17 | this.pid = pid;
18 | return get();
19 | }
20 | }
21 |
22 | class CateModel {
23 | List? result;
24 |
25 | CateModel({this.result});
26 |
27 | CateModel.fromJson(List json) {
28 | result = List.empty();
29 | json.forEach((v) {
30 | result!.add(new CateItemModel.fromJson(v));
31 | });
32 | }
33 |
34 | Map toJson() {
35 | final Map data = new Map();
36 | if (this.result != null) {
37 | data['result'] = this.result!.map((v) => v.toJson()).toList();
38 | }
39 | return data;
40 | }
41 | }
42 |
43 | class CateItemModel {
44 | String? sId;
45 | String? title;
46 | Object? status;
47 | String? pic;
48 | String? pid;
49 | String? sort;
50 |
51 | CateItemModel(
52 | {this.sId, this.title, this.status, this.pic, this.pid, this.sort});
53 |
54 | CateItemModel.fromJson(Map json) {
55 | sId = json['_id'];
56 | title = json['title'];
57 | status = json['status'];
58 | pic = json['pic'];
59 | pid = json['pid'];
60 | sort = json['sort'];
61 | }
62 |
63 | Map toJson() {
64 | final Map data = new Map();
65 | data['_id'] = this.sId;
66 | data['title'] = this.title;
67 | data['status'] = this.status;
68 | data['pic'] = this.pic;
69 | data['pid'] = this.pid;
70 | data['sort'] = this.sort;
71 | return data;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/lib/api/model/FocusModel.dart:
--------------------------------------------------------------------------------
1 | // FocusModel.fromJson(json);
2 |
3 | import 'package:flutterjdshop/config/api.dart';
4 | import 'package:flutterjdshop/http/req_model.dart';
5 |
6 | class FocusModel2 extends ReqModel {
7 | @override
8 | String url() => API.focus;
9 |
10 | Future data() => get();
11 | }
12 |
13 | class FocusModel {
14 | List? result;
15 |
16 | FocusModel({this.result});
17 |
18 | FocusModel.fromJson(List json) {
19 | result = List.empty();
20 | json.forEach((v) {
21 | result!.add(new FocusItemModel.fromJson(v));
22 | });
23 | }
24 |
25 | Map toJson() {
26 | final Map data = new Map();
27 | if (this.result != null) {
28 | data['result'] = this.result!.map((v) => v.toJson()).toList();
29 | }
30 | return data;
31 | }
32 | }
33 |
34 | class FocusItemModel {
35 | String? sId;
36 | String? title;
37 | String? status;
38 | String? pic;
39 | String? url;
40 |
41 | FocusItemModel({this.sId, this.title, this.status, this.pic, this.url});
42 |
43 | FocusItemModel.fromJson(Map json) {
44 | sId = json['_id'];
45 | title = json['title'];
46 | status = json['status'];
47 | pic = json['pic'];
48 | url = json['url'];
49 | }
50 |
51 | Map toJson() {
52 | final Map data = new Map();
53 | data['_id'] = this.sId;
54 | data['title'] = this.title;
55 | data['status'] = this.status;
56 | data['pic'] = this.pic;
57 | data['url'] = this.url;
58 | return data;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/lib/api/model/ProductModel.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutterjdshop/config/api.dart';
2 | import 'package:flutterjdshop/http/req_model.dart';
3 |
4 | class ProductModel2 extends ReqModel {
5 | int type = 0;
6 |
7 | @override
8 | String url() => "${API.plist}";
9 |
10 | Map params() {
11 | return {(type == 0 ? "is_hot" : "is_best"): "1"};
12 | }
13 |
14 | Future data(type) {
15 | this.type = type;
16 | return get();
17 | }
18 | }
19 |
20 | class ProductModel {
21 | List? result;
22 |
23 | ProductModel({this.result});
24 |
25 | ProductModel.fromJson(List json) {
26 | result = List.empty();
27 | json.forEach((v) {
28 | result!.add(new ProductItemModel.fromJson(v));
29 | });
30 | }
31 |
32 | Map toJson() {
33 | final Map data = new Map();
34 | if (this.result != null) {
35 | data['result'] = this.result!.map((v) => v.toJson()).toList();
36 | }
37 | return data;
38 | }
39 | }
40 |
41 | class ProductItemModel {
42 | String? sId;
43 | String? title;
44 | String? cid;
45 | Object? price; //所有的类型都继承 Object
46 | String? oldPrice;
47 | String? pic;
48 | String? sPic;
49 |
50 | ProductItemModel(
51 | {this.sId,
52 | this.title,
53 | this.cid,
54 | this.price,
55 | this.oldPrice,
56 | this.pic,
57 | this.sPic});
58 |
59 | ProductItemModel.fromJson(Map json) {
60 | sId = json['_id'];
61 | title = json['title'];
62 | cid = json['cid'];
63 | price = json['price'];
64 | oldPrice = json['old_price'];
65 | pic = json['pic'];
66 | sPic = json['s_pic'];
67 | }
68 |
69 | Map toJson() {
70 | final Map data = new Map();
71 | data['_id'] = this.sId;
72 | data['title'] = this.title;
73 | data['cid'] = this.cid;
74 | data['price'] = this.price;
75 | data['old_price'] = this.oldPrice;
76 | data['pic'] = this.pic;
77 | data['s_pic'] = this.sPic;
78 | return data;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/lib/api/model/cate_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutterjdshop/http/view_model.dart';
2 |
3 | import 'CateModel.dart';
4 | import 'FocusModel.dart';
5 |
6 | class CateViewModel extends ViewModel {
7 | /*
8 | * 发送信息
9 | * */
10 | CateViewModel.get(cancelToken, {view}) {
11 | this.cancelToken = cancelToken;
12 | this.view = view;
13 | }
14 |
15 | Future getData({pid = "", type = 0}) async {
16 | final data = await CateModel2().data(pid, type);
17 | if (data != null && data.isNotEmpty) {
18 | return CateModel.fromJson(data);
19 | }
20 | return Future.value(null);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lib/api/model/focus_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutterjdshop/http/view_model.dart';
2 |
3 | import 'FocusModel.dart';
4 |
5 |
6 | FocusViewModel focusViewModel = new FocusViewModel();
7 |
8 | class FocusViewModel extends ViewModel {
9 | /*
10 | * 发送信息
11 | * */
12 | Future getData() async {
13 | final data = await FocusModel2().data();
14 | if (data != null && data.isNotEmpty) {
15 | return FocusModel.fromJson(data);
16 | }
17 | return Future.value(null);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lib/api/model/list_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:dio/dio.dart';
4 | import 'package:flutterjdshop/http/mvvms.dart';
5 | import 'package:flutterjdshop/http/view_model.dart';
6 |
7 | import 'void_modle.dart';
8 |
9 | ListViewModel listViewModel = new ListViewModel();
10 |
11 | class ListViewModel extends ViewModel {
12 | ListViewModel() {
13 | print("======VoidViewModel()=====");
14 | }
15 |
16 | ListViewModel.get(IMvvmView? view, CancelToken? cancelToken) {
17 | print("======VoidViewModel.get()=====");
18 | this.view = view;
19 | this.cancelToken = cancelToken;
20 | }
21 |
22 | Future getData({type = 0, Map? params2}) async {
23 | final List? data = await (VoidModel(cancelToken, view).data(type, params2) as Future?>);
24 | if (data != null) {
25 | return data;
26 | }
27 | return Future.value(null);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lib/api/model/product_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutterjdshop/http/view_model.dart';
2 |
3 | import 'ProductModel.dart';
4 |
5 |
6 | ProductViewModel productViewModel = new ProductViewModel();
7 |
8 | class ProductViewModel extends ViewModel {
9 | /*
10 | * 发送信息
11 | * */
12 | Future getData({type=0}) async {
13 | final data = await ProductModel2().data(type);
14 | if (data != null && data.isNotEmpty) {
15 | return ProductModel.fromJson(data);
16 | }
17 | return Future.value(null);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lib/api/model/void_modle.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:dio/dio.dart';
4 | import 'package:flutterjdshop/config/api.dart';
5 | import 'package:flutterjdshop/http/mvvms.dart';
6 | import 'package:flutterjdshop/http/req_model.dart';
7 |
8 | class VoidModel extends ReqModel {
9 | static const SEND_CODE = 1;
10 | static const REGISTER = 2;
11 | static const LOGIN = 3;
12 | static const ADDRESS_LIST = 4;
13 | static const ADD_ADDRESS = 5;
14 | static const EDIT_ADDRESS = 6;
15 | static const DELETE_ADDRESS = 7;
16 | static const CHANGE_ADDRESS = 8;
17 | static const PCONTENT = 9;
18 | static const DOORDER = 10;
19 | static const ONEADDRESSLIST = 11;
20 | static const ORDERLIST = 12;
21 | static const PLIST = 13;
22 |
23 | int? type;
24 | Map? params2;
25 |
26 | VoidModel(CancelToken? cancelToken, IMvvmView? view) {
27 | this.view = view;
28 | this.cancelToken = cancelToken;
29 | }
30 |
31 | get isNotEncode {
32 | return type == ADDRESS_LIST||type==PCONTENT||type==ONEADDRESSLIST||type==ORDERLIST||type==PLIST;
33 | }
34 |
35 | ///后台正常接收参数 用的是RequestParam
36 | @override
37 | Map? params() {
38 | return isNotEncode ? params2 : null;
39 | }
40 |
41 | ///后台用RequestBody接收参数需要传入json
42 | @override
43 | String? encodeData() {
44 | return isNotEncode ? null : json.encode(params2);
45 | }
46 |
47 | @override
48 | String url() {
49 | String url = "";
50 | switch (type) {
51 | case SEND_CODE:
52 | url = API.sendCode;
53 | break;
54 | case REGISTER:
55 | url = API.register;
56 | break;
57 | case LOGIN:
58 | url = API.login;
59 | break;
60 | case ADDRESS_LIST:
61 | url = API.addressList;
62 | break;
63 | case ADD_ADDRESS:
64 | url = API.addAddress;
65 | break;
66 | case EDIT_ADDRESS:
67 | url = API.editAddress;
68 | break;
69 | case DELETE_ADDRESS:
70 | url = API.deleteAddress;
71 | break;
72 | case CHANGE_ADDRESS:
73 | url = API.changeDefaultAddress;
74 | break;
75 | case PCONTENT:
76 | url = API.pcontent;
77 | break;
78 | case DOORDER:
79 | url = API.doOrder;
80 | break;
81 | case ONEADDRESSLIST:
82 | url = API.oneAddressList;
83 | break;
84 | case ORDERLIST:
85 | url = API.orderList;
86 | break;
87 | case PLIST:
88 | url = API.plist;
89 | break;
90 | }
91 | return url;
92 | }
93 |
94 | Future data(type, Map? params2) {
95 | this.type = type;
96 | this.params2 = params2;
97 | switch (type) {
98 | case ADDRESS_LIST:
99 | case PCONTENT:
100 | case ONEADDRESSLIST:
101 | case ORDERLIST:
102 | case PLIST:
103 | return get();
104 | break;
105 | }
106 | return post();
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/lib/api/model/void_view_model.dart:
--------------------------------------------------------------------------------
1 |
2 |
3 | import 'package:dio/dio.dart';
4 | import 'package:flutterjdshop/http/mvvms.dart';
5 | import 'package:flutterjdshop/http/view_model.dart';
6 |
7 | import 'void_modle.dart';
8 |
9 | VoidViewModel voidViewModel = new VoidViewModel();
10 |
11 | class VoidViewModel extends ViewModel {
12 | VoidViewModel() {
13 | print("======VoidViewModel()=====");
14 | }
15 |
16 | VoidViewModel.get(IMvvmView? view, CancelToken? cancelToken) {
17 | print("======VoidViewModel.get()=====");
18 | this.view = view;
19 | this.cancelToken = cancelToken;
20 | }
21 |
22 | Future getData(
23 | {type = 0, Map? params2}) async {
24 | final data = await VoidModel(cancelToken, view).data(type, params2);
25 | if (data != null) {
26 | return data;
27 | }
28 | return Future.value(null);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lib/bean/option_bean.dart:
--------------------------------------------------------------------------------
1 | class OptionBean {
2 | dynamic first;
3 | dynamic second;
4 | dynamic third;
5 | dynamic four;
6 | dynamic five;
7 | dynamic isx;
8 |
9 | OptionBean(
10 | {this.first, this.second, this.third, this.four, this.five, this.isx});
11 |
12 | @override
13 | String toString() {
14 | return 'OptionBean{first: $first, second: $second, third: $third}';
15 | }
16 |
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/lib/common/api_exception.dart:
--------------------------------------------------------------------------------
1 | class ApiException implements Exception {
2 | final String? message;
3 |
4 | final int? code;
5 |
6 | const ApiException([this.code, this.message = ""]);
7 | }
8 |
--------------------------------------------------------------------------------
/lib/common/check.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | /// 手机号正则表达式->true匹配
4 | bool isMobilePhoneNumber(String value) {
5 | RegExp mobile = new RegExp(r"(0|86|17951)?(1[0-9][0-9])[0-9]{8}");
6 |
7 | return mobile.hasMatch(value);
8 | }
9 |
10 | ///验证网页URl
11 | bool isUrl(String value) {
12 | RegExp url = new RegExp(r"^((https|http|ftp|rtsp|mms)?:\/\/)[^\s]+");
13 |
14 | return url.hasMatch(value);
15 | }
16 |
17 | ///校验身份证
18 | bool isIdCard(String value) {
19 | RegExp identity = new RegExp(r"\d{17}[\d|x]|\d{15}");
20 |
21 | return identity.hasMatch(value);
22 | }
23 |
24 | ///正浮点数
25 | bool isMoney(String value) {
26 | RegExp identity = new RegExp(
27 | r"^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$");
28 | return identity.hasMatch(value);
29 | }
30 |
31 | ///校验中文
32 | bool isChinese(String value) {
33 | RegExp identity = new RegExp(r"[\u4e00-\u9fa5]");
34 |
35 | return identity.hasMatch(value);
36 | }
37 |
38 | ///校验支付宝名称
39 | bool isAliPayName(String value) {
40 | RegExp identity = new RegExp(r"[\u4e00-\u9fa5_a-zA-Z]");
41 |
42 | return identity.hasMatch(value);
43 | }
44 |
45 | /// 字符串不为空
46 | bool strNoEmpty(String value) {
47 | if (value == null) return false;
48 |
49 | return value.trim().isNotEmpty;
50 | }
51 |
52 | /// 字符串不为空
53 | bool mapNoEmpty(Map? value) {
54 | if (value == null) return false;
55 | return value.isNotEmpty;
56 | }
57 |
58 | ///判断List是否为空
59 | bool listNoEmpty(List list) {
60 | if (list == null) return false;
61 |
62 | if (list.length == 0) return false;
63 |
64 | return true;
65 | }
66 |
67 | /// 判断是否网络
68 | bool isNetWorkImg(String img) {
69 | return img.startsWith('http') || img.startsWith('https');
70 | }
71 |
72 | /// 判断是否资源图片
73 | bool isAssetsImg(String img) {
74 | return img.startsWith('asset') || img.startsWith('assets');
75 | }
76 |
77 | double getMemoryImageCashe() {
78 | return PaintingBinding.instance!.imageCache!.maximumSize / 1000;
79 | }
80 |
81 | void clearMemoryImageCache() {
82 | PaintingBinding.instance!.imageCache!.clear();
83 | }
84 |
85 | String stringAsFixed(value, num) {
86 | double v = double.parse(value.toString());
87 | String str = ((v * 100).floor() / 100).toStringAsFixed(2);
88 | return str;
89 | }
90 |
91 | String hiddenPhone(String phone){
92 | String result = '';
93 |
94 | if(phone != null && phone.length >= 11){
95 | String sub = phone.substring(0,3);
96 | String end = phone.substring(8,11);
97 | result = '$sub****$end';
98 | }
99 |
100 | return result;
101 | }
102 |
103 | ///去除后面的0
104 | String stringDisposeWithDouble(v, [fix = 2]) {
105 | double b = double.parse(v.toString());
106 | String vStr = b.toStringAsFixed(fix);
107 | int len = vStr.length;
108 | for (int i = 0; i < len; i++) {
109 | if (vStr.contains('.') && vStr.endsWith('0')) {
110 | vStr = vStr.substring(0, vStr.length - 1);
111 | } else {
112 | break;
113 | }
114 | }
115 |
116 | if (vStr.endsWith('.')) {
117 | vStr = vStr.substring(0, vStr.length - 1);
118 | }
119 |
120 | return vStr;
121 | }
122 |
123 | ///去除小数点
124 | String removeDot(v) {
125 | String vStr = v.toString().replaceAll('.', '');
126 |
127 | return vStr;
128 | }
--------------------------------------------------------------------------------
/lib/common/common.dart:
--------------------------------------------------------------------------------
1 | /// comMom
2 | export 'check.dart';
3 | export '../common/ui.dart';
4 | export 'win_media.dart';
5 | export 'check.dart';
6 | export 'date.dart';
7 | export 'file_util.dart';
8 |
9 | /// config
10 | export 'package:flutterjdshop/config/api.dart';
11 | export 'package:flutterjdshop/config/api.dart';
12 | export 'package:flutterjdshop/config/config.dart';
13 | export 'package:flutterjdshop/config/const.dart';
14 | export 'package:flutterjdshop/config/keys.dart';
15 |
16 | /// widget
17 | //export 'package:flutterjdshop/widget/bar/commom_bar.dart';
18 | //export 'package:flutterjdshop/widget/view/title_view.dart';
19 |
20 | /// other
21 | //export 'package:ncov_2019/widget/view/web_view_page.dart';
22 | export 'package:cached_network_image/cached_network_image.dart';
23 | export 'package:connectivity/connectivity.dart';
24 | import 'package:connectivity/connectivity.dart';
25 | export 'package:flutterjdshop/common/shared_util.dart';
26 |
27 |
28 | var subscription = Connectivity();
29 |
--------------------------------------------------------------------------------
/lib/common/date.dart:
--------------------------------------------------------------------------------
1 | import 'package:intl/intl.dart';
2 | import 'package:flutterjdshop/common/check.dart';
3 |
4 | class DateTimeForMater {
5 | static String full = "yyyy-MM-dd HH:mm:ss";
6 |
7 | static String formatDateV(DateTime dateTime, {bool? isUtc, String? format}) {
8 | if (dateTime == null) return "";
9 | format = format ?? full;
10 | if (format.contains("yy")) {
11 | String year = dateTime.year.toString();
12 | if (format.contains("yyyy")) {
13 | format = format.replaceAll("yyyy", year);
14 | } else {
15 | format = format.replaceAll(
16 | "yy", year.substring(year.length - 2, year.length));
17 | }
18 | }
19 |
20 | format = _comFormat(dateTime.month, format, 'M', 'MM');
21 | format = _comFormat(dateTime.day, format, 'd', 'dd');
22 | format = _comFormat(dateTime.hour, format, 'H', 'HH');
23 | format = _comFormat(dateTime.minute, format, 'm', 'mm');
24 | format = _comFormat(dateTime.second, format, 's', 'ss');
25 | format = _comFormat(dateTime.millisecond, format, 'S', 'SSS');
26 |
27 | return format;
28 | }
29 |
30 | static String _comFormat(
31 | int value, String format, String single, String full) {
32 | if (format.contains(single)) {
33 | if (format.contains(full)) {
34 | format =
35 | format.replaceAll(full, value < 10 ? '0$value' : value.toString());
36 | } else {
37 | format = format.replaceAll(single, value.toString());
38 | }
39 | }
40 | return format;
41 | }
42 | }
43 |
44 | String formatTimeStampToString(timestamp, [format]) {
45 | assert(timestamp != null);
46 |
47 | int time = 0;
48 |
49 | if (timestamp is int) {
50 | time = timestamp;
51 | } else {
52 | time = int.parse(timestamp.toString());
53 | }
54 |
55 | if (format == null) {
56 | format = 'yyyy-MM-dd HH:mm:ss';
57 | }
58 |
59 | DateFormat dateFormat = new DateFormat(format);
60 |
61 | var date = new DateTime.fromMillisecondsSinceEpoch(time * 1000);
62 |
63 | return dateFormat.format(date);
64 | }
65 |
66 | String timeHandle(int time) {
67 | double createTimeDouble = strNoEmpty('$time') ? time / 1000 : 0;
68 | int createTime = int.parse('${stringDisposeWithDouble(createTimeDouble)}');
69 | return '${formatTimeStampToString(createTime) ?? '未知'}';
70 | }
71 |
--------------------------------------------------------------------------------
/lib/common/functions.dart:
--------------------------------------------------------------------------------
1 | typedef OnChangedCallback = Future Function();
2 | ///我的界面路由回调
3 | typedef OnGoMineCallback = Future Function();
4 |
--------------------------------------------------------------------------------
/lib/common/ui.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class HorizontalLine extends StatelessWidget {
4 | final double height;
5 | final Color color;
6 | final double horizontal;
7 |
8 | HorizontalLine({
9 | this.height = 0.5,
10 | this.color = const Color(0xFFEEEEEE),
11 | this.horizontal = 0.0,
12 | });
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | return new Container(
17 | height: height,
18 | color: color,
19 | margin: new EdgeInsets.symmetric(horizontal: horizontal),
20 | );
21 | }
22 | }
23 |
24 | class VerticalLine extends StatelessWidget {
25 | final double width;
26 | final double height;
27 | final Color color;
28 | final double vertical;
29 |
30 | VerticalLine({
31 | this.width = 1.0,
32 | this.height = 25,
33 | this.color = const Color.fromRGBO(209, 209, 209, 0.5),
34 | this.vertical = 0.0,
35 | });
36 |
37 | @override
38 | Widget build(BuildContext context) {
39 | return new Container(
40 | width: width,
41 | color: Color(0xffDCE0E5),
42 | margin: new EdgeInsets.symmetric(vertical: vertical),
43 | height: height,
44 | );
45 | }
46 | }
47 |
48 | class Space extends StatelessWidget {
49 | final double width;
50 | final double height;
51 |
52 | Space({this.width = 10.0, this.height = 10.0});
53 |
54 | @override
55 | Widget build(BuildContext context) {
56 | return new Container(width: width, height: height);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/lib/common/win_media.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:flutter/material.dart';
4 |
5 | double winWidth(BuildContext context) {
6 | return MediaQuery.of(context).size.width;
7 | }
8 |
9 | double winHeight(BuildContext context) {
10 | return MediaQuery.of(context).size.height;
11 | }
12 |
13 | double winTop(BuildContext context) {
14 | return MediaQuery.of(context).padding.top;
15 | }
16 |
17 | double winBottom(BuildContext context) {
18 | return MediaQuery.of(context).padding.bottom;
19 | }
20 |
21 | double winLeft(BuildContext context) {
22 | return MediaQuery.of(context).padding.left;
23 | }
24 |
25 | double winRight(BuildContext context) {
26 | return MediaQuery.of(context).padding.right;
27 | }
28 |
29 | double winKeyHeight(BuildContext context) {
30 | return MediaQuery.of(context).viewInsets.bottom;
31 | }
32 |
33 | double statusBarHeight(BuildContext context) {
34 | return MediaQueryData.fromWindow(window).padding.top;
35 | }
36 |
37 | double navigationBarHeight(BuildContext context) {
38 | return kToolbarHeight;
39 | }
40 |
41 | double topBarHeight(BuildContext context) {
42 | return kToolbarHeight + MediaQueryData.fromWindow(window).padding.top;
43 | }
44 |
--------------------------------------------------------------------------------
/lib/config/api.dart:
--------------------------------------------------------------------------------
1 | class API {
2 | // 请求的url
3 | //static const reqUrl = 'http://10.0.2.2:8086';
4 |
5 | //static const reqUrl = 'http://47.94.169.13:8086';
6 | static const baseUrl = 'http://jd.itying.com/';
7 | static const reqUrl = '${baseUrl}api/';
8 | //
9 | static const focus = 'focus';
10 | static const plist = 'plist';
11 | static const pcate = 'pcate';
12 | static const sendCode = 'sendCode';
13 | static const register = 'register';
14 | static const addressList = 'addressList';
15 | static const login = 'doLogin';
16 | static const addAddress = 'addAddress';
17 | static const editAddress = 'editAddress';
18 | static const deleteAddress = 'deleteAddress';
19 | static const changeDefaultAddress = 'changeDefaultAddress';
20 | static const pcontent = 'pcontent';
21 | static const doOrder = 'doOrder';
22 | static const oneAddressList = 'oneAddressList';
23 | static const orderList = 'orderList';
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/lib/config/config.dart:
--------------------------------------------------------------------------------
1 | /// app名字
2 | const String title = 'ncov-2019';
3 |
4 | ///连接超时时间为5秒
5 | const int connectTimeOut = 10 ;
6 |
7 | ///响应超时时间为7秒
8 | const int receiveTimeOut = 7;
9 |
--------------------------------------------------------------------------------
/lib/config/const.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:flutter/material.dart';
4 |
5 | const bool inProduction = const bool.fromEnvironment('dart.vm.product');
6 |
7 | const topic = "topic";
8 | const cateGory = "cateGory";
9 | const IMAGE_JPG = "jpg";
10 | const IMAGE_PNG = "png";
11 | const PI = pi;
12 | const DEGREE = 180.0;
13 |
14 | int orderIndex = 0;
15 | const limitSize = 20;
16 |
17 |
18 | /// debug开关,上线需要关闭
19 | /// App运行在Release环境时,inProduction为true;当App运行在Debug和Profile环境时,inProduction为false
20 |
21 | bool isDriverTest = false;
22 | bool isUnitTest = false;
23 |
24 | const String data = 'data';
25 | const String message = 'message';
26 | const String code = 'code';
27 |
28 | const String keyGuide = 'keyGuide';
29 | const String phone = 'phone';
30 | const String accessToken = 'accessToken';
31 | const String refreshToken = 'refreshToken';
32 |
33 | const String theme = 'AppTheme';
--------------------------------------------------------------------------------
/lib/config/keys.dart:
--------------------------------------------------------------------------------
1 | class Keys {
2 | static final String account = "account";
3 | static final String keyGuide = "keyGuide";
4 | static const bool inProduction = const bool.fromEnvironment('dart.vm.product');
5 |
6 | static bool isTest = false;
7 |
8 | static const String data = 'data';
9 | static const String message = 'message';
10 | static const String code = 'code';
11 |
12 | static const String phone = 'phone';
13 | static const String accessToken = 'accessToken';
14 | static const String refreshToken = 'refreshToken';
15 |
16 | static const String theme = 'AppTheme';
17 | }
18 |
--------------------------------------------------------------------------------
/lib/config/storage_manager.dart:
--------------------------------------------------------------------------------
1 | import 'package:shared_preferences/shared_preferences.dart';
2 |
3 | class StorageManager {
4 | /// app全局配置
5 | static late SharedPreferences sp;
6 |
7 | /// 网络连接
8 | var connect;
9 |
10 | /// 必备数据的初始化操作
11 | static init() async {
12 | // async 异步操作
13 | // sync 同步操作
14 | sp = await SharedPreferences.getInstance();
15 |
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/lib/config/user_info_data.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutterjdshop/common/common.dart';
2 | import 'package:flutterjdshop/utils/utils.dart';
3 |
4 | class UserInfoData {
5 | //用户相关信息
6 | static UserInfoData? _instance;
7 | bool isUser = false;
8 | int orderIndex = 0;
9 | String? account;
10 | String? salt;
11 | String? id;
12 | String? mobile;
13 | String? token;
14 | String? nickName;
15 | String? avatar;
16 | String? gender;
17 |
18 | factory UserInfoData() => _getInstance()!;
19 |
20 | static UserInfoData? get instance => _getInstance();
21 |
22 | UserInfoData._internal() {
23 | // 初始化
24 | }
25 |
26 | static UserInfoData? _getInstance() {
27 | if (_instance == null) {
28 | _instance = new UserInfoData._internal();
29 | }
30 | return _instance;
31 | }
32 |
33 | setSalt(salt) {
34 | this.salt = salt;
35 | saveStrByKey("salt", salt);
36 | }
37 |
38 | setId(id) {
39 | this.id = id;
40 | saveStrByKey("id", id);
41 | }
42 |
43 | setToken(token) {
44 | this.token = token;
45 | saveStrByKey("token", token);
46 | }
47 |
48 | get isLogin {
49 | return account != null && account!.isNotEmpty;
50 | }
51 |
52 | setNickName(String name) {
53 | this.nickName = name;
54 | saveStrByKey("nickName", name);
55 | }
56 |
57 | setAvatar(String avatar) {
58 | this.avatar = avatar;
59 | saveStrByKey("avatar", avatar);
60 | }
61 |
62 | setMobile(String mobile) {
63 | this.mobile = mobile;
64 | saveStrByKey("mobile", mobile);
65 | }
66 |
67 | setAccount(String account) {
68 | this.account = account;
69 | saveStrByKey("account", account);
70 | }
71 |
72 | setGender(String gender) {
73 | this.gender = gender;
74 | saveStrByKey("gender", gender);
75 | }
76 |
77 | get getUserInfo {
78 | this.account = getStrByKey("account");
79 | this.token = getStrByKey("token");
80 | this.nickName = getStrByKey("nickName");
81 | this.salt = getStrByKey("salt");
82 | this.gender = getStrByKey("gender");
83 | this.id = getStrByKey("id");
84 | this.mobile = getStrByKey("mobile");
85 | this.id = getStrByKey("id");
86 | this.avatar = getStrByKey("avatar");
87 | }
88 |
89 | set userInfo(map) {
90 | setId(map["_id"]);
91 | setAccount(map["username"]);
92 | setMobile(map["tel"]);
93 | setSalt(map["salt"]);
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/lib/http/base_response.dart:
--------------------------------------------------------------------------------
1 | ///返回对象封装
2 | class BaseResponse {
3 | BaseResponse(this.result);
4 |
5 |
6 | //返回的数据,需要自己进行处理成自己想要的对象
7 | dynamic result;
8 | bool? success;
9 | String? message;
10 |
11 | BaseResponse.fromJson(Map json)
12 | :result = json["result"],success=json["success"],message=json["message"];
13 | }
--------------------------------------------------------------------------------
/lib/http/dio_utils.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:flutterjdshop/config/api.dart';
3 | import 'package:flutterjdshop/config/config.dart';
4 |
5 | import 'intercept.dart';
6 |
7 | class DioUtils {
8 | static final DioUtils _singleton = DioUtils._internal();
9 |
10 | static DioUtils get instance => DioUtils();
11 |
12 | factory DioUtils() {
13 | return _singleton;
14 | }
15 |
16 | static Dio? _dio;
17 |
18 | Dio? getDio() {
19 | return _dio;
20 | }
21 |
22 | DioUtils._internal() {
23 | var options = BaseOptions(
24 | connectTimeout: Duration(seconds: connectTimeOut),
25 | receiveTimeout: Duration(seconds: receiveTimeOut),
26 | //responseType: ResponseType.plain,
27 | headers: {
28 | 'content-type': 'application/json',
29 | },
30 | validateStatus: (status) {
31 | // 不使用http状态码判断状态,使用AdapterInterceptor来处理(适用于标准REST风格)
32 | return true;
33 | },
34 | baseUrl: API.reqUrl,
35 | // contentType: ContentType('application', 'x-www-form-urlencoded', charset: 'utf-8'),
36 | );
37 | _dio = new Dio(options);
38 | _dio!.interceptors.add(AuthInterceptor());
39 | /// Fiddler抓包代理配置 https://www.jianshu.com/p/d831b1f7c45b
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/lib/http/intercept.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:flutterjdshop/config/user_info_data.dart';
3 |
4 | class AuthInterceptor extends Interceptor {
5 | @override
6 | void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
7 | // TODO: implement onRequest
8 | options.headers['Authorization'] = UserInfoData.instance!.token;
9 | return super.onRequest(options, handler);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/lib/http/mvvms.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | abstract class IMvvmView {
5 | BuildContext getContext();
6 |
7 | /// 显示Progress
8 | void showProgress();
9 |
10 | /// 关闭Progress
11 | void closeProgress();
12 |
13 | /// 展示Toast
14 | void showToast(String string);
15 | }
16 |
--------------------------------------------------------------------------------
/lib/http/request_listener.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'base_response.dart';
4 |
5 | ///网络请求监听
6 | class RequestListener {
7 | RequestListener({required this.onSuccessListener, required this.onErrorListener});
8 |
9 | //请求成功
10 | final ValueChanged onSuccessListener;
11 |
12 | //请求失败
13 | final ValueChanged onErrorListener;
14 |
15 | void onSuccess(BaseResponse response) {
16 | if (onSuccessListener != null) onSuccessListener(response);
17 | }
18 |
19 | void onError(BaseResponse response) {
20 | if (onErrorListener != null) onErrorListener(response);
21 | }
22 | }
--------------------------------------------------------------------------------
/lib/http/view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:flutterjdshop/http/mvvms.dart';
3 |
4 | class ViewModel {
5 | V? view;
6 | CancelToken? cancelToken;
7 | }
8 |
--------------------------------------------------------------------------------
/lib/l10n/app_en.arb:
--------------------------------------------------------------------------------
1 | {
2 | "app_name": "I am flutter admin template"
3 | }
--------------------------------------------------------------------------------
/lib/l10n/app_zh.arb:
--------------------------------------------------------------------------------
1 | {
2 | "app_name": "我是 flutter admin template"
3 | }
--------------------------------------------------------------------------------
/lib/page/cart/CartItem.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutterjdshop/utils/app_size.dart';
3 | import 'package:flutterjdshop/utils/utils.dart';
4 | import 'package:flutterjdshop/widget/load_image.dart';
5 |
6 | import 'package:provider/provider.dart';
7 | import '../../provider/Cart.dart';
8 | import 'CartNum.dart';
9 |
10 | class CartItem extends StatefulWidget {
11 | Map _itemData;
12 | CartItem(this._itemData,{Key? key}) : super(key: key);
13 |
14 | _CartItemState createState() => _CartItemState();
15 | }
16 |
17 | class _CartItemState extends State {
18 | Map? _itemData;
19 |
20 | @override
21 | Widget build(BuildContext context) {
22 | //注意:给属性赋值
23 | this._itemData=widget._itemData;
24 |
25 | var cartProvider = Provider.of(context,listen: false);
26 | return Container(
27 | height: AppSize.height(220),
28 | padding: EdgeInsets.all(5),
29 | decoration: BoxDecoration(
30 | border: Border(bottom: BorderSide(width: 1, color: Colors.black12))),
31 | child: Row(
32 | children: [
33 | Container(
34 | width: AppSize.width(60),
35 | child: Checkbox(
36 | value: _itemData!["checked"],
37 | onChanged: (val) {
38 | _itemData!["checked"]=!_itemData!["checked"];
39 | cartProvider.itemChage();
40 | },
41 | activeColor: Colors.pink,
42 | ),
43 | ),
44 | Container(
45 | width: AppSize.width(160),
46 | child: LoadImage(
47 | "${getFullPath(_itemData!["pic"])}",
48 | fit: BoxFit.cover),
49 | ),
50 | Expanded(
51 | flex: 1,
52 | child: Container(
53 | padding: EdgeInsets.fromLTRB(10, 10, 10, 5),
54 | child: Column(
55 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
56 | crossAxisAlignment: CrossAxisAlignment.start,
57 | children: [
58 | Text("${_itemData!["title"]}",
59 | maxLines: 2),
60 | Text("${_itemData!["selectedAttr"]}",
61 | maxLines: 2),
62 | Stack(
63 | children: [
64 | Align(
65 | alignment: Alignment.centerLeft,
66 | child: Text("¥${_itemData!["price"]}",style: TextStyle(
67 | color: Colors.red
68 | )),
69 | ),
70 | Align(
71 | alignment: Alignment.centerRight,
72 | child: CartNum(_itemData),
73 | )
74 | ],
75 | )
76 | ],
77 | ),
78 | ),
79 | )
80 | ],
81 | ),
82 | );
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/lib/page/cart/CartNum.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/widgets.dart';
3 | import 'package:flutterjdshop/utils/app_size.dart';
4 |
5 | import 'package:provider/provider.dart';
6 | import '../../provider/Cart.dart';
7 |
8 | class CartNum extends StatefulWidget {
9 | Map? _itemData;
10 | CartNum(this._itemData,{Key? key}) : super(key: key);
11 |
12 | _CartNumState createState() => _CartNumState();
13 | }
14 |
15 | class _CartNumState extends State {
16 | Map? _itemData;
17 | late var cartProvider;
18 |
19 | @override
20 | Widget build(BuildContext context) {
21 |
22 | //注意
23 | this._itemData=widget._itemData;
24 |
25 | this.cartProvider = Provider.of(context);
26 |
27 | return Container(
28 | width: AppSize.width(168),
29 | decoration:
30 | BoxDecoration(border: Border.all(width: AppSize.width(2), color: Colors.black12)),
31 | child: Row(
32 | children: [
33 | _leftBtn(),
34 | _centerArea(),
35 | _rightBtn()
36 | ],
37 | ),
38 | );
39 | }
40 |
41 | //左侧按钮
42 |
43 | Widget _leftBtn() {
44 | return InkWell(
45 | onTap: () {
46 | if(_itemData!["count"]>1){
47 | _itemData!["count"]--;
48 | this.cartProvider.itemCountChange();
49 | }
50 | },
51 | child: Container(
52 | alignment: Alignment.center,
53 | width: AppSize.width(45),
54 | height: AppSize.height(45),
55 | child: Text("-"),
56 | ),
57 | );
58 | }
59 |
60 | //右侧按钮
61 | Widget _rightBtn() {
62 | return InkWell(
63 | onTap: (){
64 | _itemData!["count"]++;
65 | this.cartProvider.itemCountChange();
66 | },
67 | child: Container(
68 | alignment: Alignment.center,
69 | width: AppSize.width(45),
70 | height: AppSize.height(45),
71 | child: Text("+"),
72 | ),
73 | );
74 | }
75 |
76 | //中间
77 | Widget _centerArea() {
78 | return Container(
79 | alignment: Alignment.center,
80 | width: AppSize.width(70),
81 | decoration: BoxDecoration(
82 | border: Border(
83 | left: BorderSide(width: AppSize.width(2), color: Colors.black12),
84 | right: BorderSide(width: AppSize.width(2), color: Colors.black12),
85 | )),
86 | height: AppSize.height(45),
87 | child: Text("${_itemData!["count"]}"),
88 | );
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/lib/page/demo/ai_progress/progress_mixin.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | mixin ProgressMixin{
4 |
5 | //画path
6 | drawProgressPath(Paint paint,Canvas canvas, Size size);
7 |
8 | drawProgressValue(Paint paint,Canvas canvas, Size size);
9 |
10 |
11 | }
--------------------------------------------------------------------------------
/lib/page/demo/ai_progress/yuanxing/one_circle.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'dart:math';
3 |
4 | import 'package:flutterjdshop/bean/option_bean.dart';
5 |
6 | //传入颜色和值来画饼形状
7 | class OneCircle extends StatefulWidget {
8 | //饼状的颜色
9 | final List? colors;
10 | final int index;
11 |
12 | //饼状的值
13 | final List? values;
14 |
15 | OneCircle({Key? key, this.colors, this.values, this.index = -1})
16 | : super(key: key) {
17 | ///两个值数量一定要一致
18 | assert(colors!.length == values!.length);
19 | }
20 |
21 | @override
22 | _OneCircleState createState() => _OneCircleState();
23 | }
24 |
25 | class _OneCircleState extends State {
26 | @override
27 | Widget build(BuildContext context) {
28 | return Container(
29 | child: RepaintBoundary(
30 | child: CustomPaint(
31 | size: Size(100, 100),
32 | painter: B._(widget.colors, widget.values, true, true, widget.index),
33 | ),
34 | ),
35 | );
36 | }
37 | }
38 |
39 | class B extends CustomPainter {
40 | //饼状的颜色
41 | final List? colors;
42 |
43 | //饼状的值
44 | final List? values;
45 | bool _shouldRepaint;
46 |
47 | final int index;
48 |
49 | ///判断是否和中心点连接
50 | bool _useCenter;
51 |
52 | Size? size;
53 |
54 | var _valuePaint = Paint();
55 |
56 | B._(this.colors, this.values, this._shouldRepaint, this._useCenter,
57 | this.index);
58 |
59 | @override
60 | void paint(Canvas canvas, Size size) {
61 | // TODO: implement paint
62 | this.size = size;
63 | _setPaint();
64 | var of = Offset.zero & size;
65 | if (index == -1) {
66 | _getSweepAngle.map((d) {
67 | _valuePaint..color = d.third;
68 | canvas.drawArc(of, d.first, d.second, _useCenter, _valuePaint);
69 | }).toList();
70 | } else {
71 | //新创建一个图层
72 | _getSweepAngle.sublist(0,index).map((d){
73 | _valuePaint..color = d.third;
74 | canvas.drawArc(of, d.first, d.second, _useCenter, _valuePaint);
75 | }).toList();
76 | }
77 | }
78 |
79 | @override
80 | bool shouldRepaint(CustomPainter oldDelegate) {
81 | // TODO: implement shouldRepaint
82 | return _shouldRepaint;
83 | }
84 |
85 | _setPaint() {
86 | return _valuePaint
87 | ..color = Colors.grey
88 | ..strokeWidth = 10
89 | ..strokeCap = StrokeCap.round
90 | ..strokeJoin = StrokeJoin.bevel
91 | ..style = PaintingStyle.fill;
92 | }
93 |
94 | /// 算出弧度大小
95 |
96 | List get _getSweepAngle {
97 | double small = pi * 2 / getCount;
98 | double startNum = 0;
99 | List ops = [];
100 | List.generate(values!.length, (index) {
101 | var op = OptionBean(first: startNum);
102 | //设置画笔颜色和值
103 | //360
104 | op.second = values![index] * small;
105 | startNum += op.second;
106 | op.third = colors![index];
107 | ops.add(op);
108 | });
109 | return ops;
110 | }
111 |
112 | double get getCount => values!.reduce((x1, x2) => x1 + x2);
113 | }
114 |
--------------------------------------------------------------------------------
/lib/page/demo/boundary.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/rendering.dart';
3 |
4 | class LayoutBoundaryDelegate extends MultiChildLayoutDelegate {
5 | LayoutBoundaryDelegate();
6 |
7 | static const String title = 'title';
8 | static const String summary = 'summary';
9 | static const String paintBoundary = 'paintBoundary';
10 |
11 | @override
12 | void performLayout(Size size) {
13 | print('TestLayoutDelegate performLayout ');
14 |
15 | final BoxConstraints constraints = BoxConstraints(maxWidth: size.width);
16 |
17 | final Size titleSize = layoutChild(title, constraints);
18 | positionChild(title, Offset(0.0, 0.0));
19 |
20 | final double summaryY = titleSize.height;
21 | final Size descriptionSize = layoutChild(summary, constraints);
22 | positionChild(summary, Offset(0.0, summaryY));
23 |
24 | final double paintBoundaryY = summaryY + descriptionSize.height;
25 | final Size paintBoundarySize = layoutChild(paintBoundary, constraints);
26 | positionChild(
27 | paintBoundary, Offset(paintBoundarySize.width / 2, paintBoundaryY));
28 | }
29 |
30 | @override
31 | bool shouldRelayout(LayoutBoundaryDelegate oldDelegate) => false;
32 | }
33 |
34 | class LayoutBoundary extends StatefulWidget {
35 | LayoutBoundary({Key? key}) : super(key: key);
36 |
37 | @override
38 | _LayoutBoundaryState createState() => _LayoutBoundaryState();
39 | }
40 |
41 | class _LayoutBoundaryState extends State {
42 | String _buttonText = 'h';
43 | int _index = 1;
44 |
45 | @override
46 | Widget build(BuildContext context) {
47 | return Center(
48 | child: ElevatedButton(
49 | child: Text(
50 | '${_buttonText * _index}',
51 | textDirection: TextDirection.ltr,
52 | overflow: TextOverflow.ellipsis,
53 | ),
54 | onPressed: () {
55 | setState(() {
56 | _index++;
57 | });
58 | },
59 | ),
60 | );
61 | }
62 | }
63 |
64 | class PaintBoundary extends StatelessWidget {
65 | @override
66 | Widget build(BuildContext context) {
67 | return CustomPaint(painter: CirclePainter(color: Colors.orange));
68 | }
69 | }
70 |
71 | class CirclePainter extends CustomPainter {
72 | final Color? color;
73 |
74 | const CirclePainter({this.color});
75 |
76 | @override
77 | void paint(Canvas canvas, Size size) {
78 | print('CirclePainter paint');
79 | var radius = size.width / 2;
80 | var paint = Paint()
81 | ..color = color!
82 | ..style = PaintingStyle.fill;
83 | canvas.drawCircle(Offset(radius, size.height), radius, paint);
84 | }
85 |
86 | @override
87 | bool shouldRepaint(CustomPainter oldDelegate) => false;
88 | }
--------------------------------------------------------------------------------
/lib/page/demo/canvas_paint.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutterjdshop/base/base_page_state.dart';
3 | import 'package:flutterjdshop/page/demo/my_custompainter.dart';
4 | import 'package:flutterjdshop/view/app_topbar.dart';
5 |
6 | import 'my_custompainter2.dart';
7 |
8 | class CanvasPaintStudy extends StatefulWidget {
9 | @override
10 | _CanvasPaintStudyState createState() => _CanvasPaintStudyState();
11 | }
12 |
13 | class _CanvasPaintStudyState extends BasePageState {
14 |
15 | @override
16 | Widget getAppBar(BuildContext context) {
17 | // TODO: implement getAppBar
18 | return CommonBackTopBar(
19 | title: "学习画布操作"
20 | );
21 | }
22 | @override
23 | Widget getBody(BuildContext context) {
24 | // TODO: implement getBody
25 | return Container(
26 | child: Column(
27 | children: [
28 | RepaintBoundary(
29 | child: CustomPaint(
30 | size: Size(300,300),
31 | painter: MyCustomPainter(),
32 | ),
33 | ),
34 | RepaintBoundary(
35 | child: CustomPaint(
36 | size: Size(300,300),
37 | painter: MyCustomPainter2(),
38 | ),
39 | )
40 | ],
41 | ),
42 | );
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/lib/page/demo/customcheckbox/my_check_box.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/rendering.dart';
3 | import 'package:flutterjdshop/utils/log_utils.dart';
4 |
5 | ///抽取出来缩小刷新区域
6 | class MyCheckBox extends StatefulWidget {
7 | // 是否是check状态
8 | final bool? isChecked;
9 |
10 | final Color colorBg;
11 | final Color color;
12 | final double size;
13 |
14 | // check回传
15 | final ValueChanged? onChecked;
16 |
17 | MyCheckBox({
18 | Key? key,
19 | this.isChecked,
20 | this.colorBg = Colors.red,
21 | this.color = Colors.blue,
22 | this.onChecked,
23 | this.size = 300,
24 | }) : super(key: key);
25 |
26 | @override
27 | State createState() => CheckTextBox(isChecked: isChecked);
28 |
29 | }
30 |
31 | class CheckTextBox extends State {
32 | // 是否是check状态 如何修改这个状态呢
33 | bool? isChecked;
34 |
35 | CheckTextBox({this.isChecked = false});
36 |
37 | @override
38 | void initState() {
39 | // TODO: implement initState
40 | super.initState();
41 | }
42 |
43 | @override
44 | Widget build(BuildContext context) {
45 | Log.e("MyCheckBox=>build$isChecked");
46 | return Container(
47 | color: widget.colorBg,
48 | child: GestureDetector(
49 | onTap: () {
50 | setState(() {
51 | isChecked = !isChecked!;
52 | // 回传改变事件
53 | if (widget.onChecked != null) widget.onChecked!(isChecked);
54 | });
55 | },
56 |
57 | ///防止过度重绘
58 | child: RepaintBoundary(
59 | child: CustomPaint(
60 | size: Size(widget.size, widget.size),
61 | painter: MyCheckBoxPainter(isCheck: isChecked),
62 | ),
63 | ),
64 | ),
65 | );
66 | }
67 |
68 | void setChecked(bool isCheck) {
69 | isChecked = isCheck;
70 | }
71 | }
72 |
73 | class MyCheckBoxPainter extends CustomPainter {
74 | final _paint = Paint();
75 | bool? isCheck = false;
76 | Color color;
77 | MyCheckBoxPainter({this.isCheck = false, this.color = Colors.blue}) {
78 | _paint.color = color; //白色笔
79 | _paint.isAntiAlias = true; // 抗锯齿
80 | }
81 |
82 | @override
83 | void paint(Canvas canvas, Size size) {
84 | // TODO: implement paint
85 |
86 | double _center = size.height / 2; //中心点
87 | _paint.strokeWidth = size.height * 0.12; // 设置空心圆的宽度
88 | double _radius = _center - _paint.strokeWidth / 2; //半径
89 | _paint.style = PaintingStyle.stroke; // 设置空心笔
90 | ///圆形半径为(width-笔的宽度)/2
91 | ///画弧形是矩形内切
92 | canvas.drawCircle(Offset(_center, _center), _radius, _paint);
93 | if (isCheck!) {
94 | _paint.style = PaintingStyle.fill;
95 | canvas.drawCircle(Offset(_center, _center), _radius / 2, _paint);
96 | }
97 | }
98 |
99 | @override
100 | bool shouldRepaint(CustomPainter oldDelegate) {
101 | // TODO: implement shouldRepaint
102 | return (oldDelegate as MyCheckBoxPainter).isCheck != isCheck;
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/lib/page/demo/divider_study.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:rxdart/rxdart.dart';
3 |
4 | ///height:是控件的高,并不是线的高度,绘制的线居中。
5 | ///thickness:线的高度。
6 | ///indent:分割线前面空白区域。
7 | ///endIndent:分割线后面空白区域。
8 | ///可以在ThemeData-dividerTheme中配置 DividerThemeData
9 | class StudyDivider extends StatelessWidget {
10 | @override
11 | Widget build(BuildContext context) {
12 | return Scaffold(
13 | body: Container(
14 | child: Column(
15 | children: [
16 | Container(
17 | height: 200,
18 | child: ListView.separated(
19 | itemBuilder: (context, index) {
20 | return ListTile(
21 | title: Text("====$index"),
22 | );
23 | },
24 | separatorBuilder: (context, index) {
25 | return Divider(
26 | color: Colors.red,
27 | endIndent: 10,
28 | indent: 5,
29 | height: 15,
30 | );
31 | },
32 | itemCount: 3),
33 | ),
34 | Column(
35 | children: ListTile.divideTiles(context: context, tiles: gets())
36 | .toList(),
37 | )
38 | ],
39 | ),
40 | ),
41 | );
42 | }
43 |
44 | List gets() {
45 | List datas = [];
46 | for(int i=0;i<4;i++){
47 | datas.add(ListTile(
48 | title: Text("====$i"),
49 | ));
50 | }
51 |
52 |
53 | return datas;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/lib/page/demo/flutter_Inheritedwidget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/foundation.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:flutterjdshop/base/base_page_state.dart';
5 | import 'package:flutterjdshop/page/demo/share_data_widget.dart';
6 | import 'package:flutterjdshop/view/app_topbar.dart';
7 |
8 | class InheritedWidgetPage extends StatefulWidget {
9 | final Map>? address;
10 |
11 | const InheritedWidgetPage({Key? key, this.address}) : super(key: key);
12 |
13 | @override
14 | _InheritedWidgetPageState createState() => _InheritedWidgetPageState();
15 | }
16 |
17 | class _InheritedWidgetPageState extends BasePageState {
18 | int count = 0;
19 |
20 | @override
21 | Widget getAppBar(BuildContext context) {
22 | // TODO: implement getAppBar
23 | return CommonBackTopBar(title: "InheritedWidget的使用方法");
24 | }
25 |
26 | @override
27 | void subInitState() {
28 |
29 | }
30 |
31 | @override
32 | Widget getBody(BuildContext context) {
33 | // TODO: implement getBody
34 | return new Center(
35 | child: new Column(
36 | children: [
37 | ShareDataWidget(
38 | data: count,
39 | child: _TestWidget(),
40 | ),
41 | Container(
42 | color: Colors.red,
43 | child: new MaterialButton(
44 | onPressed: () {
45 | setState(() {
46 | count++;
47 | });
48 |
49 | }, child: new Text("测试InheritedWidget")),
50 | padding: const EdgeInsets.all(8.0),
51 | ),
52 | ],
53 | ),
54 | );
55 | }
56 | }
57 | class _TestWidget extends StatefulWidget {
58 | @override
59 | __TestWidgetState createState() => new __TestWidgetState();
60 | }
61 |
62 | class __TestWidgetState extends State<_TestWidget> {
63 | @override
64 | Widget build(BuildContext context) {
65 | //使用InheritedWidget中的共享数据
66 | return Text(ShareDataWidget
67 | .of(context)!
68 | .data
69 | .toString());
70 | }
71 |
72 | @override
73 | void didChangeDependencies() {
74 | super.didChangeDependencies();
75 | //父或祖先widget中的InheritedWidget改变(updateShouldNotify返回true)时会被调用。
76 | //如果build中没有依赖InheritedWidget,则此回调不会被调用。
77 | print("Dependencies change");
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/lib/page/demo/flutter_barcode.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/foundation.dart';
5 | import 'package:flutter/material.dart';
6 | import 'package:flutter/services.dart';
7 | import 'package:flutterjdshop/base/base_page_state.dart';
8 | import 'package:flutterjdshop/view/app_topbar.dart';
9 | class BracodePage extends StatefulWidget {
10 | final Map>? address;
11 |
12 | const BracodePage({Key? key, this.address}) : super(key: key);
13 |
14 | @override
15 | _BracodePageState createState() => _BracodePageState();
16 | }
17 |
18 | class _BracodePageState extends BasePageState {
19 | @override
20 | Widget getAppBar(BuildContext context) {
21 | // TODO: implement getAppBar
22 | return CommonBackTopBar(title: "Barcode Scanner Example");
23 | }
24 |
25 | @override
26 | void subInitState() {}
27 |
28 | @override
29 | Widget getBody(BuildContext context) {
30 | // TODO: implement getBody
31 | return new Center(
32 | child: new Column(
33 | children: [
34 | new Container(
35 | child: new MaterialButton(onPressed: scan, child: new Text("Scan")),
36 | padding: const EdgeInsets.all(8.0),
37 | ),
38 | new Text(barcode),
39 | ],
40 | ),
41 | );
42 | }
43 |
44 | String barcode = "";
45 |
46 | Future scan() async {
47 | // try {
48 | // ScanResult barcode = await BarcodeScanner.scan();
49 | // setState(() => this.barcode = barcode.rawContent);
50 | // } on PlatformException catch (e) {
51 | // if (e.code == BarcodeScanner.cameraAccessDenied) {
52 | // setState(() {
53 | // this.barcode = 'The user did not grant the camera permission!';
54 | // });
55 | // } else {
56 | // setState(() => this.barcode = 'Unknown error: $e');
57 | // }
58 | // } on FormatException{
59 | // setState(() => this.barcode = 'null (User returned using the "back"-button before scanning anything. Result)');
60 | // } catch (e) {
61 | // setState(() => this.barcode = 'Unknown error: $e');
62 | // }
63 | }
64 |
65 |
66 | Future loadString() async {
67 | final ByteData data = ByteData(10);
68 | if (data.lengthInBytes < 10 * 1024) {
69 | return utf8.decode(data.buffer.asUint8List());
70 | }
71 | return compute(_utf8decode, data, debugLabel: "");
72 | }
73 |
74 | static String _utf8decode(ByteData data) {
75 | return utf8.decode(data.buffer.asUint8List());
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/lib/page/demo/flutter_selector.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/foundation.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:flutterjdshop/base/base_page_state.dart';
5 | import 'package:flutterjdshop/provider/counter_provider.dart';
6 | import 'package:flutterjdshop/utils/log_utils.dart';
7 | import 'package:flutterjdshop/view/app_topbar.dart';
8 | import 'package:provider/provider.dart';
9 |
10 | import 'customcheckbox/my_check_box.dart';
11 |
12 | ///我们在使用Selector的时候也小心一些,包裹的粒度尽可能的小
13 | class SelectorPage extends StatefulWidget {
14 | final Map>? address;
15 |
16 | const SelectorPage({Key? key, this.address}) : super(key: key);
17 |
18 | @override
19 | _SelectorPageState createState() => _SelectorPageState();
20 | }
21 |
22 | class _SelectorPageState extends BasePageState {
23 | bool? check = false;
24 | var myCheckBoxKey = GlobalKey();
25 |
26 | @override
27 | Widget getAppBar(BuildContext context) {
28 | // TODO: implement getAppBar
29 | return CommonBackTopBar(title: "Selector的使用方法");
30 | }
31 |
32 | @override
33 | void subInitState() {}
34 |
35 | @override
36 | Widget getBody(BuildContext context) {
37 | // TODO: implement getBody
38 | Log.e("getBody=$check");
39 | return new Center(
40 | child: new Column(
41 | children: [
42 | Checkbox(value: check, onChanged: (value) {}),
43 | CheckboxListTile(
44 | secondary: const Icon(Icons.shutter_speed),
45 | title: const Text('硬件加速'),
46 | value: this.check,
47 | onChanged: (bool? value) {
48 | setState(() {
49 | this.check = value;
50 | (myCheckBoxKey.currentState as CheckTextBox).isChecked = check;
51 | });
52 | },
53 | ),
54 | MyCheckBox(
55 | key: myCheckBoxKey,
56 | isChecked: check,
57 | colorBg: Colors.black,
58 | onChecked: (value) {
59 | check = value;
60 | Log.e("$check");
61 | },
62 | ),
63 | new Container(
64 | child: new MaterialButton(
65 | onPressed: () {
66 | //false
67 | Provider.of(context, listen: false)
68 | .increment();
69 | setState(() {
70 | Log.e("$check");
71 | });
72 | },
73 | child: new Text("测试Selector")),
74 | padding: const EdgeInsets.all(8.0),
75 | ),
76 | Selector(builder: (context, dynamic value, child) {
77 | return Text("$value");
78 | }, selector: (context, CounterProvider value) {
79 | return value.value;
80 | })
81 | ],
82 | ),
83 | );
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/lib/page/demo/keyboard_demo_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutterjdshop/utils/utils.dart';
3 | import 'package:flutterjdshop/widget/view/keyboard_detector.dart';
4 |
5 | ///键盘相关Demo
6 | ///键盘是否弹起等
7 | class KeyBoardDemoPage extends StatefulWidget {
8 | @override
9 | _KeyBoardDemoPageState createState() => _KeyBoardDemoPageState();
10 | }
11 |
12 | class _KeyBoardDemoPageState extends State {
13 | bool isKeyboardShowing = false;
14 |
15 | final FocusNode _focusNode = new FocusNode();
16 |
17 | @override
18 | Widget build(BuildContext context) {
19 | ///必须嵌套在外层
20 | return KeyboardDetector(
21 | Scaffold(
22 | appBar: AppBar(
23 | title: new Text("KeyBoardDemoPage"),
24 | ),
25 | body: new GestureDetector(
26 | ///透明可以触摸
27 | behavior: HitTestBehavior.translucent,
28 | onTap: () {
29 | /// 触摸收起键盘
30 | hideKeyword2(context);
31 | },
32 | child: Container(
33 | child: Column(
34 | mainAxisSize: MainAxisSize.max,
35 | crossAxisAlignment: CrossAxisAlignment.center,
36 | children: [
37 | new Expanded(
38 | child: new Container(
39 | alignment: Alignment.center,
40 | child: Text(
41 | isKeyboardShowing ? "键盘弹起" : "键盘未弹起",
42 | style: TextStyle(
43 | color: isKeyboardShowing
44 | ? Colors.redAccent
45 | : Colors.greenAccent),
46 | ),
47 | ),
48 | flex: 2,
49 | ),
50 | new Expanded(
51 | child: new Center(
52 | child: new TextButton(
53 | onPressed: () {
54 | if (!isKeyboardShowing) {
55 | /// 触摸收起键盘
56 | FocusScope.of(context).unfocus();
57 | }
58 | },
59 | child: new Text("弹出键盘"),
60 | ),
61 | ),
62 | ),
63 | new Expanded(
64 | flex: 2,
65 | child: new Container(
66 | margin: EdgeInsets.symmetric(horizontal: 10),
67 | child: new TextField(
68 | focusNode: _focusNode,
69 | ),
70 | ),
71 | )
72 | ],
73 | ),
74 | ),
75 | ),
76 | ),
77 | keyboardShowCallback: (isKeyboardShowing) {
78 | ///当前键盘是否可见
79 | setState(() {
80 | this.isKeyboardShowing = isKeyboardShowing;
81 | });
82 | },
83 |
84 | );
85 | }
86 | }
--------------------------------------------------------------------------------
/lib/page/demo/my_custompainter.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/painting.dart';
3 |
4 | class MyCustomPainter extends CustomPainter {
5 | ///Canvas:一个画布,包括各种绘制方法
6 | ///|drawLine | 画线 | 实线 虚线
7 | ///| drawPoint | 画点 |
8 | ///| drawPath | 画路径 |
9 | ///| drawImage | 画图像 |
10 | ///| drawRect | 画矩形 |
11 | ///| drawCircle | 画圆 |
12 | ///| drawOval | 画椭圆 |
13 | /// | drawArc | 画圆弧 |
14 | ///Size:当前绘制区域大小
15 |
16 | Paint paint2 = Paint();
17 |
18 | @override
19 | void paint(Canvas canvas, Size size) {
20 | // TODO: implement paint
21 |
22 | double gap = size.width / 15;
23 | //设置画笔颜色
24 | paint2
25 | ..isAntiAlias = true
26 | ..style = PaintingStyle.fill
27 | ..color = Colors.red;
28 | ///画背景
29 | ///也可以用drawColor
30 | canvas.drawRect(Offset.zero & size, paint2);
31 |
32 | paint2
33 | ..color = Colors.black87
34 | ..style = PaintingStyle.stroke
35 | ..strokeWidth = 1;
36 |
37 | for (int i = 0; i < 15; i++) {
38 | var dy = gap * i;
39 | canvas.drawLine(Offset(0, dy), Offset(size.width, dy), paint2);
40 | }
41 |
42 | for (int i = 0; i < 15; i++) {
43 | var dx = gap * i;
44 | canvas.drawLine(Offset(dx, 0), Offset(dx, size.width), paint2);
45 | }
46 |
47 | paint2
48 | ..style = PaintingStyle.fill
49 | ..color = Colors.black;
50 | canvas.drawCircle(
51 | Offset(size.width / 2 + gap / 2, size.width / 2 + gap / 2),
52 | gap / 2,
53 | paint2);
54 |
55 | paint2
56 | ..style = PaintingStyle.fill
57 | ..color = Colors.white;
58 | canvas.drawCircle(
59 | Offset(size.width / 2 - gap / 2, size.width / 2 - gap / 2),
60 | gap / 2,
61 | paint2);
62 |
63 | }
64 |
65 | ///尽可能的利用好shouldRepaint返回值;在UI树重新build时,
66 | ///控件在绘制前都会先调用该方法以确定是否有必要重绘;
67 | ///假如我们绘制的UI不依赖外部状态,那么就应该始终返回false,
68 | ///因为外部状态改变导致重新build时不会影响我们的UI外观;
69 | ///如果绘制依赖外部状态,那么我们就应该在shouldRepaint中判断依赖的状态是否改变,如果已改变则应返回true来重绘,反之则应返回false不需要重绘。
70 | ///返回false不会重绘,返回true就会重绘,可以根据外部状态来处理返回值
71 | ///如果不变的Widget就单独抽出来一个Widget返回false
72 | @override
73 | bool shouldRepaint(CustomPainter oldDelegate) {
74 | // TODO: implement shouldRepaint
75 | return false;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/lib/page/demo/path_custompainter.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter/painting.dart';
5 | import 'package:flutterjdshop/common/common.dart';
6 |
7 | class PathPainterStudy extends CustomPainter {
8 | Paint paint2 = Paint();
9 | Path path = Path();
10 | Path path2 = Path();
11 | Path path3 = Path();
12 |
13 | @override
14 | void paint(Canvas canvas, Size size) {
15 | // TODO: implement paint
16 |
17 | paint2
18 | ..style = PaintingStyle.stroke
19 | ..isAntiAlias = true
20 | ..color = Colors.red;
21 |
22 | ///addXXX() - 添加子图形
23 | ///XXXTo() - 画线(直线或曲线)
24 | path.addArc(new Rect.fromLTWH(50, 50, 50, 50), 135.0 * (PI / DEGREE), 225.0 * (PI / DEGREE));
25 | path.addArc(new Rect.fromLTWH(100, 50, 50, 50), 180.0 * (PI / DEGREE), 225.0 * (PI / DEGREE));
26 | path.lineTo(100, 140);
27 | path.lineTo(58, 93);
28 |
29 | canvas.drawPath(path, paint2);
30 |
31 | paint2 ..color = Colors.blue..strokeWidth= 10;
32 |
33 | path2.moveTo(100, 100);
34 | path2.relativeLineTo(30,20);
35 |
36 | path2.moveTo(0, 100);
37 | ///x1 y1 是控制点位置 x2 y2 结束点位置
38 | path2.quadraticBezierTo(100, 50, 200, 100);
39 | ///forceMoveTo true抬起笔(moveTo),false不抬起笔
40 | path2.arcTo(Rect.fromLTWH(220, 110, 50, 50), 0* (PI / DEGREE), 90* (PI / DEGREE), true);
41 |
42 | path2.arcTo(Rect.fromLTWH(100, 150, 50, 50), 0* (PI / DEGREE), 90* (PI / DEGREE), false);
43 | path2.close();
44 | canvas.drawPath(path2, paint2);
45 |
46 | List points = List.empty();
47 | points.add(new Offset(100, 50)); // 画出控制点位置,方便理解
48 | canvas.drawPoints(PointMode.points, points, paint2);
49 | ///画弧线 - arcTo(Rect rect, double startAngle, double sweepAngle, bool forceMoveTo)
50 |
51 | }
52 |
53 | ///尽可能的利用好shouldRepaint返回值;在UI树重新build时,
54 | ///控件在绘制前都会先调用该方法以确定是否有必要重绘;
55 | ///假如我们绘制的UI不依赖外部状态,那么就应该始终返回false,
56 | ///因为外部状态改变导致重新build时不会影响我们的UI外观;
57 | ///如果绘制依赖外部状态,那么我们就应该在shouldRepaint中判断依赖的状态是否改变,如果已改变则应返回true来重绘,反之则应返回false不需要重绘。
58 | ///返回false不会重绘,返回true就会重绘,可以根据外部状态来处理返回值
59 | ///如果不变的Widget就单独抽出来一个Widget返回false
60 | @override
61 | bool shouldRepaint(CustomPainter oldDelegate) {
62 | // TODO: implement shouldRepaint
63 | return false;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/lib/page/demo/path_study.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutterjdshop/base/base_page_state.dart';
3 | import 'package:flutterjdshop/page/demo/my_custompainter.dart';
4 | import 'package:flutterjdshop/view/app_topbar.dart';
5 |
6 | import 'my_custompainter2.dart';
7 | import 'path_custompainter.dart';
8 |
9 | class PathStudy extends StatefulWidget {
10 | @override
11 | _PathStudyState createState() => _PathStudyState();
12 | }
13 |
14 | class _PathStudyState extends BasePageState {
15 | @override
16 | Widget getAppBar(BuildContext context) {
17 | // TODO: implement getAppBar
18 | return CommonBackTopBar(title: "Path学习");
19 | }
20 |
21 | @override
22 | Widget getBody(BuildContext context) {
23 | // TODO: implement getBody
24 | return Container(
25 | child: Column(
26 | children: [
27 | RepaintBoundary(
28 | child: CustomPaint(
29 | size: Size(300, 300),
30 | painter: PathPainterStudy(),
31 | ),
32 | ),
33 | ],
34 | ),
35 | );
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lib/page/demo/share_data_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/foundation.dart';
3 | import 'package:flutter/material.dart';
4 |
5 | class ShareDataWidget extends InheritedWidget {
6 | ShareDataWidget({required this.data, required Widget child})
7 | : super(child: child);
8 |
9 | final int data; //需要在子树中共享的数据,保存点击次数
10 |
11 | //定义一个便捷方法,方便子树中的widget获取共享数据
12 | static ShareDataWidget? of(BuildContext context) {
13 | return context.dependOnInheritedWidgetOfExactType();
14 | }
15 |
16 | //该回调决定当data发生变化时,是否通知子树中依赖data的Widget
17 | @override
18 | bool updateShouldNotify(ShareDataWidget old) {
19 | //如果返回true,则子树中依赖(build函数中有调用)本widget
20 | //的子widget的`state.didChangeDependencies`会被调用
21 | return old.data != data;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lib/page/demo/sliver_tabs/page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'page_state.dart';
4 |
5 |
6 |
7 |
8 | class Tab1Page extends StatefulWidget {
9 | final TabName tabName;
10 |
11 | const Tab1Page(this.tabName, {Key? key}) : super(key: key);
12 |
13 | @override
14 | _Tab1PageState createState() => _Tab1PageState();
15 | }
16 |
17 | class _Tab1PageState extends State {
18 | @override
19 | Widget build(BuildContext context) {
20 | return ListView.builder(
21 | key: PageStorageKey(widget.tabName.toString()),
22 | itemBuilder: (context, index) {
23 | return ListTile(
24 | title: Text(index.toString()),
25 | );
26 | },
27 | itemCount: 100,
28 | );
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lib/page/demo/sliver_tabs/page2.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 |
4 | import 'page.dart';
5 | import 'page_state.dart';
6 |
7 |
8 | class DemoPage extends StatefulWidget {
9 | @override
10 | _DemoPageState createState() => _DemoPageState();
11 | }
12 |
13 | class _DemoPageState extends PageState {
14 | @override
15 | Widget build(BuildContext context) {
16 | return Scaffold(
17 | appBar: AppBar(title: Text('TabsDemo')),
18 | body: NestedScrollView(
19 | headerSliverBuilder: (context, bool) {
20 | return [
21 | SliverPersistentHeader(
22 | pinned: true,
23 | delegate: MyStickyTabBarDelegate(
24 | child: PreferredSize(
25 | preferredSize: Size.fromHeight(44),
26 | child: Material(
27 | child: TabBar(
28 | labelStyle: TextStyle(fontSize: 14),
29 | labelColor: Color(0xff000000),
30 | unselectedLabelColor: Color(0xff999999),
31 | controller: tabController,
32 | tabs: [
33 | Tab(text: '出品方'),
34 | Tab(text: '拍品'),
35 | Tab(text: '拍場'),
36 | Tab(text: '展覽'),
37 | ],
38 | ),
39 | ),
40 | ),
41 | ),
42 | )
43 | ];
44 | },
45 | body: TabBarView(
46 | controller: tabController,
47 | children: [
48 | Container(child: Tab1Page(TabName.TAB1)),
49 | Container(child: Tab1Page(TabName.TAB2)),
50 | Container(child: Tab1Page(TabName.TAB3)),
51 | Container(child: Tab1Page(TabName.TAB4)),
52 | ],
53 | ),
54 | ),
55 | );
56 | }
57 | }
58 |
59 | /// 吸顶tabs
60 | class MyStickyTabBarDelegate extends SliverPersistentHeaderDelegate {
61 | final PreferredSize child;
62 |
63 | MyStickyTabBarDelegate({required this.child});
64 |
65 | @override
66 | Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
67 | return this.child;
68 | }
69 |
70 | @override
71 | double get maxExtent => this.child.preferredSize.height;
72 |
73 | @override
74 | double get minExtent => this.child.preferredSize.height;
75 |
76 | @override
77 | bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
78 | return true;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/lib/page/demo/sliver_tabs/page_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'page2.dart';
4 |
5 |
6 |
7 | /// 关注页签名称
8 | enum TabName {
9 | TAB1,
10 | TAB2,
11 | TAB3,
12 | TAB4,
13 | }
14 |
15 | abstract class PageState extends State with SingleTickerProviderStateMixin {
16 | TabController? tabController;
17 |
18 | /// 切换页签
19 | VoidCallback? _toggleTabListener() {
20 | if (!tabController!.indexIsChanging) {
21 | toggleTab(tabController!.index);
22 | }
23 | return null;
24 | }
25 |
26 | @override
27 | void initState() {
28 | super.initState();
29 | tabController = TabController(length: 4, vsync: this);
30 | tabController!.addListener(_toggleTabListener);
31 | }
32 |
33 | @override
34 | void dispose() {
35 | tabController!.removeListener(_toggleTabListener);
36 | tabController!.dispose();
37 | super.dispose();
38 | }
39 |
40 | toggleTab(tabIndex) {
41 | print(tabIndex);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/page/demo/study.dart:
--------------------------------------------------------------------------------
1 | //dart学习
2 | import 'dart:async';
3 |
4 | import 'package:flutter/cupertino.dart';
5 |
6 | Future getId() async{
7 | return 5;
8 | }
9 |
10 |
11 | Stream getNumbers() async*{
12 | while(true){
13 | await Future.delayed(Duration(seconds: 1));
14 | yield DateTime.now();
15 | }
16 | }
17 |
18 |
19 |
20 | RoundedRectangleBorder getRo(){
21 | return RoundedRectangleBorder();
22 | }
23 |
24 | //shrinkWrap 有些控件默认填充父组件,该属性可以让组件包含而不是填充 例如gridView
25 | //XXXBuilder 数据变化的时候会调用builder 所以不需要setState 避免在builder里面改变变量
26 | //调用最小的范围的的setState
27 |
28 | //组件默认大小 Stack 当没有位置组件的时候,大小会和子组件最大的一样
29 | //如果都是有位置的组件的时候,会越大越好
30 | //如果有有位置的和没有位置的组件的话,大小会和没有位置最大组件一样大,没有位置的最大组件可以作为参照物,
31 | //有位置的组件 Align Positioned Center 其他都是没有位置的默认左上角,位置组件的约束是松约束
32 | //先布局没有位置的组件(作为参照物),再布局有位置的组件,有位置的组件不会大于没有位置的组件,要不然没有任何意义
33 |
34 | //没有位置的组件会听alignment的话
35 | //clipBehavior 设置是否裁剪,Positioned 位置的值可以为负值
36 |
37 |
38 | //StackFit
39 | //loose 0-max
40 | //expand max
41 | //passthrough 直接把上一级的约束传给子组件
42 |
43 |
44 |
45 |
46 | //需要渲染的组件,一些不需要渲染的组件
47 | //StreamController.broadcast() 不能缓存事件,可以被多个监听,
48 | //StreamController可以缓存事件,只能被一个监听
49 | //StreamController 添加事件 stream 监听事件
50 |
51 | //显式动画 手动创建Controller XXXBuilder TweenAnimationBuilder
52 | //隐式动画 系统自动创建了Controller 不用自己创建 AnimatedXXX AnimatedSwitcher
53 | //json文件动画
54 |
55 | //start 从头开始,forward 从当前到末尾 repeat 循环播放动画 reverse 是否反向动画
56 | //duration 可以随时修改
57 |
58 | //SizedBox 可以强制设置宽高
59 |
60 | //组件向里面传递约束,向外面传递尺寸,无法约束的大小,因为没有告诉放在那个位置,
61 | // 加一个位置组件就可以满足设置的大小了
62 |
63 | //紧约束,最小值和最大值一样`
64 | //松约束loose 最小值是0的约束
65 | //LayoutBuilder可以查看约束
66 | //弹性和非弹性 先布局非弹性的,然后把剩余的空间分给有弹性的
67 |
68 | //有限和无限约束 无界约束中不能包含无界约束的组件
69 | // 例如 Column里面直接包含listView 由于listView 是非弹性组件并且是无限约束,
70 | // 所以会失败,需要被弹性组件包含以下就可以了
71 |
72 |
73 |
74 | //如果组件只设置了大小,没有位置就按照max,如果设置了位置和大小就正常显示
75 |
76 |
77 | //ParentDataWidget 给父类传递信息的组件,如果没有信息,直接忽略掉,例如Posit
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/lib/page/demo/study_repaintboundary.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutterjdshop/page/demo/boundary.dart';
3 |
4 | class StudyBoundary extends StatefulWidget {
5 | @override
6 | _StudyBoundaryState createState() => _StudyBoundaryState();
7 | }
8 |
9 | class _StudyBoundaryState extends State {
10 | String _buttonText = 'test';
11 | int _index = 0;
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | return Scaffold(
16 | appBar: AppBar(
17 | title: Text("ddddd"),
18 | ),
19 | body: Container(
20 | child: CustomMultiChildLayout(
21 | delegate: LayoutBoundaryDelegate(),
22 | children: [
23 | LayoutId(
24 | id: LayoutBoundaryDelegate.title,
25 | child: Row(children: [
26 | Expanded(
27 | child: Container(
28 | height: 50.0, // add for test relayoutBoundary
29 | child: LayoutBoundary(),
30 | )),
31 | Expanded(
32 | child: Text(
33 | 'You have pushed the button this many times:'))
34 | ])),
35 | LayoutId(
36 | id: LayoutBoundaryDelegate.summary,
37 | child: Container(
38 | width: 200.0, // add for test relayoutBoundary
39 | height: 50.0, // add for test relayoutBoundary
40 | child: InkWell(
41 | child: Text(
42 | _buttonText,
43 | style: Theme.of(context).textTheme.displayLarge,
44 | ),
45 | onTap: () {
46 | setState(() {
47 | _index++;
48 | _buttonText = 'onTap$_index';
49 | });
50 | },
51 | ),
52 | )),
53 | LayoutId(
54 | id: LayoutBoundaryDelegate.paintBoundary,
55 | child: Container(
56 | width: 50.0,
57 | height: 50.0,
58 | child: RepaintBoundary(
59 | // add for test repaintBoundary
60 | child: PaintBoundary(),
61 | ),
62 | )),
63 | ]),
64 | ));
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/lib/page/guide_page.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 |
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter_slidable/flutter_slidable.dart';
6 |
7 | // import 'package:flutter_swiper/flutter_swiper.dart';
8 | import 'package:rxdart/rxdart.dart';
9 | import 'package:flutterjdshop/common/shared_util.dart';
10 | import 'package:flutterjdshop/config/const.dart';
11 | import 'package:flutterjdshop/routes/fluro_navigator.dart';
12 | import 'package:flutterjdshop/utils/image_utils.dart';
13 | import 'package:flutterjdshop/utils/theme_utils.dart';
14 | import 'package:flutterjdshop/widget/load_image.dart';
15 |
16 | class GuidePage extends StatefulWidget {
17 | @override
18 | _GuidePageState createState() => _GuidePageState();
19 | }
20 |
21 | class _GuidePageState extends State {
22 | int _status = 0;
23 | List _guideList = ['app_start_1', 'app_start_2', 'app_start_3'];
24 | StreamSubscription? _subscription;
25 |
26 | @override
27 | void initState() {
28 | super.initState();
29 | WidgetsBinding.instance!.addPostFrameCallback((_) async {
30 | // 由于SpUtil未初始化,所以MaterialApp获取的为默认主题配置,这里同步一下。
31 | if (SharedUtil.instance!.getBoolean(Keys.keyGuide, defValue: true)) {
32 | /// 预先缓存图片,避免直接使用时因为首次加载造成闪动
33 | _guideList.forEach((image) {
34 | precacheImage(ImageUtils.getAssetImage(image), context);
35 | });
36 | }
37 | _initSplash();
38 | });
39 | }
40 |
41 | @override
42 | void dispose() {
43 | _subscription?.cancel();
44 | super.dispose();
45 | }
46 |
47 | void _initGuide() {
48 | setState(() {
49 | _status = 1;
50 | });
51 | }
52 |
53 | void _initSplash() {
54 | Future.delayed(Duration(milliseconds: 1500),(){
55 | SharedUtil.instance!.saveBoolean(Keys.keyGuide, false);
56 | // _initGuide();
57 | _goLogin();
58 | });
59 | }
60 |
61 | _goLogin() {
62 | NavigatorUtils.goRootPage(context);
63 | }
64 |
65 | @override
66 | Widget build(BuildContext context) {
67 | return Material(
68 | color: ThemeUtils.getBackgroundColor(context),
69 | child: _status == 0
70 | ? Align(
71 | alignment: FractionalOffset(
72 | 0.33 / (1.0 - 0.33),
73 | 0.3/(1-0.3)
74 | ),
75 | child: FractionallySizedBox (
76 | heightFactor: 0.3,
77 | widthFactor: 0.33,
78 | child: const LoadAssetImage('banner',format: IMAGE_JPG,)),
79 | )
80 | : Container(child: Text("替换"),alignment: Alignment.center,),);
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/lib/page/home/productdetail/CartNum.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/widgets.dart';
3 | import 'package:flutterjdshop/api/model/ProductContentModel.dart';
4 | import 'package:flutterjdshop/utils/app_size.dart';
5 |
6 |
7 | class CartNum extends StatefulWidget {
8 | ProductContentitem? _productContent;
9 |
10 | CartNum(this._productContent,{Key? key}) : super(key: key);
11 |
12 | _CartNumState createState() => _CartNumState();
13 | }
14 |
15 | class _CartNumState extends State {
16 | ProductContentitem? _productContent;
17 | @override
18 | void initState() {
19 | // TODO: implement initState
20 | super.initState();
21 | this._productContent=widget._productContent;
22 | }
23 |
24 | @override
25 | Widget build(BuildContext context) {
26 | return Container(
27 | width: AppSize.width(168),
28 | decoration:
29 | BoxDecoration(border: Border.all(width: AppSize.width(2), color: Colors.black12)),
30 | child: Row(
31 | children: [
32 | _leftBtn(),
33 | _centerArea(),
34 | _rightBtn()
35 | ],
36 | ),
37 | );
38 | }
39 |
40 | //左侧按钮
41 |
42 | Widget _leftBtn() {
43 | return InkWell(
44 | onTap: () {
45 | if( this._productContent!.count!>1){
46 | setState(() {
47 | this._productContent!.count=this._productContent!.count!-1;
48 | });
49 | }
50 | },
51 | child: Container(
52 | alignment: Alignment.center,
53 | width: AppSize.width(45),
54 | height: AppSize.height(45),
55 | child: Text("-"),
56 | ),
57 | );
58 | }
59 |
60 | //右侧按钮
61 | Widget _rightBtn() {
62 | return InkWell(
63 | onTap: (){
64 |
65 | setState(() {
66 | this._productContent!.count=this._productContent!.count!+1;
67 | });
68 | },
69 | child: Container(
70 | alignment: Alignment.center,
71 | width: AppSize.width(45),
72 | height: AppSize.height(45),
73 | child: Text("+"),
74 | ),
75 | );
76 | }
77 |
78 | //中间
79 | Widget _centerArea() {
80 | return Container(
81 | alignment: Alignment.center,
82 | width: AppSize.width(70),
83 | decoration: BoxDecoration(
84 | border: Border(
85 | left: BorderSide(width: AppSize.width(2), color: Colors.black12),
86 | right: BorderSide(width: AppSize.width(2), color: Colors.black12),
87 | )),
88 | height: AppSize.height(45),
89 | child: Text("${this._productContent!.count}"),
90 | );
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/lib/page/home/productdetail/ProductContent.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class ProductContent extends StatefulWidget {
4 | final String title;
5 | final int index;
6 |
7 | ProductContent(this.title, this.index, {Key? key}) : super(key: key);
8 |
9 | _ProductContentState createState() => _ProductContentState();
10 | }
11 |
12 | class _ProductContentState extends State
13 | with AutomaticKeepAliveClientMixin {
14 |
15 | bool get wantKeepAlive => true;
16 | PageStorageKey? pKey;
17 | @override
18 | void initState() {
19 | // TODO: implement initState
20 | super.initState();
21 | pKey = PageStorageKey(widget.title);
22 | }
23 |
24 | @override
25 | Widget build(BuildContext context) {
26 | super.build(context);
27 | return Builder(
28 | builder: (context) {
29 | return CustomScrollView(
30 | key: pKey,
31 | slivers: [
32 | SliverOverlapInjector(
33 | handle:
34 | NestedScrollView.sliverOverlapAbsorberHandleFor(context)),
35 | SliverFixedExtentList(
36 | delegate: SliverChildBuilderDelegate(
37 | (_, index) => Container(
38 | child: Text(
39 | '${widget.title} ${widget.index}- ProductContent-item${index + 1}',
40 | style:
41 | TextStyle(fontSize: 20.0, color: Colors.red)),
42 | alignment: Alignment.center),
43 | childCount: 15),
44 | itemExtent: 80.0)
45 | ]);
46 | },
47 | );
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/lib/page/home/productdetail/ProductContentSecond.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutterjdshop/widget/my_iframe/my_iframe.dart';
3 |
4 | class ProductContentSecond extends StatefulWidget {
5 | final List _productContentList;
6 |
7 | ProductContentSecond(this._productContentList, {Key? key}) : super(key: key);
8 |
9 | _ProductContentSecondState createState() => _ProductContentSecondState();
10 | }
11 |
12 | class _ProductContentSecondState extends State
13 | with AutomaticKeepAliveClientMixin {
14 | var _id;
15 |
16 | bool get wantKeepAlive => true;
17 |
18 | @override
19 | void initState() {
20 | // TODO: implement initState
21 | super.initState();
22 | this._id = widget._productContentList[0].sId;
23 | }
24 |
25 | @override
26 | Widget build(BuildContext context) {
27 | return Container(
28 | child: Column(
29 | children: [
30 | Expanded(
31 | child: MyIFrame(
32 | "http://jd.itying.com/pcontent?id=${this._id}",
33 | ),
34 | )
35 | ],
36 | ),
37 | );
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/lib/page/home/productdetail/ProductContentThird.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class ProductContentThird extends StatefulWidget {
4 | ProductContentThird({Key? key}) : super(key: key);
5 |
6 | _ProductContentThirdState createState() => _ProductContentThirdState();
7 | }
8 |
9 | class _ProductContentThirdState extends State with AutomaticKeepAliveClientMixin{
10 |
11 | bool get wantKeepAlive => true;
12 | @override
13 | Widget build(BuildContext context) {
14 | return Container(
15 | child: ListView.builder(
16 | itemCount: 50,
17 | itemBuilder: (context,index){
18 | return ListTile(
19 | title: Text("第${index}条"),
20 | );
21 |
22 | },
23 | )
24 | );
25 | }
26 | }
--------------------------------------------------------------------------------
/lib/page/root/root_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutterjdshop/page/cart/cart_page.dart';
4 | import 'package:flutterjdshop/page/category/category_page.dart';
5 | import 'package:flutterjdshop/page/home/home_page.dart';
6 | import 'package:flutterjdshop/page/user/user_page.dart';
7 | import 'package:flutterjdshop/utils/app_size.dart';
8 | import 'package:flutterjdshop/utils/double_tap_back_exit_app.dart';
9 | import 'package:flutterjdshop/widget/root_tabbar.dart';
10 |
11 |
12 |
13 | class RootPage extends StatefulWidget {
14 | @override
15 | _RootPageState createState() => _RootPageState();
16 | }
17 |
18 | class _RootPageState extends State {
19 | DateTime? lastPopTime;
20 |
21 | @override
22 | void initState() {
23 | super.initState();
24 | checkVersion();
25 | }
26 |
27 | /// 检查更新 [check update]
28 | checkVersion() async {
29 | // if (Platform.isIOS) return;
30 | //
31 | // final packageInfo = await PackageInfo.fromPlatform();
32 | //
33 | // VersionModel model = await versionViewModel.getData();
34 | //
35 | // int currentVersion = int.parse(removeDot(packageInfo.version));
36 | //
37 | // int netVersion = int.parse(removeDot(model.appVersion));
38 | //
39 | // if (currentVersion >= netVersion) {
40 | // debugPrint('当前版本是最新版本');
41 | // return;
42 | // }
43 | //
44 | // showDialog(
45 | // context: context,
46 | // builder: (ctx2) {
47 | // return UpdateDialog(
48 | // version: model.appVersion,
49 | // updateUrl: model.downloadUrl,
50 | // updateInfo: model.updateInfo,
51 | // isForce: model.force,
52 | // );
53 | // },
54 | // );
55 | }
56 |
57 | @override
58 | Widget build(BuildContext context) {
59 | AppSize.init(context);
60 | List pages = [
61 | new TabBarModel(
62 | title: '首页',
63 | icon: Icon(Icons.home),
64 | page: HomePage(),
65 | ),
66 | new TabBarModel(
67 | title: '分类',
68 | icon: Icon(Icons.search),
69 | page: CategoryPage(),
70 | ),
71 | new TabBarModel(
72 | title: '购物车',
73 | icon: Icon(Icons.shopping_cart),
74 | page: CartPage(),
75 | ),
76 | new TabBarModel(
77 | title: '我的',
78 | icon: Icon(Icons.people),
79 | page: UserPage(),
80 | ),
81 | ];
82 | return DoubleTapBackExitApp(
83 | child: RootTabBar(pages: pages, currentIndex: 0),
84 | );
85 | return new RootTabBar(pages: pages, currentIndex: 0);
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/lib/page/splash_page.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:rxdart/rxdart.dart';
6 | import 'package:flutterjdshop/common/shared_util.dart';
7 | import 'package:flutterjdshop/config/keys.dart';
8 | import 'package:flutterjdshop/routes/fluro_navigator.dart';
9 | import 'package:flutterjdshop/routes/shop_router.dart';
10 | import 'package:flutterjdshop/utils/image_utils.dart';
11 | import 'package:flutterjdshop/widget/load_image.dart';
12 |
13 | class SplashPage extends StatefulWidget {
14 | SplashPage({Key? key, this.title}) : super(key: key);
15 |
16 | final String? title;
17 |
18 |
19 | @override
20 | State createState() {
21 | return _SplashPageState();
22 | }
23 | }
24 |
25 | class _SplashPageState extends State {
26 | @override
27 | void initState() {
28 | // TODO: do something to init
29 | super.initState();
30 | WidgetsBinding.instance!.addPostFrameCallback((_) async {
31 | precacheImage(ImageUtils.getAssetImage('app_start_1'), context);
32 | goHome();
33 | });
34 | }
35 |
36 | goHome() {
37 | Future.delayed(Duration(milliseconds: 3000),(){
38 | if (SharedUtil.instance!.getBoolean(Keys.keyGuide, defValue: true)) {
39 | NavigatorUtils.push(context, ShopRouter.GUIDE_PAGE, replace: true);
40 | } else {
41 | NavigatorUtils.goRootPage(context);
42 | }});
43 | }
44 | @override
45 | Widget build(BuildContext context) {
46 | return Builder(builder: (context) {
47 | return Container(
48 | child: LoadAssetImage(
49 | 'app_start_1',
50 | fit: BoxFit.fill,
51 | ),
52 | );
53 | });
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/lib/page/user/loginregister/register_first.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutterjdshop/api/model/void_modle.dart';
3 | import 'package:flutterjdshop/api/model/void_view_model.dart';
4 | import 'package:flutterjdshop/base/base_page_state.dart';
5 | import 'package:flutterjdshop/res/gaps.dart';
6 | import 'package:flutterjdshop/routes/fluro_navigator.dart';
7 | import 'package:flutterjdshop/routes/my_navigator_observer.dart';
8 | import 'package:flutterjdshop/routes/routers.dart';
9 | import 'package:flutterjdshop/routes/shop_router.dart';
10 | import 'package:flutterjdshop/utils/app_size.dart';
11 | import 'package:flutterjdshop/utils/log_utils.dart';
12 | import 'package:flutterjdshop/view/app_topbar.dart';
13 | import 'package:flutterjdshop/widget/view/my_button.dart';
14 | import 'package:flutterjdshop/widget/view/text_field.dart';
15 | import 'package:rxdart/rxdart.dart';
16 |
17 | class RegisterFirst extends StatefulWidget {
18 | @override
19 | _RegisterFirstState createState() => _RegisterFirstState();
20 | }
21 |
22 | class _RegisterFirstState extends BasePageState {
23 | TextEditingController phoneController = TextEditingController();
24 | final FocusNode _nodeText1 = FocusNode();
25 |
26 | @override
27 | Widget getBody(BuildContext context) {
28 | // TODO: implement getBody
29 | return Container(
30 | padding: EdgeInsets.all(AppSize.width(20)),
31 | child: ListView(
32 | children: [
33 | Gaps.vGap50,
34 | MyTextField(
35 | key: Key("phone"),
36 | controller: phoneController,
37 | keyboardType: TextInputType.phone,
38 | maxLength: 11,
39 | focusNode: _nodeText1,
40 | hintText: "请输入手机号",
41 | ),
42 | MyButton(
43 | text: "下一步",
44 | onPressed: () {
45 | var phone = phoneController.text;
46 | if (phone.isNotEmpty && phone.length == 11) {
47 | VoidViewModel.get(this, getCancelToken()).getData(
48 | type: VoidModel.SEND_CODE,
49 | params2: {"tel": phone}).then((onValue) {
50 | NavigatorUtils.push(context, ShopRouter.REGISTER_SECOND,
51 | params: {"tel": phone});
52 | });
53 | } else {
54 | showToast("手机号格式不对");
55 | NavigatorUtils.removeRouteByName(context,ShopRouter.LOGIN);
56 | }
57 | },
58 | )
59 | ],
60 | ),
61 | );
62 | }
63 |
64 | @override
65 | Widget getAppBar(BuildContext context) {
66 | // TODO: implement getAppBar
67 | return CommonBackTopBar(
68 | title: "用户注册-第一步",
69 | );
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/lib/page/user/loginregister/register_second.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutterjdshop/api/model/void_modle.dart';
3 | import 'package:flutterjdshop/api/model/void_view_model.dart';
4 | import 'package:flutterjdshop/base/base_page_state.dart';
5 | import 'package:flutterjdshop/res/gaps.dart';
6 | import 'package:flutterjdshop/routes/fluro_navigator.dart';
7 | import 'package:flutterjdshop/routes/shop_router.dart';
8 | import 'package:flutterjdshop/utils/app_size.dart';
9 | import 'package:flutterjdshop/utils/dialog_utils.dart';
10 | import 'package:flutterjdshop/view/app_topbar.dart';
11 | import 'package:flutterjdshop/widget/view/my_button.dart';
12 | import 'package:flutterjdshop/widget/view/text_field.dart';
13 |
14 | class RegisterSecond extends StatefulWidget {
15 | String tel;
16 |
17 | RegisterSecond(this.tel);
18 |
19 | @override
20 | _RegisterSecondState createState() => _RegisterSecondState();
21 | }
22 |
23 | class _RegisterSecondState extends BasePageState {
24 | TextEditingController codeC = TextEditingController();
25 | FocusNode codeF = FocusNode();
26 |
27 | @override
28 | Widget getBody(BuildContext context) {
29 | // TODO: implement getBody
30 | return Container(
31 | padding: EdgeInsets.all(AppSize.width(20)),
32 | child: ListView(
33 | children: [
34 | Gaps.vGap10,
35 | Padding(
36 | padding: EdgeInsets.only(left: AppSize.width(10)),
37 | child: Text("验证码已经发送到了您的${widget.tel}手机,请输入${widget.tel}手机号收到的验证码"),
38 | ),
39 | Gaps.vGap10,
40 | MyTextField(
41 | key: Key("code"),
42 | controller: codeC,
43 | focusNode: codeF,
44 | hintText: "请输入验证码",
45 | maxLength: 4,
46 | keyboardType: TextInputType.number,
47 | getVCode: () async {
48 | // VoidViewModel.get(this, getCancelToken()).getData(
49 | // type: VoidModel.SEND_CODE,
50 | // params2: {"tel": widget.tel}).then((onValue) {
51 | // DialogUtil.buildToast("跳转了");
52 | // return true;
53 | // });
54 | return true;
55 | },
56 | ),
57 | Gaps.vGap10,
58 | MyButton(
59 | text: "下一步",
60 | onPressed: () {
61 | var code = codeC.text;
62 | if(code!=null&&code.length==4){
63 | NavigatorUtils.push(context, ShopRouter.REGISTER_THIRD,
64 | params: {"tel": widget.tel, "code": codeC.text});
65 | }else{
66 | showToast("验证码格式不对");
67 | }
68 | },
69 | )
70 | ],
71 | ),
72 | );
73 | }
74 |
75 | @override
76 | Widget getAppBar(BuildContext context) {
77 | // TODO: implement getAppBar
78 | return CommonBackTopBar(title: "用户注册-第二步");
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/lib/page/user/order/Pay.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutterjdshop/base/base_page_state.dart';
3 | import 'package:flutterjdshop/view/app_topbar.dart';
4 | import 'package:flutterjdshop/widget/view/my_button.dart';
5 |
6 |
7 | class PayPage extends StatefulWidget {
8 | PayPage({Key? key}) : super(key: key);
9 |
10 | _PayPageState createState() => _PayPageState();
11 | }
12 |
13 | class _PayPageState extends BasePageState {
14 | List payList = [
15 | {
16 | "title": "支付宝支付",
17 | "chekced": true,
18 | "image": "https://www.itying.com/themes/itying/images/alipay.png"
19 | },
20 | {
21 | "title": "微信支付",
22 | "chekced": false,
23 | "image": "https://www.itying.com/themes/itying/images/weixinpay.png"
24 | }
25 | ];
26 |
27 |
28 | @override
29 | Widget getAppBar(BuildContext context) {
30 | // TODO: implement getAppBar
31 | return CommonBackTopBar(title: "支付");
32 | }
33 | @override
34 | Widget getBody(BuildContext context) {
35 | // TODO: implement getBody
36 | return Column(
37 | children: [
38 | Container(
39 | height: 400,
40 | padding: EdgeInsets.all(20),
41 | child: ListView.builder(
42 | itemCount: this.payList.length,
43 | itemBuilder: (context, index) {
44 | return Column(
45 | children: [
46 | ListTile(
47 | leading:
48 | Image.network("${this.payList[index]["image"]}"),
49 | title: Text("${this.payList[index]["title"]}"),
50 | trailing: this.payList[index]["chekced"]
51 | ? Icon(Icons.check)
52 | : Text(""),
53 | onTap: () {
54 | //让payList里面的checked都等于false
55 | setState(() {
56 | for (var i = 0; i < this.payList.length; i++) {
57 | this.payList[i]['chekced'] = false;
58 | }
59 | this.payList[index]["chekced"] = true;
60 | });
61 | },
62 | ),
63 | Divider(),
64 | ],
65 | );
66 | },
67 | )),
68 | MyButton(
69 | margin: EdgeInsets.all(0),
70 | text: "支付",
71 | color: Colors.red,
72 | onPressed: () {
73 | print('支付1111');
74 | },
75 | )
76 | ],
77 | );
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/lib/page/web_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutterjdshop/utils/app_size.dart';
3 | import 'package:flutterjdshop/view/app_topbar.dart';
4 | import 'package:flutterjdshop/view/customize_appbar.dart';
5 | import 'package:flutterjdshop/widget/my_iframe/my_iframe.dart';
6 |
7 |
8 | class WebViewPage extends StatefulWidget {
9 | const WebViewPage({
10 | Key? key,
11 | required this.title,
12 | required this.url,
13 | }) : super(key: key);
14 |
15 | final String? title;
16 | final String? url;
17 |
18 | @override
19 | _WebViewState createState() => _WebViewState();
20 | }
21 |
22 | class _WebViewState extends State {
23 | bool _isLoading = true;
24 |
25 | @override
26 | void initState() {
27 | super.initState();
28 | }
29 |
30 | @override
31 | void dispose() {
32 | super.dispose();
33 | }
34 |
35 | @override
36 | Widget build(BuildContext context) {
37 | AppSize.init(context);
38 |
39 | return Scaffold(
40 | appBar: MyAppBar(
41 | preferredSize: Size.fromHeight(AppSize.height(160)),
42 | child:
43 | CommonBackTopBar(title: widget.title),
44 | ),
45 | body: Stack(
46 | children: [
47 | MyIFrame(
48 | widget.url!),
49 | _loading()
50 | ],
51 | ),
52 | );
53 | }
54 |
55 | _loading() {
56 | return _isLoading == true
57 | ? Container(
58 | decoration: BoxDecoration(color: Colors.white),
59 | child: Center(
60 | child: CircularProgressIndicator(),
61 | ),
62 | )
63 | : Text('');
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/lib/provider/CheckOut.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class CheckOut with ChangeNotifier {
4 | List _checkOutListData = []; //购物车数据
5 | List get checkOutListData => this._checkOutListData;
6 |
7 | changeCheckOutListData(data){
8 | this._checkOutListData=data;
9 | notifyListeners();
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/lib/provider/counter_provider.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class CounterProvider with ChangeNotifier {
4 | int _count = 0;
5 | int _count1 = 100;
6 |
7 | int get value => _count;
8 |
9 | int get value1 => _count1;
10 |
11 | void increment() {
12 | _count++;
13 | notifyListeners();
14 | }
15 |
16 | void increment1() {
17 | _count1++;
18 | notifyListeners();
19 | }
20 | }
--------------------------------------------------------------------------------
/lib/provider/order_page_provider.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class OrderPageProvider extends ChangeNotifier {
4 |
5 | /// Tab的下标
6 | int _index = 0;
7 | int get index => _index;
8 |
9 | void refresh() {
10 | notifyListeners();
11 | }
12 |
13 | void setIndex(int index) {
14 | _index = index;
15 | notifyListeners();
16 | }
17 |
18 | }
--------------------------------------------------------------------------------
/lib/provider/theme_provider.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 |
4 | import 'package:flutter/cupertino.dart';
5 | import 'package:flutter/material.dart';
6 | import 'package:flutterjdshop/common/common.dart';
7 | import 'package:flutterjdshop/config/keys.dart';
8 | import 'package:flutterjdshop/res/colors.dart';
9 | import 'package:flutterjdshop/res/styles.dart';
10 |
11 |
12 | class ThemeProvider extends ChangeNotifier {
13 |
14 | static const Map themes = {
15 | ThemeMode.dark: 'Dark', ThemeMode.light : 'Light', ThemeMode.system : 'System'
16 | };
17 |
18 | void syncTheme() {
19 | String theme = SharedUtil.instance!.getString(Keys.theme)!;
20 | if (theme.isNotEmpty && theme != themes[ThemeMode.system]) {
21 | notifyListeners();
22 | }
23 | }
24 |
25 | void setTheme(ThemeMode themeMode) {
26 | SharedUtil.instance!.saveString(Keys.theme, themes[themeMode]!);
27 | notifyListeners();
28 | }
29 |
30 | ThemeMode getThemeMode(){
31 | String? theme = SharedUtil.instance!.getString(Keys.theme);
32 | switch(theme) {
33 | case 'Dark':
34 | return ThemeMode.dark;
35 | case 'Light':
36 | return ThemeMode.light;
37 | default:
38 | return ThemeMode.system;
39 | }
40 | }
41 |
42 | getTheme({bool isDarkMode = false}) {
43 | return ThemeData(
44 | ///指定平台
45 | ///platform: TargetPlatform.android,
46 | errorColor: isDarkMode ? Colours.dark_red : Colours.red,
47 | brightness: isDarkMode ? Brightness.dark : Brightness.light,
48 | primaryColor: isDarkMode ? Colours.dark_app_main : Colours.app_main,
49 | // Tab指示器颜色
50 | indicatorColor: isDarkMode ? Colours.dark_app_main : Colours.app_main,
51 | // 页面背景色
52 | scaffoldBackgroundColor: isDarkMode ? Colours.dark_bg_color : Colors.white,
53 | // 主要用于Material背景色
54 | canvasColor: isDarkMode ? Colours.dark_material_bg : Colors.white,
55 | // 文字选择色(输入框复制粘贴菜单)
56 | textTheme: TextTheme(
57 | // TextField输入文字颜色
58 | // Text文字样式
59 | ),
60 | inputDecorationTheme: InputDecorationTheme(
61 | hintStyle: isDarkMode ? TextStyles.textHint14 : TextStyles.textDarkGray14,
62 | ),
63 | appBarTheme: AppBarTheme(
64 | elevation: 0.0,
65 | color: isDarkMode ? Colours.dark_bg_color : Colors.white,
66 | ),
67 | dividerTheme: DividerThemeData(
68 | color: isDarkMode ? Colours.dark_line : Colours.line,
69 | space: 0.6,
70 | thickness: 0.6
71 | ),
72 | cupertinoOverrideTheme: CupertinoThemeData(
73 | brightness: isDarkMode ? Brightness.dark : Brightness.light,
74 | )
75 | );
76 | }
77 |
78 | }
--------------------------------------------------------------------------------
/lib/provider/user_provider.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:flutter/material.dart';
3 | import 'package:flutterjdshop/config/user_info_data.dart';
4 |
5 |
6 | class UserProvider extends ChangeNotifier {
7 |
8 | UserInfoData? _user;
9 | UserInfoData? get user => _user;
10 |
11 | void setUser(UserInfoData user) {
12 | _user = user;
13 | notifyListeners();
14 | }
15 | }
--------------------------------------------------------------------------------
/lib/receiver/event_bus.dart:
--------------------------------------------------------------------------------
1 | import 'package:event_bus/event_bus.dart';
2 |
3 | //Bus初始化
4 | EventBus eventBus = EventBus();
5 |
6 | class RefreshAddressEvent {
7 | }
8 | class ProductContentEvent{
9 | }
10 | class MineChangeEvent{
11 | }
12 | class CheckOutEvent{
13 | }
14 | class OrderInEvent {
15 | String? text;
16 | OrderInEvent(String text){
17 | this.text = text;
18 | }
19 | }
20 | class UserInfoInEvent {
21 | String? text;
22 | UserInfoInEvent(String text){
23 | this.text = text;
24 | }
25 | }
26 | class SpecEvent{
27 | String? code;
28 | SpecEvent(String text){
29 | this.code=text;
30 | }
31 | }
32 |
33 | class TabIndexEvent{
34 | late int num;
35 | TabIndexEvent(int text){
36 | this.num=text;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/lib/res/colors.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class Colours {
4 | static const Color app_main = Colors.red;
5 | static const Color dark_app_main = Colors.red;
6 |
7 | static const Color bg_color = Color(0xfff1f1f1);
8 | static const Color dark_bg_color = Color(0xFF18191A);
9 |
10 | static const Color material_bg = Color(0xFFFFFFFF);
11 | static const Color dark_material_bg = Color(0xFF303233);
12 |
13 | static const Color text = Color(0xFF333333);
14 | static const Color dark_text = Color(0xFFB8B8B8);
15 |
16 | static const Color text_gray = Color(0xFF999999);
17 | static const Color dark_text_gray = Color(0xFF666666);
18 |
19 | static const Color text_gray_c = Color(0xFFcccccc);
20 | static const Color dark_button_text = Color(0xFFF2F2F2);
21 |
22 | static const Color bg_gray = Color(0xFFF6F6F6);
23 | static const Color dark_bg_gray = Color(0xFF1F1F1F);
24 |
25 | static const Color line = Color(0xFFEEEEEE);
26 | static const Color dark_line = Color(0xFF3A3C3D);
27 |
28 | static const Color red = Color(0xFFFF4759);
29 | static const Color dark_red = Color(0xFFE03E4E);
30 |
31 | static const Color text_disabled = Color(0xFFD4E2FA);
32 | static const Color dark_text_disabled = Color(0xFFCEDBF2);
33 |
34 | static const Color button_disabled = Color(0xFF96BBFA);
35 | static const Color dark_button_disabled = Color(0xFF83A5E0);
36 |
37 | static const Color unselected_item_color = Color(0xffbfbfbf);
38 | static const Color dark_unselected_item_color = Color(0xFF4D4D4D);
39 |
40 | static const Color bg_gray_ = Color(0xFFFAFAFA);
41 | static const Color dark_bg_gray_ = Color(0xFF242526);
42 |
43 | static const Color fixedColor = Colors.red;
44 |
45 |
46 |
47 | static const Color transparent_80 = Color(0x80000000); //
48 |
49 | static const Color text_dark = Color(0xFF333333);
50 | static const Color text_normal = Color(0xFF666666);
51 |
52 | static const Color divider = Color(0xffe5e5e5);
53 |
54 | static const Color gray_33 = Color(0xFF333333); //51
55 | static const Color gray_66 = Color(0xFF666666); //102
56 | static const Color gray_99 = Color(0xFF999999); //153
57 | static const Color common_orange = Color(0XFFFC9153); //252 145 83
58 | static const Color gray_ef = Color(0XFFEFEFEF); //153
59 |
60 | static const Color gray_f0 = Color(0xfff0f0f0); //
61 | static const Color white = Color(0xffffffff); //
62 | static const Color gray_f5 = Color(0xfff5f5f5); //
63 | static const Color gray_cc = Color(0xffcccccc); //
64 | static const Color gray_ce = Color(0xffcecece); //
65 | static const Color green_1 = Color(0xff2ed184); //
66 | static const Color green_62 = Color(0xff626262); //
67 | static const Color green_e5 = Color(0xffe5e5e5); //
68 | static const Color blue_1 = Color(0xff00C2FD); //
69 | static const Color lable_clour= Color(0xffff0000); //
70 |
71 | static const mainTextColor = Color.fromRGBO(115, 115, 115, 1.0);
72 |
73 | static const lineColor = Colors.grey;
74 |
75 |
76 |
77 | }
78 |
79 |
--------------------------------------------------------------------------------
/lib/res/colours.dart:
--------------------------------------------------------------------------------
1 |
2 | class Colours2 {
3 |
4 |
5 | }
--------------------------------------------------------------------------------
/lib/res/dimens.dart:
--------------------------------------------------------------------------------
1 | class Dimens {
2 | static const double font_sp10 = 10.0;
3 | static const double font_sp12 = 12.0;
4 | static const double font_sp14 = 14.0;
5 | static const double font_sp15 = 15.0;
6 | static const double font_sp16 = 16.0;
7 | static const double font_sp18 = 18.0;
8 | static const double font_sp24 = 24.0;
9 | static const double font_sp28 = 28.0;
10 |
11 | static const double dp_5 = 5;
12 | static const double dp_4 = 4;
13 | static const double dp_8 = 8;
14 | static const double dp_10 = 10;
15 | static const double dp_12 = 12;
16 | static const double dp_15 = 15;
17 | static const double dp_16 = 16;
18 | static const double dp_20 = 20;
19 | static const double dp_50 = 50;
20 | static const double dp_30 = 30;
21 | }
22 |
--------------------------------------------------------------------------------
/lib/res/gaps.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/widgets.dart';
3 | import 'package:flutterjdshop/utils/app_size.dart';
4 |
5 | import 'dimens.dart';
6 |
7 |
8 | /// 间隔
9 | class Gaps {
10 |
11 |
12 | static Widget getGaps(double number,{bool isHorizontal = true}){
13 | return isHorizontal?SizedBox(height:AppSize.height(number) ):SizedBox(width: AppSize.width(number));
14 | }
15 |
16 |
17 | /// 水平间隔
18 | static const Widget hGap4 = const SizedBox(width: Dimens.dp_4);
19 | static const Widget hGap5 = const SizedBox(width: Dimens.dp_5);
20 | static const Widget hGap8 = const SizedBox(width: Dimens.dp_8);
21 | static const Widget hGap10 = const SizedBox(width: Dimens.dp_10);
22 | static const Widget hGap12 = const SizedBox(width: Dimens.dp_12);
23 | static const Widget hGap15 = const SizedBox(width: Dimens.dp_15);
24 | static const Widget hGap16 = const SizedBox(width: Dimens.dp_16);
25 | static const Widget hGap30 = const SizedBox(width: Dimens.dp_30);
26 | static const Widget hGap20 = const SizedBox(width: Dimens.dp_20);
27 | static const Widget hGap50 = const SizedBox(width: Dimens.dp_50);
28 | /// 垂直间隔
29 | static const Widget vGap4 = const SizedBox(height: Dimens.dp_4);
30 | static const Widget vGap5 = const SizedBox(height: Dimens.dp_5);
31 | static const Widget vGap8 = const SizedBox(height: Dimens.dp_8);
32 | static const Widget vGap10 = const SizedBox(height: Dimens.dp_10);
33 | static const Widget vGap12 = const SizedBox(height: Dimens.dp_12);
34 | static const Widget vGap15 = const SizedBox(height: Dimens.dp_15);
35 | static const Widget vGap16 = const SizedBox(height: Dimens.dp_16);
36 | static const Widget vGap20 = const SizedBox(height: Dimens.dp_20);
37 | static const Widget vGap50 = const SizedBox(height: Dimens.dp_50);
38 |
39 | // static Widget line = const SizedBox(
40 | // height: 0.6,
41 | // width: double.infinity,
42 | // child: const DecoratedBox(decoration: BoxDecoration(color: Colours.line)),
43 | // );
44 |
45 | static Widget line = const Divider();
46 |
47 | static Widget vLine = const SizedBox(
48 | width: 0.6,
49 | height: 24.0,
50 | child: const VerticalDivider(),
51 | );
52 |
53 | static const Widget empty = const SizedBox.shrink();
54 | }
55 |
--------------------------------------------------------------------------------
/lib/res/resources.dart:
--------------------------------------------------------------------------------
1 | export 'colors.dart';
2 | export 'dimens.dart';
3 | export 'styles.dart';
4 | export 'gaps.dart';
5 |
6 | import 'package:flutter/widgets.dart';
7 | import 'package:flutterjdshop/widget/load_image.dart';
8 |
9 |
10 | class Images {
11 | static const Widget arrowRight = const LoadAssetImage('ic_arrow_right', height: 16.0, width: 16.0);
12 |
13 | }
--------------------------------------------------------------------------------
/lib/res/styles.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/widgets.dart';
3 |
4 | import 'colors.dart';
5 | import 'dimens.dart';
6 |
7 | class TextStyles {
8 |
9 |
10 | static const TextStyle textSize12 = const TextStyle(
11 | fontSize: Dimens.font_sp12,
12 | );
13 | static const TextStyle textSize16 = const TextStyle(
14 | fontSize: Dimens.font_sp16,
15 | );
16 |
17 | static const TextStyle textSize28 = const TextStyle(
18 | fontSize: Dimens.font_sp28,
19 | );
20 | static const TextStyle textBold14 = const TextStyle(
21 | fontSize: Dimens.font_sp14,
22 | fontWeight: FontWeight.bold
23 | );
24 | static const TextStyle textBold16 = const TextStyle(
25 | fontSize: Dimens.font_sp16,
26 | fontWeight: FontWeight.bold
27 | );
28 | static const TextStyle textBold18 = const TextStyle(
29 | fontSize: Dimens.font_sp18,
30 | fontWeight: FontWeight.bold
31 | );
32 | static const TextStyle textBold24 = const TextStyle(
33 | fontSize: 24.0,
34 | fontWeight: FontWeight.bold
35 | );
36 | static const TextStyle textBold26 = const TextStyle(
37 | fontSize: 26.0,
38 | fontWeight: FontWeight.bold
39 | );
40 |
41 | static const TextStyle textGray14 = const TextStyle(
42 | fontSize: Dimens.font_sp14,
43 | color: Colours.text_gray,
44 | );
45 | static const TextStyle textDarkGray14 = const TextStyle(
46 | fontSize: Dimens.font_sp14,
47 | color: Colours.dark_text_gray,
48 | );
49 | static const TextStyle textBlack14 = const TextStyle(
50 | fontSize: Dimens.font_sp14,
51 | color: Colors.black54,
52 | );
53 | static const TextStyle textWhite = const TextStyle(
54 | color: Colours.white,
55 | );
56 | static const TextStyle textRed16 = const TextStyle(
57 | fontSize: Dimens.font_sp16,
58 | color: Colors.red,
59 | );
60 | static const TextStyle textWhite14 = const TextStyle(
61 | fontSize: Dimens.font_sp14,
62 | color: Colors.white,
63 | );
64 | static const TextStyle textWhite28 = const TextStyle(
65 | fontSize: Dimens.font_sp28,
66 | color: Colors.white,
67 | );
68 | static const TextStyle textWhite24 = const TextStyle(
69 | fontSize: Dimens.font_sp24,
70 | color: Colors.white,
71 | );
72 | static const TextStyle text = const TextStyle(
73 | fontSize: Dimens.font_sp14,
74 | color: Colours.text,
75 | // https://github.com/flutter/flutter/issues/40248
76 | textBaseline: TextBaseline.alphabetic
77 | );
78 | static const TextStyle textDark = const TextStyle(
79 | fontSize: Dimens.font_sp14,
80 | color: Colours.dark_text,
81 | textBaseline: TextBaseline.alphabetic
82 | );
83 |
84 | static const TextStyle textGray12 = const TextStyle(
85 | fontSize: Dimens.font_sp12,
86 | color: Colours.text_gray,
87 | fontWeight: FontWeight.normal
88 | );
89 | static const TextStyle textDarkGray12 = const TextStyle(
90 | fontSize: Dimens.font_sp12,
91 | color: Colours.dark_text_gray,
92 | fontWeight: FontWeight.normal
93 | );
94 |
95 | static const TextStyle textHint14 = const TextStyle(
96 | fontSize: Dimens.font_sp14,
97 | color: Colours.dark_unselected_item_color
98 | );
99 | }
100 |
--------------------------------------------------------------------------------
/lib/routes/404.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutterjdshop/utils/app_size.dart';
3 | import 'package:flutterjdshop/view/app_topbar.dart';
4 | import 'package:flutterjdshop/view/customize_appbar.dart';
5 | import 'package:flutterjdshop/widget/view/load_state_layout.dart';
6 |
7 | class WidgetNotFound extends StatelessWidget {
8 | @override
9 | Widget build(BuildContext context) {
10 | return Scaffold(
11 | appBar: MyAppBar(
12 | preferredSize: Size.fromHeight(AppSize.height(80)),
13 | child: CommonBackTopBar(title: "页面不存在")),
14 | body: LoadStateLayout(state: LoadState.State_Error,),
15 | );
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/lib/routes/application.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:fluro/fluro.dart';
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutterjdshop/config/api.dart';
5 | import 'package:flutterjdshop/http/intercept.dart';
6 |
7 | import 'my_navigator_observer.dart';
8 |
9 | class Application {
10 | static late FluroRouter router;
11 | static GlobalKey? navKey;
12 | final dio = Dio()
13 | ..options = BaseOptions(baseUrl: API.reqUrl, connectTimeout: Duration(seconds: 30), receiveTimeout: Duration(seconds: 30))
14 | ..interceptors.add(AuthInterceptor())
15 | ..interceptors.add(LogInterceptor(responseBody: true, requestBody: true));
16 | }
17 |
--------------------------------------------------------------------------------
/lib/routes/my_navigator_observer.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | /// 记录路由,便于清空路由栈
4 | /// 可以跳转不需要context
5 | /// pop指定页面
6 | /// MyNavigatorObserver.getInstance().navigator.pushNamed("/login");
7 | /// MyNavigatorObserver.getInstance().list.forEach((element) {
8 | /// Navigator.removeRoute(context, element);
9 | /// });
10 | /// MyNavigatorObserver.getInstance().list = [];
11 | class MyNavigatorObserver extends NavigatorObserver {
12 | //清空某些页面
13 | List> list = [];
14 | static MyNavigatorObserver? _instance;
15 |
16 | static MyNavigatorObserver? getInstance() {
17 | if (_instance == null) {
18 | _instance = MyNavigatorObserver();
19 | }
20 | return _instance;
21 | }
22 |
23 | ///调用push的时候
24 | @override
25 | void didPush(Route route, Route? previousRoute) {
26 | /// 首页不添加
27 | //路由名字
28 | print("didPushname${route.settings.name}");
29 | if (route.settings.name != '/') {
30 | list.add(route);
31 | print(list.length);
32 | }
33 | }
34 |
35 | ///调用pop的时候
36 | @override
37 | void didPop(Route route, Route? previousRoute) {
38 | print("didPop${route.settings.name}");
39 | list.remove(route);
40 | print(list.length);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/lib/routes/router_init.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:fluro/fluro.dart';
3 |
4 | abstract class IRouterProvider{
5 |
6 | void initRouter(FluroRouter router);
7 | }
--------------------------------------------------------------------------------
/lib/routes/routers.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:fluro/fluro.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:flutterjdshop/page/splash_page.dart';
5 | import 'package:flutterjdshop/page/web_page.dart';
6 | import 'package:flutterjdshop/routes/demo_router.dart';
7 | import 'package:flutterjdshop/routes/router_init.dart';
8 |
9 | import '404.dart';
10 | import 'shop_router.dart';
11 |
12 |
13 | class Routes {
14 |
15 | static String home = '/';
16 | static String webViewPage = '/webview';
17 |
18 | static List _listRouter = [];
19 |
20 | static void configureRoutes(FluroRouter router) {
21 | /// 指定路由跳转错误返回页
22 | router.notFoundHandler = Handler(
23 | handlerFunc: (BuildContext? context, Map> params) {
24 | debugPrint('未找到目标页');
25 | return WidgetNotFound();
26 | });
27 |
28 | router.define(home, handler: Handler(
29 | handlerFunc: (BuildContext? context, Map> params) => SplashPage()));
30 |
31 | router.define(webViewPage, handler: Handler(handlerFunc: (_, params) {
32 | String? title = params['title']?.first;
33 | String? url = params['url']?.first;
34 | return WebViewPage(title: title, url: url);
35 | }));
36 |
37 | _listRouter.clear();
38 | /// 各自路由由各自模块管理,统一在此添加初始化
39 | _listRouter.add(ShopRouter());
40 | _listRouter.add(DemoRouter());
41 |
42 | /// 初始化路由
43 | _listRouter.forEach((routerProvider) {
44 | routerProvider.initRouter(router);
45 | });
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/lib/utils/CheckOutServices.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:flutterjdshop/common/common.dart';
4 | class CheckOutServices{
5 | //计算总价
6 | static getAllPrice(checkOutListData) {
7 | var tempAllPrice=0.0;
8 | for (var i = 0; i < checkOutListData.length; i++) {
9 | if (checkOutListData[i]["checked"] == true) {
10 | tempAllPrice += checkOutListData[i]["price"] * checkOutListData[i]["count"];
11 | }
12 | }
13 | return tempAllPrice;
14 | }
15 | static removeUnSelectedCartItem() async{
16 |
17 | List? _cartList=[];
18 | List _tempList=[];
19 | //获取购物车的数据
20 | try {
21 | List? cartListData = json.decode(SharedUtil.instance!.getString('cartList')!);
22 | _cartList = cartListData;
23 | } catch (e) {
24 | _cartList = [];
25 | }
26 |
27 | for (var i = 0; i < _cartList!.length; i++) {
28 | if (_cartList[i]["checked"] == false) {
29 | _tempList.add(_cartList[i]);
30 | }
31 | }
32 |
33 | SharedUtil.instance!.saveString("cartList", json.encode(_tempList));
34 |
35 | }
36 | }
--------------------------------------------------------------------------------
/lib/utils/SearchServices.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:flutterjdshop/common/common.dart';
4 |
5 |
6 |
7 | class SearchServices {
8 | static setHistoryData(keywords) async {
9 | /*
10 | 1、获取本地存储里面的数据 (searchList)
11 |
12 | 2、判断本地存储是否有数据
13 |
14 | 2.1、如果有数据
15 |
16 | 1、读取本地存储的数据
17 | 2、判断本地存储中有没有当前数据,
18 | 如果有不做操作、
19 | 如果没有当前数据,本地存储的数据和当前数据拼接后重新写入
20 |
21 |
22 | 2.2、如果没有数据
23 |
24 | 直接把当前数据放在数组中写入到本地存储
25 |
26 |
27 | */
28 |
29 | try {
30 | List searchListData = json.decode( SharedUtil.instance!.getString('searchList')!);
31 |
32 | print(searchListData);
33 | var hasData = searchListData.any((v) {
34 | return v == keywords;
35 | });
36 | if (!hasData) {
37 | searchListData.add(keywords);
38 | await SharedUtil.instance!.saveString('searchList', json.encode(searchListData));
39 | }
40 | } catch (e) {
41 | List tempList = List.empty();
42 | tempList.add(keywords);
43 | await SharedUtil.instance!.saveString('searchList', json.encode(tempList));
44 | }
45 | }
46 | static getHistoryList() async{
47 | try {
48 | List? searchListData = json.decode(await SharedUtil.instance!.getString('searchList')!);
49 | return searchListData;
50 | } catch (e) {
51 | return [];
52 | }
53 | }
54 |
55 | static clearHistoryList() async{
56 | await SharedUtil.instance!.remove('searchList');
57 | }
58 | static removeHistoryData(keywords) async{
59 | List searchListData = json.decode(await SharedUtil.instance!.getString('searchList')!);
60 | searchListData.remove(keywords);
61 | await SharedUtil.instance!.saveString('searchList', json.encode(searchListData));
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/lib/utils/app_size.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 |
4 | class AppSize {
5 | static void init(BuildContext context) {
6 |
7 | }
8 |
9 | static double height(double value) {
10 | return ScreenUtil().setHeight(value);
11 | }
12 |
13 | static double getItemWidth(int number, double padding) {
14 | return (ScreenUtil().screenWidth - padding) / number;
15 | }
16 | static double getWidth() {
17 | return ScreenUtil().screenWidth;
18 | }
19 | static double width(double value) {
20 | return ScreenUtil().setWidth(value);
21 | }
22 | static double sp(double value) {
23 | return ScreenUtil().setSp(value);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/utils/dialog_utils.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:fluttertoast/fluttertoast.dart';
3 | import 'app_size.dart';
4 | class DialogUtil {
5 | static void buildToast(String str) {
6 | Fluttertoast.showToast(
7 | fontSize: AppSize.sp(13),
8 | gravity: ToastGravity.CENTER,
9 | msg: str);
10 | }
11 |
12 |
13 | }
--------------------------------------------------------------------------------
/lib/utils/double_tap_back_exit_app.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'dialog_utils.dart';
4 |
5 |
6 | class DoubleTapBackExitApp extends StatefulWidget {
7 |
8 | const DoubleTapBackExitApp({
9 | Key? key,
10 | required this.child,
11 | this.duration = const Duration(milliseconds: 2500),
12 | }) : super(key: key);
13 |
14 | final Widget child;
15 |
16 | /// 两次点击返回按钮的时间间隔
17 | final Duration duration;
18 |
19 | @override
20 | _DoubleTapBackExitAppState createState() => _DoubleTapBackExitAppState();
21 | }
22 |
23 | class _DoubleTapBackExitAppState extends State {
24 |
25 | DateTime? _lastTime;
26 |
27 | @override
28 | Widget build(BuildContext context) {
29 | return WillPopScope(
30 | onWillPop: _isExit,
31 | child: widget.child,
32 | );
33 | }
34 |
35 | Future _isExit() {
36 | if (_lastTime == null ||
37 | DateTime.now().difference(_lastTime!) > widget.duration) {
38 | _lastTime = DateTime.now();
39 | DialogUtil.buildToast('再次点击退出应用');
40 | return Future.value(false);
41 | }
42 | return Future.value(true);
43 | }
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/lib/utils/image_utils.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/widgets.dart';
3 | import 'package:cached_network_image/cached_network_image.dart';
4 | import 'package:flutterjdshop/utils/utils.dart';
5 | import 'package:flutterjdshop/widget/load_image.dart';
6 |
7 |
8 | class ImageUtils {
9 |
10 | static ImageProvider getAssetImage(String name, {String format = 'png'}) {
11 | return AssetImage(getImgPath(name, format: format));
12 | }
13 |
14 | static String getImgPath(String name, {String format = 'png'}) {
15 | return 'assets/images/$name.$format';
16 | }
17 |
18 | static ImageProvider getImageProvider(String imageUrl,
19 | {String holderImg = 'none'}) {
20 | if (getSafeData(imageUrl).isNotEmpty) {
21 | return AssetImage(getImgPath(holderImg));
22 | }
23 | return CachedNetworkImageProvider(
24 | imageUrl, errorListener: (o) => print("图片加载失败!"));
25 | }
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/lib/utils/log_utils.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'dart:convert' as convert;
3 | import 'package:common_utils/common_utils.dart';
4 | import 'package:flutterjdshop/config/const.dart';
5 |
6 |
7 | /// 输出Log工具类
8 | class Log {
9 |
10 | static const String tag = 'GETH-LOG';
11 |
12 | static void init() {
13 | LogUtil.init(isDebug: !inProduction);
14 | }
15 |
16 | static void d(String msg, {String tag = tag}) {
17 | if (!inProduction) {
18 | LogUtil.v(msg, tag: tag);
19 | }
20 | }
21 |
22 | static void e(String msg, {String tag = tag}) {
23 | if (!inProduction) {
24 | LogUtil.e(msg, tag: tag);
25 | }
26 | }
27 |
28 | static void json(String msg, {String tag = tag}) {
29 | if (!inProduction) {
30 | var data = convert.json.decode(msg);
31 | if (data is Map) {
32 | _printMap(data);
33 | } else if (data is List) {
34 | _printList(data);
35 | } else
36 | LogUtil.v(msg, tag: tag);
37 | }
38 | }
39 |
40 | // https://github.com/Milad-Akarie/pretty_dio_logger
41 | static void _printMap(Map data, {String tag = tag, int tabs = 1, bool isListItem = false, bool isLast = false}) {
42 | final bool isRoot = tabs == 1;
43 | final initialIndent = _indent(tabs);
44 | tabs++;
45 |
46 | if (isRoot || isListItem) LogUtil.v('$initialIndent{', tag: tag);
47 |
48 | data.keys.toList().asMap().forEach((index, key) {
49 | final isLast = index == data.length - 1;
50 | var value = data[key];
51 | if (value is String) value = '\"$value\"';
52 | if (value is Map) {
53 | if (value.length == 0)
54 | LogUtil.v('${_indent(tabs)} $key: $value${!isLast ? ',' : ''}', tag: tag);
55 | else {
56 | LogUtil.v('${_indent(tabs)} $key: {', tag: tag);
57 | _printMap(value, tabs: tabs);
58 | }
59 | } else if (value is List) {
60 | if (value.length == 0) {
61 | LogUtil.v('${_indent(tabs)} $key: ${value.toString()}', tag: tag);
62 | } else {
63 | LogUtil.v('${_indent(tabs)} $key: [', tag: tag);
64 | _printList(value, tabs: tabs);
65 | LogUtil.v('${_indent(tabs)} ]${isLast ? '' : ','}', tag: tag);
66 | }
67 | } else {
68 | final msg = value.toString().replaceAll('\n', '');
69 | LogUtil.v('${_indent(tabs)} $key: $msg${!isLast ? ',' : ''}', tag: tag);
70 | }
71 | });
72 |
73 | LogUtil.v('$initialIndent}${isListItem && !isLast ? ',' : ''}', tag: tag);
74 | }
75 |
76 | static void _printList(List list, {String tag = tag, int tabs = 1}) {
77 | list.asMap().forEach((i, e) {
78 | final isLast = i == list.length - 1;
79 | if (e is Map) {
80 | if (e.length == 0) {
81 | LogUtil.v('${_indent(tabs)} $e${!isLast ? ',' : ''}', tag: tag);
82 | } else {
83 | _printMap(e, tabs: tabs + 1, isListItem: true, isLast: isLast);
84 | }
85 | } else {
86 | LogUtil.v('${_indent(tabs + 2)} $e${isLast ? '' : ','}', tag: tag);
87 | }
88 | });
89 | }
90 |
91 | static String _indent([int tabCount = 1]) => ' ' * tabCount;
92 | }
--------------------------------------------------------------------------------
/lib/utils/number_text_input_formatter.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:flutter/services.dart';
3 |
4 | /// 只允许输入小数
5 | class UsNumberTextInputFormatter extends TextInputFormatter {
6 | static const defaultDouble = 0.001;
7 | static double strToFloat(String str, [double defaultValue = defaultDouble]) {
8 | try {
9 | return double.parse(str);
10 | } catch (e) {
11 | return defaultValue;
12 | }
13 | }
14 |
15 | @override
16 | TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
17 | String value = newValue.text;
18 | int selectionIndex = newValue.selection.end;
19 | if (value == '.') {
20 | value = '0.';
21 | selectionIndex++;
22 | } else if (value != '' && value != defaultDouble.toString() && strToFloat(value, defaultDouble) == defaultDouble) {
23 | value = oldValue.text;
24 | selectionIndex = oldValue.selection.end;
25 | }
26 | return new TextEditingValue(
27 | text: value,
28 | selection: new TextSelection.collapsed(offset: selectionIndex),
29 | );
30 | }
31 | }
--------------------------------------------------------------------------------
/lib/utils/theme_utils.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter/services.dart';
4 | import 'package:flutterjdshop/res/colors.dart';
5 | import 'package:flutterjdshop/res/colours.dart';
6 |
7 |
8 | class ThemeUtils {
9 |
10 | static bool isDark(BuildContext context) {
11 | return Theme.of(context).brightness == Brightness.dark;
12 | }
13 |
14 | static Color? getDarkColor(BuildContext context, Color darkColor) {
15 | return isDark(context) ? darkColor : null;
16 | }
17 |
18 | static Color? getIconColor(BuildContext context) {
19 | return isDark(context) ? Colours.text_dark : null;
20 | }
21 |
22 | static Color getBackgroundColor(BuildContext context) {
23 | return Theme.of(context).scaffoldBackgroundColor;
24 | }
25 |
26 | static Color getDialogBackgroundColor(BuildContext context) {
27 | return Theme.of(context).canvasColor;
28 | }
29 |
30 | static Color getStickyHeaderColor(BuildContext context) {
31 | return isDark(context) ? Colours.dark_bg_gray_ : Colours.bg_gray_;
32 | }
33 |
34 | static Color getDialogTextFieldColor(BuildContext context) {
35 | return isDark(context) ? Colours.dark_bg_gray_ : Colours.bg_gray;
36 | }
37 |
38 | static Color? getKeyboardActionsColor(BuildContext context) {
39 | return isDark(context) ? Colours.dark_bg_color : Colors.grey[200];
40 |
41 | }
42 | }
--------------------------------------------------------------------------------
/lib/utils/utils.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 | import 'dart:typed_data';
3 | import 'dart:ui';
4 |
5 | import 'package:flutter/material.dart';
6 | import 'package:flutterjdshop/common/shared_util.dart';
7 | import 'package:flutterjdshop/config/api.dart';
8 | import 'package:crypto/crypto.dart';
9 | import 'package:flutterjdshop/utils/app_size.dart';
10 |
11 | String getSafeData(String? data) {
12 | return data ?? "";
13 | }
14 |
15 | Widget hideKeyword(Widget? child, BuildContext context) {
16 | return GestureDetector(
17 |
18 | ///透明也响应处理
19 | behavior: HitTestBehavior.opaque,
20 | child: child,
21 | onTap: () {
22 | FocusScope.of(context).unfocus();
23 | });
24 | }
25 |
26 | //显示键盘
27 | void showKeyword(BuildContext context, FocusNode _focusNode) {
28 | if (MediaQuery.of(context).viewInsets.bottom == 0) {
29 | final focusScope = FocusScope.of(context);
30 | focusScope.requestFocus(FocusNode());
31 | Future.delayed(Duration.zero, () => focusScope.requestFocus(_focusNode));
32 | }
33 | }
34 |
35 | //隐藏键盘
36 | void hideKeyword2(BuildContext context) {
37 | FocusScope.of(context).unfocus();
38 | }
39 |
40 | String getFullPath(String path) {
41 | path = path.replaceAll('\\', '/').replaceAll('api/', '');
42 | return !path.startsWith('http') ? "${API.baseUrl}$path" : path;
43 | }
44 |
45 | String getSign(json) {
46 | List attrKeys = json.keys.toList();
47 | attrKeys.sort(); //排序 ASCII 字符顺序进行升序排列
48 | String str = '';
49 | for (var i = 0; i < attrKeys.length; i++) {
50 | str += "${attrKeys[i]}${json[attrKeys[i]]}";
51 | }
52 | return md5.convert(utf8.encode(str)).toString();
53 | }
54 |
55 | String getStrByKey(String key) {
56 | return getSafeData(SharedUtil.instance!.getString(key));
57 | }
58 |
59 | Future saveStrByKey(String key, String data) async {
60 | await SharedUtil.instance!.saveString(key, data);
61 | }
62 |
63 |
64 | double getY(BuildContext buildContext) {
65 | final RenderBox box = buildContext.findRenderObject() as RenderBox;
66 | final size = box.size;
67 | ////代表的意思是说 button 组件中(0,0)点转换成全屏幕上的点的坐标值
68 | final topLeftPosition = box.localToGlobal(Offset.zero);
69 | return topLeftPosition.dy;
70 | }
71 |
72 |
73 | void get(){
74 | // FileImage(file).resolve(config)
75 | }
76 |
77 |
78 |
--------------------------------------------------------------------------------
/lib/utils/view_utils.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutterjdshop/res/styles.dart';
3 | import 'package:flutterjdshop/routes/fluro_navigator.dart';
4 | import 'package:flutterjdshop/routes/shop_router.dart';
5 |
6 | import 'app_size.dart';
7 |
8 | AppBar getSearchAppBar(context){
9 | return AppBar(
10 | leading: IconButton(
11 | icon: Icon(
12 | Icons.center_focus_weak,
13 | color: Colors.black87,
14 | ),
15 | onPressed: null,
16 | ),
17 | title: InkWell(
18 | onTap: () {
19 | NavigatorUtils.push(context, ShopRouter.SEARCH);
20 | },
21 | child: Container(
22 | height: AppSize.height(68),
23 | decoration: BoxDecoration(
24 | color: Color.fromRGBO(233, 233, 233, 0.8),
25 | borderRadius: BorderRadius.all(Radius.circular(30))),
26 | padding: EdgeInsets.only(left: AppSize.width(10)),
27 | child: Container(
28 | alignment: Alignment.center,
29 | child: TextButton.icon(
30 | onPressed: () {
31 | NavigatorUtils.push(context, ShopRouter.SEARCH);
32 | },
33 | icon: Icon(Icons.search),
34 | label: Text(
35 | "笔记本",
36 | style: TextStyles.textSize16,
37 | )),
38 | ),
39 | ),
40 | ),
41 | actions: [
42 | IconButton(
43 | icon: Icon(
44 | Icons.message,
45 | size: 28,
46 | color: Colors.black87,
47 | ),
48 | onPressed: null,
49 | )
50 | ],
51 | );
52 | }
--------------------------------------------------------------------------------
/lib/view/CustomSliverPersistentHeaderDelegate.dart:
--------------------------------------------------------------------------------
1 | // 自定义 SliverPersistentHeaderDelegate
2 | import 'package:flutter/material.dart';
3 |
4 | class CustomSliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
5 | final double max; // 最大高度
6 | final double min; // 最小高度
7 | final Widget child; // 需要展示的内容
8 |
9 | CustomSliverPersistentHeaderDelegate({required this.max, required this.min, required this.child})
10 | // 如果 assert 内部条件不成立,会报错
11 | : assert(max != null),
12 | assert(min != null),
13 | assert(child != null),
14 | assert(min <= max),
15 | super();
16 |
17 | // 返回展示的内容,如果内容固定可以直接在这定义,如果需要可扩展,这边通过传入值来定义
18 | @override
19 | Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) => child;
20 |
21 | @override
22 | double get maxExtent => max; // 返回最大高度
23 |
24 | @override
25 | double get minExtent => min; // 返回最小高度
26 |
27 | @override
28 | bool shouldRebuild(CustomSliverPersistentHeaderDelegate oldDelegate) {
29 | // 是否需要更新,这里我们定义当高度范围和展示内容被替换的时候进行刷新界面
30 | return max != oldDelegate.max || min != oldDelegate.min || child != oldDelegate.child;
31 | }
32 | }
--------------------------------------------------------------------------------
/lib/view/customize_appbar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | // import 'package:flutter_statusbarcolor/flutter_statusbarcolor.dart';
4 | import 'package:flutterjdshop/res/colors.dart';
5 | import 'package:flutterjdshop/utils/app_size.dart';
6 |
7 |
8 | class MyAppBar extends StatelessWidget implements PreferredSizeWidget {
9 | final Widget? child;
10 |
11 | @override
12 | final Size preferredSize;
13 |
14 | const MyAppBar({
15 | Key? key,
16 | required this.child,
17 | required this.preferredSize,
18 | }) : super(key: key);
19 |
20 | void initStateBar() async{
21 | // FlutterStatusbarcolor.setStatusBarWhiteForeground(true);
22 | }
23 |
24 | @override
25 | Widget build(BuildContext context) {
26 | AppSize.init(context);
27 | double _statusHeight = ScreenUtil().statusBarHeight;
28 | return Container(
29 | padding: EdgeInsets.only(left: 6, right: 6,top: _statusHeight),
30 | decoration: BoxDecoration(
31 | gradient: LinearGradient(
32 | colors: [Colours.app_main, Colours.app_main],
33 | begin: Alignment.topCenter,
34 | end: Alignment.bottomCenter),
35 | ),
36 | height: preferredSize.height+_statusHeight,
37 | // color: Theme.of(context).primaryColor,
38 | child: this.child,
39 | );
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/lib/view/flutter_icon_data.dart:
--------------------------------------------------------------------------------
1 | library flutter_iconfont;
2 |
3 | import 'package:flutter/widgets.dart' show IconData;
4 |
5 | class IconDataEx extends IconData {
6 | const IconDataEx(int codePoint)
7 | : super(
8 | codePoint,
9 | fontFamily: 'IconFont',
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/lib/view/flutter_iconfont.dart:
--------------------------------------------------------------------------------
1 | library flutter_iconfont;
2 |
3 | import 'package:flutter/widgets.dart' show IconData;
4 |
5 | import 'flutter_icon_data.dart';
6 |
7 |
8 | class IconFonts{
9 | IconFonts._();
10 |
11 | static const IconData triangle_down = const IconDataEx(0xe6b4);
12 | static const IconData eye = const IconDataEx(0xe616);
13 | static const IconData scan_code = const IconDataEx(0xe640);
14 | static const IconData triangle_right = const IconDataEx(0xe615);
15 | static const IconData arrow_down = const IconDataEx(0xe62a);
16 | static const IconData arrow_left = const IconDataEx(0xe62c);
17 | static const IconData shopping_cart = const IconDataEx(0xe614);
18 | static const IconData ellipsis = const IconDataEx(0xe727);
19 | static const IconData location = const IconDataEx(0xe612);
20 | static const IconData arrow_right = const IconDataEx(0xe620);
21 | static const IconData eye_close = const IconDataEx(0xe50e);
22 | }
23 |
--------------------------------------------------------------------------------
/lib/view/my_icons.dart.dart:
--------------------------------------------------------------------------------
1 | /// Flutter icons MyFlutterApp
2 | /// Copyright (C) 2019 by original authors @ fluttericon.com, fontello.com
3 | /// This font was generated by FlutterIcon.com, which is derived from Fontello.
4 | ///
5 | /// To use this font, place it in your fonts/ directory and include the
6 | /// following in your pubspec.yaml
7 | ///
8 | /// flutter:
9 | /// fonts:
10 | /// - family: MyFlutterApp
11 | /// fonts:
12 | /// - asset: fonts/MyFlutterApp.ttf
13 | ///
14 | ///
15 | ///
16 | import 'package:flutter/widgets.dart';
17 |
18 | class MyIcons {
19 | MyIcons._();
20 |
21 | static const _kFontFam = 'MyIcons';
22 |
23 | static const IconData orderForm = const IconData(0xe800, fontFamily: _kFontFam);
24 | static const IconData findings = const IconData(0xe801, fontFamily: _kFontFam);
25 | static const IconData home = const IconData(0xe802, fontFamily: _kFontFam);
26 | static const IconData personal = const IconData(0xe803, fontFamily: _kFontFam);
27 | static const IconData location = const IconData(0xe615, fontFamily: 'MyIcons2');
28 | static const IconData placeholder = const IconData(0xe627, fontFamily: 'MyIcons2');
29 | static const IconData addressholder = const IconData(0xe60d, fontFamily: 'MyIcons3');
30 | static const IconData youhuiquanholder = const IconData(0xe645, fontFamily: 'MyIcons3');
31 | static const IconData jifenholder = const IconData(0xe624, fontFamily: 'MyIcons3');
32 | static const IconData liwuholder = const IconData(0xe60b, fontFamily: 'MyIcons3');
33 | static const IconData daifukuan = const IconData(0xe632, fontFamily: 'MyIcons3');
34 | static const IconData daifahuo = const IconData(0xe63e, fontFamily: 'MyIcons3');
35 | static const IconData yifahuo = const IconData(0xe620, fontFamily: 'MyIcons3');
36 | static const IconData yiwancheng = const IconData(0xe6d7, fontFamily: 'MyIcons3');
37 | static const IconData zhifubpay = const IconData(0xe68a, fontFamily: 'MyIcons4');
38 | static const IconData weixinpay = const IconData(0xe61b, fontFamily: 'MyIcons4');
39 | static const IconData sexicon = const IconData(0xe611, fontFamily: 'MyIcons4');
40 | }
41 |
--------------------------------------------------------------------------------
/lib/widget/dialog/remind_dialog.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutterjdshop/res/styles.dart';
3 | import 'package:flutterjdshop/widget/view/base_dialog.dart';
4 |
5 | class RemindDialog extends StatefulWidget {
6 | final String title;
7 | final String? content;
8 | final Function? confirmFunc;
9 |
10 | RemindDialog({
11 | Key? key,
12 | this.title = "提示",
13 | this.content,
14 | this.confirmFunc,
15 | }) : super(key: key);
16 |
17 | @override
18 | _ExitDialog createState() => _ExitDialog();
19 | }
20 |
21 | class _ExitDialog extends State {
22 | @override
23 | Widget build(BuildContext context) {
24 | return BaseDialog(
25 | title: widget.title,
26 | child: Container(
27 | padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
28 | child: Text(widget.content!, style: TextStyles.textSize16),
29 | ),
30 | onPressed: widget.confirmFunc,
31 | );
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/lib/widget/load_image.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:cached_network_image/cached_network_image.dart';
3 |
4 | import 'package:flutter/material.dart';
5 | import 'package:flutterjdshop/config/const.dart';
6 | import 'package:flutterjdshop/utils/image_utils.dart';
7 | import 'package:flutterjdshop/utils/utils.dart';
8 |
9 |
10 | /// 图片加载(支持本地与网络图片)
11 | class LoadImage extends StatelessWidget {
12 |
13 | const LoadImage(this.image, {
14 | Key? key,
15 | this.width,
16 | this.height,
17 | this.fit = BoxFit.cover,
18 | this.format = 'png',
19 | this.holderImg = 'none'
20 | }): super(key: key);
21 |
22 | final String image;
23 | final double? width;
24 | final double? height;
25 | final BoxFit fit;
26 | final String format;
27 | final String holderImg;
28 |
29 | @override
30 | Widget build(BuildContext context) {
31 | if (getSafeData(image).isEmpty) {
32 | return LoadAssetImage(holderImg,
33 | height: height,
34 | width: width,
35 | fit: fit,
36 | format: format
37 | );
38 | } else {
39 | if (image.startsWith('http')) {
40 | return CachedNetworkImage(
41 | imageUrl: image,
42 | placeholder: (context, url) => LoadAssetImage(holderImg, height: height, width: width, fit: fit),
43 | errorWidget: (context, url, error) => LoadAssetImage(holderImg, height: height, width: width, fit: fit),
44 | width: width,
45 | height: height,
46 | fit: fit,
47 | );
48 | } else {
49 | return LoadAssetImage(image,
50 | height: height,
51 | width: width,
52 | fit: fit,
53 | format: format
54 | );
55 | }
56 | }
57 | }
58 | }
59 |
60 | /// 加载本地资源图片
61 | class LoadAssetImage extends StatelessWidget {
62 |
63 | const LoadAssetImage(this.image, {
64 | Key? key,
65 | this.width,
66 | this.height,
67 | this.fit,
68 | this.format = IMAGE_PNG,
69 | this.color
70 | }): super(key: key);
71 |
72 | final String image;
73 | final double? width;
74 | final double? height;
75 | final BoxFit? fit;
76 | final String format;
77 | final Color? color;
78 |
79 | @override
80 | Widget build(BuildContext context) {
81 |
82 | return Image.asset(
83 | ImageUtils.getImgPath(image, format: format),
84 | height: height,
85 | width: width,
86 | fit: fit,
87 | color: color,
88 | /// 忽略图片语义
89 | excludeFromSemantics: true,
90 | );
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/lib/widget/my_iframe/my_iframe.dart:
--------------------------------------------------------------------------------
1 | export 'my_iframe_other.dart' if (dart.library.html) 'my_iframe_web.dart';
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/lib/widget/my_iframe/my_iframe_other.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 | import 'package:flutter/gestures.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:webview_flutter/webview_flutter.dart';
5 |
6 |
7 | ///EagerGestureRecognizer 急切拿到事件,webview拿到事件
8 | class MyIFrame extends StatefulWidget {
9 | final String url;
10 | final Function(double, dynamic)? heightFunc;
11 |
12 | const MyIFrame(this.url, {Key? key, this.heightFunc}) : super(key: key);
13 |
14 | @override
15 | State createState() => _MyIFrameState();
16 | }
17 |
18 | class _MyIFrameState extends State {
19 | ValueNotifier isShowLoading = ValueNotifier(true);
20 | late WebViewController controller;
21 |
22 |
23 |
24 | @override
25 | void dispose() {
26 | controller.loadRequest(Uri.parse('about:blank'));
27 | controller.clearCache();
28 | super.dispose();
29 | }
30 |
31 | @override
32 | void initState() {
33 | super.initState();
34 | //gestureNavigationEnabled
35 | controller = WebViewController()
36 | ..setJavaScriptMode(JavaScriptMode.unrestricted)
37 | ..setBackgroundColor(Colors.transparent)
38 | ..setJavaScriptMode(JavaScriptMode.unrestricted)
39 | ..setNavigationDelegate(
40 | NavigationDelegate(
41 | onProgress: (int progress) {
42 | if (progress == 100) {
43 | isShowLoading.value = false;
44 | }
45 | },
46 | onPageStarted: (String url) {},
47 | onPageFinished: (String url) {
48 | controller
49 | .runJavaScriptReturningResult('document.body.scrollHeight')
50 | .then((value) {
51 | widget.heightFunc?.call(double.parse('$value'), controller);
52 | });
53 | },
54 | onWebResourceError: (WebResourceError error) {},
55 | onNavigationRequest: (NavigationRequest request) {
56 | if (request.url.startsWith('https://www.youtube.com/')) {
57 | return NavigationDecision.prevent;
58 | }
59 | return NavigationDecision.navigate;
60 | },
61 | ),
62 | )
63 | ..loadRequest(Uri.parse(widget.url));
64 |
65 | }
66 |
67 | @override
68 | Widget build(BuildContext context) {
69 | return Stack(
70 | children: [
71 | WebViewWidget(
72 | gestureRecognizers: {
73 | if (widget.heightFunc == null)
74 | Factory(() => EagerGestureRecognizer())
75 | },
76 | controller: controller,
77 | ),
78 | ValueListenableBuilder(
79 | valueListenable: isShowLoading,
80 | builder: (BuildContext context, bool value, Widget? child) {
81 | return isShowLoading.value
82 | ? const Center(
83 | child: CircularProgressIndicator(
84 | color: Colors.white,
85 | ))
86 | : const SizedBox.shrink();
87 | },
88 | )
89 | ],
90 | );
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/lib/widget/scroll/my_behavior.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:flutter/material.dart';
4 |
5 | class MyBehavior extends ScrollBehavior {
6 | @override
7 | Widget buildOverscrollIndicator(
8 | BuildContext context, Widget child, ScrollableDetails details) {
9 | if (Platform.isAndroid || Platform.isFuchsia) {
10 | return child;
11 | } else {
12 | return super.buildOverscrollIndicator(context, child, details);
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/lib/widget/view/LoadingWidget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | class LoadingWidget extends StatelessWidget {
3 | const LoadingWidget({Key? key}) : super(key: key);
4 |
5 | @override
6 | Widget build(BuildContext context) {
7 | return Center(
8 | child: Padding(
9 | padding: EdgeInsets.all(10.0),
10 | child: Row(
11 | mainAxisAlignment: MainAxisAlignment.center,
12 | crossAxisAlignment: CrossAxisAlignment.center,
13 | children: [
14 | CircularProgressIndicator(
15 | strokeWidth: 1.0,
16 | ),Text(
17 | '加载中...',
18 | style: TextStyle(fontSize: 16.0),
19 | )
20 | ],
21 | ),
22 | ),
23 | );;
24 | }
25 | }
--------------------------------------------------------------------------------
/lib/widget/view/keyboard_detector.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | typedef KeyboardShowCallback = void Function(bool isKeyboardShowing);
4 |
5 | class KeyboardDetector extends StatefulWidget {
6 | KeyboardShowCallback? keyboardShowCallback;
7 |
8 | Widget content;
9 |
10 | KeyboardDetector(this.content, {this.keyboardShowCallback});
11 |
12 | @override
13 | _KeyboardDetectorState createState() => _KeyboardDetectorState();
14 | }
15 |
16 | class _KeyboardDetectorState extends State
17 | with WidgetsBindingObserver {
18 | @override
19 | void initState() {
20 | WidgetsBinding.instance!.addObserver(this);
21 | super.initState();
22 | }
23 |
24 | @override
25 | void didChangeMetrics() {
26 | super.didChangeMetrics();
27 | WidgetsBinding.instance!.addPostFrameCallback((_) {
28 | print(MediaQuery.of(context).viewInsets.bottom);
29 | setState(() {
30 | widget.keyboardShowCallback
31 | ?.call(MediaQuery.of(context).viewInsets.bottom > 0);
32 | });
33 | });
34 | }
35 |
36 | @override
37 | void dispose() {
38 | WidgetsBinding.instance!.removeObserver(this);
39 | super.dispose();
40 | }
41 |
42 | @override
43 | Widget build(BuildContext context) {
44 | return widget.content;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/lib/widget/view/load_image.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:cached_network_image/cached_network_image.dart';
3 | import 'package:flutter/material.dart';
4 |
5 | import 'package:flutterjdshop/utils/image_utils.dart';
6 |
7 | /// 图片加载(支持本地与网络图片)
8 | class LoadImage extends StatelessWidget {
9 |
10 | const LoadImage(this.image, {
11 | Key? key,
12 | this.width,
13 | this.height,
14 | this.fit = BoxFit.cover,
15 | this.format = 'png',
16 | this.holderImg = 'none'
17 | }): super(key: key);
18 |
19 | final String image;
20 | final double? width;
21 | final double? height;
22 | final BoxFit fit;
23 | final String format;
24 | final String holderImg;
25 |
26 | @override
27 | Widget build(BuildContext context) {
28 | if (image==null|| image.isEmpty) {
29 | return LoadAssetImage(holderImg,
30 | height: height,
31 | width: width,
32 | fit: fit,
33 | format: format
34 | );
35 | } else {
36 | if (image.startsWith('http')) {
37 | return CachedNetworkImage(
38 | imageUrl: image,
39 | placeholder: (context, url) => LoadAssetImage(holderImg, height: height, width: width, fit: fit),
40 | errorWidget: (context, url, error) => LoadAssetImage(holderImg, height: height, width: width, fit: fit),
41 | width: width,
42 | height: height,
43 | fit: fit,
44 | );
45 | } else {
46 | return LoadAssetImage(image,
47 | height: height,
48 | width: width,
49 | fit: fit,
50 | format: format
51 | );
52 | }
53 | }
54 | }
55 | }
56 |
57 | /// 加载本地资源图片
58 | class LoadAssetImage extends StatelessWidget {
59 |
60 | const LoadAssetImage(this.image, {
61 | Key? key,
62 | this.width,
63 | this.height,
64 | this.fit,
65 | this.format = 'png',
66 | this.color
67 | }): super(key: key);
68 |
69 | final String image;
70 | final double? width;
71 | final double? height;
72 | final BoxFit? fit;
73 | final String format;
74 | final Color? color;
75 |
76 | @override
77 | Widget build(BuildContext context) {
78 |
79 | return Image.asset(
80 | ImageUtils.getImgPath(image, format: format),
81 | height: height,
82 | width: width,
83 | fit: fit,
84 | color: color,
85 | /// 忽略图片语义
86 | excludeFromSemantics: true,
87 | );
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/lib/widget/view/my_button.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutterjdshop/res/colors.dart';
3 | import 'package:flutterjdshop/res/dimens.dart';
4 | import 'package:flutterjdshop/utils/theme_utils.dart';
5 |
6 | class MyButton extends StatelessWidget {
7 | const MyButton({
8 | Key? key,
9 | this.text = '',
10 | required this.onPressed,
11 | this.margin,
12 | this.color = Colours.app_main,
13 | }) : super(key: key);
14 |
15 | final String text;
16 | final Color color;
17 | final EdgeInsetsGeometry? margin;
18 | final VoidCallback? onPressed;
19 |
20 | @override
21 | Widget build(BuildContext context) {
22 | bool isDark = ThemeUtils.isDark(context);
23 | return Container(
24 | margin: margin ?? EdgeInsets.all(20),
25 | child: TextButton(
26 | style: TextButton.styleFrom(
27 | foregroundColor: isDark ? Colours.dark_button_text : Colors.white,
28 | backgroundColor: isDark ? Colours.dark_app_main : color,
29 | disabledForegroundColor: isDark ? Colours.dark_text_disabled : Colours.text_disabled,
30 | disabledBackgroundColor: isDark ? Colours.dark_button_disabled : Colours.button_disabled,
31 | ),
32 | onPressed: onPressed,
33 | //shape:RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
34 | child: Container(
35 | height: 48,
36 | width: double.infinity,
37 | alignment: Alignment.center,
38 | child: Text(
39 | text,
40 | style: TextStyle(fontSize: Dimens.font_sp18),
41 | ),
42 | ),
43 | ),
44 | );
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/lib/widget/view/my_card.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:flutter/material.dart';
3 | import 'package:flutterjdshop/res/colors.dart';
4 | import 'package:flutterjdshop/utils/theme_utils.dart';
5 |
6 |
7 | class MyCard extends StatelessWidget {
8 |
9 | const MyCard({
10 | Key? key,
11 | required this.child,
12 | this.color,
13 | this.shadowColor
14 | }): super(key: key);
15 |
16 | final Widget child;
17 | final Color? color;
18 | final Color? shadowColor;
19 |
20 | @override
21 | Widget build(BuildContext context) {
22 | Color? _backgroundColor;
23 | Color? _shadowColor;
24 | bool isDark = ThemeUtils.isDark(context);
25 | if (color == null) {
26 | _backgroundColor = isDark ? Colours.dark_bg_gray_ : Colors.white;
27 | } else {
28 | _backgroundColor = color;
29 | }
30 |
31 | if (shadowColor == null) {
32 | _shadowColor = isDark ? Colors.transparent : const Color(0x80DCE7FA);
33 | } else {
34 | _shadowColor = isDark ? Colors.transparent : shadowColor;
35 | }
36 |
37 | return DecoratedBox(
38 | decoration: BoxDecoration(
39 | color: _backgroundColor,
40 | borderRadius: BorderRadius.circular(8.0),
41 | boxShadow: [
42 | BoxShadow(color: _shadowColor!, offset: Offset(0.0, 2.0), blurRadius: 8.0, spreadRadius: 0.0),
43 | ]
44 | ),
45 | child: child,
46 | );
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/lib/widget/view/text_field_item.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:flutter/foundation.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter/services.dart';
5 | import 'package:flutterjdshop/res/gaps.dart';
6 | import 'package:flutterjdshop/utils/number_text_input_formatter.dart';
7 |
8 |
9 | /// 封装输入框
10 | class TextFieldItem extends StatelessWidget {
11 |
12 | const TextFieldItem({
13 | Key? key,
14 | this.controller,
15 | required this.title,
16 | this.keyboardType = TextInputType.text,
17 | this.hintText = '',
18 | this.focusNode,
19 | }): super(key: key);
20 |
21 | final TextEditingController? controller;
22 | final String title;
23 | final String hintText;
24 | final TextInputType keyboardType;
25 | final FocusNode? focusNode;
26 |
27 | @override
28 | Widget build(BuildContext context) {
29 | return Container(
30 | height: 50.0,
31 | margin: const EdgeInsets.only(left: 16.0),
32 | width: double.infinity,
33 | decoration: BoxDecoration(
34 | border: Border(
35 | bottom: Divider.createBorderSide(context, width: 0.6),
36 | )
37 | ),
38 | child: Row(
39 | children: [
40 | Text(title),
41 | Gaps.hGap16,
42 | Expanded(
43 | child: TextField(
44 | focusNode: focusNode,
45 | keyboardType: keyboardType,
46 | inputFormatters: _getInputFormatters(),
47 | controller: controller,
48 | //style: TextStyles.textDark14,
49 | decoration: InputDecoration(
50 | hintText: hintText,
51 | border: InputBorder.none, //去掉下划线
52 | //hintStyle: TextStyles.textGrayC14
53 | )
54 | ),
55 | ),
56 | Gaps.hGap16
57 | ],
58 | ),
59 | );
60 | }
61 |
62 | _getInputFormatters() {
63 | if (keyboardType == TextInputType.numberWithOptions(decimal: true)) {
64 | return [UsNumberTextInputFormatter()];
65 | }
66 | if (keyboardType == TextInputType.number || keyboardType == TextInputType.phone) {
67 | return [FilteringTextInputFormatter.digitsOnly];
68 | }
69 | return null;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/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 in the flutter_test package. For example, you can send tap and scroll
5 | // // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // // tree, read text, and verify that the values of widget properties are correct.
7 | //
8 | // import 'package:flutter/material.dart';
9 | // import 'package:flutter_test/flutter_test.dart';
10 | //
11 | // import 'package:flutter_jdshop_mvvm/main.dart';
12 | //
13 | // void main() {
14 | // testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 | // // Build our app and trigger a frame.
16 | // await tester.pumpWidget(const MyApp());
17 | //
18 | // // Verify that our counter starts at 0.
19 | // expect(find.text('0'), findsOneWidget);
20 | // expect(find.text('1'), findsNothing);
21 | //
22 | // // Tap the '+' icon and trigger a frame.
23 | // await tester.tap(find.byIcon(Icons.add));
24 | // await tester.pump();
25 | //
26 | // // Verify that our counter has incremented.
27 | // expect(find.text('0'), findsNothing);
28 | // expect(find.text('1'), findsOneWidget);
29 | // });
30 | // }
31 |
--------------------------------------------------------------------------------