commit a0e57fcdfa48436489c40e836ba4f2ee67cb7b54 Author: hs <873121290@qq.com> Date: Thu Jul 3 09:45:15 2025 +0800 初始化企业端 Flutter 项目 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..79c113f --- /dev/null +++ b/.gitignore @@ -0,0 +1,45 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..3bb6b3c --- /dev/null +++ b/.metadata @@ -0,0 +1,33 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "35c388afb57ef061d06a39b537336c87e0e3d1b1" + channel: "stable" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 35c388afb57ef061d06a39b537336c87e0e3d1b1 + base_revision: 35c388afb57ef061d06a39b537336c87e0e3d1b1 + - platform: android + create_revision: 35c388afb57ef061d06a39b537336c87e0e3d1b1 + base_revision: 35c388afb57ef061d06a39b537336c87e0e3d1b1 + - platform: ios + create_revision: 35c388afb57ef061d06a39b537336c87e0e3d1b1 + base_revision: 35c388afb57ef061d06a39b537336c87e0e3d1b1 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/README.md b/README.md new file mode 100644 index 0000000..ed84766 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# qhd_prevention + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..5c7a25e --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,30 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + camel_case_types: false + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..be3943c --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,14 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java +.cxx/ + +# Remember to never publicly share your keystore. +# See https://flutter.dev/to/reference-keystore +key.properties +**/*.keystore +**/*.jks diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts new file mode 100644 index 0000000..8637db3 --- /dev/null +++ b/android/app/build.gradle.kts @@ -0,0 +1,44 @@ +plugins { + id("com.android.application") + id("kotlin-android") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "com.zhuoyun.qhdprevention.qhd_prevention" + compileSdk = flutter.compileSdkVersion + ndkVersion = "28.1.13356709" + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_11.toString() + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.zhuoyun.qhdprevention.qhd_prevention" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +flutter { + source = "../.." +} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..38da250 --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/com/zhuoyun/qhdprevention/qhd_prevention/MainActivity.kt b/android/app/src/main/kotlin/com/zhuoyun/qhdprevention/qhd_prevention/MainActivity.kt new file mode 100644 index 0000000..4a716d1 --- /dev/null +++ b/android/app/src/main/kotlin/com/zhuoyun/qhdprevention/qhd_prevention/MainActivity.kt @@ -0,0 +1,5 @@ +package com.zhuoyun.qhdprevention.qhd_prevention + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity : FlutterActivity() diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..db77bb4 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..17987b7 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..09d4391 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..d5f1c8d Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..4d6372e Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..06952be --- /dev/null +++ b/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..cb1ef88 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/build.gradle.kts b/android/build.gradle.kts new file mode 100644 index 0000000..89176ef --- /dev/null +++ b/android/build.gradle.kts @@ -0,0 +1,21 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..f018a61 --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError +android.useAndroidX=true +android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..afa1e8e --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts new file mode 100644 index 0000000..a439442 --- /dev/null +++ b/android/settings.gradle.kts @@ -0,0 +1,25 @@ +pluginManagement { + val flutterSdkPath = run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "8.7.0" apply false + id("org.jetbrains.kotlin.android") version "1.8.22" apply false +} + +include(":app") diff --git a/assets/icon-apps/home-base.png b/assets/icon-apps/home-base.png new file mode 100644 index 0000000..f61e4fe Binary files /dev/null and b/assets/icon-apps/home-base.png differ diff --git a/assets/icon-apps/home-cns.png b/assets/icon-apps/home-cns.png new file mode 100644 index 0000000..2748674 Binary files /dev/null and b/assets/icon-apps/home-cns.png differ diff --git a/assets/icon-apps/home-file.png b/assets/icon-apps/home-file.png new file mode 100644 index 0000000..7e6270e Binary files /dev/null and b/assets/icon-apps/home-file.png differ diff --git a/assets/icon-apps/home-fl.png b/assets/icon-apps/home-fl.png new file mode 100644 index 0000000..311e176 Binary files /dev/null and b/assets/icon-apps/home-fl.png differ diff --git a/assets/icon-apps/home-gw.png b/assets/icon-apps/home-gw.png new file mode 100644 index 0000000..0ab1d3a Binary files /dev/null and b/assets/icon-apps/home-gw.png differ diff --git a/assets/icon-apps/home-rili.png b/assets/icon-apps/home-rili.png new file mode 100644 index 0000000..419e6b4 Binary files /dev/null and b/assets/icon-apps/home-rili.png differ diff --git a/assets/icon-apps/home-risk.png b/assets/icon-apps/home-risk.png new file mode 100644 index 0000000..0f87f56 Binary files /dev/null and b/assets/icon-apps/home-risk.png differ diff --git a/assets/icon-apps/home-speEquip.jpg b/assets/icon-apps/home-speEquip.jpg new file mode 100644 index 0000000..c56a742 Binary files /dev/null and b/assets/icon-apps/home-speEquip.jpg differ diff --git a/assets/icon-apps/home-study.png b/assets/icon-apps/home-study.png new file mode 100644 index 0000000..8ba8b01 Binary files /dev/null and b/assets/icon-apps/home-study.png differ diff --git a/assets/icon-apps/icon-800.png b/assets/icon-apps/icon-800.png new file mode 100644 index 0000000..62cd09a Binary files /dev/null and b/assets/icon-apps/icon-800.png differ diff --git a/assets/icon-apps/icon-801.png b/assets/icon-apps/icon-801.png new file mode 100644 index 0000000..7031bb6 Binary files /dev/null and b/assets/icon-apps/icon-801.png differ diff --git a/assets/icon-apps/icon-802.png b/assets/icon-apps/icon-802.png new file mode 100644 index 0000000..97208b7 Binary files /dev/null and b/assets/icon-apps/icon-802.png differ diff --git a/assets/icon-apps/icon-803.png b/assets/icon-apps/icon-803.png new file mode 100644 index 0000000..e69be2c Binary files /dev/null and b/assets/icon-apps/icon-803.png differ diff --git a/assets/icon-apps/icon-804.png b/assets/icon-apps/icon-804.png new file mode 100644 index 0000000..becce6f Binary files /dev/null and b/assets/icon-apps/icon-804.png differ diff --git a/assets/icon-apps/icon-805.png b/assets/icon-apps/icon-805.png new file mode 100644 index 0000000..38e7628 Binary files /dev/null and b/assets/icon-apps/icon-805.png differ diff --git a/assets/icon-apps/icon-806.png b/assets/icon-apps/icon-806.png new file mode 100644 index 0000000..de07927 Binary files /dev/null and b/assets/icon-apps/icon-806.png differ diff --git a/assets/icon-apps/icon-807.png b/assets/icon-apps/icon-807.png new file mode 100644 index 0000000..5699dda Binary files /dev/null and b/assets/icon-apps/icon-807.png differ diff --git a/assets/icon-apps/icon-901.png b/assets/icon-apps/icon-901.png new file mode 100644 index 0000000..765f12a Binary files /dev/null and b/assets/icon-apps/icon-901.png differ diff --git a/assets/icon-apps/icon-902.png b/assets/icon-apps/icon-902.png new file mode 100644 index 0000000..31f56b3 Binary files /dev/null and b/assets/icon-apps/icon-902.png differ diff --git a/assets/icon-apps/icon-903.png b/assets/icon-apps/icon-903.png new file mode 100644 index 0000000..c86c652 Binary files /dev/null and b/assets/icon-apps/icon-903.png differ diff --git a/assets/icon-apps/icon-904.png b/assets/icon-apps/icon-904.png new file mode 100644 index 0000000..d4525d9 Binary files /dev/null and b/assets/icon-apps/icon-904.png differ diff --git a/assets/icon-apps/icon-905.png b/assets/icon-apps/icon-905.png new file mode 100644 index 0000000..c5526bb Binary files /dev/null and b/assets/icon-apps/icon-905.png differ diff --git a/assets/icon-apps/icon-906.png b/assets/icon-apps/icon-906.png new file mode 100644 index 0000000..bbd3817 Binary files /dev/null and b/assets/icon-apps/icon-906.png differ diff --git a/assets/icon-apps/icon-907.png b/assets/icon-apps/icon-907.png new file mode 100644 index 0000000..f46d612 Binary files /dev/null and b/assets/icon-apps/icon-907.png differ diff --git a/assets/icon-apps/icon-pc-1.png b/assets/icon-apps/icon-pc-1.png new file mode 100644 index 0000000..8f4c696 Binary files /dev/null and b/assets/icon-apps/icon-pc-1.png differ diff --git a/assets/icon-apps/icon-yh-1.png b/assets/icon-apps/icon-yh-1.png new file mode 100644 index 0000000..0f0d814 Binary files /dev/null and b/assets/icon-apps/icon-yh-1.png differ diff --git a/assets/icon-apps/icon-yxkj-1.png b/assets/icon-apps/icon-yxkj-1.png new file mode 100644 index 0000000..feeddb3 Binary files /dev/null and b/assets/icon-apps/icon-yxkj-1.png differ diff --git a/assets/icon-apps/icon-yxkj-2.png b/assets/icon-apps/icon-yxkj-2.png new file mode 100644 index 0000000..efee965 Binary files /dev/null and b/assets/icon-apps/icon-yxkj-2.png differ diff --git a/assets/icon-apps/icon-yxkj-4.png b/assets/icon-apps/icon-yxkj-4.png new file mode 100644 index 0000000..91ed148 Binary files /dev/null and b/assets/icon-apps/icon-yxkj-4.png differ diff --git a/assets/icon-apps/icon-zl-1.png b/assets/icon-apps/icon-zl-1.png new file mode 100644 index 0000000..c9eebb9 Binary files /dev/null and b/assets/icon-apps/icon-zl-1.png differ diff --git a/assets/icon-apps/icon-zl-10.png b/assets/icon-apps/icon-zl-10.png new file mode 100644 index 0000000..6a02bf6 Binary files /dev/null and b/assets/icon-apps/icon-zl-10.png differ diff --git a/assets/icon-apps/icon-zl-2.png b/assets/icon-apps/icon-zl-2.png new file mode 100644 index 0000000..1685996 Binary files /dev/null and b/assets/icon-apps/icon-zl-2.png differ diff --git a/assets/icon-apps/icon-zl-3.png b/assets/icon-apps/icon-zl-3.png new file mode 100644 index 0000000..0ba14be Binary files /dev/null and b/assets/icon-apps/icon-zl-3.png differ diff --git a/assets/icon-apps/icon-zl-4.png b/assets/icon-apps/icon-zl-4.png new file mode 100644 index 0000000..fd4e9d8 Binary files /dev/null and b/assets/icon-apps/icon-zl-4.png differ diff --git a/assets/icon-apps/icon-zl-5.png b/assets/icon-apps/icon-zl-5.png new file mode 100644 index 0000000..571e57c Binary files /dev/null and b/assets/icon-apps/icon-zl-5.png differ diff --git a/assets/icon-apps/icon-zl-6.png b/assets/icon-apps/icon-zl-6.png new file mode 100644 index 0000000..8a28c25 Binary files /dev/null and b/assets/icon-apps/icon-zl-6.png differ diff --git a/assets/icon-apps/icon-zl-7.png b/assets/icon-apps/icon-zl-7.png new file mode 100644 index 0000000..2300341 Binary files /dev/null and b/assets/icon-apps/icon-zl-7.png differ diff --git a/assets/icon-apps/icon-zl-8.png b/assets/icon-apps/icon-zl-8.png new file mode 100644 index 0000000..6c901e8 Binary files /dev/null and b/assets/icon-apps/icon-zl-8.png differ diff --git a/assets/icon-apps/icon-zl-9.png b/assets/icon-apps/icon-zl-9.png new file mode 100644 index 0000000..7f1f47e Binary files /dev/null and b/assets/icon-apps/icon-zl-9.png differ diff --git a/assets/icon-apps/icon_100.png b/assets/icon-apps/icon_100.png new file mode 100644 index 0000000..912f672 Binary files /dev/null and b/assets/icon-apps/icon_100.png differ diff --git a/assets/icon-apps/icon_101.png b/assets/icon-apps/icon_101.png new file mode 100644 index 0000000..d5aebb9 Binary files /dev/null and b/assets/icon-apps/icon_101.png differ diff --git a/assets/icon-apps/icon_102.png b/assets/icon-apps/icon_102.png new file mode 100644 index 0000000..a97e623 Binary files /dev/null and b/assets/icon-apps/icon_102.png differ diff --git a/assets/icon-apps/jobico1.png b/assets/icon-apps/jobico1.png new file mode 100644 index 0000000..c948020 Binary files /dev/null and b/assets/icon-apps/jobico1.png differ diff --git a/assets/icon-apps/jobico2.png b/assets/icon-apps/jobico2.png new file mode 100644 index 0000000..f75de1f Binary files /dev/null and b/assets/icon-apps/jobico2.png differ diff --git a/assets/icon-apps/jobico3.png b/assets/icon-apps/jobico3.png new file mode 100644 index 0000000..87b1123 Binary files /dev/null and b/assets/icon-apps/jobico3.png differ diff --git a/assets/icon-apps/jobico4.png b/assets/icon-apps/jobico4.png new file mode 100644 index 0000000..11fda21 Binary files /dev/null and b/assets/icon-apps/jobico4.png differ diff --git a/assets/icon-apps/jobico5.png b/assets/icon-apps/jobico5.png new file mode 100644 index 0000000..7ca8070 Binary files /dev/null and b/assets/icon-apps/jobico5.png differ diff --git a/assets/icon-apps/open-circuit.png b/assets/icon-apps/open-circuit.png new file mode 100644 index 0000000..fe2f651 Binary files /dev/null and b/assets/icon-apps/open-circuit.png differ diff --git a/assets/icon-apps/video.png b/assets/icon-apps/video.png new file mode 100644 index 0000000..cbdbfa2 Binary files /dev/null and b/assets/icon-apps/video.png differ diff --git a/assets/icon-apps/wenjuan.png b/assets/icon-apps/wenjuan.png new file mode 100644 index 0000000..2d00526 Binary files /dev/null and b/assets/icon-apps/wenjuan.png differ diff --git a/assets/image/gai.png b/assets/image/gai.png new file mode 100644 index 0000000..e90721d Binary files /dev/null and b/assets/image/gai.png differ diff --git a/assets/image/gaiz.png b/assets/image/gaiz.png new file mode 100644 index 0000000..e90721d Binary files /dev/null and b/assets/image/gaiz.png differ diff --git a/assets/image/logo.png b/assets/image/logo.png new file mode 100644 index 0000000..0d925fe Binary files /dev/null and b/assets/image/logo.png differ diff --git a/assets/images/1.png b/assets/images/1.png new file mode 100644 index 0000000..ae5f021 Binary files /dev/null and b/assets/images/1.png differ diff --git a/assets/images/2.png b/assets/images/2.png new file mode 100644 index 0000000..f983c0b Binary files /dev/null and b/assets/images/2.png differ diff --git a/assets/images/3.png b/assets/images/3.png new file mode 100644 index 0000000..aab7d0c Binary files /dev/null and b/assets/images/3.png differ diff --git a/assets/images/4.png b/assets/images/4.png new file mode 100644 index 0000000..6ddefdc Binary files /dev/null and b/assets/images/4.png differ diff --git a/assets/images/5.png b/assets/images/5.png new file mode 100644 index 0000000..6716b73 Binary files /dev/null and b/assets/images/5.png differ diff --git a/assets/images/ai_img.png b/assets/images/ai_img.png new file mode 100644 index 0000000..583b960 Binary files /dev/null and b/assets/images/ai_img.png differ diff --git a/assets/images/app-logo.png b/assets/images/app-logo.png new file mode 100644 index 0000000..54baf79 Binary files /dev/null and b/assets/images/app-logo.png differ diff --git a/assets/images/app-logo0.png b/assets/images/app-logo0.png new file mode 100644 index 0000000..7f00ecf Binary files /dev/null and b/assets/images/app-logo0.png differ diff --git a/assets/images/apps-banner.jpg b/assets/images/apps-banner.jpg new file mode 100644 index 0000000..9767f1d Binary files /dev/null and b/assets/images/apps-banner.jpg differ diff --git a/assets/images/apps-banner.png b/assets/images/apps-banner.png new file mode 100644 index 0000000..0093235 Binary files /dev/null and b/assets/images/apps-banner.png differ diff --git a/assets/images/avatar.png b/assets/images/avatar.png new file mode 100644 index 0000000..c22a198 Binary files /dev/null and b/assets/images/avatar.png differ diff --git a/assets/images/banner.jpg b/assets/images/banner.jpg new file mode 100644 index 0000000..3df5fa8 Binary files /dev/null and b/assets/images/banner.jpg differ diff --git a/assets/images/banner.png b/assets/images/banner.png new file mode 100644 index 0000000..f6d6ade Binary files /dev/null and b/assets/images/banner.png differ diff --git a/assets/images/bg-login.png b/assets/images/bg-login.png new file mode 100644 index 0000000..6bc71fd Binary files /dev/null and b/assets/images/bg-login.png differ diff --git a/assets/images/hg-bottom.png b/assets/images/hg-bottom.png new file mode 100644 index 0000000..774847b Binary files /dev/null and b/assets/images/hg-bottom.png differ diff --git a/assets/images/ksbgx.png b/assets/images/ksbgx.png new file mode 100644 index 0000000..4dc90e1 Binary files /dev/null and b/assets/images/ksbgx.png differ diff --git a/assets/images/login-bg.png b/assets/images/login-bg.png new file mode 100644 index 0000000..94f11a0 Binary files /dev/null and b/assets/images/login-bg.png differ diff --git a/assets/images/null.png b/assets/images/null.png new file mode 100644 index 0000000..7df785c Binary files /dev/null and b/assets/images/null.png differ diff --git a/assets/images/scan.png b/assets/images/scan.png new file mode 100644 index 0000000..6a343ee Binary files /dev/null and b/assets/images/scan.png differ diff --git a/assets/images/study-app01.png b/assets/images/study-app01.png new file mode 100644 index 0000000..087051f Binary files /dev/null and b/assets/images/study-app01.png differ diff --git a/assets/images/study-app02.png b/assets/images/study-app02.png new file mode 100644 index 0000000..223e441 Binary files /dev/null and b/assets/images/study-app02.png differ diff --git a/assets/images/study-banner.png b/assets/images/study-banner.png new file mode 100644 index 0000000..c4a2cb6 Binary files /dev/null and b/assets/images/study-banner.png differ diff --git a/assets/images/user_pic.png b/assets/images/user_pic.png new file mode 100644 index 0000000..1f196ec Binary files /dev/null and b/assets/images/user_pic.png differ diff --git a/assets/images/zt-ing.png b/assets/images/zt-ing.png new file mode 100644 index 0000000..dacbace Binary files /dev/null and b/assets/images/zt-ing.png differ diff --git a/assets/images/zt-over.png b/assets/images/zt-over.png new file mode 100644 index 0000000..bdc18bc Binary files /dev/null and b/assets/images/zt-over.png differ diff --git a/assets/js/jsencrypt.min.js b/assets/js/jsencrypt.min.js new file mode 100644 index 0000000..174916b --- /dev/null +++ b/assets/js/jsencrypt.min.js @@ -0,0 +1,2 @@ +/*! For license information please see jsencrypt.min.js.LICENSE.txt */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.JSEncrypt=e():t.JSEncrypt=e()}(window,(()=>(()=>{var t={155:t=>{var e,i,r=t.exports={};function n(){throw new Error("setTimeout has not been defined")}function s(){throw new Error("clearTimeout has not been defined")}function o(t){if(e===setTimeout)return setTimeout(t,0);if((e===n||!e)&&setTimeout)return e=setTimeout,setTimeout(t,0);try{return e(t,0)}catch(i){try{return e.call(null,t,0)}catch(i){return e.call(this,t,0)}}}!function(){try{e="function"==typeof setTimeout?setTimeout:n}catch(t){e=n}try{i="function"==typeof clearTimeout?clearTimeout:s}catch(t){i=s}}();var h,a=[],u=!1,c=-1;function f(){u&&h&&(u=!1,h.length?a=h.concat(a):c=-1,a.length&&l())}function l(){if(!u){var t=o(f);u=!0;for(var e=a.length;e;){for(h=a,a=[];++c1)for(var i=1;i{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";function t(t){return"0123456789abcdefghijklmnopqrstuvwxyz".charAt(t)}function e(t,e){return t&e}function n(t,e){return t|e}function s(t,e){return t^e}function o(t,e){return t&~e}function h(t){if(0==t)return-1;var e=0;return 0==(65535&t)&&(t>>=16,e+=16),0==(255&t)&&(t>>=8,e+=8),0==(15&t)&&(t>>=4,e+=4),0==(3&t)&&(t>>=2,e+=2),0==(1&t)&&++e,e}function a(t){for(var e=0;0!=t;)t&=t-1,++e;return e}i.d(r,{default:()=>ot});var u,c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function f(t){var e,i,r="";for(e=0;e+3<=t.length;e+=3)i=parseInt(t.substring(e,e+3),16),r+=c.charAt(i>>6)+c.charAt(63&i);for(e+1==t.length?(i=parseInt(t.substring(e,e+1),16),r+=c.charAt(i<<2)):e+2==t.length&&(i=parseInt(t.substring(e,e+2),16),r+=c.charAt(i>>2)+c.charAt((3&i)<<4));(3&r.length)>0;)r+="=";return r}function l(e){var i,r="",n=0,s=0;for(i=0;i>2),s=3&o,n=1):1==n?(r+=t(s<<2|o>>4),s=15&o,n=2):2==n?(r+=t(s),r+=t(o>>2),s=3&o,n=3):(r+=t(s<<2|o>>4),r+=t(15&o),n=0))}return 1==n&&(r+=t(s<<2)),r}var p,g={decode:function(t){var e;if(void 0===p){var i="= \f\n\r\t \u2028\u2029";for(p=Object.create(null),e=0;e<64;++e)p["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(e)]=e;for(p["-"]=62,p._=63,e=0;e=4?(r[r.length]=n>>16,r[r.length]=n>>8&255,r[r.length]=255&n,n=0,s=0):n<<=6}}switch(s){case 1:throw new Error("Base64 encoding incomplete: at least 2 bits missing");case 2:r[r.length]=n>>10;break;case 3:r[r.length]=n>>16,r[r.length]=n>>8&255}return r},re:/-----BEGIN [^-]+-----([A-Za-z0-9+\/=\s]+)-----END [^-]+-----|begin-base64[^\n]+\n([A-Za-z0-9+\/=\s]+)====/,unarmor:function(t){var e=g.re.exec(t);if(e)if(e[1])t=e[1];else{if(!e[2])throw new Error("RegExp out of sync");t=e[2]}return g.decode(t)}},d=1e13,v=function(){function t(t){this.buf=[+t||0]}return t.prototype.mulAdd=function(t,e){var i,r,n=this.buf,s=n.length;for(i=0;i0&&(n[i]=e)},t.prototype.sub=function(t){var e,i,r=this.buf,n=r.length;for(e=0;e=0;--r)i+=(d+e[r]).toString().substring(1);return i},t.prototype.valueOf=function(){for(var t=this.buf,e=0,i=t.length-1;i>=0;--i)e=e*d+t[i];return e},t.prototype.simplify=function(){var t=this.buf;return 1==t.length?t[0]:this},t}(),m=/^(\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/,y=/^(\d\d\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/;function b(t,e){return t.length>e&&(t=t.substring(0,e)+"…"),t}var T,S=function(){function t(e,i){this.hexDigits="0123456789ABCDEF",e instanceof t?(this.enc=e.enc,this.pos=e.pos):(this.enc=e,this.pos=i)}return t.prototype.get=function(t){if(void 0===t&&(t=this.pos++),t>=this.enc.length)throw new Error("Requesting byte offset ".concat(t," on a stream of length ").concat(this.enc.length));return"string"==typeof this.enc?this.enc.charCodeAt(t):this.enc[t]},t.prototype.hexByte=function(t){return this.hexDigits.charAt(t>>4&15)+this.hexDigits.charAt(15&t)},t.prototype.hexDump=function(t,e,i){for(var r="",n=t;n176)return!1}return!0},t.prototype.parseStringISO=function(t,e){for(var i="",r=t;r191&&n<224?String.fromCharCode((31&n)<<6|63&this.get(r++)):String.fromCharCode((15&n)<<12|(63&this.get(r++))<<6|63&this.get(r++))}return i},t.prototype.parseStringBMP=function(t,e){for(var i,r,n="",s=t;s127,s=n?255:0,o="";r==s&&++t4){for(o=r,i<<=3;0==(128&(+o^s));)o=+o<<1,--i;o="("+i+" bit)\n"}n&&(r-=256);for(var h=new v(r),a=t+1;a=a;--u)s+=h>>u&1?"1":"0";if(s.length>i)return n+b(s,i)}return n+s},t.prototype.parseOctetString=function(t,e,i){if(this.isASCII(t,e))return b(this.parseStringISO(t,e),i);var r=e-t,n="("+r+" byte)\n";r>(i/=2)&&(e=t+i);for(var s=t;si&&(n+="…"),n},t.prototype.parseOID=function(t,e,i){for(var r="",n=new v,s=0,o=t;oi)return b(r,i);n=new v,s=0}}return s>0&&(r+=".incomplete"),r},t}(),E=function(){function t(t,e,i,r,n){if(!(r instanceof w))throw new Error("Invalid tag value.");this.stream=t,this.header=e,this.length=i,this.tag=r,this.sub=n}return t.prototype.typeName=function(){switch(this.tag.tagClass){case 0:switch(this.tag.tagNumber){case 0:return"EOC";case 1:return"BOOLEAN";case 2:return"INTEGER";case 3:return"BIT_STRING";case 4:return"OCTET_STRING";case 5:return"NULL";case 6:return"OBJECT_IDENTIFIER";case 7:return"ObjectDescriptor";case 8:return"EXTERNAL";case 9:return"REAL";case 10:return"ENUMERATED";case 11:return"EMBEDDED_PDV";case 12:return"UTF8String";case 16:return"SEQUENCE";case 17:return"SET";case 18:return"NumericString";case 19:return"PrintableString";case 20:return"TeletexString";case 21:return"VideotexString";case 22:return"IA5String";case 23:return"UTCTime";case 24:return"GeneralizedTime";case 25:return"GraphicString";case 26:return"VisibleString";case 27:return"GeneralString";case 28:return"UniversalString";case 30:return"BMPString"}return"Universal_"+this.tag.tagNumber.toString();case 1:return"Application_"+this.tag.tagNumber.toString();case 2:return"["+this.tag.tagNumber.toString()+"]";case 3:return"Private_"+this.tag.tagNumber.toString()}},t.prototype.content=function(t){if(void 0===this.tag)return null;void 0===t&&(t=1/0);var e=this.posContent(),i=Math.abs(this.length);if(!this.tag.isUniversal())return null!==this.sub?"("+this.sub.length+" elem)":this.stream.parseOctetString(e,e+i,t);switch(this.tag.tagNumber){case 1:return 0===this.stream.get(e)?"false":"true";case 2:return this.stream.parseInteger(e,e+i);case 3:return this.sub?"("+this.sub.length+" elem)":this.stream.parseBitString(e,e+i,t);case 4:return this.sub?"("+this.sub.length+" elem)":this.stream.parseOctetString(e,e+i,t);case 6:return this.stream.parseOID(e,e+i,t);case 16:case 17:return null!==this.sub?"("+this.sub.length+" elem)":"(no elem)";case 12:return b(this.stream.parseStringUTF(e,e+i),t);case 18:case 19:case 20:case 21:case 22:case 26:return b(this.stream.parseStringISO(e,e+i),t);case 30:return b(this.stream.parseStringBMP(e,e+i),t);case 23:case 24:return this.stream.parseTime(e,e+i,23==this.tag.tagNumber)}return null},t.prototype.toString=function(){return this.typeName()+"@"+this.stream.pos+"[header:"+this.header+",length:"+this.length+",sub:"+(null===this.sub?"null":this.sub.length)+"]"},t.prototype.toPrettyString=function(t){void 0===t&&(t="");var e=t+this.typeName()+" @"+this.stream.pos;if(this.length>=0&&(e+="+"),e+=this.length,this.tag.tagConstructed?e+=" (constructed)":!this.tag.isUniversal()||3!=this.tag.tagNumber&&4!=this.tag.tagNumber||null===this.sub||(e+=" (encapsulates)"),e+="\n",null!==this.sub){t+=" ";for(var i=0,r=this.sub.length;i6)throw new Error("Length over 48 bits not supported at position "+(t.pos-1));if(0===i)return null;e=0;for(var r=0;r>6,this.tagConstructed=0!=(32&e),this.tagNumber=31&e,31==this.tagNumber){var i=new v;do{e=t.get(),i.mulAdd(128,127&e)}while(128&e);this.tagNumber=i.simplify()}}return t.prototype.isUniversal=function(){return 0===this.tagClass},t.prototype.isEOC=function(){return 0===this.tagClass&&0===this.tagNumber},t}(),D=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997],x=(1<<26)/D[D.length-1],R=function(){function i(t,e,i){null!=t&&("number"==typeof t?this.fromNumber(t,e,i):null==e&&"string"!=typeof t?this.fromString(t,256):this.fromString(t,e))}return i.prototype.toString=function(e){if(this.s<0)return"-"+this.negate().toString(e);var i;if(16==e)i=4;else if(8==e)i=3;else if(2==e)i=1;else if(32==e)i=5;else{if(4!=e)return this.toRadix(e);i=2}var r,n=(1<0)for(a>a)>0&&(s=!0,o=t(r));h>=0;)a>(a+=this.DB-i)):(r=this[h]>>(a-=i)&n,a<=0&&(a+=this.DB,--h)),r>0&&(s=!0),s&&(o+=t(r));return s?o:"0"},i.prototype.negate=function(){var t=I();return i.ZERO.subTo(this,t),t},i.prototype.abs=function(){return this.s<0?this.negate():this},i.prototype.compareTo=function(t){var e=this.s-t.s;if(0!=e)return e;var i=this.t;if(0!=(e=i-t.t))return this.s<0?-e:e;for(;--i>=0;)if(0!=(e=this[i]-t[i]))return e;return 0},i.prototype.bitLength=function(){return this.t<=0?0:this.DB*(this.t-1)+C(this[this.t-1]^this.s&this.DM)},i.prototype.mod=function(t){var e=I();return this.abs().divRemTo(t,null,e),this.s<0&&e.compareTo(i.ZERO)>0&&t.subTo(e,e),e},i.prototype.modPowInt=function(t,e){var i;return i=t<256||e.isEven()?new O(e):new A(e),this.exp(t,i)},i.prototype.clone=function(){var t=I();return this.copyTo(t),t},i.prototype.intValue=function(){if(this.s<0){if(1==this.t)return this[0]-this.DV;if(0==this.t)return-1}else{if(1==this.t)return this[0];if(0==this.t)return 0}return(this[1]&(1<<32-this.DB)-1)<>24},i.prototype.shortValue=function(){return 0==this.t?this.s:this[0]<<16>>16},i.prototype.signum=function(){return this.s<0?-1:this.t<=0||1==this.t&&this[0]<=0?0:1},i.prototype.toByteArray=function(){var t=this.t,e=[];e[0]=this.s;var i,r=this.DB-t*this.DB%8,n=0;if(t-- >0)for(r>r)!=(this.s&this.DM)>>r&&(e[n++]=i|this.s<=0;)r<8?(i=(this[t]&(1<>(r+=this.DB-8)):(i=this[t]>>(r-=8)&255,r<=0&&(r+=this.DB,--t)),0!=(128&i)&&(i|=-256),0==n&&(128&this.s)!=(128&i)&&++n,(n>0||i!=this.s)&&(e[n++]=i);return e},i.prototype.equals=function(t){return 0==this.compareTo(t)},i.prototype.min=function(t){return this.compareTo(t)<0?this:t},i.prototype.max=function(t){return this.compareTo(t)>0?this:t},i.prototype.and=function(t){var i=I();return this.bitwiseTo(t,e,i),i},i.prototype.or=function(t){var e=I();return this.bitwiseTo(t,n,e),e},i.prototype.xor=function(t){var e=I();return this.bitwiseTo(t,s,e),e},i.prototype.andNot=function(t){var e=I();return this.bitwiseTo(t,o,e),e},i.prototype.not=function(){for(var t=I(),e=0;e=this.t?0!=this.s:0!=(this[e]&1<1){var c=I();for(r.sqrTo(o[1],c);h<=u;)o[h]=I(),r.mulTo(c,o[h-2],o[h]),h+=2}var f,l,p=t.t-1,g=!0,d=I();for(n=C(t[p])-1;p>=0;){for(n>=a?f=t[p]>>n-a&u:(f=(t[p]&(1<0&&(f|=t[p-1]>>this.DB+n-a)),h=i;0==(1&f);)f>>=1,--h;if((n-=h)<0&&(n+=this.DB,--p),g)o[f].copyTo(s),g=!1;else{for(;h>1;)r.sqrTo(s,d),r.sqrTo(d,s),h-=2;h>0?r.sqrTo(s,d):(l=s,s=d,d=l),r.mulTo(d,o[f],s)}for(;p>=0&&0==(t[p]&1<=0?(r.subTo(n,r),e&&s.subTo(h,s),o.subTo(a,o)):(n.subTo(r,n),e&&h.subTo(s,h),a.subTo(o,a))}return 0!=n.compareTo(i.ONE)?i.ZERO:a.compareTo(t)>=0?a.subtract(t):a.signum()<0?(a.addTo(t,a),a.signum()<0?a.add(t):a):a},i.prototype.pow=function(t){return this.exp(t,new B)},i.prototype.gcd=function(t){var e=this.s<0?this.negate():this.clone(),i=t.s<0?t.negate():t.clone();if(e.compareTo(i)<0){var r=e;e=i,i=r}var n=e.getLowestSetBit(),s=i.getLowestSetBit();if(s<0)return e;for(n0&&(e.rShiftTo(s,e),i.rShiftTo(s,i));e.signum()>0;)(n=e.getLowestSetBit())>0&&e.rShiftTo(n,e),(n=i.getLowestSetBit())>0&&i.rShiftTo(n,i),e.compareTo(i)>=0?(e.subTo(i,e),e.rShiftTo(1,e)):(i.subTo(e,i),i.rShiftTo(1,i));return s>0&&i.lShiftTo(s,i),i},i.prototype.isProbablePrime=function(t){var e,i=this.abs();if(1==i.t&&i[0]<=D[D.length-1]){for(e=0;e=0;--e)t[e]=this[e];t.t=this.t,t.s=this.s},i.prototype.fromInt=function(t){this.t=1,this.s=t<0?-1:0,t>0?this[0]=t:t<-1?this[0]=t+this.DV:this.t=0},i.prototype.fromString=function(t,e){var r;if(16==e)r=4;else if(8==e)r=3;else if(256==e)r=8;else if(2==e)r=1;else if(32==e)r=5;else{if(4!=e)return void this.fromRadix(t,e);r=2}this.t=0,this.s=0;for(var n=t.length,s=!1,o=0;--n>=0;){var h=8==r?255&+t[n]:q(t,n);h<0?"-"==t.charAt(n)&&(s=!0):(s=!1,0==o?this[this.t++]=h:o+r>this.DB?(this[this.t-1]|=(h&(1<>this.DB-o):this[this.t-1]|=h<=this.DB&&(o-=this.DB))}8==r&&0!=(128&+t[0])&&(this.s=-1,o>0&&(this[this.t-1]|=(1<0&&this[this.t-1]==t;)--this.t},i.prototype.dlShiftTo=function(t,e){var i;for(i=this.t-1;i>=0;--i)e[i+t]=this[i];for(i=t-1;i>=0;--i)e[i]=0;e.t=this.t+t,e.s=this.s},i.prototype.drShiftTo=function(t,e){for(var i=t;i=0;--h)e[h+s+1]=this[h]>>r|o,o=(this[h]&n)<=0;--h)e[h]=0;e[s]=o,e.t=this.t+s+1,e.s=this.s,e.clamp()},i.prototype.rShiftTo=function(t,e){e.s=this.s;var i=Math.floor(t/this.DB);if(i>=this.t)e.t=0;else{var r=t%this.DB,n=this.DB-r,s=(1<>r;for(var o=i+1;o>r;r>0&&(e[this.t-i-1]|=(this.s&s)<>=this.DB;if(t.t>=this.DB;r+=this.s}else{for(r+=this.s;i>=this.DB;r-=t.s}e.s=r<0?-1:0,r<-1?e[i++]=this.DV+r:r>0&&(e[i++]=r),e.t=i,e.clamp()},i.prototype.multiplyTo=function(t,e){var r=this.abs(),n=t.abs(),s=r.t;for(e.t=s+n.t;--s>=0;)e[s]=0;for(s=0;s=0;)t[i]=0;for(i=0;i=e.DV&&(t[i+e.t]-=e.DV,t[i+e.t+1]=1)}t.t>0&&(t[t.t-1]+=e.am(i,e[i],t,2*i,0,1)),t.s=0,t.clamp()},i.prototype.divRemTo=function(t,e,r){var n=t.abs();if(!(n.t<=0)){var s=this.abs();if(s.t0?(n.lShiftTo(u,o),s.lShiftTo(u,r)):(n.copyTo(o),s.copyTo(r));var c=o.t,f=o[c-1];if(0!=f){var l=f*(1<1?o[c-2]>>this.F2:0),p=this.FV/l,g=(1<=0&&(r[r.t++]=1,r.subTo(y,r)),i.ONE.dlShiftTo(c,y),y.subTo(o,o);o.t=0;){var b=r[--v]==f?this.DM:Math.floor(r[v]*p+(r[v-1]+d)*g);if((r[v]+=o.am(0,b,r,m,0,c))0&&r.rShiftTo(u,r),h<0&&i.ZERO.subTo(r,r)}}},i.prototype.invDigit=function(){if(this.t<1)return 0;var t=this[0];if(0==(1&t))return 0;var e=3&t;return(e=(e=(e=(e=e*(2-(15&t)*e)&15)*(2-(255&t)*e)&255)*(2-((65535&t)*e&65535))&65535)*(2-t*e%this.DV)%this.DV)>0?this.DV-e:-e},i.prototype.isEven=function(){return 0==(this.t>0?1&this[0]:this.s)},i.prototype.exp=function(t,e){if(t>4294967295||t<1)return i.ONE;var r=I(),n=I(),s=e.convert(this),o=C(t)-1;for(s.copyTo(r);--o>=0;)if(e.sqrTo(r,n),(t&1<0)e.mulTo(n,s,r);else{var h=r;r=n,n=h}return e.revert(r)},i.prototype.chunkSize=function(t){return Math.floor(Math.LN2*this.DB/Math.log(t))},i.prototype.toRadix=function(t){if(null==t&&(t=10),0==this.signum()||t<2||t>36)return"0";var e=this.chunkSize(t),i=Math.pow(t,e),r=H(i),n=I(),s=I(),o="";for(this.divRemTo(r,n,s);n.signum()>0;)o=(i+s.intValue()).toString(t).substr(1)+o,n.divRemTo(r,n,s);return s.intValue().toString(t)+o},i.prototype.fromRadix=function(t,e){this.fromInt(0),null==e&&(e=10);for(var r=this.chunkSize(e),n=Math.pow(e,r),s=!1,o=0,h=0,a=0;a=r&&(this.dMultiply(n),this.dAddOffset(h,0),o=0,h=0))}o>0&&(this.dMultiply(Math.pow(e,o)),this.dAddOffset(h,0)),s&&i.ZERO.subTo(this,this)},i.prototype.fromNumber=function(t,e,r){if("number"==typeof e)if(t<2)this.fromInt(1);else for(this.fromNumber(t,r),this.testBit(t-1)||this.bitwiseTo(i.ONE.shiftLeft(t-1),n,this),this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(e);)this.dAddOffset(2,0),this.bitLength()>t&&this.subTo(i.ONE.shiftLeft(t-1),this);else{var s=[],o=7&t;s.length=1+(t>>3),e.nextBytes(s),o>0?s[0]&=(1<>=this.DB;if(t.t>=this.DB;r+=this.s}else{for(r+=this.s;i>=this.DB;r+=t.s}e.s=r<0?-1:0,r>0?e[i++]=r:r<-1&&(e[i++]=this.DV+r),e.t=i,e.clamp()},i.prototype.dMultiply=function(t){this[this.t]=this.am(0,t-1,this,0,0,this.t),++this.t,this.clamp()},i.prototype.dAddOffset=function(t,e){if(0!=t){for(;this.t<=e;)this[this.t++]=0;for(this[e]+=t;this[e]>=this.DV;)this[e]-=this.DV,++e>=this.t&&(this[this.t++]=0),++this[e]}},i.prototype.multiplyLowerTo=function(t,e,i){var r=Math.min(this.t+t.t,e);for(i.s=0,i.t=r;r>0;)i[--r]=0;for(var n=i.t-this.t;r=0;)i[r]=0;for(r=Math.max(e-this.t,0);r0)if(0==e)i=this[0]%t;else for(var r=this.t-1;r>=0;--r)i=(e*i+this[r])%t;return i},i.prototype.millerRabin=function(t){var e=this.subtract(i.ONE),r=e.getLowestSetBit();if(r<=0)return!1;var n=e.shiftRight(r);(t=t+1>>1)>D.length&&(t=D.length);for(var s=I(),o=0;o0&&(i.rShiftTo(o,i),r.rShiftTo(o,r));var h=function(){(s=i.getLowestSetBit())>0&&i.rShiftTo(s,i),(s=r.getLowestSetBit())>0&&r.rShiftTo(s,r),i.compareTo(r)>=0?(i.subTo(r,i),i.rShiftTo(1,i)):(r.subTo(i,r),r.rShiftTo(1,r)),i.signum()>0?setTimeout(h,0):(o>0&&r.lShiftTo(o,r),setTimeout((function(){e(r)}),0))};setTimeout(h,10)}},i.prototype.fromNumberAsync=function(t,e,r,s){if("number"==typeof e)if(t<2)this.fromInt(1);else{this.fromNumber(t,r),this.testBit(t-1)||this.bitwiseTo(i.ONE.shiftLeft(t-1),n,this),this.isEven()&&this.dAddOffset(1,0);var o=this,h=function(){o.dAddOffset(2,0),o.bitLength()>t&&o.subTo(i.ONE.shiftLeft(t-1),o),o.isProbablePrime(e)?setTimeout((function(){s()}),0):setTimeout(h,0)};setTimeout(h,0)}else{var a=[],u=7&t;a.length=1+(t>>3),e.nextBytes(a),u>0?a[0]&=(1<=0?t.mod(this.m):t},t.prototype.revert=function(t){return t},t.prototype.reduce=function(t){t.divRemTo(this.m,null,t)},t.prototype.mulTo=function(t,e,i){t.multiplyTo(e,i),this.reduce(i)},t.prototype.sqrTo=function(t,e){t.squareTo(e),this.reduce(e)},t}(),A=function(){function t(t){this.m=t,this.mp=t.invDigit(),this.mpl=32767&this.mp,this.mph=this.mp>>15,this.um=(1<0&&this.m.subTo(e,e),e},t.prototype.revert=function(t){var e=I();return t.copyTo(e),this.reduce(e),e},t.prototype.reduce=function(t){for(;t.t<=this.mt2;)t[t.t++]=0;for(var e=0;e>15)*this.mpl&this.um)<<15)&t.DM;for(t[i=e+this.m.t]+=this.m.am(0,r,t,e,0,this.m.t);t[i]>=t.DV;)t[i]-=t.DV,t[++i]++}t.clamp(),t.drShiftTo(this.m.t,t),t.compareTo(this.m)>=0&&t.subTo(this.m,t)},t.prototype.mulTo=function(t,e,i){t.multiplyTo(e,i),this.reduce(i)},t.prototype.sqrTo=function(t,e){t.squareTo(e),this.reduce(e)},t}(),V=function(){function t(t){this.m=t,this.r2=I(),this.q3=I(),R.ONE.dlShiftTo(2*t.t,this.r2),this.mu=this.r2.divide(t)}return t.prototype.convert=function(t){if(t.s<0||t.t>2*this.m.t)return t.mod(this.m);if(t.compareTo(this.m)<0)return t;var e=I();return t.copyTo(e),this.reduce(e),e},t.prototype.revert=function(t){return t},t.prototype.reduce=function(t){for(t.drShiftTo(this.m.t-1,this.r2),t.t>this.m.t+1&&(t.t=this.m.t+1,t.clamp()),this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3),this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);t.compareTo(this.r2)<0;)t.dAddOffset(1,this.m.t+1);for(t.subTo(this.r2,t);t.compareTo(this.m)>=0;)t.subTo(this.m,t)},t.prototype.mulTo=function(t,e,i){t.multiplyTo(e,i),this.reduce(i)},t.prototype.sqrTo=function(t,e){t.squareTo(e),this.reduce(e)},t}();function I(){return new R(null)}function N(t,e){return new R(t,e)}var P="undefined"!=typeof navigator;P&&"Microsoft Internet Explorer"==navigator.appName?(R.prototype.am=function(t,e,i,r,n,s){for(var o=32767&e,h=e>>15;--s>=0;){var a=32767&this[t],u=this[t++]>>15,c=h*a+u*o;n=((a=o*a+((32767&c)<<15)+i[r]+(1073741823&n))>>>30)+(c>>>15)+h*u+(n>>>30),i[r++]=1073741823&a}return n},T=30):P&&"Netscape"!=navigator.appName?(R.prototype.am=function(t,e,i,r,n,s){for(;--s>=0;){var o=e*this[t++]+i[r]+n;n=Math.floor(o/67108864),i[r++]=67108863&o}return n},T=26):(R.prototype.am=function(t,e,i,r,n,s){for(var o=16383&e,h=e>>14;--s>=0;){var a=16383&this[t],u=this[t++]>>14,c=h*a+u*o;n=((a=o*a+((16383&c)<<14)+i[r]+n)>>28)+(c>>14)+h*u,i[r++]=268435455&a}return n},T=28),R.prototype.DB=T,R.prototype.DM=(1<>>16)&&(t=e,i+=16),0!=(e=t>>8)&&(t=e,i+=8),0!=(e=t>>4)&&(t=e,i+=4),0!=(e=t>>2)&&(t=e,i+=2),0!=(e=t>>1)&&(t=e,i+=1),i}R.ZERO=H(0),R.ONE=H(1);var F,U,K=function(){function t(){this.i=0,this.j=0,this.S=[]}return t.prototype.init=function(t){var e,i,r;for(e=0;e<256;++e)this.S[e]=e;for(i=0,e=0;e<256;++e)i=i+this.S[e]+t[e%t.length]&255,r=this.S[e],this.S[e]=this.S[i],this.S[i]=r;this.i=0,this.j=0},t.prototype.next=function(){var t;return this.i=this.i+1&255,this.j=this.j+this.S[this.i]&255,t=this.S[this.i],this.S[this.i]=this.S[this.j],this.S[this.j]=t,this.S[t+this.S[this.i]&255]},t}(),k=null;if(null==k){k=[],U=0;var _=void 0;if("undefined"!=typeof window&&window.crypto&&window.crypto.getRandomValues){var z=new Uint32Array(256);for(window.crypto.getRandomValues(z),_=0;_=256||U>=256)window.removeEventListener?window.removeEventListener("mousemove",G,!1):window.detachEvent&&window.detachEvent("onmousemove",G);else try{var e=t.x+t.y;k[U++]=255&e,Z+=1}catch(t){}};"undefined"!=typeof window&&(window.addEventListener?window.addEventListener("mousemove",G,!1):window.attachEvent&&window.attachEvent("onmousemove",G))}function $(){if(null==F){for(F=new K;U<256;){var t=Math.floor(65536*Math.random());k[U++]=255&t}for(F.init(k),U=0;U0&&e.length>0?(this.n=N(t,16),this.e=parseInt(e,16)):console.error("Invalid RSA public key")},t.prototype.encrypt=function(t){var e=this.n.bitLength()+7>>3,i=function(t,e){if(e=0&&e>0;){var n=t.charCodeAt(r--);n<128?i[--e]=n:n>127&&n<2048?(i[--e]=63&n|128,i[--e]=n>>6|192):(i[--e]=63&n|128,i[--e]=n>>6&63|128,i[--e]=n>>12|224)}i[--e]=0;for(var s=new Y,o=[];e>2;){for(o[0]=0;0==o[0];)s.nextBytes(o);i[--e]=o[0]}return i[--e]=2,i[--e]=0,new R(i)}(t,e);if(null==i)return null;var r=this.doPublic(i);if(null==r)return null;for(var n=r.toString(16),s=n.length,o=0;o<2*e-s;o++)n="0"+n;return n},t.prototype.setPrivate=function(t,e,i){null!=t&&null!=e&&t.length>0&&e.length>0?(this.n=N(t,16),this.e=parseInt(e,16),this.d=N(i,16)):console.error("Invalid RSA private key")},t.prototype.setPrivateEx=function(t,e,i,r,n,s,o,h){null!=t&&null!=e&&t.length>0&&e.length>0?(this.n=N(t,16),this.e=parseInt(e,16),this.d=N(i,16),this.p=N(r,16),this.q=N(n,16),this.dmp1=N(s,16),this.dmq1=N(o,16),this.coeff=N(h,16)):console.error("Invalid RSA private key")},t.prototype.generate=function(t,e){var i=new Y,r=t>>1;this.e=parseInt(e,16);for(var n=new R(e,16);;){for(;this.p=new R(t-r,1,i),0!=this.p.subtract(R.ONE).gcd(n).compareTo(R.ONE)||!this.p.isProbablePrime(10););for(;this.q=new R(r,1,i),0!=this.q.subtract(R.ONE).gcd(n).compareTo(R.ONE)||!this.q.isProbablePrime(10););if(this.p.compareTo(this.q)<=0){var s=this.p;this.p=this.q,this.q=s}var o=this.p.subtract(R.ONE),h=this.q.subtract(R.ONE),a=o.multiply(h);if(0==a.gcd(n).compareTo(R.ONE)){this.n=this.p.multiply(this.q),this.d=n.modInverse(a),this.dmp1=this.d.mod(o),this.dmq1=this.d.mod(h),this.coeff=this.q.modInverse(this.p);break}}},t.prototype.decrypt=function(t){var e=N(t,16),i=this.doPrivate(e);return null==i?null:function(t,e){for(var i=t.toByteArray(),r=0;r=i.length)return null;for(var n="";++r191&&s<224?(n+=String.fromCharCode((31&s)<<6|63&i[r+1]),++r):(n+=String.fromCharCode((15&s)<<12|(63&i[r+1])<<6|63&i[r+2]),r+=2)}return n}(i,this.n.bitLength()+7>>3)},t.prototype.generateAsync=function(t,e,i){var r=new Y,n=t>>1;this.e=parseInt(e,16);var s=new R(e,16),o=this,h=function(){var e=function(){if(o.p.compareTo(o.q)<=0){var t=o.p;o.p=o.q,o.q=t}var e=o.p.subtract(R.ONE),r=o.q.subtract(R.ONE),n=e.multiply(r);0==n.gcd(s).compareTo(R.ONE)?(o.n=o.p.multiply(o.q),o.d=s.modInverse(n),o.dmp1=o.d.mod(e),o.dmq1=o.d.mod(r),o.coeff=o.q.modInverse(o.p),setTimeout((function(){i()}),0)):setTimeout(h,0)},a=function(){o.q=I(),o.q.fromNumberAsync(n,1,r,(function(){o.q.subtract(R.ONE).gcda(s,(function(t){0==t.compareTo(R.ONE)&&o.q.isProbablePrime(10)?setTimeout(e,0):setTimeout(a,0)}))}))},u=function(){o.p=I(),o.p.fromNumberAsync(t-n,1,r,(function(){o.p.subtract(R.ONE).gcda(s,(function(t){0==t.compareTo(R.ONE)&&o.p.isProbablePrime(10)?setTimeout(a,0):setTimeout(u,0)}))}))};setTimeout(u,0)};setTimeout(h,0)},t.prototype.sign=function(t,e,i){var r=function(t,e){if(e15)throw"ASN.1 length too long to represent by 8x: n = "+t.toString(16);return(128+i).toString(16)+e},this.getEncodedHex=function(){return(null==this.hTLV||this.isModified)&&(this.hV=this.getFreshValueHex(),this.hL=this.getLengthHexFromValue(),this.hTLV=this.hT+this.hL+this.hV,this.isModified=!1),this.hTLV},this.getValueHex=function(){return this.getEncodedHex(),this.hV},this.getFreshValueHex=function(){return""}},W.asn1.DERAbstractString=function(t){W.asn1.DERAbstractString.superclass.constructor.call(this),this.getString=function(){return this.s},this.setString=function(t){this.hTLV=null,this.isModified=!0,this.s=t,this.hV=stohex(this.s)},this.setStringHex=function(t){this.hTLV=null,this.isModified=!0,this.s=null,this.hV=t},this.getFreshValueHex=function(){return this.hV},void 0!==t&&("string"==typeof t?this.setString(t):void 0!==t.str?this.setString(t.str):void 0!==t.hex&&this.setStringHex(t.hex))},Q.lang.extend(W.asn1.DERAbstractString,W.asn1.ASN1Object),W.asn1.DERAbstractTime=function(t){W.asn1.DERAbstractTime.superclass.constructor.call(this),this.localDateToUTC=function(t){return utc=t.getTime()+6e4*t.getTimezoneOffset(),new Date(utc)},this.formatDate=function(t,e,i){var r=this.zeroPadding,n=this.localDateToUTC(t),s=String(n.getFullYear());"utc"==e&&(s=s.substr(2,2));var o=s+r(String(n.getMonth()+1),2)+r(String(n.getDate()),2)+r(String(n.getHours()),2)+r(String(n.getMinutes()),2)+r(String(n.getSeconds()),2);if(!0===i){var h=n.getMilliseconds();if(0!=h){var a=r(String(h),3);o=o+"."+(a=a.replace(/[0]+$/,""))}}return o+"Z"},this.zeroPadding=function(t,e){return t.length>=e?t:new Array(e-t.length+1).join("0")+t},this.getString=function(){return this.s},this.setString=function(t){this.hTLV=null,this.isModified=!0,this.s=t,this.hV=stohex(t)},this.setByDateValue=function(t,e,i,r,n,s){var o=new Date(Date.UTC(t,e-1,i,r,n,s,0));this.setByDate(o)},this.getFreshValueHex=function(){return this.hV}},Q.lang.extend(W.asn1.DERAbstractTime,W.asn1.ASN1Object),W.asn1.DERAbstractStructured=function(t){W.asn1.DERAbstractString.superclass.constructor.call(this),this.setByASN1ObjectArray=function(t){this.hTLV=null,this.isModified=!0,this.asn1Array=t},this.appendASN1Object=function(t){this.hTLV=null,this.isModified=!0,this.asn1Array.push(t)},this.asn1Array=new Array,void 0!==t&&void 0!==t.array&&(this.asn1Array=t.array)},Q.lang.extend(W.asn1.DERAbstractStructured,W.asn1.ASN1Object),W.asn1.DERBoolean=function(){W.asn1.DERBoolean.superclass.constructor.call(this),this.hT="01",this.hTLV="0101ff"},Q.lang.extend(W.asn1.DERBoolean,W.asn1.ASN1Object),W.asn1.DERInteger=function(t){W.asn1.DERInteger.superclass.constructor.call(this),this.hT="02",this.setByBigInteger=function(t){this.hTLV=null,this.isModified=!0,this.hV=W.asn1.ASN1Util.bigIntToMinTwosComplementsHex(t)},this.setByInteger=function(t){var e=new R(String(t),10);this.setByBigInteger(e)},this.setValueHex=function(t){this.hV=t},this.getFreshValueHex=function(){return this.hV},void 0!==t&&(void 0!==t.bigint?this.setByBigInteger(t.bigint):void 0!==t.int?this.setByInteger(t.int):"number"==typeof t?this.setByInteger(t):void 0!==t.hex&&this.setValueHex(t.hex))},Q.lang.extend(W.asn1.DERInteger,W.asn1.ASN1Object),W.asn1.DERBitString=function(t){if(void 0!==t&&void 0!==t.obj){var e=W.asn1.ASN1Util.newObject(t.obj);t.hex="00"+e.getEncodedHex()}W.asn1.DERBitString.superclass.constructor.call(this),this.hT="03",this.setHexValueIncludingUnusedBits=function(t){this.hTLV=null,this.isModified=!0,this.hV=t},this.setUnusedBitsAndHexValue=function(t,e){if(t<0||7=2?(n[n.length]=s,s=0,o=0):s<<=4}}if(o)throw new Error("Hex encoding incomplete: 4 bits missing");return n}(t):g.unarmor(t),n=E.decode(r);if(3===n.sub.length&&(n=n.sub[2].sub[0]),9===n.sub.length){e=n.sub[1].getHexStringValue(),this.n=N(e,16),i=n.sub[2].getHexStringValue(),this.e=parseInt(i,16);var s=n.sub[3].getHexStringValue();this.d=N(s,16);var o=n.sub[4].getHexStringValue();this.p=N(o,16);var h=n.sub[5].getHexStringValue();this.q=N(h,16);var a=n.sub[6].getHexStringValue();this.dmp1=N(a,16);var c=n.sub[7].getHexStringValue();this.dmq1=N(c,16);var f=n.sub[8].getHexStringValue();this.coeff=N(f,16)}else{if(2!==n.sub.length)return!1;if(n.sub[0].sub){var l=n.sub[1].sub[0];e=l.sub[0].getHexStringValue(),this.n=N(e,16),i=l.sub[1].getHexStringValue(),this.e=parseInt(i,16)}else e=n.sub[0].getHexStringValue(),this.n=N(e,16),i=n.sub[1].getHexStringValue(),this.e=parseInt(i,16)}return!0}catch(t){return!1}},e.prototype.getPrivateBaseKey=function(){var t={array:[new W.asn1.DERInteger({int:0}),new W.asn1.DERInteger({bigint:this.n}),new W.asn1.DERInteger({int:this.e}),new W.asn1.DERInteger({bigint:this.d}),new W.asn1.DERInteger({bigint:this.p}),new W.asn1.DERInteger({bigint:this.q}),new W.asn1.DERInteger({bigint:this.dmp1}),new W.asn1.DERInteger({bigint:this.dmq1}),new W.asn1.DERInteger({bigint:this.coeff})]};return new W.asn1.DERSequence(t).getEncodedHex()},e.prototype.getPrivateBaseKeyB64=function(){return f(this.getPrivateBaseKey())},e.prototype.getPublicBaseKey=function(){var t=new W.asn1.DERSequence({array:[new W.asn1.DERObjectIdentifier({oid:"1.2.840.113549.1.1.1"}),new W.asn1.DERNull]}),e=new W.asn1.DERSequence({array:[new W.asn1.DERInteger({bigint:this.n}),new W.asn1.DERInteger({int:this.e})]}),i=new W.asn1.DERBitString({hex:"00"+e.getEncodedHex()});return new W.asn1.DERSequence({array:[t,i]}).getEncodedHex()},e.prototype.getPublicBaseKeyB64=function(){return f(this.getPublicBaseKey())},e.wordwrap=function(t,e){if(!t)return t;var i="(.{1,"+(e=e||64)+"})( +|$\n?)|(.{1,"+e+"})";return t.match(RegExp(i,"g")).join("\n")},e.prototype.getPrivateKey=function(){var t="-----BEGIN RSA PRIVATE KEY-----\n";return(t+=e.wordwrap(this.getPrivateBaseKeyB64())+"\n")+"-----END RSA PRIVATE KEY-----"},e.prototype.getPublicKey=function(){var t="-----BEGIN PUBLIC KEY-----\n";return(t+=e.wordwrap(this.getPublicBaseKeyB64())+"\n")+"-----END PUBLIC KEY-----"},e.hasPublicKeyProperty=function(t){return(t=t||{}).hasOwnProperty("n")&&t.hasOwnProperty("e")},e.hasPrivateKeyProperty=function(t){return(t=t||{}).hasOwnProperty("n")&&t.hasOwnProperty("e")&&t.hasOwnProperty("d")&&t.hasOwnProperty("p")&&t.hasOwnProperty("q")&&t.hasOwnProperty("dmp1")&&t.hasOwnProperty("dmq1")&&t.hasOwnProperty("coeff")},e.prototype.parsePropertiesFrom=function(t){this.n=t.n,this.e=t.e,t.hasOwnProperty("d")&&(this.d=t.d,this.p=t.p,this.q=t.q,this.dmp1=t.dmp1,this.dmq1=t.dmq1,this.coeff=t.coeff)},e}(J),nt=i(155),st=void 0!==nt?null===(et=nt.env)||void 0===et?void 0:"3.3.1":void 0;const ot=function(){function t(t){void 0===t&&(t={}),t=t||{},this.default_key_size=t.default_key_size?parseInt(t.default_key_size,10):1024,this.default_public_exponent=t.default_public_exponent||"010001",this.log=t.log||!1,this.key=null}return t.prototype.setKey=function(t){this.log&&this.key&&console.warn("A key was already set, overriding existing."),this.key=new rt(t)},t.prototype.setPrivateKey=function(t){this.setKey(t)},t.prototype.setPublicKey=function(t){this.setKey(t)},t.prototype.decrypt=function(t){try{return this.getKey().decrypt(l(t))}catch(t){return!1}},t.prototype.encrypt=function(t){try{return f(this.getKey().encrypt(t))}catch(t){return!1}},t.prototype.sign=function(t,e,i){try{return f(this.getKey().sign(t,e,i))}catch(t){return!1}},t.prototype.verify=function(t,e,i){try{return this.getKey().verify(t,l(e),i)}catch(t){return!1}},t.prototype.getKey=function(t){if(!this.key){if(this.key=new rt,t&&"[object Function]"==={}.toString.call(t))return void this.key.generateAsync(this.default_key_size,this.default_public_exponent,t);this.key.generate(this.default_key_size,this.default_public_exponent)}return this.key},t.prototype.getPrivateKey=function(){return this.getKey().getPrivateKey()},t.prototype.getPrivateKeyB64=function(){return this.getKey().getPrivateBaseKeyB64()},t.prototype.getPublicKey=function(){return this.getKey().getPublicKey()},t.prototype.getPublicKeyB64=function(){return this.getKey().getPublicBaseKeyB64()},t.version=st,t}()})(),r.default})())); \ No newline at end of file diff --git a/assets/map/100.png b/assets/map/100.png new file mode 100644 index 0000000..2639bba Binary files /dev/null and b/assets/map/100.png differ diff --git a/assets/map/50.png b/assets/map/50.png new file mode 100644 index 0000000..e67c5d0 Binary files /dev/null and b/assets/map/50.png differ diff --git a/assets/map/c.png b/assets/map/c.png new file mode 100644 index 0000000..23b2c8d Binary files /dev/null and b/assets/map/c.png differ diff --git a/assets/map/h.png b/assets/map/h.png new file mode 100644 index 0000000..31cec4a Binary files /dev/null and b/assets/map/h.png differ diff --git a/assets/map/hh.png b/assets/map/hh.png new file mode 100644 index 0000000..dc8c775 Binary files /dev/null and b/assets/map/hh.png differ diff --git a/assets/map/jc.png b/assets/map/jc.png new file mode 100644 index 0000000..38bbc8f Binary files /dev/null and b/assets/map/jc.png differ diff --git a/assets/map/l.png b/assets/map/l.png new file mode 100644 index 0000000..165f498 Binary files /dev/null and b/assets/map/l.png differ diff --git a/assets/map/ls.png b/assets/map/ls.png new file mode 100644 index 0000000..fb06e6b Binary files /dev/null and b/assets/map/ls.png differ diff --git a/assets/tabbar/application.png b/assets/tabbar/application.png new file mode 100644 index 0000000..03fc273 Binary files /dev/null and b/assets/tabbar/application.png differ diff --git a/assets/tabbar/application_cur.png b/assets/tabbar/application_cur.png new file mode 100644 index 0000000..c0bab46 Binary files /dev/null and b/assets/tabbar/application_cur.png differ diff --git a/assets/tabbar/basics.png b/assets/tabbar/basics.png new file mode 100644 index 0000000..f2ad80a Binary files /dev/null and b/assets/tabbar/basics.png differ diff --git a/assets/tabbar/basics_cur.png b/assets/tabbar/basics_cur.png new file mode 100644 index 0000000..63b1965 Binary files /dev/null and b/assets/tabbar/basics_cur.png differ diff --git a/assets/tabbar/my.png b/assets/tabbar/my.png new file mode 100644 index 0000000..b5c45b8 Binary files /dev/null and b/assets/tabbar/my.png differ diff --git a/assets/tabbar/my_cur.png b/assets/tabbar/my_cur.png new file mode 100644 index 0000000..79d148a Binary files /dev/null and b/assets/tabbar/my_cur.png differ diff --git a/assets/tabbar/works.png b/assets/tabbar/works.png new file mode 100644 index 0000000..d36d3ba Binary files /dev/null and b/assets/tabbar/works.png differ diff --git a/assets/tabbar/works_cur.png b/assets/tabbar/works_cur.png new file mode 100644 index 0000000..0ac9ec8 Binary files /dev/null and b/assets/tabbar/works_cur.png differ diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 0000000..fa0b357 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..7a7f987 --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..7c56964 --- /dev/null +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 12.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..ec97fc6 --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..c4855bf --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..e549ee2 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,43 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '12.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000..bcf59c8 --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,36 @@ +PODS: + - Flutter (1.0.0) + - image_picker_ios (0.0.1): + - Flutter + - mobile_scanner (7.0.0): + - Flutter + - FlutterMacOS + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS + +DEPENDENCIES: + - Flutter (from `Flutter`) + - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) + - mobile_scanner (from `.symlinks/plugins/mobile_scanner/darwin`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + image_picker_ios: + :path: ".symlinks/plugins/image_picker_ios/ios" + mobile_scanner: + :path: ".symlinks/plugins/mobile_scanner/darwin" + shared_preferences_foundation: + :path: ".symlinks/plugins/shared_preferences_foundation/darwin" + +SPEC CHECKSUMS: + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a + mobile_scanner: 9157936403f5a0644ca3779a38ff8404c5434a93 + shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 + +PODFILE CHECKSUM: 4305caec6b40dde0ae97be1573c53de1882a07e5 + +COCOAPODS: 1.16.2 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..6caa2c4 --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,731 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 66834350160CC0CD3C21B3C6 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27A21C95F9CD84635ECDCCE7 /* Pods_Runner.framework */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + CD1A9A9B724474173510336B /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4621ED2122C53316571BD703 /* Pods_RunnerTests.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 19C3F450BC80B5A7805E1AEC /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 26B606F41C2A0A98CB6C6675 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 27A21C95F9CD84635ECDCCE7 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 4621ED2122C53316571BD703 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4A0D5C873AAC2044ACCD3EF3 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 4E0B158099CBA2DF914F5FDF /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9397CA8B9C31F420C79D0BC9 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A5EFE972749B9FBFF8A17D3C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 66834350160CC0CD3C21B3C6 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9AD71197BA5C33D24636B03A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CD1A9A9B724474173510336B /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 5192495AF0A714C8F787F1E6 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 27A21C95F9CD84635ECDCCE7 /* Pods_Runner.framework */, + 4621ED2122C53316571BD703 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + D1B24C997F4A0101CD2D397B /* Pods */, + 5192495AF0A714C8F787F1E6 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + D1B24C997F4A0101CD2D397B /* Pods */ = { + isa = PBXGroup; + children = ( + 9397CA8B9C31F420C79D0BC9 /* Pods-Runner.debug.xcconfig */, + 4E0B158099CBA2DF914F5FDF /* Pods-Runner.release.xcconfig */, + A5EFE972749B9FBFF8A17D3C /* Pods-Runner.profile.xcconfig */, + 4A0D5C873AAC2044ACCD3EF3 /* Pods-RunnerTests.debug.xcconfig */, + 19C3F450BC80B5A7805E1AEC /* Pods-RunnerTests.release.xcconfig */, + 26B606F41C2A0A98CB6C6675 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 466AC0C02FC505ED8DCCFA8C /* [CP] Check Pods Manifest.lock */, + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + 9AD71197BA5C33D24636B03A /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + E4D037C0008E7F556DE2AEEF /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 960C41EE6556C5D7788D41A3 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 466AC0C02FC505ED8DCCFA8C /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 960C41EE6556C5D7788D41A3 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + E4D037C0008E7F556DE2AEEF /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 8AKCJ9LW7D; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.zhuoyun.qhdprevention.qhdPrevention; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4A0D5C873AAC2044ACCD3EF3 /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.zhuoyun.qhdprevention.qhdPrevention.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 19C3F450BC80B5A7805E1AEC /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.zhuoyun.qhdprevention.qhdPrevention.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 26B606F41C2A0A98CB6C6675 /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.zhuoyun.qhdprevention.qhdPrevention.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 8AKCJ9LW7D; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.zhuoyun.qhdprevention.qhdPrevention; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 8AKCJ9LW7D; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.zhuoyun.qhdprevention.qhdPrevention; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..15cada4 --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..21a3cc1 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..6266644 --- /dev/null +++ b/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import Flutter +import UIKit + +@main +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000..dc9ada4 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000..7353c41 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000..797d452 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000..6ed2d93 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000..4cd7b00 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000..fe73094 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000..321773c Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000..797d452 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000..502f463 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000..0ec3034 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000..0ec3034 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000..e9f5fea Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000..84ac32a Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000..8953cba Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000..0467bf1 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000..0bedcf2 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +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. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 0000000..c7b90b8 --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Qhd Prevention + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + qhd_prevention + CFBundlePackageType + APPL + NSCameraUsageDescription + 需要相机权限来扫描二维码 + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/ios/RunnerTests/RunnerTests.swift b/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..86a7c3b --- /dev/null +++ b/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/lib/customWidget/ItemWidgetFactory.dart b/lib/customWidget/ItemWidgetFactory.dart new file mode 100644 index 0000000..461916a --- /dev/null +++ b/lib/customWidget/ItemWidgetFactory.dart @@ -0,0 +1,271 @@ +import 'package:flutter/material.dart'; + +/// 自定义组件 +class ListItemFactory { + /// 类型1:横向spaceBetween布局两个文本 + static Widget createRowSpaceBetweenItem({ + required String leftText, + required String rightText, + double verticalPadding = 15, + double horizontalPadding = 0, + bool isRight = false, + }) { + return Padding( + padding: EdgeInsets.symmetric( + vertical: verticalPadding, + horizontal: horizontalPadding, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + leftText, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + if (isRight) + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + rightText, + style: TextStyle(fontSize: 15, color: Colors.grey), + ), + SizedBox(width: 2,), + Icon(Icons.arrow_forward_ios_rounded, size: 15), + ], + ) + else + Text(rightText, style: TextStyle(fontSize: 15, color: Colors.grey)), + ], + ), + ); + } + + ///类型2:上下布局两个文本(自适应高度) + static Widget createColumnTextItem({ + required String topText, + required String bottomText, + double verticalPadding = 15, + double horizontalPadding = 0, + }) { + return Padding( + padding: EdgeInsets.symmetric( + vertical: verticalPadding, + horizontal: horizontalPadding, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + topText, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + const SizedBox(height: 5), + Text( + bottomText, + style: TextStyle(fontSize: 15, color: Colors.grey), + softWrap: true, + maxLines: null, // 允许无限行数 + ), + ], + ), + ); + } + + /// 类型3:文本和图片上下布局 + static Widget createTextImageItem({ + required String text, + required String imageUrl, + double imageHeight = 90, + double verticalPadding = 15, + double horizontalPadding = 0, + // 添加点击事件回调函数 + VoidCallback? onImageTapped, // 新增的回调函数参数 + }) { + return Padding( + padding: EdgeInsets.symmetric( + vertical: verticalPadding, + horizontal: horizontalPadding, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + text, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + const SizedBox(height: 10), + // 使用GestureDetector包裹图片区域 + GestureDetector( + onTap: onImageTapped, // 将外部传入的回调绑定到点击事件 + child: Builder( + builder: (context) { + // 网络图片 + if (imageUrl.startsWith('http')) { + return Image.network( + imageUrl, + height: imageHeight, + width: imageHeight * 3 / 2, + fit: BoxFit.cover, + alignment: Alignment.centerLeft, + ); + } + // 本地图片 + else { + return Image.asset( + imageUrl, + height: imageHeight, + width: double.infinity, + fit: BoxFit.cover, + alignment: Alignment.centerLeft, + ); + } + }, + ), + ), + ], + ), + ); + } + + ///类型4:一个文本(自适应高度) + static Widget createAloneTextItem({ + required String text, + double verticalPadding = 15, + double horizontalPadding = 0, + }) { + return Padding( + padding: EdgeInsets.symmetric( + vertical: verticalPadding, + horizontal: horizontalPadding, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + text, + style: TextStyle(fontSize: 15, color: Colors.grey), + softWrap: true, + maxLines: null, // 允许无限行数 + ), + ], + ), + ); + } + + /// 分类头部 + static Widget createYesNoSection({ + required String title, + required String yesLabel, + required String noLabel, + required bool groupValue, + required ValueChanged onChanged, + double verticalPadding = 15, + double horizontalPadding = 0, + }) { + return Padding( + padding: EdgeInsets.symmetric( + vertical: verticalPadding, + horizontal: horizontalPadding, + ), + child: Container( + padding: EdgeInsets.symmetric(horizontal: 10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(5), + ), + child: Row( + children: [ + Expanded( + child: Text( + title, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + ), + Row( + children: [ + Row( + children: [ + Radio( + activeColor: Colors.blue, + value: true, + groupValue: groupValue, + onChanged: (val) => onChanged(val!), + ), + Text(yesLabel), + ], + ), + const SizedBox(width: 16), + Row( + children: [ + Radio( + activeColor: Colors.blue, + value: false, + groupValue: groupValue, + onChanged: (val) => onChanged(val!), + ), + Text(noLabel), + ], + ), + ], + ), + ], + ), + ), + ); + } + static Widget createBuildSimpleSection(String title) { + return Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Row( + children: [ + Container(width: 3, height: 15, color: Colors.blue), + const SizedBox(width: 8), + Text( + title, + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + ), + ], + ), + ), + ); + } + + /// 扩展项(根据需求自定义) + static Widget createCustomItem({ + required Widget child, + double verticalPadding = 15, + double horizontalPadding = 0, + }) { + return Padding( + padding: EdgeInsets.symmetric( + vertical: verticalPadding, + horizontal: horizontalPadding, + ), + child: child, + ); + } +} diff --git a/lib/customWidget/custom_button.dart b/lib/customWidget/custom_button.dart new file mode 100644 index 0000000..f41e432 --- /dev/null +++ b/lib/customWidget/custom_button.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; + +/// 自定义默认按钮 +class CustomButton extends StatelessWidget { + final String text; // 按钮文字 + final Color backgroundColor; // 按钮背景色 + final double borderRadius; // 圆角半径(默认5) + final VoidCallback? onPressed; // 点击事件回调 + final EdgeInsetsGeometry? padding; // 内边距 + final EdgeInsetsGeometry? margin; // 外边距 + final double? height; // 按钮高度 + final TextStyle? textStyle; // 文字样式 + + const CustomButton({ + super.key, + required this.text, + required this.backgroundColor, + this.borderRadius = 5.0, + this.onPressed, + this.padding, + this.margin, + this.height, + this.textStyle, + }); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onPressed, + child: Container( + height: height ?? 50, // 默认高度50 + padding: padding ?? const EdgeInsets.all(8), // 默认内边距 + margin: margin ?? const EdgeInsets.symmetric(horizontal: 8), // 默认外边距 + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(borderRadius), + color: backgroundColor, + ), + child: Center( + child: Text( + text, + style: textStyle ?? const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/customWidget/custom_driver_drawer.dart b/lib/customWidget/custom_driver_drawer.dart new file mode 100644 index 0000000..9ef6eab --- /dev/null +++ b/lib/customWidget/custom_driver_drawer.dart @@ -0,0 +1,193 @@ +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/customWidget/department_picker.dart'; +import '../tools/h_colors.dart'; +import '/customWidget/custom_button.dart'; +import '../tools/tools.dart'; + +/// 自定义抽屉 +class CustomDriverDrawer extends StatefulWidget { + const CustomDriverDrawer({super.key}); + + @override + _CustomDriverDrawerState createState() => _CustomDriverDrawerState(); +} + +class _CustomDriverDrawerState extends State { + // 四个选项的单选 index + int _selectedOption = -1; + // 已选择的分类 id + String? _selectedCategoryId; + + @override + Widget build(BuildContext context) { + final List items = ["重大风险", "较大风险", "一般风险", "低风险"]; + final List data = [ + Category( + id: '1', + title: '分类一', + children: [ + Category(id: '1-1', title: '子项 1-1'), + Category(id: '1-2', title: '子项 1-2'), + ], + ), + Category(id: '2', title: '分类二'), + Category( + id: '3', + title: '分类三', + children: [ + Category(id: '3-1', title: '子项 3-1', children: [ + Category(id: '3-1-1', title: '子项 3-1-1'), + ]), + ], + ), + ]; + + // 显示分类选择器 + void showCategoryPicker() { + showModalBottomSheet( + context: context, + isScrollControlled: true, + barrierColor: Colors.black54, + backgroundColor: Colors.transparent, + builder: (ctx) => DepartmentPicker( + data: data, + onSelected: (selectedId) { + setState(() { + _selectedCategoryId = selectedId; + }); + }, + ), + ); + } + + return SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: const [ + Text( + "高级查询", + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + ], + ), + const Divider(height: 24, color: Colors.grey), + + // 管控部门 + _buildDropdownBox( + "管控部门", + display: _selectedCategoryId ?? '请选择', + onTap: showCategoryPicker, + ), + const SizedBox(height: 12), + + // 风险点(单元) + _buildDropdownBox( + "风险点(单元)", + display: '请选择', + onTap: () { + // TODO: 打开 B 的下拉 + }, + ), + + const SizedBox(height: 24), + const Text( + "风险等级", + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500), + ), + const SizedBox(height: 12), + + // 风险等级:一行一个 + Column( + children: List.generate(items.length, (idx) { + final bool selected = _selectedOption == idx; + return GestureDetector( + onTap: () => setState(() => _selectedOption = idx), + child: Container( + width: double.infinity, + margin: const EdgeInsets.only(bottom: 8), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + decoration: BoxDecoration( + color: selected ? Colors.blue : Colors.transparent, + borderRadius: BorderRadius.circular(4), + border: Border.all(color: Colors.blue, width: 1), + ), + child: Text( + items[idx], + style: TextStyle( + fontSize: 14, + color: selected ? Colors.white : Colors.blue, + ), + ), + ), + ); + }), + ), + + const Spacer(), + Row( + children: [ + Expanded( + flex: 1, + child: CustomButton( + text: "重置", + backgroundColor: h_backGroundColor(), + textStyle: const TextStyle(color: Colors.black45), + onPressed: () { + setState(() { + _selectedOption = -1; + _selectedCategoryId = null; + }); + }, + ), + ), + const SizedBox(width: 12), + Expanded( + flex: 2, + child: CustomButton( + text: "完成", + backgroundColor: Colors.blue, + onPressed: () { + // TODO: 提交筛选条件 + }, + ), + ), + ], + ), + ], + ), + ), + ); + } + + Widget _buildDropdownBox(String title, + {required String display, required VoidCallback onTap}) { + return GestureDetector( + onTap: onTap, + child: Container( + height: 48, + padding: const EdgeInsets.symmetric(horizontal: 12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + border: Border.all(color: Colors.grey.shade400), + color: Colors.white, + ), + child: Row( + children: [ + Text(title, style: const TextStyle(fontSize: 14)), + const Spacer(), + Row( + children: [ + Text(display), + const Icon(Icons.arrow_drop_down, color: Colors.grey), + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/customWidget/date_picker_dialog.dart b/lib/customWidget/date_picker_dialog.dart new file mode 100644 index 0000000..f7f25d0 --- /dev/null +++ b/lib/customWidget/date_picker_dialog.dart @@ -0,0 +1,168 @@ +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; + +class HDatePickerDialog extends StatefulWidget { + final DateTime initialDate; + final VoidCallback onCancel; + final ValueChanged onConfirm; + + const HDatePickerDialog({ + Key? key, + required this.initialDate, + required this.onCancel, + required this.onConfirm, + }) : super(key: key); + + @override + _HDatePickerDialogState createState() => _HDatePickerDialogState(); +} + +class _HDatePickerDialogState extends State { + late DateTime _displayedMonth; + late DateTime _selectedDate; + + @override + void initState() { + super.initState(); + _selectedDate = widget.initialDate; + _displayedMonth = DateTime(widget.initialDate.year, widget.initialDate.month); + } + + void _prevMonth() { + setState(() { + _displayedMonth = DateTime(_displayedMonth.year, _displayedMonth.month - 1); + }); + } + + void _nextMonth() { + setState(() { + _displayedMonth = DateTime(_displayedMonth.year, _displayedMonth.month + 1); + }); + } + + @override + Widget build(BuildContext context) { + final daysInMonth = DateUtils.getDaysInMonth(_displayedMonth.year, _displayedMonth.month); + final firstWeekday = DateTime(_displayedMonth.year, _displayedMonth.month, 1).weekday; + + return GestureDetector( + onTap: widget.onCancel, + child: Material( + color: Colors.black54, + child: Center( + child: GestureDetector( + onTap: () {}, // 拦截点击 + child: Container( + width: 320, + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // 顶部显示选中日期 + Text( + DateFormat('yyyy-MM-dd').format(_selectedDate), + style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 16), + + // 月份选择 + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + IconButton( + icon: const Icon(Icons.chevron_left), + onPressed: _prevMonth, + ), + Text( + DateFormat('yyyy 年 MM 月').format(_displayedMonth), + style: const TextStyle(fontSize: 16), + ), + IconButton( + icon: const Icon(Icons.chevron_right), + onPressed: _nextMonth, + ), + ], + ), + + // 星期标题 + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: ['一', '二', '三', '四', '五', '六', '日'] + .map((d) => Expanded( + child: Center(child: Text(d)), + )) + .toList(), + ), + SizedBox(height: 10,), + // 日历网格 + GridView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 7, + childAspectRatio: 1.2, + crossAxisSpacing: 4, + mainAxisSpacing: 4, + ), + itemCount: daysInMonth + firstWeekday - 1, + itemBuilder: (context, index) { + if (index < firstWeekday - 1) { + return const SizedBox(); + } + final day = index - firstWeekday + 2; + final date = DateTime(_displayedMonth.year, _displayedMonth.month, day); + final isSelected = DateUtils.isSameDay(date, _selectedDate); + + return GestureDetector( + onTap: () { + setState(() { + _selectedDate = date; + }); + }, + child: Container( + decoration: BoxDecoration( + color: isSelected ? Theme.of(context).primaryColor : null, + shape: BoxShape.circle, + ), + child: Center( + child: Text( + '$day', + style: TextStyle( + color: isSelected ? Colors.white : Colors.black87, + ), + ), + ), + ), + ); + }, + ), + + const SizedBox(height: 16), + + // 按钮 + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + TextButton( + onPressed: widget.onCancel, + child: const Text('取消'), + ), + ElevatedButton( + onPressed: () => widget.onConfirm(_selectedDate), + child: const Text('确定'), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/customWidget/department_picker.dart b/lib/customWidget/department_picker.dart new file mode 100644 index 0000000..98f1d39 --- /dev/null +++ b/lib/customWidget/department_picker.dart @@ -0,0 +1,152 @@ +import 'package:flutter/material.dart'; + +class Category { + final String id; + final String title; + final List children; + + Category({ + required this.id, + required this.title, + this.children = const [], + }); +} + +class DepartmentPicker extends StatefulWidget { + final List data; + final String? initialSelectedId; + final Set? initialExpandedSet; + final ValueChanged onSelected; + + const DepartmentPicker({ + Key? key, + required this.data, + this.initialSelectedId, + this.initialExpandedSet, + required this.onSelected, + }) : super(key: key); + + @override + _DepartmentPickerState createState() => _DepartmentPickerState(); +} + +class _DepartmentPickerState extends State { + late String? selectedId; + late Set expandedSet; + + @override + void initState() { + super.initState(); + selectedId = widget.initialSelectedId; + expandedSet = Set.from(widget.initialExpandedSet ?? {}); + } + + Widget _buildRow(Category cat, int indent) { + final bool hasChildren = cat.children.isNotEmpty; + final bool isExpanded = expandedSet.contains(cat.id); + final bool isSelected = cat.id == selectedId; + + return Column( + children: [ + InkWell( + onTap: () { + setState(() { + if (hasChildren) { + if (isExpanded) { + expandedSet.remove(cat.id); + } else { + expandedSet.add(cat.id); + } + } + selectedId = cat.id; + }); + }, + child: Container( + color: Colors.white, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // 左侧缩进 + SizedBox(width: 16.0 * indent), + // 展开/占位图标 + SizedBox( + width: 24, + child: hasChildren + ? Icon( + isExpanded ? Icons.expand_less : Icons.expand_more, + size: 20, + color: Colors.grey[600], + ) + : const SizedBox.shrink(), + ), + const SizedBox(width: 8), + // 标题 + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 12), + child: Text(cat.title), + ), + ), + // 单选圈保持右侧对齐 + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Icon( + isSelected + ? Icons.radio_button_checked + : Icons.radio_button_unchecked, + color: Colors.green, + ), + ), + ], + ), + ), + ), + if (hasChildren && isExpanded) + ...cat.children.map((c) => _buildRow(c, indent + 1)), + // const Divider(height: 1), + ], + ); + } + + @override + Widget build(BuildContext context) { + return Container( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height * 0.7, + color: Colors.transparent, + child: Column( + children: [ + // 顶部操作栏 + Container( + color: Colors.white, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + onTap: () => Navigator.of(context).pop(), + child: const Text('取消', style: TextStyle(fontSize: 16)), + ), + GestureDetector( + onTap: () => Navigator.of(context).pop(selectedId), + child: const Text('确定', style: TextStyle(fontSize: 16, color: Colors.green),), + ), + ], + ), + ), + const Divider(height: 1), + // 列表区 + Expanded( + child: Container( + color: Colors.white, + child: ListView.builder( + itemCount: widget.data.length, + itemBuilder: (ctx, idx) => _buildRow(widget.data[idx], 0), + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/customWidget/photo_picker_row.dart b/lib/customWidget/photo_picker_row.dart new file mode 100644 index 0000000..c756b75 --- /dev/null +++ b/lib/customWidget/photo_picker_row.dart @@ -0,0 +1,162 @@ +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:wechat_assets_picker/wechat_assets_picker.dart'; + +/// 横向一行最多四张图片的添加组件,支持拍照和全屏相册多选 +/// 使用示例: +/// PhotoPickerRow( +/// maxCount: 4, +/// onChanged: (List images) { +/// // images 列表更新 +/// }, +/// ), +class PhotoPickerRow extends StatefulWidget { + final int maxCount; + final ValueChanged> onChanged; + + const PhotoPickerRow({ + Key? key, + this.maxCount = 4, + required this.onChanged, + }) : super(key: key); + + @override + _PhotoPickerRowState createState() => _PhotoPickerRowState(); +} + +class _PhotoPickerRowState extends State { + final ImagePicker _picker = ImagePicker(); + final List _images = []; + + Future _showPickerOptions() async { + showModalBottomSheet( + context: context, + builder: (_) => SafeArea( + child: Wrap( + children: [ + ListTile( + leading: const Icon(Icons.camera_alt), + title: const Text('拍照'), + onTap: () { + Navigator.of(context).pop(); + _pickCamera(); + }, + ), + ListTile( + leading: const Icon(Icons.photo_library), + title: const Text('从相册选择'), + onTap: () { + Navigator.of(context).pop(); + _pickGallery(); + }, + ), + ListTile( + leading: const Icon(Icons.close), + title: const Text('取消'), + onTap: () => Navigator.of(context).pop(), + ), + ], + ), + ), + ); + } + + Future _pickCamera() async { + if (_images.length >= widget.maxCount) return; + final XFile? picked = await _picker.pickImage(source: ImageSource.camera); + if (picked != null) { + setState(() { + _images.add(File(picked.path)); + }); + widget.onChanged(_images); + } + } + + Future _pickGallery() async { + if (_images.length >= widget.maxCount) return; + final remaining = widget.maxCount - _images.length; + final List? assets = await AssetPicker.pickAssets( + context, + pickerConfig: AssetPickerConfig( + requestType: RequestType.image, + maxAssets: remaining, + gridCount: 4, + ), + ); + if (assets != null && assets.isNotEmpty) { + for (final asset in assets) { + if (_images.length >= widget.maxCount) break; + final file = await asset.file; + if (file != null) { + _images.add(file); + } + } + setState(() {}); + widget.onChanged(_images); + } + } + + void _removeImage(int index) { + setState(() { + _images.removeAt(index); + }); + widget.onChanged(_images); + } + + @override + Widget build(BuildContext context) { + return SizedBox( + height: 80, + child: ListView.separated( + scrollDirection: Axis.horizontal, + itemCount: _images.length < widget.maxCount + ? _images.length + 1 + : widget.maxCount, + separatorBuilder: (_, __) => const SizedBox(width: 8), + itemBuilder: (context, index) { + if (index < _images.length) { + // 已选图片 + return Stack( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(5), + child: Image.file( + _images[index], + width: 80, + height: 80, + fit: BoxFit.cover, + ), + ), + Positioned( + top: -6, + right: -6, + child: IconButton( + icon: const Icon(Icons.cancel, size: 20, color: Colors.red), + onPressed: () => _removeImage(index), + ), + ), + ], + ); + } else { + // 添加按钮 + return GestureDetector( + onTap: _showPickerOptions, + child: Container( + width: 80, + height: 80, + decoration: BoxDecoration( + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(5), + ), + child: const Center( + child: Icon(Icons.camera_alt, color: Colors.grey), + ), + ), + ); + } + }, + ), + ); + } +} diff --git a/lib/customWidget/search_bar_widget.dart b/lib/customWidget/search_bar_widget.dart new file mode 100644 index 0000000..ee095a0 --- /dev/null +++ b/lib/customWidget/search_bar_widget.dart @@ -0,0 +1,124 @@ +import 'package:flutter/material.dart'; + +class SearchBarWidget extends StatelessWidget { + final String hintText; + final String buttonText; + final ValueChanged onSearch; + final TextEditingController controller; // 改为必传参数 + final bool autoFocus; + final bool showResetButton; + final String resetButtonText; + final VoidCallback? onReset; + final bool isClickableOnly; + final VoidCallback? onInputTap; + final ValueChanged? onTextChanged; // 新增文本变化回调 + + const SearchBarWidget({ + Key? key, + required this.onSearch, + required this.controller, // 必须传入controller + this.hintText = '请输入关键字', + this.buttonText = '搜索', + this.autoFocus = false, + this.showResetButton = false, + this.resetButtonText = '重置', + this.onReset, + this.isClickableOnly = false, + this.onInputTap, + this.onTextChanged, // 可选文本变化监听 + }) : super(key: key); + + // 公共方法:更新输入框内容(可在外部调用) + void updateText(String newText) { + controller.text = newText; + controller.selection = TextSelection.fromPosition( + TextPosition(offset: newText.length), + ); + // 可选:触发文本变化回调 + onTextChanged?.call(newText); + } + + @override + Widget build(BuildContext context) { + + return Row( + children: [ + Expanded( + child: GestureDetector( + onTap: isClickableOnly ? onInputTap : null, + child: AbsorbPointer( + absorbing: isClickableOnly, + child: TextField( + controller: controller, + autofocus: autoFocus, + readOnly: isClickableOnly, + style: const TextStyle(fontSize: 15), + onChanged: onTextChanged, // 监听文本变化 + decoration: InputDecoration( + filled: true, + fillColor: const Color(0xFFF5F5F5), + prefixIcon: const Icon(Icons.search_rounded), + hintText: hintText, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: BorderSide.none, + ), + isDense: true, + contentPadding: const EdgeInsets.symmetric(vertical: 8), + + ), + onSubmitted: onSearch, + ), + ), + ), + ), + const SizedBox(width: 10), + // 搜索按钮 + ElevatedButton( + onPressed: () => onSearch(controller.text.trim()), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.green, + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + elevation: 4, + shadowColor: Colors.black45, + ), + child: Text( + buttonText, + style: const TextStyle( + color: Colors.white, + fontSize: 16, + ), + ), + ), + // 重置按钮 + if (showResetButton) const SizedBox(width: 10), + if (showResetButton) + ElevatedButton( + onPressed: () { + updateText(''); // 使用统一方法清空 + onReset?.call(); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + elevation: 1, + shadowColor: Colors.black26, + ), + child: Text( + resetButtonText, + style: TextStyle( + color: Colors.white, + fontSize: 16, + ), + ), + ), + ], + ); + } +} \ No newline at end of file diff --git a/lib/customWidget/single_image_viewer.dart b/lib/customWidget/single_image_viewer.dart new file mode 100644 index 0000000..d947482 --- /dev/null +++ b/lib/customWidget/single_image_viewer.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'package:photo_view/photo_view.dart'; +// 查看大图 +class SingleImageViewer extends StatelessWidget { + final String imageUrl; + const SingleImageViewer({Key? key, required this.imageUrl}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.black, + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0, + ), + body: Center( + child: PhotoView( + imageProvider: NetworkImage(imageUrl), + backgroundDecoration: BoxDecoration(color: Colors.black), + minScale: PhotoViewComputedScale.contained, + maxScale: PhotoViewComputedScale.covered * 2, + onTapUp: (context, details, controllerValue) { + Navigator.of(context).pop(); + }, + ), + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..a573193 --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import './pages/login_page.dart'; // 导入登录页面 +import './pages/main_tab.dart'; // 导入主页(带TabBar的页面) +import 'package:intl/date_symbol_data_local.dart'; + +void main() async { + // 确保Flutter引擎初始化完成 + WidgetsFlutterBinding.ensureInitialized(); + await initializeDateFormatting('zh_CN', null); + + // 获取共享首选项实例 + final prefs = await SharedPreferences.getInstance(); + + // 获取登录状态 + final isLoggedIn = prefs.getBool('isLoggedIn') ?? false; + + runApp(MyApp(isLoggedIn: isLoggedIn)); +} + +class MyApp extends StatelessWidget { + final bool isLoggedIn; + + const MyApp({super.key, required this.isLoggedIn}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: '', + theme: ThemeData( + dividerTheme: const DividerThemeData( + color: Colors.black12, + thickness: 1, // 线高 + indent: 0, // 左缩进 + endIndent: 0, // 右缩进 + ), + primarySwatch: Colors.blue, + colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), + inputDecorationTheme: const InputDecorationTheme( + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(horizontal: 8), + ), + ), + // 根据登录状态决定初始页面 + home: isLoggedIn ? const MainPage() : const LoginPage(), + debugShowCheckedModeBanner: false, + ); + } +} \ No newline at end of file diff --git a/lib/pages/app/application_page.dart b/lib/pages/app/application_page.dart new file mode 100644 index 0000000..a59abea --- /dev/null +++ b/lib/pages/app/application_page.dart @@ -0,0 +1,179 @@ +import 'package:flutter/material.dart'; + +class ApplicationPage extends StatelessWidget { + const ApplicationPage({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final List> buttonInfos = [ + { + 'title': '隐患排查', + 'list': [ + {'icon': 'assets/icon-apps/icon-zl-6.png', 'title': '隐患排查', 'num': 0}, + {'icon': 'assets/icon-apps/icon-pc-1.png', 'title': '隐患快报', 'num': 2}, + {'icon': 'assets/icon-apps/icon-zl-2.png', 'title': '检查记录', 'num': 0}, + ], + }, + { + 'title': '隐患治理', + 'list': [ + {'icon': 'assets/icon-apps/icon-zl-2.png', 'title': '隐患记录', 'num': 1}, + { + 'icon': 'assets/icon-apps/icon-zl-3.png', + 'title': '待整改隐患', + 'num': 3, + }, + { + 'icon': 'assets/icon-apps/icon-zl-4.png', + 'title': '超期未整改', + 'num': 0, + }, + {'icon': 'assets/icon-apps/icon-yh-1.png', 'title': '隐患验收', 'num': 2}, + { + 'icon': 'assets/icon-apps/icon-zl-1.png', + 'title': '已验收隐患', + 'num': 0, + }, + ], + }, + { + 'title': '专项检查', + 'list': [ + {'icon': 'assets/icon-apps/icon-pc-1.png', 'title': '隐患整改', 'num': 5}, + {'icon': 'assets/icon-apps/icon-zl-2.png', 'title': '隐患记录', 'num': 0}, + ], + }, + { + 'title': '监管帮扶', + 'list': [ + {'icon': 'assets/icon-apps/icon-pc-1.png', 'title': '隐患整改', 'num': 2}, + {'icon': 'assets/icon-apps/icon-zl-2.png', 'title': '隐患记录', 'num': 0}, + ], + }, + ]; + + return Scaffold( + body: ListView.builder( + physics: const AlwaysScrollableScrollPhysics(), + padding: const EdgeInsets.all(0), + itemCount: buttonInfos.length + 1, + itemBuilder: (context, index) { + // 第一项显示顶部图片 + if (index == 0) { + return ClipRRect( + child: Image.asset( + 'assets/images/apps-banner.jpg', + fit: BoxFit.cover, + ), + ); + } + // 后续显示各 section + final section = buttonInfos[index - 1]; + final items = section['list'] as List; + return Padding( + padding: const EdgeInsets.only(top: 10), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Section title + Padding( + padding: const EdgeInsets.fromLTRB(10, 10, 10, 5), + child: Row( + children: [ + Container(width: 2, height: 10, color: Colors.blue), + const SizedBox(width: 5), + Text( + section['title'] as String, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + // Items wrap + Padding( + padding: const EdgeInsets.all(10), + child: LayoutBuilder( + builder: (context, constraints) { + const spacing = 10.0; + // 4 items per row + final totalWidth = constraints.maxWidth; + final itemWidth = (totalWidth - spacing * 3) / 4; + return Wrap( + spacing: spacing, + runSpacing: spacing, + children: + items.map((item) { + return SizedBox( + width: itemWidth, + child: _buildItem(item), + ); + }).toList(), + ); + }, + ), + ), + ], + ), + ), + ); + }, + ), + ); + } + + Widget _buildItem(Map item) { + const double size = 60; + final int badgeNum = item['num'] as int; + return SizedBox( + width: size, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Image with badge overlay + Stack( + clipBehavior: Clip.none, + children: [ + SizedBox( + width: 30, + height: 30, + child: Image.asset(item['icon'] as String, fit: BoxFit.contain), + ), + if (badgeNum > 0) + Positioned( + top: -5, + right: -10, + child: Container( + width: 16, + height: 16, + decoration: const BoxDecoration( + color: Colors.red, + shape: BoxShape.circle, + ), + alignment: Alignment.center, + child: Text( + badgeNum.toString(), + style: const TextStyle(color: Colors.white, fontSize: 10), + ), + ), + ), + ], + ), + const SizedBox(height: 4), + Text( + item['title'] as String, + style: const TextStyle(fontSize: 12), + textAlign: TextAlign.center, + ), + ], + ), + ); + } +} diff --git a/lib/pages/home/home_page.dart b/lib/pages/home/home_page.dart new file mode 100644 index 0000000..c2b7b73 --- /dev/null +++ b/lib/pages/home/home_page.dart @@ -0,0 +1,360 @@ +import 'dart:async'; +import 'dart:ffi'; +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart'; +import 'package:qhd_prevention/pages/home/low_page.dart'; +import 'package:qhd_prevention/pages/home/risk/riskControl_page.dart'; +import 'package:qhd_prevention/pages/home/userInfo_page.dart'; +import 'package:qhd_prevention/pages/home/work/danger_page.dart'; +import 'package:qhd_prevention/pages/home/work/danger_wait_list_page.dart'; +import 'package:qhd_prevention/pages/home/workSet_page.dart'; + +import '../../tools/tools.dart'; + +class HomePage extends StatefulWidget { + const HomePage({Key? key}) : super(key: key); + + @override + _HomePageState createState() => _HomePageState(); +} + +class _HomePageState extends State { + final List> buttonInfos = [ + {"icon": "assets/icon-apps/home-base.png", "title": "人员信息"}, + {"icon": "assets/icon-apps/home-rili.png", "title": "工作安排"}, + {"icon": "assets/icon-apps/home-risk.png", "title": "风险布控"}, + {"icon": "assets/icon-apps/home-fl.png", "title": "法律法规"}, + ]; + final List> workInfos = [ + { + "icon": "assets/icon-apps/jobico1.png", + "num": "1", + "detail": "待排查", + "index": 1, + }, + { + "icon": "assets/icon-apps/jobico2.png", + "num": "2", + "detail": "待整改", + "index": 2, + }, + { + "icon": "assets/icon-apps/jobico3.png", + "num": "3", + "detail": "已超期", + "index": 3, + }, + { + "icon": "assets/icon-apps/jobico4.png", + "num": "4", + "detail": "待验收", + "index": 4, + }, + { + "icon": "assets/icon-apps/jobico5.png", + "num": "5", + "detail": "已验收", + "index": 5, + }, + ]; + final List> pcData = [ + { + "index": 1, + "detail": {"jiancha": "2", "yinhuan": "20", "yanshou": "4"}, + }, + { + "index": 2, + "detail": {"jiancha": "4", "yinhuan": "10", "yanshou": "5"}, + }, + { + "index": 3, + "detail": {"jiancha": "3", "yinhuan": "23", "yanshou": "3"}, + }, + ]; + final List> tagLabels = [ + ['我', '的'], + ['部', '门'], + ['监', '管'], + ]; + + Future _onRefresh() async { + // 模拟网络请求 + await Future.delayed(const Duration(seconds: 2)); + // 刷新数据逻辑,如 fetchData() + setState(() { + // TODO: 更新数据源 + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: RefreshIndicator( + onRefresh: _onRefresh, + child: ListView( + physics: const AlwaysScrollableScrollPhysics(), + padding: const EdgeInsets.all(10), + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(5), + child: Image.asset('assets/images/banner.jpg', fit: BoxFit.cover), + ), + const SizedBox(height: 10), + _buildIconSection(context), + const SizedBox(height: 10), + _buildWorkSection(context), + const SizedBox(height: 10), + ListItemFactory.createBuildSimpleSection("隐患播报"), + const SizedBox(height: 10), + _buildPCDataSection(), + SizedBox(height: 50), + ], + ), + ), + ); + } + + Widget _buildIconSection(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: + buttonInfos.asMap().entries.map((entry) { + final index = entry.key; // 获取当前索引 + final btnInfo = entry.value; // 获取按钮信息 + + return _buildIconButton( + icon: Image.asset(btnInfo["icon"]!, width: 40, height: 40), + label: btnInfo["title"]!, + onPressed: () { + // 使用索引判断点击的是哪个按钮 + print("点击了第 $index 个按钮"); + if (index == 0) { + pushPage(UserinfoPage(), context); + } else if (index == 1) { + pushPage(WorkSetPage(), context); + } else if (index == 2) { + pushPage(RiskControlPage(), context); + } else if (index == 3) { + pushPage(LowPage(), context); + } + }, + ); + }).toList(), + ), + ); + } + + Widget _buildWorkSection(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // _widgetTopTip(title: "我的工作"), + ListItemFactory.createBuildSimpleSection("我的工作"), + + Padding( + padding: const EdgeInsets.fromLTRB(10, 0, 10, 10), + child: LayoutBuilder( + builder: (context, constraints) { + const spacing = 10.0; + final totalWidth = constraints.maxWidth; + final itemWidth = (totalWidth - spacing * 2) / 3; + return Wrap( + spacing: spacing, + runSpacing: spacing, + children: + workInfos.map((info) { + return SizedBox( + width: itemWidth, + child: _buildGridItem( + context, + icon: info["icon"]!, + title: info["num"]!, + subtitle: info["detail"]!, + index: info["index"]!, + ), + ); + }).toList(), + ); + }, + ), + ), + ], + ), + ); + } + + + + Widget _buildPCDataSection() { + return Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // _widgetTopTip(title: "排查数据"), + ListItemFactory.createBuildSimpleSection("排查数据"), + ...pcData.map(_widgetPCDataItem), + ], + ), + ); + } + + // 构建图标按钮:图上文字下 + Widget _buildIconButton({ + required Widget icon, + required String label, + required VoidCallback onPressed, // 添加点击回调参数 + }) { + return InkWell( + onTap: onPressed, // 处理点击事件 + borderRadius: BorderRadius.circular(8), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + icon, + const SizedBox(height: 5), + Text(label, style: const TextStyle(fontSize: 14)), + ], + ), + ), + ); + } + + // 排查数据列表 item + Widget _widgetPCDataItem(Map item) { + final detail = item["detail"] as Map; + final values = [detail["jiancha"]!, detail["yinhuan"]!, detail["yanshou"]!]; + const labels = ["检查数", "发现隐患数", "已验收隐患数"]; + const colors = [Color(0xFF3283FF), Color(0xFFF37B1D), Color(0xFF41B852)]; + final int idx = int.tryParse(item["index"].toString())! - 1; + + return Padding( + padding: const EdgeInsets.fromLTRB(15, 0, 10, 15), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + for (var i = 0; i < 3; i++) + Column( + children: [ + Text( + values[i], + style: TextStyle( + color: colors[i], + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 4), + Text( + labels[i], + style: TextStyle(color: Colors.black38, fontSize: 15), + ), + ], + ), + Container( + color: idx == 0 ? Colors.red : Colors.blue, + width: 20, + height: 40, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + tagLabels[idx][0], + style: TextStyle(color: Colors.white, fontSize: 12), + ), + Text( + tagLabels[idx][1], + style: TextStyle(color: Colors.white, fontSize: 12), + ), + ], + ), + ), + ], + ), + SizedBox(height: 10), + Divider(height: 1, color: Colors.black12), + ], + ), + ); + } + + // 构建灰色网格项 + Widget _buildGridItem( + BuildContext context, { + required String icon, + required String title, + required String subtitle, + required int index, + }) { + return GestureDetector( + onTap: () { + if (index == 1) { + pushPage(DangerPage(), context); + } else if (index == 2) { + pushPage(DangerWaitListPage(DangerType.wait), context); + } else if (index == 3) { + pushPage(DangerWaitListPage(DangerType.expired), context); + }else if (index == 4) { + pushPage(DangerWaitListPage(DangerType.waitAcceptance), context); + }else if (index == 5) { + pushPage(DangerWaitListPage(DangerType.acceptance), context); + } + }, + child: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: const Color(0xfbf9f9ff), + borderRadius: BorderRadius.circular(6), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Image.asset(icon, width: 35, height: 35), + const SizedBox(width: 15), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 4), + Text( + subtitle, + style: const TextStyle(fontSize: 14, color: Colors.black), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/home/low_page.dart b/lib/pages/home/low_page.dart new file mode 100644 index 0000000..26c1647 --- /dev/null +++ b/lib/pages/home/low_page.dart @@ -0,0 +1,77 @@ +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/tools/tools.dart'; +import '/customWidget/search_bar_widget.dart'; + +class LowPage extends StatefulWidget { + const LowPage({super.key}); + + @override + State createState() => _LowPagePageState(); +} + +class _LowPagePageState extends State { + // 模拟数据 + final List> _dataInfos = List.generate(10, (i) { + return { + 'title': '测试数据标题标题 ${i + 1}', + }; + }); + final TextEditingController _searchController = TextEditingController(); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: MyAppbar( + title: "法律法规", + ), + body: SafeArea(child: _vcDetailWidget()), + ); + } + + Widget _vcDetailWidget() { + return Column( + children: [ + Padding( + padding: EdgeInsets.all(10), + child: SearchBarWidget( + controller: _searchController, + onSearch: (keyboard) { + // 输入请求接口 + + }, + ), + ), + + // 修复:使用Expanded包裹ListView确保正确高度 + Expanded( + child: ListView.separated( + separatorBuilder: (_, __) => const Divider(height: 0.5, color: Colors.black12,), + itemCount: _dataInfos.length, + itemBuilder: (context, index) { + final item = _dataInfos[index]; + return _fxitemCell(item); + }, + ), + ), + ], + ); + } + + Widget _fxitemCell(final item) { + String title = item['title']; + + return Container( + height: 50, + color: Colors.white, + padding: EdgeInsets.symmetric(horizontal: 16), // 添加水平内边距 + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(title), + Icon(Icons.arrow_forward_ios, color: Colors.black26,) + ], + ), + ); + } +} diff --git a/lib/pages/home/risk/riskControl_page.dart b/lib/pages/home/risk/riskControl_page.dart new file mode 100644 index 0000000..0bf360e --- /dev/null +++ b/lib/pages/home/risk/riskControl_page.dart @@ -0,0 +1,194 @@ +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/customWidget/custom_button.dart'; +import 'package:qhd_prevention/customWidget/custom_driver_drawer.dart'; +import 'package:qhd_prevention/pages/home/risk/risk_detail_page.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/tools/tools.dart'; +import '/customWidget/search_bar_widget.dart'; + +class RiskControlPage extends StatefulWidget { + const RiskControlPage({super.key}); + + @override + State createState() => _RiskControlPageState(); +} + +class _RiskControlPageState extends State { + // 模拟数据 + final List> _dataInfos = List.generate(10, (i) { + bool read = i % 3 == 0; + return { + 'title': '测试数据标题标题 ${i + 1}', + 'label1': '2025-06-${10 + i} 12:3${i}', + 'label2': '2025-06-${1 + i} 2:1${i}', + 'level': getRandomWithNum(1, 4), + }; + }); + + // 风险等级颜色 + final List _fxColors = [ + const Color(0xFFFADBD9), + const Color(0xFFFCE6D2), + const Color(0xFFFDF2CE), + const Color(0xFFCCE6FF), + ]; + final TextEditingController _searchController = TextEditingController(); + + // 风险等级文本 + final List _levelTexts = ["重大风险/A级", "较大风险/B级", "一般风险/C级", "低风险/D级"]; + final GlobalKey _scaffoldKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + // 取屏幕宽度 + final double screenWidth = MediaQuery.of(context).size.width; + + return Scaffold( + key: _scaffoldKey, // ② 绑定 key + appBar: MyAppbar( + title: "风险分布", + actions: [ + TextButton( + onPressed: () { + // 查询 右侧弹窗页面 + _scaffoldKey.currentState?.openEndDrawer(); + }, + child: Text( + "查询", + style: TextStyle(color: Colors.white, fontSize: 16), + ), + ), + ], + ), + endDrawer: Drawer( + // 用 Container 限制宽度为屏幕的 3/5 + child: Container( + width: screenWidth * 3 / 5, + color: Colors.white, + child: const CustomDriverDrawer(), + ), + ), + body: SafeArea(child: _vcDetailWidget()), + ); + } + + Widget _vcDetailWidget() { + return Column( + children: [ + Padding( + padding: EdgeInsets.all(10), + child: SearchBarWidget( + controller: _searchController, + onSearch: (keyboard) { + // 输入请求接口 + }, + ), + ), + + Expanded( + child: ListView.separated( + separatorBuilder: (_, __) => const Divider(height: 1), + itemCount: _dataInfos.length, + itemBuilder: (context, index) { + final item = _dataInfos[index]; + return _fxitemCell(item); + }, + ), + ), + ], + ); + } + + Widget _fxitemCell(final item) { + int level = item['level'] as int; + // 确保level在有效范围内 (1-4) + level = level.clamp(1, 4) - 1; + + // 使用GestureDetector包裹整个列表项以添加点击事件 + return GestureDetector( + onTap: () { + // 点击后跳转到详情页面 + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => RiskDetailPage(itemData: item), + ), + ); + }, + child: Container( + height: 100, + color: Colors.white, + padding: EdgeInsets.symmetric(horizontal: 16), // 添加水平内边距 + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // 左侧信息列 + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + item['title'] ?? '', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + SizedBox(height: 8), + Text( + item['label1'] ?? '', + style: TextStyle(fontSize: 14, color: Colors.grey), + ), + SizedBox(height: 4), + Text( + item['label2'] ?? '', + style: TextStyle(fontSize: 14, color: Colors.grey), + ), + ], + ), + ), + + // 右侧风险等级和箭头 + Padding( + padding: EdgeInsets.only(top: 15), + child: Column( + children: [ + // 风险等级标签 + Row( + children: [ + Container( + padding: EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + decoration: BoxDecoration( + color: _fxColors[level], + borderRadius: BorderRadius.circular(2), + ), + child: Text( + _levelTexts[level], + style: TextStyle(fontSize: 12), + ), + ), + SizedBox(width: 30), + ], + ), + SizedBox(height: 12), // 添加间距 + Row( + children: [ + SizedBox(width: 110), + Icon(Icons.arrow_forward_ios_rounded, size: 16), + ], + ), + ], + ), + ), + ], + ), + ), + ); + } +} + + + diff --git a/lib/pages/home/risk/risk_detail_page.dart b/lib/pages/home/risk/risk_detail_page.dart new file mode 100644 index 0000000..3d257c2 --- /dev/null +++ b/lib/pages/home/risk/risk_detail_page.dart @@ -0,0 +1,238 @@ +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/tools/tools.dart'; + +import '../../../tools/h_colors.dart'; + +class RiskDetailPage extends StatefulWidget { + const RiskDetailPage({super.key, required this.itemData}); + + final dynamic itemData; + + @override + State createState() => _RiskDetailPageState(); +} + +class _RiskDetailPageState extends State { + final List> _dataInfos = [ + { + "title": "存在风险", + "detail": ["测试", "测试去外地恰逢其会发起违反去和我i回复IQ请勿凤求凰IQ佛ifi哦好气哦hi哦发i哦前期我放弃"], + }, + { + "title": "主要管控措施", + "detail": ["测试去外地恰逢其会发起违反去和我i回复IQ请勿凤求凰IQ佛ifi哦好气哦hi哦发i哦前期我放"], + }, + { + "title": "管控部门", + "detail": ["哈哈"], + }, + { + "title": "事故类型", + "detail": ["物体打击,车辆伤害"], + }, + ]; + + @override + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: MyAppbar(title: "风险分布-详情"), + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + // 设置底部最小高度,要预留出来 + const double bottomAreaHeight = 100; + final double maxCardHeight = + constraints.maxHeight - bottomAreaHeight; + + return Column( + children: [ + // 卡片区:最大高度受限 + Padding( + padding: const EdgeInsets.all(15), + child: ConstrainedBox( + constraints: BoxConstraints(maxHeight: maxCardHeight), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(5), + boxShadow: [/* ... */], + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + _buildHeader(), + const Divider( + height: .5, + thickness: .5, + color: Colors.grey, + ), + + // ★ 这个 Flexible 包裹 SingleChildScrollView ★ + Flexible( + fit: FlexFit.loose, + child: SingleChildScrollView( + padding: const EdgeInsets.symmetric(vertical: 10), + physics: const ClampingScrollPhysics(), + child: Column( + mainAxisSize: MainAxisSize.min, + children: _dataInfos.map(_itemCell).toList(), + ), + ), + ), + + const Divider( + height: .5, + thickness: .5, + color: Colors.grey, + ), + _buildFooter(), + ], + ), + ), + ), + ), + Spacer(), + // 底部按钮固定 + _buildBottomButton(), + ], + ); + }, + ), + ), + ); + } + + // 头部信息组件 + Widget _buildHeader() { + return Padding( + padding: const EdgeInsets.all(15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + "风险点位", + style: TextStyle(fontSize: 16, color: Colors.black54), + ), + Text( + widget.itemData?['location'] ?? "未知地区", + style: const TextStyle(fontSize: 16, color: Colors.black54), + ), + ], + ), + ); + } + + // 风险等级标签 + Widget _buildFooter() { + return Padding( + padding: const EdgeInsets.all(15), + child: Row( + children: [ + Container( + margin: const EdgeInsets.only(bottom: 8), + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + color: const Color(0xFFFADBD9), + borderRadius: BorderRadius.circular(2), + ), + child: Text( + "风险等级", + style: TextStyle(color: const Color(0xFFE54D42)), + ), + ), + const Spacer(), + ], + ), + ); + } + + // 底部按钮 + Widget _buildBottomButton() { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), + child: SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.green, + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + elevation: 3, + ), + onPressed: () { + // 按钮点击事件 + }, + child: const Text( + "提交位置", + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + ), + ), + ); + } + + // 单项信息组件 + Widget _itemCell(Map item) { + final details = item["detail"] as List; + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 标题行 + Row( + children: [ + Container( + width: 4, + height: 16, + decoration: BoxDecoration( + color: Colors.black38, + borderRadius: BorderRadius.circular(2), + ), + ), + const SizedBox(width: 5), + Text( + item["title"], + style: const TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: Colors.black87, + ), + ), + ], + ), + const SizedBox(height: 10), + // 内容区域 + ...details.map((text) => _textItem(text, false)).toList(), + ], + ), + ); + } + + // 文本项组件 + Widget _textItem(String text, bool isInfinity) { + return Container( + width: isInfinity ? double.infinity : null, + margin: const EdgeInsets.only(bottom: 8), + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: h_backGroundColor(), + borderRadius: BorderRadius.circular(6), + ), + child: Text( + text, + style: const TextStyle( + fontSize: 14, + color: Colors.black87, + height: 1.5, + ), + ), + ); + } +} diff --git a/lib/pages/home/scan_page.dart b/lib/pages/home/scan_page.dart new file mode 100644 index 0000000..7eebba1 --- /dev/null +++ b/lib/pages/home/scan_page.dart @@ -0,0 +1,212 @@ +import 'dart:io'; +import 'dart:math' as math; + +import 'package:flutter/material.dart'; +import 'package:mobile_scanner/mobile_scanner.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:image_picker/image_picker.dart'; + +class ScanPage extends StatefulWidget { + const ScanPage({Key? key}) : super(key: key); + + @override + State createState() => _ScanPageState(); +} + +class _ScanPageState extends State { + final MobileScannerController _controller = MobileScannerController(); + bool _torchOn = false; + + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + Future _scanFromGallery() async { + final picker = ImagePicker(); + final XFile? image = await picker.pickImage(source: ImageSource.gallery); + if (image == null) return; + + try { + // ★ 新版:返回 BarcodeCapture? + final capture = await _controller.analyzeImage(image.path); + if (capture != null && capture.barcodes.isNotEmpty) { + final code = capture.barcodes.first.rawValue ?? ''; + _showResult(code); + } else { + _showResult('未识别到二维码/条码'); + } + } catch (e) { + _showResult('扫描失败:$e'); + } + } + + void _showResult(String code) { + showDialog( + context: context, + builder: (_) => AlertDialog( + title: const Text('扫描结果'), + content: Text(code), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + _controller.start(); // 恢复扫码 + }, + child: const Text('确定'), + ), + ], + ), + ); + } + + @override + Widget build(BuildContext context) { + // 中心扫描框大小 + const double scanSize = 250; + final Size screen = MediaQuery.of(context).size; + final double left = (screen.width - scanSize) / 2; + final double top = (screen.height - scanSize) / 3 - kToolbarHeight; + // 因为 SafeArea + AppBar 占了高度,所以减去 toolbar 高度 + const double cornerSize = 20.0; // 角标正方形区域大小 + const double strokeWidth = 4.0; // 边线宽度 + return Scaffold( + appBar: MyAppbar( + title: "二维码/条码扫描", + actions: [ + TextButton( + onPressed: _scanFromGallery, + child: const Text( + "相册", + style: TextStyle(color: Colors.white, fontSize: 16), + ), + ), + ], + ), + body: Stack( + children: [ + // 1. 摄像头预览 + MobileScanner( + controller: _controller, + onDetect: (capture) { + for (final barcode in capture.barcodes) { + final code = barcode.rawValue; + if (code != null && mounted) { + _controller.stop(); + _showResult(code); + break; + } + } + }, + ), + + // 2. 半透明遮罩 + // 顶部 + // 1. 顶部遮罩 + Positioned( + left: 0, right: 0, top: 0, + height: top, // 从顶到底部到扫描框上边缘 + child: Container(color: Colors.black54), + ), + + // 2. 底部遮罩 + Positioned( + left: 0, right: 0, + top: top + scanSize, // 从扫描框下边缘开始 + bottom: 0, + child: Container(color: Colors.black54), + ), + + // 3. 左侧遮罩 + Positioned( + left: 0, + top: top, + width: left, // 从屏幕左侧到扫描框左边缘 + height: scanSize, // 和扫描框一样高 + child: Container(color: Colors.black54), + ), + + // 4. 右侧遮罩 + Positioned( + left: left + scanSize, + top: top, + right: 0, + height: scanSize, // 和扫描框一样高 + child: Container(color: Colors.black54), + ), + + // 3. 扫描框四个角 + // 左上 + Positioned( + left: left, + top: top, + child: _corner(size: cornerSize, stroke: strokeWidth), + ), + // 右上 + Positioned( + left: left + scanSize - cornerSize, + top: top, + child: _corner(size: cornerSize, stroke: strokeWidth, rotation: 1), + ), + // 左下 + Positioned( + left: left, + top: top + scanSize - cornerSize, + child: _corner(size: cornerSize, stroke: strokeWidth, rotation: 3), + ), + // 右下 + Positioned( + left: left + scanSize - cornerSize, + top: top + scanSize - cornerSize, + child: _corner(size: cornerSize, stroke: strokeWidth, rotation: 2), + ), + + // 闪光灯按钮 + Positioned( + left: (screen.width - 40) / 2, + top: top + scanSize - 60, + child: IconButton( + iconSize: 32, + color: Colors.white, + icon: Icon(_torchOn ? Icons.flashlight_off_outlined : Icons.flashlight_on_outlined), + onPressed: () { + _controller.toggleTorch(); + setState(() { + _torchOn = !_torchOn; + }); + }, + ), + ), + ], + ), + ); + } + + /// 角装饰:一个 L 形的蓝色粗边 + Widget _corner({ + double size = 20, + double stroke = 4, + int rotation = 0, // 0=左上, 1=右上, 2=右下, 3=左下 + }) { + return Transform.rotate( + angle: rotation * math.pi / 2, + child: Container( + width: size, + height: size, + decoration: BoxDecoration( + border: Border( + top: BorderSide(color: Colors.blue, width: stroke), + left: BorderSide(color: Colors.blue, width: stroke), + ), + ), + ), + ); + } + +} diff --git a/lib/pages/home/userInfo_page.dart b/lib/pages/home/userInfo_page.dart new file mode 100644 index 0000000..d88f1bb --- /dev/null +++ b/lib/pages/home/userInfo_page.dart @@ -0,0 +1,64 @@ +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; + +class UserinfoPage extends StatefulWidget { + const UserinfoPage({super.key}); + + @override + State createState() => _UserinfoPageState(); +} + +class _UserinfoPageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: MyAppbar(title: "人员信息"), + body: SafeArea( + child: ListView( + children: [ + _userItemCell("姓名", "-----", false), + _userItemCell("部门", "-----", false), + _userItemCell("岗位", "-----", true), + ], + ), + ), + ); + } + + Widget _userItemCell(final String title, final String detail, bool isLast) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 15), + decoration: + isLast + ? const BoxDecoration( + color: Colors.white, + border: Border( + bottom: BorderSide(color: Colors.grey, width: 0), + ), + ) + : const BoxDecoration( + color: Colors.white, + + border: Border( + bottom: BorderSide(color: Colors.grey, width: 0.5), + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text(title, style: const TextStyle(fontSize: 16, color: Colors.grey)), + Flexible( + child: Text( + detail, + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500), + textAlign: TextAlign.right, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ); + } +} diff --git a/lib/pages/home/work/danger_page.dart b/lib/pages/home/work/danger_page.dart new file mode 100644 index 0000000..64bdfce --- /dev/null +++ b/lib/pages/home/work/danger_page.dart @@ -0,0 +1,255 @@ +import 'dart:ui'; + +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/customWidget/department_picker.dart'; +import 'package:qhd_prevention/customWidget/search_bar_widget.dart'; +import 'package:qhd_prevention/pages/home/scan_page.dart'; +import 'package:qhd_prevention/pages/home/work/risk_list_page.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/tools/SmallWidget.dart'; +import 'package:qhd_prevention/tools/tools.dart'; + +class DangerPage extends StatefulWidget { + const DangerPage({super.key}); + + @override + _DangerPageState createState() => _DangerPageState(); +} + +class _DangerPageState extends State + with SingleTickerProviderStateMixin { + late TabController _tabController; + int _selectedTab = 0; + + // 模拟数据 + final List _notifications = List.generate(10, (i) { + bool read = i % 3 == 0; + String title = '测试数据标题标题 ${i + 1}'; + String time = '2025-06-${10 + i} 12:3${i}'; + return NotificationItem(title, time); + }); + final List data = [ + Category( + id: '1', + title: '分类一', + children: [ + Category(id: '1-1', title: '子项 1-1'), + Category(id: '1-2', title: '子项 1-2'), + ], + ), + Category(id: '2', title: '分类二'), + Category( + id: '3', + title: '分类三', + children: [ + Category( + id: '3-1', + title: '子项 3-1', + children: [Category(id: '3-1-1', title: '子项 3-1-1')], + ), + ], + ), + ]; + final TextEditingController _searchController = TextEditingController(); + + @override + void initState() { + super.initState(); + _tabController = TabController(length: 2, vsync: this); + _tabController.addListener(() { + if (!_tabController.indexIsChanging) { + setState(() => _selectedTab = _tabController.index); + } + }); + } + + @override + void dispose() { + _tabController.dispose(); + super.dispose(); + } + void _handleItemTap(NotificationItem item, int index) { + print("点击了: ${item.title}"); + pushPage(riskListPage(), context); + } + // 显示分类选择器 + void showCategoryPicker() { + showModalBottomSheet( + context: context, + isScrollControlled: true, + barrierColor: Colors.black54, + backgroundColor: Colors.transparent, + builder: + (ctx) => DepartmentPicker( + data: data, + onSelected: (selectedId) { + setState(() {}); + }, + ), + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: MyAppbar( + title: "隐患排查", + actions: [ + TextButton( + onPressed: () { + pushPage(ScanPage(), context); + }, + child: Text( + "清单扫描", + style: TextStyle(color: Colors.white, fontSize: 16), + ), + ), + ], + ), + body: SafeArea( + child: Column( + children: [ + // Tab bar + TabBar( + controller: _tabController, + labelStyle: TextStyle(fontSize: 16), + indicator: UnderlineTabIndicator( + borderSide: BorderSide(width: 3.0, color: Colors.blue), + insets: EdgeInsets.symmetric(horizontal: 100.0), + ), + labelColor: Colors.blue, + unselectedLabelColor: Colors.grey, + tabs: const [Tab(text: '待排查'), Tab(text: '已排查')], + ), + + // Search bar + Padding( + padding: const EdgeInsets.all(10), + child: SearchBarWidget( + showResetButton: true, + onInputTap: () { + showCategoryPicker(); + }, + hintText: "", + isClickableOnly: true, + onSearch: (text) { + print('----------'); + }, + controller: _searchController, + ), + ), + + // List + Expanded( + child: ListView.separated( + itemCount: _notifications.length, + separatorBuilder: (_, __) => const SizedBox(), + itemBuilder: (context, index) { + NotificationItem item = _notifications[index]; + return GestureDetector( + onTap: () => _handleItemTap(item, index), + child: _itemCell(item), + ); + }, + ), + ), + ], + ), + ), + ); + } + + Widget _itemCell(final item) { + return Padding( + padding: EdgeInsets.only(left: 15, right: 15, bottom: 15), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(5)), + ), + child: Column( + children: [ + Padding( + padding: EdgeInsets.symmetric(vertical: 10, horizontal: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Icon( + Icons.star_rate_sharp, + color: Colors.green, + size: 18, + ), + SizedBox(width: 5), + Text("测试--------", style: TextStyle(fontSize: 14)), + ], + ), + Icon( + Icons.arrow_forward_ios_rounded, + color: Colors.grey, + size: 15, + ), + ], + ), + ), + Divider(height: 1), + Padding( + padding: EdgeInsets.symmetric(vertical: 10, horizontal: 15), + child: Column( + spacing: 5, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + HhTextStyleUtils.secondaryTitle("清单类型:测试"), + HhTextStyleUtils.secondaryTitle("排查周期:测试"), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + HhTextStyleUtils.secondaryTitle("包含检查项:3"), + HhTextStyleUtils.secondaryTitle("负责人:是测试"), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + HhTextStyleUtils.secondaryTitle( + "起始时间:2025-6-20 - 2026-3-31", + ), + SizedBox(), + ], + ), + ], + ), + ), + Padding( + padding: EdgeInsets.only(top: 0, bottom: 15, left: 15, right: 15), + child: Row( + spacing: 5, + children: [ + riskTagText(1, "重大风险:0"), + riskTagText(2, "较大:3"), + riskTagText(3, "一般:1"), + riskTagText(4, "低:0") + + ], + ), + ), + ], + ), + ), + ); + } + +} + +// 模拟数据模版 +class NotificationItem { + final String title; + final String time; + + NotificationItem(this.title, this.time); +} diff --git a/lib/pages/home/work/danger_project_page.dart b/lib/pages/home/work/danger_project_page.dart new file mode 100644 index 0000000..141e519 --- /dev/null +++ b/lib/pages/home/work/danger_project_page.dart @@ -0,0 +1,172 @@ +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/tools/h_colors.dart'; +import 'package:qhd_prevention/tools/tools.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; + +class DangerProjectPage extends StatefulWidget { + const DangerProjectPage({super.key}); + + @override + State createState() => _DangerProjectPageState(); +} + +class _DangerProjectPageState extends State { + // 单选按钮的值 + String? _selectedValue; + + // 单选按钮选项 + final List> _options = [ + { + "value": "option1", + "label": "合格", + "icon": Icons.check_circle_rounded, + "color": Colors.green, + }, + { + "value": "option2", + "label": "不合格", + "icon": Icons.check_circle_rounded, + "color": Colors.green, + }, + { + "value": "option3", + "label": "不涉及", + "icon": Icons.check_circle_rounded, + "color": Colors.green, + }, + ]; + + @override + Widget build(BuildContext context) { + final screenWidth = MediaQuery.of(context).size.width; + + return Scaffold( + backgroundColor: h_backGroundColor(), + appBar: MyAppbar(title: "隐患排除项"), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // 内容卡片 + Card( + color: Colors.white, + child: Container( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 问题描述 + Text( + "存在风险:1、罐体破损、变形、锈蚀等;2、附件安装不正确、不牢固;3、铭牌模糊无法识别;4、压力表不灵敏、不准确;5、报警装置故障失效;6、阀门锈蚀、泄露;7、洗眼器、防毒面具等应急设备缺失、过期。检查内容:1、定期检查獬体倩况,如发现破损、变形、锈蚀等情况及时进行维修;2、严格按照系统设计进行安装附件,确保附件安装牢固;3、及时清理铭牌上的异物,确保铭牌清晰可辨:4、定期检查压力表,确保压力表灵敏有效;5、定期检查报警装置,确保报警装置齐全有效;6、按时对阀门进行养护及定时检查紧固,及时更换阀门填料,操作时注意观察压帽是否随阀轴转动;7、定期检查应急设备,确保应急设备齐全有效", + style: TextStyle( + fontSize: 16, + color: Colors.grey[700], + height: 1.5, + ), + ), + + // 单选按钮组 + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: + _options.map((option) { + return _buildOptionButton( + context: context, + value: option['value'], + label: option['label'], + icon: option['icon'], + color: option['color'], + screenWidth: screenWidth, + ); + }).toList(), + ), + + ], + ), + ), + ), + Spacer(), + // 下一步按钮 + Container( + margin: const EdgeInsets.only(bottom: 20), + height: 50, + decoration: BoxDecoration( + color: _selectedValue != null ? Colors.green : Colors.grey, + borderRadius: BorderRadius.circular(10), + boxShadow: [ + BoxShadow( + color: Colors.black12, + blurRadius: 6, + offset: Offset(0, 2), + ), + ], + ), + child: TextButton( + onPressed: _selectedValue != null ? _submit : null, + child: Text( + "提交", + style: TextStyle( + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ), + ), + ), + ); + } + + // 构建单选按钮 + Widget _buildOptionButton({ + required BuildContext context, + required String value, + required String label, + required IconData icon, + required Color color, + required double screenWidth, + }) { + final isSelected = _selectedValue == value; + final buttonWidth = (screenWidth - 60) / 3 - 10; // 计算按钮宽度 + + return GestureDetector( + onTap: () { + setState(() { + _selectedValue = value; + }); + }, + child: Container( + width: buttonWidth, + padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8), + + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(icon, color: isSelected ? color : Colors.grey, size: 30), + const SizedBox(width: 8), + Text( + label, + style: TextStyle( + fontSize: 16, + fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, + color: isSelected ? color : Colors.grey[600], + ), + ), + ], + ), + ), + ); + } + + void _submit() { + if (_selectedValue == null) return; + + // 这里可以添加导航到下一页的代码 + // Navigator.push(context, MaterialPageRoute(builder: (_) => NextPage())); + } +} diff --git a/lib/pages/home/work/danger_repair_page.dart b/lib/pages/home/work/danger_repair_page.dart new file mode 100644 index 0000000..6ebdc93 --- /dev/null +++ b/lib/pages/home/work/danger_repair_page.dart @@ -0,0 +1,301 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:photo_view/photo_view.dart'; +import 'package:photo_view/photo_view_gallery.dart'; +import 'package:qhd_prevention/customWidget/custom_button.dart'; +import 'package:qhd_prevention/customWidget/single_image_viewer.dart'; +import 'package:qhd_prevention/pages/home/work/danger_wait_list_page.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/tools/h_colors.dart'; +import 'package:qhd_prevention/tools/tools.dart'; + +import '../../../customWidget/ItemWidgetFactory.dart'; +import '../../../customWidget/date_picker_dialog.dart'; +import '../../../customWidget/photo_picker_row.dart'; + +class DangerRepairPage extends StatefulWidget { + const DangerRepairPage(this.dangerType, {Key? key}) : super(key: key); + + final DangerType dangerType; + + @override + State createState() => _DangerRepairPageState(); +} + +class _DangerRepairPageState extends State { + bool _accepted = false; + var _selectData = DateTime.now(); + + Widget build(BuildContext context) { + return Scaffold( + appBar: MyAppbar(title: widget.dangerType.detailTitle), + body: SafeArea( + child: Column( + children: [ + // 可滚动内容区域 + Expanded( + child: SingleChildScrollView( + padding: const EdgeInsets.all(15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // 第一部分:内嵌列表 + _danner_detail(), + + ListItemFactory.createYesNoSection( + title: '是否正常整改', + yesLabel: '是', + noLabel: '否', + groupValue: _accepted, + onChanged: (val) { + setState(() { + _accepted = val; + }); + }, + ), + // 整改选项 + _accepted ? _danner_repair() : _noAccepet_repair(_accepted), + + const SizedBox(height: 20), + CustomButton(text: "提交", backgroundColor: Colors.blue), + ], + ), + ), + ), + // 底部警示文字,固定在页面底部 + Container( + padding: const EdgeInsets.all(15), + color: Colors.white, + child: Text( + ' 严禁在本互联网非涉密平台处理、传输国家秘密和工作秘密,请确认扫描、传输的文件资料不涉及国家秘密和工作秘密', + style: TextStyle(fontSize: 14, color: Colors.red), + ), + ), + ], + ), + ), + ); + } + + /// 整改 + Widget _danner_repair() { + return Container( + padding: EdgeInsets.only(bottom: 10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(5), + ), + child: Column( + children: [ + ListItemFactory.createBuildSimpleSection("隐患整改"), + Divider(height: 1), + Container( + height: 130, + padding: EdgeInsets.all(15), + child: Column( + children: [ + Row( + children: [HhTextStyleUtils.mainTitle("隐患描述", fontSize: 15)], + ), + TextField( + keyboardType: TextInputType.multiline, + maxLines: null, // 不限制行数,输入多少文字就撑开多少行 + style: TextStyle(fontSize: 15), + decoration: InputDecoration( + hintText: '请对隐患进行详细描述(必填项)', + border: InputBorder.none, + ), + ), + ], + ), + ), + Divider(height: 1), + GestureDetector( + onTap: () { + showDialog( + context: context, + builder: + (_) => HDatePickerDialog( + initialDate: DateTime.now(), + onCancel: () => Navigator.of(context).pop(), + onConfirm: (selected) { + print('选中日期: $selected'); + Navigator.of(context).pop(); + setState(() { + _selectData = selected; + }); + }, + ), + ); + }, + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 10), + child: ListItemFactory.createRowSpaceBetweenItem( + leftText: "整改日期", + rightText: "请选择", + isRight: true, + ), + ), + ), + Divider(), + Padding( + padding: EdgeInsets.symmetric(horizontal: 10), + child: ListItemFactory.createRowSpaceBetweenItem( + leftText: "整改后照片", + rightText: "0/4", + ), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 10), + child: PhotoPickerRow( + maxCount: 4, + onChanged: (List images) { + // images 列表更新 + }, + ), + ), + Divider(), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + CustomButton( + onPressed: () {}, + text: "添加", + backgroundColor: Colors.blue, + borderRadius: 17, + height: 34, + padding: EdgeInsets.symmetric(horizontal: 20), + ), + ], + ), + _departmentItem(1), + _departmentItem(2), + Divider(), + // ListItemFactory.createYesNoSection(title: "是否有整改方案", yesLabel: "", noLabel: noLabel, groupValue: groupValue, onChanged: onChanged) + ], + ), + ); + } + + Widget _departmentItem(int index) { + return Padding( + padding: const EdgeInsets.all(10), + child: Stack( + clipBehavior: Clip.none, + children: [ + Container( + decoration: BoxDecoration( + border: Border.all(color: Colors.black12, width: 1), + ), + child: _noAccepet_repair(false), + ), + + // 当 index > 1 时,左上角显示删除按钮 + if (index > 1) + Positioned( + top: -20, + left: -20, + child: IconButton( + padding: EdgeInsets.zero, + constraints: const BoxConstraints(), + icon: const Icon(Icons.cancel, color: Colors.red, size: 25), + onPressed: () { + // 这里处理删除逻辑,比如: + // setState(() => _items.removeAt(index)); + }, + ), + ), + ], + ), + ); + } + + + /// 不整改 + Widget _noAccepet_repair(bool _accept) { + return Column( + children: [ + Container( + padding: EdgeInsets.symmetric(horizontal: 10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(5), + ), + child: ListItemFactory.createRowSpaceBetweenItem( + leftText: "整改部门", + rightText: "测试啊", + isRight: true, + ), + ), + Divider(height: 10,color: _accept ? Colors.black12 : Colors.transparent,), + Container( + padding: EdgeInsets.symmetric(horizontal: 10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(5), + ), + child: ListItemFactory.createRowSpaceBetweenItem( + leftText: "整改负责人", + rightText: "测试啊", + isRight: true, + ), + ), + ], + ); + } + + /// 隐患详情 + Widget _danner_detail() { + return Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(5), + ), + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ListView.builder( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemCount: 16, + itemBuilder: (context, index) { + if (index == 0) { + return ListItemFactory.createAloneTextItem( + text: "地坪漆漆未分配全皮肤期漆未分配全皮肤期漆未分配全皮肤期未分配全皮肤期间哦飞机哦脾气金佛怕", + ); + } else if ((index > 0 && index < 4) || + index == 5 || + (index > 6 && index < 15)) { + return ListItemFactory.createRowSpaceBetweenItem( + leftText: "隐患来源", + rightText: "隐患排查", + ); + } else if (index == 4 || index == 6) { + return ListItemFactory.createColumnTextItem( + topText: "存在风险", + bottomText: "哦IQ好然后前后hi前后哦i", + ); + } + return ListItemFactory.createTextImageItem( + text: "隐患照片", + imageUrl: + "https://pic.rmb.bdstatic.com/bjh/news/100b8b78cbd136ede03249d9f3b3f5c42221.jpeg", + onImageTapped: () { + pushPage( + SingleImageViewer( + imageUrl: + "https://pic.rmb.bdstatic.com/bjh/news/100b8b78cbd136ede03249d9f3b3f5c42221.jpeg", + ), + context, + ); + }, + ); + }, + ), + ], + ), + ); + } +} diff --git a/lib/pages/home/work/danger_wait_list_page.dart b/lib/pages/home/work/danger_wait_list_page.dart new file mode 100644 index 0000000..ea79b69 --- /dev/null +++ b/lib/pages/home/work/danger_wait_list_page.dart @@ -0,0 +1,190 @@ +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/customWidget/custom_driver_drawer.dart'; +import 'package:qhd_prevention/pages/home/risk/risk_detail_page.dart'; +import 'package:qhd_prevention/pages/home/work/danger_repair_page.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/tools/h_colors.dart'; +import 'package:qhd_prevention/tools/tools.dart'; +import '/customWidget/search_bar_widget.dart'; + +enum DangerType { + wait("待整改隐患", "隐患整改"), + expired("超期未整改", "超期未整改-详情"), + waitAcceptance("隐患验收", "隐患验收"), + acceptance("已验收隐患", "已验收隐患"); + + final String displayName; + final String detailTitle; + + const DangerType(this.displayName, this.detailTitle); +} +class DangerWaitListPage extends StatefulWidget { + const DangerWaitListPage(this.dangerType,{super.key}); + final DangerType dangerType; + @override + State createState() => _DangerWaitListPageState(); +} + +class _DangerWaitListPageState extends State { + // 模拟数据 + final List> _dataInfos = List.generate(10, (i) { + bool read = i % 3 == 0; + return { + 'title': '测试数据标题标题 ${i + 1}', + 'label1': '2025-06-${10 + i} 12:3${i}', + 'label2': '2025-06-${1 + i} 2:1${i}', + 'level': getRandomWithNum(1, 2), + }; + }); + + // 隐患等级颜色 + final List _fxColors = [ + const Color(0xFFFCE6D2), + const Color(0xFFFDF2CE), + ]; + final TextEditingController _searchController = TextEditingController(); + + // 隐患等级文本 + final List _levelTexts = ["较大隐患","一般隐患"]; + final GlobalKey _scaffoldKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + // 取屏幕宽度 + final double screenWidth = MediaQuery.of(context).size.width; + + return Scaffold( + key: _scaffoldKey, // ② 绑定 key + appBar: MyAppbar( + title: widget.dangerType.displayName + ), + + body: SafeArea( + child: _vcDetailWidget()), + backgroundColor: Colors.white, + ); + } + + Widget _vcDetailWidget() { + return Column( + children: [ + Padding( + padding: EdgeInsets.all(10), + child: SearchBarWidget( + controller: _searchController, + onSearch: (keyboard) { + // 输入请求接口 + }, + ), + ), + Container( + height: 5, + color: h_backGroundColor(), + ), + Expanded( + child: ListView.separated( + separatorBuilder: (_, __) => const Divider(height: 1), + itemCount: _dataInfos.length, + itemBuilder: (context, index) { + final item = _dataInfos[index]; + return _fxitemCell(item); + }, + ), + ), + ], + ); + } + + Widget _fxitemCell(final item) { + int level = item['level'] as int; + // 确保level在有效范围内 (1-4) + level = level.clamp(1, 4) - 1; + + // 使用GestureDetector包裹整个列表项以添加点击事件 + return GestureDetector( + onTap: () { + // 点击后跳转到详情页面 + // pushDetailByType( + // type: item.type, + // context: context, + // ); + pushPage(DangerRepairPage(widget.dangerType), context); + + }, + child: Container( + height: 100, + color: Colors.white, + padding: EdgeInsets.symmetric(horizontal: 16), // 添加水平内边距 + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // 左侧信息列 + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + item['title'] ?? '', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + SizedBox(height: 8), + Text( + item['label1'] ?? '', + style: TextStyle(fontSize: 14, color: Colors.grey), + ), + SizedBox(height: 4), + Text( + item['label2'] ?? '', + style: TextStyle(fontSize: 14, color: Colors.grey), + ), + ], + ), + ), + + // 右侧风险等级和箭头 + Padding( + padding: EdgeInsets.only(top: 15), + child: Column( + children: [ + // 风险等级标签 + Row( + children: [ + Container( + padding: EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + decoration: BoxDecoration( + color: _fxColors[level], + borderRadius: BorderRadius.circular(2), + ), + child: Text( + _levelTexts[level], + style: TextStyle(fontSize: 12), + ), + ), + SizedBox(width: 30), + ], + ), + SizedBox(height: 12), // 添加间距 + Row( + children: [ + SizedBox(width: 110), + Icon(Icons.arrow_forward_ios_rounded, size: 16), + ], + ), + ], + ), + ), + ], + ), + ), + ); + } +} + + + diff --git a/lib/pages/home/work/risk_list_page.dart b/lib/pages/home/work/risk_list_page.dart new file mode 100644 index 0000000..d63e7f3 --- /dev/null +++ b/lib/pages/home/work/risk_list_page.dart @@ -0,0 +1,116 @@ +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/pages/home/scan_page.dart'; +import 'package:qhd_prevention/pages/home/work/danger_project_page.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/tools/h_colors.dart'; +import 'package:qhd_prevention/tools/tools.dart'; + +class riskListPage extends StatefulWidget { + const riskListPage({super.key}); + + @override + State createState() => _riskListPageState(); +} + +class _riskListPageState extends State { + + final List _dataList = [ + Model("青椒皮蛋鸡尾酒哦普佛椒皮鸡尾酒哦普佛椒皮鸡尾鸡尾酒哦普佛椒皮鸡尾鸡尾酒哦普佛椒皮鸡尾鸡尾酒哦普佛椒皮鸡尾鸡尾酒哦普佛"), + Model("dqfiqfjpoqo阿迪王期待期待五千多强大f"), + Model("dqfiqfjpoqof"), + Model("dqfiqfjpoqof") + ]; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: h_backGroundColor(), + appBar: MyAppbar( + title: "风险点(单元)列表", + actions: [ + TextButton( + onPressed: () { + pushPage(ScanPage(), context); + }, + child: Text( + "扫描", + style: TextStyle(color: Colors.white, fontSize: 16), + ), + ), + ], + ), + body: SafeArea( + child: Column( + children: [ + Expanded(child: ListView.separated( + itemCount: _dataList.length, + separatorBuilder: (_, __) => const SizedBox(), + itemBuilder: (context, index) { + Model item = _dataList[index]; + return GestureDetector( + onTap: () => _selectItem(item), + child: _itemCell(item), + ); + }, + )), + Container( + decoration: BoxDecoration( + color: Colors.green, + borderRadius: BorderRadius.circular(5) + ), + width: screenWidth(context) - 30, + height: 50, + child: TextButton( + onPressed: () => _nextHandle(), child: Text("下一步", style: TextStyle(color: Colors.white),)), + ) + + ], + )), + ); + } + + Widget _itemCell(Model item) { + return Padding(padding: EdgeInsets.symmetric(vertical: 7, horizontal: 15), + child: GestureDetector( + onTap: () => _selectItem(item), + child: Container( + height: 100, + padding: EdgeInsets.symmetric(horizontal: 10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(5) + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Image.asset("assets/images/zt-ing.png", width: 70, height: 70,), + const SizedBox(width: 10), // 添加间距 + Expanded( // 修复3: 文本过长时自动换行 + child: Text( + item.title, + style: const TextStyle(fontSize: 16), + maxLines: 2, // 限制两行 + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), + ), + ); + } + + void _nextHandle() { + + } + + void _selectItem(Model Item) { + pushPage(DangerProjectPage(), context); + } +} + +class Model { + final String title; + + Model(this.title); +} diff --git a/lib/pages/home/workSet_page.dart b/lib/pages/home/workSet_page.dart new file mode 100644 index 0000000..0c7b4bc --- /dev/null +++ b/lib/pages/home/workSet_page.dart @@ -0,0 +1,292 @@ +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/pages/home/work_alert.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/tools/tools.dart'; +import 'package:table_calendar/table_calendar.dart'; +import 'package:intl/intl.dart'; + +import '../../tools/h_colors.dart'; + +class WorkSetPage extends StatefulWidget { + const WorkSetPage({super.key}); + + @override + State createState() => _WorkSetPageState(); +} + +class _WorkSetPageState extends State { + DateTime _focusedDay = DateTime.now(); + DateTime _selectedDay = DateTime.now(); + + void _goToToday() { + setState(() { + _focusedDay = DateTime.now(); + _selectedDay = DateTime.now(); + selectDate(); + }); + } + + void _goToPrevMonth() { + setState(() { + _focusedDay = DateTime(_focusedDay.year, _focusedDay.month - 1); + }); + } + + void _goToNextMonth() { + setState(() { + _focusedDay = DateTime(_focusedDay.year, _focusedDay.month + 1); + }); + } + + void selectDate() { + print("======$_selectedDay"); + showWorkAlert( + context: context, + alertTitle: "标题:", + inputHint: "请输入", + contentHint: "请输入", + onConfirm: (title, content) { + // 处理确定后的逻辑 + print("标题: $title"); + print("内容: $content"); + }, + onCancel: () { + // 处理取消逻辑 + print("用户取消了操作"); + }, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: h_backGroundColor(), + appBar: MyAppbar(title: "工作安排"), + body: Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 1), + child: _calendarHeader(), + ), + Container( + padding: EdgeInsets.only(top: 10), + color: Colors.white, + child: TableCalendar( + locale: 'zh_CN', // 👈 设置为中文 + firstDay: DateTime(2000), + lastDay: DateTime(2100), + focusedDay: _focusedDay, + selectedDayPredicate: (day) => isSameDay(_selectedDay, day), + onDaySelected: (selectedDay, focusedDay) { + setState(() { + _selectedDay = selectedDay; + _focusedDay = focusedDay; + selectDate(); + }); + }, + daysOfWeekStyle: DaysOfWeekStyle( + dowTextFormatter: (date, locale) { + // date.weekday: 1=Mon ... 7=Sun + const weekdays = ['日', '一', '二', '三', '四', '五', '六']; + return weekdays[date.weekday % 7]; // 0=Sun + }, + weekdayStyle: const TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black87, + ), + weekendStyle: const TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black45, + ), + ), + calendarFormat: CalendarFormat.month, + startingDayOfWeek: StartingDayOfWeek.sunday, + headerVisible: false, + enabledDayPredicate: (day) { + // 禁用非当前月份日期 + return day.month == _focusedDay.month; + }, + calendarStyle: const CalendarStyle( + outsideTextStyle: TextStyle(color: Colors.grey), + outsideDecoration: BoxDecoration( + color: Colors.transparent, + shape: BoxShape.rectangle, + ), + todayDecoration: BoxDecoration( + color: Colors.transparent, // 不再使用默认 today 样式 + ), + selectedDecoration: BoxDecoration( + color: Colors.blue, + shape: BoxShape.circle, + ), + ), + calendarBuilders: CalendarBuilders( + defaultBuilder: (context, day, focusedDay) { + return _buildDayCell(day); + }, + outsideBuilder: (context, day, focusedDay) { + return _buildDayCell(day, isOutside: true); + }, + todayBuilder: (context, day, focusedDay) { + return _buildDayCell(day); + }, + selectedBuilder: (context, day, focusedDay) { + return _buildDayCell(day, isSelected: true); + }, + ), + ), + ), + Container(color: h_backGroundColor(), height: 20), + _workTipWidget(), + ], + ), + ); + } + + /// 本日工作题型 + Widget _workTipWidget() { + return Container( + color: Colors.white, + padding: EdgeInsets.all(12), + child: Column( + spacing: 20, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("本日工作题型", style: TextStyle(fontSize: 16)), + Spacer(), + ], + ), + Column( + spacing: 5, + children: [ + _itemCell("需进行2项隐患排查", true), + _itemCell("需进行2项隐患排查", false), + ], + + ), + ], + + ), + ); + } + Widget _itemCell(final String title, bool isFinish) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + spacing: 5, + children: [ + Icon(Icons.circle, size: 10, color: Colors.blue), + Text(title, style: TextStyle(color: Colors.black45),), + ], + ), + Text(isFinish?"已完成":"未完成", style: TextStyle(color: isFinish?Colors.green:Colors.red)), + ], + ); + } + ///日历头 + Widget _calendarHeader() { + return Container( + color: Colors.white, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // 占位 + const Spacer(), + const Spacer(), + // 中间内容:← 年月 → + Row( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + icon: const Icon(Icons.chevron_left), + onPressed: _goToPrevMonth, + padding: EdgeInsets.zero, + constraints: const BoxConstraints(), + ), + const SizedBox(width: 4), + Text( + DateFormat('yyyy年MM月').format(_focusedDay), + style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + const SizedBox(width: 4), + IconButton( + icon: const Icon(Icons.chevron_right), + onPressed: _goToNextMonth, + padding: EdgeInsets.zero, + constraints: const BoxConstraints(), + ), + ], + ), + const Spacer(), + Container( + height: 24, + decoration: BoxDecoration( + color: h_backGroundColor(), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(12), + bottomLeft: Radius.circular(12), + ), + ), + child: TextButton( + onPressed: _goToToday, + style: TextButton.styleFrom( + padding: const EdgeInsets.symmetric(horizontal: 7), + minimumSize: Size.zero, + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + ), + child: const Text("回到今天", style: TextStyle(fontSize: 11)), + ), + ), + ], + ), + ); + } + + Widget _buildDayCell( + DateTime day, { + bool isSelected = false, + bool isOutside = false, + }) { + final bool isToday = isSameDay(day, DateTime.now()); + final bool selected = isSameDay(day, _selectedDay); + + Color textColor; + if (selected) { + textColor = Colors.white; + } else if (isOutside) { + textColor = Colors.grey; + } else { + textColor = Colors.black87; + } + + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 35, + height: 35, + alignment: Alignment.center, + decoration: BoxDecoration( + color: selected ? Colors.blue : Colors.transparent, + shape: BoxShape.circle, + ), + child: Text( + '${day.day}', + style: TextStyle(color: textColor, fontWeight: FontWeight.w500), + ), + ), + if (isToday) + Text( + "今天", + style: TextStyle( + fontSize: 12, + color: selected ? Colors.white : Colors.blue, + ), + ), + ], + ); + } +} diff --git a/lib/pages/home/work_alert.dart b/lib/pages/home/work_alert.dart new file mode 100644 index 0000000..8c74415 --- /dev/null +++ b/lib/pages/home/work_alert.dart @@ -0,0 +1,176 @@ +import 'package:flutter/material.dart'; + +// 自定义弹窗组件 +class WorkAlertDialog extends StatefulWidget { + final String alertTitle; // 弹窗标题 + final String inputHint; // 输入框提示文本 + final String contentHint; // 内容框提示文本 + final String initialTitle; // 标题初始值 + final String initialContent; // 内容初始值 + final Function(String, String) onConfirm; // 确定回调 + final VoidCallback? onCancel; // 取消回调 + + const WorkAlertDialog({ + super.key, + required this.alertTitle, + this.inputHint = "请输入标题", + this.contentHint = "请输入内容", + this.initialTitle = "", + this.initialContent = "", + required this.onConfirm, + this.onCancel, + }); + + @override + State createState() => _WorkAlertDialogState(); +} + +class _WorkAlertDialogState extends State { + late TextEditingController _titleController; + late TextEditingController _contentController; + + @override + void initState() { + super.initState(); + _titleController = TextEditingController(text: widget.initialTitle); + _contentController = TextEditingController(text: widget.initialContent); + } + + @override + Widget build(BuildContext context) { + return Dialog( + backgroundColor: Colors.transparent, + child: Container( + width: MediaQuery.of(context).size.width * 0.6, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(5), + ), + padding: const EdgeInsets.all(15), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 弹窗标题 + Text( + widget.alertTitle, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 5), + + // 标题输入框 + TextField( + controller: _titleController, + decoration: InputDecoration( + border: const OutlineInputBorder(), + hintText: widget.inputHint, + contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), + ), + ), + const SizedBox(height: 20), + + // 内容标题 + const Text( + '内容:', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 5), + + // 内容输入框 + TextField( + controller: _contentController, + maxLines: 4, + decoration: InputDecoration( + border: const OutlineInputBorder(), + hintText: widget.contentHint, + contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 12), + ), + ), + const SizedBox(height: 10), + Padding( + padding: EdgeInsets.only(left: 40, right: 40), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ElevatedButton( + child: const Text('确定', style: TextStyle(color: Colors.white, fontSize: 14),), + style: ElevatedButton.styleFrom( + // maximumSize: Size(50, 30), + minimumSize: Size(50, 30), + backgroundColor: Colors.blue, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + ), + onPressed: () { + Navigator.of(context).pop(); // 关闭弹窗 + widget.onConfirm( + _titleController.text, + _contentController.text + ); + }, + ), + ElevatedButton( + + onPressed: () { + Navigator.of(context).pop(); // 关闭弹窗 + widget.onCancel?.call(); + }, + style: ElevatedButton.styleFrom( + // maximumSize: Size(50, 30), + minimumSize: Size(50, 30), + + backgroundColor: Colors.red, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + ), + child: const Text('取消', style: TextStyle(color: Colors.white, fontSize: 14),), + ) + ], + ), + ) + // 按钮行 + + ], + ), + ), + ); + } + + @override + void dispose() { + _titleController.dispose(); + _contentController.dispose(); + super.dispose(); + } +} + +// 在其他页面调用弹窗的方法 +void showWorkAlert({ + required BuildContext context, + required String alertTitle, + String inputHint = "请输入标题", + String contentHint = "请输入内容", + String initialTitle = "", + String initialContent = "", + required Function(String title, String content) onConfirm, + VoidCallback? onCancel, +}) { + showDialog( + context: context, + barrierColor: Colors.black.withOpacity(0.5), // 黑色半透明背景 + builder: (context) => WorkAlertDialog( + alertTitle: alertTitle, + inputHint: inputHint, + contentHint: contentHint, + initialTitle: initialTitle, + initialContent: initialContent, + onConfirm: onConfirm, + onCancel: onCancel, + ), + ); +} \ No newline at end of file diff --git a/lib/pages/login_page.dart b/lib/pages/login_page.dart new file mode 100644 index 0000000..c8fd3be --- /dev/null +++ b/lib/pages/login_page.dart @@ -0,0 +1,286 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:flutter/material.dart'; +import 'main_tab.dart'; + +void main() => runApp(const MyApp()); + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: '登录页面', + theme: ThemeData( + primarySwatch: Colors.blue, + inputDecorationTheme: const InputDecorationTheme( + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(horizontal: 8), + ), + ), + home: const LoginPage(), + debugShowCheckedModeBanner: false, + ); + } +} + +class LoginPage extends StatefulWidget { + const LoginPage({super.key}); + + @override + // ignore: library_private_types_in_public_api + _LoginPageState createState() => _LoginPageState(); +} + +class _LoginPageState extends State { + final TextEditingController _phoneController = TextEditingController(); + final TextEditingController _passwordController = TextEditingController(); + final GlobalKey _formKey = GlobalKey(); + String _errorMessage = ''; + bool _isLoading = false; + bool _obscurePassword = true; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + body: SingleChildScrollView( + child: Column( + children: [ + _buildHeader(), + + Transform.translate( + offset: const Offset(0, -20), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(30), + topRight: Radius.circular(30), + ), + ), + child: Padding( + padding: const EdgeInsets.only(top: 30), + child: Column( + children: [ + // 手机号 + _buildInputSection( + label: "手机号码", + controller: _phoneController, + hintText: "请输入手机号...", + keyboardType: TextInputType.phone, + validator: (value) { + if (value == null || value.isEmpty) { + return '请输入手机号'; + } + if (!RegExp(r'^1[3-9]\d{9}$').hasMatch(value)) { + return '请输入有效的手机号'; + } + return null; + }, + ), + + Padding(padding: const EdgeInsets.symmetric(horizontal: 25), + child: const Divider(height: 1, thickness: 1), + ), + // 密码 + _buildInputSection( + label: "密码", + controller: _passwordController, + hintText: "请输入密码...", + obscureText: _obscurePassword, + suffixIcon: IconButton( + icon: Icon( + _obscurePassword + ? Icons.visibility + : Icons.visibility_off, + color: Colors.grey, + ), + onPressed: () { + setState(() { + _obscurePassword = !_obscurePassword; + }); + }, + ), + validator: (value) { + if (value == null || value.isEmpty) { + return '请输入密码'; + } + if (value.length < 6) { + return '密码长度至少6位'; + } + return null; + }, + ), + Padding(padding: const EdgeInsets.symmetric(horizontal: 25), + child: const Divider(height: 1, thickness: 1), + ), + // 登录按钮 + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 25, vertical: 24), + child: SizedBox( + width: double.infinity, + height: 48, + child: ElevatedButton( + onPressed: _isLoading ? null : _handleLogin, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: _isLoading + ? const CircularProgressIndicator( + color: Colors.white, + ) + : const Text( + '登录', + style: TextStyle( + fontSize: 18, + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ), + Padding(padding: const EdgeInsets.only(left: 30, right: 30), + child:Text(" 本平台为互联网非涉密平台,严禁处理、传输国家秘密和工作秘密", + style: TextStyle(color: Colors.red)) + ) + ], + ), + ), + ), + ), + ], + ), + ), + ); + } + + // 顶部图片和文字 + Widget _buildHeader() { + return Stack( + alignment: Alignment.center, + children: [ + Image.asset( + 'assets/images/login-bg.png', + width: double.infinity, + fit: BoxFit.fitWidth, + ), + Positioned( + bottom: 40, + left: 30, + child: Column( + children: [ + const Text( + '欢迎登录', + style: TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, + color: Colors.white, + shadows: [ + Shadow( + blurRadius: 10, + color: Colors.black45, + offset: Offset(2, 2), + ), + ], + ), + ), + const SizedBox(height: 8), + Text( + '秦皇岛市应急管局\n数智应急管理平台', + style: TextStyle(fontSize: 18, color: Colors.white), + ), + ], + ), + ), + ], + ); + } + // 输入区域组件 + Widget _buildInputSection({ + required String label, + required TextEditingController controller, + required String hintText, + bool obscureText = false, + TextInputType keyboardType = TextInputType.text, + Widget? suffixIcon, + String? Function(String?)? validator, + }) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + color: Colors.black87, + ), + ), + const SizedBox(height: 15), + TextFormField( + controller: controller, + obscureText: obscureText, + keyboardType: keyboardType, + validator: validator, + // 关键属性:让文字在行内垂直居中 + textAlignVertical: TextAlignVertical.center, + decoration: InputDecoration( + hintText: hintText, + suffixIcon: suffixIcon, + // 去掉默认的上下/左右 padding,让文字贴紧外层的 25 左边距 + isDense: true, + contentPadding: EdgeInsets.zero, + ), + ), + ], + ), + ); + } + + + // 登录处理 + void _handleLogin() { + // 清除之前的错误信息 + setState(() => _errorMessage = ''); + Navigator.pushReplacement( + context, + MaterialPageRoute(builder: (context) => const MainPage()), + ); + // if (_formKey.currentState?.validate() ?? false) { + // setState(() => _isLoading = true); + // + // // 模拟登录请求 + // Future.delayed(const Duration(seconds: 2), () { + // setState(() => _isLoading = false); + // // 登录成功,跳转到主页 + // // Navigator.pushReplacement( + // // context, + // // MaterialPageRoute(builder: (context) => const MainPage()), + // // ); + // // 模拟登录逻辑 + // if (_phoneController.text == "13800138000" && + // _passwordController.text == "123456") { + // // 登录成功,跳转到主页 + // Navigator.pushReplacement( + // context, + // MaterialPageRoute(builder: (context) => const MainPage()), + // ); + // } else { + // // 登录失败,显示错误信息 + // setState(() { + // _errorMessage = '手机号或密码错误,请重试'; + // }); + // } + // }); + // } + } +} diff --git a/lib/pages/main_tab.dart b/lib/pages/main_tab.dart new file mode 100644 index 0000000..c1dff41 --- /dev/null +++ b/lib/pages/main_tab.dart @@ -0,0 +1,89 @@ +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/pages/home/scan_page.dart'; +import 'home/home_page.dart'; +import 'app/application_page.dart'; +import 'mine/mine_page.dart'; +import 'notif/notif_page.dart'; + +class MainPage extends StatefulWidget { + const MainPage({super.key}); + + @override + _MainPageState createState() => _MainPageState(); +} + +class _MainPageState extends State { + int _currentIndex = 0; + + // 页面列表 + final List _pages = const [ + HomePage(), + ApplicationPage(), + NotifPage(), + MinePage() + ]; + + // 页面标题 + final List _titles = [ + '首页', + '应用中心', + '通知公告', + '我的', + ]; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: _currentIndex == 1 + ? null + : AppBar( + title: Text( + _currentIndex == 0 ? "泰盛安全首页" : _titles[_currentIndex], + style: const TextStyle( + fontSize: 17, + color: Colors.white, + ), + ), + centerTitle: true, + backgroundColor: Colors.blue, + actions: [ + if (_currentIndex == 0) + IconButton(onPressed: () { + Navigator.push(context, MaterialPageRoute(builder: (context) => ScanPage() )); + }, icon: Image.asset("assets/images/scan.png", width: 20, height: 20,)) + ], + ), + + body: _pages[_currentIndex], + bottomNavigationBar: BottomNavigationBar( + currentIndex: _currentIndex, + type: BottomNavigationBarType.fixed, // 保证超过3个图标不压缩 + selectedItemColor: Colors.blue, + unselectedItemColor: Colors.grey, + onTap: (index) => setState(() => _currentIndex = index), + items: [ + BottomNavigationBarItem( + icon: Image.asset('assets/tabbar/basics.png', width: 24, height: 24), + activeIcon: Image.asset('assets/tabbar/basics_cur.png', width: 24, height: 24), + label: '首页', + ), + BottomNavigationBarItem( + icon: Image.asset('assets/tabbar/application.png', width: 24, height: 24), + activeIcon: Image.asset('assets/tabbar/application_cur.png', width: 24, height: 24), + label: '应用', + ), + BottomNavigationBarItem( + icon: Image.asset('assets/tabbar/works.png', width: 24, height: 24), + activeIcon: Image.asset('assets/tabbar/works_cur.png', width: 24, height: 24), + label: '通知', + ), + BottomNavigationBarItem( + icon: Image.asset('assets/tabbar/my.png', width: 24, height: 24), + activeIcon: Image.asset('assets/tabbar/my_cur.png', width: 24, height: 24), + label: '我的', + ), + ], + ), + ); + } +} diff --git a/lib/pages/mine/mine_page.dart b/lib/pages/mine/mine_page.dart new file mode 100644 index 0000000..735b6f7 --- /dev/null +++ b/lib/pages/mine/mine_page.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; + +class MinePage extends StatefulWidget { + const MinePage({super.key}); + + @override + State createState() => _MinePageState(); +} + +class _MinePageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body: ListView(children: [ + Container( + height: 120, + color: Colors.white, + padding: EdgeInsets.all(0), + child: Padding( + padding: EdgeInsets.only(left: 30), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + spacing: 10, + children: [ + + ClipRRect( + borderRadius: BorderRadius.circular(30), + child: Image.asset( + "assets/images/avatar.png", + height: 60, + width: 60, + ), + ), + SizedBox( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + spacing: 10, + children: [ + Text("珊瑚撒", style: TextStyle(fontSize: 17, fontWeight: FontWeight.bold),), + Text("手机号:129378348949", style: TextStyle(color: Colors.black54),)], + ), + ), + ], + ), + ), + ), + SizedBox(height: 10,), + _setItemWidget("设置"), + Divider(height: 1,color: Colors.black12,), + _setItemWidget("关于") + ],), + ); + } + Widget _setItemWidget(final String text) { + return Container( + height: 55, + color: Colors.white, + child: Padding( + padding: EdgeInsets.all(15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(text, style: TextStyle(fontSize: 16),), + Icon(Icons.chevron_right) + ], + ), + ), + ); + } + +} + diff --git a/lib/pages/my_appbar.dart b/lib/pages/my_appbar.dart new file mode 100644 index 0000000..9c6df44 --- /dev/null +++ b/lib/pages/my_appbar.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; + +class MyAppbar extends StatelessWidget implements PreferredSizeWidget { + final String title; + final VoidCallback? onBackPressed; + final Color backgroundColor; + final Color textColor; + final List? actions; // 👉 新增参数:右侧按钮 + + const MyAppbar({ + Key? key, + required this.title, + this.onBackPressed, + this.backgroundColor = Colors.blue, + this.textColor = Colors.white, + this.actions, + }) : super(key: key); + + @override + Size get preferredSize => const Size.fromHeight(kToolbarHeight); + + @override + Widget build(BuildContext context) { + return AppBar( + backgroundColor: backgroundColor, + automaticallyImplyLeading: false, + centerTitle: true, + title: Text( + title, + style: TextStyle( + color: textColor, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + leading: _buildBackButton(context), + actions: actions, // 👉 设置右侧按钮 + ); + } + + Widget _buildBackButton(BuildContext context) { + return IconButton( + icon: const Icon(Icons.arrow_back_ios, color: Colors.white, size: 20), + onPressed: onBackPressed ?? () => Navigator.of(context).pop(), + ); + } +} diff --git a/lib/pages/notif/notif_page.dart b/lib/pages/notif/notif_page.dart new file mode 100644 index 0000000..c76b561 --- /dev/null +++ b/lib/pages/notif/notif_page.dart @@ -0,0 +1,158 @@ +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/customWidget/search_bar_widget.dart'; + +class NotifPage extends StatefulWidget { + const NotifPage({Key? key}) : super(key: key); + + @override + _NotifPageState createState() => _NotifPageState(); +} + +class _NotifPageState extends State with SingleTickerProviderStateMixin { + late TabController _tabController; + int _selectedTab = 0; + + // 模拟数据 + final List> _notifications = List.generate(10, (i) { + bool read = i % 3 == 0; + return { + 'title': '测试数据标题标题 ${i + 1}', + 'time': '2025-06-${10 + i} 12:3${i}', + 'read': read, + }; + }); + + @override + void initState() { + super.initState(); + _tabController = TabController(length: 2, vsync: this); + _tabController.addListener(() { + if (!_tabController.indexIsChanging) { + setState(() => _selectedTab = _tabController.index); + } + }); + } + + @override + void dispose() { + _tabController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final TextEditingController searchController = TextEditingController(); + + return GestureDetector( + onTap: () { + FocusScope.of(context).unfocus(); // 收起键盘 + }, + behavior: HitTestBehavior.opaque, + child: Scaffold( + body: SafeArea( + child:Column( + children: [ + // Tab bar + TabBar( + controller: _tabController, + labelStyle: TextStyle(fontSize: 16), + indicator: UnderlineTabIndicator( + borderSide: BorderSide(width: 3.0, color: Colors.blue), + insets: EdgeInsets.symmetric(horizontal: 100.0), + ), + labelColor: Colors.blue, + unselectedLabelColor: Colors.grey, + tabs: const [ + Tab(text: '政府公告'), + Tab(text: '企业公告'), + ], + ), + + // Search bar + Padding( + padding: const EdgeInsets.all(10), + child: SearchBarWidget( + controller: searchController, + onSearch: (keyword) { + print("用户输入的是: $keyword"); + // TODO: 执行搜索 + }, + ) + ), + + // List + Expanded( + child: ListView.separated( + itemCount: _notifications.length, + separatorBuilder: (_, __) => const Divider(height: 1), + itemBuilder: (context, index) { + final item = _notifications[index]; + return _itemCell(item); + }, + ), + ), + ], + ) + ), + ), + ); + } + + Widget _itemCell(final item) { + return ListTile( + contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + + title: Padding( + padding: const EdgeInsets.only(bottom: 20), // 减小底部间距 + child: Text( + item['title'], + style: const TextStyle(fontSize: 14), + ), + ), + + subtitle: Text( + item['time'], + style: TextStyle(fontSize: 13), + ), + + trailing: Container( + constraints: const BoxConstraints(minHeight: 100), // 确保最小高度 + + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, // 关键修改:使用最小尺寸 + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + item['read'] ? '已读' : '未读', + style: TextStyle( + fontSize: 12, // 稍微减小字体大小 + color: item['read'] ? Colors.grey : Colors.red, + ), + ), + SizedBox(height: 15,), + + if (item['read']) + SizedBox( + height: 24, // 固定按钮高度 + child: TextButton( + onPressed: () {}, + child: const Text( + '删除', + style: TextStyle(fontSize: 13, color: Colors.white), + ), + style: TextButton.styleFrom( + padding: const EdgeInsets.symmetric(horizontal: 12), + backgroundColor: Colors.red, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/tools/SmallWidget.dart b/lib/tools/SmallWidget.dart new file mode 100644 index 0000000..73df7b0 --- /dev/null +++ b/lib/tools/SmallWidget.dart @@ -0,0 +1,25 @@ +import 'dart:ffi'; + +import 'package:flutter/material.dart'; + +import 'h_colors.dart'; +/// 标签(eg:风险等级) +Widget riskTagText(int level, String title) { + + final List colors = riskLevelTextColors(); + if (colors.length <= (level - 1)) { + return SizedBox(); + } + return Container( + padding: EdgeInsets.symmetric(vertical: 3, horizontal: 5), + decoration: BoxDecoration( + color: colors[level-1], + borderRadius: const BorderRadius.all(Radius.circular(5)), + ), + // color: Colors., + child: Text( + title, + style: TextStyle(color: Colors.white, fontSize: 14), + ), + ); +} \ No newline at end of file diff --git a/lib/tools/h_colors.dart b/lib/tools/h_colors.dart new file mode 100644 index 0000000..5f0251a --- /dev/null +++ b/lib/tools/h_colors.dart @@ -0,0 +1,11 @@ +import 'dart:ffi'; +import 'dart:ui'; + +Color h_backGroundColor() => Color(0xF1F1F1FF); +List riskLevelTextColors() { + return [Color(0xFFE54D42),Color(0xFFF37B1D),Color(0xFFF9BD08),Color(0xFF3281FF)]; +} + +List riskLevelBgColors() { + return [Color(0xFFFADBD9),Color(0xFFFCE6D2),Color(0xFFFDF2CE),Color(0xFFCCE6FF)]; +} diff --git a/lib/tools/tools.dart b/lib/tools/tools.dart new file mode 100644 index 0000000..d7814fe --- /dev/null +++ b/lib/tools/tools.dart @@ -0,0 +1,85 @@ +import 'dart:ui'; +import 'dart:math'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +int getRandomWithNum(int min, int max) { + final random = Random(); + return random.nextInt(max) + min; // 生成随机数 +} + +double screenWidth(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + return screenWidth; +} + +void pushPage(Widget page, BuildContext context) { + Navigator.push(context, MaterialPageRoute(builder: (context) => page)); +} +/// 文本样式工具类 +/// 文本样式工具类 +/// 文本样式工具类,返回 Text Widget +class HhTextStyleUtils { + /// 主要标题,返回 Text + /// [text]: 文本内容 + /// [color]: 文本颜色,默认黑色 + /// [fontSize]: 字体大小,默认16.0 + /// [bold]: 是否加粗,默认true + static Text mainTitle( + String text, { + Color color = Colors.black, + double fontSize = 16.0, + bool bold = true, + }) { + return Text( + text, + style: TextStyle( + color: color, + fontSize: fontSize, + fontWeight: bold ? FontWeight.bold : FontWeight.normal, + ), + ); + } + + /// 次要标题,返回 Text + /// [text]: 文本内容 + /// [color]: 文本颜色,默认深灰 + /// [fontSize]: 字体大小,默认14.0 + /// [bold]: 是否加粗,默认false + static Text secondaryTitle( + String text, { + Color color = Colors.black54, + double fontSize = 14.0, + bool bold = false, + }) { + return Text( + text, + style: TextStyle( + color: color, + fontSize: fontSize, + fontWeight: bold ? FontWeight.bold : FontWeight.normal, + ), + ); + } + + /// 小文字,返回 Text + /// [text]: 文本内容 + /// [color]: 文本颜色,默认灰色 + /// [fontSize]: 字体大小,默认12.0 + /// [bold]: 是否加粗,默认false + static Text smallText( + String text, { + Color color = Colors.black54, + double fontSize = 12.0, + bool bold = false, + }) { + return Text( + text, + style: TextStyle( + color: color, + fontSize: fontSize, + fontWeight: bold ? FontWeight.bold : FontWeight.normal, + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..7c71458 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,706 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.12.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.1.2" + characters: + dependency: transitive + description: + name: characters + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.4.0" + clock: + dependency: transitive + description: + name: clock + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.1.2" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.19.1" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "0.3.4+2" + crypto: + dependency: transitive + description: + name: crypto + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "3.0.6" + csslib: + dependency: transitive + description: + name: csslib + sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.0.2" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.0.8" + extended_image: + dependency: transitive + description: + name: extended_image + sha256: f6cbb1d798f51262ed1a3d93b4f1f2aa0d76128df39af18ecb77fa740f88b2e0 + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "10.0.1" + extended_image_library: + dependency: transitive + description: + name: extended_image_library + sha256: "1f9a24d3a00c2633891c6a7b5cab2807999eb2d5b597e5133b63f49d113811fe" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "5.0.1" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.3.2" + ffi: + dependency: transitive + description: + name: ffi + sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.1.4" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "7.0.1" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "0.9.3+2" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: "8c9250b2bd2d8d4268e39c82543bacbaca0fda7d29e0728c3c4bbb7c820fd711" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "0.9.4+3" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.6.2" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: "320fcfb6f33caa90f0b58380489fc5ac05d99ee94b61aa96ec2bff0ba81d3c2b" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "0.9.3+4" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "5.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: f948e346c12f8d5480d2825e03de228d0eb8c3a737e4cdaa122267b89c022b5e + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.0.28" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + html: + dependency: transitive + description: + name: html + sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "0.15.6" + http: + dependency: transitive + description: + name: http + sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.4.0" + http_client_helper: + dependency: transitive + description: + name: http_client_helper + sha256: "8a9127650734da86b5c73760de2b404494c968a3fd55602045ffec789dac3cb1" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "3.0.0" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "4.1.2" + image_picker: + dependency: "direct main" + description: + name: image_picker + sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.1.2" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "317a5d961cec5b34e777b9252393f2afbd23084aa6e60fcf601dcf6341b9ebeb" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "0.8.12+23" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "717eb042ab08c40767684327be06a5d8dbb341fe791d514e4b92c7bbe1b7bb83" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "3.0.6" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: "05da758e67bc7839e886b3959848aa6b44ff123ab4b28f67891008afe8ef9100" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "0.8.12+2" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "34a65f6740df08bbbeb0a1abd8e6d32107941fd4868f67a507b25601651022c9" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "0.2.1+2" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "1b90ebbd9dcf98fb6c1d01427e49a55bd96b5d67b8c67cf955d60a5de74207c1" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "0.2.1+2" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: "886d57f0be73c4b140004e78b9f28a8914a09e50c2d816bdd0520051a71236a0" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.10.1" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "0.2.1+1" + intl: + dependency: "direct main" + description: + name: intl + sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "0.20.2" + js: + dependency: transitive + description: + name: js + sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "0.7.2" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "10.0.8" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "3.0.9" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "3.0.1" + lints: + dependency: transitive + description: + name: lints + sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "5.1.1" + matcher: + dependency: transitive + description: + name: matcher + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "0.12.17" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "0.11.1" + meta: + dependency: transitive + description: + name: meta + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.16.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.0.0" + mobile_scanner: + dependency: "direct main" + description: + name: mobile_scanner + sha256: "54005bdea7052d792d35b4fef0f84ec5ddc3a844b250ecd48dc192fb9b4ebc95" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "7.0.1" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.0.0" + path: + dependency: transitive + description: + name: path + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.9.1" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.1.5" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9 + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.2.17" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.4.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.3.0" + photo_manager: + dependency: transitive + description: + name: photo_manager + sha256: a0d9a7a9bc35eda02d33766412bde6d883a8b0acb86bbe37dac5f691a0894e8a + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "3.7.1" + photo_manager_image_provider: + dependency: transitive + description: + name: photo_manager_image_provider + sha256: b6015b67b32f345f57cf32c126f871bced2501236c405aafaefa885f7c821e4f + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.2.0" + photo_view: + dependency: "direct main" + description: + name: photo_view + sha256: "1fc3d970a91295fbd1364296575f854c9863f225505c28c46e0a03e48960c75e" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "0.15.0" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "3.1.6" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.1.8" + provider: + dependency: transitive + description: + name: provider + sha256: "4abbd070a04e9ddc287673bf5a030c7ca8b685ff70218720abab8b092f53dd84" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "6.1.5" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.5.3" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "20cbd561f743a342c76c151d6ddb93a9ce6005751e7aa458baad3858bfbfb6ac" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.4.10" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.5.4" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.4.1" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.4.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.4.3" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.4.1" + simple_gesture_detector: + dependency: transitive + description: + name: simple_gesture_detector + sha256: ba2cd5af24ff20a0b8d609cec3f40e5b0744d2a71804a2616ae086b9c19d19a3 + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "0.2.1" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + source_span: + dependency: transitive + description: + name: source_span + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.10.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.12.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.1.4" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.4.1" + table_calendar: + dependency: "direct main" + description: + name: table_calendar + sha256: "0c0c6219878b363a2d5f40c7afb159d845f253d061dc3c822aa0d5fe0f721982" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "3.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.2.2" + test_api: + dependency: transitive + description: + name: test_api + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "0.7.4" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.4.0" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.1.4" + video_player: + dependency: transitive + description: + name: video_player + sha256: "0d55b1f1a31e5ad4c4967bfaa8ade0240b07d20ee4af1dfef5f531056512961a" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.10.0" + video_player_android: + dependency: transitive + description: + name: video_player_android + sha256: "4a5135754a62dbc827a64a42ef1f8ed72c962e191c97e2d48744225c2b9ebb73" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.8.7" + video_player_avfoundation: + dependency: transitive + description: + name: video_player_avfoundation + sha256: "0d47db6cbf72db61d86369219efd35c7f9d93515e1319da941ece81b1f21c49c" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.7.2" + video_player_platform_interface: + dependency: transitive + description: + name: video_player_platform_interface + sha256: cf2a1d29a284db648fd66cbd18aacc157f9862d77d2cc790f6f9678a46c1db5a + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "6.4.0" + video_player_web: + dependency: transitive + description: + name: video_player_web + sha256: e8bba2e5d1e159d5048c9a491bb2a7b29c535c612bb7d10c1e21107f5bd365ba + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "2.3.5" + visibility_detector: + dependency: transitive + description: + name: visibility_detector + sha256: dd5cc11e13494f432d15939c3aa8ae76844c42b723398643ce9addb88a5ed420 + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "0.4.0+2" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "14.3.1" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.1.1" + wechat_assets_picker: + dependency: "direct main" + description: + name: wechat_assets_picker + sha256: cafe3d32564ed3cacf9822f251941f7b44fe9885c17c8de4fca7e939a459e1ef + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "9.5.1" + wechat_picker_library: + dependency: transitive + description: + name: wechat_picker_library + sha256: a42e09cb85b15fc9410f6a69671371cc60aa99c4a1f7967f6593a7f665f6f47a + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.0.5" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.1.0" +sdks: + dart: ">=3.7.0 <4.0.0" + flutter: ">=3.29.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..dad599c --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,105 @@ +name: qhd_prevention +description: "A new Flutter project." +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +# In Windows, build-name is used as the major, minor, and patch parts +# of the product and file versions while build-number is used as the build suffix. +version: 1.0.0+1 + +environment: + sdk: ^3.7.0 + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.8 + shared_preferences: ^2.2.2 # 用于保存登录状态 + # 扫码 + mobile_scanner: ^7.0.1 + # 相册 + image_picker: ^1.1.2 + wechat_assets_picker: ^9.5.1 + # 日历 + table_calendar: ^3.2.0 + intl: ^0.20.0 + #图片查看大图 + photo_view: ^0.15.0 + +dev_dependencies: + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^5.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + assets: + - assets/images/ + - assets/icon-apps/ + - assets/image/ + - assets/js/ + - assets/map/ + - assets/tabbar/ + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/to/asset-from-package + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/to/font-from-package