初始化

This commit is contained in:
zpc 2026-03-02 18:13:36 +08:00
commit d50fd7ae9b
885 changed files with 88310 additions and 0 deletions

39
.gitignore vendored Normal file
View File

@ -0,0 +1,39 @@
# 操作系统相关
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
Desktop.ini
# IDE 相关
.vscode/
.idea/
*.swp
*.swo
*~
# 日志文件
*.log
logs/
# 临时文件
*.tmp
*.temp
*.bak
*.cache
# 环境配置文件(包含敏感信息)
.env
.env.local
.env.*.local
# 依赖目录
node_modules/
# 构建输出
dist/
build/
out/

89
app/.gitignore vendored Normal file
View File

@ -0,0 +1,89 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# VS Code
.vscode/
*.code-workspace
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
.packages
.flutter-plugins-dependencies
.metadata
# 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
# Android 相关
/android/local.properties
/android/.gradle/
/android/captures/
/android/gradlew
/android/gradlew.bat
/android/key.properties
*.jks
*.keystore
# iOS 相关
/ios/Pods/
/ios/.symlinks/
/ios/Flutter/Flutter.framework
/ios/Flutter/Flutter.podspec
/ios/Flutter/Generated.xcconfig
/ios/Flutter/app.flx
/ios/Flutter/app.zip
/ios/Flutter/flutter_assets/
/ios/ServiceDefinitions.json
/ios/Runner/GeneratedPluginRegistrant.*
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/xcuserdata/
# Web 相关
/web/flutter_service_worker.js
/web/version.json
# 依赖锁定文件(可选,团队协作时建议保留)
pubspec.lock
# 环境配置
.env
.env.local
# 生成的文件
*.g.dart
*.freezed.dart
*.gr.dart

16
app/README.md Normal file
View File

@ -0,0 +1,16 @@
# odf
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.

28
app/analysis_options.yaml Normal file
View File

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

13
app/android/.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks

View File

@ -0,0 +1,73 @@
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
android {
namespace "com.machine.odf.odf"
compileSdk flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
signingConfigs {
//
signConfig {
storeFile file("talk.jks")
storePassword '123456'
keyAlias 'talk'
keyPassword '123456'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.machine.odf.odf"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
signingConfig signingConfigs.signConfig //gradlew assembleRelease
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
//
minifyEnabled false //
shrinkResources false //
}
debug {
signingConfig signingConfigs.signConfig
}
}
}
flutter {
source '../..'
}

View File

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

View File

@ -0,0 +1,47 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"
android:label="绥时录">
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:exported="true"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility?hl=en and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT" />
<data android:mimeType="text/plain" />
</intent>
</queries>
</manifest>

View File

@ -0,0 +1,6 @@
package com.machine.odf.odf;
import io.flutter.embedding.android.FlutterActivity;
public class MainActivity extends FlutterActivity {
}

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

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

View File

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

View File

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

18
app/android/build.gradle Normal file
View File

@ -0,0 +1,18 @@
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

View File

@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx4G
android.useAndroidX=true
android.enableJetifier=true

View File

@ -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-7.6.3-all.zip

View File

@ -0,0 +1,26 @@
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}
settings.ext.flutterSdkPath = flutterSdkPath()
includeBuild("${settings.ext.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 "7.3.0" apply false
id "org.jetbrains.kotlin.android" version "1.7.10" apply false
}
include ":app"

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 893 KiB

34
app/ios/.gitignore vendored Normal file
View File

@ -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

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
</dict>
</plist>

View File

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

View File

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

View File

@ -0,0 +1,616 @@
// !$*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 */; };
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 */; };
/* 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 = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
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 = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
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 = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
331C8082294A63A400263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C807B294A618700263BE5 /* RunnerTests.swift */,
);
path = RunnerTests;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
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 = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
331C8080294A63A400263BE5 /* RunnerTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
331C807D294A63A400263BE5 /* Sources */,
331C807F294A63A400263BE5 /* Resources */,
);
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 = (
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
);
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";
};
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";
};
/* 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 = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* 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)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.machine.odf.odf;
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;
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.machine.odf.odf.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;
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.machine.odf.odf.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;
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.machine.odf.odf.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)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.machine.odf.odf;
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)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.machine.odf.odf;
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 */;
}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "331C8080294A63A400263BE5"
BuildableName = "RunnerTests.xctest"
BlueprintName = "RunnerTests"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

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

View File

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

View File

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

View File

@ -0,0 +1,13 @@
import UIKit
import Flutter
@UIApplicationMain
@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)
}
}

View File

@ -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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

View File

@ -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.

View File

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

View File

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

49
app/ios/Runner/Info.plist Normal file
View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Odf</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>odf</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>

View File

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

View File

@ -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.
}
}

View File

@ -0,0 +1,15 @@
import 'package:json_annotation/json_annotation.dart';
part 'company_bean.g.dart';
@JsonSerializable(explicitToJson: true)
class CompanyBean {
int? deptId;
String? deptName;
CompanyBean(this.deptId, this.deptName);
factory CompanyBean.fromJson(Map<String, dynamic> json) => _$CompanyBeanFromJson(json);
Map<String, dynamic> toJson() => _$CompanyBeanToJson(this);
}

View File

@ -0,0 +1,17 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:odf/bean/port_list_bean.dart';
part 'details_bean.g.dart';
@JsonSerializable(explicitToJson: true)
class DetailsBean {
int? id;
String? name;
List<PortListBean> odfPortsList;
DetailsBean(this.id, this.name, this.odfPortsList);
factory DetailsBean.fromJson(Map<String, dynamic> json) => _$DetailsBeanFromJson(json);
Map<String, dynamic> toJson() => _$DetailsBeanToJson(this);
}

View File

@ -0,0 +1,17 @@
import 'package:json_annotation/json_annotation.dart';
part 'device_list_bean.g.dart';
@JsonSerializable(explicitToJson: true)
class DeviceListBean {
int? dictCode;
int? dictSort;
String? dictLabel;
String? dictValue;
DeviceListBean(this.dictCode, this.dictSort, this.dictLabel, this.dictValue);
factory DeviceListBean.fromJson(Map<String, dynamic> json) => _$DeviceListBeanFromJson(json);
Map<String, dynamic> toJson() => _$DeviceListBeanToJson(this);
}

View File

@ -0,0 +1,15 @@
import 'package:json_annotation/json_annotation.dart';
part 'history_fault_bean.g.dart';
@JsonSerializable(explicitToJson: true)
class HistoryFaultBean {
String? faultTime;
String? faultReason;
HistoryFaultBean(this.faultTime, this.faultReason);
factory HistoryFaultBean.fromJson(Map<String, dynamic> json) => _$HistoryFaultBeanFromJson(json);
Map<String, dynamic> toJson() => _$HistoryFaultBeanToJson(this);
}

View File

@ -0,0 +1,16 @@
import 'package:json_annotation/json_annotation.dart';
part 'login_bean.g.dart';
@JsonSerializable(explicitToJson: true)
class LoginBean {
String? jwt;
int? userId;
String? userName;
LoginBean(this.jwt, this.userId, this.userName);
factory LoginBean.fromJson(Map<String, dynamic> json) => _$LoginBeanFromJson(json);
Map<String, dynamic> toJson() => _$LoginBeanToJson(this);
}

View File

@ -0,0 +1,19 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:odf/bean/search_bean.dart';
import 'new_search_room_bean.dart';
part 'new_search_bean.g.dart';
@JsonSerializable(explicitToJson: true)
class NewSearchBean {
List<NewSearchRoomBean> rooms;
SearchBean? ports;
NewSearchBean(this.rooms, this.ports);
factory NewSearchBean.fromJson(Map<String, dynamic> json) => _$NewSearchBeanFromJson(json);
Map<String, dynamic> toJson() => _$NewSearchBeanToJson(this);
}

View File

@ -0,0 +1,18 @@
import 'package:json_annotation/json_annotation.dart';
part 'new_search_room_bean.g.dart';
@JsonSerializable(explicitToJson: true)
class NewSearchRoomBean {
int? roomId;
String? roomName;
String? roomAddress;
String? remarks;
String? deptName;
NewSearchRoomBean(this.roomId,this.roomName, this.roomAddress, this.remarks, this.deptName);
factory NewSearchRoomBean.fromJson(Map<String, dynamic> json) => _$NewSearchRoomBeanFromJson(json);
Map<String, dynamic> toJson() => _$NewSearchRoomBeanToJson(this);
}

View File

@ -0,0 +1,62 @@
import 'package:json_annotation/json_annotation.dart';
import 'history_fault_bean.dart';
part 'odf_details_bean.g.dart';
@JsonSerializable(explicitToJson: true)
class OdfDetailsBean {
int? id;
String? name;
int? roomId;
String? roomName;
int? rackId;
String? rackName;
int? frameId;
String? frameName;
int? deptId;
int? rowNumber;
int? portNumber;
int? status;
String? remarks;
String? opticalAttenuation;
String? opticalCableOffRemarks;
String? historyRemarks;
List<HistoryFaultBean>? historyFault;
String? createdAt;
String? updatedAt;
String? statusLabel;
String? deptName;
String? equipmentModel;
String? businessType;
OdfDetailsBean(
this.id,
this.name,
this.roomId,
this.roomName,
this.rackId,
this.rackName,
this.frameId,
this.frameName,
this.deptId,
this.rowNumber,
this.portNumber,
this.status,
this.remarks,
this.opticalAttenuation,
this.opticalCableOffRemarks,
this.historyRemarks,
this.historyFault,
this.createdAt,
this.updatedAt,
this.statusLabel,
this.deptName,
this.equipmentModel,
this.businessType);
factory OdfDetailsBean.fromJson(Map<String, dynamic> json) => _$OdfDetailsBeanFromJson(json);
Map<String, dynamic> toJson() => _$OdfDetailsBeanToJson(this);
}

View File

@ -0,0 +1,16 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:odf/bean/row_list_bean.dart';
part 'port_list_bean.g.dart';
@JsonSerializable(explicitToJson: true)
class PortListBean {
String? name;
List<RowListBean> rowList;
PortListBean(this.name, this.rowList);
factory PortListBean.fromJson(Map<String, dynamic> json) => _$PortListBeanFromJson(json);
Map<String, dynamic> toJson() => _$PortListBeanToJson(this);
}

View File

@ -0,0 +1,20 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:odf/bean/racks_list_bean.dart';
part 'racks_bean.g.dart';
@JsonSerializable(explicitToJson: true)
class RacksBean {
int? pageSize;
int? pageIndex;
int? totalNum;
int? totalPage;
List<RacksListBean> result;
RacksBean(this.pageSize, this.pageIndex, this.totalNum, this.totalPage, this.result);
factory RacksBean.fromJson(Map<String, dynamic> json) => _$RacksBeanFromJson(json);
Map<String, dynamic> toJson() => _$RacksBeanToJson(this);
}

View File

@ -0,0 +1,20 @@
import 'package:json_annotation/json_annotation.dart';
part 'racks_list_bean.g.dart';
@JsonSerializable(explicitToJson: true)
class RacksListBean {
int? id;
int? roomId;
int? sequenceNumber;
String? rackName;
int? frameCount;
String? createdAt;
String? updatedAt;
RacksListBean(this.id, this.roomId, this.sequenceNumber, this.rackName, this.frameCount, this.createdAt, this.updatedAt);
factory RacksListBean.fromJson(Map<String, dynamic> json) => _$RacksListBeanFromJson(json);
Map<String, dynamic> toJson() => _$RacksListBeanToJson(this);
}

View File

@ -0,0 +1,22 @@
import 'package:json_annotation/json_annotation.dart';
part 'result_list_bean.g.dart';
@JsonSerializable(explicitToJson: true)
class ResultListBean {
int? id;
int? deptId;
String? deptName;
String? roomName;
String? roomAddress;
int? racksCount;
String? remarks;
String? createdAt;
String? updatedAt;
ResultListBean(this.id, this.deptId, this.deptName, this.roomName, this.roomAddress, this.racksCount, this.remarks, this.createdAt, this.updatedAt);
factory ResultListBean.fromJson(Map<String, dynamic> json) => _$ResultListBeanFromJson(json);
Map<String, dynamic> toJson() => _$ResultListBeanToJson(this);
}

View File

@ -0,0 +1,19 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:odf/bean/result_list_bean.dart';
part 'room_list_bean.g.dart';
@JsonSerializable(explicitToJson: true)
class RoomListBean {
int? pageSize;
int? pageIndex;
int? totalNum;
int? totalPage;
List<ResultListBean> result;
RoomListBean(this.pageSize, this.pageIndex, this.totalNum, this.totalPage, this.result);
factory RoomListBean.fromJson(Map<String, dynamic> json) => _$RoomListBeanFromJson(json);
Map<String, dynamic> toJson() => _$RoomListBeanToJson(this);
}

View File

@ -0,0 +1,17 @@
import 'package:json_annotation/json_annotation.dart';
part 'row_list_bean.g.dart';
@JsonSerializable(explicitToJson: true)
class RowListBean {
int? id;
String? name;
int? status;
String? tips;
RowListBean(this.id, this.name, this.status, this.tips);
factory RowListBean.fromJson(Map<String, dynamic> json) => _$RowListBeanFromJson(json);
Map<String, dynamic> toJson() => _$RowListBeanToJson(this);
}

View File

@ -0,0 +1,19 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:odf/bean/search_list_bean.dart';
part 'search_bean.g.dart';
@JsonSerializable(explicitToJson: true)
class SearchBean {
int? pageSize;
int? pageIndex;
int? totalNum;
int? totalPage;
List<SearchListBean>? result;
SearchBean(this.pageSize, this.pageIndex, this.totalNum, this.totalPage, this.result);
factory SearchBean.fromJson(Map<String, dynamic> json) => _$SearchBeanFromJson(json);
Map<String, dynamic> toJson() => _$SearchBeanToJson(this);
}

View File

@ -0,0 +1,30 @@
import 'package:json_annotation/json_annotation.dart';
part 'search_list_bean.g.dart';
@JsonSerializable(explicitToJson: true)
class SearchListBean {
int? id;
String? name;
int? roomId;
String? roomName;
int? rackId;
String? rackName;
int? frameId;
String? frameName;
int? rowNumber;
int? portNumber;
int? status;
String? remarks;
String? opticalAttenuation;
String? opticalCableOffRemarks;
String? historyRemarks;
String? address;
SearchListBean(this.id, this.name, this.roomId, this.roomName, this.rackId, this.rackName, this.frameId, this.frameName, this.rowNumber,
this.portNumber, this.status, this.remarks, this.opticalAttenuation,this.opticalCableOffRemarks, this.historyRemarks, this.address);
factory SearchListBean.fromJson(Map<String, dynamic> json) => _$SearchListBeanFromJson(json);
Map<String, dynamic> toJson() => _$SearchListBeanToJson(this);
}

View File

@ -0,0 +1,18 @@
import 'package:json_annotation/json_annotation.dart';
part 'update_bean.g.dart';
@JsonSerializable(explicitToJson: true)
class UpdateBean {
bool? needUpdate;
bool? forceUpdate;
String? latestVersion;
String? downloadUrl;
String? updateDescription;
UpdateBean(this.needUpdate, this.forceUpdate, this.latestVersion, this.downloadUrl, this.updateDescription);
factory UpdateBean.fromJson(Map<String, dynamic> json) => _$UpdateBeanFromJson(json);
Map<String, dynamic> toJson() => _$UpdateBeanToJson(this);
}

View File

@ -0,0 +1,52 @@
import 'package:flutter/services.dart';
import '../network/NetworkConfig.dart';
const int Environment_Dev = 1;
const int Environment_Pre = 2;
const int Environment_Online = 3;
class Global {
factory Global() => _getInstance();
static Global get instance => _getInstance();
static Global? _instance;
Global._internal() {
//
}
static Global _getInstance() {
_instance ??= Global._internal();
return _instance!;
}
static const method = MethodChannel('samples.flutter.dev/battery');
static bool get isRelease => bool.fromEnvironment("dart.vm.product");
static String? flatform_name;
static Future initialize() async {
if (!NetworkConfig.isTest) {
// NetworkConfig.BASE_URLS = NetworkConfig.BASE_URLS_TEST;
}
// if (Platform.isIOS) {
// //ios相关代码
// flatform_name = 'iOS';
// } else if (Platform.isAndroid) {
// //android相关代码
// flatform_name = 'Android';
// } else if (Platform.isWindows) {
// //android相关代码
// flatform_name = 'Windows';
// }
// WidgetsFlutterBinding.ensureInitialized(); ///
// SystemChrome.setPreferredOrientations([
// //
// DeviceOrientation.portraitUp,
// DeviceOrientation.portraitDown
// ]);
// Global a = Global.instance;
}
}

70
app/lib/common/func.dart Normal file
View File

@ -0,0 +1,70 @@
import 'package:flutter/material.dart';
class FunctionUtil {
static BuildContext? dialogContext;
//
static void popDialog(BuildContext context, Widget widget) {
showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
dialogContext = context;
return widget;
});
}
//
static void popDialog2(BuildContext context, Widget widget) {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
dialogContext = context;
return WillPopScope(onWillPop: () async => false, child: widget);
});
}
//
static void bottomSheetDialog(BuildContext context, Widget widget) {
showModalBottomSheet(
backgroundColor: const Color(0x00FFFFFF),
context: context,
/* isDismissible: false,*/
isScrollControlled: true,
builder: (BuildContext context) {
dialogContext = context;
return widget;
},
);
}
//
static void bottomNoSheetDialog(BuildContext context, Widget widget) {
showModalBottomSheet(
backgroundColor: Color(0x00FFFFFF),
context: context,
isDismissible: false,
isScrollControlled: true,
enableDrag: false,
builder: (BuildContext context) {
dialogContext = context;
return WillPopScope(onWillPop: () async => false, child: widget);
});
}
//
static void pop() {
Navigator.pop(dialogContext!);
}
//push到下一级
static Future push(BuildContext context, Widget widget) {
return Navigator.push(
context,
MaterialPageRoute(
builder: (context) => widget,
),
);
}
}

View File

@ -0,0 +1,347 @@
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import '../network/NetworkConfig.dart';
class AddNoteDialog extends StatefulWidget {
final Function onTap;
const AddNoteDialog({
super.key,
required this.onTap,
});
@override
State<AddNoteDialog> createState() => _AddNoteDialogState();
}
class _AddNoteDialogState extends State<AddNoteDialog> {
final TextEditingController _businessNameController = TextEditingController();
final TextEditingController _portNumber1Controller = TextEditingController();
final TextEditingController _portNumber2Controller = TextEditingController();
final TextEditingController _portNumber3Controller = TextEditingController();
// final List<String> items2 = ['电视', '光缆', '大会员', '电信', '联通'];
String selectedValue = "";
String selectedValue2 = "";
@override
void initState() {
// TODO: implement initState
super.initState();
selectedValue = NetworkConfig.diverItems.first;
selectedValue2 = NetworkConfig.businessItems.first;
}
@override
void dispose() {
// TODO: implement dispose
_businessNameController.dispose();
_portNumber1Controller.dispose();
_portNumber2Controller.dispose();
_portNumber3Controller.dispose();
super.dispose();
}
submitInfo() {
if (_businessNameController.text == "") {
EasyLoading.showToast("请输入业务名称");
return;
}
if (_portNumber1Controller.text == "" || _portNumber2Controller.text == "" || _portNumber3Controller.text == "") {
EasyLoading.showToast("请输入端口号");
return;
}
widget.onTap(_businessNameController.text, selectedValue, selectedValue2,
"${_portNumber1Controller.text}/${_portNumber2Controller.text}/${_portNumber3Controller.text}");
Navigator.pop(context);
}
@override
Widget build(BuildContext context) {
final bottomInset = MediaQuery.of(context).viewInsets.bottom;
return Material(
type: MaterialType.transparency, //
color: const Color(0x1A000000),
child: Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Container(
width: 307,
color: Colors.white,
padding: EdgeInsets.only(left: 5, right: 5, top: 5, bottom: bottomInset),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
child: Text(
"添加备注",
style: TextStyle(fontWeight: FontWeight.w600),
),
),
///
Container(
alignment: Alignment.centerLeft,
margin: EdgeInsets.all(10),
child: Text(
"业务名称",
style: TextStyle(fontSize: 12),
),
),
Container(
margin: EdgeInsets.only(left: 10, right: 10),
padding: EdgeInsets.symmetric(horizontal: 5),
height: 35,
alignment: Alignment.center,
decoration: BoxDecoration(color: Color(0xFFEBEBEB), borderRadius: BorderRadius.all(Radius.circular(7))),
child: TextField(
cursorColor: Color(0xFF1A73EC),
controller: _businessNameController,
decoration: InputDecoration(
isDense: true,
contentPadding: EdgeInsets.zero,
hintText: '请输入业务名称',
border: InputBorder.none,
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
hintStyle: TextStyle(color: Color(0xFF999999), fontSize: 12),
),
style: TextStyle(fontSize: 12),
),
),
///
Container(
alignment: Alignment.centerLeft,
margin: EdgeInsets.all(10),
child: Text(
"设备型号",
style: TextStyle(fontSize: 12),
),
),
Container(
margin: EdgeInsets.only(left: 10, right: 10),
padding: EdgeInsets.symmetric(horizontal: 5),
height: 35,
alignment: Alignment.center,
decoration: BoxDecoration(color: Color(0xFFEBEBEB), borderRadius: BorderRadius.all(Radius.circular(7))),
child: DropdownButton<String>(
value: selectedValue,
//
icon: const Icon(Icons.arrow_drop_down, color: Colors.blue),
hint: const Text('请选择设备型号'),
underline: Container(),
isExpanded: true,
dropdownColor: const Color(0xFFEBEBEB),
onChanged: (String? newValue) {
//
setState(() {
selectedValue = newValue!;
});
},
items: NetworkConfig.diverItems.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w400),
),
);
}).toList(),
),
),
///
Container(
alignment: Alignment.centerLeft,
margin: EdgeInsets.all(10),
child: Text(
"业务类型",
style: TextStyle(fontSize: 12),
),
),
Container(
margin: EdgeInsets.only(left: 10, right: 10),
padding: EdgeInsets.symmetric(horizontal: 5),
height: 35,
alignment: Alignment.center,
decoration: BoxDecoration(color: Color(0xFFEBEBEB), borderRadius: BorderRadius.all(Radius.circular(7))),
child: DropdownButton<String>(
value: selectedValue2,
//
icon: const Icon(Icons.arrow_drop_down, color: Colors.blue),
hint: const Text('请选择业务类型'),
underline: Container(),
isExpanded: true,
dropdownColor: const Color(0xFFEBEBEB),
onChanged: (String? newValue) {
//
setState(() {
selectedValue2 = newValue!;
});
},
items: NetworkConfig.businessItems.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w400),
),
);
}).toList(),
),
),
///
Container(
alignment: Alignment.centerLeft,
margin: EdgeInsets.all(10),
child: Text(
"端口号数",
style: TextStyle(fontSize: 12),
),
),
Row(
children: [
Expanded(
flex: 1,
child: Container(
margin: EdgeInsets.only(left: 10, right: 10),
padding: EdgeInsets.symmetric(horizontal: 5),
height: 35,
alignment: Alignment.center,
decoration: BoxDecoration(color: Color(0xFFEBEBEB), borderRadius: BorderRadius.all(Radius.circular(5))),
child: TextField(
cursorColor: Color(0xFF1A73EC),
controller: _portNumber1Controller,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
isDense: true,
contentPadding: EdgeInsets.zero,
hintText: '1号端口数',
border: InputBorder.none,
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
hintStyle: TextStyle(color: Color(0xFF999999), fontSize: 12),
),
style: TextStyle(fontSize: 12),
),
),
),
Expanded(
flex: 1,
child: Container(
margin: const EdgeInsets.only(left: 10, right: 10),
padding: const EdgeInsets.symmetric(horizontal: 5),
height: 35,
alignment: Alignment.center,
decoration: const BoxDecoration(color: Color(0xFFEBEBEB), borderRadius: BorderRadius.all(Radius.circular(5))),
child: TextField(
cursorColor: const Color(0xFF1A73EC),
controller: _portNumber2Controller,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
isDense: true,
contentPadding: EdgeInsets.zero,
hintText: '2号端口数',
border: InputBorder.none,
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
hintStyle: TextStyle(color: Color(0xFF999999), fontSize: 12),
),
style: TextStyle(fontSize: 12),
),
),
),
Expanded(
flex: 1,
child: Container(
margin: const EdgeInsets.only(left: 10, right: 10),
padding: const EdgeInsets.symmetric(horizontal: 5),
height: 35,
alignment: Alignment.center,
decoration: const BoxDecoration(color: Color(0xFFEBEBEB), borderRadius: BorderRadius.all(Radius.circular(5))),
child: TextField(
cursorColor: const Color(0xFF1A73EC),
controller: _portNumber3Controller,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
isDense: true,
contentPadding: EdgeInsets.zero,
hintText: '3号端口数',
border: InputBorder.none,
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
hintStyle: TextStyle(color: Color(0xFF999999), fontSize: 12),
),
style: TextStyle(fontSize: 12),
),
),
),
],
),
Container(
margin: EdgeInsets.symmetric(vertical: 10),
child: Row(
children: [
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Container(
height: 32,
alignment: Alignment.center,
margin: EdgeInsets.symmetric(horizontal: 10, vertical: 10),
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.all(Radius.circular(6)),
),
child: Text(
"取消",
style: TextStyle(fontSize: 14, color: Colors.white),
),
),
),
),
Expanded(
flex: 2,
child: GestureDetector(
onTap: () {
submitInfo();
},
child: Container(
height: 32,
alignment: Alignment.center,
margin: EdgeInsets.symmetric(horizontal: 10, vertical: 10),
decoration: BoxDecoration(
color: Color(0xFF1A73EC),
borderRadius: BorderRadius.all(Radius.circular(6)),
),
child: Text(
"提交",
style: TextStyle(fontSize: 14, color: Colors.white),
),
),
),
),
],
),
),
],
),
),
),
),
);
}
}

View File

@ -0,0 +1,669 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_cupertino_datetime_picker/flutter_cupertino_datetime_picker.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:odf/bean/odf_details_bean.dart';
import 'package:odf/network/NetworkConfig.dart';
import 'package:odf/tools/machine/machine_model.dart';
import '../bean/history_fault_bean.dart';
import '../common/func.dart';
import 'add_note_dialog.dart';
class ModifyInfoDialog extends StatefulWidget {
final Function onTap;
final String id;
const ModifyInfoDialog({super.key, required this.onTap, required this.id});
@override
State<ModifyInfoDialog> createState() => _ModifyInfoDialogState();
}
class DataItem {
String time;
String content;
DataItem({required this.time, required this.content});
}
class _ModifyInfoDialogState extends State<ModifyInfoDialog> {
late StreamSubscription subscription;
final MachineModel _viewmodel = MachineModel();
late OdfDetailsBean odfDetailsBean;
final TextEditingController _remarksController = TextEditingController();
final TextEditingController _opticalAttenuationController = TextEditingController();
final TextEditingController _historyRemarksController = TextEditingController();
final TextEditingController _opticalCableOffRemarksController = TextEditingController();
bool isConnect = false;
bool isLoad = false;
//
late List<TextEditingController> _controllers;
final List<HistoryFaultBean> _items = [];
///
void _addItem() {
setState(() {
_items.add(HistoryFaultBean("", ""));
_controllers.add(TextEditingController(text: ""));
});
}
///
void _removeItem(int index) {
setState(() {
_items.removeAt(index);
_controllers.removeAt(index);
});
}
///
void appendTextWithNewline(String newContent) {
//
String currentText = _remarksController.text;
//
String updatedText = currentText.isEmpty ? newContent : '$currentText\n$newContent';
_remarksController.text = updatedText;
//
_remarksController.selection = TextSelection.fromPosition(TextPosition(offset: _remarksController.text.length));
}
@override
void initState() {
// TODO: implement initState
super.initState();
subscription = _viewmodel.streamController.stream.listen((event) {
String code = event['code'];
if (code.isNotEmpty) {
switch (code) {
case "odfDetails":
isLoad = true;
odfDetailsBean = event['data'];
_remarksController.text = '${odfDetailsBean.remarks}';
_opticalAttenuationController.text = '${odfDetailsBean.opticalAttenuation}';
_historyRemarksController.text = '${odfDetailsBean.historyRemarks}';
_opticalCableOffRemarksController.text = '${odfDetailsBean.opticalCableOffRemarks}';
if (odfDetailsBean.status == 0) {
isConnect = false;
} else {
isConnect = true;
}
if (odfDetailsBean.historyFault!.isNotEmpty) {
for (var data in odfDetailsBean.historyFault!) {
_items.add(data);
}
}
_controllers = List.generate(
_items.length,
//
(index) => TextEditingController(text: odfDetailsBean.historyFault![index].faultReason),
);
break;
case "save": //
EasyLoading.dismiss();
widget.onTap();
Navigator.pop(context);
break;
}
}
EasyLoading.dismiss();
setState(() {});
});
EasyLoading.show(status: "loading...");
_viewmodel.odfDetails(widget.id);
}
@override
void dispose() {
// TODO: implement dispose
subscription.cancel();
_remarksController.dispose();
_opticalAttenuationController.dispose();
_historyRemarksController.dispose();
_opticalCableOffRemarksController.dispose();
for (var controller in _controllers) {
controller.dispose();
}
super.dispose();
}
///
Future<void> saveData() async {
///.
for (int i = 0; i < _controllers.length; i++) {
// print('输入框的值: ${_controllers[i].text}');
_items[i].faultReason = _controllers[i].text;
}
if (_items.isNotEmpty) {
bool allFaultTimeEmpty = _items.every((bean) {
// faultTime是否不为null且不是空字符串
return bean.faultTime != null && bean.faultTime!.trim().isNotEmpty;
});
if (!allFaultTimeEmpty) {
EasyLoading.showToast("请选择障碍发生时间!");
return;
}
}
EasyLoading.show(status: "loading...");
_viewmodel.save(widget.id, isConnect ? 1 : 0, _remarksController.text, _opticalAttenuationController.text, _historyRemarksController.text, _items,
_opticalCableOffRemarksController.text);
}
@override
Widget build(BuildContext context) {
final bottomInset = MediaQuery.of(context).viewInsets.bottom;
return Material(
type: MaterialType.transparency, //
color: const Color(0x1A000000),
child: Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Container(
width: 307,
color: Colors.white,
padding: EdgeInsets.only(left: 5, right: 5, top: 5, bottom: bottomInset),
child: isLoad
? Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
child: Row(
// crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"位置:${odfDetailsBean.frameName}${odfDetailsBean.name}",
style: const TextStyle(fontSize: 12),
),
GestureDetector(
onTap: () {
if (NetworkConfig.isPermission) {
FunctionUtil.popDialog2(
context,
AddNoteDialog(
onTap: (value1, value2, value3, value4) {
// print("$value1-$value2-$value3-$value4");
// appendTextWithNewline("$value1 $value2 $value3 $value4");
_remarksController.text = "$value1 $value2 $value3 $value4";
setState(() {});
},
),
);
}
},
child: Container(
alignment: Alignment.center,
margin: const EdgeInsets.only(left: 10),
width: 60,
height: 20,
decoration: const BoxDecoration(
color: Colors.lightBlue,
borderRadius: BorderRadius.all(Radius.circular(5)),
),
child: const Text(
"添加备注",
style: TextStyle(fontSize: 11, color: Colors.white),
),
),
),
],
),
Row(
children: [
const Text(
"当前状态:",
style: TextStyle(fontSize: 12),
),
Container(
width: 12,
height: 12,
margin: const EdgeInsets.only(left: 10, right: 5),
decoration: BoxDecoration(
color: odfDetailsBean.status == 0 ? Colors.red : Colors.green,
shape: BoxShape.circle,
),
),
Text(
odfDetailsBean.status == 0 ? "已断开" : "已连接",
style: const TextStyle(fontSize: 12),
)
],
),
],
),
),
Container(
width: double.infinity,
margin: const EdgeInsets.only(left: 10, right: 10),
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
decoration: const BoxDecoration(color: Color(0xFFEBEBEB), borderRadius: BorderRadius.all(Radius.circular(7))),
child: TextField(
maxLines: 5,
cursorColor: const Color(0xFF1A73EC),
controller: _remarksController,
enabled: NetworkConfig.isPermission,
decoration: const InputDecoration(
contentPadding: EdgeInsets.zero,
hintText: '请输入备注说明',
border: InputBorder.none,
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
hintStyle: TextStyle(color: Color(0xFF999999), fontSize: 12),
),
style: const TextStyle(fontSize: 12),
),
),
Container(
alignment: Alignment.centerLeft,
margin: const EdgeInsets.all(10),
child: const Text(
"光衰信息",
style: TextStyle(fontSize: 12),
),
),
Container(
margin: const EdgeInsets.only(left: 10, right: 10),
padding: const EdgeInsets.symmetric(horizontal: 5),
alignment: Alignment.center,
height: 35,
decoration: const BoxDecoration(color: Color(0xFFEBEBEB), borderRadius: BorderRadius.all(Radius.circular(7))),
child: TextField(
cursorColor: const Color(0xFF1A73EC),
controller: _opticalAttenuationController,
enabled: NetworkConfig.isPermission,
decoration: const InputDecoration(
isDense: true,
contentPadding: EdgeInsets.zero,
hintText: '请输入光衰信息',
border: InputBorder.none,
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
hintStyle: TextStyle(color: Color(0xFF999999), fontSize: 12),
),
style: const TextStyle(fontSize: 12),
),
),
Container(
alignment: Alignment.centerLeft,
margin: const EdgeInsets.all(10),
child: const Text(
"历史障碍发生原因及时间",
style: TextStyle(fontSize: 12),
),
),
ListView.builder(
shrinkWrap: true,
itemCount: _items.length,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return _item(index, context, _items[index]);
}),
GestureDetector(
onTap: () {
if (NetworkConfig.isPermission) {
_addItem();
}
},
child: const Text(
"添加新记录",
style: TextStyle(fontSize: 12, color: Colors.lightBlue),
),
),
// Container(
// margin: EdgeInsets.only(left: 10, right: 10),
// padding: EdgeInsets.symmetric(horizontal: 5, vertical: 5),
// decoration: BoxDecoration(color: Color(0xFFEBEBEB), borderRadius: BorderRadius.all(Radius.circular(10))),
// child: TextField(
// maxLines: 3,
// cursorColor: Color(0xFF1A73EC),
// controller: _historyRemarksController,
// enabled: NetworkConfig.isPermission,
// decoration: InputDecoration(
// contentPadding: EdgeInsets.zero,
// hintText: '请输入历史障碍发生原因及时间',
// border: InputBorder.none,
// enabledBorder: InputBorder.none,
// focusedBorder: InputBorder.none,
// hintStyle: TextStyle(color: Color(0xFF999999), fontSize: 12),
// ),
// style: TextStyle(fontSize: 12),
// ),
// ),
Container(
alignment: Alignment.centerLeft,
margin: const EdgeInsets.all(10),
child: const Text(
"光缆段信息",
style: TextStyle(fontSize: 12),
),
),
Container(
margin: const EdgeInsets.only(left: 10, right: 10),
padding: const EdgeInsets.symmetric(horizontal: 5),
height: 35,
alignment: Alignment.center,
decoration: const BoxDecoration(color: Color(0xFFEBEBEB), borderRadius: BorderRadius.all(Radius.circular(10))),
child: TextField(
maxLines: 1,
cursorColor: const Color(0xFF1A73EC),
controller: _opticalCableOffRemarksController,
enabled: NetworkConfig.isPermission,
decoration: const InputDecoration(
isDense: true,
contentPadding: EdgeInsets.zero,
hintText: '请输入光缆段信息',
border: InputBorder.none,
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
hintStyle: TextStyle(color: Color(0xFF999999), fontSize: 12),
),
style: const TextStyle(fontSize: 12),
),
),
NetworkConfig.isPermission
? Container(
alignment: Alignment.centerLeft,
margin: const EdgeInsets.all(10),
child: const Text(
"改变状态",
style: TextStyle(fontSize: 12),
),
)
: Container(),
NetworkConfig.isPermission
? Container(
margin: const EdgeInsets.symmetric(horizontal: 10),
child: Row(
children: [
Expanded(
child: GestureDetector(
onTap: () {
isConnect = true;
setState(() {});
},
child: Container(
height: 40,
margin: const EdgeInsets.only(right: 5),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(7)),
color: isConnect ? const Color(0xFF13ED13) : const Color(0xFFEBEBEB),
),
child: Text(
"连接",
style: TextStyle(fontSize: 12, color: isConnect ? Colors.white : Colors.black),
),
),
)),
Expanded(
child: GestureDetector(
onTap: () {
isConnect = false;
setState(() {});
},
child: Container(
height: 40,
margin: const EdgeInsets.only(left: 5),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(7)),
color: !isConnect ? const Color(0xFFFF0000) : const Color(0xFFEBEBEB),
),
child: Text(
"断开",
style: TextStyle(fontSize: 12, color: !isConnect ? Colors.white : Colors.black),
),
),
))
],
),
)
: Container(),
NetworkConfig.isPermission
? Container(
margin: const EdgeInsets.symmetric(vertical: 5),
child: const Text(
"断开后只清空备注说明,其他内容不影响",
style: TextStyle(fontSize: 10, color: Color(0xFF999999)),
),
)
: Container(),
NetworkConfig.isPermission
? Row(
children: [
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Container(
height: 32,
alignment: Alignment.center,
margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
decoration: const BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.all(Radius.circular(6)),
),
child: const Text(
"取消",
style: TextStyle(fontSize: 14, color: Colors.white),
),
),
),
),
Expanded(
flex: 2,
child: GestureDetector(
onTap: () {
saveData();
},
child: Container(
height: 32,
alignment: Alignment.center,
margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
decoration: const BoxDecoration(
color: Color(0xFF1A73EC),
borderRadius: BorderRadius.all(Radius.circular(6)),
),
child: const Text(
"提交",
style: TextStyle(fontSize: 14, color: Colors.white),
),
),
),
),
],
)
: Container(),
!NetworkConfig.isPermission
? GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Container(
height: 32,
alignment: Alignment.center,
margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
decoration: const BoxDecoration(
color: Color(0xFF1A73EC),
borderRadius: BorderRadius.all(Radius.circular(6)),
),
child: const Text(
"关闭",
style: TextStyle(fontSize: 14, color: Colors.white),
),
),
)
: Container(),
],
)
: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Container(
height: 32,
alignment: Alignment.center,
margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
decoration: const BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.all(Radius.circular(6)),
),
child: const Text(
"取消",
style: TextStyle(fontSize: 14, color: Colors.white),
),
),
),
),
),
),
),
);
}
_item(index, context, dataItem) {
return Container(
margin: const EdgeInsets.only(left: 10, right: 10, bottom: 10),
child: Column(
children: [
SizedBox(
height: 35,
child: Row(
children: [
Expanded(
flex: 5,
child: GestureDetector(
onTap: () {
if (!NetworkConfig.isPermission) {
return;
}
DatePicker.showDatePicker(
context,
minDateTime: DateTime(1980),
maxDateTime: DateTime(2080),
initialDateTime: DateTime.now(),
dateFormat: "yyyy-MM-dd HH:mm:ss",
pickerTheme: const DateTimePickerTheme(
backgroundColor: Colors.white,
cancelTextStyle: TextStyle(
color: Colors.grey,
fontSize: 16,
),
confirmTextStyle: TextStyle(
color: Colors.lightBlueAccent,
fontSize: 16,
),
pickerHeight: 220,
),
// timeFormat: "HH:mm",
locale: DateTimePickerLocale.zh_cn,
onConfirm: (dateTime, List<int> data) {
setState(() {
_items[index].faultTime =
"${dateTime.year}-${dateTime.month.toString().padLeft(2, '0')}-${dateTime.day.toString().padLeft(2, '0')} "
"${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}:${dateTime.second.toString().padLeft(2, '0')}";
});
},
);
},
child: Container(
height: 35,
padding: const EdgeInsets.symmetric(horizontal: 10),
decoration: const BoxDecoration(color: Color(0xFFEBEBEB), borderRadius: BorderRadius.all(Radius.circular(5))),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"时间:${dataItem.faultTime}",
style: const TextStyle(fontSize: 12),
),
const Icon(
Icons.arrow_drop_down,
color: Colors.blue,
size: 20,
),
],
),
),
),
),
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
if (NetworkConfig.isPermission) {
_removeItem(index);
}
},
child: Container(
height: 30,
decoration: BoxDecoration(
border: Border.all(color: Colors.red, width: 1, style: BorderStyle.solid),
borderRadius: const BorderRadius.all(Radius.circular(5))),
margin: const EdgeInsets.only(left: 10),
alignment: Alignment.center,
child: const Text(
"-",
style: TextStyle(
fontSize: 25,
color: Colors.red,
),
),
),
))
],
),
),
Container(
margin: const EdgeInsets.only(top: 10),
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
decoration: const BoxDecoration(color: Color(0xFFEBEBEB), borderRadius: BorderRadius.all(Radius.circular(10))),
child: TextField(
maxLines: 3,
cursorColor: const Color(0xFF1A73EC),
controller: _controllers[index],
enabled: NetworkConfig.isPermission,
decoration: const InputDecoration(
contentPadding: EdgeInsets.zero,
hintText: '请输入历史障碍发生原因及时间',
border: InputBorder.none,
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
hintStyle: TextStyle(color: Color(0xFF999999), fontSize: 12),
),
style: const TextStyle(fontSize: 12),
),
),
],
),
);
}
}

View File

@ -0,0 +1,81 @@
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
class UpdateDialog extends StatefulWidget {
final String downloadUrl;
const UpdateDialog({super.key, required this.downloadUrl});
@override
State<UpdateDialog> createState() => _UpdateDialogState();
}
//
Future<void> launchExternalBrowser(String url) async {
// URL
if (await canLaunchUrl(Uri.parse(url))) {
// URL使
await launchUrl(
Uri.parse(url),
mode: LaunchMode.externalApplication, // 使
);
} else {
// URL
throw '无法打开 $url';
}
}
class _UpdateDialogState extends State<UpdateDialog> {
@override
Widget build(BuildContext context) {
return Material(
type: MaterialType.transparency,
color: const Color(0x1A000000),
child: Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Container(
width: 307,
color: Colors.white,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
margin: EdgeInsets.only(top: 20),
child: Image(
width: 80,
height: 80,
image: AssetImage('assets/images/ic_update.png'),
),
),
Container(
margin: EdgeInsets.only(top: 20),
child: Text(
"有新版本请更新",
style: TextStyle(fontSize: 20),
),
),
GestureDetector(
onTap: () {
launchExternalBrowser(widget.downloadUrl);
},
child: Container(
width: 160,
height: 50,
alignment: Alignment.center,
margin: EdgeInsets.symmetric(vertical: 20),
decoration: BoxDecoration(color: Colors.lightBlue, borderRadius: BorderRadius.all(Radius.circular(15))),
child: Text(
"去更新",
style: TextStyle(fontSize: 22, color: Colors.white),
),
),
)
],
),
),
),
),
);
}
}

70
app/lib/main.dart Normal file
View File

@ -0,0 +1,70 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:odf/tools/home/home_page.dart';
import 'package:odf/tools/login/login_page.dart';
import 'package:odf/tools/search/search_page.dart';
import 'package:odf/tools/set/change_password_page.dart';
import 'package:odf/tools/set/set_page.dart';
import 'package:odf/tools/start_page.dart';
import 'common/Global.dart';
void main() async {
await runZonedGuarded(() async {
WidgetsFlutterBinding.ensureInitialized();
Global.initialize().then((e) {
Global();
runApp(const MyApp());
if (Platform.isAndroid) {
// android状态栏为透明的沉浸set赋值MaterialApp组件会覆盖掉这个值
SystemUiOverlayStyle systemUiOverlayStyle = const SystemUiOverlayStyle(statusBarColor: Colors.transparent);
SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
}
});
}, (error, stackTrace) {
print("error==$error");
});
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
// TODO: implement initState
super.initState();
//
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '绥时录',
home: const StartPage(),
//
routes: <String, WidgetBuilder>{
'/LoginPage': (BuildContext context) => const LoginPage(),
'/HomePage': (BuildContext context) => const HomePage(),
'/SearchPage': (BuildContext context) => const SearchPage(),
'/SetPage': (BuildContext context) => const SetPage(),
'/ChangePasswordPage': (BuildContext context) => const ChangePasswordPage(),
},
//
debugShowMaterialGrid: false,
//debug
debugShowCheckedModeBanner: false,
//
builder: EasyLoading.init(),
);
}
}

View File

@ -0,0 +1,42 @@
class BaseEntity {
int? code;
int? result;
String? msg;
dynamic data;
//
BaseEntity({this.code, this.result, this.msg, this.data});
//
factory BaseEntity.fromJson(json) {
dynamic data = json["content"][0]["text"];
return BaseEntity(code: 0,data: data);
}
//
factory BaseEntity.PlayfromComfyUi(json) {
Map<String, dynamic> responseData = json;
String message = responseData["type"]; //
dynamic data = responseData["name"];
return BaseEntity(code: 0, result: 0, msg: message, data: data);
}
//
factory BaseEntity.PlayfromJson(json) {
Map<String, dynamic> responseData = json;
int code = responseData["code"];
// int result = responseData["Result"];
String message = responseData["msg"]; //
dynamic data = responseData["data"];
return BaseEntity(code: code, result: 0, msg: message, data: data);
}
}
class ErrorEntity {
int? code;
String? msg;
ErrorEntity({this.code, this.msg});
}

View File

@ -0,0 +1,134 @@
import 'package:dio/dio.dart';
///
class DioLogInterceptor extends Interceptor {
///
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
String requestStr = "\n 请求 - URL:${/*options.baseUrl + */ options.uri}" + " 时间 - :${DateTime.now().millisecondsSinceEpoch}\n";
//requestStr += "- HEADER:\n${options.headers.mapToStructureString()}\n";
final data = options.data;
if (data != null) {
if (data is Map)
requestStr += "- BODY:\n${data.mapToStructureString()}\n";
else if (data is FormData) {
final formDataMap = Map()
..addEntries(data.fields)
..addEntries(data.files);
requestStr += "- BODY:\n${formDataMap.mapToStructureString()}\n";
} else
requestStr += "- BODY:\n${data.toString()}\n";
}
print(requestStr);
handler.next(options);
}
///
@override
void onError(DioError err, ErrorInterceptorHandler handler) {
String errorStr = "\n==================== 响应 ====================\n"
"- URL:\n${err.requestOptions.path}\n"
"- METHOD: ${err.requestOptions.method}\n";
/* errorStr +=
"- HEADER:\n${err.response.headers.map.mapToStructureString()}\n";*/
if (err.response != null && err.response!.data != null) {
print('${err.type.toString()}');
errorStr += "- ERROR:\n${_parseResponse(err.response!)}\n";
} else {
errorStr += "- ERRORTYPE: ${err.type}\n";
errorStr += "- MSG: ${err.message}\n";
}
print(errorStr);
handler.next(err);
}
///
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
String responseStr = "\n 响应 - URL:${response.requestOptions.uri}" + " 时间 - :${DateTime.now().millisecondsSinceEpoch}\n";
/* responseStr += "- HEADER:\n{";
response.headers.forEach(
(key, list) => responseStr += "\n " + "\"$key\" : \"$list\",");
responseStr += "\n}\n";*/
//responseStr += "- STATUS: ${response.statusCode}\n";
if (response.data != null) {
responseStr += "- BODY:\n ${_parseResponse(response)}";
}
printWrapped(responseStr);
handler.next(response);
}
void printWrapped(String text) {
final pattern = new RegExp('.{1,800}'); // 800 is the size of each chunk
pattern.allMatches(text).forEach((match) => print(match.group(0)));
}
String _parseResponse(Response response) {
String responseStr = "";
var data = response.data;
if (data is Map)
responseStr += data.mapToStructureString();
else if (data is List)
responseStr += data.listToStructureString();
else
responseStr += response.data.toString();
return responseStr;
}
}
///Map拓展MAp转字符串输出
extension Map2StringEx on Map {
String mapToStructureString({int indentation = 2}) {
String result = "";
String indentationStr = " " * indentation;
if (true) {
result += " {";
this.forEach((key, value) {
if (value is Map) {
var temp = value.mapToStructureString(indentation: indentation + 2);
result += "$indentationStr" + "\"$key\":$temp,";
} else if (value is List) {
result += "$indentationStr" + "\"$key\":${value.listToStructureString(indentation: indentation + 2)},";
} else {
result += "$indentationStr" + "\"$key\":\"$value\",";
}
});
result = result.substring(0, result.length - 1);
result += indentation == 2 ? "}" : "\n${" " * (indentation - 1)}}";
}
return result;
}
}
///List拓展List转字符串输出
extension List2StringEx on List {
String listToStructureString({int indentation = 2}) {
String result = "";
String indentationStr = " " * indentation;
if (true) {
result += "$indentationStr[";
this.forEach((value) {
if (value is Map) {
var temp = value.mapToStructureString(indentation: indentation + 2);
result += "\n$indentationStr" + "\"$temp\",";
} else if (value is List) {
result += value.listToStructureString(indentation: indentation + 2);
} else {
result += "\n$indentationStr" + "\"$value\",";
}
});
result = result.substring(0, result.length - 1);
result += "\n$indentationStr]";
}
return result;
}
}

View File

@ -0,0 +1,62 @@
class NetworkConfig {
static String ServerDomain_Online = BASE_URLS[SELECT_INDEX];
static String deviceID = ""; //ID
static String systemVersion = ""; //ID
///
static int SELECT_INDEX = 0;
static List BASE_URLS = [
"http://49.233.115.141:11082",
"http://49.233.115.141:11082",
];
static List BASE_URLS_TEST = [
"https://odf.zpc-xy.com",
];
static bool isTest = true;
static String token = "";
static String userToken = ""; //
static String AppId = "1";
static String BossId = "";
static String userId = "";
static String userName = "";
static String Version = "1.0.0";
static String Language = "en";
static bool isPermission = false; //
static List<String> diverItems = [];
static List<String> businessItems = [];
static const String appLogin = "/appLogin"; //
static const String odf = "/business/OdfPorts/odf"; //
static const String roomList = "/business/OdfRooms/list"; //
static const String racksList = "/business/OdfRacks/list"; //
static const String mList = "/business/OdfPorts/mlist"; //
static const String odfDetails = "/business/OdfPorts/"; //
static const String save = "/business/OdfPorts/save"; //
static const String search = "/business/OdfPorts/search"; //
static const String updateUserPwd = "/system/user/profile/updateUserPwd"; //
static const String newSearch = "/business/OdfPorts/search2"; //
static const String getCompany = "/business/OdfRooms/getcompany"; //
static const String getRegion = "/business/OdfRooms/getregion"; //
static const String odfPortsUnitType = "/system/dict/data/type/odf_ports_unit_type"; //
static const String odfPortsBusinessType = "/system/dict/data/type/odf_ports_business_type"; //
static const String checkAppVersion = "/webapi/CheckAppVersion"; //
}

View File

@ -0,0 +1,398 @@
import 'dart:async';
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import 'BaseEntity.dart';
import 'DioLogInterceptor.dart';
import 'NetworkConfig.dart';
enum RequestMethod {
Post,
Get,
}
const RequestMethodValues = {
RequestMethod.Get: "GET",
RequestMethod.Post: "POST",
};
class RequestCenter {
factory RequestCenter() => _getInstance();
static RequestCenter get instance => _getInstance();
static RequestCenter? _instance;
static String signKey = "5159d59637fe1b79ba789e87443e8282";
Dio? _dio, _dioLog;
final dio = Dio();
void setupDio() {
dio.options.baseUrl = 'https://openapi.shhuanmeng.com/';
dio.interceptors.add(InterceptorsWrapper(
onRequest: (options, handler) {
//
return handler.next(options);
},
onResponse: (response, handler) {
//
return handler.next(response);
},
onError: (DioError e, handler) {
//
return handler.next(e);
},
));
}
RequestCenter._internal() {
setup();
setupDio();
}
static RequestCenter _getInstance() {
_instance ??= RequestCenter._internal();
//
if (_instance!._dio != null && NetworkConfig.ServerDomain_Online != _instance!._dio!.options.baseUrl) {
_instance!._dio!.options.baseUrl = NetworkConfig.ServerDomain_Online;
}
return _instance!;
}
void setup() {
//
if (null == _dio) {
_dio = Dio(BaseOptions(
baseUrl: NetworkConfig.ServerDomain_Online,
sendTimeout: const Duration(seconds: 10),
receiveTimeout: const Duration(seconds: 20),
connectTimeout: const Duration(seconds: 20),
contentType: Headers.jsonContentType,
responseType: ResponseType.json));
_dio!.interceptors.add(DioLogInterceptor());
/* _dio.interceptors.add(new ResponseInterceptors());*/
_dioLog = Dio(BaseOptions(
sendTimeout: const Duration(seconds: 10),
receiveTimeout: const Duration(seconds: 20),
connectTimeout: const Duration(seconds: 20),
contentType: Headers.jsonContentType,
responseType: ResponseType.json));
//_dioLog!.interceptors.add(DioLogInterceptor());
// (_dio?.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
// client.findProxy = (uri) {
// return "PROXY 192.168.1.11:8888";
// };
// //Https包设置
// client.badCertificateCallback = (X509Certificate cert, String host, int port) => true;
// };
}
}
// post
Future<BaseEntity?> request(path, Map<Object, dynamic> parmeters, Function(BaseEntity dataEntity) success, Function(ErrorEntity errorEntity) error,
{RequestMethod? method}) async {
try {
//FormData formData = FormData.fromMap(parmeters);
Response response = await _dio!.post(path,
data: parmeters,
options: Options(
headers: {
'Authorization': "Bearer ${NetworkConfig.token}",
'Userid': NetworkConfig.userId,
'Username': NetworkConfig.userName,
},
));
BaseEntity entity = BaseEntity.PlayfromJson(response.data);
success(entity);
return entity;
} catch (e) {
error(ErrorEntity(code: -1, msg: "$e"));
return null;
}
}
Future<BaseEntity?> requestGet(
path, Map<String, dynamic> parmeters, Function(BaseEntity dataEntity) success, Function(ErrorEntity errorEntity) error,
{RequestMethod? method}) async {
try {
//FormData formData = FormData.fromMap(parmeters);
Response response = await _dio!.get(path,
queryParameters: parmeters,
options: Options(
headers: {
'Authorization': "Bearer ${NetworkConfig.token}",
'Userid': NetworkConfig.userId,
'Username': NetworkConfig.userName,
},
));
BaseEntity entity = BaseEntity.PlayfromJson(response.data);
success(entity);
return entity;
} catch (e) {
error(ErrorEntity(code: -1, msg: "$e"));
return null;
}
}
Future<BaseEntity?> sendRequest(
Map<Object, dynamic> parmeters,
Function(BaseEntity dataEntity) success,
Function(ErrorEntity errorEntity) error,
) async {
try {
print('Request: $parmeters');
final response = await dio.post('/messages',
data: parmeters,
options: Options(
contentType: Headers.jsonContentType,
responseType: ResponseType.json,
headers: {'x-api-key': 'sk-V6d51cc6aa28906caecb7f22803d92ae3f18cfeb799nh4mc', 'anthropic-version': "2023-06-01"},
));
print('Response: ${response.data}');
BaseEntity entity = BaseEntity.fromJson(response.data);
success(entity);
return entity;
} on DioError catch (e) {
print('Error: ${e.response?.data}');
}
return null;
}
//post
Future<BaseEntity?> request1(path, Map<String, dynamic> parmeters, Function(BaseEntity dataEntity) success, Function(ErrorEntity errorEntity) error,
{RequestMethod? method}) async {
Map<String, dynamic> headers = {
"AppId": NetworkConfig.AppId,
"userId": NetworkConfig.userId,
"Version": NetworkConfig.Version,
"Language": NetworkConfig.Language
};
parmeters.addAll(headers);
Map<String, dynamic> parmetersSign = sign(parmeters);
try {
/*由于服务器是表单结构*/
FormData formData = FormData.fromMap(parmetersSign);
Response response = await _dio!.post(path, data: formData);
if (response != null && response.statusCode == 200) {
BaseEntity entity = BaseEntity.fromJson(response.data);
success(entity);
return entity;
} else {
error(ErrorEntity(code: -1, msg: "Network Anomaly"));
return null;
}
} catch (e) {
error(ErrorEntity(code: -1, msg: "Network Anomaly"));
return null;
}
}
Future<BaseEntity?> requestLog(
path, Map<String, dynamic> parmeters, Function(BaseEntity dataEntity) success, Function(ErrorEntity errorEntity) error,
{RequestMethod? method}) async {
Map<String, dynamic> headers = {
"AppId": NetworkConfig.AppId,
/*"BossId": NetworkConfig.BossId,*/
"userId": NetworkConfig.userId,
"Version": NetworkConfig.Version,
"Language": NetworkConfig.Language
};
parmeters.addAll(headers);
Map<String, dynamic> parmetersSign = sign(parmeters);
try {
/*由于服务器是表单结构*/
FormData formData = FormData.fromMap(parmetersSign);
Response response = await _dioLog!.post(path, data: formData);
if (response != null && response.statusCode == 200) {
BaseEntity entity = BaseEntity.fromJson(response.data);
success(entity);
return entity;
} else {
error(ErrorEntity(code: -1, msg: "Network Anomaly"));
return null;
}
} catch (e) {
error(ErrorEntity(code: -1, msg: "Network Anomaly"));
return null;
}
}
// post
Future<BaseEntity?> requestPay(
path, Map<String, dynamic> parmeters, Function(BaseEntity dataEntity) success, Function(ErrorEntity errorEntity) error,
{RequestMethod? method}) async {
Map<String, dynamic> headers = {
"AppId": NetworkConfig.AppId,
/*"BossId": NetworkConfig.BossId,*/
"userId": NetworkConfig.userId,
"Version": NetworkConfig.Version,
"Language": NetworkConfig.Language
};
parmeters.addAll(headers);
Map<String, dynamic> parmetersSign = sign(parmeters);
try {
FormData formData = FormData.fromMap(parmetersSign);
Response response = await _dio!.post(path, data: formData);
if (response != null && response.statusCode == 200) {
BaseEntity entity = BaseEntity.fromJson(response.data);
success(entity);
return entity;
} else {
error(ErrorEntity(code: -1, msg: "未知错误"));
return null;
}
} catch (e) {
ErrorEntity(code: -1, msg: "未知错误");
return null;
}
}
// post ()
Future<BaseEntity?> requestWeb(
path, Map<String, dynamic> parmeters, Function(BaseEntity dataEntity) success, Function(ErrorEntity errorEntity) error,
{RequestMethod? method}) async {
Map<String, dynamic> headers = {
"AppId": NetworkConfig.AppId,
/*"BossId": NetworkConfig.BossId,*/
"UserId": NetworkConfig.userId,
"Version": NetworkConfig.Version,
"Language": NetworkConfig.Language
};
parmeters.addAll(headers);
//
Map<String, dynamic> parmetersSign = sign(parmeters);
try {
/*由于服务器是表单结构*/
FormData formData = FormData.fromMap(parmetersSign);
Response response = await _dio!.post(path, data: formData);
if (response != null && response.statusCode == 200) {
BaseEntity entity = BaseEntity.fromJson(response.data);
Map<String, dynamic> parmeters = {
"AppId": NetworkConfig.AppId,
/*"BossId": NetworkConfig.BossId,*/
"UserId": NetworkConfig.userId,
"Token": entity.msg
};
Map<String, dynamic> p1 = sign(parmeters);
parmeters.addAll(p1);
//data
entity.data = gettoken(parmeters);
success(entity);
return entity;
} else {
error(ErrorEntity(code: -1, msg: "Network Anomaly"));
return null;
}
} catch (e) {
ErrorEntity(code: -1, msg: "Network Anomaly");
return null;
}
}
//
ErrorEntity _getErrorMsg(DioError error) {
switch (error.type) {
case DioErrorType.cancel:
{
return ErrorEntity(code: -1, msg: "请求取消");
}
break;
case DioErrorType.connectionTimeout:
{
return ErrorEntity(code: -1, msg: "连接超时");
}
break;
case DioErrorType.sendTimeout:
{
return ErrorEntity(code: -1, msg: "请求超时");
}
break;
case DioErrorType.receiveTimeout:
{
return ErrorEntity(code: -1, msg: "响应超时");
}
break;
case DioErrorType.badResponse:
{
try {
int errCode = error.response!.statusCode!;
String errorMsg = error.response!.statusMessage!;
return ErrorEntity(code: errCode, msg: errorMsg);
} on Exception catch (_) {
return ErrorEntity(code: -1, msg: "Network Anomaly");
}
}
break;
default:
{
return ErrorEntity(code: -1, msg: "Network Anomaly");
}
}
}
Map<String, dynamic> sign(Map<String, dynamic> parmeters) {
List<String> keys = parmeters.keys.toList();
// key排序
keys.sort((a, b) {
List<int> al = a.codeUnits;
List<int> bl = b.codeUnits;
for (int i = 0; i < al.length; i++) {
if (bl.length <= i) return 1;
if (al[i] > bl[i]) {
return 1;
} else if (al[i] < bl[i]) return -1;
}
return 0;
});
Map<String, dynamic> treeMap = Map();
keys.forEach((element) {
treeMap[element] = parmeters[element];
});
String data = "";
for (dynamic str in treeMap.values) {
if (str != null) {
data = data + str.toString();
}
}
treeMap["sign"] = generateMd5(data + NetworkConfig.userToken);
return treeMap;
}
String gettoken(Map<String, dynamic> parmeters) {
List<String> keys = parmeters.keys.toList();
// key排序
keys.sort((a, b) {
List<int> al = a.codeUnits;
List<int> bl = b.codeUnits;
for (int i = 0; i < al.length; i++) {
if (bl.length <= i) return 1;
if (al[i] > bl[i]) {
return 1;
} else if (al[i] < bl[i]) return -1;
}
return 0;
});
Map<String, dynamic> treeMap = Map();
keys.forEach((element) {
treeMap[element] = parmeters[element];
});
String data = "";
treeMap.forEach((key, value) {
if (data == "") {
data = key + "=" + value.toString();
} else {
data = data + "&" + key + "=" + value.toString();
}
});
return data;
}
String generateMd5(String data) {
return md5.convert(utf8.encode(data)).toString();
}
}

View File

@ -0,0 +1,98 @@
import 'dart:async';
import 'package:odf/bean/room_list_bean.dart';
import 'package:odf/network/NetworkConfig.dart';
import 'package:odf/network/RequestCenter.dart';
import '../../bean/company_bean.dart';
import '../../bean/device_list_bean.dart';
import '../../bean/update_bean.dart';
class HomeModel {
StreamController streamController = StreamController.broadcast();
///
Future<void> roomList(pageNum, pageSize, deptId) async {
RequestCenter.instance.requestGet(NetworkConfig.roomList, {
"pageNum": pageNum,
"pageSize": pageSize,
"deptId": deptId,
}, (dataEntity) {
if (dataEntity.code == 200) {
RoomListBean roomListBean = RoomListBean.fromJson(dataEntity.data);
streamController.sink.add({
'code': "roomList", //
'data': roomListBean,
});
}
}, (errorEntity) {
print("errorEntity==${errorEntity.msg}");
});
}
///
Future<void> getCompany() async {
RequestCenter.instance.requestGet(NetworkConfig.getCompany, {}, (dataEntity) {
if (dataEntity.code == 200) {
List<CompanyBean> data = (dataEntity.data as List<dynamic>).map((e) => CompanyBean.fromJson(e as Map<String, dynamic>)).toList();
streamController.sink.add({
'code': "getCompany", //
'data': data,
});
}
}, (errorEntity) {
print("errorEntity==${errorEntity.msg}");
});
}
///
Future<void> odfPortsUnitType() async {
List<String> list = [];
RequestCenter.instance.requestGet(NetworkConfig.odfPortsUnitType, {}, (dataEntity) {
if (dataEntity.code == 200) {
List<DeviceListBean> data = (dataEntity.data as List<dynamic>).map((e) => DeviceListBean.fromJson(e as Map<String, dynamic>)).toList();
for (var element in data) {
list.add("${element.dictValue}");
}
NetworkConfig.diverItems = list;
}
}, (errorEntity) {
print("errorEntity==${errorEntity.msg}");
});
}
///
Future<void> odfPortsBusinessType() async {
List<String> list = [];
RequestCenter.instance.requestGet(NetworkConfig.odfPortsBusinessType, {}, (dataEntity) {
if (dataEntity.code == 200) {
List<DeviceListBean> data = (dataEntity.data as List<dynamic>).map((e) => DeviceListBean.fromJson(e as Map<String, dynamic>)).toList();
for (var element in data) {
list.add("${element.dictValue}");
}
NetworkConfig.businessItems = list;
}
}, (errorEntity) {
print("errorEntity==${errorEntity.msg}");
});
}
///
Future<void> checkAppVersion(version) async {
RequestCenter.instance.requestGet(NetworkConfig.checkAppVersion, {"version": version}, (dataEntity) {
if (dataEntity.code == 200) {
UpdateBean updateBean = UpdateBean.fromJson(dataEntity.data);
streamController.sink.add({
'code': "checkAppVersion", //
'data': updateBean,
});
}
}, (errorEntity) {
print("errorEntity==${errorEntity.msg}");
});
}
}

View File

@ -0,0 +1,234 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:odf/tools/home/home_model.dart';
import 'package:package_info_plus/package_info_plus.dart';
import '../../bean/company_bean.dart';
import '../../bean/update_bean.dart';
import '../../common/func.dart';
import '../../dialog/update_dialog.dart';
import '../machine/region_page.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
late StreamSubscription subscription;
final HomeModel _viewmodel = HomeModel();
bool isLoad = false;
List<CompanyBean> companyList = [];
late UpdateBean updateBean;
@override
void initState() {
// TODO: implement initState
super.initState();
subscription = _viewmodel.streamController.stream.listen((event) {
String code = event['code'];
if (code.isNotEmpty) {
switch (code) {
case "getCompany":
isLoad = true;
companyList = event['data'];
break;
case "checkAppVersion":
updateBean = event['data'];
if (updateBean.needUpdate != null && updateBean.needUpdate!) {
FunctionUtil.popDialog2(
context,
UpdateDialog(
downloadUrl: "${updateBean.downloadUrl}",
),
);
}
break;
}
}
setState(() {});
});
_viewmodel.getCompany();
_viewmodel.odfPortsUnitType();
_viewmodel.odfPortsBusinessType();
getUpdate();
}
///
getUpdate() async {
final info = await PackageInfo.fromPlatform();
String version = info.version;
print("版本:version==$version");
_viewmodel.checkAppVersion(version);
}
@override
void dispose() {
// TODO: implement dispose
subscription.cancel();
super.dispose();
}
//
Future<void> _refreshData() async {
_viewmodel.getCompany();
}
@override
Widget build(BuildContext context) {
final double statusBarHeight = MediaQuery.of(context).padding.top;
final size = MediaQuery.of(context).size;
final t10 = size.width / 36;
final s20 = size.width / 18;
final h35 = size.width / 10.285714285714;
final l16 = size.width / 22.5;
final w18 = size.width / 20;
final l11 = size.width / 32.727272727272;
final s14 = size.width / 25.714285714285;
return Scaffold(
body: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/home_bg.png'),
fit: BoxFit.cover,
)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
margin: EdgeInsets.only(top: statusBarHeight + t10, left: l16, right: l16),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
///
GestureDetector(
onTap: () {
_refreshData();
},
child: Image(
width: w18,
image: const AssetImage('assets/images/ic_refresh.png'),
),
),
GestureDetector(
onTap: () {},
child: Container(
alignment: Alignment.center,
child: Text(
'公司列表',
style: TextStyle(fontSize: s20, fontWeight: FontWeight.w600),
),
),
),
///
GestureDetector(
onTap: () {
Navigator.pushNamed(context, '/SetPage');
},
child: Image(
width: w18,
image: const AssetImage('assets/images/ic_set.png'),
),
),
],
),
),
///
GestureDetector(
onTap: () {
Navigator.pushNamed(context, "/SearchPage");
},
child: Container(
height: h35,
margin: EdgeInsets.only(top: t10, left: l11, right: l11),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(width: 0.5, color: Colors.black12),
borderRadius: BorderRadius.all(Radius.circular(l16)),
),
child: Row(
children: [
Container(
margin: EdgeInsets.only(left: t10),
child: Image(
width: l16,
image: const AssetImage('assets/images/ic_search.png'),
),
),
Container(
margin: EdgeInsets.only(left: s20),
child: Text(
"请输入要搜索的备注内容",
style: TextStyle(color: const Color(0xFF999999), fontSize: s14),
),
)
],
),
),
),
isLoad
? Expanded(
child: Container(
margin: EdgeInsets.only(top: s20, left: t10, right: t10),
child: RefreshIndicator(
color: const Color(0xFF1A73EC),
onRefresh: _refreshData,
child: ListView.builder(
itemCount: companyList.length,
padding: const EdgeInsets.all(0),
itemBuilder: (BuildContext context, int index) {
return _item(companyList[index], t10, s20);
}),
),
),
)
: Container()
],
),
),
);
}
_item(CompanyBean data, t10, t20) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ReginPage(
deptId: '${data.deptId}',
),
),
);
},
child: Container(
margin: EdgeInsets.only(bottom: t10),
child: Card(
color: Colors.white,
child: Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(left: t20, top: t20, bottom: t20),
child: Text("${data.deptName}"),
),
),
),
);
}
}

View File

@ -0,0 +1,81 @@
import 'dart:async';
import 'package:odf/bean/login_bean.dart';
import 'package:odf/network/BaseEntity.dart';
import 'package:odf/network/NetworkConfig.dart';
import 'package:odf/network/RequestCenter.dart';
import 'package:shared_preferences/shared_preferences.dart';
class LoginModel {
StreamController streamController = StreamController.broadcast();
///
Future<void> appLogin(username, password) async {
RequestCenter.instance.request(NetworkConfig.appLogin, {
"username": username,
"password": password,
}, (BaseEntity dataEntity) async {
print("dataEntity==${dataEntity.msg}");
if (dataEntity.code == 200) {
LoginBean loginBean = LoginBean.fromJson(dataEntity.data);
NetworkConfig.token = loginBean.jwt!.toString();
NetworkConfig.userId = loginBean.userId!.toString();
NetworkConfig.userName = loginBean.userName!.toString();
final SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString('token', loginBean.jwt!);
print("dataEntity==成功");
odf();
streamController.sink.add({
'code': "appLogin", //
'data': dataEntity.msg,
});
} else {
streamController.sink.add({
'code': "error", //
'data': dataEntity.msg,
});
}
}, (ErrorEntity errorEntity) {
print("errorEntity==${errorEntity.msg}");
});
}
///
Future<void> odf() async {
RequestCenter.instance.requestGet(NetworkConfig.odf, {}, (BaseEntity dataEntity) {
switch (dataEntity.code) {
case 200:
NetworkConfig.isPermission = true;
streamController.sink.add({
'code': "odf", //
'data': dataEntity.msg,
});
break;
case 403:
NetworkConfig.isPermission = false;
streamController.sink.add({
'code': "odf", //
'data': dataEntity.msg,
});
break;
case 401:
streamController.sink.add({
'code': "login", //
'data': dataEntity.msg,
});
break;
default:
streamController.sink.add({
'code': "error", //
'data': dataEntity.msg,
});
break;
}
}, (ErrorEntity errorEntity) {
print("errorEntity==${errorEntity.msg}");
});
}
}

View File

@ -0,0 +1,169 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:odf/tools/login/login_model.dart';
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
@override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
late StreamSubscription subscription;
final LoginModel _viewmodel = LoginModel();
@override
void initState() {
// TODO: implement initState
super.initState();
subscription = _viewmodel.streamController.stream.listen((event) {
String code = event['code'];
if (code.isNotEmpty) {
switch (code) {
case "appLogin":
Navigator.of(context).pushReplacementNamed("/HomePage");
break;
case "error":
EasyLoading.showToast(event['data']);
break;
}
}
});
}
String userName = "";
String passWord = "";
void _userNameChanged(String str) {
userName = str;
setState(() {});
}
void _passWordChanged(String str) {
passWord = str;
setState(() {});
}
@override
void dispose() {
// TODO: implement dispose
subscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
final t100 = size.width / 3.6;
final s20 = size.width / 18;
final t50 = size.width / 7.2;
final l10 = size.width / 36;
final s14 = size.width / 25.714285714285;
final t20 = size.width / 18;
final t80 = size.width / 4.5;
final s18 = size.width / 20;
return Scaffold(
backgroundColor: const Color(0xF8F8F8FF),
resizeToAvoidBottomInset: false,
body: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/login_bg.png'),
fit: BoxFit.cover,
)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
margin: EdgeInsets.only(top: t100),
child: Text(
"绥时录",
style: TextStyle(fontSize: s20, fontWeight: FontWeight.w600),
),
),
Container(
margin: EdgeInsets.only(top: t50),
alignment: Alignment.center,
child: Container(
height: t50,
alignment: Alignment.center,
margin: EdgeInsets.only(left: t50, right: t50),
padding: EdgeInsets.only(left: l10),
decoration: BoxDecoration(
color: const Color(0xFFECEFF3),
border: Border.all(width: 0.5, color: Colors.black12),
borderRadius: BorderRadius.all(Radius.circular(l10)),
),
child: TextField(
cursorColor: const Color(0xFF1A73EC),
onChanged: _userNameChanged,
decoration: const InputDecoration(
hintText: '请输入账号',
border: InputBorder.none,
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
hintStyle: TextStyle(color: Color(0xFF999999)),
),
style: TextStyle(fontSize: s14),
),
),
),
Container(
margin: EdgeInsets.only(top: t20),
alignment: Alignment.center,
child: Container(
height: t50,
alignment: Alignment.center,
margin: EdgeInsets.only(left: t50, right: t50),
padding: EdgeInsets.only(left: l10),
decoration: BoxDecoration(
color: const Color(0xFFECEFF3),
border: Border.all(width: 0.5, color: Colors.black12),
borderRadius: BorderRadius.all(Radius.circular(l10)),
),
child: TextField(
cursorColor: const Color(0xFF1A73EC),
keyboardType: TextInputType.visiblePassword,
obscureText: true,
onChanged: _passWordChanged,
decoration: const InputDecoration(
hintText: '请输入密码',
border: InputBorder.none,
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
hintStyle: TextStyle(color: Color(0xFF999999)),
),
style: TextStyle(fontSize: s14),
),
),
),
GestureDetector(
onTap: () {
_viewmodel.appLogin(userName, passWord);
},
child: Container(
height: t50,
margin: EdgeInsets.only(top: t80, left: t50, right: t50),
alignment: Alignment.center,
decoration: BoxDecoration(
color: const Color(0xFF1A73EC),
borderRadius: BorderRadius.all(Radius.circular(l10)),
),
child: Text(
"登录",
style: TextStyle(fontSize: s18, color: Colors.white),
),
),
)
],
),
),
);
}
}

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