Browse Source

'首次提交'

mq 1 year ago
commit
e0f818700e
100 changed files with 3866 additions and 0 deletions
  1. 44 0
      .gitignore
  2. 45 0
      .metadata
  3. 16 0
      README.md
  4. 28 0
      analysis_options.yaml
  5. 13 0
      android/.gitignore
  6. 74 0
      android/app/build.gradle
  7. 7 0
      android/app/src/debug/AndroidManifest.xml
  8. 34 0
      android/app/src/main/AndroidManifest.xml
  9. 6 0
      android/app/src/main/java/com/szls/lszlgl/MainActivity.java
  10. 12 0
      android/app/src/main/res/drawable-v21/launch_background.xml
  11. 12 0
      android/app/src/main/res/drawable/launch_background.xml
  12. BIN
      android/app/src/main/res/mipmap-hdpi/ic_launcher.png
  13. BIN
      android/app/src/main/res/mipmap-mdpi/ic_launcher.png
  14. BIN
      android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
  15. BIN
      android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  16. BIN
      android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  17. 18 0
      android/app/src/main/res/values-night/styles.xml
  18. 18 0
      android/app/src/main/res/values/styles.xml
  19. 7 0
      android/app/src/profile/AndroidManifest.xml
  20. 31 0
      android/build.gradle
  21. 9 0
      android/gradle.properties
  22. 5 0
      android/gradle/wrapper/gradle-wrapper.properties
  23. 20 0
      android/settings.gradle
  24. BIN
      assets/images/home_list_bg.webp
  25. BIN
      assets/images/home_list_pzjc.webp
  26. BIN
      assets/images/home_list_zcjy.webp
  27. BIN
      assets/images/home_top_bg.webp
  28. BIN
      assets/images/item_arrow_down.webp
  29. BIN
      assets/images/item_arrow_right.webp
  30. BIN
      assets/images/login_account.webp
  31. BIN
      assets/images/login_bg.webp
  32. BIN
      assets/images/login_pwd.webp
  33. BIN
      assets/images/login_title.webp
  34. BIN
      assets/images/nav_home.webp
  35. BIN
      assets/images/nav_home_select.webp
  36. BIN
      assets/images/nav_user_center.webp
  37. BIN
      assets/images/nav_user_center_select.webp
  38. BIN
      assets/images/user_center_account.webp
  39. BIN
      assets/images/user_center_setting.webp
  40. 34 0
      ios/.gitignore
  41. 26 0
      ios/Flutter/AppFrameworkInfo.plist
  42. 1 0
      ios/Flutter/Debug.xcconfig
  43. 1 0
      ios/Flutter/Release.xcconfig
  44. 614 0
      ios/Runner.xcodeproj/project.pbxproj
  45. 7 0
      ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  46. 8 0
      ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  47. 8 0
      ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
  48. 98 0
      ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
  49. 7 0
      ios/Runner.xcworkspace/contents.xcworkspacedata
  50. 8 0
      ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  51. 8 0
      ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
  52. 13 0
      ios/Runner/AppDelegate.swift
  53. 122 0
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
  54. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
  55. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
  56. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
  57. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
  58. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
  59. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
  60. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
  61. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
  62. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
  63. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
  64. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
  65. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
  66. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
  67. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
  68. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
  69. 23 0
      ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
  70. BIN
      ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
  71. BIN
      ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
  72. BIN
      ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
  73. 5 0
      ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
  74. 37 0
      ios/Runner/Base.lproj/LaunchScreen.storyboard
  75. 26 0
      ios/Runner/Base.lproj/Main.storyboard
  76. 49 0
      ios/Runner/Info.plist
  77. 1 0
      ios/Runner/Runner-Bridging-Header.h
  78. 12 0
      ios/RunnerTests/RunnerTests.swift
  79. 41 0
      lib/base/base_state.dart
  80. 15 0
      lib/config/colors.dart
  81. 35 0
      lib/config/pics.dart
  82. 99 0
      lib/main.dart
  83. 163 0
      lib/page/home/home_page.dart
  84. 207 0
      lib/page/login/login_page.dart
  85. 123 0
      lib/page/main_tab_page.dart
  86. 63 0
      lib/page/reap_step/reap_sample_detail/reap_sample_basic_detail_page.dart
  87. 61 0
      lib/page/reap_step/reap_sample_detail/reap_sample_disaster_detail_page.dart
  88. 94 0
      lib/page/reap_step/reap_sample_detail/reap_sample_medicine_detail_page.dart
  89. 52 0
      lib/page/reap_step/reap_sample_detail/reap_sample_org_detail_page.dart
  90. 61 0
      lib/page/reap_step/reap_sample_detail/reap_sample_variety_detail_page.dart
  91. 140 0
      lib/page/reap_step/reap_sample_task/reap_sample_basic_page.dart
  92. 195 0
      lib/page/reap_step/reap_sample_task/reap_sample_disaster_page.dart
  93. 191 0
      lib/page/reap_step/reap_sample_task/reap_sample_medicine_page.dart
  94. 72 0
      lib/page/reap_step/reap_sample_task/reap_sample_org_page.dart
  95. 189 0
      lib/page/reap_step/reap_sample_task/reap_sample_task_page.dart
  96. 185 0
      lib/page/reap_step/reap_sample_task/reap_sample_variety_page.dart
  97. 232 0
      lib/page/reap_step/reap_step_list_page.dart
  98. 119 0
      lib/page/reap_step/reap_step_tab_page.dart
  99. 22 0
      lib/page/unknow_page.dart
  100. 0 0
      lib/page/user_center/account_manage_page.dart

+ 44 - 0
.gitignore

@@ -0,0 +1,44 @@
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
+.packages
31
+.pub-cache/
32
+.pub/
33
+/build/
34
+
35
+# Symbolication related
36
+app.*.symbols
37
+
38
+# Obfuscation related
39
+app.*.map.json
40
+
41
+# Android Studio will place build artifacts here
42
+/android/app/debug
43
+/android/app/profile
44
+/android/app/release

+ 45 - 0
.metadata

@@ -0,0 +1,45 @@
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: "d211f42860350d914a5ad8102f9ec32764dc6d06"
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: d211f42860350d914a5ad8102f9ec32764dc6d06
17
+      base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
18
+    - platform: android
19
+      create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
20
+      base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
21
+    - platform: ios
22
+      create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
23
+      base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
24
+    - platform: linux
25
+      create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
26
+      base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
27
+    - platform: macos
28
+      create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
29
+      base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
30
+    - platform: web
31
+      create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
32
+      base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
33
+    - platform: windows
34
+      create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
35
+      base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
36
+
37
+  # User provided section
38
+
39
+  # List of Local paths (relative to this file) that should be
40
+  # ignored by the migrate tool.
41
+  #
42
+  # Files that are not part of the templates will be ignored by default.
43
+  unmanaged_files:
44
+    - 'lib/main.dart'
45
+    - 'ios/Runner.xcodeproj/project.pbxproj'

+ 16 - 0
README.md

@@ -0,0 +1,16 @@
1
+# lszlgl
2
+
3
+A new Flutter project.
4
+
5
+## Getting Started
6
+
7
+This project is a starting point for a Flutter application.
8
+
9
+A few resources to get you started if this is your first Flutter project:
10
+
11
+- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
12
+- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
13
+
14
+For help getting started with Flutter development, view the
15
+[online documentation](https://docs.flutter.dev/), which offers tutorials,
16
+samples, guidance on mobile development, and a full API reference.

+ 28 - 0
analysis_options.yaml

@@ -0,0 +1,28 @@
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

+ 13 - 0
android/.gitignore

@@ -0,0 +1,13 @@
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

+ 74 - 0
android/app/build.gradle

@@ -0,0 +1,74 @@
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.szls.lszlgl"
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
+    defaultConfig {
36
+        applicationId "com.szls.lszlgl"
37
+        // You can update the following values to match your application needs.
38
+        // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
39
+        minSdkVersion flutter.minSdkVersion
40
+        targetSdkVersion flutter.targetSdkVersion
41
+        versionCode flutterVersionCode.toInteger()
42
+        versionName flutterVersionName
43
+    }
44
+
45
+    // 签名配置
46
+    signingConfigs {
47
+        release {
48
+            v1SigningEnabled true
49
+            v2SigningEnabled true
50
+
51
+            storeFile file(KEY_PATH)
52
+            storePassword KEY_PWD
53
+            keyAlias = ALIAS_NAME
54
+            keyPassword ALIAS_PWD
55
+        }
56
+    }
57
+
58
+    buildTypes {
59
+        release {
60
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
61
+            signingConfig signingConfigs.release
62
+        }
63
+        profile {
64
+            signingConfig signingConfigs.release
65
+        }
66
+        debug {
67
+            signingConfig signingConfigs.release
68
+        }
69
+    }
70
+}
71
+
72
+flutter {
73
+    source '../..'
74
+}

+ 7 - 0
android/app/src/debug/AndroidManifest.xml

@@ -0,0 +1,7 @@
1
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+    <!-- The INTERNET permission is required for development. Specifically,
3
+         the Flutter tool needs it to communicate with the running application
4
+         to allow setting breakpoints, to provide hot reload, etc.
5
+    -->
6
+    <uses-permission android:name="android.permission.INTERNET"/>
7
+</manifest>

+ 34 - 0
android/app/src/main/AndroidManifest.xml

@@ -0,0 +1,34 @@
1
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+    <uses-permission android:name="android.permission.INTERNET"/>
3
+    <application
4
+        android:label="粮食质量管理"
5
+        android:name="${applicationName}"
6
+        android:icon="@mipmap/ic_launcher">
7
+        <activity
8
+            android:name=".MainActivity"
9
+            android:exported="true"
10
+            android:launchMode="singleTop"
11
+            android:theme="@style/LaunchTheme"
12
+            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
13
+            android:hardwareAccelerated="true"
14
+            android:windowSoftInputMode="adjustResize">
15
+            <!-- Specifies an Android theme to apply to this Activity as soon as
16
+                 the Android process has started. This theme is visible to the user
17
+                 while the Flutter UI initializes. After that, this theme continues
18
+                 to determine the Window background behind the Flutter UI. -->
19
+            <meta-data
20
+              android:name="io.flutter.embedding.android.NormalTheme"
21
+              android:resource="@style/NormalTheme"
22
+              />
23
+            <intent-filter>
24
+                <action android:name="android.intent.action.MAIN"/>
25
+                <category android:name="android.intent.category.LAUNCHER"/>
26
+            </intent-filter>
27
+        </activity>
28
+        <!-- Don't delete the meta-data below.
29
+             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
30
+        <meta-data
31
+            android:name="flutterEmbedding"
32
+            android:value="2" />
33
+    </application>
34
+</manifest>

+ 6 - 0
android/app/src/main/java/com/szls/lszlgl/MainActivity.java

@@ -0,0 +1,6 @@
1
+package com.szls.lszlgl;
2
+
3
+import io.flutter.embedding.android.FlutterActivity;
4
+
5
+public class MainActivity extends FlutterActivity {
6
+}

+ 12 - 0
android/app/src/main/res/drawable-v21/launch_background.xml

@@ -0,0 +1,12 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!-- Modify this file to customize your launch splash screen -->
3
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
4
+    <item android:drawable="?android:colorBackground" />
5
+
6
+    <!-- You can insert your own image assets here -->
7
+    <!-- <item>
8
+        <bitmap
9
+            android:gravity="center"
10
+            android:src="@mipmap/launch_image" />
11
+    </item> -->
12
+</layer-list>

+ 12 - 0
android/app/src/main/res/drawable/launch_background.xml

@@ -0,0 +1,12 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!-- Modify this file to customize your launch splash screen -->
3
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
4
+    <item android:drawable="@android:color/white" />
5
+
6
+    <!-- You can insert your own image assets here -->
7
+    <!-- <item>
8
+        <bitmap
9
+            android:gravity="center"
10
+            android:src="@mipmap/launch_image" />
11
+    </item> -->
12
+</layer-list>

BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher.png


BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher.png


BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher.png


BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png


BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png


+ 18 - 0
android/app/src/main/res/values-night/styles.xml

@@ -0,0 +1,18 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<resources>
3
+    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
4
+    <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
5
+        <!-- Show a splash screen on the activity. Automatically removed when
6
+             the Flutter engine draws its first frame -->
7
+        <item name="android:windowBackground">@drawable/launch_background</item>
8
+    </style>
9
+    <!-- Theme applied to the Android Window as soon as the process has started.
10
+         This theme determines the color of the Android Window while your
11
+         Flutter UI initializes, as well as behind your Flutter UI while its
12
+         running.
13
+
14
+         This Theme is only used starting with V2 of Flutter's Android embedding. -->
15
+    <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
16
+        <item name="android:windowBackground">?android:colorBackground</item>
17
+    </style>
18
+</resources>

+ 18 - 0
android/app/src/main/res/values/styles.xml

@@ -0,0 +1,18 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<resources>
3
+    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
4
+    <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
5
+        <!-- Show a splash screen on the activity. Automatically removed when
6
+             the Flutter engine draws its first frame -->
7
+        <item name="android:windowBackground">@drawable/launch_background</item>
8
+    </style>
9
+    <!-- Theme applied to the Android Window as soon as the process has started.
10
+         This theme determines the color of the Android Window while your
11
+         Flutter UI initializes, as well as behind your Flutter UI while its
12
+         running.
13
+
14
+         This Theme is only used starting with V2 of Flutter's Android embedding. -->
15
+    <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
16
+        <item name="android:windowBackground">?android:colorBackground</item>
17
+    </style>
18
+</resources>

+ 7 - 0
android/app/src/profile/AndroidManifest.xml

@@ -0,0 +1,7 @@
1
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+    <!-- The INTERNET permission is required for development. Specifically,
3
+         the Flutter tool needs it to communicate with the running application
4
+         to allow setting breakpoints, to provide hot reload, etc.
5
+    -->
6
+    <uses-permission android:name="android.permission.INTERNET"/>
7
+</manifest>

+ 31 - 0
android/build.gradle

@@ -0,0 +1,31 @@
1
+buildscript {
2
+    ext.kotlin_version = '1.7.10'
3
+    repositories {
4
+        google()
5
+        mavenCentral()
6
+    }
7
+
8
+    dependencies {
9
+        classpath 'com.android.tools.build:gradle:7.3.0'
10
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11
+    }
12
+}
13
+
14
+allprojects {
15
+    repositories {
16
+        google()
17
+        mavenCentral()
18
+    }
19
+}
20
+
21
+rootProject.buildDir = '../build'
22
+subprojects {
23
+    project.buildDir = "${rootProject.buildDir}/${project.name}"
24
+}
25
+subprojects {
26
+    project.evaluationDependsOn(':app')
27
+}
28
+
29
+tasks.register("clean", Delete) {
30
+    delete rootProject.buildDir
31
+}

+ 9 - 0
android/gradle.properties

@@ -0,0 +1,9 @@
1
+org.gradle.jvmargs=-Xmx1536M
2
+android.useAndroidX=true
3
+android.enableJetifier=true
4
+
5
+# SigningConfigs
6
+KEY_PATH=../keystore.jks
7
+KEY_PWD=lszlgl123
8
+ALIAS_NAME=lszlgl
9
+ALIAS_PWD=lszlgl123

+ 5 - 0
android/gradle/wrapper/gradle-wrapper.properties

@@ -0,0 +1,5 @@
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

+ 20 - 0
android/settings.gradle

@@ -0,0 +1,20 @@
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
+    plugins {
14
+        id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false
15
+    }
16
+}
17
+
18
+include ":app"
19
+
20
+apply from: "${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle/app_plugin_loader.gradle"

BIN
assets/images/home_list_bg.webp


BIN
assets/images/home_list_pzjc.webp


BIN
assets/images/home_list_zcjy.webp


BIN
assets/images/home_top_bg.webp


BIN
assets/images/item_arrow_down.webp


BIN
assets/images/item_arrow_right.webp


BIN
assets/images/login_account.webp


BIN
assets/images/login_bg.webp


BIN
assets/images/login_pwd.webp


BIN
assets/images/login_title.webp


BIN
assets/images/nav_home.webp


BIN
assets/images/nav_home_select.webp


BIN
assets/images/nav_user_center.webp


BIN
assets/images/nav_user_center_select.webp


BIN
assets/images/user_center_account.webp


BIN
assets/images/user_center_setting.webp


+ 34 - 0
ios/.gitignore

@@ -0,0 +1,34 @@
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

+ 26 - 0
ios/Flutter/AppFrameworkInfo.plist

@@ -0,0 +1,26 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+  <key>CFBundleDevelopmentRegion</key>
6
+  <string>en</string>
7
+  <key>CFBundleExecutable</key>
8
+  <string>App</string>
9
+  <key>CFBundleIdentifier</key>
10
+  <string>io.flutter.flutter.app</string>
11
+  <key>CFBundleInfoDictionaryVersion</key>
12
+  <string>6.0</string>
13
+  <key>CFBundleName</key>
14
+  <string>App</string>
15
+  <key>CFBundlePackageType</key>
16
+  <string>FMWK</string>
17
+  <key>CFBundleShortVersionString</key>
18
+  <string>1.0</string>
19
+  <key>CFBundleSignature</key>
20
+  <string>????</string>
21
+  <key>CFBundleVersion</key>
22
+  <string>1.0</string>
23
+  <key>MinimumOSVersion</key>
24
+  <string>11.0</string>
25
+</dict>
26
+</plist>

+ 1 - 0
ios/Flutter/Debug.xcconfig

@@ -0,0 +1 @@
1
+#include "Generated.xcconfig"

+ 1 - 0
ios/Flutter/Release.xcconfig

@@ -0,0 +1 @@
1
+#include "Generated.xcconfig"

+ 614 - 0
ios/Runner.xcodeproj/project.pbxproj

@@ -0,0 +1,614 @@
1
+// !$*UTF8*$!
2
+{
3
+	archiveVersion = 1;
4
+	classes = {
5
+	};
6
+	objectVersion = 54;
7
+	objects = {
8
+
9
+/* Begin PBXBuildFile section */
10
+		1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11
+		3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
12
+		74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
13
+		97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
14
+		97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
15
+		97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
16
+		331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
17
+/* End PBXBuildFile section */
18
+
19
+/* Begin PBXContainerItemProxy section */
20
+		331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
21
+			isa = PBXContainerItemProxy;
22
+			containerPortal = 97C146E61CF9000F007C117D /* Project object */;
23
+			proxyType = 1;
24
+			remoteGlobalIDString = 97C146ED1CF9000F007C117D;
25
+			remoteInfo = Runner;
26
+		};
27
+/* End PBXContainerItemProxy section */
28
+
29
+/* Begin PBXCopyFilesBuildPhase section */
30
+		9705A1C41CF9048500538489 /* Embed Frameworks */ = {
31
+			isa = PBXCopyFilesBuildPhase;
32
+			buildActionMask = 2147483647;
33
+			dstPath = "";
34
+			dstSubfolderSpec = 10;
35
+			files = (
36
+			);
37
+			name = "Embed Frameworks";
38
+			runOnlyForDeploymentPostprocessing = 0;
39
+		};
40
+/* End PBXCopyFilesBuildPhase section */
41
+
42
+/* Begin PBXFileReference section */
43
+		1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
44
+		1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
45
+		3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
46
+		74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
47
+		74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
48
+		7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
49
+		9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
50
+		9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
51
+		97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
52
+		97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
53
+		97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
54
+		97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
55
+		97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
56
+		331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
57
+		331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
58
+/* End PBXFileReference section */
59
+
60
+/* Begin PBXFrameworksBuildPhase section */
61
+		97C146EB1CF9000F007C117D /* Frameworks */ = {
62
+			isa = PBXFrameworksBuildPhase;
63
+			buildActionMask = 2147483647;
64
+			files = (
65
+			);
66
+			runOnlyForDeploymentPostprocessing = 0;
67
+		};
68
+/* End PBXFrameworksBuildPhase section */
69
+
70
+/* Begin PBXGroup section */
71
+		9740EEB11CF90186004384FC /* Flutter */ = {
72
+			isa = PBXGroup;
73
+			children = (
74
+				3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
75
+				9740EEB21CF90195004384FC /* Debug.xcconfig */,
76
+				7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
77
+				9740EEB31CF90195004384FC /* Generated.xcconfig */,
78
+			);
79
+			name = Flutter;
80
+			sourceTree = "<group>";
81
+		};
82
+		331C8082294A63A400263BE5 /* RunnerTests */ = {
83
+			isa = PBXGroup;
84
+			children = (
85
+				331C807B294A618700263BE5 /* RunnerTests.swift */,
86
+			);
87
+			path = RunnerTests;
88
+			sourceTree = "<group>";
89
+		};
90
+		97C146E51CF9000F007C117D = {
91
+			isa = PBXGroup;
92
+			children = (
93
+				9740EEB11CF90186004384FC /* Flutter */,
94
+				97C146F01CF9000F007C117D /* Runner */,
95
+				97C146EF1CF9000F007C117D /* Products */,
96
+				331C8082294A63A400263BE5 /* RunnerTests */,
97
+			);
98
+			sourceTree = "<group>";
99
+		};
100
+		97C146EF1CF9000F007C117D /* Products */ = {
101
+			isa = PBXGroup;
102
+			children = (
103
+				97C146EE1CF9000F007C117D /* Runner.app */,
104
+				331C8081294A63A400263BE5 /* RunnerTests.xctest */,
105
+			);
106
+			name = Products;
107
+			sourceTree = "<group>";
108
+		};
109
+		97C146F01CF9000F007C117D /* Runner */ = {
110
+			isa = PBXGroup;
111
+			children = (
112
+				97C146FA1CF9000F007C117D /* Main.storyboard */,
113
+				97C146FD1CF9000F007C117D /* Assets.xcassets */,
114
+				97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
115
+				97C147021CF9000F007C117D /* Info.plist */,
116
+				1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
117
+				1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
118
+				74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
119
+				74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
120
+			);
121
+			path = Runner;
122
+			sourceTree = "<group>";
123
+		};
124
+/* End PBXGroup section */
125
+
126
+/* Begin PBXNativeTarget section */
127
+		331C8080294A63A400263BE5 /* RunnerTests */ = {
128
+			isa = PBXNativeTarget;
129
+			buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
130
+			buildPhases = (
131
+				331C807D294A63A400263BE5 /* Sources */,
132
+				331C807E294A63A400263BE5 /* Frameworks */,
133
+				331C807F294A63A400263BE5 /* Resources */,
134
+			);
135
+			buildRules = (
136
+			);
137
+			dependencies = (
138
+				331C8086294A63A400263BE5 /* PBXTargetDependency */,
139
+			);
140
+			name = RunnerTests;
141
+			productName = RunnerTests;
142
+			productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
143
+			productType = "com.apple.product-type.bundle.unit-test";
144
+		};
145
+		97C146ED1CF9000F007C117D /* Runner */ = {
146
+			isa = PBXNativeTarget;
147
+			buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
148
+			buildPhases = (
149
+				9740EEB61CF901F6004384FC /* Run Script */,
150
+				97C146EA1CF9000F007C117D /* Sources */,
151
+				97C146EB1CF9000F007C117D /* Frameworks */,
152
+				97C146EC1CF9000F007C117D /* Resources */,
153
+				9705A1C41CF9048500538489 /* Embed Frameworks */,
154
+				3B06AD1E1E4923F5004D2608 /* Thin Binary */,
155
+			);
156
+			buildRules = (
157
+			);
158
+			dependencies = (
159
+			);
160
+			name = Runner;
161
+			productName = Runner;
162
+			productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
163
+			productType = "com.apple.product-type.application";
164
+		};
165
+/* End PBXNativeTarget section */
166
+
167
+/* Begin PBXProject section */
168
+		97C146E61CF9000F007C117D /* Project object */ = {
169
+			isa = PBXProject;
170
+			attributes = {
171
+				BuildIndependentTargetsInParallel = YES;
172
+				LastUpgradeCheck = 1430;
173
+				ORGANIZATIONNAME = "";
174
+				TargetAttributes = {
175
+					331C8080294A63A400263BE5 = {
176
+						CreatedOnToolsVersion = 14.0;
177
+						TestTargetID = 97C146ED1CF9000F007C117D;
178
+					};
179
+					97C146ED1CF9000F007C117D = {
180
+						CreatedOnToolsVersion = 7.3.1;
181
+						LastSwiftMigration = 1100;
182
+					};
183
+				};
184
+			};
185
+			buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
186
+			compatibilityVersion = "Xcode 9.3";
187
+			developmentRegion = en;
188
+			hasScannedForEncodings = 0;
189
+			knownRegions = (
190
+				en,
191
+				Base,
192
+			);
193
+			mainGroup = 97C146E51CF9000F007C117D;
194
+			productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
195
+			projectDirPath = "";
196
+			projectRoot = "";
197
+			targets = (
198
+				97C146ED1CF9000F007C117D /* Runner */,
199
+				331C8080294A63A400263BE5 /* RunnerTests */,
200
+			);
201
+		};
202
+/* End PBXProject section */
203
+
204
+/* Begin PBXResourcesBuildPhase section */
205
+		331C807F294A63A400263BE5 /* Resources */ = {
206
+			isa = PBXResourcesBuildPhase;
207
+			buildActionMask = 2147483647;
208
+			files = (
209
+			);
210
+			runOnlyForDeploymentPostprocessing = 0;
211
+		};
212
+		97C146EC1CF9000F007C117D /* Resources */ = {
213
+			isa = PBXResourcesBuildPhase;
214
+			buildActionMask = 2147483647;
215
+			files = (
216
+				97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
217
+				3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
218
+				97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
219
+				97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
220
+			);
221
+			runOnlyForDeploymentPostprocessing = 0;
222
+		};
223
+/* End PBXResourcesBuildPhase section */
224
+
225
+/* Begin PBXShellScriptBuildPhase section */
226
+		3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
227
+			isa = PBXShellScriptBuildPhase;
228
+			alwaysOutOfDate = 1;
229
+			buildActionMask = 2147483647;
230
+			files = (
231
+			);
232
+			inputPaths = (
233
+				"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
234
+			);
235
+			name = "Thin Binary";
236
+			outputPaths = (
237
+			);
238
+			runOnlyForDeploymentPostprocessing = 0;
239
+			shellPath = /bin/sh;
240
+			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
241
+		};
242
+		9740EEB61CF901F6004384FC /* Run Script */ = {
243
+			isa = PBXShellScriptBuildPhase;
244
+			alwaysOutOfDate = 1;
245
+			buildActionMask = 2147483647;
246
+			files = (
247
+			);
248
+			inputPaths = (
249
+			);
250
+			name = "Run Script";
251
+			outputPaths = (
252
+			);
253
+			runOnlyForDeploymentPostprocessing = 0;
254
+			shellPath = /bin/sh;
255
+			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
256
+		};
257
+/* End PBXShellScriptBuildPhase section */
258
+
259
+/* Begin PBXSourcesBuildPhase section */
260
+		331C807D294A63A400263BE5 /* Sources */ = {
261
+			isa = PBXSourcesBuildPhase;
262
+			buildActionMask = 2147483647;
263
+			files = (
264
+				331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
265
+			);
266
+			runOnlyForDeploymentPostprocessing = 0;
267
+		};
268
+		97C146EA1CF9000F007C117D /* Sources */ = {
269
+			isa = PBXSourcesBuildPhase;
270
+			buildActionMask = 2147483647;
271
+			files = (
272
+				74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
273
+				1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
274
+			);
275
+			runOnlyForDeploymentPostprocessing = 0;
276
+		};
277
+/* End PBXSourcesBuildPhase section */
278
+
279
+/* Begin PBXTargetDependency section */
280
+		331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
281
+			isa = PBXTargetDependency;
282
+			target = 97C146ED1CF9000F007C117D /* Runner */;
283
+			targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
284
+		};
285
+/* End PBXTargetDependency section */
286
+
287
+/* Begin PBXVariantGroup section */
288
+		97C146FA1CF9000F007C117D /* Main.storyboard */ = {
289
+			isa = PBXVariantGroup;
290
+			children = (
291
+				97C146FB1CF9000F007C117D /* Base */,
292
+			);
293
+			name = Main.storyboard;
294
+			sourceTree = "<group>";
295
+		};
296
+		97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
297
+			isa = PBXVariantGroup;
298
+			children = (
299
+				97C147001CF9000F007C117D /* Base */,
300
+			);
301
+			name = LaunchScreen.storyboard;
302
+			sourceTree = "<group>";
303
+		};
304
+/* End PBXVariantGroup section */
305
+
306
+/* Begin XCBuildConfiguration section */
307
+		249021D3217E4FDB00AE95B9 /* Profile */ = {
308
+			isa = XCBuildConfiguration;
309
+			buildSettings = {
310
+				ALWAYS_SEARCH_USER_PATHS = NO;
311
+				CLANG_ANALYZER_NONNULL = YES;
312
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
313
+				CLANG_CXX_LIBRARY = "libc++";
314
+				CLANG_ENABLE_MODULES = YES;
315
+				CLANG_ENABLE_OBJC_ARC = YES;
316
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
317
+				CLANG_WARN_BOOL_CONVERSION = YES;
318
+				CLANG_WARN_COMMA = YES;
319
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
320
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
321
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
322
+				CLANG_WARN_EMPTY_BODY = YES;
323
+				CLANG_WARN_ENUM_CONVERSION = YES;
324
+				CLANG_WARN_INFINITE_RECURSION = YES;
325
+				CLANG_WARN_INT_CONVERSION = YES;
326
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
327
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
328
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
329
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
330
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
331
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
332
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
333
+				CLANG_WARN_UNREACHABLE_CODE = YES;
334
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
335
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
336
+				COPY_PHASE_STRIP = NO;
337
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
338
+				ENABLE_NS_ASSERTIONS = NO;
339
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
340
+				GCC_C_LANGUAGE_STANDARD = gnu99;
341
+				GCC_NO_COMMON_BLOCKS = YES;
342
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
343
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
344
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
345
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
346
+				GCC_WARN_UNUSED_FUNCTION = YES;
347
+				GCC_WARN_UNUSED_VARIABLE = YES;
348
+				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
349
+				MTL_ENABLE_DEBUG_INFO = NO;
350
+				SDKROOT = iphoneos;
351
+				SUPPORTED_PLATFORMS = iphoneos;
352
+				TARGETED_DEVICE_FAMILY = "1,2";
353
+				VALIDATE_PRODUCT = YES;
354
+			};
355
+			name = Profile;
356
+		};
357
+		249021D4217E4FDB00AE95B9 /* Profile */ = {
358
+			isa = XCBuildConfiguration;
359
+			baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
360
+			buildSettings = {
361
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
362
+				CLANG_ENABLE_MODULES = YES;
363
+				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
364
+				ENABLE_BITCODE = NO;
365
+				INFOPLIST_FILE = Runner/Info.plist;
366
+				LD_RUNPATH_SEARCH_PATHS = (
367
+					"$(inherited)",
368
+					"@executable_path/Frameworks",
369
+				);
370
+				PRODUCT_BUNDLE_IDENTIFIER = com.szls.lszlgl;
371
+				PRODUCT_NAME = "$(TARGET_NAME)";
372
+				SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
373
+				SWIFT_VERSION = 5.0;
374
+				VERSIONING_SYSTEM = "apple-generic";
375
+			};
376
+			name = Profile;
377
+		};
378
+		331C8088294A63A400263BE5 /* Debug */ = {
379
+			isa = XCBuildConfiguration;
380
+			baseConfigurationReference = AE0B7B92F70575B8D7E0D07E /* Pods-RunnerTests.debug.xcconfig */;
381
+			buildSettings = {
382
+				BUNDLE_LOADER = "$(TEST_HOST)";
383
+				CODE_SIGN_STYLE = Automatic;
384
+				CURRENT_PROJECT_VERSION = 1;
385
+				GENERATE_INFOPLIST_FILE = YES;
386
+				MARKETING_VERSION = 1.0;
387
+				PRODUCT_BUNDLE_IDENTIFIER = com.szls.lszlgl.RunnerTests;
388
+				PRODUCT_NAME = "$(TARGET_NAME)";
389
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
390
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
391
+				SWIFT_VERSION = 5.0;
392
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
393
+			};
394
+			name = Debug;
395
+		};
396
+		331C8089294A63A400263BE5 /* Release */ = {
397
+			isa = XCBuildConfiguration;
398
+			baseConfigurationReference = 89B67EB44CE7B6631473024E /* Pods-RunnerTests.release.xcconfig */;
399
+			buildSettings = {
400
+				BUNDLE_LOADER = "$(TEST_HOST)";
401
+				CODE_SIGN_STYLE = Automatic;
402
+				CURRENT_PROJECT_VERSION = 1;
403
+				GENERATE_INFOPLIST_FILE = YES;
404
+				MARKETING_VERSION = 1.0;
405
+				PRODUCT_BUNDLE_IDENTIFIER = com.szls.lszlgl.RunnerTests;
406
+				PRODUCT_NAME = "$(TARGET_NAME)";
407
+				SWIFT_VERSION = 5.0;
408
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
409
+			};
410
+			name = Release;
411
+		};
412
+		331C808A294A63A400263BE5 /* Profile */ = {
413
+			isa = XCBuildConfiguration;
414
+			baseConfigurationReference = 640959BDD8F10B91D80A66BE /* Pods-RunnerTests.profile.xcconfig */;
415
+			buildSettings = {
416
+				BUNDLE_LOADER = "$(TEST_HOST)";
417
+				CODE_SIGN_STYLE = Automatic;
418
+				CURRENT_PROJECT_VERSION = 1;
419
+				GENERATE_INFOPLIST_FILE = YES;
420
+				MARKETING_VERSION = 1.0;
421
+				PRODUCT_BUNDLE_IDENTIFIER = com.szls.lszlgl.RunnerTests;
422
+				PRODUCT_NAME = "$(TARGET_NAME)";
423
+				SWIFT_VERSION = 5.0;
424
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
425
+			};
426
+			name = Profile;
427
+		};
428
+		97C147031CF9000F007C117D /* Debug */ = {
429
+			isa = XCBuildConfiguration;
430
+			buildSettings = {
431
+				ALWAYS_SEARCH_USER_PATHS = NO;
432
+				CLANG_ANALYZER_NONNULL = YES;
433
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
434
+				CLANG_CXX_LIBRARY = "libc++";
435
+				CLANG_ENABLE_MODULES = YES;
436
+				CLANG_ENABLE_OBJC_ARC = YES;
437
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
438
+				CLANG_WARN_BOOL_CONVERSION = YES;
439
+				CLANG_WARN_COMMA = YES;
440
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
441
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
442
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
443
+				CLANG_WARN_EMPTY_BODY = YES;
444
+				CLANG_WARN_ENUM_CONVERSION = YES;
445
+				CLANG_WARN_INFINITE_RECURSION = YES;
446
+				CLANG_WARN_INT_CONVERSION = YES;
447
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
448
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
449
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
450
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
451
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
452
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
453
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
454
+				CLANG_WARN_UNREACHABLE_CODE = YES;
455
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
456
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
457
+				COPY_PHASE_STRIP = NO;
458
+				DEBUG_INFORMATION_FORMAT = dwarf;
459
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
460
+				ENABLE_TESTABILITY = YES;
461
+				GCC_C_LANGUAGE_STANDARD = gnu99;
462
+				GCC_DYNAMIC_NO_PIC = NO;
463
+				GCC_NO_COMMON_BLOCKS = YES;
464
+				GCC_OPTIMIZATION_LEVEL = 0;
465
+				GCC_PREPROCESSOR_DEFINITIONS = (
466
+					"DEBUG=1",
467
+					"$(inherited)",
468
+				);
469
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
470
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
471
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
472
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
473
+				GCC_WARN_UNUSED_FUNCTION = YES;
474
+				GCC_WARN_UNUSED_VARIABLE = YES;
475
+				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
476
+				MTL_ENABLE_DEBUG_INFO = YES;
477
+				ONLY_ACTIVE_ARCH = YES;
478
+				SDKROOT = iphoneos;
479
+				TARGETED_DEVICE_FAMILY = "1,2";
480
+			};
481
+			name = Debug;
482
+		};
483
+		97C147041CF9000F007C117D /* Release */ = {
484
+			isa = XCBuildConfiguration;
485
+			buildSettings = {
486
+				ALWAYS_SEARCH_USER_PATHS = NO;
487
+				CLANG_ANALYZER_NONNULL = YES;
488
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
489
+				CLANG_CXX_LIBRARY = "libc++";
490
+				CLANG_ENABLE_MODULES = YES;
491
+				CLANG_ENABLE_OBJC_ARC = YES;
492
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
493
+				CLANG_WARN_BOOL_CONVERSION = YES;
494
+				CLANG_WARN_COMMA = YES;
495
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
496
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
497
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
498
+				CLANG_WARN_EMPTY_BODY = YES;
499
+				CLANG_WARN_ENUM_CONVERSION = YES;
500
+				CLANG_WARN_INFINITE_RECURSION = YES;
501
+				CLANG_WARN_INT_CONVERSION = YES;
502
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
503
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
504
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
505
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
506
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
507
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
508
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
509
+				CLANG_WARN_UNREACHABLE_CODE = YES;
510
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
511
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
512
+				COPY_PHASE_STRIP = NO;
513
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
514
+				ENABLE_NS_ASSERTIONS = NO;
515
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
516
+				GCC_C_LANGUAGE_STANDARD = gnu99;
517
+				GCC_NO_COMMON_BLOCKS = YES;
518
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
519
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
520
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
521
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
522
+				GCC_WARN_UNUSED_FUNCTION = YES;
523
+				GCC_WARN_UNUSED_VARIABLE = YES;
524
+				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
525
+				MTL_ENABLE_DEBUG_INFO = NO;
526
+				SDKROOT = iphoneos;
527
+				SUPPORTED_PLATFORMS = iphoneos;
528
+				SWIFT_COMPILATION_MODE = wholemodule;
529
+				SWIFT_OPTIMIZATION_LEVEL = "-O";
530
+				TARGETED_DEVICE_FAMILY = "1,2";
531
+				VALIDATE_PRODUCT = YES;
532
+			};
533
+			name = Release;
534
+		};
535
+		97C147061CF9000F007C117D /* Debug */ = {
536
+			isa = XCBuildConfiguration;
537
+			baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
538
+			buildSettings = {
539
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
540
+				CLANG_ENABLE_MODULES = YES;
541
+				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
542
+				ENABLE_BITCODE = NO;
543
+				INFOPLIST_FILE = Runner/Info.plist;
544
+				LD_RUNPATH_SEARCH_PATHS = (
545
+					"$(inherited)",
546
+					"@executable_path/Frameworks",
547
+				);
548
+				PRODUCT_BUNDLE_IDENTIFIER = com.szls.lszlgl;
549
+				PRODUCT_NAME = "$(TARGET_NAME)";
550
+				SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
551
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
552
+				SWIFT_VERSION = 5.0;
553
+				VERSIONING_SYSTEM = "apple-generic";
554
+			};
555
+			name = Debug;
556
+		};
557
+		97C147071CF9000F007C117D /* Release */ = {
558
+			isa = XCBuildConfiguration;
559
+			baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
560
+			buildSettings = {
561
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
562
+				CLANG_ENABLE_MODULES = YES;
563
+				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
564
+				ENABLE_BITCODE = NO;
565
+				INFOPLIST_FILE = Runner/Info.plist;
566
+				LD_RUNPATH_SEARCH_PATHS = (
567
+					"$(inherited)",
568
+					"@executable_path/Frameworks",
569
+				);
570
+				PRODUCT_BUNDLE_IDENTIFIER = com.szls.lszlgl;
571
+				PRODUCT_NAME = "$(TARGET_NAME)";
572
+				SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
573
+				SWIFT_VERSION = 5.0;
574
+				VERSIONING_SYSTEM = "apple-generic";
575
+			};
576
+			name = Release;
577
+		};
578
+/* End XCBuildConfiguration section */
579
+
580
+/* Begin XCConfigurationList section */
581
+		331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
582
+			isa = XCConfigurationList;
583
+			buildConfigurations = (
584
+				331C8088294A63A400263BE5 /* Debug */,
585
+				331C8089294A63A400263BE5 /* Release */,
586
+				331C808A294A63A400263BE5 /* Profile */,
587
+			);
588
+			defaultConfigurationIsVisible = 0;
589
+			defaultConfigurationName = Release;
590
+		};
591
+		97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
592
+			isa = XCConfigurationList;
593
+			buildConfigurations = (
594
+				97C147031CF9000F007C117D /* Debug */,
595
+				97C147041CF9000F007C117D /* Release */,
596
+				249021D3217E4FDB00AE95B9 /* Profile */,
597
+			);
598
+			defaultConfigurationIsVisible = 0;
599
+			defaultConfigurationName = Release;
600
+		};
601
+		97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
602
+			isa = XCConfigurationList;
603
+			buildConfigurations = (
604
+				97C147061CF9000F007C117D /* Debug */,
605
+				97C147071CF9000F007C117D /* Release */,
606
+				249021D4217E4FDB00AE95B9 /* Profile */,
607
+			);
608
+			defaultConfigurationIsVisible = 0;
609
+			defaultConfigurationName = Release;
610
+		};
611
+/* End XCConfigurationList section */
612
+	};
613
+	rootObject = 97C146E61CF9000F007C117D /* Project object */;
614
+}

+ 7 - 0
ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata

@@ -0,0 +1,7 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<Workspace
3
+   version = "1.0">
4
+   <FileRef
5
+      location = "self:">
6
+   </FileRef>
7
+</Workspace>

+ 8 - 0
ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist

@@ -0,0 +1,8 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>IDEDidComputeMac32BitWarning</key>
6
+	<true/>
7
+</dict>
8
+</plist>

+ 8 - 0
ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings

@@ -0,0 +1,8 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>PreviewsEnabled</key>
6
+	<false/>
7
+</dict>
8
+</plist>

+ 98 - 0
ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme

@@ -0,0 +1,98 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<Scheme
3
+   LastUpgradeVersion = "1430"
4
+   version = "1.3">
5
+   <BuildAction
6
+      parallelizeBuildables = "YES"
7
+      buildImplicitDependencies = "YES">
8
+      <BuildActionEntries>
9
+         <BuildActionEntry
10
+            buildForTesting = "YES"
11
+            buildForRunning = "YES"
12
+            buildForProfiling = "YES"
13
+            buildForArchiving = "YES"
14
+            buildForAnalyzing = "YES">
15
+            <BuildableReference
16
+               BuildableIdentifier = "primary"
17
+               BlueprintIdentifier = "97C146ED1CF9000F007C117D"
18
+               BuildableName = "Runner.app"
19
+               BlueprintName = "Runner"
20
+               ReferencedContainer = "container:Runner.xcodeproj">
21
+            </BuildableReference>
22
+         </BuildActionEntry>
23
+      </BuildActionEntries>
24
+   </BuildAction>
25
+   <TestAction
26
+      buildConfiguration = "Debug"
27
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29
+      shouldUseLaunchSchemeArgsEnv = "YES">
30
+      <MacroExpansion>
31
+         <BuildableReference
32
+            BuildableIdentifier = "primary"
33
+            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
34
+            BuildableName = "Runner.app"
35
+            BlueprintName = "Runner"
36
+            ReferencedContainer = "container:Runner.xcodeproj">
37
+         </BuildableReference>
38
+      </MacroExpansion>
39
+      <Testables>
40
+         <TestableReference
41
+            skipped = "NO"
42
+            parallelizable = "YES">
43
+            <BuildableReference
44
+               BuildableIdentifier = "primary"
45
+               BlueprintIdentifier = "331C8080294A63A400263BE5"
46
+               BuildableName = "RunnerTests.xctest"
47
+               BlueprintName = "RunnerTests"
48
+               ReferencedContainer = "container:Runner.xcodeproj">
49
+            </BuildableReference>
50
+         </TestableReference>
51
+      </Testables>
52
+   </TestAction>
53
+   <LaunchAction
54
+      buildConfiguration = "Debug"
55
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
56
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
57
+      launchStyle = "0"
58
+      useCustomWorkingDirectory = "NO"
59
+      ignoresPersistentStateOnLaunch = "NO"
60
+      debugDocumentVersioning = "YES"
61
+      debugServiceExtension = "internal"
62
+      allowLocationSimulation = "YES">
63
+      <BuildableProductRunnable
64
+         runnableDebuggingMode = "0">
65
+         <BuildableReference
66
+            BuildableIdentifier = "primary"
67
+            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
68
+            BuildableName = "Runner.app"
69
+            BlueprintName = "Runner"
70
+            ReferencedContainer = "container:Runner.xcodeproj">
71
+         </BuildableReference>
72
+      </BuildableProductRunnable>
73
+   </LaunchAction>
74
+   <ProfileAction
75
+      buildConfiguration = "Profile"
76
+      shouldUseLaunchSchemeArgsEnv = "YES"
77
+      savedToolIdentifier = ""
78
+      useCustomWorkingDirectory = "NO"
79
+      debugDocumentVersioning = "YES">
80
+      <BuildableProductRunnable
81
+         runnableDebuggingMode = "0">
82
+         <BuildableReference
83
+            BuildableIdentifier = "primary"
84
+            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
85
+            BuildableName = "Runner.app"
86
+            BlueprintName = "Runner"
87
+            ReferencedContainer = "container:Runner.xcodeproj">
88
+         </BuildableReference>
89
+      </BuildableProductRunnable>
90
+   </ProfileAction>
91
+   <AnalyzeAction
92
+      buildConfiguration = "Debug">
93
+   </AnalyzeAction>
94
+   <ArchiveAction
95
+      buildConfiguration = "Release"
96
+      revealArchiveInOrganizer = "YES">
97
+   </ArchiveAction>
98
+</Scheme>

+ 7 - 0
ios/Runner.xcworkspace/contents.xcworkspacedata

@@ -0,0 +1,7 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<Workspace
3
+   version = "1.0">
4
+   <FileRef
5
+      location = "group:Runner.xcodeproj">
6
+   </FileRef>
7
+</Workspace>

+ 8 - 0
ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist

@@ -0,0 +1,8 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>IDEDidComputeMac32BitWarning</key>
6
+	<true/>
7
+</dict>
8
+</plist>

+ 8 - 0
ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings

@@ -0,0 +1,8 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>PreviewsEnabled</key>
6
+	<false/>
7
+</dict>
8
+</plist>

+ 13 - 0
ios/Runner/AppDelegate.swift

@@ -0,0 +1,13 @@
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
+}

+ 122 - 0
ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json

@@ -0,0 +1,122 @@
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
+}

BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png


+ 23 - 0
ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json

@@ -0,0 +1,23 @@
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
+}

BIN
ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png


BIN
ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png


BIN
ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png


+ 5 - 0
ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md

@@ -0,0 +1,5 @@
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.

+ 37 - 0
ios/Runner/Base.lproj/LaunchScreen.storyboard

@@ -0,0 +1,37 @@
1
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
3
+    <dependencies>
4
+        <deployment identifier="iOS"/>
5
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
6
+    </dependencies>
7
+    <scenes>
8
+        <!--View Controller-->
9
+        <scene sceneID="EHf-IW-A2E">
10
+            <objects>
11
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
12
+                    <layoutGuides>
13
+                        <viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
14
+                        <viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
15
+                    </layoutGuides>
16
+                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
17
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
18
+                        <subviews>
19
+                            <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
20
+                            </imageView>
21
+                        </subviews>
22
+                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
23
+                        <constraints>
24
+                            <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
25
+                            <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
26
+                        </constraints>
27
+                    </view>
28
+                </viewController>
29
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
30
+            </objects>
31
+            <point key="canvasLocation" x="53" y="375"/>
32
+        </scene>
33
+    </scenes>
34
+    <resources>
35
+        <image name="LaunchImage" width="168" height="185"/>
36
+    </resources>
37
+</document>

+ 26 - 0
ios/Runner/Base.lproj/Main.storyboard

@@ -0,0 +1,26 @@
1
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
3
+    <dependencies>
4
+        <deployment identifier="iOS"/>
5
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
6
+    </dependencies>
7
+    <scenes>
8
+        <!--Flutter View Controller-->
9
+        <scene sceneID="tne-QT-ifu">
10
+            <objects>
11
+                <viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
12
+                    <layoutGuides>
13
+                        <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
14
+                        <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
15
+                    </layoutGuides>
16
+                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
17
+                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
18
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
19
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
20
+                    </view>
21
+                </viewController>
22
+                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
23
+            </objects>
24
+        </scene>
25
+    </scenes>
26
+</document>

+ 49 - 0
ios/Runner/Info.plist

@@ -0,0 +1,49 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>CFBundleDevelopmentRegion</key>
6
+	<string>$(DEVELOPMENT_LANGUAGE)</string>
7
+	<key>CFBundleDisplayName</key>
8
+	<string>Lszlgl</string>
9
+	<key>CFBundleExecutable</key>
10
+	<string>$(EXECUTABLE_NAME)</string>
11
+	<key>CFBundleIdentifier</key>
12
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
13
+	<key>CFBundleInfoDictionaryVersion</key>
14
+	<string>6.0</string>
15
+	<key>CFBundleName</key>
16
+	<string>lszlgl</string>
17
+	<key>CFBundlePackageType</key>
18
+	<string>APPL</string>
19
+	<key>CFBundleShortVersionString</key>
20
+	<string>$(FLUTTER_BUILD_NAME)</string>
21
+	<key>CFBundleSignature</key>
22
+	<string>????</string>
23
+	<key>CFBundleVersion</key>
24
+	<string>$(FLUTTER_BUILD_NUMBER)</string>
25
+	<key>LSRequiresIPhoneOS</key>
26
+	<true/>
27
+	<key>UILaunchStoryboardName</key>
28
+	<string>LaunchScreen</string>
29
+	<key>UIMainStoryboardFile</key>
30
+	<string>Main</string>
31
+	<key>UISupportedInterfaceOrientations</key>
32
+	<array>
33
+		<string>UIInterfaceOrientationPortrait</string>
34
+		<string>UIInterfaceOrientationLandscapeLeft</string>
35
+		<string>UIInterfaceOrientationLandscapeRight</string>
36
+	</array>
37
+	<key>UISupportedInterfaceOrientations~ipad</key>
38
+	<array>
39
+		<string>UIInterfaceOrientationPortrait</string>
40
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
41
+		<string>UIInterfaceOrientationLandscapeLeft</string>
42
+		<string>UIInterfaceOrientationLandscapeRight</string>
43
+	</array>
44
+	<key>CADisableMinimumFrameDurationOnPhone</key>
45
+	<true/>
46
+	<key>UIApplicationSupportsIndirectInputEvents</key>
47
+	<true/>
48
+</dict>
49
+</plist>

+ 1 - 0
ios/Runner/Runner-Bridging-Header.h

@@ -0,0 +1 @@
1
+#import "GeneratedPluginRegistrant.h"

+ 12 - 0
ios/RunnerTests/RunnerTests.swift

@@ -0,0 +1,12 @@
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
+}

+ 41 - 0
lib/base/base_state.dart

@@ -0,0 +1,41 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:lszlgl/config/pics.dart';
3
+
4
+export 'package:lszlgl/config/pics.dart';
5
+export 'package:lszlgl/router/my_navigator.dart';
6
+export 'package:lszlgl/router/my_router.dart';
7
+
8
+abstract class BaseState<T extends StatefulWidget> extends State<T> {
9
+  /// 隐藏软键盘
10
+  void hideKeyboard() {
11
+    FocusScopeNode currentFocus = FocusScope.of(context);
12
+    if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) {
13
+      FocusManager.instance.primaryFocus?.unfocus();
14
+    }
15
+  }
16
+
17
+  AppBar myAppBar({
18
+    String title = '',
19
+    String? titleIcon,
20
+    bool autoLeading = true,
21
+    PreferredSizeWidget? bottom,
22
+  }) {
23
+    return AppBar(
24
+      title: Text(title),
25
+      bottom: bottom,
26
+      automaticallyImplyLeading: autoLeading,
27
+    );
28
+  }
29
+
30
+  /// 带背景图的Scaffold
31
+  Widget myScaffold({required Widget child}) {
32
+    return Scaffold(
33
+      body: Stack(
34
+        children: [
35
+          SizedBox(width: double.infinity, child: Image.asset(imgHomeTopBg)),
36
+          child,
37
+        ],
38
+      ),
39
+    );
40
+  }
41
+}

+ 15 - 0
lib/config/colors.dart

@@ -0,0 +1,15 @@
1
+import 'package:flutter/material.dart';
2
+
3
+class MyColor {
4
+  MyColor._();
5
+
6
+  static const Color c_333333 = Color(0xFF333333);
7
+  static const Color c_666666 = Color(0xFF666666);
8
+
9
+  static const Color c_3BD2E5 = Color(0xFF3BD2E5);
10
+  static const Color c_25A6EE = Color(0xFF25A6EE);
11
+  static const Color c_28A3ED = Color(0xFF28A3ED);
12
+  static const Color c_1383C2 = Color(0xFF1383C2);
13
+
14
+  static const Color c_467F86 = Color(0xFF467F86);
15
+}

+ 35 - 0
lib/config/pics.dart

@@ -0,0 +1,35 @@
1
+/// 图片资源
2
+
3
+// 登录页背景
4
+const String imgLoginBg = 'assets/images/login_bg.webp';
5
+// 登录页标题
6
+const String imgLoginTitle = 'assets/images/login_title.webp';
7
+// 登录页账号icon
8
+const String imgLoginAccount = 'assets/images/login_account.webp';
9
+// 登录页密码icon
10
+const String imgLoginPwd = 'assets/images/login_pwd.webp';
11
+
12
+// 导航栏图标
13
+const String imgNavHome = 'assets/images/nav_home.webp';
14
+const String imgNavHomeSelect = 'assets/images/nav_home_select.webp';
15
+const String imgNavUserCenter = 'assets/images/nav_user_center.webp';
16
+const String imgNavUserCenterSelect = 'assets/images/nav_user_center_select.webp';
17
+
18
+// 首页顶部背景
19
+const String imgHomeTopBg = 'assets/images/home_top_bg.webp';
20
+// 首页列表背景
21
+const String imgHomeListBg = 'assets/images/home_list_bg.webp';
22
+// 首页列表品质监测
23
+const String imgHomeListPzjc = 'assets/images/home_list_pzjc.webp';
24
+// 首页列表整仓检验
25
+const String imgHomeListZcjy = 'assets/images/home_list_zcjy.webp';
26
+
27
+// 用户中心账户
28
+const String imgUserCenterAccount = 'assets/images/user_center_account.webp';
29
+// 用户中心设置
30
+const String imgUserCenterSetting = 'assets/images/user_center_setting.webp';
31
+
32
+// 列表项右箭头
33
+const String imgItemArrowRight = 'assets/images/item_arrow_right.webp';
34
+// 列表项下箭头
35
+const String imgItemArrowDown = 'assets/images/item_arrow_down.webp';

+ 99 - 0
lib/main.dart

@@ -0,0 +1,99 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:flutter/services.dart';
3
+import 'package:flutter_localizations/flutter_localizations.dart';
4
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
5
+import 'package:lszlgl/router/my_navigator.dart';
6
+import 'package:lszlgl/router/my_router.dart';
7
+
8
+void main() {
9
+  WidgetsFlutterBinding.ensureInitialized();
10
+  SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light.copyWith(statusBarColor: Colors.transparent));
11
+  SystemChrome.setPreferredOrientations([
12
+    DeviceOrientation.portraitUp,
13
+    DeviceOrientation.portraitDown,
14
+  ]);
15
+  runApp(const MyApp());
16
+}
17
+
18
+class MyApp extends StatelessWidget {
19
+  const MyApp({super.key});
20
+
21
+  @override
22
+  Widget build(BuildContext context) {
23
+    return MaterialApp(
24
+      title: '粮食质量管理',
25
+      theme: ThemeData(
26
+        colorScheme: ColorScheme.fromSeed(
27
+          seedColor: Colors.blue,
28
+        ),
29
+        scaffoldBackgroundColor: const Color(0xFFF5F5F5),
30
+        // navigationBarTheme: const NavigationBarThemeData(height: 56),
31
+        appBarTheme: const AppBarTheme(
32
+          centerTitle: true,
33
+          foregroundColor: Colors.white,
34
+          backgroundColor: Colors.transparent,
35
+          systemOverlayStyle: SystemUiOverlayStyle.light,
36
+        ),
37
+        useMaterial3: true,
38
+      ),
39
+      navigatorObservers: [FlutterSmartDialog.observer],
40
+      builder: FlutterSmartDialog.init(),
41
+      localizationsDelegates: const [
42
+        GlobalMaterialLocalizations.delegate,
43
+        GlobalCupertinoLocalizations.delegate,
44
+        GlobalWidgetsLocalizations.delegate,
45
+      ],
46
+      supportedLocales: const [Locale('zh')],
47
+      onGenerateRoute: rOnGenerateRoute,
48
+      navigatorKey: Nav.navigatorKey,
49
+    );
50
+  }
51
+}
52
+
53
+class MyHomePage extends StatefulWidget {
54
+  const MyHomePage({super.key, required this.title});
55
+
56
+  final String title;
57
+
58
+  @override
59
+  State<MyHomePage> createState() => _MyHomePageState();
60
+}
61
+
62
+class _MyHomePageState extends State<MyHomePage> {
63
+  int _counter = 0;
64
+
65
+  void _incrementCounter() {
66
+    setState(() {
67
+      _counter++;
68
+    });
69
+  }
70
+
71
+  @override
72
+  Widget build(BuildContext context) {
73
+    return Scaffold(
74
+      appBar: AppBar(
75
+        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
76
+        title: Text(widget.title),
77
+      ),
78
+      body: Center(
79
+        child: Column(
80
+          mainAxisAlignment: MainAxisAlignment.center,
81
+          children: <Widget>[
82
+            const Text(
83
+              'You have pushed the button this many times:',
84
+            ),
85
+            Text(
86
+              '$_counter',
87
+              style: Theme.of(context).textTheme.headlineMedium,
88
+            ),
89
+          ],
90
+        ),
91
+      ),
92
+      floatingActionButton: FloatingActionButton(
93
+        onPressed: _incrementCounter,
94
+        tooltip: 'Increment',
95
+        child: const Icon(Icons.add),
96
+      ),
97
+    );
98
+  }
99
+}

+ 163 - 0
lib/page/home/home_page.dart

@@ -0,0 +1,163 @@
1
+import 'package:cached_network_image/cached_network_image.dart';
2
+import 'package:card_swiper/card_swiper.dart';
3
+import 'package:flutter/cupertino.dart';
4
+import 'package:flutter/material.dart';
5
+import 'package:lszlgl/base/base_state.dart';
6
+import 'package:lszlgl/page/reap_step/reap_step_tab_page.dart';
7
+
8
+/// 首页
9
+class HomePage extends StatefulWidget {
10
+  const HomePage({Key? key}) : super(key: key);
11
+
12
+  @override
13
+  State<HomePage> createState() => _HomePageState();
14
+}
15
+
16
+class _HomePageState extends BaseState<HomePage> with AutomaticKeepAliveClientMixin {
17
+  List<String> bannerList = [
18
+    'https://gd-hbimg.huaban.com/c7a22fb15d70a0a976e20fb810c048ec11c76fc31ac08-hajElf_fw658webp',
19
+    'https://gd-hbimg.huaban.com/82e60fd3c61530d52ec1d01f80cfda11526c42e4495cb-6JwN1d_fw658webp',
20
+  ];
21
+
22
+  late List<ServiceModel> serviceList;
23
+
24
+  void startReap() {
25
+    MyRouter.startReapStepList(const ReapStepTabPageArgs(type: StepType.reap));
26
+  }
27
+
28
+  void startStore() {
29
+    MyRouter.startReapStepList(const ReapStepTabPageArgs(type: StepType.stock));
30
+  }
31
+
32
+  @override
33
+  void initState() {
34
+    super.initState();
35
+    serviceList = [
36
+      ServiceModel(name: '收货环节', icon: imgHomeListPzjc, onTap: startReap),
37
+      ServiceModel(name: '库存环节', icon: imgHomeListZcjy, onTap: startStore),
38
+    ];
39
+  }
40
+
41
+  @override
42
+  Widget build(BuildContext context) {
43
+    super.build(context);
44
+    return myScaffold(child: buildBody());
45
+  }
46
+
47
+  Widget buildBody() {
48
+    return Column(
49
+      children: [
50
+        myAppBar(title: '质量安全检验监测', autoLeading: false),
51
+        Expanded(
52
+          child: SingleChildScrollView(
53
+            physics: const BouncingScrollPhysics(),
54
+            child: Column(
55
+              children: [
56
+                buildBanner(),
57
+                const SizedBox(height: 24),
58
+                ...List.generate(
59
+                  serviceList.length,
60
+                  (index) => buildServiceItem(serviceList[index]),
61
+                ).toList(),
62
+              ],
63
+            ),
64
+          ),
65
+        ),
66
+      ],
67
+    );
68
+  }
69
+
70
+  Widget buildTitle() {
71
+    return Container(
72
+      alignment: Alignment.center,
73
+      padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top + 26, bottom: 26),
74
+      child: const Text(
75
+        '质量安全检验监测',
76
+        style: TextStyle(color: Colors.white, fontSize: 22, fontWeight: FontWeight.w500),
77
+      ),
78
+    );
79
+  }
80
+
81
+  Widget buildBanner() {
82
+    return Container(
83
+      margin: const EdgeInsets.symmetric(horizontal: 12),
84
+      decoration: const BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(18))),
85
+      clipBehavior: Clip.hardEdge,
86
+      child: AspectRatio(
87
+        aspectRatio: 2 / 1,
88
+        child: Swiper(
89
+          autoplay: true,
90
+          autoplayDelay: const Duration(seconds: 5).inMilliseconds,
91
+          itemCount: bannerList.length,
92
+          itemBuilder: (_, index) => CachedNetworkImage(
93
+            fit: BoxFit.cover,
94
+            imageUrl: bannerList[index],
95
+            placeholder: (_, __) => const Center(child: CircularProgressIndicator()),
96
+            errorWidget: (context, url, error) => const Center(child: Icon(Icons.error)),
97
+          ),
98
+        ),
99
+      ),
100
+    );
101
+  }
102
+
103
+  Widget buildServiceItem(ServiceModel service) {
104
+    return GestureDetector(
105
+      onTap: service.onTap,
106
+      child: Container(
107
+        margin: const EdgeInsets.only(left: 14, right: 14, bottom: 28),
108
+        padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 48),
109
+        clipBehavior: Clip.hardEdge,
110
+        decoration: BoxDecoration(
111
+          borderRadius: const BorderRadius.all(Radius.circular(12)),
112
+          boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.1), offset: const Offset(0, 5), blurRadius: 4)],
113
+          image: const DecorationImage(image: AssetImage(imgHomeListBg), fit: BoxFit.fill),
114
+        ),
115
+        child: Row(
116
+          children: [
117
+            Image.asset(service.icon, height: 80),
118
+            const SizedBox(width: 16),
119
+            Expanded(
120
+              child: Column(
121
+                mainAxisSize: MainAxisSize.min,
122
+                children: [
123
+                  Text(
124
+                    service.name,
125
+                    textAlign: TextAlign.center,
126
+                    style: const TextStyle(color: Color(0xFF333333), fontSize: 27, fontWeight: FontWeight.w500),
127
+                  ),
128
+                  service.nameEn != null
129
+                      ? Padding(
130
+                          padding: const EdgeInsets.only(top: 4),
131
+                          child: Text(
132
+                            service.nameEn!,
133
+                            textAlign: TextAlign.center,
134
+                            style: const TextStyle(color: Color(0xFF333333), fontSize: 12, fontWeight: FontWeight.w500),
135
+                          ),
136
+                        )
137
+                      : const SizedBox.shrink(),
138
+                ],
139
+              ),
140
+            ),
141
+          ],
142
+        ),
143
+      ),
144
+    );
145
+  }
146
+
147
+  @override
148
+  bool get wantKeepAlive => true;
149
+}
150
+
151
+class ServiceModel {
152
+  final String name;
153
+  final String? nameEn;
154
+  final String icon;
155
+  final VoidCallback onTap;
156
+
157
+  ServiceModel({
158
+    required this.name,
159
+    this.nameEn,
160
+    required this.icon,
161
+    required this.onTap,
162
+  });
163
+}

+ 207 - 0
lib/page/login/login_page.dart

@@ -0,0 +1,207 @@
1
+import 'package:flutter/cupertino.dart';
2
+import 'package:flutter/material.dart';
3
+import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
4
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
5
+import 'package:lszlgl/router/my_navigator.dart';
6
+import 'package:lszlgl/widget/button.dart';
7
+
8
+import '../../base/base_state.dart';
9
+import '../main_tab_page.dart';
10
+
11
+/// 登录页面
12
+class LoginPage extends StatefulWidget {
13
+  const LoginPage({Key? key}) : super(key: key);
14
+
15
+  @override
16
+  State<LoginPage> createState() => _LoginPageState();
17
+}
18
+
19
+class _LoginPageState extends BaseState<LoginPage> {
20
+  late TextEditingController accountCtrl;
21
+  late TextEditingController pwdCtrl;
22
+
23
+  void onLogin() {
24
+    var account = accountCtrl.text;
25
+    var pwd = pwdCtrl.text;
26
+    if (account.isEmpty || pwd.isEmpty) {
27
+      SmartDialog.showToast('请输入账号和密码');
28
+      return;
29
+    }
30
+    MyRouter.startMain(popAll: true);
31
+  }
32
+
33
+  @override
34
+  void initState() {
35
+    super.initState();
36
+    accountCtrl = TextEditingController();
37
+    pwdCtrl = TextEditingController();
38
+  }
39
+
40
+  @override
41
+  void dispose() {
42
+    accountCtrl.dispose();
43
+    pwdCtrl.dispose();
44
+    super.dispose();
45
+  }
46
+
47
+  @override
48
+  Widget build(BuildContext context) {
49
+    return Scaffold(
50
+      backgroundColor: const Color(0xFF49AAF2),
51
+      body: KeyboardDismissOnTap(
52
+        dismissOnCapturedTaps: true,
53
+        child: SingleChildScrollView(
54
+          physics: const BouncingScrollPhysics(),
55
+          child: Stack(
56
+            children: [
57
+              Positioned.fill(child: Image.asset(imgLoginBg, fit: BoxFit.fill)),
58
+              SizedBox(
59
+                height: MediaQuery.of(context).size.height,
60
+                child: buildBody(),
61
+              ),
62
+            ],
63
+          ),
64
+        ),
65
+      ),
66
+    );
67
+  }
68
+
69
+  Widget buildBody() {
70
+    return Column(
71
+      children: [
72
+        const SizedBox(height: 88),
73
+        Container(
74
+          width: double.infinity,
75
+          padding: const EdgeInsets.symmetric(horizontal: 72),
76
+          child: Image.asset(imgLoginTitle, fit: BoxFit.fill),
77
+        ),
78
+        const SizedBox(height: 32),
79
+        loginContainer(),
80
+      ],
81
+    );
82
+  }
83
+
84
+  Widget loginContainer() {
85
+    return SizedBox(
86
+      width: double.infinity,
87
+      child: Stack(
88
+        alignment: Alignment.topCenter,
89
+        children: [
90
+          buildInputContent(),
91
+          userTitle(),
92
+        ],
93
+      ),
94
+    );
95
+  }
96
+
97
+  Widget userTitle() {
98
+    return Container(
99
+      height: 48,
100
+      width: 174,
101
+      alignment: Alignment.center,
102
+      decoration: const BoxDecoration(
103
+        color: Colors.white,
104
+        borderRadius: BorderRadius.all(Radius.circular(100)),
105
+        border: Border.fromBorderSide(BorderSide(color: Color(0xFF49AAF2), width: 1)),
106
+        boxShadow: [BoxShadow(color: Color(0x941C90FF), offset: Offset(0, 3))],
107
+      ),
108
+      child: const Text(
109
+        '用户登录',
110
+        style: TextStyle(color: Color(0xFF1187DE), fontSize: 18),
111
+      ),
112
+    );
113
+  }
114
+
115
+  Widget buildInputContent() {
116
+    return Container(
117
+      margin: const EdgeInsets.only(top: 14, left: 18, right: 18),
118
+      padding: const EdgeInsets.all(10),
119
+      decoration: BoxDecoration(
120
+        color: Colors.white.withOpacity(0.2),
121
+        borderRadius: const BorderRadius.all(Radius.circular(24)),
122
+      ),
123
+      child: Container(
124
+        padding: const EdgeInsets.symmetric(horizontal: 32),
125
+        alignment: Alignment.center,
126
+        decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(24))),
127
+        child: Column(
128
+          children: [
129
+            const SizedBox(height: 72),
130
+            buildEdit(
131
+              ctrl: accountCtrl,
132
+              hint: '请输入登录账号',
133
+              icon: imgLoginAccount,
134
+              action: TextInputAction.next,
135
+            ),
136
+            const SizedBox(height: 32),
137
+            buildEdit(
138
+              ctrl: pwdCtrl,
139
+              hint: '请输入登录密码',
140
+              icon: imgLoginPwd,
141
+              obscure: true,
142
+              onSubmit: (value) => onLogin(),
143
+            ),
144
+            const SizedBox(height: 80),
145
+            buildLoginBtn(),
146
+            const SizedBox(height: 56),
147
+          ],
148
+        ),
149
+      ),
150
+    );
151
+  }
152
+
153
+  Widget buildEdit({
154
+    required TextEditingController ctrl,
155
+    required String hint,
156
+    String? icon,
157
+    TextInputAction action = TextInputAction.done,
158
+    bool obscure = false,
159
+    ValueChanged? onSubmit,
160
+  }) {
161
+    return TextField(
162
+      controller: ctrl,
163
+      decoration: InputDecoration(
164
+        prefixIcon: icon == null
165
+            ? null
166
+            : Padding(
167
+                padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
168
+                child: Image.asset(icon, height: 22),
169
+              ),
170
+        prefixIconConstraints: const BoxConstraints(),
171
+        border: const OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(100))),
172
+        enabledBorder: const OutlineInputBorder(
173
+          borderSide: BorderSide(color: Color(0xFFE6E6E6), width: 1),
174
+          borderRadius: BorderRadius.all(Radius.circular(100)),
175
+        ),
176
+        hintText: hint,
177
+        hintStyle: const TextStyle(color: Color(0xFFBBBBBB)),
178
+        isDense: true,
179
+        contentPadding: EdgeInsets.zero,
180
+      ),
181
+      style: const TextStyle(fontSize: 14),
182
+      textInputAction: action,
183
+      obscureText: obscure,
184
+      onSubmitted: onSubmit,
185
+    );
186
+  }
187
+
188
+  Widget buildLoginBtn() {
189
+    return MyButton(
190
+      '登录',
191
+      onTap: onLogin,
192
+      gradient: const LinearGradient(colors: [Color(0xFF60B5F4), Color(0xFF62A4D6)]),
193
+    );
194
+    return GestureDetector(
195
+      onTap: onLogin,
196
+      child: Container(
197
+        alignment: Alignment.center,
198
+        padding: const EdgeInsets.symmetric(vertical: 12),
199
+        decoration: const BoxDecoration(
200
+          gradient: LinearGradient(colors: [Color(0xFF60B5F4), Color(0xFF62A4D6)]),
201
+          borderRadius: BorderRadius.all(Radius.circular(100)),
202
+        ),
203
+        child: const Text('登录', style: TextStyle(fontSize: 16, color: Colors.white)),
204
+      ),
205
+    );
206
+  }
207
+}

+ 123 - 0
lib/page/main_tab_page.dart

@@ -0,0 +1,123 @@
1
+import 'dart:async';
2
+
3
+import 'package:flutter/material.dart';
4
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
5
+import 'package:lszlgl/base/base_state.dart';
6
+import 'package:lszlgl/page/home/home_page.dart';
7
+import 'package:lszlgl/page/user_center/user_center_page.dart';
8
+
9
+/// 主页tab页面
10
+class MainTabPage extends StatefulWidget {
11
+  const MainTabPage({Key? key}) : super(key: key);
12
+
13
+  @override
14
+  State<MainTabPage> createState() => _MainTabPageState();
15
+}
16
+
17
+class _MainTabPageState extends State<MainTabPage> {
18
+  late List<String> tabTextList;
19
+
20
+  late List<String> tabIconList;
21
+  late List<String> tabIconSelectList;
22
+
23
+  late List<Widget> pageList;
24
+
25
+  late PageController ctrl;
26
+
27
+  int selectedIndex = 0;
28
+
29
+  DateTime? lastTime;
30
+
31
+  ValueNotifier<bool> popState = ValueNotifier(false);
32
+
33
+  void refreshTab(int index, {bool refreshPage = false}) {
34
+    if (index == selectedIndex) return;
35
+    setState(() {
36
+      selectedIndex = index;
37
+    });
38
+    if (refreshPage) ctrl.jumpToPage(index);
39
+  }
40
+
41
+  @override
42
+  void initState() {
43
+    super.initState();
44
+    tabTextList = ['首页', '用户中心'];
45
+    tabIconList = [imgNavHome, imgNavUserCenter];
46
+    tabIconSelectList = [imgNavHomeSelect, imgNavUserCenterSelect];
47
+    pageList = [const HomePage(), const UserCenterPage()];
48
+    ctrl = PageController(initialPage: selectedIndex);
49
+  }
50
+
51
+  @override
52
+  Widget build(BuildContext context) {
53
+    return Scaffold(
54
+      backgroundColor: const Color(0xFFF3F3F3),
55
+      body: buildPop(buildBody()),
56
+      bottomNavigationBar: buildNavigation(),
57
+    );
58
+  }
59
+
60
+  Widget buildPop(Widget child) {
61
+    return ValueListenableBuilder<bool>(
62
+      valueListenable: popState,
63
+      builder: (_, value, __) {
64
+        return PopScope(
65
+          canPop: value,
66
+          child: child,
67
+          onPopInvoked: (didPop) {
68
+            if (didPop) return;
69
+            SmartDialog.showToast('再试一次退出');
70
+            popState.value = true;
71
+            // 2秒后不可退出
72
+            Timer(
73
+              const Duration(seconds: 2),
74
+              () => popState.value = false,
75
+            );
76
+          },
77
+        );
78
+      },
79
+    );
80
+  }
81
+
82
+  Widget buildBody() {
83
+    return PageView.builder(
84
+      controller: ctrl,
85
+      // physics: const BouncingScrollPhysics(),
86
+      onPageChanged: refreshTab,
87
+      itemCount: pageList.length,
88
+      itemBuilder: (_, index) => pageList[index],
89
+    );
90
+  }
91
+
92
+  Widget buildNavigation() {
93
+    return NavigationBar(
94
+      selectedIndex: selectedIndex,
95
+      surfaceTintColor: Colors.white,
96
+      onDestinationSelected: (index) => refreshTab(index, refreshPage: true),
97
+      destinations: List.generate(
98
+        tabTextList.length,
99
+        (index) => GestureDetector(
100
+          behavior: HitTestBehavior.opaque,
101
+          onTap: () => refreshTab(index, refreshPage: true),
102
+          child: Column(
103
+            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
104
+            children: [
105
+              Image.asset(
106
+                index == selectedIndex ? tabIconSelectList[index] : tabIconList[index],
107
+                height: 23,
108
+              ),
109
+              Text(
110
+                tabTextList[index],
111
+                style: TextStyle(
112
+                  fontSize: 14,
113
+                  fontWeight: FontWeight.w500,
114
+                  color: index == selectedIndex ? const Color(0xFF333333) : const Color(0xFF888888),
115
+                ),
116
+              ),
117
+            ],
118
+          ),
119
+        ),
120
+      ).toList(),
121
+    );
122
+  }
123
+}

+ 63 - 0
lib/page/reap_step/reap_sample_detail/reap_sample_basic_detail_page.dart

@@ -0,0 +1,63 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:lszlgl/base/base_state.dart';
3
+import 'package:lszlgl/widget/button.dart';
4
+import 'package:lszlgl/widget/card_item.dart';
5
+
6
+/// 收获扦样-基础信息
7
+class ReapSampleBasicDetailPage extends StatefulWidget {
8
+
9
+  const ReapSampleBasicDetailPage({
10
+    super.key,
11
+  });
12
+
13
+  @override
14
+  State<ReapSampleBasicDetailPage> createState() => _ReapSampleBasicDetailPageState();
15
+}
16
+
17
+class _ReapSampleBasicDetailPageState extends BaseState<ReapSampleBasicDetailPage> with AutomaticKeepAliveClientMixin {
18
+  @override
19
+  bool get wantKeepAlive => true;
20
+
21
+  @override
22
+  Widget build(BuildContext context) {
23
+    super.build(context);
24
+    return Column(
25
+      children: [
26
+        Expanded(child: SingleChildScrollView(child: buildList())),
27
+        buildButton(),
28
+      ],
29
+    );
30
+  }
31
+
32
+  Widget buildList() {
33
+    return Column(
34
+      children: [
35
+        CardItemWidget('扦样任务单号', rightText: '*****************', bottomLine: true),
36
+        CardItemWidget('扦样单位', rightText: '自动生成', bottomLine: true),
37
+        CardItemWidget('扦样人员', rightText: '李飞', bottomLine: true),
38
+        CardItemWidget('任务类型', rightText: '收购监测', bottomLine: true),
39
+        CardItemWidget('省份选择', rightText: '北京市', bottomLine: true),
40
+        CardItemWidget('市区选择', rightText: '市辖区', bottomLine: true),
41
+        CardItemWidget('区县选择', rightText: '平谷区', bottomLine: true),
42
+        CardItemWidget('乡镇选择', rightText: '黄松峪乡', bottomLine: true),
43
+        CardItemWidget('村选择', rightText: '黑豆峪村', bottomLine: true),
44
+        CardItemWidget('扦样地点经纬度', rightText: '经度118.17,纬度26.18', bottomLine: true),
45
+        CardItemWidget('种植面积(亩地)', rightText: '500', bottomLine: true),
46
+        CardItemWidget('土壤地理类型', rightText: '***********', bottomLine: true),
47
+        CardItemWidget('被调查农户或合作社', rightText: '***********', bottomLine: true),
48
+        CardItemWidget('联系方式', rightText: '***********', bottomLine: true),
49
+      ],
50
+    );
51
+  }
52
+
53
+  Widget buildButton() {
54
+    return Container(
55
+      color: const Color(0xFFF1F7F6),
56
+      padding: const EdgeInsets.all(12),
57
+      child: MyButton(
58
+        '重新录入',
59
+        onTap: () => MyRouter.startReapSampleTask(),
60
+      ),
61
+    );
62
+  }
63
+}

+ 61 - 0
lib/page/reap_step/reap_sample_detail/reap_sample_disaster_detail_page.dart

@@ -0,0 +1,61 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:lszlgl/base/base_state.dart';
3
+import 'package:lszlgl/widget/button.dart';
4
+import 'package:lszlgl/widget/card_item.dart';
5
+
6
+/// 收获扦样-灾害污染
7
+class ReapSampleDisasterDetailPage extends StatefulWidget {
8
+  const ReapSampleDisasterDetailPage({
9
+    super.key,
10
+  });
11
+
12
+  @override
13
+  State<ReapSampleDisasterDetailPage> createState() => _ReapSampleDisasterDetailPageState();
14
+}
15
+
16
+class _ReapSampleDisasterDetailPageState extends BaseState<ReapSampleDisasterDetailPage>
17
+    with AutomaticKeepAliveClientMixin {
18
+  @override
19
+  bool get wantKeepAlive => true;
20
+
21
+  @override
22
+  Widget build(BuildContext context) {
23
+    super.build(context);
24
+    return Column(
25
+      children: [
26
+        Expanded(child: SingleChildScrollView(child: buildList())),
27
+        buildButton(),
28
+      ],
29
+    );
30
+  }
31
+
32
+  Widget buildList() {
33
+    return Column(
34
+      children: [
35
+        CardItemWidget('种植土地周围是否有工厂排污', rightText: '是', bottomLine: true),
36
+        CardItemWidget('工厂排污类型', rightText: '***********', bottomLine: true),
37
+        CardItemWidget('种植土地周围使用水源、土壤是否有污染', rightText: '是', bottomLine: true),
38
+        CardItemWidget('污染物类型', rightText: '***********', bottomLine: true),
39
+        CardItemWidget('生产过程中是否发生比较严重的病虫害', rightText: '否', bottomLine: true),
40
+        CardItemWidget('病虫害类型', rightText: '***********', bottomLine: true),
41
+        CardItemWidget('收货期间是否发生连阴雨天气', rightText: '是', bottomLine: true),
42
+        CardItemWidget('收货粮食水分是否偏高', rightText: '否', bottomLine: true),
43
+        CardItemWidget('近年来本地是否发生真菌毒素污染', rightText: '是', bottomLine: true),
44
+        CardItemWidget('真菌毒素污染类型', rightText: '***********', bottomLine: true),
45
+        CardItemWidget('近年来本地是否发生重金属污染', rightText: '否', bottomLine: true),
46
+        CardItemWidget('重金属污染类型', rightText: '***********', bottomLine: true),
47
+      ],
48
+    );
49
+  }
50
+
51
+  Widget buildButton() {
52
+    return Container(
53
+      color: const Color(0xFFF1F7F6),
54
+      padding: const EdgeInsets.all(12),
55
+      child: MyButton(
56
+        '重新录入',
57
+        onTap: () => MyRouter.startReapSampleTask(),
58
+      ),
59
+    );
60
+  }
61
+}

+ 94 - 0
lib/page/reap_step/reap_sample_detail/reap_sample_medicine_detail_page.dart

@@ -0,0 +1,94 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:lszlgl/base/base_state.dart';
3
+import 'package:lszlgl/widget/button.dart';
4
+import 'package:lszlgl/widget/card_item.dart';
5
+
6
+/// 收获扦样-用药情况
7
+class ReapSampleMedicineDetailPage extends StatefulWidget {
8
+  const ReapSampleMedicineDetailPage({
9
+    super.key,
10
+  });
11
+
12
+  @override
13
+  State<ReapSampleMedicineDetailPage> createState() => _ReapSampleMedicineDetailPageState();
14
+}
15
+
16
+class _ReapSampleMedicineDetailPageState extends BaseState<ReapSampleMedicineDetailPage>
17
+    with AutomaticKeepAliveClientMixin {
18
+  @override
19
+  bool get wantKeepAlive => true;
20
+
21
+  @override
22
+  Widget build(BuildContext context) {
23
+    super.build(context);
24
+    return Column(
25
+      children: [
26
+        Expanded(child: SingleChildScrollView(child: buildList())),
27
+        buildButton(),
28
+      ],
29
+    );
30
+  }
31
+
32
+  Widget buildList() {
33
+    return Column(
34
+      children: List.generate(
35
+        2,
36
+        buildItem,
37
+      ).toList(),
38
+    );
39
+  }
40
+
41
+  Widget buildItem(int index) {
42
+    return Container(
43
+      clipBehavior: Clip.hardEdge,
44
+      decoration: const BoxDecoration(
45
+        color: Color(0xFFF5FFFD),
46
+        borderRadius: BorderRadius.all(Radius.circular(8)),
47
+      ),
48
+      margin: const EdgeInsets.only(left: 12, right: 12, top: 8),
49
+      child: IntrinsicHeight(
50
+        child: Row(
51
+          mainAxisSize: MainAxisSize.min,
52
+          children: [
53
+            Container(
54
+              color: const Color(0xFF3ACEE6),
55
+              alignment: Alignment.center,
56
+              padding: const EdgeInsets.symmetric(horizontal: 2),
57
+              child: Text(
58
+                '${index + 1}',
59
+                style: const TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w700),
60
+              ),
61
+            ),
62
+            Expanded(
63
+              child: Column(
64
+                mainAxisSize: MainAxisSize.min,
65
+                children: [
66
+                  CardItemWidget('使用农药品种', rightText: '***********', bottomLine: true, backgroundColor: null),
67
+                  CardItemWidget(
68
+                    '使用农药的数量(公斤或毫升/每亩地)',
69
+                    rightText: '***********',
70
+                    bottomLine: true,
71
+                    backgroundColor: null,
72
+                  ),
73
+                  CardItemWidget('施药时间', rightText: '***********', bottomLine: true, backgroundColor: null),
74
+                  CardItemWidget('施药方法', rightText: '***********', backgroundColor: null),
75
+                ],
76
+              ),
77
+            ),
78
+          ],
79
+        ),
80
+      ),
81
+    );
82
+  }
83
+
84
+  Widget buildButton() {
85
+    return Container(
86
+      color: const Color(0xFFF1F7F6),
87
+      padding: const EdgeInsets.all(12),
88
+      child: MyButton(
89
+        '重新录入',
90
+        onTap: () => MyRouter.startReapSampleTask(),
91
+      ),
92
+    );
93
+  }
94
+}

+ 52 - 0
lib/page/reap_step/reap_sample_detail/reap_sample_org_detail_page.dart

@@ -0,0 +1,52 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:lszlgl/base/base_state.dart';
3
+import 'package:lszlgl/widget/button.dart';
4
+import 'package:lszlgl/widget/card_item.dart';
5
+
6
+/// 收获扦样-检验机构
7
+class ReapSampleOrgDetailPage extends StatefulWidget {
8
+  const ReapSampleOrgDetailPage({
9
+    super.key,
10
+  });
11
+
12
+  @override
13
+  State<ReapSampleOrgDetailPage> createState() => _ReapSampleOrgDetailPageState();
14
+}
15
+
16
+class _ReapSampleOrgDetailPageState extends BaseState<ReapSampleOrgDetailPage> with AutomaticKeepAliveClientMixin {
17
+  @override
18
+  bool get wantKeepAlive => true;
19
+
20
+  @override
21
+  Widget build(BuildContext context) {
22
+    super.build(context);
23
+    return Column(
24
+      children: [
25
+        Expanded(child: SingleChildScrollView(child: buildList())),
26
+        buildButton(),
27
+      ],
28
+    );
29
+  }
30
+
31
+  Widget buildList() {
32
+    return Column(
33
+      children: [
34
+        CardItemWidget('质量检验机构', rightText: '****', bottomLine: true),
35
+        CardItemWidget('机构地址', rightText: '****', bottomLine: true),
36
+        CardItemWidget('食品安全指标检验机构', rightText: '****', bottomLine: true),
37
+        CardItemWidget('机构地址', rightText: '****'),
38
+      ],
39
+    );
40
+  }
41
+
42
+  Widget buildButton() {
43
+    return Container(
44
+      color: const Color(0xFFF1F7F6),
45
+      padding: const EdgeInsets.all(12),
46
+      child: MyButton(
47
+        '重新录入',
48
+        onTap: () => MyRouter.startReapSampleTask(),
49
+      ),
50
+    );
51
+  }
52
+}

+ 61 - 0
lib/page/reap_step/reap_sample_detail/reap_sample_variety_detail_page.dart

@@ -0,0 +1,61 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:lszlgl/base/base_state.dart';
3
+import 'package:lszlgl/widget/button.dart';
4
+import 'package:lszlgl/widget/card_item.dart';
5
+
6
+/// 收获扦样-品种信息
7
+class ReapSampleVarietyDetailPage extends StatefulWidget {
8
+  const ReapSampleVarietyDetailPage({
9
+    super.key,
10
+  });
11
+
12
+  @override
13
+  State<ReapSampleVarietyDetailPage> createState() => _ReapSampleVarietyDetailPageState();
14
+}
15
+
16
+class _ReapSampleVarietyDetailPageState extends BaseState<ReapSampleVarietyDetailPage>
17
+    with AutomaticKeepAliveClientMixin {
18
+  @override
19
+  bool get wantKeepAlive => true;
20
+
21
+  @override
22
+  Widget build(BuildContext context) {
23
+    super.build(context);
24
+    return Column(
25
+      children: [
26
+        Expanded(child: SingleChildScrollView(child: buildList())),
27
+        buildButton(),
28
+      ],
29
+    );
30
+  }
31
+
32
+  Widget buildList() {
33
+    return Column(
34
+      children: [
35
+        CardItemWidget('采样品种', rightText: '****', bottomLine: true),
36
+        CardItemWidget('粮食品类', rightText: '****', bottomLine: true),
37
+        CardItemWidget('样品编号', rightText: '****', bottomLine: true),
38
+        CardItemWidget('种植品种', rightText: '****', bottomLine: true),
39
+        CardItemWidget('是否优质品种', rightText: '****', bottomLine: true),
40
+        CardItemWidget('优质品种类型', rightText: '****', bottomLine: true),
41
+        CardItemWidget('收获时间', rightText: '****', bottomLine: true),
42
+        CardItemWidget('扦样时间', rightText: '****', bottomLine: true),
43
+        CardItemWidget('扦样数量(公斤)', rightText: '****', bottomLine: true),
44
+        CardItemWidget('扦样代表数量(公斤)', rightText: '****', bottomLine: true),
45
+        CardItemWidget('温度(℃)', rightText: '****', bottomLine: true),
46
+        CardItemWidget('湿度(%)', rightText: '****'),
47
+      ],
48
+    );
49
+  }
50
+
51
+  Widget buildButton() {
52
+    return Container(
53
+      color: const Color(0xFFF1F7F6),
54
+      padding: const EdgeInsets.all(12),
55
+      child: MyButton(
56
+        '重新录入',
57
+        onTap: () => MyRouter.startReapSampleTask(),
58
+      ),
59
+    );
60
+  }
61
+}

+ 140 - 0
lib/page/reap_step/reap_sample_task/reap_sample_basic_page.dart

@@ -0,0 +1,140 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:lszlgl/base/base_state.dart';
3
+import 'package:lszlgl/widget/button.dart';
4
+import 'package:lszlgl/widget/card_item.dart';
5
+
6
+/// 收获扦样-基础信息
7
+class ReapSampleBasicPage extends StatefulWidget {
8
+  final VoidCallback nextCallback;
9
+
10
+  const ReapSampleBasicPage({
11
+    super.key,
12
+    required this.nextCallback,
13
+  });
14
+
15
+  @override
16
+  State<ReapSampleBasicPage> createState() => _ReapSampleBasicPageState();
17
+}
18
+
19
+class _ReapSampleBasicPageState extends BaseState<ReapSampleBasicPage> with AutomaticKeepAliveClientMixin {
20
+  late Widget arrowDown;
21
+
22
+  ValueNotifier<String?> sq = ValueNotifier(null);
23
+  ValueNotifier<String?> qx = ValueNotifier(null);
24
+  ValueNotifier<String?> xz = ValueNotifier(null);
25
+  ValueNotifier<String?> cz = ValueNotifier(null);
26
+  ValueNotifier<String?> dllx = ValueNotifier(null);
27
+
28
+  @override
29
+  void initState() {
30
+    super.initState();
31
+    arrowDown = Image.asset(imgItemArrowDown, width: 20);
32
+  }
33
+
34
+  @override
35
+  bool get wantKeepAlive => true;
36
+
37
+  @override
38
+  Widget build(BuildContext context) {
39
+    super.build(context);
40
+    return Column(
41
+      children: [
42
+        Expanded(child: SingleChildScrollView(child: buildList())),
43
+        buildButton(),
44
+      ],
45
+    );
46
+  }
47
+
48
+  Widget buildList() {
49
+    return Column(
50
+      children: [
51
+        CardItemWidget('扦样任务单号', rightText: '自动生成', bottomLine: true),
52
+        CardItemWidget('扦样单位', rightText: '自动生成', bottomLine: true),
53
+        CardItemWidget('扦样人员', rightText: '自动生成', bottomLine: true),
54
+        CardItemWidget('任务类型', rightText: '自动生成', bottomLine: true),
55
+        CardItemWidget('省份选择', rightText: '北京市', bottomLine: true),
56
+        CardItemWidget('市区选择', rightChild: buildMenu(sq), bottomLine: true),
57
+        CardItemWidget('区县选择', rightChild: buildMenu(qx), bottomLine: true),
58
+        CardItemWidget('乡镇选择', rightChild: buildMenu(xz), bottomLine: true),
59
+        CardItemWidget('村选择', rightChild: buildMenu(cz), bottomLine: true),
60
+        CardItemWidget('扦样地点经纬度', rightText: '', hint: '点击获取', bottomLine: true),
61
+        CardItemWidget('种植面积(亩地)', rightChild: buildField(hint: '点击填写'), bottomLine: true),
62
+        CardItemWidget('土壤地理类型', rightChild: buildMenu(dllx), bottomLine: true),
63
+        CardItemWidget('被调查农户或合作社', rightChild: buildField(hint: '点击填写'), bottomLine: true),
64
+        CardItemWidget('联系方式', rightChild: buildField(hint: '点击填写'), bottomLine: true),
65
+      ],
66
+    );
67
+  }
68
+
69
+  Widget buildButton() {
70
+    return Container(
71
+      color: const Color(0xFFF1F7F6),
72
+      padding: const EdgeInsets.all(12),
73
+      child: MyButton(
74
+        '下一步',
75
+        onTap: widget.nextCallback,
76
+      ),
77
+    );
78
+  }
79
+
80
+  Widget buildField({String? hint, TextInputType? inputType}) {
81
+    return TextField(
82
+      keyboardType: inputType,
83
+      textAlign: TextAlign.right,
84
+      decoration: InputDecoration(
85
+        hintText: hint,
86
+        border: InputBorder.none,
87
+        contentPadding: EdgeInsets.zero,
88
+        isDense: true,
89
+      ),
90
+      textInputAction: TextInputAction.next,
91
+      inputFormatters: [],
92
+    );
93
+  }
94
+
95
+  Widget buildMenu(ValueNotifier<String?> notifier) {
96
+    return ValueListenableBuilder(
97
+      valueListenable: notifier,
98
+      builder: (_, value, __) {
99
+        return MenuAnchor(
100
+          builder: (_, ctrl, __) {
101
+            return GestureDetector(
102
+              behavior: HitTestBehavior.opaque,
103
+              onTap: () {
104
+                if (ctrl.isOpen) {
105
+                  ctrl.close();
106
+                } else {
107
+                  ctrl.open();
108
+                }
109
+              },
110
+              child: Row(
111
+                mainAxisSize: MainAxisSize.min,
112
+                children: [
113
+                  Text(
114
+                    value ?? '',
115
+                    textAlign: TextAlign.right,
116
+                    style: const TextStyle(
117
+                      color: Color(0xFF01B2C8),
118
+                      fontSize: 16,
119
+                      fontWeight: FontWeight.w500,
120
+                    ),
121
+                  ),
122
+                  const SizedBox(width: 8),
123
+                  arrowDown,
124
+                ],
125
+              ),
126
+            );
127
+          },
128
+          menuChildren: ['选项一', '选项二', '选项三', '选项四']
129
+              .map(
130
+                (e) => MenuItemButton(
131
+                  child: Text(e),
132
+                  onPressed: () => notifier.value = e,
133
+                ),
134
+              )
135
+              .toList(),
136
+        );
137
+      },
138
+    );
139
+  }
140
+}

+ 195 - 0
lib/page/reap_step/reap_sample_task/reap_sample_disaster_page.dart

@@ -0,0 +1,195 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:lszlgl/base/base_state.dart';
3
+import 'package:lszlgl/widget/button.dart';
4
+import 'package:lszlgl/widget/card_item.dart';
5
+
6
+/// 收获扦样-灾害污染
7
+class ReapSampleDisasterPage extends StatefulWidget {
8
+  final VoidCallback nextCallback;
9
+  final VoidCallback previousCallback;
10
+
11
+  const ReapSampleDisasterPage({
12
+    super.key,
13
+    required this.nextCallback,
14
+    required this.previousCallback,
15
+  });
16
+
17
+  @override
18
+  State<ReapSampleDisasterPage> createState() => _ReapSampleDisasterPageState();
19
+}
20
+
21
+class _ReapSampleDisasterPageState extends BaseState<ReapSampleDisasterPage> with AutomaticKeepAliveClientMixin {
22
+  late Widget arrowDown;
23
+
24
+  // 工厂排污
25
+  ValueNotifier<bool> gcpw = ValueNotifier(false);
26
+
27
+  // 水源污染
28
+  ValueNotifier<bool> sywr = ValueNotifier(false);
29
+
30
+  // 病虫害
31
+  ValueNotifier<bool> bch = ValueNotifier(false);
32
+
33
+  // 阴雨天气
34
+  ValueNotifier<bool> yytq = ValueNotifier(false);
35
+
36
+  // 水分偏高
37
+  ValueNotifier<bool> sfpg = ValueNotifier(false);
38
+
39
+  // 真菌污染
40
+  ValueNotifier<bool> zjwr = ValueNotifier(false);
41
+
42
+  // 金属污染
43
+  ValueNotifier<bool> jswr = ValueNotifier(false);
44
+
45
+  ValueNotifier<String?> pwlx = ValueNotifier(null);
46
+  ValueNotifier<String?> wrlx = ValueNotifier(null);
47
+  ValueNotifier<String?> bchlx = ValueNotifier(null);
48
+  ValueNotifier<String?> zjlx = ValueNotifier(null);
49
+  ValueNotifier<String?> jslx = ValueNotifier(null);
50
+
51
+  @override
52
+  void initState() {
53
+    super.initState();
54
+    arrowDown = Image.asset(imgItemArrowDown, width: 20);
55
+  }
56
+
57
+  @override
58
+  bool get wantKeepAlive => true;
59
+
60
+  @override
61
+  Widget build(BuildContext context) {
62
+    super.build(context);
63
+    return Column(
64
+      children: [
65
+        Expanded(child: SingleChildScrollView(child: buildList())),
66
+        buildButton(),
67
+      ],
68
+    );
69
+  }
70
+
71
+  Widget buildList() {
72
+    return Column(
73
+      children: [
74
+        CardItemWidget('种植土地周围是否有工厂排污', rightChild: buildSwitch(gcpw), bottomLine: true),
75
+        CardItemWidget('工厂排污类型', rightChild: buildMenu(pwlx), bottomLine: true),
76
+        CardItemWidget('种植土地周围使用水源、土壤是否有污染', rightChild: buildSwitch(sywr), bottomLine: true),
77
+        CardItemWidget('污染物类型', rightChild: buildMenu(wrlx), bottomLine: true),
78
+        CardItemWidget('生产过程中是否发生比较严重的病虫害', rightChild: buildSwitch(bch), bottomLine: true),
79
+        CardItemWidget('病虫害类型', rightChild: buildMenu(bchlx), bottomLine: true),
80
+        CardItemWidget('收货期间是否发生连阴雨天气', rightChild: buildSwitch(yytq), bottomLine: true),
81
+        CardItemWidget('收货粮食水分是否偏高', rightChild: buildSwitch(sfpg), bottomLine: true),
82
+        CardItemWidget('近年来本地是否发生真菌毒素污染', rightChild: buildSwitch(zjwr), bottomLine: true),
83
+        CardItemWidget('真菌毒素污染类型', rightChild: buildMenu(zjlx), bottomLine: true),
84
+        CardItemWidget('近年来本地是否发生重金属污染', rightChild: buildSwitch(jswr), bottomLine: true),
85
+        CardItemWidget('重金属污染类型', rightChild: buildMenu(jslx), bottomLine: true),
86
+      ],
87
+    );
88
+  }
89
+
90
+  Widget buildButton() {
91
+    return Container(
92
+      color: const Color(0xFFF1F7F6),
93
+      padding: const EdgeInsets.all(12),
94
+      child: Row(
95
+        children: [
96
+          Expanded(
97
+            flex: 2,
98
+            child: MyButton(
99
+              '上一步',
100
+              onTap: widget.previousCallback,
101
+            ),
102
+          ),
103
+          const Spacer(flex: 1),
104
+          Expanded(
105
+            flex: 2,
106
+            child: MyButton(
107
+              '下一步',
108
+              onTap: widget.nextCallback,
109
+            ),
110
+          ),
111
+        ],
112
+      ),
113
+    );
114
+  }
115
+
116
+  Widget buildField({String? hint, TextInputType? inputType}) {
117
+    return TextField(
118
+      keyboardType: inputType,
119
+      textAlign: TextAlign.right,
120
+      decoration: InputDecoration(
121
+        hintText: hint,
122
+        border: InputBorder.none,
123
+        contentPadding: EdgeInsets.zero,
124
+        isDense: true,
125
+      ),
126
+      inputFormatters: [],
127
+    );
128
+  }
129
+
130
+  Widget buildSwitch(ValueNotifier<bool> notifier) {
131
+    return ValueListenableBuilder<bool>(
132
+      valueListenable: notifier,
133
+      builder: (_, value, __) => Switch(
134
+        value: value,
135
+        onChanged: (change) => notifier.value = change,
136
+      ),
137
+    );
138
+    return ValueListenableBuilder<bool>(
139
+      valueListenable: notifier,
140
+      builder: (_, value, __) => SegmentedButton<bool>(
141
+        segments: const [
142
+          ButtonSegment(value: true, label: Text('是')),
143
+          ButtonSegment(value: false, label: Text('否')),
144
+        ],
145
+        selected: {value},
146
+      ),
147
+    );
148
+  }
149
+
150
+  Widget buildMenu(ValueNotifier<String?> notifier) {
151
+    return ValueListenableBuilder(
152
+      valueListenable: notifier,
153
+      builder: (_, value, __) {
154
+        return MenuAnchor(
155
+          builder: (_, ctrl, __) {
156
+            return GestureDetector(
157
+              behavior: HitTestBehavior.opaque,
158
+              onTap: () {
159
+                if (ctrl.isOpen) {
160
+                  ctrl.close();
161
+                } else {
162
+                  ctrl.open();
163
+                }
164
+              },
165
+              child: Row(
166
+                mainAxisSize: MainAxisSize.min,
167
+                children: [
168
+                  Text(
169
+                    value ?? '',
170
+                    textAlign: TextAlign.right,
171
+                    style: const TextStyle(
172
+                      color: Color(0xFF01B2C8),
173
+                      fontSize: 16,
174
+                      fontWeight: FontWeight.w500,
175
+                    ),
176
+                  ),
177
+                  const SizedBox(width: 8),
178
+                  arrowDown,
179
+                ],
180
+              ),
181
+            );
182
+          },
183
+          menuChildren: ['选项一', '选项二', '选项三', '选项四']
184
+              .map(
185
+                (e) => MenuItemButton(
186
+                  child: Text(e),
187
+                  onPressed: () => notifier.value = e,
188
+                ),
189
+              )
190
+              .toList(),
191
+        );
192
+      },
193
+    );
194
+  }
195
+}

+ 191 - 0
lib/page/reap_step/reap_sample_task/reap_sample_medicine_page.dart

@@ -0,0 +1,191 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:lszlgl/base/base_state.dart';
3
+import 'package:lszlgl/widget/button.dart';
4
+import 'package:lszlgl/widget/card_item.dart';
5
+
6
+/// 收获扦样-用药情况
7
+class ReapSampleMedicinePage extends StatefulWidget {
8
+  final VoidCallback nextCallback;
9
+  final VoidCallback previousCallback;
10
+
11
+  const ReapSampleMedicinePage({
12
+    super.key,
13
+    required this.nextCallback,
14
+    required this.previousCallback,
15
+  });
16
+
17
+  @override
18
+  State<ReapSampleMedicinePage> createState() => _ReapSampleMedicinePageState();
19
+}
20
+
21
+class _ReapSampleMedicinePageState extends BaseState<ReapSampleMedicinePage> with AutomaticKeepAliveClientMixin {
22
+  late Widget arrowDown;
23
+
24
+  List<String> list = [];
25
+
26
+  void add() {
27
+    setState(() {
28
+      list.add('');
29
+    });
30
+  }
31
+
32
+  @override
33
+  void initState() {
34
+    super.initState();
35
+    arrowDown = Image.asset(imgItemArrowDown, width: 20);
36
+  }
37
+
38
+  @override
39
+  bool get wantKeepAlive => true;
40
+
41
+  @override
42
+  Widget build(BuildContext context) {
43
+    super.build(context);
44
+    return Column(
45
+      children: [
46
+        Expanded(child: SingleChildScrollView(child: buildList())),
47
+        buildButton(),
48
+      ],
49
+    );
50
+  }
51
+
52
+  Widget buildList() {
53
+    return Column(
54
+      children: [
55
+        ...List.generate(
56
+          list.length,
57
+          buildItem,
58
+        ).toList(),
59
+        buildAdd(),
60
+      ],
61
+    );
62
+  }
63
+
64
+  Widget buildItem(int index) {
65
+    return Container(
66
+      clipBehavior: Clip.hardEdge,
67
+      decoration: const BoxDecoration(
68
+        color: Color(0xFFF5FFFD),
69
+        borderRadius: BorderRadius.all(Radius.circular(8)),
70
+      ),
71
+      margin: const EdgeInsets.only(left: 12, right: 12, top: 8),
72
+      child: IntrinsicHeight(
73
+        child: Row(
74
+          mainAxisSize: MainAxisSize.min,
75
+          children: [
76
+            Container(
77
+              color: const Color(0xFF3ACEE6),
78
+              alignment: Alignment.center,
79
+              padding: const EdgeInsets.symmetric(horizontal: 2),
80
+              child: Text(
81
+                '${index + 1}',
82
+                style: const TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w700),
83
+              ),
84
+            ),
85
+            Expanded(
86
+              child: Column(
87
+                mainAxisSize: MainAxisSize.min,
88
+                children: [
89
+                  CardItemWidget(
90
+                    '使用农药品种',
91
+                    rightChild: buildField(hint: '点击填写'),
92
+                    bottomLine: true,
93
+                    backgroundColor: null,
94
+                  ),
95
+                  CardItemWidget(
96
+                    '使用农药的数量(公斤或毫升/每亩地)',
97
+                    rightChild: buildField(hint: '点击填写'),
98
+                    bottomLine: true,
99
+                    backgroundColor: null,
100
+                  ),
101
+                  CardItemWidget(
102
+                    '施药时间',
103
+                    rightChild: buildField(hint: '点击填写'),
104
+                    bottomLine: true,
105
+                    backgroundColor: null,
106
+                  ),
107
+                  CardItemWidget(
108
+                    '施药方法',
109
+                    rightChild: buildField(hint: '点击填写'),
110
+                    backgroundColor: null,
111
+                  ),
112
+                ],
113
+              ),
114
+            ),
115
+          ],
116
+        ),
117
+      ),
118
+    );
119
+  }
120
+
121
+  Widget buildAdd() {
122
+    return MyButton(
123
+      '添加用药记录',
124
+      onTap: add,
125
+      margin: const EdgeInsets.symmetric(horizontal: 14, vertical: 22),
126
+      gradient: const LinearGradient(colors: [Color(0xFF3BD2E5), Color(0xFF247AF8)]),
127
+    );
128
+  }
129
+
130
+  Widget buildButton() {
131
+    return Container(
132
+      color: const Color(0xFFF1F7F6),
133
+      padding: const EdgeInsets.all(12),
134
+      child: Row(
135
+        children: [
136
+          Expanded(
137
+            flex: 2,
138
+            child: MyButton(
139
+              '上一步',
140
+              onTap: widget.previousCallback,
141
+            ),
142
+          ),
143
+          const Spacer(flex: 1),
144
+          Expanded(
145
+            flex: 2,
146
+            child: MyButton(
147
+              '下一步',
148
+              onTap: widget.nextCallback,
149
+            ),
150
+          ),
151
+        ],
152
+      ),
153
+    );
154
+  }
155
+
156
+  Widget buildField({String? hint, TextInputType? inputType}) {
157
+    return TextField(
158
+      keyboardType: inputType,
159
+      textAlign: TextAlign.right,
160
+      decoration: InputDecoration(
161
+        hintText: hint,
162
+        border: InputBorder.none,
163
+        contentPadding: EdgeInsets.zero,
164
+        isDense: true,
165
+        counterText: '',
166
+      ),
167
+      textInputAction: TextInputAction.next,
168
+      inputFormatters: [],
169
+    );
170
+  }
171
+
172
+  Widget buildSwitch(ValueNotifier<bool> notifier) {
173
+    return ValueListenableBuilder<bool>(
174
+      valueListenable: notifier,
175
+      builder: (_, value, __) => Switch(
176
+        value: value,
177
+        onChanged: (change) => notifier.value = change,
178
+      ),
179
+    );
180
+    return ValueListenableBuilder<bool>(
181
+      valueListenable: notifier,
182
+      builder: (_, value, __) => SegmentedButton<bool>(
183
+        segments: const [
184
+          ButtonSegment(value: true, label: Text('是')),
185
+          ButtonSegment(value: false, label: Text('否')),
186
+        ],
187
+        selected: {value},
188
+      ),
189
+    );
190
+  }
191
+}

+ 72 - 0
lib/page/reap_step/reap_sample_task/reap_sample_org_page.dart

@@ -0,0 +1,72 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:lszlgl/base/base_state.dart';
3
+import 'package:lszlgl/widget/button.dart';
4
+import 'package:lszlgl/widget/card_item.dart';
5
+
6
+/// 收获扦样-检验机构
7
+class ReapSampleOrgPage extends StatefulWidget {
8
+  final VoidCallback previousCallback;
9
+  final VoidCallback submitCallback;
10
+
11
+  const ReapSampleOrgPage({
12
+    super.key,
13
+    required this.previousCallback,
14
+    required this.submitCallback,
15
+  });
16
+
17
+  @override
18
+  State<ReapSampleOrgPage> createState() => _ReapSampleOrgPageState();
19
+}
20
+
21
+class _ReapSampleOrgPageState extends BaseState<ReapSampleOrgPage> with AutomaticKeepAliveClientMixin {
22
+  @override
23
+  bool get wantKeepAlive => true;
24
+
25
+  @override
26
+  Widget build(BuildContext context) {
27
+    super.build(context);
28
+    return Column(
29
+      children: [
30
+        Expanded(child: SingleChildScrollView(child: buildList())),
31
+        buildButton(),
32
+      ],
33
+    );
34
+  }
35
+
36
+  Widget buildList() {
37
+    return Column(
38
+      children: [
39
+        CardItemWidget('质量检验机构', rightText: '系统代入', bottomLine: true),
40
+        CardItemWidget('机构地址', rightText: '系统代入', bottomLine: true),
41
+        CardItemWidget('食品安全指标检验机构', rightText: '系统代入', bottomLine: true),
42
+        CardItemWidget('机构地址', rightText: '系统代入'),
43
+      ],
44
+    );
45
+  }
46
+
47
+  Widget buildButton() {
48
+    return Container(
49
+      color: const Color(0xFFF1F7F6),
50
+      padding: const EdgeInsets.all(12),
51
+      child: Row(
52
+        children: [
53
+          Expanded(
54
+            flex: 2,
55
+            child: MyButton(
56
+              '上一步',
57
+              onTap: widget.previousCallback,
58
+            ),
59
+          ),
60
+          const Spacer(flex: 1),
61
+          Expanded(
62
+            flex: 2,
63
+            child: MyButton(
64
+              '提交',
65
+              onTap: widget.submitCallback,
66
+            ),
67
+          ),
68
+        ],
69
+      ),
70
+    );
71
+  }
72
+}

+ 189 - 0
lib/page/reap_step/reap_sample_task/reap_sample_task_page.dart

@@ -0,0 +1,189 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
3
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
4
+import 'package:lszlgl/base/base_state.dart';
5
+import 'package:lszlgl/config/colors.dart';
6
+import 'package:lszlgl/page/reap_step/reap_sample_detail/reap_sample_basic_detail_page.dart';
7
+import 'package:lszlgl/page/reap_step/reap_sample_detail/reap_sample_disaster_detail_page.dart';
8
+import 'package:lszlgl/page/reap_step/reap_sample_detail/reap_sample_medicine_detail_page.dart';
9
+import 'package:lszlgl/page/reap_step/reap_sample_detail/reap_sample_org_detail_page.dart';
10
+import 'package:lszlgl/page/reap_step/reap_sample_detail/reap_sample_variety_detail_page.dart';
11
+import 'package:lszlgl/page/reap_step/reap_sample_task/reap_sample_basic_page.dart';
12
+import 'package:lszlgl/page/reap_step/reap_sample_task/reap_sample_disaster_page.dart';
13
+import 'package:lszlgl/page/reap_step/reap_sample_task/reap_sample_medicine_page.dart';
14
+import 'package:lszlgl/page/reap_step/reap_sample_task/reap_sample_org_page.dart';
15
+import 'package:lszlgl/page/reap_step/reap_sample_task/reap_sample_variety_page.dart';
16
+import 'package:lszlgl/page/reap_step/reap_step_list_page.dart';
17
+
18
+/// 收货扦样任务
19
+class ReapSampleTaskPage extends StatefulWidget {
20
+  final bool? detail;
21
+
22
+  const ReapSampleTaskPage({
23
+    Key? key,
24
+    this.detail,
25
+  }) : super(key: key);
26
+
27
+  @override
28
+  State<ReapSampleTaskPage> createState() => _ReapSampleTaskPageState();
29
+}
30
+
31
+class _ReapSampleTaskPageState extends BaseState<ReapSampleTaskPage> with TickerProviderStateMixin {
32
+  late PageController pageCtrl;
33
+
34
+  late List<String> tabTextList;
35
+  late List<Widget> pageList;
36
+
37
+  ValueNotifier<int> tabIndex = ValueNotifier(0);
38
+
39
+  void next() {
40
+    if (tabIndex.value < tabTextList.length - 1) {
41
+      pageCtrl.jumpToPage(tabIndex.value + 1);
42
+    }
43
+  }
44
+
45
+  void previous() {
46
+    if (tabIndex.value <= 0) return;
47
+    pageCtrl.jumpToPage(tabIndex.value - 1);
48
+  }
49
+
50
+  void submit() {
51
+    Nav.pop();
52
+    SmartDialog.showToast('提交成功');
53
+  }
54
+
55
+  @override
56
+  void initState() {
57
+    super.initState();
58
+    tabTextList = ['基础信息', '品种信息', '灾害污染', '用药情况', '检验机构'];
59
+    if (widget.detail ?? false) {
60
+      pageList = [
61
+        ReapSampleBasicDetailPage(),
62
+        ReapSampleVarietyDetailPage(),
63
+        ReapSampleDisasterDetailPage(),
64
+        ReapSampleMedicineDetailPage(),
65
+        ReapSampleOrgDetailPage(),
66
+      ];
67
+    } else {
68
+      pageList = [
69
+        ReapSampleBasicPage(nextCallback: next),
70
+        ReapSampleVarietyPage(nextCallback: next, previousCallback: previous),
71
+        ReapSampleDisasterPage(nextCallback: next, previousCallback: previous),
72
+        ReapSampleMedicinePage(nextCallback: next, previousCallback: previous),
73
+        ReapSampleOrgPage(previousCallback: previous, submitCallback: submit),
74
+      ];
75
+    }
76
+
77
+    pageCtrl = PageController();
78
+  }
79
+
80
+  @override
81
+  Widget build(BuildContext context) {
82
+    return myScaffold(child: buildBody());
83
+  }
84
+
85
+  Widget buildBody() {
86
+    return KeyboardDismissOnTap(
87
+      dismissOnCapturedTaps: true,
88
+      child: Column(
89
+        children: [
90
+          myAppBar(title:(widget.detail ?? false)?'扦样完成详情':'扦样任务单'),
91
+          Expanded(
92
+            child: Container(
93
+              clipBehavior: Clip.hardEdge,
94
+              decoration: const BoxDecoration(
95
+                color: Colors.white,
96
+                borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
97
+              ),
98
+              child: Column(
99
+                children: [
100
+                  buildTab(),
101
+                  Expanded(child: buildPage()),
102
+                ],
103
+              ),
104
+            ),
105
+          ),
106
+        ],
107
+      ),
108
+    );
109
+  }
110
+
111
+  Widget buildTab() {
112
+    return ValueListenableBuilder<int>(
113
+      valueListenable: tabIndex,
114
+      builder: (_, value, __) {
115
+        return Container(
116
+          height: 40,
117
+          color: Colors.white,
118
+          padding: const EdgeInsets.symmetric(horizontal: 4),
119
+          child: Row(
120
+            children: List.generate(
121
+              tabTextList.length,
122
+              buildTabItem,
123
+            ),
124
+          ),
125
+        );
126
+      },
127
+    );
128
+  }
129
+
130
+  Widget buildTabItem(int index) {
131
+    var select = index == tabIndex.value;
132
+    return Expanded(
133
+      child: GestureDetector(
134
+        behavior: HitTestBehavior.opaque,
135
+        onTap: () {
136
+          tabIndex.value = index;
137
+          if ((pageCtrl.page?.toInt() ?? 0) == index) return;
138
+          pageCtrl.jumpToPage(index);
139
+        },
140
+        child: Container(
141
+          alignment: Alignment.center,
142
+          child: Stack(
143
+            children: [
144
+              buildTabLine(select),
145
+              Text(
146
+                tabTextList[index],
147
+                style: TextStyle(
148
+                  fontSize: select ? 18 : 15,
149
+                  color: select ? MyColor.c_333333 : MyColor.c_467F86,
150
+                  fontWeight: select ? FontWeight.w700 : FontWeight.w400,
151
+                ),
152
+              ),
153
+            ],
154
+          ),
155
+        ),
156
+      ),
157
+    );
158
+  }
159
+
160
+  Widget buildTabLine(bool show) {
161
+    if (!show) return const SizedBox.shrink();
162
+    return Positioned(
163
+      left: 0,
164
+      right: 0,
165
+      bottom: 0,
166
+      child: Container(
167
+        height: 8,
168
+        decoration: const BoxDecoration(
169
+          gradient: LinearGradient(
170
+            colors: [Color(0xFF3BD2E5), Color(0xFF2379F8)],
171
+          ),
172
+        ),
173
+      ),
174
+    );
175
+  }
176
+
177
+  Widget buildPage() {
178
+    return PageView.builder(
179
+      controller: pageCtrl,
180
+      // physics: const BouncingScrollPhysics(),
181
+      onPageChanged: (index) {
182
+        if (index == tabIndex.value) return;
183
+        tabIndex.value = index;
184
+      },
185
+      itemCount: pageList.length,
186
+      itemBuilder: (_, index) => pageList[index],
187
+    );
188
+  }
189
+}

+ 185 - 0
lib/page/reap_step/reap_sample_task/reap_sample_variety_page.dart

@@ -0,0 +1,185 @@
1
+import 'package:date_format/date_format.dart';
2
+import 'package:flutter/material.dart';
3
+import 'package:lszlgl/base/base_state.dart';
4
+import 'package:lszlgl/widget/button.dart';
5
+import 'package:lszlgl/widget/card_item.dart';
6
+
7
+/// 收获扦样-品种信息
8
+class ReapSampleVarietyPage extends StatefulWidget {
9
+  final VoidCallback nextCallback;
10
+  final VoidCallback previousCallback;
11
+
12
+  const ReapSampleVarietyPage({
13
+    super.key,
14
+    required this.nextCallback,
15
+    required this.previousCallback,
16
+  });
17
+
18
+  @override
19
+  State<ReapSampleVarietyPage> createState() => _ReapSampleVarietyPageState();
20
+}
21
+
22
+class _ReapSampleVarietyPageState extends BaseState<ReapSampleVarietyPage> with AutomaticKeepAliveClientMixin {
23
+  late Widget arrowDown;
24
+
25
+  ValueNotifier<String?> lspl = ValueNotifier(null);
26
+  ValueNotifier<String?> yzpz = ValueNotifier(null);
27
+  ValueNotifier<String?> yzpzlx = ValueNotifier(null);
28
+
29
+  ValueNotifier<String?> shsj = ValueNotifier(null);
30
+  ValueNotifier<String?> qysj = ValueNotifier(null);
31
+
32
+  void showDate(ValueNotifier<String?> notifier) async {
33
+    var date = await showDatePicker(
34
+      context: context,
35
+      firstDate: DateTime(2020),
36
+      lastDate: DateTime.now(),
37
+    );
38
+    if (date == null) return;
39
+    notifier.value = formatDate(date, [yyyy, '-', mm, '-', dd]);
40
+  }
41
+
42
+  @override
43
+  void initState() {
44
+    super.initState();
45
+    arrowDown = Image.asset(imgItemArrowDown, width: 20);
46
+  }
47
+
48
+  @override
49
+  bool get wantKeepAlive => true;
50
+
51
+  @override
52
+  Widget build(BuildContext context) {
53
+    super.build(context);
54
+    return Column(
55
+      children: [
56
+        Expanded(child: SingleChildScrollView(child: buildList())),
57
+        buildButton(),
58
+      ],
59
+    );
60
+  }
61
+
62
+  Widget buildList() {
63
+    return Column(
64
+      children: [
65
+        CardItemWidget('采样品种', rightText: '自动生成', bottomLine: true),
66
+        CardItemWidget('粮食品类', rightChild: buildMenu(lspl), bottomLine: true),
67
+        CardItemWidget('样品编号', rightText: '自动生成', bottomLine: true),
68
+        CardItemWidget('种植品种', rightChild: buildField(hint: '点击填写'), bottomLine: true),
69
+        CardItemWidget('是否优质品种', rightChild: buildMenu(yzpz), bottomLine: true),
70
+        CardItemWidget('优质品种类型', rightChild: buildMenu(yzpzlx), bottomLine: true),
71
+        ValueListenableBuilder(
72
+          valueListenable: shsj,
73
+          builder: (_, value, __) => CardItemWidget(
74
+            '收获时间',
75
+            rightText: value ?? '',
76
+            trailing: arrowDown,
77
+            bottomLine: true,
78
+            onTap: () => showDate(shsj),
79
+          ),
80
+        ),
81
+        ValueListenableBuilder(
82
+          valueListenable: qysj,
83
+          builder: (_, value, __) => CardItemWidget(
84
+            '扦样时间',
85
+            rightText: value ?? '',
86
+            trailing: arrowDown,
87
+            bottomLine: true,
88
+            onTap: () => showDate(qysj),
89
+          ),
90
+        ),
91
+        CardItemWidget('扦样数量(公斤)', rightChild: buildField(hint: '点击填写'), bottomLine: true),
92
+        CardItemWidget('扦样代表数量(公斤)', rightChild: buildField(hint: '点击填写'), bottomLine: true),
93
+        CardItemWidget('温度(℃)', rightChild: buildField(hint: '点击填写'), bottomLine: true),
94
+        CardItemWidget('湿度(%)', rightChild: buildField(hint: '点击填写')),
95
+      ],
96
+    );
97
+  }
98
+
99
+  Widget buildButton() {
100
+    return Container(
101
+      color: const Color(0xFFF1F7F6),
102
+      padding: const EdgeInsets.all(12),
103
+      child: Row(
104
+        children: [
105
+          Expanded(
106
+            flex: 2,
107
+            child: MyButton(
108
+              '上一步',
109
+              onTap: widget.previousCallback,
110
+            ),
111
+          ),
112
+          const Spacer(flex: 1),
113
+          Expanded(
114
+            flex: 2,
115
+            child: MyButton(
116
+              '下一步',
117
+              onTap: widget.nextCallback,
118
+            ),
119
+          ),
120
+        ],
121
+      ),
122
+    );
123
+  }
124
+
125
+  Widget buildField({String? hint, TextInputType? inputType}) {
126
+    return TextField(
127
+      keyboardType: inputType,
128
+      textAlign: TextAlign.right,
129
+      decoration: InputDecoration(
130
+        hintText: hint,
131
+        border: InputBorder.none,
132
+        contentPadding: EdgeInsets.zero,
133
+        isDense: true,
134
+      ),
135
+      textInputAction: TextInputAction.next,
136
+      inputFormatters: [],
137
+    );
138
+  }
139
+
140
+  Widget buildMenu(ValueNotifier<String?> notifier) {
141
+    return ValueListenableBuilder(
142
+      valueListenable: notifier,
143
+      builder: (_, value, __) {
144
+        return MenuAnchor(
145
+          builder: (_, ctrl, __) {
146
+            return GestureDetector(
147
+              behavior: HitTestBehavior.opaque,
148
+              onTap: () {
149
+                if (ctrl.isOpen) {
150
+                  ctrl.close();
151
+                } else {
152
+                  ctrl.open();
153
+                }
154
+              },
155
+              child: Row(
156
+                mainAxisSize: MainAxisSize.min,
157
+                children: [
158
+                  Text(
159
+                    value ?? '',
160
+                    textAlign: TextAlign.right,
161
+                    style: const TextStyle(
162
+                      color: Color(0xFF01B2C8),
163
+                      fontSize: 16,
164
+                      fontWeight: FontWeight.w500,
165
+                    ),
166
+                  ),
167
+                  const SizedBox(width: 8),
168
+                  arrowDown,
169
+                ],
170
+              ),
171
+            );
172
+          },
173
+          menuChildren: ['选项一', '选项二', '选项三', '选项四']
174
+              .map(
175
+                (e) => MenuItemButton(
176
+                  child: Text(e),
177
+                  onPressed: () => notifier.value = e,
178
+                ),
179
+              )
180
+              .toList(),
181
+        );
182
+      },
183
+    );
184
+  }
185
+}

+ 232 - 0
lib/page/reap_step/reap_step_list_page.dart

@@ -0,0 +1,232 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:lszlgl/base/base_state.dart';
3
+import 'package:lszlgl/config/colors.dart';
4
+import 'package:lszlgl/page/reap_step/reap_step_tab_page.dart';
5
+import 'package:lszlgl/widget/button.dart';
6
+
7
+/// 扦样环节列表
8
+class ReapStepListPage extends StatefulWidget {
9
+  final StepType type;
10
+  final bool complete;
11
+
12
+  const ReapStepListPage({
13
+    super.key,
14
+    required this.type,
15
+    this.complete = false,
16
+  });
17
+
18
+  @override
19
+  State<ReapStepListPage> createState() => _ReapStepListPageState();
20
+}
21
+
22
+class _ReapStepListPageState extends State<ReapStepListPage> {
23
+  late List<Map<String, String>> infoList;
24
+
25
+  /// 详情
26
+  void startDetail() {
27
+    if (!widget.complete) return;
28
+    switch (widget.type) {
29
+      case StepType.reap:
30
+        MyRouter.startReapSampleTask(detail: true);
31
+        break;
32
+      case StepType.stock:
33
+        break;
34
+    }
35
+  }
36
+
37
+  /// 扦样
38
+  void startSample() {
39
+    switch (widget.type) {
40
+      case StepType.reap:
41
+        MyRouter.startReapSampleTask();
42
+        break;
43
+      case StepType.stock:
44
+        break;
45
+    }
46
+  }
47
+
48
+  @override
49
+  void initState() {
50
+    super.initState();
51
+    String taskType = switch (widget.type) {
52
+      StepType.reap => '收购监测',
53
+      StepType.stock => '库存监测',
54
+      _ => '',
55
+    };
56
+    if (widget.complete) {
57
+      infoList = [
58
+        {'采样品种': '玉米'},
59
+        {'粮食品类': '粮食品类'},
60
+        {'任务类型': taskType},
61
+        {'扦样数量(kg)': '10'},
62
+        {'扦样人员': '李飞'},
63
+        {'扦样时间': '2024-01-01'},
64
+      ];
65
+    } else {
66
+      infoList = [
67
+        {'采样品种': '玉米'},
68
+        {'报送截止时间': '2024-01-01'},
69
+        {'任务类型': taskType},
70
+        {'扦样人员': '李飞'},
71
+      ];
72
+    }
73
+  }
74
+
75
+  @override
76
+  Widget build(BuildContext context) {
77
+    return Container(
78
+      clipBehavior: Clip.hardEdge,
79
+      decoration: const BoxDecoration(
80
+        color: Colors.white,
81
+        borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
82
+      ),
83
+      alignment: Alignment.center,
84
+      child: buildList(),
85
+    );
86
+  }
87
+
88
+  Widget buildList() {
89
+    return ListView.builder(
90
+      physics: const BouncingScrollPhysics(),
91
+      padding: EdgeInsets.zero,
92
+      itemCount: 10,
93
+      itemBuilder: (_, index) => buildItem(index),
94
+    );
95
+  }
96
+
97
+  Widget buildItem(int index) {
98
+    return GestureDetector(
99
+      behavior: HitTestBehavior.opaque,
100
+      onTap: () => startDetail(),
101
+      child: Container(
102
+        margin: const EdgeInsets.only(left: 12, right: 12, top: 12),
103
+        decoration: const BoxDecoration(
104
+          color: Color(0xFFF5FFFD),
105
+          borderRadius: BorderRadius.all(Radius.circular(8)),
106
+        ),
107
+        child: Column(
108
+          crossAxisAlignment: CrossAxisAlignment.start,
109
+          children: [
110
+            const SizedBox(height: 15),
111
+            buildTop(),
112
+            buildNumber(),
113
+            buildGrid(),
114
+            buildBottom(),
115
+            const SizedBox(height: 15),
116
+          ],
117
+        ),
118
+      ),
119
+    );
120
+  }
121
+
122
+  Widget buildTop() {
123
+    return Row(
124
+      children: [
125
+        buildVLine(),
126
+        const Expanded(
127
+          child: Text(
128
+            '扦样任务单号',
129
+            style: TextStyle(color: MyColor.c_333333, fontSize: 18, fontWeight: FontWeight.w500),
130
+          ),
131
+        ),
132
+        buildState(),
133
+      ],
134
+    );
135
+  }
136
+
137
+  Widget buildVLine() {
138
+    return Container(
139
+      width: 4,
140
+      height: 20,
141
+      margin: const EdgeInsets.only(right: 8),
142
+      decoration: const BoxDecoration(
143
+        color: MyColor.c_25A6EE,
144
+        borderRadius: BorderRadius.all(Radius.circular(2)),
145
+      ),
146
+    );
147
+  }
148
+
149
+  Widget buildState() {
150
+    String state = widget.complete ? '已扦样' : '待扦样';
151
+    return Container(
152
+      padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 4),
153
+      decoration: BoxDecoration(
154
+        color: MyColor.c_25A6EE.withOpacity(0.1),
155
+        borderRadius: const BorderRadius.horizontal(left: Radius.circular(100)),
156
+      ),
157
+      child: Text(
158
+        '状态:$state',
159
+        style: const TextStyle(color: MyColor.c_1383C2, fontSize: 16),
160
+      ),
161
+    );
162
+  }
163
+
164
+  Widget buildNumber() {
165
+    return const Padding(
166
+      padding: EdgeInsets.only(left: 12, top: 4, bottom: 6),
167
+      child: Text(
168
+        '***********',
169
+        style: TextStyle(color: MyColor.c_333333, fontSize: 18, fontWeight: FontWeight.w500),
170
+      ),
171
+    );
172
+  }
173
+
174
+  Widget buildGrid() {
175
+    return Padding(
176
+      padding: const EdgeInsets.symmetric(horizontal: 12),
177
+      child: LayoutBuilder(builder: (context, constraints) {
178
+        return Wrap(
179
+          spacing: 4,
180
+          runSpacing: 4,
181
+          children: infoList.map((item) {
182
+            return SizedBox(
183
+              width: constraints.maxWidth / 2 - 2,
184
+              child: Text(
185
+                '${item.keys.first}:${item.values.first}',
186
+                style: const TextStyle(fontSize: 16, color: MyColor.c_666666),
187
+              ),
188
+            );
189
+          }).toList(),
190
+        );
191
+      }),
192
+    );
193
+  }
194
+
195
+  Widget buildBottom() {
196
+    if (widget.complete) return const SizedBox.shrink();
197
+    return Column(
198
+      children: [
199
+        buildDivider(),
200
+        Row(
201
+          children: [
202
+            const SizedBox(width: 12),
203
+            const Expanded(
204
+              child: Text(
205
+                '[张三]创建于2024-01-01 00:00:00',
206
+                style: TextStyle(fontSize: 16, color: MyColor.c_666666),
207
+              ),
208
+            ),
209
+            const SizedBox(width: 4),
210
+            MyButton(
211
+              '开始扦样',
212
+              onTap: () => startSample(),
213
+              fountSize: 16,
214
+              alignment: null,
215
+              padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
216
+            ),
217
+            const SizedBox(width: 12),
218
+          ],
219
+        ),
220
+      ],
221
+    );
222
+  }
223
+
224
+  Widget buildDivider() {
225
+    return Container(
226
+      width: double.infinity,
227
+      height: 1,
228
+      color: MyColor.c_3BD2E5.withOpacity(0.15),
229
+      margin: const EdgeInsets.symmetric(vertical: 10),
230
+    );
231
+  }
232
+}

+ 119 - 0
lib/page/reap_step/reap_step_tab_page.dart

@@ -0,0 +1,119 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:lszlgl/base/base_state.dart';
3
+import 'package:lszlgl/config/colors.dart';
4
+import 'package:lszlgl/page/reap_step/reap_step_list_page.dart';
5
+
6
+enum StepType {
7
+  reap(title: '收获环节'),
8
+  stock(title: '库存环节');
9
+
10
+  const StepType({required this.title});
11
+
12
+  final String title;
13
+}
14
+
15
+class ReapStepTabPageArgs {
16
+  final StepType type;
17
+
18
+  const ReapStepTabPageArgs({required this.type});
19
+}
20
+
21
+/// 收获环节
22
+class ReapStepTabPage extends StatefulWidget {
23
+  final ReapStepTabPageArgs args;
24
+
25
+  const ReapStepTabPage({
26
+    Key? key,
27
+    ReapStepTabPageArgs? args,
28
+  })  : args = args ?? const ReapStepTabPageArgs(type: StepType.reap),
29
+        super(key: key);
30
+
31
+  @override
32
+  State<ReapStepTabPage> createState() => _ReapStepTabPageState();
33
+}
34
+
35
+class _ReapStepTabPageState extends BaseState<ReapStepTabPage> with TickerProviderStateMixin {
36
+  late TabController tabCtrl;
37
+  late PageController pageCtrl;
38
+
39
+  late List<String> tabTextList;
40
+  late List<Widget> pageList;
41
+
42
+  @override
43
+  void initState() {
44
+    super.initState();
45
+    tabCtrl = TabController(length: 2, vsync: this);
46
+    pageCtrl = PageController();
47
+
48
+    tabTextList = ['待扦样', '扦样完成'];
49
+    pageList = [
50
+      ReapStepListPage(type: widget.args.type),
51
+      ReapStepListPage(type: widget.args.type, complete: true),
52
+    ];
53
+  }
54
+
55
+  @override
56
+  Widget build(BuildContext context) {
57
+    return myScaffold(child: buildBody());
58
+  }
59
+
60
+  Widget buildBody() {
61
+    return Column(
62
+      children: [
63
+        myAppBar(title: widget.args.type.title),
64
+        buildTab(),
65
+        const SizedBox(height: 12),
66
+        Expanded(child: buildPage()),
67
+      ],
68
+    );
69
+  }
70
+
71
+  Widget buildTab() {
72
+    return Container(
73
+      clipBehavior: Clip.hardEdge,
74
+      height: 36,
75
+      decoration: const BoxDecoration(
76
+        color: Colors.white,
77
+        borderRadius: BorderRadius.all(Radius.circular(100)),
78
+        border: Border.fromBorderSide(BorderSide(color: Colors.white, width: 1)),
79
+      ),
80
+      child: TabBar(
81
+        controller: tabCtrl,
82
+        onTap: (index) {
83
+          if ((pageCtrl.page?.toInt() ?? 0) == index) return;
84
+          pageCtrl.animateToPage(index, duration: const Duration(milliseconds: 200), curve: Curves.ease);
85
+        },
86
+        tabAlignment: TabAlignment.center,
87
+        indicator: const BoxDecoration(
88
+          borderRadius: BorderRadius.all(Radius.circular(100)),
89
+          color: MyColor.c_28A3ED,
90
+        ),
91
+        indicatorSize: TabBarIndicatorSize.tab,
92
+        dividerHeight: 0,
93
+        labelStyle: const TextStyle(
94
+          fontSize: 14,
95
+          fontWeight: FontWeight.w500,
96
+          color: Colors.white,
97
+        ),
98
+        unselectedLabelStyle: const TextStyle(
99
+          fontSize: 14,
100
+          color: MyColor.c_28A3ED,
101
+        ),
102
+        tabs: tabTextList.map((text) => Tab(text: text)).toList(),
103
+      ),
104
+    );
105
+  }
106
+
107
+  Widget buildPage() {
108
+    return PageView.builder(
109
+      controller: pageCtrl,
110
+      // physics: const BouncingScrollPhysics(),
111
+      onPageChanged: (index) {
112
+        if (index == tabCtrl.index) return;
113
+        tabCtrl.animateTo(index);
114
+      },
115
+      itemCount: pageList.length,
116
+      itemBuilder: (_, index) => pageList[index],
117
+    );
118
+  }
119
+}

+ 22 - 0
lib/page/unknow_page.dart

@@ -0,0 +1,22 @@
1
+import 'package:flutter/material.dart';
2
+
3
+/// 未知页面
4
+class UnknownPage extends StatelessWidget {
5
+  final String? name;
6
+
7
+  const UnknownPage({
8
+    Key? key,
9
+    this.name,
10
+  }) : super(key: key);
11
+
12
+  @override
13
+  Widget build(BuildContext context) {
14
+    return Scaffold(
15
+      appBar: AppBar(),
16
+      body: Container(
17
+        alignment: Alignment.center,
18
+        child: Text("${name ?? ''}页面不存在"),
19
+      ),
20
+    );
21
+  }
22
+}

+ 0 - 0
lib/page/user_center/account_manage_page.dart


Some files were not shown because too many files changed in this diff