diff --git a/android/app/build.gradle b/android/app/build.gradle index c41e74c9..21be3ed4 100755 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -85,28 +85,28 @@ android { dimension "flavor-type" applicationId "com.starlock.lock.local" signingConfig signingConfigs.debug - resValue "string", "app_name", "星锁-local" + resValue "string", "app_name", "Star Lock" manifestPlaceholders.JPUSH_PKGNAME = "com.starlock.lock.local" } dev { dimension "flavor-type" applicationId "com.starlock.lock.dev" signingConfig signingConfigs.debug - resValue "string", "app_name", "星锁-dev" + resValue "string", "app_name", "Star Lock" manifestPlaceholders.JPUSH_PKGNAME = "com.starlock.lock.dev" } pre { dimension "flavor-type" applicationId "com.starlock.lock.pre" signingConfig signingConfigs.debug - resValue "string", "app_name", "星锁" + resValue "string", "app_name", "Star Lock-P" manifestPlaceholders.JPUSH_PKGNAME = "com.starlock.lock.pre" } sky { dimension "flavor-type" applicationId "com.skychip.lock" signingConfig signingConfigs.sky - resValue "string", "app_name", "锁通通" + resValue "string", "app_name", "TTLock Pro" manifestPlaceholders.JPUSH_PKGNAME = "com.skychip.lock" proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules-sky.pro' } @@ -114,21 +114,21 @@ android { dimension "flavor-type" applicationId "com.skychip.lock.pre" signingConfig signingConfigs.sky - resValue "string", "app_name", "锁通通-P" + resValue "string", "app_name", "TTLock Pro-P" manifestPlaceholders.JPUSH_PKGNAME = "com.skychip.lock.pre" } sky_dev { dimension "flavor-type" applicationId "com.skychip.lock.dev" signingConfig signingConfigs.sky - resValue "string", "app_name", "锁通通-D" + resValue "string", "app_name", "TTLock Pro" manifestPlaceholders.JPUSH_PKGNAME = "com.skychip.lock.dev" } xhj { dimension "flavor-type" applicationId "com.xhjcn.lock" signingConfig signingConfigs.xhj - resValue "string", "app_name", "星星锁" + resValue "string", "app_name", "Star Lock" manifestPlaceholders.JPUSH_PKGNAME = "com.xhjcn.lock" proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules-xhj.pro' } @@ -136,14 +136,14 @@ android { dimension "flavor-type" applicationId "com.xhjcn.lock.pre" signingConfig signingConfigs.xhj - resValue "string", "app_name", "星星锁-P" + resValue "string", "app_name", "Star Lock-P" manifestPlaceholders.JPUSH_PKGNAME = "com.xhjcn.lock.pre" } xhj_dev { dimension "flavor-type" applicationId "com.xhjcn.lock.dev" signingConfig signingConfigs.xhj - resValue "string", "app_name", "星星锁-D" + resValue "string", "app_name", "Star Lock" manifestPlaceholders.JPUSH_PKGNAME = "com.xhjcn.lock.dev" } } diff --git a/android/app/src/dev/res/values-zh-rCN/string.xml b/android/app/src/dev/res/values-zh-rCN/string.xml index e55b995c..d42c50e6 100644 --- a/android/app/src/dev/res/values-zh-rCN/string.xml +++ b/android/app/src/dev/res/values-zh-rCN/string.xml @@ -1,4 +1,4 @@ - 星锁 + 星锁-dev \ No newline at end of file diff --git a/android/app/src/sky_pre/res/values-en-rUS/string.xml b/android/app/src/sky_pre/res/values-en-rUS/string.xml new file mode 100644 index 00000000..e5736ebd --- /dev/null +++ b/android/app/src/sky_pre/res/values-en-rUS/string.xml @@ -0,0 +1,4 @@ + + + TTLock Pro-P + \ No newline at end of file diff --git a/android/app/src/sky_pre/res/values-zh-rCN/string.xml b/android/app/src/sky_pre/res/values-zh-rCN/string.xml new file mode 100644 index 00000000..04482066 --- /dev/null +++ b/android/app/src/sky_pre/res/values-zh-rCN/string.xml @@ -0,0 +1,4 @@ + + + 锁通通-P + \ No newline at end of file diff --git a/android/app/src/xhj_pre/res/values-en-rUS/string.xml b/android/app/src/xhj_pre/res/values-en-rUS/string.xml new file mode 100644 index 00000000..1f8a4906 --- /dev/null +++ b/android/app/src/xhj_pre/res/values-en-rUS/string.xml @@ -0,0 +1,4 @@ + + + Star Lock-P + \ No newline at end of file diff --git a/android/app/src/xhj_pre/res/values-zh-rCN/string.xml b/android/app/src/xhj_pre/res/values-zh-rCN/string.xml new file mode 100644 index 00000000..9129d25b --- /dev/null +++ b/android/app/src/xhj_pre/res/values-zh-rCN/string.xml @@ -0,0 +1,4 @@ + + + 星星锁-P + \ No newline at end of file diff --git a/assets/test.jpg b/assets/test.jpg new file mode 100644 index 00000000..f74d412c Binary files /dev/null and b/assets/test.jpg differ diff --git a/images/icon_left_grey.png b/images/icon_left_grey.png new file mode 100644 index 00000000..26593087 Binary files /dev/null and b/images/icon_left_grey.png differ diff --git a/ios/Podfile.lock b/ios/Podfile.lock index bb07ffbd..b61fd8fb 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -10,12 +10,12 @@ PODS: - EMASRest - AlicloudUT (5.2.0.16): - AlicloudUTDID - - AlicloudUTDID (1.5.0.94) - - AlicloudUtils (1.4.1): + - AlicloudUTDID (1.6.0) + - AlicloudUtils (2.0.0): - AlicloudUTDID - aliyun_face_plugin (0.0.1): - Flutter - - AMap3DMap (10.0.600): + - AMap3DMap (10.0.700): - AMapFoundation (>= 1.8.0) - amap_flutter_location (0.0.1): - AMapLocation @@ -42,35 +42,35 @@ PODS: - FlutterMacOS - device_info_plus (0.0.1): - Flutter - - DKImagePickerController/Core (4.3.7): + - DKImagePickerController/Core (4.3.9): - DKImagePickerController/ImageDataManager - DKImagePickerController/Resource - - DKImagePickerController/ImageDataManager (4.3.7) - - DKImagePickerController/PhotoGallery (4.3.7): + - DKImagePickerController/ImageDataManager (4.3.9) + - DKImagePickerController/PhotoGallery (4.3.9): - DKImagePickerController/Core - DKPhotoGallery - - DKImagePickerController/Resource (4.3.7) - - DKPhotoGallery (0.0.17): - - DKPhotoGallery/Core (= 0.0.17) - - DKPhotoGallery/Model (= 0.0.17) - - DKPhotoGallery/Preview (= 0.0.17) - - DKPhotoGallery/Resource (= 0.0.17) + - DKImagePickerController/Resource (4.3.9) + - DKPhotoGallery (0.0.19): + - DKPhotoGallery/Core (= 0.0.19) + - DKPhotoGallery/Model (= 0.0.19) + - DKPhotoGallery/Preview (= 0.0.19) + - DKPhotoGallery/Resource (= 0.0.19) - SDWebImage - SwiftyGif - - DKPhotoGallery/Core (0.0.17): + - DKPhotoGallery/Core (0.0.19): - DKPhotoGallery/Model - DKPhotoGallery/Preview - SDWebImage - SwiftyGif - - DKPhotoGallery/Model (0.0.17): + - DKPhotoGallery/Model (0.0.19): - SDWebImage - SwiftyGif - - DKPhotoGallery/Preview (0.0.17): + - DKPhotoGallery/Preview (0.0.19): - DKPhotoGallery/Model - DKPhotoGallery/Resource - SDWebImage - SwiftyGif - - DKPhotoGallery/Resource (0.0.17): + - DKPhotoGallery/Resource (0.0.19): - SDWebImage - SwiftyGif - EMASRest (11.1.1.2) @@ -136,9 +136,9 @@ PODS: - FlutterMacOS - permission_handler_apple (9.3.0): - Flutter - - SDWebImage (5.19.1): - - SDWebImage/Core (= 5.19.1) - - SDWebImage/Core (5.19.1) + - SDWebImage (5.19.2): + - SDWebImage/Core (= 5.19.2) + - SDWebImage/Core (5.19.2) - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS @@ -321,10 +321,10 @@ SPEC CHECKSUMS: AlicloudPush: 88529c9b796e4ece0601de0867b30359f55b61f7 AlicloudSender: 1f468b6bd962a099ffc19d45e3608b0fe98f259d AlicloudUT: 6d1cf30d57d096b7e9bb4b069dd0ba6ad59a3338 - AlicloudUTDID: 7323c443dcdf9a73e2224dc6ce51703671d7a765 - AlicloudUtils: 873a76615bebcee8b1996f20820d366e433c3eab + AlicloudUTDID: 4e9d44c2fd704b3508069c38eaec9d6a759e702c + AlicloudUtils: 2a78de434a8b2dc99e408c4d6220e654076d9ef0 aliyun_face_plugin: 7a90b6526c5acea616062e809699294c782c3eb8 - AMap3DMap: d104a679c2bad573c908e0ddadf26bc399678b24 + AMap3DMap: 6ee456d7ba946ebbad580a343b74ffa8e9936175 amap_flutter_location: 44ff5beb64f42e0bf5feb402fe299dac0013af6f amap_flutter_map: 979e54d227cedac6c7504a2151bfbf3bcf96760a AMapFoundation: 9885c48fc3a78fdfb84a0299a2293e56ea3c9fec @@ -337,8 +337,8 @@ SPEC CHECKSUMS: camera_avfoundation: dd002b0330f4981e1bbcb46ae9b62829237459a4 connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed - DKImagePickerController: 0a24ebfe7b48beeb74c27531540aaa2cc1dac6cf - DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 + DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c + DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 EMASRest: 8df6f87836767a9415ad5cc4af739bc9d215b475 fast_rsa: a1fed69b074093d2e2e3fefae6b821a071649d4c file_picker: ce3938a0df3cc1ef404671531facef740d03f920 @@ -365,7 +365,7 @@ SPEC CHECKSUMS: package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 - SDWebImage: 40b0b4053e36c660a764958bff99eed16610acbb + SDWebImage: dfe95b2466a9823cf9f0c6d01217c06550d7b29a shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 572fcf04..e988c153 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 04C1FC572D13F1A2000C959E /* InfoPlist.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 04C1FC562D13F1A2000C959E /* InfoPlist.xcstrings */; }; 04D0CC262D06CE570042EF10 /* launchImage_xhj.png in Resources */ = {isa = PBXBuildFile; fileRef = 82B657662C919BDF0079121C /* launchImage_xhj.png */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 25B2A1422F9A2CCCBBCBBB97 /* skyRelease.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 35F02D170492750B437D6AB6 /* skyRelease.xcconfig */; }; @@ -98,6 +99,7 @@ /* Begin PBXFileReference section */ 0420903B2C0EEAA50073E654 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Main.strings"; sourceTree = ""; }; 04BFC4482BCFE05100688FCA /* RunnerRelease-xhj.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "RunnerRelease-xhj.entitlements"; sourceTree = ""; }; + 04C1FC562D13F1A2000C959E /* InfoPlist.xcstrings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json.xcstrings; path = InfoPlist.xcstrings; sourceTree = ""; }; 0BEB3ADCCEC961E2916B9004 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 0D02C18E16914A687A4A1AC2 /* devDebug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = devDebug.xcconfig; path = Flutter/devDebug.xcconfig; sourceTree = ""; }; 126D1370182AB44291C67A10 /* Pods-Runner.dev-release-sky.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.dev-release-sky.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.dev-release-sky.xcconfig"; sourceTree = ""; }; @@ -341,6 +343,7 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + 04C1FC562D13F1A2000C959E /* InfoPlist.xcstrings */, E0B3E9EC2D04B36C00907A95 /* info_dev.plist */, E0B3E9EB2D04B36C00907A95 /* info_pre.plist */, E0B3E9EA2D04B36C00907A95 /* info_sky.plist */, @@ -507,6 +510,7 @@ 9C453CBFAB0703DFA762337C /* preProfile.xcconfig in Resources */, 44827AC367F1EAB110A97660 /* preRelease.xcconfig in Resources */, D7EF77645AB1C3CEEA536468 /* skyDebug.xcconfig in Resources */, + 04C1FC572D13F1A2000C959E /* InfoPlist.xcstrings in Resources */, 7B54002BF45E5D8B295B6447 /* skyProfile.xcconfig in Resources */, 25B2A1422F9A2CCCBBCBBB97 /* skyRelease.xcconfig in Resources */, ADF948FD9EE8BD1AE71F0984 /* xhjDebug.xcconfig in Resources */, @@ -698,10 +702,9 @@ baseConfigurationReference = 4A63B2C308CB401731950EC8 /* Pods-Runner.debug-sky.xcconfig */; buildSettings = { CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-sky.entitlements"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = NAQ5PL2DYC; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = SF86QP26TZ; INFOPLIST_FILE = Runner/info_sky.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -711,7 +714,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.starlock.lock.local; PRODUCT_NAME = Runner; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Debug_com.starlock.lock.local.mobileprovision; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -795,10 +797,9 @@ baseConfigurationReference = 22D858E988707FF26E068457 /* Pods-Runner.debug-xhj.xcconfig */; buildSettings = { CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-xhj.entitlements"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = NAQ5PL2DYC; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = SF86QP26TZ; INFOPLIST_FILE = Runner/info_xhj.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -808,7 +809,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.starlock.lock.local; PRODUCT_NAME = Runner; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Debug_com.starlock.lock.local.mobileprovision; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -821,9 +821,9 @@ baseConfigurationReference = 16A83D21DFB231D8453DC681 /* Pods-Runner.release-sky.xcconfig */; buildSettings = { CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-sky.entitlements"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = NAQ5PL2DYC; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = NAQ5PL2DYC; INFOPLIST_FILE = Runner/info_sky.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -831,7 +831,7 @@ "$(inherited)", ); PRODUCT_NAME = Runner; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Appstore_com.skychip.lock.mobileprovision; + PROVISIONING_PROFILE_SPECIFIER = ""; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -844,9 +844,9 @@ baseConfigurationReference = CDC2B8ED804B514A774F187D /* Pods-Runner.release-xhj.xcconfig */; buildSettings = { CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-xhj.entitlements"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = P8997RW3V8; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = P8997RW3V8; INFOPLIST_FILE = Runner/info_xhj.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -855,7 +855,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.xhjcn.lock; PRODUCT_NAME = Runner; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Appstore_com.xhjcn.lock.mobileprovision; + PROVISIONING_PROFILE_SPECIFIER = ""; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -1088,10 +1088,8 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = "Runner/RunnerDebug-dev.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = NAQ5PL2DYC; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = SF86QP26TZ; INFOPLIST_FILE = Runner/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -1101,7 +1099,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.starlock.lock.local; PRODUCT_NAME = Runner; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Debug_com.starlock.lock.local.mobileprovision; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -1185,10 +1182,9 @@ baseConfigurationReference = D697F91E8405773AB9A5881E /* Pods-Runner.pre-release-sky.xcconfig */; buildSettings = { CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-sky.entitlements"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = NAQ5PL2DYC; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = NAQ5PL2DYC; INFOPLIST_FILE = Runner/info_sky.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -1198,7 +1194,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.skychip.lock.pre; PRODUCT_NAME = Runner; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Adhoc_com.skychip.lock.pre.mobileprovision; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -1282,10 +1277,9 @@ baseConfigurationReference = 126D1370182AB44291C67A10 /* Pods-Runner.dev-release-sky.xcconfig */; buildSettings = { CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-sky.entitlements"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = NAQ5PL2DYC; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = NAQ5PL2DYC; INFOPLIST_FILE = Runner/info_sky.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -1295,7 +1289,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.skychip.lock.dev; PRODUCT_NAME = Runner; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Adhoc_com.skychip.lock.dev.mobileprovision; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -1379,10 +1372,9 @@ baseConfigurationReference = 789004F1B475B44713E199BC /* Pods-Runner.pre-release-xhj.xcconfig */; buildSettings = { CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-xhj.entitlements"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = P8997RW3V8; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = P8997RW3V8; INFOPLIST_FILE = Runner/info_xhj.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -1392,7 +1384,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.xhjcn.lock.pre; PRODUCT_NAME = Runner; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Adhoc_com.xhjcn.lock.pre.mobileprovision; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -1476,10 +1467,9 @@ baseConfigurationReference = ED3A443EA1439FD0FB4BCF80 /* Pods-Runner.dev-release-xhj.xcconfig */; buildSettings = { CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-xhj.entitlements"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = P8997RW3V8; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = P8997RW3V8; INFOPLIST_FILE = Runner/info_xhj.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -1489,7 +1479,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.xhjcn.lock.dev; PRODUCT_NAME = Runner; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Adhoc_com.xhjcn.lock.dev.mobileprovision; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; diff --git a/lan/lan_ar.json b/lan/lan_ar.json index 1cd0e45a..de21a723 100644 --- a/lan/lan_ar.json +++ b/lan/lan_ar.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "ستتم إزالة جميع معلومات حسابك من المنصة بشكل دائم ولا يمكن استردادها. هل تريد حذفها ؟", "监控": "شاشة", "视频日志": "سجل الفيديو", - "网关设备": "بوابة", "开门器": "فاتح باب", "面容开锁": "يفتح الوجه", "开门方向设置": "مجموعة فتح الاتجاه", @@ -778,7 +777,6 @@ "导出": "التصدير", "批量导出": "تصدير الدفعة", "读取记录": "تحديث السجلات", - "手机需联网": "إبرة", "设备": "جهاز", "消息": "الرسائل", "智能分析": "تحليلات ذكية", @@ -1110,5 +1108,15 @@ "常规使用": "استخدام منتظم", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "بعد تشغيل البوابة ، اضغط مع الاستمرار على زر إعادة الضبط لمدة 5 ثوانٍ ، وانقر بعد ذلك عندما يومض مصباح المؤشر بالتناوب", "扫描设备": "جهاز المسح الضوئي", - "删除失败,网关可能已经离线,是否强制删除该数据?": "فشل الحذف. ربما تكون البوابة قد اختفت دون اتصال. هل تريد فرض حذف البيانات ؟" + "删除失败,网关可能已经离线,是否强制删除该数据?": "فشل الحذف. ربما تكون البوابة قد اختفت دون اتصال. هل تريد فرض حذف البيانات ؟", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_bg.json b/lan/lan_bg.json index 42500e03..e4cbd2e3 100644 --- a/lan/lan_bg.json +++ b/lan/lan_bg.json @@ -314,7 +314,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Цялата информация за профила ви ще бъде премахната от платформата за постоянно и не може да бъде възстановена. искате ли да изтриете?", "监控": "Монитор", "视频日志": "Видео дневник", - "网关设备": "Шлюз", "开门器": "Отварачка за врати", "面容开锁": "Face отключва", "开门方向设置": "Задаване на посоката на отваряне", @@ -779,7 +778,6 @@ "导出": "Експортиране", "批量导出": "Партиден износ", "读取记录": "Опресняване на записи", - "手机需联网": "Neednet", "设备": "Устройство", "消息": "Съобщения", "智能分析": "Интелигентни анализи", @@ -1110,5 +1108,15 @@ "常规使用": "Редовна употреба", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "След като шлюзът е включен, натиснете и задръжте бутона reset за 5 секунди и щракнете върху следващия, когато индикаторната светлина мига алтернативно", "扫描设备": "Сканиране устройство", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Изтриването не успя. Портата може да е отишла офлайн. Искате ли да принудите изтриване на данните?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Изтриването не успя. Портата може да е отишла офлайн. Искате ли да принудите изтриване на данните?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_bn.json b/lan/lan_bn.json index 24d339ed..94eb47cf 100644 --- a/lan/lan_bn.json +++ b/lan/lan_bn.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "অ্যালসসআরগানগান্টের মাইউইল্ডবেইভেড-এরফেইট্রোমফর্ম", "监控": "Monitor", "视频日志": "নিঃশব্দ", - "网关设备": "সমুদ্রে", "开门器": "ডোরওএফ", "面容开锁": "ফেসসসুনcolocs", "开门方向设置": "ডিরেক্টরসেট", @@ -778,7 +777,6 @@ "导出": "পোর্ট", "批量导出": "পোর্ট", "读取记录": "রূপ", - "手机需联网": "উইমেনেট", "设备": "ব্লিভাইস", "消息": "এন্টস", "智能分析": "Intel▁লিজেন্টা", @@ -1110,5 +1108,15 @@ "常规使用": "গ্যারিউস", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "অ্যারাস্টার্টিউইসপোভেরেডন, প্রেস এবং টিপেস্টেট্রিসেট গানttonfor5sononds, এবং চক্লিক উইভেন্থে-উইন্টার", "扫描设备": "সিস্কান্লিভাইস", - "删除失败,网关可能已经离线,是否强制删除该数据?": "ডাইজেজেশনিমেরিলেড। টিভওয়েমাইয়ানভিগনোনোআরলাইন। ডো ডাউনডেটা?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "ডাইজেজেশনিমেরিলেড। টিভওয়েমাইয়ানভিগনোনোআরলাইন। ডো ডাউনডেটা?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_cs.json b/lan/lan_cs.json index 454a51d4..a4f55b06 100644 --- a/lan/lan_cs.json +++ b/lan/lan_cs.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Všechny informace o vašem účtu budou z platformy odebrány natrvalo a nemohou být obnoveny.", "监控": "Monitor", "视频日志": "Protokol videa", - "网关设备": "Brána", "开门器": "Otvírač dveří", "面容开锁": "Tvář odemkne", "开门方向设置": "Nastavit směr otevření", @@ -778,7 +777,6 @@ "导出": "Export", "批量导出": "Export šarže", "读取记录": "Refresh records", - "手机需联网": "Neednet", "设备": "Zařízení", "消息": "Zprávy", "智能分析": "Inteligentní analýza", @@ -1110,5 +1108,15 @@ "常规使用": "Pravidelné použití", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Po zapnutí brány stiskněte a podržte tlačítko reset po dobu 5 sekund a klepněte na tlačítko next", "扫描设备": "Skenovat zařízení", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Odstranění se nezdařilo. Brána možná byla offline. Chcete vynutit smazat data?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Odstranění se nezdařilo. Brána možná byla offline. Chcete vynutit smazat data?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_da.json b/lan/lan_da.json index b954a372..d5e1d294 100644 --- a/lan/lan_da.json +++ b/lan/lan_da.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Alle dine kontooplysninger vil blive fjernet fra platformen PERMANENTENTIGT og kan ikke gendannes. Ønsker du at slette?", "监控": "Skærm", "视频日志": "Videologg", - "网关设备": "GatewayName", "开门器": "Døråbnere", "面容开锁": "Ansigt åbnes", "开门方向设置": "Åbningsvejssæt", @@ -778,7 +777,6 @@ "导出": "Eksportører", "批量导出": "Batch-eksport", "读取记录": "Genopfrisk poster", - "手机需联网": "NeedNet", "设备": "Enhed", "消息": "Meddelelser", "智能分析": "Intelligent analyse", @@ -1110,5 +1108,15 @@ "常规使用": "Regelmæssig anvendelse", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Når gateway er tændt, tryk og hold nulstillingsknappen i 5 sekunder, og klik Next, når indikator lys blinker skiftevist", "扫描设备": "Scan- enhed", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Sletning mislykkedes. Porten er måske offline. Vil du tvinge slette data?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Sletning mislykkedes. Porten er måske offline. Vil du tvinge slette data?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_de.json b/lan/lan_de.json index 8f257d7b..9b95837e 100644 --- a/lan/lan_de.json +++ b/lan/lan_de.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Alle Ihre Konto informationen werden DAUERHAFT von der Plattform entfernt und können nicht wieder hergestellt werden. Möchten Sie löschen?", "监控": "Monitor", "视频日志": "Video protokoll", - "网关设备": "Gateway", "开门器": "Türöffner", "面容开锁": "Gesicht öffnet sich", "开门方向设置": "Öffnungs richtung Set", @@ -778,7 +777,6 @@ "导出": "Export", "批量导出": "Batch-Export", "读取记录": "Rekorde auffrischen", - "手机需联网": "NeedNet", "设备": "Gerät", "消息": "Nachrichten", "智能分析": "Intelligente Analytik", @@ -1110,5 +1108,15 @@ "常规使用": "Regelmäßige Verwendung", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Nachdem das Gateway eingesc haltet ist, drücken und halten Sie die Reset-Taste für 5 Sekunden, und klicken Sie auf Weiter, wenn die Kontroll leuchte blinkt abwechselnd", "扫描设备": "Scan-Gerät", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Löschung fehl geschlagen. Das Gateway ist möglicher weise offline gegangen. Möchten Sie das Löschen der Daten erzwingen?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Löschung fehl geschlagen. Das Gateway ist möglicher weise offline gegangen. Möchten Sie das Löschen der Daten erzwingen?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_el.json b/lan/lan_el.json index 050fc964..6c459d12 100644 --- a/lan/lan_el.json +++ b/lan/lan_el.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Όλες οι πληροφορίες λογαριασμού σας θα αφαιρεθούν από την πλατφόρμα ΜΟΝΑ και δεν μπορούν να ανακτηθούν. Θέλετε να διαγραφείτε;", "监控": "Παρακολούθηση", "视频日志": "Καταγραφή βίντεο", - "网关设备": "Πύλη πύλης", "开门器": "Ανοιχτή πόρτας", "面容开锁": "Ξεκλείδωμα πρόσωπου", "开门方向设置": "Άνοιγμα σύνολο κατεύθυνσης", @@ -778,7 +777,6 @@ "导出": "Εξαγωγή", "批量导出": "Παρτίδα εξαγωγή", "读取记录": "Ανανέωση εγγραφής", - "手机需联网": "NeedNet", "设备": "Συσκευή", "消息": "Μηνύματα", "智能分析": "Ευφυής αναλυτικός", @@ -1110,5 +1108,15 @@ "常规使用": "Κανονική χρήση:", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Αφού ενεργοποιηθεί η πύλη, πατήστε και κρατήστε το κουμπί επαναφοράς για 5 δευτερόλεπτα, και κάντε κλικ Next όταν το φως δείκτη αναβοσβήνει εναλλάξα", "扫描设备": "Συσκευή σάρωσης", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Η διαγραφή απέτυχε. Η πύλη μπορεί να έχει εκτός λειτουργίας. Θέλετε να αναγκάσετε τη διαγραφή των δεδομένων;" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Η διαγραφή απέτυχε. Η πύλη μπορεί να έχει εκτός λειτουργίας. Θέλετε να αναγκάσετε τη διαγραφή των δεδομένων;", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_en.json b/lan/lan_en.json index 108785fa..2bc8eeaf 100644 --- a/lan/lan_en.json +++ b/lan/lan_en.json @@ -315,7 +315,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "All your Account information will be Removed from the Platform PERMANENTLY and cannot be Recovered.Do you want to Delete?", "监控": "Monitor", "视频日志": "Video Log", - "网关设备": "Gateway", "开门器": "Door Opener", "面容开锁": "Face Unlocks", "开门方向设置": "Opening Direction Set", @@ -787,7 +786,6 @@ "导出":"Export", "批量导出":"Batch export", "读取记录":"Refresh Records", - "手机需联网":"NeedNet", "设备":"Device", "消息":"Messages", "智能分析":"Intelligent analytics", @@ -1113,6 +1111,15 @@ "中功率": "Medium power", "常规使用": "Regular use", "扫描设备": "Scan device", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Deletion failed. The gateway may have gone offline. Do you want to force delete the data?" - + "删除失败,网关可能已经离线,是否强制删除该数据?": "Deletion failed. The gateway may have gone offline. Do you want to force delete the data?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } diff --git a/lan/lan_es.json b/lan/lan_es.json index 248e721c..79c49887 100644 --- a/lan/lan_es.json +++ b/lan/lan_es.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Toda la información de su cuenta se eliminará de la plataforma de forma permanente y no se podrá recuperar.", "监控": "Monitor", "视频日志": "Registro de vídeo", - "网关设备": "Puerta de enlace", "开门器": "Abrelatas de la puerta", "面容开锁": "Desbloquea la cara", "开门方向设置": "Conjunto de dirección de apertura", @@ -778,7 +777,6 @@ "导出": "Exportación", "批量导出": "Exportación de lotes", "读取记录": "Actualizar registros", - "手机需联网": "NeedNet", "设备": "Dispositivo", "消息": "Mensajes", "智能分析": "Analítica inteligente", @@ -1110,5 +1108,15 @@ "常规使用": "Uso regular", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Después de encender la puerta de enlace, mantenga presionado el botón de reinicio durante 5 segundos y haga clic en Siguiente cuando la luz indicadora parpadee alternativamente", "扫描设备": "Dispositivo de exploración", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Falló la eliminación. Es posible que la puerta de enlace se haya desconectado. ¿Desea forzar la eliminación de los datos?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Falló la eliminación. Es posible que la puerta de enlace se haya desconectado. ¿Desea forzar la eliminación de los datos?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_et.json b/lan/lan_et.json index 299d4c1d..23cbb933 100644 --- a/lan/lan_et.json +++ b/lan/lan_et.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Kogu Teie konto teave eemaldatakse platvormilt PERMANENTILT ja seda ei saa taastada.Kas soovite kustutada?", "监控": "Monitor", "视频日志": "Video logi", - "网关设备": "Väravatee", "开门器": "Ukseavaja", "面容开锁": "Nägu lahti lukustus", "开门方向设置": "Avava suuna komplektComment", @@ -778,7 +777,6 @@ "导出": "Eksport", "批量导出": "Partii eksportimine", "读取记录": "Värskenda salvestus", - "手机需联网": "NeedNet", "设备": "Seade", "消息": "Teated", "智能分析": "Intelligentne analüüs", @@ -1110,5 +1108,15 @@ "常规使用": "Regulaarne kasutamine", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Kui värav on sisse lülitatud, vajutage ja hoidke nuppu 5 sekundit, ja klõpsa Järgmine, kui indikaator valgus vilgub vaheldumisel", "扫描设备": "Skaneerimisseade", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Kustutamine nurjus. Värav võis välja lülitada. Kas soovid kustutada andmed?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Kustutamine nurjus. Värav võis välja lülitada. Kas soovid kustutada andmed?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_fi.json b/lan/lan_fi.json index 4b2fe7ae..9141b427 100644 --- a/lan/lan_fi.json +++ b/lan/lan_fi.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Kaikki tilitiedot poistetaan alustalta PERMANENTTI eikä niitä voi palauttaa.Haluatko poistaa?", "监控": "Monitori", "视频日志": "Videoloki", - "网关设备": "GatewayComment", "开门器": "Oviaukko", "面容开锁": "Kasvo avaa", "开门方向设置": "Avaava suunta", @@ -778,7 +777,6 @@ "导出": "Vienti", "批量导出": "Erän vienti", "读取记录": "Päivitä tiedostot", - "手机需联网": "NeedNet", "设备": "Laite", "消息": "Viestit", "智能分析": "Älykäs analytiikka", @@ -1110,5 +1108,15 @@ "常规使用": "Säännöllinen käyttö", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Kun portti on käytössä, paina ja pidä painiketta nollauspainiketta 5 sekunnin ajan, ja klikkaa Seuraava kun ilmaisin valo vilkkuu vuorotellensa", "扫描设备": "Skannauslaite", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Poisto epäonnistui. Portti on ehkä pois päältä. Haluatko pakottaa poistamaan tiedot?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Poisto epäonnistui. Portti on ehkä pois päältä. Haluatko pakottaa poistamaan tiedot?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_fr.json b/lan/lan_fr.json index 87e47a72..43debbe2 100644 --- a/lan/lan_fr.json +++ b/lan/lan_fr.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Toutes les informations de votre compte seront supprimées de la plate-forme de manière PERMANENTE et ne pourront pas être récupérées. Voulez-vous supprimer?", "监控": "Moniteur", "视频日志": "Journal vidéo", - "网关设备": "Passerelle", "开门器": "Ouvre-porte", "面容开锁": "Le visage se déverrouille", "开门方向设置": "Ensemble de direction d'ouverture", @@ -778,7 +777,6 @@ "导出": "Exportation", "批量导出": "Exportation par lots", "读取记录": "Rafraîchir les enregistrements", - "手机需联网": "NeedNet", "设备": "Appareil", "消息": "Messages", "智能分析": "Analyse intelligente", @@ -1110,5 +1108,15 @@ "常规使用": "Utilisation régulière", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Une fois la passerelle allumée, appuyez et maintenez enfoncé le bouton de réinitialisation pendant 5 secondes, puis cliquez sur Suivant lorsque le voyant clignote alternativement", "扫描设备": "Appareil de numérisation", - "删除失败,网关可能已经离线,是否强制删除该数据?": "La suppression a échoué. La passerelle est peut-être hors ligne. Voulez-vous forcer la suppression des données?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "La suppression a échoué. La passerelle est peut-être hors ligne. Voulez-vous forcer la suppression des données?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_he.json b/lan/lan_he.json index 7e7e4579..c0bd0c01 100644 --- a/lan/lan_he.json +++ b/lan/lan_he.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "כל פרטי החשבון שלך יוסר מהפלטפורמה לצמיתות ולא ניתן לשחזר. האם ברצונך למחוק?", "监控": "מוניטור", "视频日志": "יומן וידאו", - "网关设备": "שער", "开门器": "פותחן דלת", "面容开锁": "פותח פנים", "开门方向设置": "פתיחת כיוון", @@ -778,7 +777,6 @@ "导出": "יצוא", "批量导出": "יצוא אצווה", "读取记录": "ריענון רשומות", - "手机需联网": "נברשת", "设备": "מכשיר", "消息": "הודעות", "智能分析": "ניתוח חכם", @@ -1110,5 +1108,15 @@ "常规使用": "שימוש קבוע", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "לאחר השער מופעל, לחץ והחזק את כפתור איפוס עבור 5 שניות, ולחץ על הבא כאשר מחוון אור מהבהב לסירוגין", "扫描设备": "התקן סריקה", - "删除失败,网关可能已经离线,是否强制删除该数据?": "מחיקה נכשלה. ייתכן שהשער נעלם מהרשת. האם ברצונך לאלץ למחוק את הנתונים?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "מחיקה נכשלה. ייתכן שהשער נעלם מהרשת. האם ברצונך לאלץ למחוק את הנתונים?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_hk.json b/lan/lan_hk.json index 39083939..977e1f37 100644 --- a/lan/lan_hk.json +++ b/lan/lan_hk.json @@ -314,7 +314,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "您的所有账户信息将从平台上永久删除,且无法恢复。要删除吗?", "监控": "监控", "视频日志": "视频日志", - "网关设备": "网关", "开门器": "开门器", "面容开锁": "脸解锁", "开门方向设置": "开启方向集", @@ -786,7 +785,6 @@ "导出": "出口", "批量导出": "批量出口", "读取记录": "刷新记录", - "手机需联网": "NeedNet", "设备": "设备", "消息": "消息", "智能分析": "智能分析", @@ -1110,5 +1108,15 @@ "常规使用": "经常使用", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "待设备上电后,长按复位键5秒,指示灯交替闪烁后,单击“下一步”", "扫描设备": "扫描设备", - "删除失败,网关可能已经离线,是否强制删除该数据?": "删除失败。网关可能已经脱机。是否要强制删除数据?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "删除失败。网关可能已经脱机。是否要强制删除数据?", + "超级管理员英文": "超级管理员", + "授权管理员英文": "使管理", + "普通管理员英文": "普通用户", + "网关设备英文": "网关设备", + "手机需联网英文": "手机需联网", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_hr.json b/lan/lan_hr.json index 0260ecaa..d4dd8fd3 100644 --- a/lan/lan_hr.json +++ b/lan/lan_hr.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Sve informacije vašeg računa će biti uklonjene s platforme i neće se moći vratiti.Želite li izbrisati?", "监控": "Monitor", "视频日志": "Video dnevnik", - "网关设备": "Prolaz", "开门器": "Otvarač vrata", "面容开锁": "Otključa lice", "开门方向设置": "Smjer otvaranja", @@ -778,7 +777,6 @@ "导出": "Izvozi", "批量导出": "Izvoz serije", "读取记录": "Osvježi zapise", - "手机需联网": "NeedNet", "设备": "Uređaj", "消息": "Poruka servera:", "智能分析": "Inteligentna analiza", @@ -1110,5 +1108,15 @@ "常规使用": "Redovna upotreba", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Nakon što se prolaz ukljuèi, pritisnite i zadržite dugme za reset 5 sekundi, i kliknite Sljedeća kada svjetlost indikatora izmijeniti", "扫描设备": "Skeniraj uređaj", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Brisanje nije uspjelo. Prolaz je možda nestao. Želite li prisiliti brisati podatke?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Brisanje nije uspjelo. Prolaz je možda nestao. Želite li prisiliti brisati podatke?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_hu.json b/lan/lan_hu.json index 19496163..bed7ca9a 100644 --- a/lan/lan_hu.json +++ b/lan/lan_hu.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Az összes számlaadatot végleg eltávolítjuk a platformról, és nem lehet visszanyerni. szeretné törölni?", "监控": "Monitor", "视频日志": "Videó napló", - "网关设备": "Gateway", "开门器": "Ajtónyitó", "面容开锁": "Face kinyit", "开门方向设置": "Nyitási irány beállítás", @@ -778,7 +777,6 @@ "导出": "Export", "批量导出": "Batch export", "读取记录": "Refresh records", - "手机需联网": "Neednet", "设备": "Eszköz", "消息": "Üzenetek", "智能分析": "Intelligens analitika", @@ -1110,5 +1108,15 @@ "常规使用": "Rendszeres használat", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Miután az átjáró be van kapcsolva, nyomja meg és tartsa a reset gombot 5 másodpercig, és kattintson a következő gombra, amikor a jelző fény felváltva villog", "扫描设备": "Beolvasási eszköz", - "删除失败,网关可能已经离线,是否强制删除该数据?": "A törlés nem sikerült. Az átjáró lehet, hogy offline lett. Szeretné kényszeríteni az adatok törlését?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "A törlés nem sikerült. Az átjáró lehet, hogy offline lett. Szeretné kényszeríteni az adatok törlését?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_id.json b/lan/lan_id.json index 2ec41527..e494a7b5 100644 --- a/lan/lan_id.json +++ b/lan/lan_id.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Semua informasi akun Anda akan dihapus dari Platform permanen dan tidak dapat dipulihkan. Apakah Anda ingin menghapus?", "监控": "Monitor", "视频日志": "Log Video", - "网关设备": "Gateway", "开门器": "Pembuka pintu", "面容开锁": "Buka kunci wajah", "开门方向设置": "Set penunjuk arah", @@ -778,7 +777,6 @@ "导出": "Ekspor", "批量导出": "Batch ekspor", "读取记录": "Refresh rekaman", - "手机需联网": "NeedNet", "设备": "Perangkat", "消息": "Pesan", "智能分析": "Intelligent analytics", @@ -1110,5 +1108,15 @@ "常规使用": "Penggunaan biasa", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Setelah gateway menyala, tekan dan tahan tombol reset selama 5 detik, dan klik berikutnya ketika lampu indikator berkedip secara bersamaan", "扫描设备": "Perangkat Pindai", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Penghapusan gagal. Gateway mungkin telah offline. Ingin menghapus data?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Penghapusan gagal. Gateway mungkin telah offline. Ingin menghapus data?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_it.json b/lan/lan_it.json index faeda996..2434772c 100644 --- a/lan/lan_it.json +++ b/lan/lan_it.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Tutte le informazioni del tuo account verranno rimosse dalla piattaforma PERMANENTAMENTE e non potranno essere recuperate. Vuoi eliminare?", "监控": "Monitor", "视频日志": "Registro video", - "网关设备": "Gateway", "开门器": "Apriporta", "面容开锁": "Il viso si sblocca", "开门方向设置": "Set di direzione di apertura", @@ -778,7 +777,6 @@ "导出": "Esportazione", "批量导出": "Esportazione in batch", "读取记录": "Aggiorna i record", - "手机需联网": "NeedNet", "设备": "Dispositivo", "消息": "Messaggi", "智能分析": "Analisi intelligente", @@ -1110,5 +1108,15 @@ "常规使用": "Uso regolare", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Dopo aver acceso il gateway, tenere premuto il pulsante di ripristino per 5 secondi e fare clic su Avanti quando l'indicatore luminoso lampeggia alternativamente", "扫描设备": "Dispositivo di scansione", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Eliminazione non riuscita. Il gateway potrebbe essere andato offline. Vuoi forzare l'eliminazione dei dati?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Eliminazione non riuscita. Il gateway potrebbe essere andato offline. Vuoi forzare l'eliminazione dei dati?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_ja.json b/lan/lan_ja.json index 4e1801c0..be431bac 100644 --- a/lan/lan_ja.json +++ b/lan/lan_ja.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "すべてのアカウント情報は完全にプラットフォームから削除され、回復できません。削除しますか?", "监控": "モニター", "视频日志": "ビデオログ", - "网关设备": "ゲートウェイ", "开门器": "ドアオープナー", "面容开锁": "顔のロック解除", "开门方向设置": "オープニング方向セット", @@ -778,7 +777,6 @@ "导出": "エクスポート", "批量导出": "一括エクスポート", "读取记录": "レコードの更新", - "手机需联网": "ニードネット", "设备": "デバイス", "消息": "メッセージ", "智能分析": "インテリジェント分析", @@ -1110,5 +1108,15 @@ "常规使用": "通常の使用", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "ゲートウェイの電源がオンになった後、リセットボタンを5秒間押し続け、インジケーターライトが交互に点滅したら [次へ] をクリックします。", "扫描设备": "スキャン装置", - "删除失败,网关可能已经离线,是否强制删除该数据?": "削除に失敗しました。ゲートウェイがオフラインになった可能性があります。強制的にデータを削除しますか?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "削除に失敗しました。ゲートウェイがオフラインになった可能性があります。強制的にデータを削除しますか?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_keys.json b/lan/lan_keys.json index 1babbe1b..a26d6864 100755 --- a/lan/lan_keys.json +++ b/lan/lan_keys.json @@ -317,7 +317,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?", "监控": "监控", "视频日志": "视频日志", - "网关设备": "网关设备", "开门器": "开门器", "面容开锁": "面容开锁", "开门方向设置": "开门方向设置", @@ -1112,5 +1111,15 @@ "中功率": "中功率", "常规使用": "常规使用", "扫描设备": "扫描设备", - "删除失败,网关可能已经离线,是否强制删除该数据?": "删除失败,网关可能已经离线,是否强制删除该数据?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "删除失败,网关可能已经离线,是否强制删除该数据?", + "超级管理员英文": "超级管理员英文", + "授权管理员英文": "授权管理员英文", + "普通管理员英文": "普通管理员英文", + "网关设备英文": "网关设备英文", + "手机需联网英文": "手机需联网英文", + "年简称": "年简称", + "月简称": "月简称", + "日简称": "日简称", + "时简称": "时简称", + "分简称": "分简称" } diff --git a/lan/lan_kk.json b/lan/lan_kk.json index 65b7b013..1c8871ae 100644 --- a/lan/lan_kk.json +++ b/lan/lan_kk.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Тіркелгіңіздің барлық мәліметі Платформадан өшірілген және қайта жоғалтылмайды. Өшіруге қалайсыз ба?", "监控": "Монитор", "视频日志": "Видео журналы", - "网关设备": "Шлюз", "开门器": "Қашықтығы ашу", "面容开锁": "Өшірілгендер", "开门方向设置": "Ашату жолы жинағы", @@ -778,7 +777,6 @@ "导出": "Экспорттау", "批量导出": "Бағдарлама экспорттау", "读取记录": "Жаңарту", - "手机需联网": "NeedNet", "设备": "Құрылғысы", "消息": "Хаттар", "智能分析": "Интелгент аналітикасы", @@ -1110,5 +1108,15 @@ "常规使用": "Қалыпты қолданылсын", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Келесі періңізнен соң, ысырып тасымалдау батырмасын басып 5 секунд басыңыз, Индикаторның жарықты ауыстырғанда, келесі басыңыз", "扫描设备": "Сканер құрылғысы", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Өшіру жаңылысы. Келесі жіберді. Деректерді өшіргіңіз келе ме?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Өшіру жаңылысы. Келесі жіберді. Деректерді өшіргіңіз келе ме?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_ko.json b/lan/lan_ko.json index 547c9091..589b5633 100644 --- a/lan/lan_ko.json +++ b/lan/lan_ko.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "모든 계정 정보는 플랫폼에서 자동으로 삭제되며 복구 할 수 없습니다. 삭제 하시겠습니까?", "监控": "모니터", "视频日志": "비디오 로그", - "网关设备": "게이트웨이", "开门器": "도어 오프너", "面容开锁": "얼굴 잠금 해제", "开门方向设置": "오프닝 방향 세트", @@ -778,7 +777,6 @@ "导出": "수출", "批量导出": "배치 수출", "读取记录": "레코드 새로 고침", - "手机需联网": "니드넷", "设备": "장치", "消息": "메시지", "智能分析": "지능형 분석", @@ -1110,5 +1108,15 @@ "常规使用": "정사이즈 사용", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "게이트웨이의 전원이 켜진 후 5 초 동안 리셋 버튼을 누르고 누르고 표시등이 번갈아 깜박이면 다음 을 클릭하십시오.", "扫描设备": "스캔 장치", - "删除失败,网关可能已经离线,是否强制删除该数据?": "삭제가 실패했습니다. 게이트웨이가 오프라인 상태일 수 있다. 강제로 데이터 삭제를 하시겠습니까?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "삭제가 실패했습니다. 게이트웨이가 오프라인 상태일 수 있다. 강제로 데이터 삭제를 하시겠습니까?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_lt.json b/lan/lan_lt.json index b986a3ed..84e203e1 100644 --- a/lan/lan_lt.json +++ b/lan/lan_lt.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Visa jūsų paskyros informacija bus pašalinta iš platformos visam laikui ir jų negalima atkurti. ar norite ištrinti?", "监控": "Monitorius", "视频日志": "Vaizdo žurnalas", - "网关设备": "Vartai", "开门器": "Durų atidarytuvas", "面容开锁": "Veidas atrakinamas", "开门方向设置": "Atidarymo kryptis nustatytas", @@ -778,7 +777,6 @@ "导出": "Eksporto", "批量导出": "Paketo eksportas", "读取记录": "Atnaujinti įrašus", - "手机需联网": "Neednet", "设备": "Įtaisas", "消息": "Pranešimai", "智能分析": "Intelektuali analizė", @@ -1110,5 +1108,15 @@ "常规使用": "Reguliarus naudojimas", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Įjungus vartus, 5 sekundes paspauskite ir palaikykite reset mygtuką ir spustelėkite toliau, kai indikatoriaus lemputė mirksi pakaitomis.", "扫描设备": "Nuskaitymo įrenginys", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Ištrynimas nepavyko. Vartai gali būti neprisijungę. Ar norite priversti ištrinti duomenis?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Ištrynimas nepavyko. Vartai gali būti neprisijungę. Ar norite priversti ištrinti duomenis?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_ms.json b/lan/lan_ms.json index 9adef58c..d6b27146 100644 --- a/lan/lan_ms.json +++ b/lan/lan_ms.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Semua maklumat akaun anda akan dikeluarkan dari Platform secara kekal dan tidak dapat dipulihkan. Adakah anda ingin memadam?", "监控": "Monitor", "视频日志": "Log Video", - "网关设备": "Pintu masuk", "开门器": "Pembuka pintu", "面容开锁": "Membuka muka", "开门方向设置": "Set arah pembukaan", @@ -778,7 +777,6 @@ "导出": "Eksport", "批量导出": "Eksport Batch", "读取记录": "Rekod-rekod segar semula", - "手机需联网": "NeedNet", "设备": "Peranti", "消息": "Mesej", "智能分析": "Analisis pintar", @@ -1110,5 +1108,15 @@ "常规使用": "Penggunaan biasa", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Selepas pintu masuk dihidupkan, tekan dan tahan butang reset selama 5 saat, dan klik seterusnya apabila lampu penunjuk berkelip bergantian", "扫描设备": "Imbas peranti", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Penghapusan gagal. Pintu masuk mungkin telah pergi di luar talian. Adakah anda mahu memaksa memadam data?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Penghapusan gagal. Pintu masuk mungkin telah pergi di luar talian. Adakah anda mahu memaksa memadam data?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_nl.json b/lan/lan_nl.json index 1df7d3e7..82ed9aac 100644 --- a/lan/lan_nl.json +++ b/lan/lan_nl.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Alle accountgegevens worden PERMANENT van het Platform verwijderd en kunnen niet worden teruggevonden. Wilt u Verwijderen?", "监控": "Monitor", "视频日志": "Videologboek", - "网关设备": "Gateway", "开门器": "Deuropener", "面容开锁": "Gezicht ontgrendelt", "开门方向设置": "Openingsrichtingsset", @@ -778,7 +777,6 @@ "导出": "Uitvoer", "批量导出": "Batch export", "读取记录": "Records vernieuwen", - "手机需联网": "Neednet", "设备": "Apparaat", "消息": "Berichten", "智能分析": "Intelligente analyses", @@ -1110,5 +1108,15 @@ "常规使用": "Regelmatig gebruik", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Nadat de gateway is ingeschakeld, houdt u de resetknop 5 seconden ingedrukt en klikt u op Volgende wanneer het indicatielampje afwisselend knippert", "扫描设备": "Scan apparaat", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Verwijdering is mislukt. De gateway is mogelijk offline gegaan. Wilt u de gegevens forceren verwijderen?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Verwijdering is mislukt. De gateway is mogelijk offline gegaan. Wilt u de gegevens forceren verwijderen?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_pl.json b/lan/lan_pl.json index f0b2f14f..7ca0add8 100644 --- a/lan/lan_pl.json +++ b/lan/lan_pl.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Wszystkie informacje o koncie zostaną usunięte z platformy i nie będzie można ich odzyskać. Czy chcesz usunąć?", "监控": "Monitor", "视频日志": "Dziennik wideo", - "网关设备": "Brama", "开门器": "Otwieracz do drzwi", "面容开锁": "Odblokowywanie twarzy", "开门方向设置": "Zestaw kierunku otwierania", @@ -778,7 +777,6 @@ "导出": "Eksport", "批量导出": "Eksport partii", "读取记录": "Odśwież rekordy", - "手机需联网": "NeedNet", "设备": "Urządzenie", "消息": "Wiadomości", "智能分析": "Inteligentna analityka", @@ -1110,5 +1108,15 @@ "常规使用": "Regularne stosowanie", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Po włączeniu bramy naciśnij i przytrzymaj przycisk resetowania przez 5 sekund i kliknij przycisk Dalej, gdy wskaźnik miga na przemian", "扫描设备": "Urządzenie skanujące", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Usunięcie nie powiodło się. Brama mogła zostać wyłączona. Czy chcesz wymusić usunięcie danych?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Usunięcie nie powiodło się. Brama mogła zostać wyłączona. Czy chcesz wymusić usunięcie danych?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_pt.json b/lan/lan_pt.json index 8a12675b..5660f8cf 100644 --- a/lan/lan_pt.json +++ b/lan/lan_pt.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Todas as informações da sua conta serão removidas da plataforma PERMANENTEMENTE e não poderão ser recuperadas. Deseja excluir?", "监控": "Monitore", "视频日志": "Log Vídeo", - "网关设备": "Gateway", "开门器": "Abridor porta", "面容开锁": "Rosto desbloqueia", "开门方向设置": "Conjunto Direção Abertura", @@ -778,7 +777,6 @@ "导出": "Exportação", "批量导出": "Exportação lote", "读取记录": "Atualizar Registros", - "手机需联网": "NeedNet", "设备": "Dispositivo", "消息": "Mensagens", "智能分析": "Análise inteligente", @@ -1110,5 +1108,15 @@ "常规使用": "Uso regular", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Depois que o gateway estiver ligado, pressione e segure o botão de reset por 5 segundos e clique em Next quando a luz indicadora pisca alternadamente", "扫描设备": "Digitalizar dispositivo", - "删除失败,网关可能已经离线,是否强制删除该数据?": "A eliminação falhou. O gateway pode ter ficado offline. Você quer forçar a exclusão dos dados?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "A eliminação falhou. O gateway pode ter ficado offline. Você quer forçar a exclusão dos dados?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_ro.json b/lan/lan_ro.json index 8b3258b0..18926d79 100644 --- a/lan/lan_ro.json +++ b/lan/lan_ro.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Toate informațiile contului dumneavoastră vor fi înlăturate de pe platformă și nu pot fi recuperate. Doriți să ștergeți?", "监控": "Monitor", "视频日志": "Jurnal video", - "网关设备": "GatewayComment", "开门器": "Deschizător de uși", "面容开锁": "Fața deblochează", "开门方向设置": "Set de direcție de deschidere", @@ -778,7 +777,6 @@ "导出": "Exportă", "批量导出": "Export pe lot", "读取记录": "Reîmprospătește înregistrările", - "手机需联网": "NeedNet", "设备": "Dispozitive", "消息": "Mesaje", "智能分析": "Analitică inteligentă", @@ -1110,5 +1108,15 @@ "常规使用": "Utilizare regulată", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "După ce poarta este pornită, apăsați și țineți butonul de resetare timp de 5 secunde, și faceți clic pe Următor atunci când lumina indicatorului se aprinde alternativ.", "扫描设备": "Dispozitiv de scanare", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Ștergerea a eșuat. Poarta poate s-a oprit. Doriți să forțați ștergerea datelor?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Ștergerea a eșuat. Poarta poate s-a oprit. Doriți să forțați ștergerea datelor?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_ru.json b/lan/lan_ru.json index 43aa4f45..5fb8f68b 100644 --- a/lan/lan_ru.json +++ b/lan/lan_ru.json @@ -180,7 +180,7 @@ "隐藏无效开锁权限": "Скрыть недопустимый доступ", "APP开锁时需手机连网的锁": "Замки требующие телефона онлайн", "增值服务": "Услуги", - "关于": "Касательно", + "关于": "О нас", "退出": "Выход", "删除账号": "Удалить аккаунт", "个人信息": "Информация счета", @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Вся информация о вашей учетной записи будет удалена с платформы ПОСТОЯННО и не может быть восстановлена. Вы хотите удалить?", "监控": "Монитор", "视频日志": "Видео журнал", - "网关设备": "Шлюз", "开门器": "Дверь открывалка", "面容开锁": "Лицо разблокирует", "开门方向设置": "Набор направления открытия", @@ -778,7 +777,6 @@ "导出": "Экспорт", "批量导出": "Пакетный экспорт", "读取记录": "Обновить записи", - "手机需联网": "Ниднет", "设备": "Устройство", "消息": "Сообщения", "智能分析": "Интеллектуальная аналитика", @@ -1110,5 +1108,15 @@ "常规使用": "Регулярное использование", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "После включения шлюза нажмите и удерживайте кнопку сброса в течение 5 секунд и нажмите «Далее», когда индикатор попеременно начнет мигать.", "扫描设备": "Устройство сканирования", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Ошибка удаления. Возможно, шлюз ушел в автономный режим. Хотите ли вы принудительно удалить данные?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Ошибка удаления. Возможно, шлюз ушел в автономный режим. Хотите ли вы принудительно удалить данные?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_sk.json b/lan/lan_sk.json index d7b46780..f1d7df2d 100644 --- a/lan/lan_sk.json +++ b/lan/lan_sk.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Všetky informácie o vašom účte budú natrvalo odstránené z platformy a nemôžu byť obnovené. chcete odstrániť?", "监控": "Monitor", "视频日志": "Video log", - "网关设备": "Brána", "开门器": "Otvárač dverí", "面容开锁": "Tvár odomkne", "开门方向设置": "Nastaviť smer otvorenia", @@ -778,7 +777,6 @@ "导出": "Export", "批量导出": "Export šarže", "读取记录": "Refresh records", - "手机需联网": "Neednet", "设备": "Zariadenie", "消息": "Správy", "智能分析": "Inteligentná analýza", @@ -1110,5 +1108,15 @@ "常规使用": "Pravidelné použitie", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Po zapnutí brány stlačte a podržte tlačidlo reset po dobu 5 sekúnd a kliknite na ďalšie, keď indikátorové svetlo záblesky striedavo", "扫描设备": "Skenovanie zariadenia", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Vymazanie sa nepodarilo. Brána môže ísť offline. Chcete vynútiť odstránenie údajov?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Vymazanie sa nepodarilo. Brána môže ísť offline. Chcete vynútiť odstránenie údajov?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_sr_cyrl.json b/lan/lan_sr_cyrl.json index eaf1375b..be13221a 100644 --- a/lan/lan_sr_cyrl.json +++ b/lan/lan_sr_cyrl.json @@ -181,7 +181,7 @@ "隐藏无效开锁权限": "Сакриј неважећи приступ", "APP开锁时需手机连网的锁": "Браве које захтевају телефон на мрежи", "增值服务": "Услуге", - "关于": "Povodom", + "关于": "O nama", "退出": "Одјавити се", "删除账号": "Избриши налог", "个人信息": "Информације о налогу", @@ -314,7 +314,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Сви подаци о вашем налогу ће бити трајно уклоњени са платформе и не могу се Рецоверед.До желите да избришете?", "监控": "Монитор", "视频日志": "Видео Дневник", - "网关设备": "Пролаз", "开门器": "Отварач врата", "面容开锁": "Откључавање лица", "开门方向设置": "Отварање Правац Сет", @@ -786,7 +785,6 @@ "导出": "Извоз", "批量导出": "Серијски извоз", "读取记录": "Освежите записе", - "手机需联网": "Претраживање", "设备": "Уређај", "消息": "Поруке", "智能分析": "Интелигентна аналитика", @@ -1110,5 +1108,15 @@ "常规使用": "Редовна употреба", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Након што је гатеваи укључен, притисните и држите дугме за ресетовање за 5 секунди, и кликните Следећи када индикатор трепери наизменично", "扫描设备": "Уређај за скенирање", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Брисање није успело. Гатеваи је можда отишао ван мреже. Да ли желите да присилите брисање података?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Брисање није успело. Гатеваи је можда отишао ван мреже. Да ли желите да присилите брисање података?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_sv.json b/lan/lan_sv.json index c284f4da..0a1bbc5b 100644 --- a/lan/lan_sv.json +++ b/lan/lan_sv.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "All information från dina konto kommer att tas bort från plattformen PERMANENTLYT och kan inte återställas. Vill du ta bort?", "监控": "Övervakare", "视频日志": "Videologg", - "网关设备": "Gateway", "开门器": "Dörröppnare", "面容开锁": "Ansiktet upplåsas", "开门方向设置": "Öppningsriktning", @@ -778,7 +777,6 @@ "导出": "Exportering", "批量导出": "Export från sats", "读取记录": "Uppdatera poster", - "手机需联网": "NeedNet", "设备": "Enheten", "消息": "Meddelanden", "智能分析": "Intelligent analys", @@ -1110,5 +1108,15 @@ "常规使用": "Regelbunden användning", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "När gateway är på, tryck och håll omställningsknappen i 5 sekunder, och klicka Nästa när indikatorljuset blinkar växelvist", "扫描设备": "Söka enheter", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Borttagning misslyckades. Porten kan ha gått offline. Vill du tvinga bort data?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Borttagning misslyckades. Porten kan ha gått offline. Vill du tvinga bort data?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_th.json b/lan/lan_th.json index 73c491b8..94dda514 100644 --- a/lan/lan_th.json +++ b/lan/lan_th.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "ข้อมูลบัญชีทั้งหมดของคุณจะถูกลบออกจากแพลตฟอร์มอย่างถาวรและไม่สามารถกู้คืนได้คุณต้องการลบหรือไม่?", "监控": "จอภาพสำหรับตรวจสอบ", "视频日志": "บันทึกวิดีโอบันทึก", - "网关设备": "เกตเวย์เกตเวย์", "开门器": "ที่เปิดประตู", "面容开锁": "ปลดล็อคใบหน้า", "开门方向设置": "ชุดเปิดทิศทาง", @@ -778,7 +777,6 @@ "导出": "ส่งออกจากต่างประเทศ", "批量导出": "ชุดส่งออก", "读取记录": "รีเฟรชระเบียน", - "手机需联网": "ตาข่ายปักลาย", "设备": "อุปกรณ์สำหรับเชื่อมต่อ", "消息": "ข้อความต่างๆ", "智能分析": "การวิเคราะห์อัจฉริยะ", @@ -1110,5 +1108,15 @@ "常规使用": "ใช้เป็นประจำ", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "หลังจากเปิดเกตเวย์แล้วให้กดปุ่มรีเซ็ตค้างไว้5วินาทีและคลิกถัดไปเมื่อไฟแสดงสถานะกะพริบสลับกัน", "扫描设备": "อุปกรณ์สแกน", - "删除失败,网关可能已经离线,是否强制删除该数据?": "การลบล้มเหลวเกตเวย์อาจออฟไลน์ไปแล้วคุณต้องการบังคับให้ลบข้อมูลหรือไม่?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "การลบล้มเหลวเกตเวย์อาจออฟไลน์ไปแล้วคุณต้องการบังคับให้ลบข้อมูลหรือไม่?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_tr.json b/lan/lan_tr.json index ee69bc05..cd306451 100644 --- a/lan/lan_tr.json +++ b/lan/lan_tr.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Tüm hesap bilgileriniz platformdan kalıcı olarak kaldırılacak ve kurtarılamayacaktır. silmek ister misiniz?", "监控": "Monitör", "视频日志": "Video günlüğü", - "网关设备": "Ağ geçidi", "开门器": "Kapı açacağı", "面容开锁": "Yüz kilidini açar", "开门方向设置": "Açılış yönü seti", @@ -778,7 +777,6 @@ "导出": "Ihracat", "批量导出": "Toplu ihracat", "读取记录": "Kayıtları yenileyin", - "手机需联网": "Neednet", "设备": "Cihaz", "消息": "Mesajlar", "智能分析": "Akıllı analiz", @@ -1110,5 +1108,15 @@ "常规使用": "Düzenli kullanım", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Ağ geçidi açıldıktan sonra, sıfırlama düğmesine 5 saniye basılı tutun ve gösterge ışığı dönüşümlü olarak yanıp söndüğünde İleri'ye tıklayın.", "扫描设备": "Tarama cihazı", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Silme başarısız oldu. Ağ geçidi çevrimdışı geçmiş olabilir. Verileri silmeye zorlamak ister misiniz?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Silme başarısız oldu. Ağ geçidi çevrimdışı geçmiş olabilir. Verileri silmeye zorlamak ister misiniz?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_tw.json b/lan/lan_tw.json index 5e2e0575..38ea07af 100644 --- a/lan/lan_tw.json +++ b/lan/lan_tw.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "您的所有帳戶信息都將從平台中永久刪除,並且無法恢復。 是否要刪除?", "监控": "顯示器", "视频日志": "視頻日誌", - "网关设备": "網關", "开门器": "開門器", "面容开锁": "面部解鎖", "开门方向设置": "打開方向設置", @@ -778,7 +777,6 @@ "导出": "出口", "批量导出": "批量導出", "读取记录": "刷新記錄", - "手机需联网": "NeedNet", "设备": "設備", "消息": "消息", "智能分析": "智能分析", @@ -1110,5 +1108,16 @@ "常规使用": "經常使用", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "網關通電後,按住reset按鈕5秒鐘,當指示燈交替閃爍時單擊Next", "扫描设备": "掃描設備", - "删除失败,网关可能已经离线,是否强制删除该数据?": "刪除失敗。 網關可能已脫機。 是否要強制刪除數據?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "刪除失敗。 網關可能已脫機。 是否要強制刪除數據?", + "超级管理员英文": "超級管理員", + "授权管理员英文": "授權管理員", + "普通管理员英文": "普通用戶", + "网关设备英文": "網關設備", + "手机需联网英文": "手機需要聯網", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" + } \ No newline at end of file diff --git a/lan/lan_uk.json b/lan/lan_uk.json index 239316e6..18d523a5 100644 --- a/lan/lan_uk.json +++ b/lan/lan_uk.json @@ -314,7 +314,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Вся інформація вашого Облікового запису буде видалена з Платформи НАЗАВЖДИ і не може бути Recovered.Do ви хочете Видалити?", "监控": "Монітор", "视频日志": "Відео журнал", - "网关设备": "Шлюз", "开门器": "Відкривач дверей", "面容开锁": "Розблокування по обличчю", "开门方向设置": "Встановлено напрямок відкривання", @@ -786,7 +785,6 @@ "导出": "Експорт", "批量导出": "Пакетний експорт", "读取记录": "Оновити записи", - "手机需联网": "Мережа NeedNet", "设备": "Пристрій", "消息": "Повідомлення", "智能分析": "Інтелектуальна аналітика", @@ -1110,5 +1108,15 @@ "常规使用": "Регулярне використання", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Після ввімкнення шлюзу натисніть і утримуйте кнопку скидання протягом 5 секунд, а потім натисніть «Далі», коли індикатор почне блимати по черзі", "扫描设备": "Сканування пристрою", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Видалення не вдалося. Можливо, шлюз перейшов в автономний режим. Ви хочете примусово видалити дані?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Видалення не вдалося. Можливо, шлюз перейшов в автономний режим. Ви хочете примусово видалити дані?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_vi.json b/lan/lan_vi.json index c39b0f23..3fac30ad 100644 --- a/lan/lan_vi.json +++ b/lan/lan_vi.json @@ -313,7 +313,6 @@ "删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?": "Tất cả thông tin tài khoản của bạn sẽ bị xóa vĩnh viễn khỏi nền tảng và không thể phục hồi. Bạn có muốn xóa?", "监控": "Màn hình", "视频日志": "Nhật ký video", - "网关设备": "Cổng", "开门器": "Dụng cụ mở cửa", "面容开锁": "Mở khóa mặt", "开门方向设置": "Bộ hướng mở", @@ -778,7 +777,6 @@ "导出": "Xuất khẩu", "批量导出": "Hàng loạt xuất khẩu", "读取记录": "Làm mới hồ sơ", - "手机需联网": "Neednet", "设备": "Thiết bị", "消息": "Tin nhắn", "智能分析": "Phân Tích thông minh", @@ -1110,5 +1108,15 @@ "常规使用": "Sử dụng thường xuyên", "网关通电后,长按重置按钮5秒,指示灯交替闪烁时点击下一步": "Sau khi cổng được bật, Nhấn và giữ nút đặt lại trong 5 giây và Nhấp vào tiếp theo khi đèn báo nhấp nháy luân phiên", "扫描设备": "Thiết bị quét", - "删除失败,网关可能已经离线,是否强制删除该数据?": "Xóa thất bại. Cổng có thể đã tắt. Bạn có muốn buộc xóa dữ liệu không?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "Xóa thất bại. Cổng có thể đã tắt. Bạn có muốn buộc xóa dữ liệu không?", + "超级管理员英文": "Super Admin", + "授权管理员英文": "Make admin", + "普通管理员英文": "Ordinary user", + "网关设备英文": "Gateway", + "手机需联网英文": "NeedNet", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } \ No newline at end of file diff --git a/lan/lan_zh.json b/lan/lan_zh.json index a293b024..20d398f7 100755 --- a/lan/lan_zh.json +++ b/lan/lan_zh.json @@ -1112,5 +1112,15 @@ "中功率": "中功率", "常规使用": "常规使用", "扫描设备": "扫描设备", - "删除失败,网关可能已经离线,是否强制删除该数据?": "删除失败,网关可能已经离线,是否强制删除该数据?" + "删除失败,网关可能已经离线,是否强制删除该数据?": "删除失败,网关可能已经离线,是否强制删除该数据?", + "超级管理员英文": "超级管理员", + "授权管理员英文": "授权管理员", + "普通管理员英文": "普通管理员", + "网关设备英文": "网关设备", + "手机需联网英文": "手机需联网", + "年简称": "Y", + "月简称": "M", + "日简称": "D", + "时简称": "H", + "分简称": "M" } diff --git a/lib/app.dart b/lib/app.dart index c81290a1..fad7b31d 100755 --- a/lib/app.dart +++ b/lib/app.dart @@ -10,7 +10,6 @@ import 'package:star_lock/main/lockMian/lockMain/lockMain_logic.dart'; import 'package:star_lock/tools/appFirstEnterHandle.dart'; import 'package:star_lock/tools/app_manager.dart'; import 'package:star_lock/tools/bindings/app_binding.dart'; -import 'package:star_lock/tools/change_language_format.dart'; import 'package:star_lock/tools/storage.dart'; import 'package:star_lock/translations/app_dept.dart'; @@ -21,6 +20,7 @@ import 'baseWidget.dart'; import 'tools/appRouteObserver.dart'; import 'tools/store_service.dart'; +import 'translations/current_locale_tool.dart'; class MyApp extends StatefulWidget { MyApp({required this.isLogin, GlobalKey? key}) : super(key: key); @@ -62,36 +62,26 @@ class _MyAppState extends State with WidgetsBindingObserver, BaseWidget { // localeResolutionCallback用于在启动时动态确定应该使用哪种语言和地区。 localeResolutionCallback: (Locale? locale, Iterable supportedLocales) { - if (widget.isLogin) { - // 登录之后调用存储的语言 - if (StoreService.to.getLanguageCode()!.isNotEmpty) { - locale = appDept.deptSupportedLocales - .where((Locale element) => - element.toString() == StoreService.to.getLanguageCode()) - .first; - } else { - // 如果没储存则调用系统的语言 - locale = Get.deviceLocale; - } - } else { - // 没登录之前调用系统的语言 - locale = Get.deviceLocale; - } - locale = ChangeLanguageFormat.convertLocale(locale!); - return supportedLocales.contains(locale) - ? locale - : supportedLocales.first; + AppLog.log( + 'System device locale: ${Get.deviceLocale} locale:$locale'); + // if (widget.isLogin) { + // 登录之后调用存储的语言 + locale = CurrentLocaleTool.getCurrentLocale(); + // } else { + // // 没登录之前调用系统的语言 + // locale = Get.deviceLocale; + // } + locale = CurrentLocaleTool.convertLocale(locale); + AppLog.log('localeResolutionCallback locale: $locale'); + AppManager() + .setLanCode(code: '${locale.languageCode}_${locale.countryCode}'); + return Locale(locale.languageCode, locale.countryCode); }, // 用来指定应用当前使用的语言和地区。它定义了应用在启动时加载的默认语言环境。 - locale: StoreService.to.getLanguageCode()!.isNotEmpty - ? appDept.deptSupportedLocales - .where((Locale element) => - element.toString() == StoreService.to.getLanguageCode()) - .first - : Get.deviceLocale, + locale: CurrentLocaleTool.getCurrentLocale(), // locale: Get.deviceLocale, // fallbackLocale用于指定在无法找到匹配的语言时,应用应该使用的默认语言和地区。 - fallbackLocale: Get.deviceLocale, + fallbackLocale: const Locale('en', 'US'), theme: ThemeData( scaffoldBackgroundColor: const Color(0xFFF6F6F6), backgroundColor: const Color(0xFFF6F6F6), diff --git a/lib/appRouters.dart b/lib/appRouters.dart index 12fbb302..1c460c84 100755 --- a/lib/appRouters.dart +++ b/lib/appRouters.dart @@ -21,6 +21,7 @@ import 'package:star_lock/main/lockDetail/lockDetail/lockDetail_main_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/catEyeSet/catEyeCustomMode/catEyeCustomMode_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/catEyeSet/videoSlot/videoSlot_page.dart'; +import 'package:star_lock/main/lockDetail/lockSet/double_lock_link/double_lock_link_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/faceUnlock/faceUnlock_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/liveVideo/liveVideo_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/motorPower/motorPower_page.dart'; @@ -35,6 +36,7 @@ import 'package:star_lock/main/lockDetail/messageWarn/msgNotification/msgNotific import 'package:star_lock/main/lockDetail/messageWarn/msgNotification/nDaysUnopened/nDaysUnopened_page.dart'; import 'package:star_lock/main/lockDetail/messageWarn/msgNotification/openDoorNotify/openDoorNotify_page.dart'; import 'package:star_lock/main/lockDetail/messageWarn/notificationMode/notificationMode_page.dart'; +import 'package:star_lock/main/lockDetail/monitoring/star_chart_h264/star_chart_page.dart'; import 'package:star_lock/main/lockDetail/palm/addPalm/addPalm_page.dart'; import 'package:star_lock/main/lockDetail/palm/palmList/palmList_page.dart'; import 'package:star_lock/main/lockDetail/passwordKey/passwordKeyDetailChangeDate/passwordKeyDetailChangeDate_page.dart'; @@ -42,6 +44,7 @@ import 'package:star_lock/main/lockMian/lockMain/xhj/lockMain_xhj_page.dart'; import 'package:star_lock/mine/about/webviewShow_page.dart'; import 'package:star_lock/mine/mine/safeVerify/safeVerify_page.dart'; import 'package:star_lock/mine/minePersonInfo/minePersonInfoEmail/mineBindPhoneOrEmail_page.dart'; +import 'package:star_lock/mine/minePersonInfo/minePersonInfoPage/minePersonInfo_entity.dart'; import 'package:star_lock/mine/minePersonInfo/minePersonInfoViewSafetyProblem/minePersonInfoViewSafetyProblem_page.dart'; import 'package:star_lock/mine/mineSet/amazon_alexa/amazon_alexa_page.dart'; import 'package:star_lock/mine/mineSet/authorizedAdministrator/administratorAssociationLock/administratorAssociationLock_page.dart'; @@ -509,6 +512,8 @@ abstract class Routers { static const String login = '/login'; //登录 static const String amazonAlexaPage = '/amazonAlexaPage'; //AmazonAlexa static const String googleHomePage = '/googleHomePage'; //GoogleHome + static const String doubleLockLinkPage = '/doubleLockLinkPage'; //双锁联动 + static const String starChartPage = '/starChartPage'; //星图 } abstract class AppRouters { @@ -1183,5 +1188,10 @@ abstract class AppRouters { GetPage( name: Routers.gatewayGetWifiListPage, page: () => const GatewayGetWifiListPage()), + GetPage( + name: Routers.doubleLockLinkPage, + page: () => const DoubleLockLinkPage()), + GetPage( + name: Routers.starChartPage, page: () => const StarChartPage()), ]; } diff --git a/lib/blue/io_protocol/io_configuringWifi.dart b/lib/blue/io_protocol/io_configuringWifi.dart index 99ac0e29..8cc0142d 100755 --- a/lib/blue/io_protocol/io_configuringWifi.dart +++ b/lib/blue/io_protocol/io_configuringWifi.dart @@ -17,6 +17,7 @@ class SenderConfiguringWifiCommand extends SenderProtocol { this.userID, this.ssid, this.password, + this.peerId, this.numberOfServers, this.listOfServers, this.numberOfPhone, @@ -31,6 +32,7 @@ class SenderConfiguringWifiCommand extends SenderProtocol { String? userID; String? ssid; String? password; + String? peerId; int? numberOfServers; List? listOfServers; int? numberOfPhone; @@ -44,7 +46,7 @@ class SenderConfiguringWifiCommand extends SenderProtocol { @override String toString() { return 'SenderConfiguringWifiCommand{keyID: $keyID, userID: $userID, ' - 'ssid: $ssid, password: $password, numberOfServers: $numberOfServers, ' + 'ssid: $ssid, password: $password,peerId: $peerId, numberOfServers: $numberOfServers, ' 'listOfServers: $listOfServers, numberOfPhone: $numberOfPhone, ' 'listOfPhone: $listOfPhone, token: $token, needAuthor: $needAuthor, ' 'publicKey: $publicKey, privateKey: $privateKey}'; @@ -87,6 +89,11 @@ class SenderConfiguringWifiCommand extends SenderProtocol { subData.addAll(utf8.encode(password!)); subData = getFixedLengthList(subData, 20 - passwordLength); + //peerId 44 + final int peerIdLength = utf8.encode(peerId!).length; + subData.addAll(utf8.encode(peerId!)); + subData = getFixedLengthList(subData, 44 - peerIdLength); + // NumberOfServers subData.add(numberOfServers!); diff --git a/lib/blue/sender_manage.dart b/lib/blue/sender_manage.dart index 9255ef15..d9880c73 100755 --- a/lib/blue/sender_manage.dart +++ b/lib/blue/sender_manage.dart @@ -854,6 +854,7 @@ class IoSenderManage { required String? userID, required String? ssid, required String? password, + required String? peerId, required int? numberOfServers, required List? listOfServers, required int? numberOfPhone, @@ -869,6 +870,7 @@ class IoSenderManage { userID: userID, ssid: ssid, password: password, + peerId: peerId, numberOfServers: numberOfServers, listOfServers: listOfServers, numberOfPhone: numberOfPhone, diff --git a/lib/login/login/starLock_login_logic.dart b/lib/login/login/starLock_login_logic.dart index 5ff5ba81..82426458 100755 --- a/lib/login/login/starLock_login_logic.dart +++ b/lib/login/login/starLock_login_logic.dart @@ -61,12 +61,14 @@ class StarLockLoginLogic extends BaseGetXController { Storage.saveLoginData(entity.data); Storage.setBool(saveIsVip, entity.data!.isVip == 1); //如已有星图配置则保存 无需重复注册节点及重复绑定 - final Starchart starChart = entity.data!.starchart!; - await Storage.saveStarChartRegisterNodeInfo(StarChartRegisterNodeEntity( - peer: PeerData( - id: starChart.starchartId, - publicKey: starChart.starchartPeerPublicKey, - privateKey: starChart.starchartPeerPrivateKey))); + if (entity.data!.starchart != null) { + final Starchart starChart = entity.data!.starchart!; + Storage.saveStarChartRegisterNodeInfo(StarChartRegisterNodeEntity( + peer: PeerData( + id: starChart.starchartId, + publicKey: starChart.starchartPeerPublicKey, + privateKey: starChart.starchartPeerPrivateKey))); + } eventBus.fire(MineInfoChangeRefreshUI()); if (Get.isRegistered()) { Get.find().getStarLockInfo(isUnShowLoading: true); diff --git a/lib/login/login/starLock_login_page.dart b/lib/login/login/starLock_login_page.dart index ea62eec7..2b9be8e9 100755 --- a/lib/login/login/starLock_login_page.dart +++ b/lib/login/login/starLock_login_page.dart @@ -7,8 +7,8 @@ import 'package:star_lock/login/login/starLock_login_state.dart'; import 'package:star_lock/talk/startChart/handle/impl/udp_talk_ping_handler.dart'; import 'package:star_lock/talk/startChart/start_chart_manage.dart'; import 'package:star_lock/tools/appFirstEnterHandle.dart'; -import 'package:star_lock/tools/wechat/customer_tool.dart'; import 'package:star_lock/tools/storage.dart'; +import 'package:star_lock/tools/wechat/customer_tool.dart'; import '../../appRouters.dart'; import '../../app_settings/app_colors.dart'; @@ -50,14 +50,16 @@ class _StarLockLoginPageState extends State { haveBack: false, backgroundColor: AppColors.mainColor, actionsList: [ - IconButton( - onPressed: () { - WechatManageTool.getAppInfo(CustomerTool.openCustomerService); - }, - icon: const Icon( - Icons.support_agent, - color: Colors.white, - )), + if (state.isChina == true) + IconButton( + onPressed: () { + WechatManageTool.getAppInfo( + CustomerTool.openCustomerService); + }, + icon: const Icon( + Icons.support_agent, + color: Colors.white, + )), TextButton( child: Text( '注册'.tr, diff --git a/lib/login/login/starLock_login_state.dart b/lib/login/login/starLock_login_state.dart index 6edb1563..41bc0fef 100755 --- a/lib/login/login/starLock_login_state.dart +++ b/lib/login/login/starLock_login_state.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import '../../translations/current_locale_tool.dart'; + class StarLockLoginState { StarLockLoginState() { // emailOrPhone.value = StoreService.to.getLastUserAccount() as String; @@ -15,6 +17,16 @@ class StarLockLoginState { /// 获取翻译后的国家名称 String get countryName => countryKey.value.tr; + /// + bool get isChina { + if (CurrentLocaleTool.convertLocale(Get.deviceLocale!) == + const Locale('zh', 'CN')) { + return true; + } else { + return false; + } + } + RxString emailOrPhone = ''.obs; RxString pwd = ''.obs; RxBool canNext = false.obs; diff --git a/lib/login/login/starLock_login_xhj_page.dart b/lib/login/login/starLock_login_xhj_page.dart index 76e06922..8138db92 100755 --- a/lib/login/login/starLock_login_xhj_page.dart +++ b/lib/login/login/starLock_login_xhj_page.dart @@ -5,8 +5,8 @@ import 'package:get/get.dart'; import 'package:star_lock/flavors.dart'; import 'package:star_lock/login/login/starLock_login_state.dart'; import 'package:star_lock/tools/appFirstEnterHandle.dart'; -import 'package:star_lock/tools/wechat/customer_tool.dart'; import 'package:star_lock/tools/storage.dart'; +import 'package:star_lock/tools/wechat/customer_tool.dart'; import '../../appRouters.dart'; import '../../app_settings/app_colors.dart'; @@ -63,15 +63,16 @@ class _StarLockLoginPageState extends State { ), ), ), - IconButton( - onPressed: () { - WechatManageTool.getAppInfo( - CustomerTool.openCustomerService); - }, - icon: Icon( - Icons.support_agent, - color: AppColors.mainColor, - )), + if (state.isChina == true) + IconButton( + onPressed: () { + WechatManageTool.getAppInfo( + CustomerTool.openCustomerService); + }, + icon: Icon( + Icons.support_agent, + color: AppColors.mainColor, + )), ], ), SizedBox(height: 30.h), diff --git a/lib/login/selectCountryRegion/selectCountryRegion_page.dart b/lib/login/selectCountryRegion/selectCountryRegion_page.dart index c429a934..08d9de36 100755 --- a/lib/login/selectCountryRegion/selectCountryRegion_page.dart +++ b/lib/login/selectCountryRegion/selectCountryRegion_page.dart @@ -10,6 +10,7 @@ import 'package:star_lock/tools/baseGetXController.dart'; import '../../app_settings/app_colors.dart'; import '../../tools/keySearchWidget.dart'; import '../../tools/titleAppBar.dart'; +import '../../translations/current_locale_tool.dart'; import 'common/index.dart'; class SelectCountryRegionPage extends StatefulWidget { @@ -24,11 +25,14 @@ class _SelectCountryRegionPageState extends State { List countriesList = []; List topCountriesList = []; TextEditingController searchController = TextEditingController(); + String currentLanguage = ''; @override void initState() { super.initState(); + currentLanguage = CurrentLocaleTool.getCurrentLocaleString(); + SuspensionUtil.setShowSuspensionStatus( countriesList.cast()); Future.delayed(const Duration(milliseconds: 20), getCountriesListRequest); @@ -154,7 +158,9 @@ class _SelectCountryRegionPageState extends State { final String tag = model.getSuspensionTag(); return Utils.getSusItem(context, tag); }, - indexBarData: const ['★', ...kIndexBarData], + indexBarData: currentLanguage == 'zh_CN' + ? const ['★', ...kIndexBarData] + : [], ), ), ], diff --git a/lib/main.dart b/lib/main.dart index 119528f6..10a2339e 100755 --- a/lib/main.dart +++ b/lib/main.dart @@ -12,6 +12,7 @@ import 'package:star_lock/mine/about/debug/debug_tool.dart'; import 'package:star_lock/network/api_provider.dart'; import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/network/start_chart_api.dart'; +import 'package:star_lock/talk/startChart/appLifecycle_observer.dart'; import 'package:star_lock/tools/bugly/bugly_tool.dart'; import 'package:star_lock/tools/device_info_service.dart'; import 'package:star_lock/tools/platform_info_services.dart'; @@ -29,6 +30,10 @@ FutureOr main() async { FlutterBugly.postCatchedException(() async { WidgetsFlutterBinding.ensureInitialized(); + // 创建并注册 AppLifecycleObserver(用于程序是否进入后台的监听) + AppLifecycleObserver appLifecycleObserver = AppLifecycleObserver(); + WidgetsBinding.instance.addObserver(appLifecycleObserver); + await _setCommonServices(); // 设置国际化信息 @@ -76,7 +81,8 @@ Future _setCommonServices() async { //关于隐私协议的初始化 Future privacySDKInitialization() async { - UmengCommonSdk.initCommon('671244cf80464b33f6df9648', '671244ae80464b33f6df9646', 'Product'); + UmengCommonSdk.initCommon( + '671244cf80464b33f6df9648', '671244ae80464b33f6df9646', 'Product'); UmengCommonSdk.setPageCollectionModeManual(); await Get.putAsync(() => PlatformInfoService().init()); @@ -85,27 +91,3 @@ Future privacySDKInitialization() async { final XSJPushProvider jpushProvider = XSJPushProvider(); await jpushProvider.initJPushService(); } - -void checkChinese() { - // 获取当前脚本的目录 - final String scriptDir = path.dirname(Platform.script.path); - - // 遍历这个目录下的所有 .dart 文件 - findChineseCharacters(Directory(scriptDir)); -} - -void findChineseCharacters(Directory directory) { - final List files = directory.listSync(recursive: true); - for (FileSystemEntity file in files) { - if (file is File && file.path.endsWith('.dart')) { - final String content = file.readAsStringSync(encoding: utf8); - if (hasChineseCharacters(content)) { - print('Found Chinese characters in ${file.path}'); - } - } - } -} - -bool hasChineseCharacters(String input) { - return RegExp(r'[\u4e00-\u9fa5]').hasMatch(input); -} diff --git a/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_page.dart b/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_page.dart index 6e1013b5..c9e4ff0f 100755 --- a/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_page.dart +++ b/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_page.dart @@ -1,8 +1,6 @@ -import 'package:expandable/expandable.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:flutter/widgets.dart'; import 'package:flutter_native_contact_picker/flutter_native_contact_picker.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; @@ -109,12 +107,13 @@ class _AuthorizedAdminPageState extends State Widget keyInfoWidget() { return Column( children: [ - CommonItem( - leftTitel: '接收者'.tr, - rightTitle: '', - isHaveLine: true, - isHaveRightWidget: true, - rightWidget: getTFWidget(true, '请输入手机号或者邮箱'.tr, 1)), + // CommonItem( + // leftTitel: '接收者'.tr, + // rightTitle: '', + // isHaveLine: true, + // isHaveRightWidget: true, + // rightWidget: getTFWidget(true, '请输入手机号或者邮箱'.tr, 1)), + perpetualKeyWidget('接收者'.tr, '请输入手机号或者邮箱'.tr), CommonItem( leftTitel: '国家/地区'.tr, rightTitle: '', @@ -192,6 +191,88 @@ class _AuthorizedAdminPageState extends State ); } + Widget perpetualKeyWidget(String titleStr, String rightTitle) { + return Column( + children: [ + Container( + height: 65.h, + padding: EdgeInsets.only(left: 20.w, right: 20.w), + color: Colors.white, + child: Row( + children: [ + Text(titleStr, style: TextStyle(fontSize: 22.sp)), + SizedBox(width: 6.w), + Expanded( + child: TextField( + controller: logic.getCurrentController(1), + //输入框一行 + maxLines: 1, + inputFormatters: [ + FilteringTextInputFormatter.deny('\n'), + LengthLimitingTextInputFormatter(30), + ], + // controller: _controller, + autofocus: false, + textAlign: TextAlign.end, + decoration: InputDecoration( + //输入里面输入文字内边距设置 + hintText: rightTitle, + hintStyle: TextStyle(fontSize: 22.sp), + focusedBorder: const OutlineInputBorder( + borderSide: + BorderSide(width: 0, color: Colors.transparent)), + disabledBorder: const OutlineInputBorder( + borderSide: + BorderSide(width: 0, color: Colors.transparent)), + enabledBorder: const OutlineInputBorder( + borderSide: + BorderSide(width: 0, color: Colors.transparent)), + border: const OutlineInputBorder( + borderSide: + BorderSide(width: 0, color: Colors.transparent)), + contentPadding: const EdgeInsets.symmetric(vertical: 0), + ), + style: TextStyle( + fontSize: 22.sp, textBaseline: TextBaseline.alphabetic), + ), + ), + SizedBox( + width: 10.w, + ), + Container( + width: 32.w, + height: 32.w, + decoration: const BoxDecoration( + color: Colors.white, + image: DecorationImage( + image: AssetImage('images/icon_addressBook.png'), + fit: BoxFit.fill), + ), + alignment: Alignment.center, + child: InkWell( + onTap: () async { + final Contact? currentContact = + await logic.state.contactPicker.selectContact(); + logic.state.contact = currentContact!; + if (currentContact.phoneNumbers!.isNotEmpty) { + logic.state.emailOrPhoneController.text = currentContact + .phoneNumbers![0] + .replaceAll(RegExp(r'\s+\b|\b\s'), ''); + } + if (currentContact.fullName!.isNotEmpty) { + logic.state.keyNameController.text = + currentContact.fullName!; + } + }, + ), + ) + ], + ), + ) + ], + ); + } + // 实名认证 Widget keyOnlyManageWidget() { return Column( diff --git a/lib/main/lockDetail/card/cardList/cardList_page.dart b/lib/main/lockDetail/card/cardList/cardList_page.dart index bbaf9657..705d5c8c 100755 --- a/lib/main/lockDetail/card/cardList/cardList_page.dart +++ b/lib/main/lockDetail/card/cardList/cardList_page.dart @@ -244,8 +244,6 @@ class _CardListPageState extends State with RouteAware { children: [ Flexible( child: Text(showTime, - maxLines: 1, - overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 18.sp, color: AppColors.placeholderTextColor)), diff --git a/lib/main/lockDetail/electronicKey/sendElectronicKey/sendElectronicKey/view/sendElectronicKeyView_page.dart b/lib/main/lockDetail/electronicKey/sendElectronicKey/sendElectronicKey/view/sendElectronicKeyView_page.dart index 51cc15b5..4aa39e86 100755 --- a/lib/main/lockDetail/electronicKey/sendElectronicKey/sendElectronicKey/view/sendElectronicKeyView_page.dart +++ b/lib/main/lockDetail/electronicKey/sendElectronicKey/sendElectronicKey/view/sendElectronicKeyView_page.dart @@ -1,4 +1,3 @@ - import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -22,7 +21,6 @@ import 'package:star_lock/tools/showTipView.dart'; import 'package:star_lock/tools/submitBtn.dart'; class SendElectronicKeyView extends StatefulWidget { - SendElectronicKeyView({required this.type, Key? key}) : super(key: key); String type; @@ -105,16 +103,17 @@ class _SendElectronicKeyViewState extends State return Column( children: [ // Container(height: 10.h), - CommonItem( - leftTitel: '接收者'.tr, - rightTitle: '', - isHaveLine: true, - isHaveRightWidget: true, - rightWidget: getTFWidget( - true, - '请输入手机号或者邮箱'.tr, - 1, - logic)), + // CommonItem( + // leftTitel: '接收者'.tr, + // rightTitle: '', + // isHaveLine: true, + // isHaveRightWidget: true, + // rightWidget: getTFWidget( + // true, + // '请输入手机号或者邮箱'.tr, + // 1, + // logic)), + perpetualKeyWidget(logic, '接收者'.tr, '请输入手机号或者邮箱'.tr), CommonItem( leftTitel: '国家/地区'.tr, rightTitle: '', @@ -142,14 +141,95 @@ class _SendElectronicKeyViewState extends State leftTitel: '姓名'.tr, rightTitle: '', isHaveRightWidget: true, - rightWidget: getTFWidget( - false, '请输入'.tr, 2, logic, - maxSize: 50)), + rightWidget: getTFWidget(false, '请输入'.tr, 2, logic, maxSize: 50)), Container(height: 10.h), ], ); } + Widget perpetualKeyWidget( + SendElectronicKeyViewLogic logic, String titleStr, String rightTitle) { + return Column( + children: [ + Container( + height: 65.h, + padding: EdgeInsets.only(left: 20.w, right: 20.w), + color: Colors.white, + child: Row( + children: [ + Text(titleStr, style: TextStyle(fontSize: 22.sp)), + SizedBox(width: 6.w), + Expanded( + child: TextField( + controller: logic.getCurrentController(1), + //输入框一行 + maxLines: 1, + inputFormatters: [ + FilteringTextInputFormatter.deny('\n'), + LengthLimitingTextInputFormatter(30), + ], + // controller: _controller, + autofocus: false, + textAlign: TextAlign.end, + decoration: InputDecoration( + //输入里面输入文字内边距设置 + hintText: rightTitle, + hintStyle: TextStyle(fontSize: 22.sp), + focusedBorder: const OutlineInputBorder( + borderSide: + BorderSide(width: 0, color: Colors.transparent)), + disabledBorder: const OutlineInputBorder( + borderSide: + BorderSide(width: 0, color: Colors.transparent)), + enabledBorder: const OutlineInputBorder( + borderSide: + BorderSide(width: 0, color: Colors.transparent)), + border: const OutlineInputBorder( + borderSide: + BorderSide(width: 0, color: Colors.transparent)), + contentPadding: const EdgeInsets.symmetric(vertical: 0), + ), + style: TextStyle( + fontSize: 22.sp, textBaseline: TextBaseline.alphabetic), + ), + ), + SizedBox( + width: 10.w, + ), + Container( + width: 32.w, + height: 32.w, + decoration: const BoxDecoration( + color: Colors.white, + image: DecorationImage( + image: AssetImage('images/icon_addressBook.png'), + fit: BoxFit.fill), + ), + alignment: Alignment.center, + child: InkWell( + onTap: () async { + final Contact? currentContact = + await logic.state.contactPicker.selectContact(); + logic.state.contact = currentContact!; + if (currentContact.phoneNumbers!.isNotEmpty) { + logic.state.emailOrPhoneController.text = currentContact + .phoneNumbers![0] + .replaceAll(RegExp(r'\s+\b|\b\s'), ''); + } + if (currentContact.fullName!.isNotEmpty) { + logic.state.keyNameController.text = + currentContact.fullName!; + } + }, + ), + ) + ], + ), + ) + ], + ); + } + // 生效失效时间 Widget keyTimeWidget(SendElectronicKeyViewLogic logic) { return Column( @@ -163,7 +243,8 @@ class _SendElectronicKeyViewState extends State final PDuration selectDate = PDuration.parse( DateTime.parse(logic.state.timeLimitBeginTime)); Pickers.showDatePicker(context, - selectDate: selectDate, mode: DateMode.YMDHM, onConfirm: (PDuration p) { + selectDate: selectDate, + mode: DateMode.YMDHM, onConfirm: (PDuration p) { logic.state.timeLimitBeginTime = DateTool().getYMDHNDateString(p, 1); logic.update(); @@ -177,7 +258,8 @@ class _SendElectronicKeyViewState extends State final PDuration selectDate = PDuration.parse( DateTime.tryParse(logic.state.timeLimitEndTime)); Pickers.showDatePicker(context, - selectDate: selectDate, mode: DateMode.YMDHM, onConfirm: (PDuration p) { + selectDate: selectDate, + mode: DateMode.YMDHM, onConfirm: (PDuration p) { logic.state.timeLimitEndTime = DateTool().getYMDHNDateString(p, 1); logic.update(); @@ -237,14 +319,14 @@ class _SendElectronicKeyViewState extends State isHaveDirection: true, isHaveLine: true, action: () async { - final result = - await Get.toNamed(Routers.seletKeyCyclicDatePage, arguments: { - 'validityValue': logic.state.weekdaysList, - 'starDate': logic.state.cycleBeginTime, - 'endDate': logic.state.cycleEndTime, - 'starTime': logic.state.effectiveDateTime, - 'endTime': logic.state.failureDateTime - }); + final result = await Get.toNamed(Routers.seletKeyCyclicDatePage, + arguments: { + 'validityValue': logic.state.weekdaysList, + 'starDate': logic.state.cycleBeginTime, + 'endDate': logic.state.cycleEndTime, + 'starTime': logic.state.effectiveDateTime, + 'endTime': logic.state.failureDateTime + }); if (result != null && result.isNotEmpty) { logic.state.weekdaysList = result['validityValue']; logic.state.cycleBeginTime = result['starDate']; @@ -418,7 +500,8 @@ class _SendElectronicKeyViewState extends State ), if (logic.emailOrPhone != null) OutLineBtn( - btnName: logic.state.userNameType.value == 1 ? '短信通知'.tr : '邮件通知'.tr, + btnName: + logic.state.userNameType.value == 1 ? '短信通知'.tr : '邮件通知'.tr, onClick: () { Get.toNamed(Routers.sendEmailNotificationPage, arguments: { diff --git a/lib/main/lockDetail/fingerprint/fingerprintList/fingerprintList_page.dart b/lib/main/lockDetail/fingerprint/fingerprintList/fingerprintList_page.dart index ad3f11c2..acfb8e9a 100755 --- a/lib/main/lockDetail/fingerprint/fingerprintList/fingerprintList_page.dart +++ b/lib/main/lockDetail/fingerprint/fingerprintList/fingerprintList_page.dart @@ -251,8 +251,6 @@ class _FingerprintListPageState extends State children: [ Flexible( child: Text(showTime, - maxLines: 1, - overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 18.sp, color: AppColors.placeholderTextColor)), diff --git a/lib/main/lockDetail/lockDetail/lockDetail_page.dart b/lib/main/lockDetail/lockDetail/lockDetail_page.dart index 730b3794..6009bfeb 100755 --- a/lib/main/lockDetail/lockDetail/lockDetail_page.dart +++ b/lib/main/lockDetail/lockDetail/lockDetail_page.dart @@ -109,9 +109,23 @@ class _LockDetailPageState extends State SingleChildScrollView( child: Column( children: [ - SizedBox( - height: isShowTip ? 70.h : 10.h, + Visibility( + visible: isShowTip, + child: Container( + // height: 30.h, + width: 1.sw, + color: const Color(0xFFFBEFD4), + padding: EdgeInsets.only(top: 8.h, bottom: 8.h), + child: Text( + "${"钥匙将在".tr}${DateTool().compareTimeGetDaysFromNow(state.keyInfos.value.endDate!)}${"天后失效".tr}", + maxLines: 2, + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.center, + style: TextStyle( + color: const Color(0xffCBA74B), fontSize: 24.sp)), + ), ), + SizedBox(height: 10.h), Padding( padding: EdgeInsets.symmetric(horizontal: 24.w), child: Text( @@ -152,23 +166,6 @@ class _LockDetailPageState extends State ], ), ), - Visibility( - visible: isShowTip, - child: Container( - // height: 30.h, - color: const Color(0xFFFBEFD4), - padding: EdgeInsets.only(top: 8.h, bottom: 8.h), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "${"钥匙将在".tr}${DateTool().compareTimeGetDaysFromNow(state.keyInfos.value.endDate!)}${"天后失效".tr}", - style: TextStyle( - color: const Color(0xffCBA74B), fontSize: 24.sp)) - ], - ), - ), - ), Visibility( visible: state.iSClosedUnlockSuccessfulPopup.value, // visible: true, @@ -508,17 +505,17 @@ class _LockDetailPageState extends State , child: Container( // height: 30.h, + width: 1.sw, color: const Color(0xFFFBEFD4), - padding: EdgeInsets.only(top: 8.h, bottom: 8.h), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "${"钥匙将在".tr}${DateTool().compareTimeGetDaysFromNow(state.keyInfos.value.endDate!)}${"天后失效".tr}", - style: TextStyle( - color: const Color(0xffCBA74B), fontSize: 24.sp)) - ], - ), + padding: + EdgeInsets.only(top: 8.h, bottom: 8.h, right: 10.w, left: 10.h), + child: Text( + "${"钥匙将在".tr}${DateTool().compareTimeGetDaysFromNow(state.keyInfos.value.endDate!)}${"天后失效".tr}", + maxLines: 2, + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.center, + style: + TextStyle(color: const Color(0xffCBA74B), fontSize: 24.sp)), ), ), Stack(children: [ @@ -808,10 +805,10 @@ class _LockDetailPageState extends State SizedBox(width: 6.w), Text( state.keyInfos.value.isLockOwner == 1 - ? '超级管理员'.tr + ? '超级管理员英文'.tr : (state.keyInfos.value.keyRight == 1 - ? '授权管理员'.tr - : '普通用户'.tr), + ? '授权管理员英文'.tr + : '普通用户英文'.tr), style: TextStyle( fontSize: 20.sp, color: AppColors.darkGrayTextColor), ), @@ -832,7 +829,7 @@ class _LockDetailPageState extends State ), SizedBox(width: 6.w), Text( - '网关设备'.tr, + '网关设备英文'.tr, style: TextStyle( fontSize: 20.sp, color: state.keyInfos.value.hasGateway == 1 @@ -855,7 +852,7 @@ class _LockDetailPageState extends State ), SizedBox(width: 6.w), Text( - '手机需联网'.tr, + '手机需联网英文'.tr, style: TextStyle( fontSize: 20.sp, color: state.isOpenLockNeedOnline.value == 1 diff --git a/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart b/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart index 3049a26c..eb6f1ccc 100755 --- a/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart +++ b/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart @@ -1,4 +1,3 @@ - import 'dart:async'; import 'dart:io'; @@ -8,6 +7,7 @@ import 'package:network_info_plus/network_info_plus.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:star_lock/login/login/entity/LoginEntity.dart'; import 'package:star_lock/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifiEntity.dart'; +import 'package:star_lock/talk/startChart/entity/star_chart_register_node_entity.dart'; import 'package:star_lock/tools/baseGetXController.dart'; import '../../../../../blue/blue_manage.dart'; @@ -21,24 +21,26 @@ import '../../../../../tools/eventBusEventManage.dart'; import '../../../../../tools/storage.dart'; import 'configuringWifi_state.dart'; -class ConfiguringWifiLogic extends BaseGetXController{ +class ConfiguringWifiLogic extends BaseGetXController { final ConfiguringWifiState state = ConfiguringWifiState(); Future getWifiLockServiceIpAndPort() async { - final ConfiguringWifiEntity entity = await ApiRepository.to.getWifiLockServiceIpAndPort(); - if(entity.errorCode! == 0){ + final ConfiguringWifiEntity entity = + await ApiRepository.to.getWifiLockServiceIpAndPort(); + if (entity.errorCode! == 0) { state.configuringWifiEntity.value = entity; } } - Future updateNetworkInfo() async{ + Future updateNetworkInfo() async { final LoginEntity entity = await ApiRepository.to.updateNetworkInfo( lockId: state.lockSetInfoData.value.lockId!, - network:state.wifiNameController.text, + network: state.wifiNameController.text, ); - if(entity.errorCode!.codeIsSuccessful){ - showToast('配网成功'.tr, something:(){ - eventBus.fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value)); + if (entity.errorCode!.codeIsSuccessful) { + showToast('配网成功'.tr, something: () { + eventBus + .fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value)); Get.close(2); }); } @@ -46,10 +48,12 @@ class ConfiguringWifiLogic extends BaseGetXController{ // 监听设备返回的数据 late StreamSubscription _replySubscription; + void _initReplySubscription() { - _replySubscription = EventBusManager().eventBus!.on().listen((Reply reply) async { + _replySubscription = + EventBusManager().eventBus!.on().listen((Reply reply) async { // WIFI配网结果 - if(reply is SenderConfiguringWifiReply) { + if (reply is SenderConfiguringWifiReply) { _replySenderConfiguringWifi(reply); } }); @@ -59,7 +63,7 @@ class ConfiguringWifiLogic extends BaseGetXController{ Future _replySenderConfiguringWifi(Reply reply) async { final int status = reply.data[5]; - switch(status){ + switch (status) { case 0x00: //成功 state.sureBtnState.value = 0; @@ -69,19 +73,26 @@ class ConfiguringWifiLogic extends BaseGetXController{ break; case 0x06: //无权限 - final List? privateKey = await Storage.getStringList(saveBluePrivateKey); - final List getPrivateKeyList = changeStringListToIntList(privateKey!); + final List? privateKey = + await Storage.getStringList(saveBluePrivateKey); + final List getPrivateKeyList = + changeStringListToIntList(privateKey!); - final List? publicKey = await Storage.getStringList(saveBluePublicKey); - final List publicKeyDataList = changeStringListToIntList(publicKey!); + final List? publicKey = + await Storage.getStringList(saveBluePublicKey); + final List publicKeyDataList = + changeStringListToIntList(publicKey!); final List tokenData = reply.data.sublist(7, 10); final List saveStrList = changeIntListToStringList(tokenData); Storage.setStringList(saveBlueToken, saveStrList); final List serversList = []; - for(int i = 0; i itemList = item.serviceIp!.split('.'); for (String element in itemList) { serversList.add(int.parse(element)); @@ -94,6 +105,11 @@ class ConfiguringWifiLogic extends BaseGetXController{ serversList.add(type2); } + final StarChartRegisterNodeEntity? registerNodeEntity = + await Storage.getStarChartRegisterNodeInfo(); + // 获取app用户的peerId + String appPeerId = registerNodeEntity?.peer?.id ?? ''; + final List uidList = [Storage.getUid().toString()]; IoSenderManage.senderConfiguringWifiCommand( keyID: state.lockSetInfoData.value.lockBasicInfo!.keyId.toString(), @@ -108,6 +124,7 @@ class ConfiguringWifiLogic extends BaseGetXController{ needAuthor: 1, publicKey: publicKeyDataList, privateKey: getPrivateKeyList, + peerId: appPeerId, ); break; @@ -123,42 +140,51 @@ class ConfiguringWifiLogic extends BaseGetXController{ // 点击配置wifi Future senderConfiguringWifiAction() async { - if(state.wifiNameController.text.isEmpty){ + if (state.wifiNameController.text.isEmpty) { showToast('请输入wifi名称'.tr); return; } - if(state.sureBtnState.value == 1){ + if (state.sureBtnState.value == 1) { return; } state.sureBtnState.value = 1; showEasyLoading(); - showBlueConnetctToastTimer(action: (){ + showBlueConnetctToastTimer(action: () { dismissEasyLoading(); state.sureBtnState.value = 0; }); - BlueManage().blueSendData(BlueManage().connectDeviceName, (BluetoothConnectionState connectionState) async { - if (connectionState == BluetoothConnectionState.connected){ - final List? privateKey = await Storage.getStringList(saveBluePrivateKey); - final List getPrivateKeyList = changeStringListToIntList(privateKey!); + BlueManage().blueSendData(BlueManage().connectDeviceName, + (BluetoothConnectionState connectionState) async { + if (connectionState == BluetoothConnectionState.connected) { + final List? privateKey = + await Storage.getStringList(saveBluePrivateKey); + final List getPrivateKeyList = + changeStringListToIntList(privateKey!); - final List? publicKey = await Storage.getStringList(saveBluePublicKey); - final List publicKeyDataList = changeStringListToIntList(publicKey!); + final List? publicKey = + await Storage.getStringList(saveBluePublicKey); + final List publicKeyDataList = + changeStringListToIntList(publicKey!); final List? token = await Storage.getStringList(saveBlueToken); final List getTokenList = changeStringListToIntList(token!); final List serversList = []; - for(int i = 0; i itemList = item.serviceIp!.split('.'); for (String element in itemList) { serversList.add(int.parse(element)); } - }else{ - final List addresses = await InternetAddress.lookup(item.serviceIp!); + } else { + final List addresses = + await InternetAddress.lookup(item.serviceIp!); final List itemList = addresses.first.address.split('.'); for (String element in itemList) { serversList.add(int.parse(element)); @@ -174,11 +200,17 @@ class ConfiguringWifiLogic extends BaseGetXController{ final String? uidStr = await Storage.getUid(); final List uidList = [uidStr.toString()]; + + final StarChartRegisterNodeEntity? registerNodeEntity = + await Storage.getStarChartRegisterNodeInfo(); + // 获取app用户的peerId + String appPeerId = registerNodeEntity?.peer?.id ?? ''; IoSenderManage.senderConfiguringWifiCommand( keyID: state.lockSetInfoData.value.lockBasicInfo!.keyId.toString(), userID: await Storage.getUid(), ssid: state.wifiNameController.text, password: state.wifiPWDController.text, + peerId: appPeerId, numberOfServers: state.configuringWifiEntity.value.data!.serviceNum, listOfServers: serversList, numberOfPhone: uidList.length, @@ -192,7 +224,7 @@ class ConfiguringWifiLogic extends BaseGetXController{ dismissEasyLoading(); cancelBlueConnetctToastTimer(); state.sureBtnState.value = 0; - if(state.ifCurrentScreen.value == true){ + if (state.ifCurrentScreen.value == true) { showBlueConnetctToast(); } } @@ -200,6 +232,7 @@ class ConfiguringWifiLogic extends BaseGetXController{ } final NetworkInfo _networkInfo = NetworkInfo(); + Future getWifiName() async { String ssid = ''; ssid = (await _networkInfo.getWifiName())!; @@ -211,17 +244,19 @@ class ConfiguringWifiLogic extends BaseGetXController{ ///定位权限 Future checkLocationPermission() async { final PermissionStatus value = await locationPermission(); - final bool allow = value != PermissionStatus.permanentlyDenied && value != PermissionStatus.denied; + final bool allow = value != PermissionStatus.permanentlyDenied && + value != PermissionStatus.denied; return allow; } - Future locationPermission() async => Permission.location.request(); + Future locationPermission() async => + Permission.location.request(); @override void onReady() { super.onReady(); - if(state.wifiName.value.isEmpty){ + if (state.wifiName.value.isEmpty) { getWifiName().then((String value) { state.wifiNameController.text = value; }); diff --git a/lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_logic.dart b/lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_logic.dart new file mode 100644 index 00000000..8652afa1 --- /dev/null +++ b/lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_logic.dart @@ -0,0 +1,54 @@ +import 'package:get/get.dart'; +import 'package:star_lock/main/lockDetail/lockSet/double_lock_link/double_lock_link_state.dart'; +import 'package:star_lock/main/lockMian/lockMain/lockMain_logic.dart'; +import 'package:star_lock/mine/mineSet/appUnlockNeedMobileNetworkingLock/selectLockListEntity.dart'; +import 'package:star_lock/network/api_repository.dart'; +import 'package:star_lock/tools/baseGetXController.dart'; + +class DoubleLockLinkLogic extends BaseGetXController { + final DoubleLockLinkState state = DoubleLockLinkState(); + + //请求锁列表 + Future mockNetworkDataRequest() async { + final SelectLockListEntity entity = await ApiRepository.to + .selectLockList(searchStr: state.searchController.text); + List dataList = []; + if (entity.errorCode!.codeIsSuccessful) { + dataList = entity.data!.list!; + state.lockItemList.value = dataList; + for (int i = 0; i < dataList.length; i++) { + final LockItemData itemData = dataList[i]; + if (itemData.appUnlockOnline == 1) { + state.selectLockIdList.add(itemData.lockId); + } + } + } + return entity; + } + + //APP开锁时需手机联网的锁 + Future setAppUnlockMustOnlineRequest() async { + final SelectLockListEntity entity = + await ApiRepository.to.setAppUnlockMustOnline(state.selectLockIdList); + if (entity.errorCode!.codeIsSuccessful) { + showToast('操作成功'.tr); + + //刷新锁列表,更新锁详情--手机需联网标识 + if (Get.isRegistered()) { + Get.find().getStarLockInfo(isUnShowLoading: true); + } + } + } + + @override + void onReady() { + super.onReady(); + + // mockNetworkDataRequest(); + } + + @override + void onInit() { + super.onInit(); + } +} diff --git a/lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_page.dart b/lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_page.dart new file mode 100644 index 00000000..9fb5a687 --- /dev/null +++ b/lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_page.dart @@ -0,0 +1,149 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:star_lock/app_settings/app_colors.dart'; +import 'package:star_lock/main/lockDetail/lockSet/double_lock_link/double_lock_link_logic.dart'; +import 'package:star_lock/main/lockDetail/lockSet/double_lock_link/double_lock_link_state.dart'; +import 'package:star_lock/mine/mineSet/appUnlockNeedMobileNetworkingLock/selectLockListEntity.dart'; +import 'package:star_lock/tools/keySearchWidget.dart'; +import 'package:star_lock/tools/noData.dart'; +import 'package:star_lock/tools/storage.dart'; +import 'package:star_lock/tools/submitBtn.dart'; +import 'package:star_lock/tools/titleAppBar.dart'; + +class DoubleLockLinkPage extends StatefulWidget { + const DoubleLockLinkPage({Key? key}) : super(key: key); + + @override + State createState() => _DoubleLockLinkPageState(); +} + +class _DoubleLockLinkPageState extends State { + final DoubleLockLinkLogic logic = Get.put(DoubleLockLinkLogic()); + final DoubleLockLinkState state = Get.find().state; + + // 定义一个状态变量来存储选中的锁的 ID + int? _selectedLockId; + + Future getHttpData() async { + final bool? isDemoMode = await Storage.getBool(ifIsDemoModeOrNot); + if (isDemoMode == false) { + logic.mockNetworkDataRequest().then((SelectLockListEntity value) { + setState(() {}); + }); + } + } + + @override + void initState() { + super.initState(); + getHttpData(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColors.mainBackgroundColor, + resizeToAvoidBottomInset: false, + appBar: TitleAppBar( + barTitle: '双锁联动'.tr, + haveBack: true, + backgroundColor: AppColors.mainColor, + ), + body: Obx( + () => state.lockItemList.value.isEmpty + ? NoData() + : Column( + children: [ + KeySearchWidget( + editingController: state.searchController, + onSubmittedAction: () { + state.lockItemList.value = []; + logic.mockNetworkDataRequest(); + }, + ), + Container( + padding: EdgeInsets.all(15.w), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Text( + '对于当前拥有的锁和选中的锁,其中任意一把开启/关闭,另外一把则自动开启/关闭'.tr, + style: TextStyle(fontSize: 22.sp), + ), + ), + ], + ), + ), + SizedBox(height: 15.h), + Expanded( + child: ListView.builder( + itemCount: state.lockItemList.value.length, + itemBuilder: (BuildContext c, int index) { + final LockItemData itemData = + state.lockItemList.value[index]; + return _gatewatListItem(itemData); + }, + ), + ), + SubmitBtn( + btnName: '确定'.tr, + onClick: () { + logic.showToast('关联成功'.tr); + Get.back(); + }, + ), + SizedBox( + height: 40.h, + ), + ], + ), + ), + ); + } + + Widget _gatewatListItem(LockItemData itemData) { + return GestureDetector( + onTap: () { + setState(() { + // 更新选中的锁的 ID + _selectedLockId = itemData.lockId; + }); + }, + child: Container( + height: 80.h, + margin: const EdgeInsets.only(bottom: 2), + padding: + EdgeInsets.only(left: 10.w, right: 20.w, top: 20.h, bottom: 20.h), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10.w), + ), + child: Row( + children: [ + SizedBox( + width: 15.w, + ), + Image.asset( + _selectedLockId == itemData.lockId + ? 'images/icon_round_select.png' + : 'images/icon_round_unSelect.png', + width: 30.w, + height: 30.w, + ), + SizedBox( + width: 10.w, + ), + Expanded( + child: Text( + itemData.lockAlias ?? '', + style: TextStyle(fontSize: 22.sp, fontWeight: FontWeight.w600), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_state.dart b/lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_state.dart new file mode 100644 index 00000000..277d735d --- /dev/null +++ b/lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_state.dart @@ -0,0 +1,11 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:star_lock/mine/mineSet/appUnlockNeedMobileNetworkingLock/selectLockListEntity.dart'; + +class DoubleLockLinkState { + RxList lockItemList = [].obs; + List selectLockIdList = []; + RxBool isCheckAll = false.obs; + + final TextEditingController searchController = TextEditingController(); +} diff --git a/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart b/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart index 79302a59..44277007 100755 --- a/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart +++ b/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart @@ -3,9 +3,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; +import 'package:qr_flutter/qr_flutter.dart'; +import 'package:star_lock/blue/blue_manage.dart'; import 'package:star_lock/main/lockDetail/lockSet/lockSet/checkingInInfoData_entity.dart'; import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSet_state.dart'; import 'package:star_lock/main/lockMian/lockMain/lockMain_logic.dart'; +import 'package:star_lock/tools/showCupertinoAlertView.dart'; import '../../../../appRouters.dart'; import '../../../../app_settings/app_colors.dart'; @@ -317,6 +320,21 @@ class _LockSetPageState extends State 'lockSetInfoData': state.lockSetInfoData.value }); }))), + //todo 电子反锁、可视门铃码国际化 + // 电子反锁 + Obx(() => CommonItem( + leftTitel: '电子反锁'.tr, + rightTitle: '', + isHaveLine: true, + isHaveRightWidget: true, + rightWidget: _elecAntiLockSwitch())), + // 可视门铃码 + Obx(() => CommonItem( + leftTitel: '可视门铃码'.tr, + rightTitle: '', + isHaveLine: true, + isHaveRightWidget: true, + rightWidget: _visualDoorbellCodeSwitch())), SizedBox(height: 10.h), // 常开模式 Obx(() => Visibility( @@ -335,6 +353,25 @@ class _LockSetPageState extends State 'lockSetInfoData': state.lockSetInfoData.value }); }))), + //todo: 双重认证、双锁联动国际化、API接口 + //双重认证 + Obx(() => Visibility( + visible: true, + child: CommonItem( + leftTitel: '双重认证'.tr, + rightTitle: '', + isHaveLine: true, + isHaveRightWidget: true, + rightWidget: _dualAuthSwitch()))), + // 双锁联动 + CommonItem( + leftTitel: '双锁联动'.tr, + rightTitle: '未关联'.tr, + isHaveLine: true, + isHaveDirection: true, + action: () { + Get.toNamed(Routers.doubleLockLinkPage); + }), // 远程开锁 Obx(() => Visibility( visible: state.lockFeature.value.remoteUnlock == 1, @@ -529,11 +566,9 @@ class _LockSetPageState extends State () => Visibility( visible: state.lockBasicInfo.value.isLockOwner == 1 && state.lockFeature.value.appUnlockOnline == 1, - child: CommonItem( - leftTitel: '开锁时是否需联网'.tr, - rightTitle: '', + child: otherItem( + leftTitle: '开锁时是否需联网'.tr, isHaveLine: false, - isHaveRightWidget: true, rightWidget: _openLockNeedOnlineSwitch()), ), ), @@ -653,6 +688,33 @@ class _LockSetPageState extends State style: TextStyle(fontSize: 22.sp, color: AppColors.darkGrayTextColor)); } + Widget otherItem({String? leftTitle, bool? isHaveLine, Widget? rightWidget}) { + return Container( + width: 1.sw, + padding: + EdgeInsets.only(left: 20.w, top: 7.5.h, bottom: 7.5.h, right: 10.w), + decoration: BoxDecoration( + color: Colors.white, + border: isHaveLine! + ? Border( + bottom: BorderSide( + color: AppColors.greyLineColor, // 设置边框颜色 + width: 2.0.h, // 设置边框宽度 + ), + ) + : null, + ), + child: Row( + children: [ + Expanded(child: Text(leftTitle!, style: TextStyle(fontSize: 22.sp))), + SizedBox(width: 10.w), + rightWidget ?? Container(), + SizedBox(width: 5.w), + ], + ), + ); + } + // 开启考勤 // CupertinoSwitch _openCheckInSwitch() { // return CupertinoSwitch( @@ -710,6 +772,64 @@ class _LockSetPageState extends State ); } + // 电子反锁 + CupertinoSwitch _elecAntiLockSwitch() { + return CupertinoSwitch( + activeColor: CupertinoColors.activeBlue, + trackColor: CupertinoColors.systemGrey5, + thumbColor: CupertinoColors.white, + value: state.isElecAntiLock.value == 1, + onChanged: state.sureBtnState.value == 1 + ? null + : (bool value) { + setState(() { + state.isElecAntiLock.value = value ? 1 : 0; + }); + }, + ); + } + + // 可视门铃码 + CupertinoSwitch _visualDoorbellCodeSwitch() { + return CupertinoSwitch( + activeColor: CupertinoColors.activeBlue, + trackColor: CupertinoColors.systemGrey5, + thumbColor: CupertinoColors.white, + value: state.isVisualDoorbellCode.value == 1, + onChanged: state.sureBtnState.value == 1 + ? null + : (bool value) { + setState(() { + state.isVisualDoorbellCode.value = value ? 1 : 0; + if (state.isVisualDoorbellCode.value == 1) { + ShowCupertinoAlertView().showVisualDoorbellCodeAlert( + widgetContext: context, + qrCodeUrl: BlueManage().connectDeviceName, + qrCodeText: '请扫描可视门铃码二维码'.tr, + ); + } else {} + }); + }, + ); + } + + // 双重认证 + CupertinoSwitch _dualAuthSwitch() { + return CupertinoSwitch( + activeColor: CupertinoColors.activeBlue, + trackColor: CupertinoColors.systemGrey5, + thumbColor: CupertinoColors.white, + value: state.isDualAuth.value == 1, + onChanged: state.sureBtnState.value == 1 + ? null + : (bool value) { + setState(() { + state.isDualAuth.value = value ? 1 : 0; + }); + }, + ); + } + // 异常警告 // CupertinoSwitch _lockExceptionWarningsSwitch() { // return CupertinoSwitch( diff --git a/lib/main/lockDetail/lockSet/lockSet/lockSet_state.dart b/lib/main/lockDetail/lockSet/lockSet/lockSet_state.dart index 2713b51e..be7d054f 100755 --- a/lib/main/lockDetail/lockSet/lockSet/lockSet_state.dart +++ b/lib/main/lockDetail/lockSet/lockSet/lockSet_state.dart @@ -22,13 +22,16 @@ class LockSetState { RxInt isOpenBlueBroadcast = 0.obs; // 是否开启蓝牙广播 RxInt isOpenExceptionWarnings = 0.obs; // 是否开启异常警告 RxInt isOpenStayWarn = 0.obs; // 是否开启逗留警告 + RxInt isElecAntiLock = 0.obs; // 电子反锁 + RxInt isVisualDoorbellCode = 0.obs; // 电子可视门铃 + RxInt isDualAuth = 0.obs; // 双重认证 TextEditingController passwordTF = TextEditingController(); int settingUpSupportFeatures = 0; RxBool ifCurrentScreen = true.obs; // 是否是当前界面,用于判断是否需要针对当前界面进行展示 RxBool deleteAdministratorIsHaveAllData = false.obs; // 删除管理员是否有所有数据 - RxInt sureBtnState = 0.obs;// 0普通状态(可用) 1连接中(不可用) + RxInt sureBtnState = 0.obs; // 0普通状态(可用) 1连接中(不可用) final ShowTipView showTipView = ShowTipView(); LockSetState() { diff --git a/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_logic.dart b/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_logic.dart old mode 100755 new mode 100644 index 0956e9ed..2b47048d --- a/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_logic.dart +++ b/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_logic.dart @@ -5,7 +5,6 @@ import 'package:flutter_voice_processor/flutter_voice_processor.dart'; import 'package:get/get.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:star_lock/talk/call/callTalk.dart'; -import 'package:star_lock/talk/startChart/start_chart_manage.dart'; import 'package:star_lock/talk/udp/udp_talkClass.dart'; import '../../../../app_settings/app_settings.dart'; @@ -23,11 +22,8 @@ class LockMonitoringLogic extends BaseGetXController { state.voiceProcessor = VoiceProcessor.instance; } -/* -旧协议暂时不用 /// 收到UDP发送的状态 StreamSubscription? _getUDPStatusRefreshUIEvent; - void _getUDPStatusRefreshUIAction() { _getUDPStatusRefreshUIEvent = eventBus.on().listen((event) async { @@ -57,7 +53,6 @@ class LockMonitoringLogic extends BaseGetXController { } }); } - */ //发起接听命令,每隔一秒钟发一次,六秒无应答则失败 void initiateUdpAnswerAction() { @@ -79,9 +74,6 @@ class LockMonitoringLogic extends BaseGetXController { UDPTalkClass().callNoAnswer(1); } }); - - // 发送同意接听消息 - StartChartManage().sendTalkAcceptMessage(); } /// 接听 @@ -112,9 +104,6 @@ class LockMonitoringLogic extends BaseGetXController { UDPTalkClass().callNoAnswer(2); } }); - - // 发送拒绝接听消息 - StartChartManage().sendTalkRejectMessage(); } /// 挂断 @@ -416,7 +405,7 @@ class LockMonitoringLogic extends BaseGetXController { void onReady() { super.onReady(); - // _getUDPStatusRefreshUIAction(); + _getUDPStatusRefreshUIAction(); initRecorder(); } @@ -430,7 +419,7 @@ class LockMonitoringLogic extends BaseGetXController { void onClose() { CallTalk().finishAVData(); stopProcessing(); - // _getUDPStatusRefreshUIEvent!.cancel(); + _getUDPStatusRefreshUIEvent!.cancel(); state.getTVDataRefreshUIEvent!.cancel(); if (state.oneMinuteTimeTimer != null) { diff --git a/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart b/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart old mode 100755 new mode 100644 index 03588c94..52998c78 --- a/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart +++ b/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:convert'; import 'dart:io'; import 'dart:ui' as ui; @@ -11,18 +10,16 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:image_gallery_saver/image_gallery_saver.dart'; import 'package:path_provider/path_provider.dart'; -import 'package:star_lock/app_settings/app_colors.dart'; -import 'package:star_lock/app_settings/app_settings.dart'; -import 'package:star_lock/main/lockDetail/monitoring/monitoring/star_chart_logic.dart'; +import 'package:star_lock/main/lockDetail/monitoring/monitoring/lockMonitoring_state.dart'; import 'package:star_lock/talk/call/callTalk.dart'; -import 'package:star_lock/talk/startChart/start_chart_talk_status.dart'; -import 'package:star_lock/talk/startChart/webView/h264_web_view.dart'; import 'package:star_lock/talk/udp/udp_manage.dart'; import 'package:star_lock/tools/eventBusEventManage.dart'; -import 'package:star_lock/tools/showTFView.dart'; +import '../../../../app_settings/app_colors.dart'; +import '../../../../app_settings/app_settings.dart'; +import '../../../../login/selectCountryRegion/common/index.dart'; +import '../../../../tools/showTFView.dart'; import 'lockMonitoring_logic.dart'; -import 'lockMonitoring_state.dart'; class LockMonitoringPage extends StatefulWidget { const LockMonitoringPage({Key? key}) : super(key: key); @@ -32,13 +29,12 @@ class LockMonitoringPage extends StatefulWidget { } class _LockMonitoringPageState extends State { - final StarChartLogic logic = Get.put(StarChartLogic()); - final LockMonitoringState state = Get.find().state; + final LockMonitoringLogic logic = Get.put(LockMonitoringLogic()); + final LockMonitoringState state = Get.find().state; @override void initState() { super.initState(); - initAsync(); _getTVDataRefreshUIAction(); } @@ -50,156 +46,242 @@ class _LockMonitoringPageState extends State { @override Widget build(BuildContext context) { return PopScope( - canPop: false, - child: RepaintBoundary( - key: state.globalKey, + canPop: false, + child: RepaintBoundary( + key: state.globalKey, + child: Container( + width: 1.sw, + height: 1.sh, + color: Colors.transparent, + child: Stack( + children: [ + Image.memory( + state.listPhotoData.value, + gaplessPlayback: true, + width: 1.sw, + height: 1.sh, + fit: BoxFit.cover, //contain-原比例 none-原始图片 + filterQuality: FilterQuality.high, + errorBuilder: (BuildContext context, Object error, + StackTrace? stackTrace) { + return Container(color: Colors.transparent); + }, + ), + Positioned( + top: ScreenUtil().statusBarHeight + 30.h, + width: 1.sw, + child: Obx(() { + final String sec = (state.oneMinuteTime.value % 60) + .toString() + .padLeft(2, '0'); + final String min = (state.oneMinuteTime.value ~/ 60) + .toString() + .padLeft(2, '0'); + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('$min:$sec', + style: TextStyle( + fontSize: 26.sp, color: Colors.white)), + ]); + }), + ), + Positioned( + bottom: 10.w, + child: Container( + width: 1.sw - 30.w * 2, + // height: 300.h, + margin: EdgeInsets.all(30.w), + decoration: BoxDecoration( + color: const Color(0xC83C3F41), + borderRadius: BorderRadius.circular(20.h)), + child: Column( + children: [ + SizedBox(height: 20.h), + bottomTopBtnWidget(), + SizedBox(height: 20.h), + bottomBottomBtnWidget(), + SizedBox(height: 20.h), + ], + ), + )) + ], + ), + ), + )); + } + + Widget bottomTopBtnWidget() { + return Row(mainAxisAlignment: MainAxisAlignment.center, children: [ + // 打开关闭声音 + GestureDetector( + onTap: () { + state.isOpenVoice.value = !state.isOpenVoice.value; + }, child: Container( - width: 1.sw, - height: 1.sh, - color: Colors.transparent, - child: _buildTalkView(isMpeg4: false), + width: 50.w, + height: 50.w, + padding: EdgeInsets.all(5.w), + child: Obx(() => Image( + width: 40.w, + height: 40.w, + image: state.isOpenVoice.value + ? const AssetImage( + 'images/main/icon_lockDetail_monitoringCloseVoice.png') + : const AssetImage( + 'images/main/icon_lockDetail_monitoringOpenVoice.png'))), ), ), - ); + SizedBox(width: 60.w), + // 截图 + GestureDetector( + onTap: captureAndSavePng, + child: Container( + width: 50.w, + height: 50.w, + padding: EdgeInsets.all(5.w), + child: Image( + width: 40.w, + height: 40.w, + image: const AssetImage( + 'images/main/icon_lockDetail_monitoringScreenshot.png')), + ), + ), + SizedBox(width: 60.w), + // 录制 + GestureDetector( + onTap: () { + // Get.toNamed(Routers.monitoringRealTimeScreenPage); + }, + child: Container( + width: 50.w, + height: 50.w, + padding: EdgeInsets.all(5.w), + child: Image( + width: 40.w, + height: 40.w, + image: const AssetImage( + 'images/main/icon_lockDetail_monitoringScreenRecording.png')), + ), + ), + ]); } - Widget buildTopButtons() { + Widget bottomBottomBtnWidget() { return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - buildIconButton( - icon: state.isOpenVoice.value - ? 'images/main/icon_lockDetail_monitoringCloseVoice.png' - : 'images/main/icon_lockDetail_monitoringOpenVoice.png', - onTap: () { - state.isOpenVoice.value = !state.isOpenVoice.value; - }, - ), - SizedBox(width: 60.w), - buildIconButton( - icon: 'images/main/icon_lockDetail_monitoringScreenshot.png', - onTap: captureAndSavePng, - ), - SizedBox(width: 60.w), - buildIconButton( - icon: 'images/main/icon_lockDetail_monitoringScreenRecording.png', - onTap: () { - // Get.toNamed(Routers.monitoringRealTimeScreenPage); - }, - ), - ], - ); - } - - Widget buildBottomButtons() { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - buildAnswerButton(), - buildIconButton( - icon: 'images/main/icon_lockDetail_hangUp.png', - label: '挂断'.tr, - color: Colors.red, - onTap: () async { - // logic.stopProcessing(); - // CallTalk().finishAVData(); - - if (!state.isClickHangUp.value) { - // logic.initiateUdpHangUpAction(3); - logic.initiateHangUpCommand(); + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + // 接听 + Obx(() => bottomBtnItemWidget( + state.isClickAnswer.value == true + ? 'images/main/icon_lockDetail_monitoringUnTalkback.png' + : getAnswerBtnImg(), + state.isClickAnswer.value == true + ? '长按说话'.tr + : getAnswerBtnName(), + Colors.white, () async { + if (state.isClickAnswer.value == false) { + logic.initiateUdpAnswerAction(); + state.isClickAnswer.value = true; + } + }, longPress: () { + // 开始长按 + AppLog.log('onLongPress'); + state.listAudioData.value = []; + if (state.udpStatus.value == 8) { + state.udpStatus.value = 9; + } + // logic.readG711Data(); + logic.startProcessing(); + }, longPressUp: () async { + // 长按结束 + AppLog.log('onLongPressUp'); + if (state.udpStatus.value == 9) { + state.udpStatus.value = 8; + } + logic.stopProcessing(); + })), + bottomBtnItemWidget( + 'images/main/icon_lockDetail_hangUp.png', '挂断'.tr, Colors.red, + () async { + logic.stopProcessing(); + CallTalk().finishAVData(); + // 挂断 + if (state.isClickHangUp.value == false) { + logic.initiateUdpHangUpAction(3); state.isClickHangUp.value = true; } - }, - ), - buildIconButton( - icon: 'images/main/icon_lockDetail_monitoringUnlock.png', - label: '开锁'.tr, - color: AppColors.mainColor, - onTap: () { + // else { + // AppLog.log('点了这里?'); + // state.isClickHangUp.value = true; + // UDPTalkClass().stopLocalAudio(); + // logic.initiateUdpHangUpAction(4); + // } + }), + bottomBtnItemWidget( + 'images/main/icon_lockDetail_monitoringUnlock.png', + '开锁'.tr, + AppColors.mainColor, () { if (UDPManage().remoteUnlock == 1) { showDeletPasswordAlertDialog(context); } else { logic.showToast('请在锁设置中开启远程开锁'.tr); } - }, - ), - ], - ); + }) + ]); } - Widget buildAnswerButton() { - return Obx(() { - final bool isDuringCall = - state.talkStatus.value == TalkStatus.duringCall.index; - return buildIconButton( - icon: isDuringCall - ? 'images/main/icon_lockDetail_monitoringUnTalkback.png' - : 'images/main/icon_lockDetail_monitoringAnswerCalls.png', - label: isDuringCall ? '长按说话'.tr : '接听'.tr, - onTap: () async { - if (!state.isClickAnswer.value) { - logic.initiateAnswerCommand(); - state.isClickAnswer.value = true; - } - }, - onLongPress: () { - state.listAudioData.value = []; - // if (state.udpStatus.value == 8) { - // state.udpStatus.value = 9; - // } - logic.startProcessing(); - }, - onLongPressUp: () { - // if (state.udpStatus.value == 9) { - // state.udpStatus.value = 8; - // } - logic.stopProcessing(); - }, - ); - }); + String getAnswerBtnImg() { + switch (state.udpStatus.value) { + case 8: + return 'images/main/icon_lockDetail_monitoringUnTalkback.png'; + case 9: + return 'images/main/icon_lockDetail_monitoringTalkback.png'; + default: + return 'images/main/icon_lockDetail_monitoringAnswerCalls.png'; + } } - Widget buildIconButton({ - required String icon, - String? label, - Color color = Colors.white, - required Function() onTap, - Function()? onLongPress, - Function()? onLongPressUp, - }) { + String getAnswerBtnName() { + switch (state.udpStatus.value) { + case 8: + return '长按说话'.tr; + case 9: + return '松开发送'.tr; + default: + return '接听'.tr; + } + } + + Widget bottomBtnItemWidget( + String iconUrl, String name, Color backgroundColor, Function() onClick, + {Function()? longPress, Function()? longPressUp}) { final double wh = 80.w; return GestureDetector( - onTap: onTap, - onLongPress: onLongPress, - onLongPressUp: onLongPressUp, + onTap: onClick, + onLongPress: longPress, + onLongPressUp: longPressUp, child: SizedBox( - height: 140.h, - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - width: wh, - height: wh, - decoration: BoxDecoration( - color: color, - borderRadius: BorderRadius.circular((wh + 10.w * 2) / 2), + height: 140.h, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: wh, + height: wh, + decoration: BoxDecoration( + color: backgroundColor, + borderRadius: BorderRadius.circular((wh + 10.w * 2) / 2)), + padding: EdgeInsets.all(20.w), + child: Image.asset(iconUrl, fit: BoxFit.fitWidth), ), - padding: EdgeInsets.all(20.w), - child: Image.asset(icon, fit: BoxFit.fitWidth), - ), - if (label != null) ...[ SizedBox(height: 20.w), Expanded( - child: Text( - label, - style: TextStyle(fontSize: 20.sp, color: Colors.white), - textAlign: TextAlign.center, - ), - ), + child: Text(name, + style: TextStyle(fontSize: 20.sp, color: Colors.white), + textAlign: TextAlign.center)) ], - ], - ), - ), + )), ); } @@ -217,18 +299,23 @@ class _LockMonitoringPageState extends State { FilteringTextInputFormatter.allow(RegExp('[0-9]')), ], sureClick: () async { + //发送删除锁请求 if (state.passwordTF.text.isEmpty) { logic.showToast('请输入开锁密码'.tr); return; } + + // List numbers = state.passwordTF.text.split('').map((char) => int.parse(char)).toList(); + // 开锁 + // lockID final List numbers = []; final List lockIDData = utf8.encode(state.passwordTF.text); numbers.addAll(lockIDData); + // topBytes = getFixedLengthList(lockIDData, 20 - lockIDData.length); for (int i = 0; i < 6 - lockIDData.length; i++) { numbers.add(0); } - //todo: 开门暂未实现 - // logic.udpOpenDoorAction(numbers); + logic.udpOpenDoorAction(numbers); }, cancelClick: () { Get.back(); @@ -238,11 +325,16 @@ class _LockMonitoringPageState extends State { ); } - Future requestMicrophonePermission() async { + //获取麦克风权限 + Future requestMicrophonePermission() async { await logic.getPermissionStatus().then((bool value) async { if (!value) { return; } + + // state.isSenderAudioData.value = false; + // AppLog.log("发送接听了"); + // 刚进来是接听状态,然后改为长按对讲 }); } @@ -263,12 +355,15 @@ class _LockMonitoringPageState extends State { } final Uint8List pngBytes = byteData.buffer.asUint8List(); + // 获取应用程序的文档目录 final Directory directory = await getApplicationDocumentsDirectory(); final String imagePath = '${directory.path}/screenshot.png'; + // 将截图保存为文件 final File imgFile = File(imagePath); await imgFile.writeAsBytes(pngBytes); + // 将截图保存到相册 await ImageGallerySaver.saveFile(imagePath); AppLog.log('截图保存路径: $imagePath'); @@ -278,19 +373,31 @@ class _LockMonitoringPageState extends State { } } + /// 收到视频流数据 void _getTVDataRefreshUIAction() { + // 蓝牙协议通知传输跟蓝牙之外的数据传输类不一样 eventBus state.getTVDataRefreshUIEvent = eventBus .on() .listen((GetTVDataRefreshUI event) async { if (event.tvList.isNotEmpty && event.tvList.length > 100) { + // 比较新旧数据是否相同 final Uint8List imageData = Uint8List.fromList(event.tvList); + if (!listEquals(state.listPhotoData.value, imageData)) { + // 更新状态 state.listPhotoData.value = imageData; + // 设置标志为true,表示需要更新UI state.shouldUpdateUI.value = true; + // WidgetsBinding.instance.addPostFrameCallback((_) { + // 调用setState方法之前检查标志,只有当标志为true时才更新UI if (state.shouldUpdateUI.value) { - setState(() {}); + setState(() { + // 更新UI + }); + // 更新完UI后将标志重新设置为false state.shouldUpdateUI.value = false; } + // }); } } }); @@ -302,109 +409,4 @@ class _LockMonitoringPageState extends State { logic.stopProcessing(); state.getTVDataRefreshUIEvent!.cancel(); } - - Widget _buildTalkView({required bool isMpeg4}) { - return isMpeg4 ? _buildMpeg4TalkView() : _buildH264TalkView(); - } - - Widget _buildMpeg4TalkView() { - return Stack( - children: [ - Image.memory( - state.listPhotoData.value, - gaplessPlayback: true, - width: 1.sw, - height: 1.sh, - fit: BoxFit.cover, - filterQuality: FilterQuality.high, - errorBuilder: - (BuildContext context, Object error, StackTrace? stackTrace) { - return Container(color: Colors.transparent); - }, - ), - Positioned( - top: ScreenUtil().statusBarHeight + 30.h, - width: 1.sw, - child: Obx(() { - final String sec = - (state.oneMinuteTime.value % 60).toString().padLeft(2, '0'); - final String min = - (state.oneMinuteTime.value ~/ 60).toString().padLeft(2, '0'); - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text('$min:$sec', - style: TextStyle(fontSize: 26.sp, color: Colors.white)), - ], - ); - }), - ), - Positioned( - bottom: 10.w, - child: Container( - width: 1.sw - 30.w * 2, - margin: EdgeInsets.all(30.w), - decoration: BoxDecoration( - color: const Color(0xC83C3F41), - borderRadius: BorderRadius.circular(20.h), - ), - child: Column( - children: [ - SizedBox(height: 20.h), - buildTopButtons(), - SizedBox(height: 20.h), - buildBottomButtons(), - SizedBox(height: 20.h), - ], - ), - ), - ), - ], - ); - } - - Widget _buildH264TalkView() { - return Stack( - children: [ - H264WebView(), - Positioned( - top: ScreenUtil().statusBarHeight + 30.h, - width: 1.sw, - child: Obx(() { - final String sec = - (state.oneMinuteTime.value % 60).toString().padLeft(2, '0'); - final String min = - (state.oneMinuteTime.value ~/ 60).toString().padLeft(2, '0'); - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text('$min:$sec', - style: TextStyle(fontSize: 26.sp, color: Colors.white)), - ], - ); - }), - ), - Positioned( - bottom: 10.w, - child: Container( - width: 1.sw - 30.w * 2, - margin: EdgeInsets.all(30.w), - decoration: BoxDecoration( - color: const Color(0xC83C3F41), - borderRadius: BorderRadius.circular(20.h), - ), - child: Column( - children: [ - SizedBox(height: 20.h), - buildTopButtons(), - SizedBox(height: 20.h), - buildBottomButtons(), - SizedBox(height: 20.h), - ], - ), - ), - ), - ], - ); - } } diff --git a/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_state.dart b/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_state.dart old mode 100755 new mode 100644 index d26067bb..c0f07e83 --- a/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_state.dart +++ b/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_state.dart @@ -5,7 +5,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_voice_processor/flutter_voice_processor.dart'; import 'package:get/get.dart'; import 'package:network_info_plus/network_info_plus.dart'; -import 'package:star_lock/talk/startChart/start_chart_talk_status.dart'; import '../../../../tools/storage.dart'; @@ -19,8 +18,8 @@ class LockMonitoringState { Future userMobileIP = NetworkInfo().getWifiIP(); Future userUid = Storage.getUid(); - // RxInt udpStatus = - // 0.obs; //0:初始状态 1:等待监视 2: 3:监视中 4:呼叫成功 5:主角通话中 6:被叫通话 8:被叫通话中 9:长按说话 + RxInt udpStatus = + 0.obs; //0:初始状态 1:等待监视 2: 3:监视中 4:呼叫成功 5:主角通话中 6:被叫通话 8:被叫通话中 9:长按说话 TextEditingController passwordTF = TextEditingController(); Rx listPhotoData = Uint8List(0).obs; //得到的视频流字节数据 @@ -32,6 +31,10 @@ class LockMonitoringState { RxBool isButtonDisabled = false.obs; //是否禁用按钮 final int frameLength = 320; //音视频帧长度为320 final int sampleRate = 8000; //音频采样率为8000 + // final int volumeHistoryCapacity = 5; //音量历史记录的容量 + // final double dbOffset = 50.0; //用于音量计算的偏移量 + // var volumeHistory = [].obs; //用于存储音量历史记录的列表 + // var smoothedVolumeValue = 0.0.obs; //存储平滑后的音量值 RxString errorMessage = ''.obs; List> allFrames = >[]; @@ -52,6 +55,4 @@ class LockMonitoringState { late Timer openDoorTimer = Timer(const Duration(seconds: 1), () {}); //开门命令定时器 RxInt openDoorSeconds = 0.obs; - - RxInt talkStatus = 0.obs; //星图对讲状态 } diff --git a/lib/main/lockDetail/monitoring/monitoring/star_chart_logic.dart b/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_logic.dart similarity index 69% rename from lib/main/lockDetail/monitoring/monitoring/star_chart_logic.dart rename to lib/main/lockDetail/monitoring/star_chart_h264/star_chart_logic.dart index b90c1d14..dd5f1a89 100644 --- a/lib/main/lockDetail/monitoring/monitoring/star_chart_logic.dart +++ b/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_logic.dart @@ -4,15 +4,16 @@ import 'package:flutter_voice_processor/flutter_voice_processor.dart'; import 'package:get/get.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:star_lock/app_settings/app_settings.dart'; +import 'package:star_lock/blue/io_tool/manager_event_bus.dart'; +import 'package:star_lock/main/lockDetail/monitoring/star_chart_h264/star_chart_state.dart'; import 'package:star_lock/talk/startChart/events/talk_status_change_event.dart'; import 'package:star_lock/talk/startChart/start_chart_manage.dart'; import 'package:star_lock/talk/startChart/start_chart_talk_status.dart'; import 'package:star_lock/tools/baseGetXController.dart'; import 'package:star_lock/tools/eventBusEventManage.dart'; -import 'lockMonitoring_state.dart'; class StarChartLogic extends BaseGetXController { - final LockMonitoringState state = LockMonitoringState(); + final StarChartState state = StarChartState(); /// 收到Talk发送的状态 StreamSubscription? _getTalkStatusRefreshUIEvent; @@ -24,15 +25,19 @@ class StarChartLogic extends BaseGetXController { } void _getTalkStatusRefreshUIAction() { - _getTalkStatusRefreshUIEvent = eventBus + _getTalkStatusRefreshUIEvent = EventBusManager() + .eventBus! .on() .listen((TalkStatusChangeEvent event) async { state.talkStatus.value = event.newStatus.index; state.oneMinuteTime.value = 0; - if (state.talkStatus.value == TalkStatus.rejected.index || + state.talkStatus.value == TalkStatus.notTalkData.index || + state.talkStatus.value == TalkStatus.notTalkPing.index || state.talkStatus.value == TalkStatus.end.index) { _cancelTimers(); + // 状态错误,返回页面 + Get.back(); return; } @@ -58,26 +63,10 @@ class StarChartLogic extends BaseGetXController { void _cancelTimers() { state.oneMinuteTimeTimer.cancel(); - state.answerTimer.cancel(); } // 发起接听命令 void initiateAnswerCommand() { - // state.answerTimer = Timer.periodic(const Duration(seconds: 1), (timer) { - // StartChartManage().sendTalkAcceptMessage(); - // state.answerSeconds++; - - // if (state.talkStatus.value == TalkStatus.duringCall.index) { - // state.answerTimer.cancel(); - // return; - // } - - // if (state.answerSeconds >= 6) { - // state.answerTimer.cancel(); - // showToast('接听失败'.tr); - // initiateHangUpCommand(); - // } - // }); StartChartManage().sendTalkAcceptMessage(); } @@ -113,23 +102,23 @@ class StarChartLogic extends BaseGetXController { } Future startProcessing() async { - state.isButtonDisabled.value = true; - - state.voiceProcessor?.addFrameListener(_onFrame); - state.voiceProcessor?.addErrorListener(_onError); - try { - if (await state.voiceProcessor?.hasRecordAudioPermission() ?? false) { - await state.voiceProcessor?.start(state.frameLength, state.sampleRate); - state.isProcessing.value = - await state.voiceProcessor?.isRecording() ?? false; - } else { - state.errorMessage.value = 'Recording permission not granted'; - } - } on PlatformException catch (ex) { - state.errorMessage.value = 'Failed to start recorder: $ex'; - } finally { - state.isButtonDisabled.value = false; - } + // state.isButtonDisabled.value = true; + // + // state.voiceProcessor?.addFrameListener(_onFrame); + // state.voiceProcessor?.addErrorListener(_onError); + // try { + // if (await state.voiceProcessor?.hasRecordAudioPermission() ?? false) { + // await state.voiceProcessor?.start(state.frameLength, state.sampleRate); + // state.isProcessing.value = + // await state.voiceProcessor?.isRecording() ?? false; + // } else { + // state.errorMessage.value = 'Recording permission not granted'; + // } + // } on PlatformException catch (ex) { + // state.errorMessage.value = 'Failed to start recorder: $ex'; + // } finally { + // state.isButtonDisabled.value = false; + // } } void _onError(VoiceProcessorException error) { @@ -137,18 +126,24 @@ class StarChartLogic extends BaseGetXController { } Future stopProcessing() async { - state.isButtonDisabled.value = true; - try { - await state.voiceProcessor?.stop(); - state.voiceProcessor?.removeFrameListener(_onFrame); - state.udpSendDataFrameNumber = 0; - } on PlatformException catch (ex) { - state.errorMessage.value = 'Failed to stop recorder: $ex'; - } finally { - state.isProcessing.value = - await state.voiceProcessor?.isRecording() ?? false; - state.isButtonDisabled.value = false; - } + // 检查 voiceProcessor 是否已经初始化 + // if (state.voiceProcessor == null) { + // state.errorMessage.value = 'Voice processor is not initialized.'; + // return; + // } + // + // state.isButtonDisabled.value = true; + // try { + // await state.voiceProcessor?.stop(); + // state.voiceProcessor?.removeFrameListener(_onFrame); + // state.udpSendDataFrameNumber = 0; + // } on PlatformException catch (ex) { + // state.errorMessage.value = 'Failed to stop recorder: $ex'; + // } finally { + // state.isProcessing.value = + // await state.voiceProcessor?.isRecording() ?? false; + // state.isButtonDisabled.value = false; + // } } int linearToULaw(int pcmVal) { diff --git a/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_page.dart b/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_page.dart new file mode 100644 index 00000000..8508c58e --- /dev/null +++ b/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_page.dart @@ -0,0 +1,396 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:ui' as ui; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:image_gallery_saver/image_gallery_saver.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:star_lock/app_settings/app_colors.dart'; +import 'package:star_lock/app_settings/app_settings.dart'; +import 'package:star_lock/main/lockDetail/monitoring/star_chart_h264/star_chart_logic.dart'; +import 'package:star_lock/main/lockDetail/monitoring/star_chart_h264/star_chart_state.dart'; +import 'package:star_lock/talk/startChart/start_chart_talk_status.dart'; +import 'package:star_lock/talk/startChart/webView/h264_web_view.dart'; +import 'package:star_lock/talk/udp/udp_manage.dart'; +import 'package:star_lock/tools/eventBusEventManage.dart'; +import 'package:star_lock/tools/showTFView.dart'; + +class StarChartPage extends StatefulWidget { + const StarChartPage({Key? key}) : super(key: key); + + @override + State createState() => _StarChartPageState(); +} + +class _StarChartPageState extends State { + final StarChartLogic logic = Get.put(StarChartLogic()); + final StarChartState state = Get.find().state; + + @override + void initState() { + super.initState(); + + initAsync(); + _getTVDataRefreshUIAction(); + } + + Future initAsync() async { + await requestMicrophonePermission(); + } + + @override + Widget build(BuildContext context) { + return PopScope( + canPop: false, + child: RepaintBoundary( + key: state.globalKey, + child: Container( + width: 1.sw, + height: 1.sh, + color: Colors.transparent, + child: _buildTalkView(isMpeg4: true), + ), + ), + ); + } + + Widget buildTopButtons() { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + buildIconButton( + icon: state.isOpenVoice.value + ? 'images/main/icon_lockDetail_monitoringCloseVoice.png' + : 'images/main/icon_lockDetail_monitoringOpenVoice.png', + onTap: () { + state.isOpenVoice.value = !state.isOpenVoice.value; + }, + ), + SizedBox(width: 60.w), + buildIconButton( + icon: 'images/main/icon_lockDetail_monitoringScreenshot.png', + onTap: captureAndSavePng, + ), + SizedBox(width: 60.w), + buildIconButton( + icon: 'images/main/icon_lockDetail_monitoringScreenRecording.png', + onTap: () { + // Get.toNamed(Routers.monitoringRealTimeScreenPage); + }, + ), + ], + ); + } + + Widget buildBottomButtons() { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + buildAnswerButton(), + buildIconButton( + icon: 'images/main/icon_lockDetail_hangUp.png', + label: '挂断'.tr, + color: Colors.red, + onTap: () async { + logic.initiateHangUpCommand(); + }, + ), + buildIconButton( + icon: 'images/main/icon_lockDetail_monitoringUnlock.png', + label: '开锁'.tr, + color: AppColors.mainColor, + onTap: () { + if (UDPManage().remoteUnlock == 1) { + showDeletPasswordAlertDialog(context); + } else { + logic.showToast('请在锁设置中开启远程开锁'.tr); + } + }, + ), + ], + ); + } + + Widget buildAnswerButton() { + return Obx(() { + // final bool isDuringCall = + // state.talkStatus.value == TalkStatus.duringCall.index; + return buildIconButton( + icon: state.talkStatus.value == TalkStatus.duringCall.index + ? 'images/main/icon_lockDetail_monitoringUnTalkback.png' + : 'images/main/icon_lockDetail_monitoringAnswerCalls.png', + label: state.talkStatus.value == TalkStatus.duringCall.index + ? '长按说话'.tr + : '接听'.tr, + onTap: () async { + if (state.talkStatus.value == TalkStatus.waitingAnswer.index) { + logic.initiateAnswerCommand(); + setState(() {}); + } + }, + onLongPress: () { + state.listAudioData.value = []; + logic.startProcessing(); + }, + onLongPressUp: () { + logic.stopProcessing(); + }, + ); + }); + } + + Widget buildIconButton({ + required String icon, + String? label, + Color color = Colors.white, + required Function() onTap, + Function()? onLongPress, + Function()? onLongPressUp, + }) { + final double wh = 80.w; + return GestureDetector( + onTap: onTap, + onLongPress: onLongPress, + onLongPressUp: onLongPressUp, + child: SizedBox( + height: 140.h, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: wh, + height: wh, + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular((wh + 10.w * 2) / 2), + ), + padding: EdgeInsets.all(20.w), + child: Image.asset(icon, fit: BoxFit.fitWidth), + ), + if (label != null) ...[ + SizedBox(height: 20.w), + Expanded( + child: Text( + label, + style: TextStyle(fontSize: 20.sp, color: Colors.white), + textAlign: TextAlign.center, + ), + ), + ], + ], + ), + ), + ); + } + + void showDeletPasswordAlertDialog(BuildContext context) { + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) { + return ShowTFView( + title: '请输入6位数字开锁密码'.tr, + tipTitle: '', + controller: state.passwordTF, + inputFormatters: [ + LengthLimitingTextInputFormatter(6), //限制长度 + FilteringTextInputFormatter.allow(RegExp('[0-9]')), + ], + sureClick: () async { + if (state.passwordTF.text.isEmpty) { + logic.showToast('请输入开锁密码'.tr); + return; + } + final List numbers = []; + final List lockIDData = utf8.encode(state.passwordTF.text); + numbers.addAll(lockIDData); + for (int i = 0; i < 6 - lockIDData.length; i++) { + numbers.add(0); + } + //todo: 开门暂未实现 + // logic.udpOpenDoorAction(numbers); + }, + cancelClick: () { + Get.back(); + }, + ); + }, + ); + } + + Future requestMicrophonePermission() async { + await logic.getPermissionStatus().then((bool value) async { + if (!value) { + return; + } + }); + } + + Future captureAndSavePng() async { + try { + if (state.globalKey.currentContext == null) { + AppLog.log('截图失败: 未找到当前上下文'); + return; + } + final RenderRepaintBoundary boundary = state.globalKey.currentContext! + .findRenderObject()! as RenderRepaintBoundary; + final ui.Image image = await boundary.toImage(); + final ByteData? byteData = + await image.toByteData(format: ui.ImageByteFormat.png); + if (byteData == null) { + AppLog.log('截图失败: 图像数据为空'); + return; + } + final Uint8List pngBytes = byteData.buffer.asUint8List(); + + final Directory directory = await getApplicationDocumentsDirectory(); + final String imagePath = '${directory.path}/screenshot.png'; + + final File imgFile = File(imagePath); + await imgFile.writeAsBytes(pngBytes); + + await ImageGallerySaver.saveFile(imagePath); + + AppLog.log('截图保存路径: $imagePath'); + logic.showToast('截图已保存到相册'.tr); + } catch (e) { + AppLog.log('截图失败: $e'); + } + } + + void _getTVDataRefreshUIAction() { + state.getTVDataRefreshUIEvent = eventBus + .on() + .listen((GetTVDataRefreshUI event) async { + if (event.tvList.isNotEmpty && event.tvList.length > 100) { + final Uint8List imageData = Uint8List.fromList(event.tvList); + if (!listEquals(state.listPhotoData.value, imageData)) { + state.listPhotoData.value = imageData; + state.shouldUpdateUI.value = true; + if (state.shouldUpdateUI.value) { + setState(() {}); + state.shouldUpdateUI.value = false; + } + } + } + }); + } + + @override + void dispose() { + super.dispose(); + logic.stopProcessing(); + state.getTVDataRefreshUIEvent!.cancel(); + } + + Widget _buildTalkView({required bool isMpeg4}) { + return isMpeg4 ? _buildMpeg4TalkView() : _buildH264TalkView(); + } + + Widget _buildMpeg4TalkView() { + return Stack( + children: [ + Image.memory( + state.listPhotoData.value, + gaplessPlayback: true, + width: 1.sw, + height: 1.sh, + fit: BoxFit.cover, + filterQuality: FilterQuality.high, + errorBuilder: + (BuildContext context, Object error, StackTrace? stackTrace) { + return Container(color: Colors.transparent); + }, + ), + Positioned( + top: ScreenUtil().statusBarHeight + 30.h, + width: 1.sw, + child: Obx(() { + final String sec = + (state.oneMinuteTime.value % 60).toString().padLeft(2, '0'); + final String min = + (state.oneMinuteTime.value ~/ 60).toString().padLeft(2, '0'); + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('$min:$sec', + style: TextStyle(fontSize: 26.sp, color: Colors.white)), + ], + ); + }), + ), + Positioned( + bottom: 10.w, + child: Container( + width: 1.sw - 30.w * 2, + margin: EdgeInsets.all(30.w), + decoration: BoxDecoration( + color: const Color(0xC83C3F41), + borderRadius: BorderRadius.circular(20.h), + ), + child: Column( + children: [ + SizedBox(height: 20.h), + buildTopButtons(), + SizedBox(height: 20.h), + buildBottomButtons(), + SizedBox(height: 20.h), + ], + ), + ), + ), + ], + ); + } + + Widget _buildH264TalkView() { + return Stack( + children: [ + H264WebView(), + Positioned( + top: ScreenUtil().statusBarHeight + 30.h, + width: 1.sw, + child: Obx(() { + final String sec = + (state.oneMinuteTime.value % 60).toString().padLeft(2, '0'); + final String min = + (state.oneMinuteTime.value ~/ 60).toString().padLeft(2, '0'); + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('$min:$sec', + style: TextStyle(fontSize: 26.sp, color: Colors.white)), + ], + ); + }), + ), + Positioned( + bottom: 10.w, + child: Container( + width: 1.sw - 30.w * 2, + margin: EdgeInsets.all(30.w), + decoration: BoxDecoration( + color: const Color(0xC83C3F41), + borderRadius: BorderRadius.circular(20.h), + ), + child: Column( + children: [ + SizedBox(height: 20.h), + buildTopButtons(), + SizedBox(height: 20.h), + buildBottomButtons(), + SizedBox(height: 20.h), + ], + ), + ), + ), + ], + ); + } +} diff --git a/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_state.dart b/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_state.dart new file mode 100644 index 00000000..4a8ddfc4 --- /dev/null +++ b/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_state.dart @@ -0,0 +1,57 @@ +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:flutter/material.dart'; +import 'package:flutter_voice_processor/flutter_voice_processor.dart'; +import 'package:get/get.dart'; +import 'package:network_info_plus/network_info_plus.dart'; +import 'package:star_lock/talk/startChart/start_chart_talk_status.dart'; + +import '../../../../tools/storage.dart'; + +class StarChartState { + RxBool isOpenVoice = false.obs; + int udpSendDataFrameNumber = 0; // 帧序号 + // var isSenderAudioData = false.obs;// 是否要发送音频数据 + StreamSubscription? getTVDataRefreshUIEvent; //收到视频流数据 + RxBool shouldUpdateUI = false.obs; //是否需要更新UI + + Future userMobileIP = NetworkInfo().getWifiIP(); + Future userUid = Storage.getUid(); + + // RxInt udpStatus = + // 0.obs; //0:初始状态 1:等待监视 2: 3:监视中 4:呼叫成功 5:主角通话中 6:被叫通话 8:被叫通话中 9:长按说话 + TextEditingController passwordTF = TextEditingController(); + + Rx listPhotoData = Uint8List(0).obs; //得到的视频流字节数据 + RxList listAudioData = [].obs; //得到的音频流字节数据 + +//录音相关 + late VoiceProcessor? voiceProcessor; + RxBool isProcessing = false.obs; //是否正在处理音频数据 + RxBool isButtonDisabled = false.obs; //是否禁用按钮 + final int frameLength = 320; //音视频帧长度为320 + final int sampleRate = 8000; //音频采样率为8000 + RxString errorMessage = ''.obs; + List> allFrames = >[]; + + GlobalKey globalKey = GlobalKey(); + + late Timer oneMinuteTimeTimer = + Timer(const Duration(seconds: 1), () {}); // 定时器超过60秒关闭当前界面 + RxInt oneMinuteTime = 0.obs; // 定时器秒数 + + // 定时器如果发送了接听的命令 而没收到回复就每秒重复发送10次 + late Timer answerTimer = Timer(const Duration(seconds: 1), () {}); //接听命令定时器 + RxInt answerSeconds = 0.obs; + RxBool isClickAnswer = false.obs; //是否点击了接听按钮 + + late Timer hangUpTimer = Timer(const Duration(seconds: 1), () {}); //挂断命令定时器 + RxInt hangUpSeconds = 0.obs; + RxBool isClickHangUp = false.obs; //是否点击了挂断按钮 + + late Timer openDoorTimer = Timer(const Duration(seconds: 1), () {}); //开门命令定时器 + RxInt openDoorSeconds = 0.obs; + + RxInt talkStatus = 0.obs; //星图对讲状态 +} diff --git a/lib/main/lockMian/demoMode/demoModeLockDetail/demoModeLockDetail_page.dart b/lib/main/lockMian/demoMode/demoModeLockDetail/demoModeLockDetail_page.dart index b33c0663..ffc757c6 100755 --- a/lib/main/lockMian/demoMode/demoModeLockDetail/demoModeLockDetail_page.dart +++ b/lib/main/lockMian/demoMode/demoModeLockDetail/demoModeLockDetail_page.dart @@ -187,7 +187,7 @@ class _DemoModeLockDetailPageState extends State { width: 6.w, ), Text( - '网关设备'.tr, + '网关设备英文'.tr, style: TextStyle(fontSize: 20.sp, color: AppColors.btnDisableColor), ), @@ -227,8 +227,8 @@ class _DemoModeLockDetailPageState extends State { // 考勤 // if (state.keyInfos.value.isAttendance == 1) { - showWidgetArr.add(bottomItem('images/main/icon_main_clockingIn.png', - '考勤'.tr, () { + showWidgetArr + .add(bottomItem('images/main/icon_main_clockingIn.png', '考勤'.tr, () { // gotoLogin(); Get.toNamed(Routers.checkingInListPage, arguments: LockListInfoItemEntity()); @@ -237,34 +237,35 @@ class _DemoModeLockDetailPageState extends State { final List defaultWidgetArr = [ // 电子钥匙 - bottomItem('images/main/icon_main_electronicKey.png', - '电子钥匙'.tr, () { + bottomItem('images/main/icon_main_electronicKey.png', '电子钥匙'.tr, () { // gotoLogin(); Get.toNamed(Routers.electronicKeyListPage, - arguments: {'keyInfo': LockListInfoItemEntity()}); + arguments: { + 'keyInfo': LockListInfoItemEntity() + }); }), // 密码 - bottomItem('images/main/icon_main_password.png', - '密码'.tr, () { + bottomItem('images/main/icon_main_password.png', '密码'.tr, () { // gotoLogin(); Get.toNamed(Routers.passwordKeyListPage, - arguments: {'keyInfo': LockListInfoItemEntity()}); + arguments: { + 'keyInfo': LockListInfoItemEntity() + }); }), // ic卡 - bottomItem('images/main/icon_main_icCard.png', - '卡'.tr, () { + bottomItem('images/main/icon_main_icCard.png', '卡'.tr, () { // gotoLogin(); - Get.toNamed(Routers.cardListPage, arguments: {'lockId': 0}); + Get.toNamed(Routers.cardListPage, + arguments: {'lockId': 0}); }), // 指纹 - bottomItem('images/main/icon_main_fingerprint.png', - '指纹'.tr, () { + bottomItem('images/main/icon_main_fingerprint.png', '指纹'.tr, () { // gotoLogin(); Get.toNamed(Routers.fingerprintListPage, @@ -272,8 +273,7 @@ class _DemoModeLockDetailPageState extends State { }), // 遥控 - bottomItem('images/main/icon_main_remoteControl.png', - '遥控'.tr, gotoLogin), + bottomItem('images/main/icon_main_remoteControl.png', '遥控'.tr, gotoLogin), ]; showWidgetArr.addAll(defaultWidgetArr); @@ -295,18 +295,21 @@ class _DemoModeLockDetailPageState extends State { final List endWiddget = [ // 授权管理员 - bottomItem('images/main/icon_main_authorizedAdmin.png', - '授权管理员'.tr, () { + bottomItem('images/main/icon_main_authorizedAdmin.png', '授权管理员'.tr, () { // gotoLogin(); Get.toNamed(Routers.authorizedAdminListPage, - arguments: {'keyInfo': LockListInfoItemEntity()}); + arguments: { + 'keyInfo': LockListInfoItemEntity() + }); }), // 操作记录 bottomItem('images/main/icon_main_operatingRecord.png', '操作记录'.tr, () { // gotoLogin(); Get.toNamed(Routers.lockOperatingRecordPage, - arguments: {'keyInfo': LockListInfoItemEntity()}); + arguments: { + 'keyInfo': LockListInfoItemEntity() + }); }), // 视频日志 bottomItem('images/main/icon_lockDetail_videoLog.png', '视频日志'.tr, () { @@ -319,9 +322,7 @@ class _DemoModeLockDetailPageState extends State { Get.toNamed(Routers.msgNotificationPage); }), // 设置 - bottomItem( - 'images/main/icon_main_set.png', '设置'.tr, - () { + bottomItem('images/main/icon_main_set.png', '设置'.tr, () { Get.toNamed(Routers.demoModeLockSetPage); }), ]; diff --git a/lib/main/lockMian/lockList/lockList_xhj_page.dart b/lib/main/lockMian/lockList/lockList_xhj_page.dart index 3e74f0d1..790e985e 100755 --- a/lib/main/lockMian/lockList/lockList_xhj_page.dart +++ b/lib/main/lockMian/lockList/lockList_xhj_page.dart @@ -290,21 +290,25 @@ class _LockListXHJPageState extends State with RouteAware { const Spacer(), Column( children: [ - Row( - children: [ - Image.asset( - logic.showElectricIcon(keyInfo.electricQuantity!), - width: 30.w, - height: 24.w, - ), - SizedBox(width: 2.w), - Text( - '${keyInfo.electricQuantity!}%', - style: TextStyle( - fontSize: 16.sp, - color: AppColors.darkGrayTextColor), - ), - ], + SizedBox( + width: (1.sw - 10.w * 3) / 2 - 48.w - 50.w, + child: Row( + children: [ + Spacer(), + Image.asset( + logic.showElectricIcon(keyInfo.electricQuantity!), + width: 30.w, + height: 24.w, + ), + SizedBox(width: 2.w), + Text( + '${keyInfo.electricQuantity!}%', + style: TextStyle( + fontSize: 16.sp, + color: AppColors.darkGrayTextColor), + ), + ], + ), ), SizedBox( width: (1.sw - 10.w * 3) / 2 - 48.w - 50.w, @@ -316,6 +320,7 @@ class _LockListXHJPageState extends State with RouteAware { : '普通用户'.tr), maxLines: 1, overflow: TextOverflow.ellipsis, + textAlign: TextAlign.right, style: TextStyle( fontSize: 16.sp, color: AppColors.darkGrayTextColor), diff --git a/lib/main/lockMian/lockMain/lockMain_page.dart b/lib/main/lockMian/lockMain/lockMain_page.dart index b4e92804..babe6e59 100755 --- a/lib/main/lockMian/lockMain/lockMain_page.dart +++ b/lib/main/lockMian/lockMain/lockMain_page.dart @@ -1,12 +1,15 @@ import 'dart:async'; +import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:star_lock/app_settings/app_colors.dart'; import 'package:star_lock/blue/blue_manage.dart'; import 'package:star_lock/main/lockMian/lockList/lockList_xhj_page.dart'; import 'package:star_lock/main/lockMian/lockMain/lockMain_state.dart'; +import 'package:star_lock/talk/startChart/proto/talk_request.pb.dart'; import 'package:star_lock/talk/startChart/start_chart_manage.dart'; import 'package:star_lock/tools/noData.dart'; import 'package:star_lock/tools/submitBtn.dart'; @@ -104,6 +107,13 @@ class _StarLockMainPageState extends State ), onPressed: () { Scaffold.of(context).openDrawer(); + final writeToBuffer = TalkReq( + callerName: 'T9A_d9904c8c47c8', + callerType: TalkReq_CallerTypeE.Lock) + .writeToBuffer(); + final talkReq = TalkReq.fromBuffer(writeToBuffer); + + print('$talkReq\nwriteToBuffer:$writeToBuffer'); }, )), backgroundColor: AppColors.mainColor, @@ -219,6 +229,22 @@ class _StarLockMainPageState extends State SizedBox( height: 160.h, ), + // _buildImage(), + SubmitBtn( + btnName: '发送回声测试'.tr, + onClick: () async { + String assetPath = 'assets/test.jpg'; // 替换为你的图片路径 + List imageBytes = await loadAssetImageAsBytes(assetPath); + // String testStr = + // '---天地玄黄宇宙洪荒日月盈昃辰宿列张寒来暑往秋收冬藏闰余成岁律吕调阳云腾致雨露结为霜金生丽水玉出昆冈剑号巨阙珠称夜光果珍李柰菜重芥姜海咸河淡鳞潜羽翔龙师火帝鸟官人皇始制文字乃服衣裳推位让国有虞陶唐吊民伐罪周发殷汤坐朝问道垂拱平章爱育黎首臣伏戎羌遐迩体率宾归王鳴鳳翔兮神靈應和炫耀光芒照灼穹蒼迤邐岷峨嶢峻崢巍懿承緒劬勞育秩延佚賡孳蕃鑑識祗崇乾坤纘宵旰卿芮詒朔皎琲犂檄圮黯馭燎竈硎洮蠟胝攢囤嶇葺錡堯羲冕箕翬騏闡燮鸞蓊枘橐榘稟泗沂涖浹涔浣淇漱瀋潢瀾沚澮澆潦瀦瀌瀹灧炅焯燠燋爨熠焜煆烜燴炻熛燧牝牯犛犴牖牒疰疴痀癜痱癃皞皎盂盰盱盻眚眵瞋瞑瞷矙矧矬矰矞砟砉砥砣硇磑磲硤硭礌礞礡祀祚祜祧祼祺禋禡秭秣稃稞稹稷穈穄窀窆窠窸笄筇筌筅筮箦篑篯簟籀籝糅糗紵紽紾綃綈綬綣緜縞縰縻縴繢繇繙罟罾羝羶羸羼翊翕翥翡翳翽耖耜耠耱耦耧耩耨耬耵耶胂胼胬脘腽膦臢臬臾舂舄舡舸艋艏艟艤艚艨艪艭艴芏芊苣苴苕茌茱荄荃莛莪莶菰萁菸菽萸葶蒯蓍蓐蓬蓼蔌蔪蕈蕖蕙蕺蕻薷藦藨藭蘅蘧蘼虍虔虬虮虰虺虻蚨蚋蚱蛏蛘蜊蜍蜉蜣蜥蜩蜴蜱蜮蜾蝣蝤蝥螓螯螨蟒蟑蟛蠊蠋蠛蠡蠹衄衒衢衾袢袷裎裥裨裾褊褙褚褡褰褶襁襦襻觇觋觖觫觿訇訑訾詑詈詟詹誊誨誥誦誨諉諛謏謦譊譖譟譬譯譴讴讵讷诐诪诮诰诳诶谂谄谌谏谑谟谡谥谧谮谯谳谵豇豉豕豚豳豸貂貊貔賑賚賡贐赍赑赗赪赭赳趑趔趱趿跂跏跎跖跗跣跹跽踆踔踝踟踬踮踯蹀蹅蹇蹉蹐蹙蹦蹩躅躐躔躜躞軎軑軔軛軫軬軺輀輅輇輈輐輗輢輦輭輶轋轘轜辀辂辒辚辩迓迕迤迨迮逄逋逑逖逯遄遘遑遴遽邂邈邋邙邡邴邳邶郅郇郛郡郾鄌鄑鄘鄜鄞鄢鄣鄯鄹酃酆酈酖酗酘酢酤酴酹酽酾酾醅醊醑醚醢醪醭醮醯醵醴醶釃釅釐釜釡釴釸釾鉅鈦鈍鈹鈾鈿鉦鉬鉮鉻鉿銎銋銖銩銫銮銲鋈鋋鋌鋮鋯鋹鋻錎錡錣錤鍉鍐鍬鍱鍾鎏鎑鎒鎰鎵鎸鎿鏊鏖鏞鏟鏸鏹鏺鏽鐃鐋鐔鐛鐠鐣鐦鐭鐮鐯鐳鐴鐵鐼鐿鑌鑒鑔鑕鑞鑢鑬鑰鑱鑲鑴鑽鑾鑿钁钆钇钋钍钏钔钗钜钯钴钷钹钺钼钽钿铄铈铊铍铐铖铗铘铙铚铠铨铪铬铮铰铹铼铿锃锆锊锍锎锏锒锓锔锖锗锘锞锟锢锩锫锬锭锯锴锶锷锸锺锼锾镂镄镅镆镉镎镏镒镔镖镙镛镞镡镢镤镩镪镫镬镭镮镯镰镱镲镳镴镶镸长門閃閔閘閡闅闈闑闒闓闔闛闞闠闤闥闦闬闿阂阃阄阆阇阘阛阝队阡阯阱阪阽陀陂陉陔陘陞陟陧陬陲陴陶隃隋隍隒隓隗隦隰隱隳隵隶隽隿雎雋雐雚雝雟雤雩雯雱雿霈霅霌霎霏霗霙霛霝霡霣霤霧靂靅靆靉靎靏靐靕靗靛靡靺靻靽鞀鞉鞎鞑鞔鞖鞚鞝鞡鞤鞧鞨鞫鞬鞮鞯鞳鞴韁韃韈韉韋韐韒韓韗韙韝韟韢韡韣韦韧韨韩韪韫韬韭韮韯韲音頍頏頔頖頞頟頤頦頬頰頲頴頵頹頽頿顃顅顈顊顋顒顕顗顛顝顟顤顪顫顬顮顰顱顲顳顴页顶顷顸颃预颋颌颎颏颐频颓颔颕颙颖颛颟颡颢颣颤颥颦颧風颮颯颰颱颳颶颷颸颹颻颼颾飁飆飇飉飋飏飐飔飗飘飙飚飛飜飝飛飜飝飛飜飝飛飜飝雊霺霿靁靟鞲韞韭頫顴颿飌飡馺駃騑騜髐鬃鰩鳯鷊黴在古老的东方有一座美丽的城市名为锦绣锦绣城四季如春风景秀丽是人们心中的理想之地城中有一条清澈见底的小河河水潺潺流过滋养着两岸的花草树木河边有一座古老的石桥桥上雕刻着精美的图案见证了无数过往行人锦绣城的居民勤劳善良他们日出而作日落而息过着简单而幸福的生活城中有一位智者名叫慧心慧心先生博学多才深受人们的尊敬他常常在河边的亭子里给孩子们讲述历史故事传授知识和智慧孩子们围坐在他身边听得津津有味仿佛置身于一个个奇妙的世界在锦绣城的北边有一片茂密的森林森林里生活着各种各样的动物有活泼可爱的猴子它们在树上跳跃嬉戏有威武雄壮的老虎它们在林间巡视守护着森林的安宁还有许多不知名的鸟儿它们在枝头欢快地歌唱为森林增添了无限生机一天慧心先生带着几个学生走进森林进行一次生动的自然课他们观察着各种植物的生长了解它们的特性聆听鸟儿的鸣叫感受大自然的和谐学生们兴奋不已他们发现大自然是一个神奇的宝库蕴藏着无尽的奥秘在森林的深处有一片神秘的湖泊湖水碧绿如玉清澈见底传说中湖中住着一位美丽的水仙子她用神奇的力量保护着湖泊和周围的生灵慧心先生告诉学生们要爱护大自然与万物和谐共处才能得到大自然的馈赠锦绣城的居民们深知这一点他们珍惜每一滴水每一寸土地努力保护着这片美丽的家园他们相信只要人与自然和谐相处锦绣城将永远充满生机与活力锦绣城外群山环绕山间云雾缭绕宛如仙境山中有一处幽静的山谷谷中开满了五颜六色的花朵香气扑鼻引得蝴蝶翩翩起舞山谷中还有一条蜿蜒的小径两旁长满了奇花异草仿佛是一条通往神秘世界的通道慧心先生的学生们在一次探险中偶然发现了这个山谷他们惊叹于大自然的鬼斧神工纷纷拿出画笔将这美丽的景色描绘下来他们还发现了一种奇特的植物它的叶子呈现出透明的蓝色在阳光下闪闪发光仿佛蕴含着神秘的力量慧心先生告诉他们这种植物名为“梦幻草”只生长在特定的环境中非常稀有在锦绣城的东边有一片广阔的草原草原上绿草如茵牛羊成群草原上还有一座古老的风车风车的叶片随风旋转发出“吱呀吱呀”的声响仿佛在诉说着岁月的故事草原上的人们以放牧为生他们骑着骏马驰骋在广阔的天地间享受着自由自在的生活一天慧心先生带领学生们来到草原给他们上了一堂生动的地理课他指着远处的山脉告诉学生们山脉的形成过程以及它们对气候和生态环境的影响学生们听得入迷仿佛置身于大自然的怀抱中感受到了大自然的壮丽与神奇在锦绣城的南边有一片茂密的竹林竹林里竹子挺拔绿意盎然竹林中有一条清澈的小溪溪水潺潺流淌溪边长满了青苔竹林里还有一座精致的小亭子亭子的柱子上刻着优美的诗句让人感受到一种宁静与雅致慧心先生常常在竹林中的小亭子里静坐思考人生的哲理他告诉学生们竹子虽然柔弱但却有着坚韧不拔的精神无论遇到多大的困难都能顽强地生长学生们深受启发明白了在人生的道路上要像竹子一样勇敢地面对挑战坚持不懈地追求自己的理想锦绣城的居民们还擅长制作各种手工艺品他们的作品精美绝伦远近闻名有巧夺天工的陶瓷色彩斑斓形态各异有细腻精致的刺绣图案生动栩栩如生还有雕刻精美的木雕栩栩如生令人叹为观止这些手工艺品不仅展现了锦绣城居民的智慧和技艺也成为了他们与外界交流的纽带在锦绣城的中心有一座宏伟的宫殿宫殿的建筑风格独特气势恢宏宫殿的屋顶覆盖着金色的琉璃瓦在阳光下熠熠生辉宫殿的墙壁上雕刻着精美的图案栩栩如生仿佛在诉说着一个个古老的故事宫殿里住着一位英明的君主他以仁爱之心治理国家深受百姓的爱戴慧心先生常常受邀到宫殿中为君主出谋划策帮助他解决国家大事君主也非常尊重慧心先生的智慧常常向他请教治国之道在他们的共同努力下锦绣城国泰民安繁荣昌盛锦绣城的居民们还非常重视教育他们相信知识能够改变命运让孩子们拥有更加美好的未来城中有一座古老的书院书院的建筑古朴典雅环境优美书院里有许多博学的老师他们用心地教导学生传授知识和智慧学生们在这里努力学习汲取知识的养分,为将来的发展打下坚实的基础慧心先生也常常到书院授课他用自己的知识和智慧启迪学生们的思维引导他们去探索未知的世界学生们对慧心先生敬仰有加他们知道只有不断学习才能像慧心先生一样拥有渊博的知识和智慧为社会做出贡献锦绣城的故事还有很多这里的人们用自己的勤劳和智慧创造了一个充满生机与活力的美好家园他们相信只要人与自然和谐相处与他人携手共进锦绣城的明天一定会更加美好=='; + + // List imageBytes = utf8.encode(testStr).toList(); + // List imageBytes = utf8.encode(testStr).toList(); + // state.talkData.value = imageBytes; + // setState(() {}); + StartChartManage().sendEchoMessage(payload: imageBytes); + }, + ), if (F.isLite) Container() else @@ -247,6 +273,23 @@ class _StarLockMainPageState extends State }); } + Future> loadAssetImageAsBytes(String assetPath) async { + try { + // 从资产中加载字节数据 + ByteData byteData = await rootBundle.load(assetPath); + + // 将 ByteData 转换为 Uint8List + Uint8List uint8List = + Uint8List.sublistView(byteData); //byteData.buffer.asUint8List(); + + // 返回字节数组 + return uint8List.toList(); + } catch (e) { + print('从资产加载图片时发生错误: $e'); + rethrow; + } + } + @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); diff --git a/lib/main/lockMian/lockMain/xhj/lockMain_xhj_logic.dart b/lib/main/lockMian/lockMain/xhj/lockMain_xhj_logic.dart index ce6ecb96..ae48b082 100755 --- a/lib/main/lockMian/lockMain/xhj/lockMain_xhj_logic.dart +++ b/lib/main/lockMian/lockMain/xhj/lockMain_xhj_logic.dart @@ -3,6 +3,7 @@ import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; +import 'package:star_lock/app_settings/app_settings.dart'; import 'package:star_lock/main/lockMian/lockMain/lockMain_page.dart'; import 'package:star_lock/main/lockMian/lockMain/xhj/lockMain_xhj_state.dart'; import 'package:star_lock/mine/minePersonInfo/minePersonInfoPage/minePersonInfo_entity.dart'; @@ -12,6 +13,8 @@ import 'package:star_lock/tools/baseGetXController.dart'; import 'package:star_lock/tools/push/xs_jPhush.dart'; import 'package:star_lock/tools/storage.dart'; +import '../../../../tools/store_service.dart'; + class LockMainXHJLogic extends BaseGetXController { final LockMainXHJState state = LockMainXHJState(); @@ -26,15 +29,20 @@ class LockMainXHJLogic extends BaseGetXController { Future getUserInfoRequest() async { final MinePersonInfoEntity entity = await ApiRepository.to.getUserInfo(); if (entity.errorCode!.codeIsSuccessful) { - final String languageCodeAndCountryCode = entity.data!.lang ?? 'zh-CN'; - if (languageCodeAndCountryCode.contains('-')) { + final String languageCodeAndCountryCode = entity.data!.lang!; + if (languageCodeAndCountryCode.isEmpty) { + await StoreService.to.saveLanguageCode(''); + } else if (languageCodeAndCountryCode.contains('-')) { final List parts = languageCodeAndCountryCode.split('-'); final Locale locale = Locale(parts[0], parts[1]); - Get.updateLocale(locale); + await Get.updateLocale(locale); + await StoreService.to.saveLanguageCode(locale.toString()); } else if (languageCodeAndCountryCode.contains('_')) { final List parts = languageCodeAndCountryCode.split('_'); final Locale locale = Locale(parts[0], parts[1]); - Get.updateLocale(locale); + await Get.updateLocale(locale); + AppLog.log('用户信息请求成功 更新locale: $locale'); + await StoreService.to.saveLanguageCode(locale.toString()); } Storage.setBool(saveIsVip, entity.data!.isVip == 1); diff --git a/lib/mine/mineMultiLanguage/mineMultiLanguage_logic.dart b/lib/mine/mineMultiLanguage/mineMultiLanguage_logic.dart index 0c1ee11c..459615f6 100755 --- a/lib/mine/mineMultiLanguage/mineMultiLanguage_logic.dart +++ b/lib/mine/mineMultiLanguage/mineMultiLanguage_logic.dart @@ -5,6 +5,9 @@ import 'package:star_lock/tools/baseGetXController.dart'; import '../../main/lockDetail/passwordKey/passwordKeyList/passwordKeyListEntity.dart'; import '../../network/api_repository.dart'; import '../../tools/eventBusEventManage.dart'; +import '../../tools/store_service.dart'; +import '../../translations/app_dept.dart'; +import '../../translations/current_locale_tool.dart'; import 'mineMultiLanguage_state.dart'; class MineMultiLanguageLogic extends GetxController { @@ -13,20 +16,21 @@ class MineMultiLanguageLogic extends GetxController { //更新个人信息 Future updateUserLangInfo(Locale l) async { // AppLog.log('lanTypeTitle: $lanTypeTitle'); - - final String lang = l.toLanguageTag(); + String lang = l.toString(); + if (state.currentLanguageType.value == LanguageType.system) { + lang = ''; + } final PasswordKeyListEntity entity = await ApiRepository.to.updateUserLangInfo(lang: lang); if (entity.errorCode!.codeIsSuccessful) { await changeLanguage(l); eventBus.fire(ChangeLanguageBlockLastLanguageEvent()); - print('发送语言变化事件'); } } Future changeLanguage(Locale l) async { - if (l == Get.locale) return; await Get.updateLocale(l); - state.resetLan(); + await StoreService.to.saveLanguageCode( + CurrentLocaleTool.convertLocale(Get.locale!).toString()); } } diff --git a/lib/mine/mineMultiLanguage/mineMultiLanguage_page.dart b/lib/mine/mineMultiLanguage/mineMultiLanguage_page.dart index 9422f4cb..87e1c395 100755 --- a/lib/mine/mineMultiLanguage/mineMultiLanguage_page.dart +++ b/lib/mine/mineMultiLanguage/mineMultiLanguage_page.dart @@ -1,8 +1,8 @@ - import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:star_lock/mine/mineMultiLanguage/mineMultiLanguage_state.dart'; +import 'package:star_lock/translations/current_locale_tool.dart'; import '../../app_settings/app_colors.dart'; import '../../tools/commonItem.dart'; @@ -26,35 +26,66 @@ class _MineMultiLanguagePageState extends State { return Scaffold( backgroundColor: AppColors.mainBackgroundColor, appBar: TitleAppBar( - barTitle: '多语言'.tr, - haveBack: true, - backgroundColor: AppColors.mainColor), - body: ListView( - // mainAxisAlignment: MainAxisAlignment.start, - // mainAxisSize: MainAxisSize.min, - children: _children(), - ) - ); + barTitle: '多语言'.tr, + haveBack: true, + backgroundColor: AppColors.mainColor, + actionsList: [ + TextButton( + onPressed: () async { + await logic.updateUserLangInfo(state.seletLocale); + final String lanTypeTitle = + ExtensionLanguageType.fromLocale(state.seletLocale) + .lanTitle; + Get.back(result: {'currentLanguage': lanTypeTitle}); + }, + child: Text( + '保存'.tr, + style: TextStyle( + color: Colors.white, + fontSize: 22.sp, + ), + ), + ), + ], + ), + body: Obx(() => ListView( + // mainAxisAlignment: MainAxisAlignment.start, + // mainAxisSize: MainAxisSize.min, + children: _children(), + ))); } List _children() { final List l = []; - // l.add( - // CommonItem( - // leftTitel: '跟随系统', - // rightTitle: "", - // isHaveLine: true, - // isHaveDirection: false, - // isHaveRightWidget: true, - // rightWidget: Container(), - // action: () { - // // logic.changeLanguage(e); - // }), - // ); + l.add( + CommonItem( + leftTitel: '跟随系统', + rightTitle: '', + isHaveLine: true, + isHaveDirection: false, + isHaveRightWidget: true, + rightWidget: state.currentLanguageType.value == LanguageType.system + ? Image( + image: const AssetImage('images/icon_item_checked.png'), + width: 30.w, + height: 30.w, + fit: BoxFit.contain, + ) + : Container(), + action: () { + state.seletLocale = + CurrentLocaleTool.convertLocale(Get.deviceLocale!); + state.currentLanguageType.value = LanguageType.system; + }), + ); for (int i = 0; i < state.languages.length; i++) { final Locale e = state.languages[i]; final LanguageType lanType = ExtensionLanguageType.fromLocale(e); // AppLog.log('e:$e lanType:$lanType state.currentLanguageType.value:${state.currentLanguageType.value} Get.locale!.languageCode:${Get.locale!.languageCode} Get.locale!.countryCode:${Get.locale!.countryCode}'); + + if (state.currentLanguageType.value == lanType) { + state.seletLocale = e; + } l.add( CommonItem( leftTitel: lanType.lanTitle, @@ -62,17 +93,19 @@ class _MineMultiLanguagePageState extends State { isHaveLine: true, isHaveDirection: false, isHaveRightWidget: true, - rightWidget: Obx(() => state.currentLanguageType.value == lanType + rightWidget: state.currentLanguageType.value == lanType ? Image( image: const AssetImage('images/icon_item_checked.png'), width: 30.w, height: 30.w, fit: BoxFit.contain, ) - : Container()), + : Container(), action: () { - logic.updateUserLangInfo(e); - // eventBus.fire(ChangeLanguageBlockLastLanguageEvent(lanType.lanTitle)); + // logic.updateUserLangInfo(e); + state.seletLocale = e; + state.currentLanguageType.value = + ExtensionLanguageType.fromLocale(state.seletLocale); }), ); } diff --git a/lib/mine/mineMultiLanguage/mineMultiLanguage_state.dart b/lib/mine/mineMultiLanguage/mineMultiLanguage_state.dart index 573b04f5..c424b8e9 100755 --- a/lib/mine/mineMultiLanguage/mineMultiLanguage_state.dart +++ b/lib/mine/mineMultiLanguage/mineMultiLanguage_state.dart @@ -6,19 +6,16 @@ import '../../tools/store_service.dart'; import '../../translations/app_dept.dart'; class MineMultiLanguageState { - MineMultiLanguageState() { - resetLan(); - } + // MineMultiLanguageState() { + // resetLan(); + // } List get languages { return appDept.deptSupportedLocales; } - var currentLanguageType = ExtensionLanguageType.fromLocale(Get.locale!).obs; + Rx currentLanguageType = + ExtensionLanguageType.fromLocale(Get.locale!).obs; - Future resetLan() async { - currentLanguageType.value = ExtensionLanguageType.fromLocale(Get.locale!); - // AppLog.log('currentLanguageType.value:${currentLanguageType.value} Get.locale!.languageCode:${Get.locale!.languageCode} languages:$languages'); - await StoreService.to.saveLanguageCode(Get.locale!.toString()); - } + late Locale seletLocale; } diff --git a/lib/mine/mineSet/lockUserManage/lockUserManageList/lockUserManageList_page.dart b/lib/mine/mineSet/lockUserManage/lockUserManageList/lockUserManageList_page.dart index dfd66945..174a938f 100755 --- a/lib/mine/mineSet/lockUserManage/lockUserManageList/lockUserManageList_page.dart +++ b/lib/mine/mineSet/lockUserManage/lockUserManageList/lockUserManageList_page.dart @@ -1,4 +1,4 @@ - +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; @@ -25,7 +25,8 @@ class LockUserManageListPage extends StatefulWidget { class _LockUserManageListPageState extends State { final LockUserManageListLogic logic = Get.put(LockUserManageListLogic()); - final LockUserManageListState state = Get.find().state; + final LockUserManageListState state = + Get.find().state; Future getHttpData() async { logic.lockUserListRequest().then((LockUserListEntity value) { @@ -167,8 +168,9 @@ class _LockUserManageListPageState extends State { arguments: {'uid': itemData.uid}); }, child: Container( - height: 90.h, + // height: 90.h, color: Colors.white, + padding: EdgeInsets.only(top: 15.h, bottom: 15.h), // decoration: BoxDecoration( // color: Colors.white, // borderRadius: BorderRadius.circular(10.w), @@ -192,17 +194,20 @@ class _LockUserManageListPageState extends State { SizedBox( width: 20.w, ), - Expanded( + SizedBox( + width: 1.sw - 30.w - 60.w - 20.w - 20.w - 20.w - 12.w, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - Text( - itemData.nickname ?? '', - style: TextStyle( - fontSize: 24.sp, color: AppColors.blackColor), + Expanded( + child: Text( + itemData.nickname ?? '', + style: TextStyle( + fontSize: 24.sp, color: AppColors.blackColor), + ), ), ], ), @@ -234,7 +239,8 @@ class _LockUserManageListPageState extends State { ); } - void showIosTipViewDialog(BuildContext context, LockUserItemData lockUserData) { + void showIosTipViewDialog( + BuildContext context, LockUserItemData lockUserData) { showDialog( context: context, builder: (BuildContext context) { diff --git a/lib/mine/mineSet/mineSet/mineSet_logic.dart b/lib/mine/mineSet/mineSet/mineSet_logic.dart index 7a581232..672cf196 100755 --- a/lib/mine/mineSet/mineSet/mineSet_logic.dart +++ b/lib/mine/mineSet/mineSet/mineSet_logic.dart @@ -18,14 +18,10 @@ import 'package:umeng_common_sdk/umeng_common_sdk.dart'; import '../../../../network/api_repository.dart'; import '../../../../tools/baseGetXController.dart'; -import '../../../app_settings/app_settings.dart'; import '../../../blue/blue_manage.dart'; import '../../../talk/udp/udp_help.dart'; -import '../../../tools/change_language_format.dart'; import '../../../tools/dateTool.dart'; -import '../../../tools/eventBusEventManage.dart'; import '../../../tools/store_service.dart'; -import '../../../translations/app_dept.dart'; class MineSetLogic extends BaseGetXController { final MineSetState state = MineSetState(); @@ -180,46 +176,14 @@ class MineSetLogic extends BaseGetXController { } } - // 下级界面修改成功后传递数据 - StreamSubscription? _getNumberEvent; - void _initLoadDataAction() { - // 蓝牙协议通知传输跟蓝牙之外的数据传输类不一样 eventBus - _getNumberEvent = eventBus - .on() - .listen((ChangeLanguageBlockLastLanguageEvent event) { - state.currentLanguage.value = _getCurrentLanguage(); - }); - } - - String _getCurrentLanguage() { - String? language = StoreService.to.getLanguageCode(); - AppLog.log('language: $language Get.locale!: ${Get.locale!}'); - if (language!.isEmpty) { - language = ChangeLanguageFormat.convertLocale(Get.locale!).toString(); - } - AppLog.log('language: $language'); - final String currentLanguage = ExtensionLanguageType.fromLocale(appDept - .deptSupportedLocales - .where((Locale element) => element.toString() == language) - .first) - .lanTitle; - return currentLanguage; - } - - @override - void onReady() { - super.onReady(); - - state.currentLanguage.value = _getCurrentLanguage(); - - _initLoadDataAction(); - getUserInfoRequest(); - } - - @override - void onClose() { - super.onClose(); - - _getNumberEvent!.cancel(); - } + // // 下级界面修改成功后传递数据 + // StreamSubscription? _getNumberEvent; + // void _initLoadDataAction() { + // // 蓝牙协议通知传输跟蓝牙之外的数据传输类不一样 eventBus + // _getNumberEvent = eventBus + // .on() + // .listen((ChangeLanguageBlockLastLanguageEvent event) { + // state.currentLanguage.value = CurrentLocaleTool.getCurrentLocaleString(); + // }); + // } } diff --git a/lib/mine/mineSet/mineSet/mineSet_page.dart b/lib/mine/mineSet/mineSet/mineSet_page.dart index c3a2908b..3cb15f4e 100755 --- a/lib/mine/mineSet/mineSet/mineSet_page.dart +++ b/lib/mine/mineSet/mineSet/mineSet_page.dart @@ -6,7 +6,9 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; +import 'package:get/get_state_manager/get_state_manager.dart'; import 'package:permission_handler/permission_handler.dart'; +import 'package:star_lock/app_settings/app_settings.dart'; import 'package:star_lock/flavors.dart'; import 'package:star_lock/mine/mineSet/mineSet/mineSet_logic.dart'; import 'package:star_lock/mine/mineSet/mineSet/mineSet_state.dart'; @@ -170,7 +172,6 @@ class _MineSetPageState extends State Widget getListDataView() { // 检测系统语言是否为中文 - bool isChinese = LanguageTool.instance.isChinese; return Column( children: [ /* 2024-01-12 会议确定去掉“提示音、触摸开锁” by DaisyWu @@ -214,8 +215,9 @@ class _MineSetPageState extends State height: 50.h, child: Obx(_isPushNotificationSwitch))), // if (F.appFlavor == Flavor.sky) - if (isChinese) - CommonItem( + Visibility( + visible: state.currentLanguageName == '简体中文'.tr, + child: CommonItem( leftTitel: '微信公众号推送'.tr, rightTitle: '', isHaveLine: true, @@ -225,9 +227,8 @@ class _MineSetPageState extends State height: 50.h, child: Obx(_isWechatPublicAccountPushSwitch), ), - ) - else - Container(), + ), + ), SizedBox(height: 10.h), CommonItem( leftTitel: '锁用户管理'.tr, @@ -292,19 +293,22 @@ class _MineSetPageState extends State SizedBox( height: 10.h, ), - Obx(() => CommonItem( - leftTitel: '多语言'.tr, - rightTitle: state.currentLanguage.value, - isHaveLine: true, - isHaveDirection: true, - action: () async { - // Get.toNamed(Routers.mineMultiLanguagePage); - var result = await Get.toNamed(Routers.mineMultiLanguagePage); - if (result != null) { - result as Map; - state.currentLanguage.value = result['currentLanguage']; - } - })), + Obx(() { + AppLog.log( + 'state.currentLanguageName: ${state.currentLanguageName} state.currentLanguage.value: ${state.currentLanguage.value}'); + return CommonItem( + leftTitel: '多语言'.tr, + rightTitle: state.currentLanguageName, + isHaveLine: true, + isHaveDirection: true, + action: () async { + // Get.toNamed(Routers.mineMultiLanguagePage); + await Get.toNamed(Routers.mineMultiLanguagePage)!.then( + (value) => { + state.currentLanguage.value = value['currentLanguage'] + }); + }); + }), /* 2024-01-12 会议确定去掉“锁屏” by DaisyWu Obx(() => CommonItem( leftTitel: TranslationLoader.lanKeys!.lockScreen!.tr, diff --git a/lib/mine/mineSet/mineSet/mineSet_state.dart b/lib/mine/mineSet/mineSet/mineSet_state.dart index d4e18272..cae4519d 100755 --- a/lib/mine/mineSet/mineSet/mineSet_state.dart +++ b/lib/mine/mineSet/mineSet/mineSet_state.dart @@ -3,6 +3,9 @@ import 'package:get/get.dart'; import 'package:star_lock/mine/minePersonInfo/minePersonInfoPage/minePersonInfo_entity.dart'; import 'package:star_lock/mine/mineSet/mineSet/userSettingInfoEntity.dart'; +import '../../../translations/app_dept.dart'; +import '../../../translations/current_locale_tool.dart'; + class MineSetState { final Rx userInfoData = UserSettingInfoData().obs; final Rx userSetting = UserSettings().obs; @@ -16,7 +19,17 @@ class MineSetState { RxInt lockScreen = 2.obs; //锁屏 RxInt hideExpiredAccessFlag = 2.obs; //隐藏无效开锁 - RxString currentLanguage = ''.obs; //隐藏无效开锁 + RxString currentLanguage = + CurrentLocaleTool.getCurrentLocaleString().obs; // 当前选择语言 + + /// 获取翻译后的国家名称 + String get currentLanguageName { + return ExtensionLanguageType.fromLocale( + CurrentLocaleTool.getCurrentLocaleWithLanguageCode( + currentLanguage.value)) + .lanTitle; + } + RxBool isAmazonAlexa = false.obs; //亚马逊Alexa RxBool isGoogleHome = false.obs; //谷歌Home Rx amazonAlexaData = AmazonAlexa().obs; diff --git a/lib/network/api_provider.dart b/lib/network/api_provider.dart index c12fb6d2..36801d32 100755 --- a/lib/network/api_provider.dart +++ b/lib/network/api_provider.dart @@ -2707,7 +2707,8 @@ class ApiProvider extends BaseProvider { 'starchartPeerPublicKey': starchartPeerPublicKey, 'starchartPeerPrivateKey': starchartPeerPrivateKey, }), - isUnShowLoading: true); + isUnShowLoading: true, + isShowNetworkErrorMsg: false); } extension ExtensionString on String { diff --git a/lib/network/api_repository.dart b/lib/network/api_repository.dart index ef9594fd..330ba4f3 100755 --- a/lib/network/api_repository.dart +++ b/lib/network/api_repository.dart @@ -2021,7 +2021,7 @@ class ApiRepository { //获取个人信息 Future getUserInfo() async { - final res = await apiProvider.getUserInfo(""); + final res = await apiProvider.getUserInfo(''); return MinePersonInfoEntity.fromJson(res.body); } diff --git a/lib/network/request_interceptor.dart b/lib/network/request_interceptor.dart index 95617873..46f43aea 100755 --- a/lib/network/request_interceptor.dart +++ b/lib/network/request_interceptor.dart @@ -1,16 +1,12 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:ui'; import 'package:get/get.dart'; import 'package:get/get_connect/http/src/request/request.dart'; -import 'package:star_lock/app_settings/app_settings.dart'; import 'package:star_lock/login/login/entity/LoginData.dart'; -import '../tools/change_language_format.dart'; import '../tools/platform_info_services.dart'; import '../tools/storage.dart'; -import '../tools/store_service.dart'; -import '../translations/app_dept.dart'; +import '../translations/current_locale_tool.dart'; //公共获取UA String getUserAgent() { @@ -22,8 +18,8 @@ String getUserAgent() { FutureOr requestInterceptor(Request request) async { request.headers['User-Agent'] = getUserAgent(); - request.headers['Accept-Language'] = - getLanguageCode(); // StoreService.to.getLanguageCode() + request.headers['Accept-Language'] = CurrentLocaleTool + .getCurrentLocaleString(); // StoreService.to.getLanguageCode() // request.headers['Content-Type'] = 'application/json'; // request.headers['token'] = StoreService.to.userToken!; String? xToken = ''; @@ -34,17 +30,3 @@ FutureOr requestInterceptor(Request request) async { request.headers['Authorization'] = "Bearer ${xToken ?? ''}"; return request; } - -String getLanguageCode() { - final Locale locale = StoreService.to.getLanguageCode()!.isNotEmpty - ? appDept.deptSupportedLocales - .where((Locale element) => - element.toString() == StoreService.to.getLanguageCode()) - .first - : Get.locale!; // Get.deviceLocale; - String languageCode = - ChangeLanguageFormat.convertLocale(locale).toLanguageTag(); - AppLog.log( - 'languageCode: ${locale.toLanguageTag()} locale: $locale languageCode:$languageCode'); - return languageCode; -} diff --git a/lib/talk/startChart/appLifecycle_observer.dart b/lib/talk/startChart/appLifecycle_observer.dart new file mode 100644 index 00000000..9f4dab42 --- /dev/null +++ b/lib/talk/startChart/appLifecycle_observer.dart @@ -0,0 +1,42 @@ +import 'package:flutter/widgets.dart'; +import 'package:star_lock/talk/startChart/start_chart_manage.dart'; + +class AppLifecycleObserver extends WidgetsBindingObserver { + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + + // 打印应用程序生命周期状态 + print('AppLifecycleState: $state'); + + // 根据应用程序状态执行相应的操作 + if (state == AppLifecycleState.paused) { + // 应用程序进入后台 + onAppPaused(); + } else if (state == AppLifecycleState.resumed) { + // 应用程序恢复到前台 + onAppResumed(); + } else if (state == AppLifecycleState.detached) { + // 应用程序被杀死 + onAppDetached(); + } + } + + void onAppPaused() { + // 处理应用程序进入后台的逻辑 + print('App has entered the background.'); + StartChartManage().destruction(); + } + + void onAppResumed() { + // 处理应用程序恢复到前台的逻辑 + StartChartManage().init(); + print('App has resumed to the foreground.'); + } + + void onAppDetached() { + // 处理应用程序被杀死的逻辑 + StartChartManage().destruction(); + print('App has been detached.'); + } +} diff --git a/lib/talk/startChart/command/message_command.dart b/lib/talk/startChart/command/message_command.dart index ee17c97e..40038f1a 100644 --- a/lib/talk/startChart/command/message_command.dart +++ b/lib/talk/startChart/command/message_command.dart @@ -16,22 +16,44 @@ import 'package:star_lock/talk/startChart/proto/talk_reject.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_request.pb.dart'; class MessageCommand { + // 全局字典,用于存储每个 ToPeerId 对应的当前 messageId + static Map _messageIdMap = {}; + static int _maxIntValue = 9223372036854775807; // Dart 中 int 的最大值 + + // 获取并递增消息ID + static int getNextMessageId(String toPeerId, {bool increment = true}) { + + if (_messageIdMap.containsKey(toPeerId)) { + if (increment) { + _messageIdMap[toPeerId] = _messageIdMap[toPeerId]! + 1; + // 如果 messageId 超过 int 的最大值,则重置为 1 + if (_messageIdMap[toPeerId]! > _maxIntValue) { + _messageIdMap[toPeerId] = 1; + } + } + } else { + _messageIdMap[toPeerId] = 1; + } + return _messageIdMap[toPeerId]!; + } + /// 客户端去中继上线命令 static List goOnlineRelay({ required String FromPeerId, required String ToPeerId, + int? MessageId, }) { String serializedBytesString = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, - MessageId: 1, - SpTotal: 0, - SpIndex: 0, + MessageId: MessageId, + SpTotal: 1, + SpIndex: 1, FromPeerId: FromPeerId, ToPeerId: ToPeerId, - Payload: 'hello', - PayloadCRC: 55230, - PayloadLength: 5, + Payload: [0], + PayloadCRC: 0, + PayloadLength: 0, PayloadType: PayloadTypeConstant.goOnline, ).serialize(); return _hexToBytes(serializedBytesString); @@ -41,19 +63,22 @@ class MessageCommand { static List echoMessage({ required String ToPeerId, required String FromPeerId, + List? payload, + int? SpTotal, + int? SpIndex, + int? MessageId, }) { - String payload = 'hello'; ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, - MessageId: 1, - SpTotal: 0, - SpIndex: 0, + MessageId: MessageId, + SpTotal: SpTotal, + SpIndex: SpIndex, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, - PayloadCRC: calculationCrc(_stringToUint8List(payload)), - PayloadLength: payload.length, + PayloadCRC: calculationCrcFromIntList(payload ?? []), + PayloadLength: payload?.length ?? 0, PayloadType: PayloadTypeConstant.echoTest, ); String serializedBytesString = message.serialize(); @@ -64,14 +89,15 @@ class MessageCommand { static List heartbeatMessage({ required String FromPeerId, required String ToPeerId, + int? MessageId, }) { String payload = 'hello'; ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, - MessageId: 1, - SpTotal: 0, - SpIndex: 0, + MessageId: MessageId, + SpTotal: 1, + SpIndex: 1, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, @@ -89,6 +115,7 @@ class MessageCommand { required String FromPeerId, required String ToPeerId, required int time, + int? MessageId, }) { // 构建荷载 final gatewayResetReq = GatewayResetReq( @@ -100,9 +127,9 @@ class MessageCommand { ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, - MessageId: 1, - SpTotal: 0, - SpIndex: 0, + MessageId: MessageId, + SpTotal: 1, + SpIndex: 1, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, @@ -118,15 +145,16 @@ class MessageCommand { static List talkAcceptMessage({ required String FromPeerId, required String ToPeerId, + int? MessageId, }) { final talkAcceptReq = TalkAcceptReq(); final payload = talkAcceptReq.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, - MessageId: 1, - SpTotal: 0, - SpIndex: 0, + MessageId: MessageId, + SpTotal: 1, + SpIndex: 1, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, @@ -142,15 +170,16 @@ class MessageCommand { static List talkRequestMessage({ required String FromPeerId, required String ToPeerId, + int? MessageId, }) { final talkReq = TalkReq(); final payload = talkReq.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, - MessageId: 1, - SpTotal: 0, - SpIndex: 0, + MessageId: MessageId, + SpTotal: 1, + SpIndex: 1, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, @@ -166,15 +195,16 @@ class MessageCommand { static List talkRejectMessage({ required String FromPeerId, required String ToPeerId, + int? MessageId, }) { final talkReject = TalkReject(); final payload = talkReject.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, - MessageId: 1, - SpTotal: 0, - SpIndex: 0, + MessageId: MessageId, + SpTotal: 1, + SpIndex: 1, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, @@ -190,15 +220,16 @@ class MessageCommand { static List talkPingMessage({ required String FromPeerId, required String ToPeerId, + int? MessageId, }) { final talkPing = TalkPing(); final payload = talkPing.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, - MessageId: 1, - SpTotal: 0, - SpIndex: 0, + MessageId: MessageId, + SpTotal: 1, + SpIndex: 1, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, @@ -214,15 +245,16 @@ class MessageCommand { static List talkHangupMessage({ required String FromPeerId, required String ToPeerId, + int? MessageId, }) { final talkHangup = TalkHangup(); final payload = talkHangup.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, - MessageId: 1, - SpTotal: 0, - SpIndex: 0, + MessageId: MessageId, + SpTotal: 1, + SpIndex: 1, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, @@ -239,14 +271,15 @@ class MessageCommand { required String FromPeerId, required String ToPeerId, required TalkData talkData, + int? MessageId, }) { final payload = talkData.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.RealTimeData, - MessageId: 1, - SpTotal: 0, - SpIndex: 0, + MessageId: MessageId, + SpTotal: 1, + SpIndex: 1, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, @@ -263,14 +296,15 @@ class MessageCommand { required String FromPeerId, required String ToPeerId, required TalkExpect talkExpect, + int? MessageId, }) { final payload = talkExpect.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, - MessageId: 1, - SpTotal: 0, - SpIndex: 0, + MessageId: MessageId, + SpTotal: 1, + SpIndex: 1, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, @@ -287,6 +321,7 @@ class MessageCommand { required String FromPeerId, required String ToPeerId, required int PayloadType, + int? MessageId, }) { final genericResp = GenericResp(); genericResp.message = 'ok'; @@ -295,9 +330,9 @@ class MessageCommand { ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Resp, - MessageId: 1, - SpTotal: 0, - SpIndex: 0, + MessageId: MessageId, + SpTotal: 1, + SpIndex: 1, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, @@ -314,6 +349,7 @@ class MessageCommand { required String FromPeerId, required String ToPeerId, required int PayloadType, + int? MessageId, }) { final genericResp = GenericResp(); genericResp.message = 'error'; @@ -322,9 +358,9 @@ class MessageCommand { ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Resp, - MessageId: 1, - SpTotal: 0, - SpIndex: 0, + MessageId: MessageId, + SpTotal: 1, + SpIndex: 1, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, @@ -351,6 +387,15 @@ class MessageCommand { return crc32Value; } + // 重载的方法,接受 List + static int calculationCrcFromIntList(List intList) { + // 将 List 转换为 Uint8List + final Uint8List uint8Payload = Uint8List.fromList(intList); + + // 调用现有的 calculationCrc 方法 + return calculationCrc(uint8Payload); + } + // 将字符串转换为 Uint8List static Uint8List _stringToUint8List(String input) { return Uint8List.fromList(utf8.encode(input)); diff --git a/lib/talk/startChart/entity/scp_message.dart b/lib/talk/startChart/entity/scp_message.dart index 361b89f4..a2fbef53 100644 --- a/lib/talk/startChart/entity/scp_message.dart +++ b/lib/talk/startChart/entity/scp_message.dart @@ -1,9 +1,12 @@ import 'dart:convert'; +import 'package:get/get.dart'; +import 'package:protobuf/protobuf.dart'; import 'package:star_lock/app_settings/app_settings.dart'; import 'package:star_lock/talk/startChart/constant/message_type_constant.dart'; import 'package:star_lock/talk/startChart/constant/payload_type_constant.dart'; import 'package:star_lock/talk/startChart/entity/heartbeat_response.dart'; import 'package:star_lock/talk/startChart/entity/login_response.dart'; +import 'package:star_lock/talk/startChart/handle/other/talk_data_repository.dart'; import 'package:star_lock/talk/startChart/proto/ble_message.pb.dart'; import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart'; import 'package:star_lock/talk/startChart/proto/gateway_transfer.pb.dart'; @@ -20,6 +23,10 @@ import 'package:star_lock/talk/startChart/proto/talk_reject.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_request.pb.dart'; class ScpMessage { + /// 分包缓冲区 + // 存储每个 messageId 对应的分包数据 + static Map>> _packetBuffer = {}; + ScpMessage({ this.ProtocolFlag, this.MessageType, @@ -149,7 +156,7 @@ class ScpMessage { // Payload (字符串,转换为字节) if (Payload != null && Payload is String) { bytes.addAll(utf8.encode(Payload!)); - } else { + } else if (Payload != null) { // 如果不是字符串则需要外部转为字节数组,这里直接添加 bytes.addAll(Payload); } @@ -163,7 +170,12 @@ class ScpMessage { static ScpMessage deserialize(List bytes) { final message = ScpMessage(); int offset = 0; + // Convert byte array to hex string with zero padding and without spaces + String hexString = + bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(); + // Log the hex string + _log(text: '原始字节数组: $hexString'); // ProtocolFlag (4 bytes) if (bytes.length - offset >= 4) { message.ProtocolFlag = utf8.decode(bytes.sublist(offset, offset + 4)); @@ -253,7 +265,6 @@ class ScpMessage { if (message.PayloadLength != null && bytes.length - offset >= message.PayloadLength!) { final sublist = bytes.sublist(offset, offset + message.PayloadLength!); - // print('sublist:$sublist'); offset += message.PayloadLength!; message.Payload = _handlePayLoad( payloadType: message.PayloadType ?? 0, @@ -261,7 +272,13 @@ class ScpMessage { byte: sublist, offset: offset, PayloadLength: message.PayloadLength, + spIndex: message.SpIndex, + spTotal: message.SpTotal, + messageId: message.MessageId, ); + // if (message.Payload != null && message.Payload is List) { + // message.PayloadLength = message.Payload.length; + // } } else { throw FormatException("Invalid Payload or PayloadLength"); } @@ -269,20 +286,6 @@ class ScpMessage { return message; } - static String bytesToHex(List bytes) { - return bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join(''); - } - - // 辅助函数:将16进制字符串转换为字节数组 - static List hexToBytes(String hexString) { - final bytes = []; - for (int i = 0; i < hexString.length; i += 2) { - final hexByte = hexString.substring(i, i + 2); - bytes.add(int.parse(hexByte, radix: 16)); - } - return bytes; - } - // 根据不同payloadType序列化对应的payload结构体 static dynamic _handlePayLoad({ required int payloadType, @@ -290,6 +293,9 @@ class ScpMessage { required List byte, int? offset, int? PayloadLength, + int? spTotal, + int? spIndex, + int? messageId, }) { try { switch (payloadType) { @@ -304,8 +310,23 @@ class ScpMessage { return heartbeatResponse; case PayloadTypeConstant.echoTest: // 回声测试 - String payload = utf8.decode(byte); - return payload; + if (spTotal != null && + spTotal > 1 && + messageId != null && + spIndex != null) { + // 分包处理 + return _handleFragmentedPayload( + messageId: messageId, + spTotal: spTotal, + spIndex: spIndex, + byte: byte, + payloadType: payloadType, + ); + } else { + // 如果 spTotal 为 1 或者没有分包信息,直接处理 byte 数据 + String payload = utf8.decode(byte); + return payload; + } case PayloadTypeConstant.gatewayReset: // 初始化网关 if (messageType == MessageTypeConstant.Resp) { @@ -430,8 +451,24 @@ class ScpMessage { final GenericResp genericResp = GenericResp.fromBuffer(byte); return genericResp; } else if (messageType == MessageTypeConstant.RealTimeData) { - final TalkData talkData = TalkData.fromBuffer(byte); - return talkData; + // 回声测试 + if (spTotal != null && + spTotal > 1 && + messageId != null && + spIndex != null) { + // 分包处理 + return _handleFragmentedPayload( + messageId: messageId, + spTotal: spTotal, + spIndex: spIndex, + byte: byte, + payloadType: payloadType, + ); + } else { + // 没有分包直接解析 + final TalkData talkData = TalkData.fromBuffer(byte); + return talkData; + } } else { String payload = utf8.decode(byte); return payload; @@ -452,14 +489,75 @@ class ScpMessage { String payload = utf8.decode(byte); return payload; } - } catch (e) { + } catch (e, stackTrace) { + // 打印异常信息 _log(text: '❌反序列化udp数据时遇到错误----》$e'); - String payload = utf8.decode(byte); - return payload; + // 打印堆栈跟踪信息 + _log(text: '堆栈跟踪:\n$stackTrace'); + return ''; } } + static String bytesToHex(List bytes) { + return bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join(''); + } + + // 辅助函数:将16进制字符串转换为字节数组 + static List hexToBytes(String hexString) { + final bytes = []; + for (int i = 0; i < hexString.length; i += 2) { + final hexByte = hexString.substring(i, i + 2); + bytes.add(int.parse(hexByte, radix: 16)); + } + return bytes; + } + static void _log({required String text}) { AppLog.log('=====${text}'); } + + /// 处理分包逻辑 + /// 如果没有收到所有包则返回null + static dynamic _handleFragmentedPayload({ + required int messageId, + required int spTotal, + required int spIndex, + required List byte, + required int payloadType, + }) { + // 初始化分包列表 + if (!_packetBuffer.containsKey(messageId)) { + _packetBuffer[messageId] = List.filled(spTotal, []); + } + + // 检查分包索引是否在合法范围内 + if (spIndex < 1 || spIndex > spTotal) { + print('Invalid spIndex: $spIndex for messageId: $messageId'); + return null; + } + + // 存储当前分包 + _packetBuffer[messageId]![spIndex - 1] = byte; + + // 检查是否接收到所有分包 + if (_packetBuffer[messageId]!.every((packet) => packet.isNotEmpty)) { + // 重组所有分包 + List completePayload = _packetBuffer[messageId]!.expand((packet) => packet).toList(); + + // 清除已重组的分包数据 + _packetBuffer.remove(messageId); + + // 解析完整的 payload + if (payloadType == PayloadTypeConstant.talkData) { + final TalkData talkData = TalkData.fromBuffer(completePayload); + return talkData; + } else { + String payload = utf8.decode(completePayload); + return payload; + } + } else { + // 如果分包尚未接收完全,返回 null 或其他指示符 + return null; + } + } } diff --git a/lib/talk/startChart/handle/impl/udp_echo_test_handler.dart b/lib/talk/startChart/handle/impl/udp_echo_test_handler.dart index a98870b5..f8b446b3 100644 --- a/lib/talk/startChart/handle/impl/udp_echo_test_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_echo_test_handler.dart @@ -3,6 +3,7 @@ import 'package:get/get.dart'; import 'package:star_lock/talk/startChart/entity/scp_message.dart'; import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart'; import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart'; +import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart'; import '../../start_chart_manage.dart'; @@ -16,7 +17,14 @@ class UdpEchoTestHandler extends ScpMessageBaseHandle @override void handleResp(ScpMessage scpMessage) { // TODO: 收到回声测试回复 - EasyLoading.showToast(scpMessage.Payload, duration: 2000.milliseconds); + final List payload = scpMessage.Payload; + + if (payload is String) { + EasyLoading.showToast(scpMessage.Payload, duration: 2000.milliseconds); + } else { + talkDataRepository.addTalkData( + TalkData(content: payload, contentType: TalkData_ContentTypeE.Image)); + } } @override diff --git a/lib/talk/startChart/handle/impl/udp_talk_accept_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_accept_handler.dart index 3fae7d0a..0b9510a3 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_accept_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_accept_handler.dart @@ -26,10 +26,10 @@ class UdpTalkAcceptHandler extends ScpMessageBaseHandle // 收到同意接听回复 final GenericResp genericResp = scpMessage.Payload; if (checkGenericRespSuccess(genericResp)) { - // 启动通话保持定时器 - _handleStartTalkPing(); // 延迟2秒后启动监听 - Future.delayed(Duration(seconds: 2), () { + Future.delayed(Duration(seconds: 4), () { + // 启动通话保持定时器 + _handleStartTalkPing(); // 启动发送预期数据请求 _handleStartSendTalkExpectDataRequest(); // 启动通话数据检查的定时器 diff --git a/lib/talk/startChart/handle/impl/udp_talk_data_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_data_handler.dart index 3e172271..51527d9d 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_data_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_data_handler.dart @@ -27,6 +27,7 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle final TalkData talkData = scpMessage.Payload; // 处理音视频数据 _handleTalkData(talkData: talkData); + print('talkData:$talkData'); // 收到数据后调用更新,防止定时器超时 talkDataOverTimeTimerManager.receiveMessage(); } @@ -53,7 +54,7 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle /// 处理h264协议的数据 void _handleVideoH264(TalkData talkData) { - talkDataRepository.addTalkData(talkData); + // talkDataRepository.addTalkData(talkData); } /// 处理图片数据 diff --git a/lib/talk/startChart/handle/impl/udp_talk_request_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_request_handler.dart index cd6c544c..45aaf970 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_request_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_request_handler.dart @@ -29,7 +29,6 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle startChartManage.ToPeerId = scpMessage.FromPeerId!; // 处理收到接听请求后的事件 _talkRequestEvent(talkObjectName: talkReq.callerName); - } @override @@ -53,7 +52,7 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle _showTalkRequestNotification(talkObjectName: talkObjectName); // 收到呼叫请求,跳转到接听页面 Get.toNamed( - Routers.lockMonitoringPage, + Routers.starChartPage, arguments: {'lockId': '111'}, ); } diff --git a/lib/talk/startChart/handle/other/overtime_timer_manger.dart b/lib/talk/startChart/handle/other/overtime_timer_manger.dart index f92990a6..c813dcaf 100644 --- a/lib/talk/startChart/handle/other/overtime_timer_manger.dart +++ b/lib/talk/startChart/handle/other/overtime_timer_manger.dart @@ -31,7 +31,6 @@ class OverTimeTimerManager { // 接收到消息时调用此方法 void receiveMessage() { - print("Received a message, resetting the timer."); startTimer(); } diff --git a/lib/talk/startChart/proto/test.proto b/lib/talk/startChart/proto/test.proto new file mode 100644 index 00000000..bec1e975 --- /dev/null +++ b/lib/talk/startChart/proto/test.proto @@ -0,0 +1,10 @@ +// 用于测试包序列化大小 +// 如果两个int都是0,那么序列化出来是0字节,也需要正常反序列化 +syntax = "proto3"; +package main; +option go_package = "./spb"; + +message TestStruct { + uint32 StatusA = 1; + uint32 StatusB = 2; +} diff --git a/lib/talk/startChart/start_chart_manage.dart b/lib/talk/startChart/start_chart_manage.dart index a238a9b6..790d6ea5 100644 --- a/lib/talk/startChart/start_chart_manage.dart +++ b/lib/talk/startChart/start_chart_manage.dart @@ -50,12 +50,16 @@ class StartChartManage { final String _productName = F.navTitle; RawDatagramSocket? _udpSocket; + final Map> _completers = {}; // 发送消息的请求是否完成 + final Uuid _uuid = Uuid(); // 用于区分发送的消息的唯一id + int _messageMaxTimeout = 5; // 消息最大超时时间(s) late String remoteHost = ''; // 远程主机地址(服务器返回) late int remotePort = 0; // 远程主机端口(服务器返回) final int localPort = 62289; // 本地端口 String localPublicHost = ''; // 本地公网ip地址 int heartbeatIntervalTime = 1; // 心跳包间隔时间(s) + Timer? _heartBeatTimer; // 心跳包定时器 bool _heartBeatTimerRunning = false; // 心跳包定时任务发送状态 @@ -75,9 +79,11 @@ class StartChartManage { int talkDataIntervalTime = 10; // 通话数据的消息间隔(ms) Timer? talkDataTimer; // 发送通话数据消息定时器 + final int _maxPayloadSize = 8 * 1024; // 分包大小 + // 默认通话的期望数据格式 TalkExpect defaultTalkExpect = TalkExpect( - videoType: [TalkExpect_VideoTypeE.H264], + videoType: [TalkExpect_VideoTypeE.IMAGE], audioType: [TalkExpect_AudioTypeE.G711], ); @@ -109,7 +115,7 @@ class StartChartManage { Future _clientRegister() async { final StarChartRegisterNodeEntity? registerNodeEntity = await Storage.getStarChartRegisterNodeInfo(); - if (registerNodeEntity != null) { + if (registerNodeEntity != null && registerNodeEntity.peer?.id != null) { _log(text: '获取到星图注册节点信息:$registerNodeEntity'); FromPeerId = registerNodeEntity.peer!.id ?? ''; } else { @@ -120,6 +126,7 @@ class StartChartManage { FromPeerId = requestStarChartRegisterNode.peer!.id ?? ''; bindUserStarchart(); } + } //绑定星图配置 @@ -153,14 +160,19 @@ class StartChartManage { } if (relayInfoEntity.relay_list != null && - relayInfoEntity.relay_list!.length != 0) { - final data = relayInfoEntity.relay_list?[0]; - final parseUdpUrl = _parseUdpUrl(data?.listenAddr ?? ''); - remoteHost = parseUdpUrl['host'] ?? ''; - remotePort = parseUdpUrl['port'] ?? ''; - relayPeerId = data?.peerID ?? ''; - ToPeerId = relayPeerId; - _log(text: '中继信息----》${relayInfoEntity}'); + relayInfoEntity.relay_list!.length > 0) { + for (int i = 0; i <= relayInfoEntity.relay_list!.length; i++) { + final data = relayInfoEntity.relay_list?[i]; + if (data?.peerID != FromPeerId) { + final parseUdpUrl = _parseUdpUrl(data?.listenAddr ?? ''); + remoteHost = parseUdpUrl['host'] ?? ''; + remotePort = parseUdpUrl['port'] ?? ''; + relayPeerId = data?.peerID ?? ''; + ToPeerId = relayPeerId; + _log(text: '中继信息----》${relayInfoEntity}'); + break; + } + } } else { _log(text: '未查询到中继信息----》'); } @@ -208,7 +220,7 @@ class StartChartManage { // 发送上线消息 Future _sendOnlineMessage() async { - _log(text: '发送上线消息'); + _log(text: '发送上线消息,是否已经上线:$isOnlineStartChartServer'); if (isOnlineStartChartServer) { _log(text: '星图已上线,请勿重复发送上线消息'); return; @@ -217,6 +229,7 @@ class StartChartManage { final message = MessageCommand.goOnlineRelay( FromPeerId: FromPeerId, ToPeerId: ToPeerId, + MessageId: MessageCommand.getNextMessageId(ToPeerId, increment: true), ); await _sendMessage(message: message); } @@ -231,6 +244,7 @@ class StartChartManage { final message = MessageCommand.talkRequestMessage( FromPeerId: FromPeerId, ToPeerId: ToPeerId, + MessageId: MessageCommand.getNextMessageId(ToPeerId, increment: true), ); await _sendMessage(message: message); } @@ -242,6 +256,7 @@ class StartChartManage { FromPeerId: FromPeerId, ToPeerId: ToPeerId, talkData: talkData, + MessageId: MessageCommand.getNextMessageId(ToPeerId, increment: true), ); await _sendMessage(message: message); } @@ -260,6 +275,8 @@ class StartChartManage { final List message = MessageCommand.heartbeatMessage( FromPeerId: FromPeerId, ToPeerId: relayPeerId, + MessageId: + MessageCommand.getNextMessageId(relayPeerId, increment: true), ); await _sendMessage(message: message); }, @@ -268,13 +285,37 @@ class StartChartManage { } // 发送回声测试消息 - void sendEchoMessage() async { - final message = MessageCommand.echoMessage( - ToPeerId: echoPeerId, - FromPeerId: FromPeerId, - ); - await _sendMessage(message: message); - _log(text: '发送回声测试消息'); + void sendEchoMessage({required List payload}) async { + String toPeerId = '7SDLN3XMNAQvVAJ2yrbLFfJkKQdgfBrpa8wV7s7TXYcu'; + + // 计算需要分多少个包发送 + final int totalPackets = (payload.length / _maxPayloadSize).ceil(); + // 循环遍历 + for (int i = 0; i < totalPackets; i++) { + int start = i * _maxPayloadSize; + int end = (i + 1) * _maxPayloadSize; + if (end > payload.length) { + end = payload.length; + } + // 取到分包数据 + List packet = payload.sublist(start, end); + + final messageId = + MessageCommand.getNextMessageId(toPeerId, increment: false); + // 组装分包数据 + final message = MessageCommand.echoMessage( + ToPeerId: toPeerId, + FromPeerId: FromPeerId, + payload: packet, + SpTotal: totalPackets, + SpIndex: i + 1, + MessageId: messageId, + ); + // 发送消息 + await _sendMessage(message: message); + } + // 分包发送完了递增一下id + MessageCommand.getNextMessageId(toPeerId); } // 发送网关初始化消息 @@ -285,6 +326,7 @@ class StartChartManage { FromPeerId: FromPeerId, gatewayId: gatewayId, time: DateTime.now().millisecondsSinceEpoch ~/ 1000, + MessageId: MessageCommand.getNextMessageId(ToPeerId, increment: true), ); await _sendMessage(message: message); } @@ -294,6 +336,7 @@ class StartChartManage { final message = MessageCommand.talkAcceptMessage( ToPeerId: ToPeerId, FromPeerId: FromPeerId, + MessageId: MessageCommand.getNextMessageId(ToPeerId, increment: true), ); await _sendMessage(message: message); talkStatus.setWaitingAnswer(); @@ -304,6 +347,7 @@ class StartChartManage { final message = MessageCommand.talkRejectMessage( ToPeerId: ToPeerId, FromPeerId: FromPeerId, + MessageId: MessageCommand.getNextMessageId(ToPeerId, increment: true), ); await _sendMessage(message: message); } @@ -314,6 +358,7 @@ class StartChartManage { ToPeerId: ToPeerId, FromPeerId: FromPeerId, talkExpect: talkExpect, + MessageId: MessageCommand.getNextMessageId(ToPeerId, increment: true), ); await _sendMessage(message: message); } @@ -327,6 +372,7 @@ class StartChartManage { ToPeerId: ToPeerId, FromPeerId: FromPeerId, PayloadType: PayloadType, + MessageId: MessageCommand.getNextMessageId(ToPeerId, increment: false), ); await _sendMessage(message: message); } @@ -340,6 +386,7 @@ class StartChartManage { ToPeerId: ToPeerId, FromPeerId: FromPeerId, PayloadType: PayloadType, + MessageId: MessageCommand.getNextMessageId(ToPeerId, increment: false), ); await _sendMessage(message: message); } @@ -350,6 +397,7 @@ class StartChartManage { final message = MessageCommand.talkPingMessage( ToPeerId: ToPeerId, FromPeerId: FromPeerId, + MessageId: MessageCommand.getNextMessageId(ToPeerId, increment: true), ); await _sendMessage(message: message); } @@ -359,6 +407,7 @@ class StartChartManage { final message = MessageCommand.talkHangupMessage( ToPeerId: ToPeerId, FromPeerId: FromPeerId, + MessageId: MessageCommand.getNextMessageId(ToPeerId, increment: true), ); await _sendMessage(message: message); } @@ -405,7 +454,7 @@ class StartChartManage { message, InternetAddress(remoteHost), remotePort); if (result != message.length) { AppLog.log('❌Udp send data error----> $result ${message.length}'); - _udpSocket = null; + // _udpSocket = null; } } @@ -716,10 +765,12 @@ class StartChartManage { } if (deserialize.PayloadType != PayloadTypeConstant.heartbeat) { _log(text: 'Udp收到结构体数据---》$deserialize'); + // _log(text: 'text---》${utf8.decode(deserialize.Payload)}'); } } - } catch (e) { + } catch (e, stackTrace) { _log(text: '❌ Udp result data error ----> $e'); + _log(text: '堆栈跟踪:\n$stackTrace'); } } }); @@ -742,7 +793,7 @@ class StartChartManage { handler.handleInvalidReq(scpMessage); } } catch (e) { - _log(text: '❌ 处理udp返回数据时遇到错误---> $e'); + // _log(text: '❌ 处理udp返回数据时遇到错误---> $e'); } } @@ -897,12 +948,13 @@ class StartChartManage { /// 销毁资源 void destruction() async { + isOnlineStartChartServer = false; stopTalkExpectMessageTimer(); stopTalkPingMessageTimer(); stopHeartbeat(); stopReStartOnlineStartChartServer(); stopTalkDataTimer(); - await Storage.removerRelayInfo(); - await Storage.removerStarChartRegisterNodeInfo(); + // await Storage.removerRelayInfo(); + // await Storage.removerStarChartRegisterNodeInfo(); } } diff --git a/lib/tools/change_language_format.dart b/lib/tools/change_language_format.dart deleted file mode 100644 index 46e2ef8e..00000000 --- a/lib/tools/change_language_format.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'dart:ui'; - -class ChangeLanguageFormat { - static Locale convertLocale(Locale locale) { - if (locale.languageCode == 'zh') { - if (locale.scriptCode == 'Hans') { - // 简体中文 - return const Locale('zh', 'CN'); - } else if (locale.scriptCode == 'Hant') { - // 繁体中文 - if (locale.countryCode == 'CN') { - return const Locale('zh', 'TW'); - } else if (locale.countryCode == 'HK') { - return const Locale('zh', 'HK'); - } - } - } - // 默认返回 Locale 的完整格式 - return locale; - } -} diff --git a/lib/tools/commonItem.dart b/lib/tools/commonItem.dart index d6776391..30e36dd9 100755 --- a/lib/tools/commonItem.dart +++ b/lib/tools/commonItem.dart @@ -1,7 +1,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; import 'package:star_lock/app_settings/app_colors.dart'; +import '../translations/app_dept.dart'; +import '../translations/current_locale_tool.dart'; + class CommonItem extends StatelessWidget { CommonItem( {required this.leftTitel, @@ -86,11 +90,27 @@ class CommonItem extends StatelessWidget { ), if (isHaveDirection!) SizedBox(width: 15.w) else Container(), if (isHaveDirection!) - Image.asset( - 'images/icon_right_grey.png', - width: 12.w, - height: 21.w, - ) + if (CurrentLocaleTool.getCurrentLocaleString() == + ExtensionLanguageType.fromLanguageType( + LanguageType.hebrew) + .toLanguageTag() || + CurrentLocaleTool.getCurrentLocaleString() == + ExtensionLanguageType.fromLanguageType( + LanguageType.arabic) + .toLanguageTag() || + rightTitle == '希伯来语'.tr || + rightTitle == '阿拉伯语'.tr) + Image.asset( + 'images/icon_left_grey.png', + width: 21.w, + height: 21.w, + ) + else + Image.asset( + 'images/icon_right_grey.png', + width: 12.w, + height: 21.w, + ) else SizedBox(width: 10.w), if (isHaveDirection!) SizedBox(width: 5.w) else Container(), diff --git a/lib/tools/pickers/time_picker/model/suffix.dart b/lib/tools/pickers/time_picker/model/suffix.dart index 3a903a21..5f1b82f2 100755 --- a/lib/tools/pickers/time_picker/model/suffix.dart +++ b/lib/tools/pickers/time_picker/model/suffix.dart @@ -14,12 +14,12 @@ class Suffix { this.seconds = ''}); Suffix.normal() { - years = '年'.tr; - month = '月'.tr; - days = '日'.tr; - hours = '时'.tr; - minutes = '分'.tr; - seconds = '秒'.tr; + years = '年简称'.tr; + month = '月简称'.tr; + days = '日简称'.tr; + hours = '时简称'.tr; + minutes = '分简称'.tr; + seconds = '秒简称'.tr; } late String years; late String month; diff --git a/lib/tools/showCupertinoAlertView.dart b/lib/tools/showCupertinoAlertView.dart index 62a53f6f..607dc414 100755 --- a/lib/tools/showCupertinoAlertView.dart +++ b/lib/tools/showCupertinoAlertView.dart @@ -1,16 +1,24 @@ +import 'dart:typed_data'; +import 'dart:ui'; + import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; +import 'package:image_gallery_saver/image_gallery_saver.dart'; +import 'package:qr_flutter/qr_flutter.dart'; import 'package:star_lock/appRouters.dart'; import 'package:star_lock/app_settings/app_colors.dart'; import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart'; +import 'package:star_lock/tools/submitBtn.dart'; typedef AuthInfoCallback = void Function(String? idCard, String? name); class ShowCupertinoAlertView { bool isSystemEmailSelected = true; // 默认选中系统邮件 + final GlobalKey _repaintBoundaryKey = GlobalKey(); //微信公众号二维码弹窗 void showQRImageAlert( @@ -138,7 +146,7 @@ class ShowCupertinoAlertView { style: TextStyle(color: Colors.white, fontSize: 22.sp), )), ), - SizedBox(width:2.w) + SizedBox(width: 2.w) // Expanded( // child: SizedBox( // width: 2.w, @@ -395,6 +403,101 @@ class ShowCupertinoAlertView { ); } + //可视门铃二维码弹窗 + void showVisualDoorbellCodeAlert( + {required BuildContext widgetContext, + required String qrCodeUrl, + required String qrCodeText}) { + showCupertinoModalPopup( + context: widgetContext, + builder: (BuildContext context) { + return CupertinoActionSheet( + actions: [ + Container( + color: Colors.white, // 设置底色为白色 + child: CupertinoActionSheetAction( + child: Container( + margin: const EdgeInsets.all(0), + child: Column( + children: [ + SizedBox( + height: 60.h, + ), + if (qrCodeUrl.isNotEmpty) + RepaintBoundary( + key: _repaintBoundaryKey, + child: SizedBox( + width: 200, + height: 200, + child: QrImageView( + data: qrCodeUrl, + version: QrVersions.auto, + size: 200.0, + ), + ), + ) + else + Container(), + SizedBox( + height: 20.h, + ), + Padding( + padding: EdgeInsets.only( + left: 60.w, right: 60.w, bottom: 30), + child: Text( + qrCodeText, + style: + TextStyle(fontSize: 24.sp, color: Colors.black), + )), + Container( + margin: EdgeInsets.only(left: 60.w, right: 60.w), + child: OutLineBtn( + btnName: '保存到相册'.tr, + onClick: () async { + // 截图并保存到相册 + try { + final RenderRepaintBoundary boundary = + _repaintBoundaryKey.currentContext! + .findRenderObject()! + as RenderRepaintBoundary; + final image = await boundary.toImage(); + final ByteData? byteData = await image + .toByteData(format: ImageByteFormat.png); + final Uint8List pngBytes = + byteData!.buffer.asUint8List(); + + final result = + await ImageGallerySaver.saveImage( + Uint8List.fromList(pngBytes), + quality: 100, + name: 'qr_code'); + if (result['isSuccess']) { + EasyLoading.showToast('保存成功'.tr); + } else { + EasyLoading.showToast('保存失败'.tr); + } + } catch (e) { + EasyLoading.showToast('保存失败'.tr); + } + }), + ), + SizedBox( + height: 40.h, + ) + ], + ), + ), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ), + ], + ); + }, + ); + } + // //邮件通知类型选择弹窗 // void emailNotifyTypeSlectAlert() { // showCupertinoDialog( diff --git a/lib/tools/store_service.dart b/lib/tools/store_service.dart index 938c0222..201e1872 100755 --- a/lib/tools/store_service.dart +++ b/lib/tools/store_service.dart @@ -7,8 +7,8 @@ import 'package:star_lock/login/login/entity/LoginData.dart'; import '../login/login/entity/LoginEntity.dart'; final box = GetStorage(); -class StoreService extends GetxService { +class StoreService extends GetxService { static StoreService get to => Get.find(); Future> init() async { await GetStorage.init(); @@ -21,11 +21,13 @@ class StoreService extends GetxService { bool hasData(String? key) => box.hasData(key!); final String _deviceUUID = 'DEVICE_ID'; - final String _languageCode = 'LANGUAGE_CODE'; + final String _language = 'LANGUAGE'; - String? getDeviceId() => hasData(_deviceUUID) ? read(_deviceUUID).toString(): ''; + String? getDeviceId() => + hasData(_deviceUUID) ? read(_deviceUUID).toString() : ''; Future saveDeviceId(String uuid) => save(_deviceUUID, uuid); - String? getLanguageCode() => hasData(_languageCode) ? read(_languageCode).toString(): ''; - Future saveLanguageCode(String code) => save(_languageCode, code); + String? getLanguageCode() => + hasData(_language) ? read(_language).toString() : ''; + Future saveLanguageCode(String code) => save(_language, code); } diff --git a/lib/translations/app_dept.dart b/lib/translations/app_dept.dart index bd4febad..55cf2762 100755 --- a/lib/translations/app_dept.dart +++ b/lib/translations/app_dept.dart @@ -103,6 +103,7 @@ AppDept appDept = ExtensionAppDept.fromAppPackageName(AppManager().packageName); final List appSupportedLocales = appDept.deptSupportedLocales; enum LanguageType { + system, chinese, english, // 繁体中文(中国台湾) @@ -298,121 +299,6 @@ extension ExtensionLanguageType on LanguageType { return str; } - // static LanguageType fromLanguageCode(String code) { - // LanguageType languageType = LanguageType.english; - // switch(code.toLowerCase()){ - // case 'en': - // languageType = LanguageType.english; - // break; - // case 'zh': - // languageType = LanguageType.chinese; - // break; - // case 'tw': - // languageType = LanguageType.traditionalChinese; - // break; - // case 'fr': - // languageType = LanguageType.french; - // break; - // case 'ru': - // languageType = LanguageType.russian; - // break; - // case 'de': - // languageType = LanguageType.german; - // break; - // case 'ja': - // languageType = LanguageType.japanese; - // break; - // case 'ko': - // languageType = LanguageType.korean; - // break; - // case 'it': - // languageType = LanguageType.italian; - // break; - // // case 'uk': - // // languageType = LanguageType.ukrainian; - // // break; - // case 'pt': - // languageType = LanguageType.portuguese; - // break; - // case 'es': - // languageType = LanguageType.spanish; - // break; - // case 'ar': - // languageType = LanguageType.arabic; - // break; - // case 'vi': - // languageType = LanguageType.vietnamese; - // break; - // case 'ms': - // languageType = LanguageType.malay; - // break; - // case 'nl': - // languageType = LanguageType.dutch; - // break; - // case 'ro': - // languageType = LanguageType.romanian; - // break; - // case 'lt': - // languageType = LanguageType.lithuanian; - // break; - // case 'sv': - // languageType = LanguageType.swedish; - // break; - // case 'et': - // languageType = LanguageType.estonian; - // break; - // case 'pl': - // languageType = LanguageType.polish; - // break; - // case 'sk': - // languageType = LanguageType.slovak; - // break; - // case 'cs': - // languageType = LanguageType.czech; - // break; - // case 'el': - // languageType = LanguageType.greek; - // break; - // case 'he': - // languageType = LanguageType.hebrew; - // break; - // // case 'sr': - // // languageType = LanguageType.serbian; - // // break; - // case 'tr': - // languageType = LanguageType.turkish; - // break; - // case 'hu': - // languageType = LanguageType.hungarian; - // break; - // case 'bg': - // languageType = LanguageType.bulgarian; - // break; - // case 'kk': - // languageType = LanguageType.kazakh; - // break; - // case 'bn': - // languageType = LanguageType.bengali; - // break; - // case 'hr': - // languageType = LanguageType.croatian; - // break; - // case 'th': - // languageType = LanguageType.thai; - // break; - // case 'id': - // languageType = LanguageType.indonesian; - // break; - // case 'fi': - // languageType = LanguageType.finnish; - // break; - // case 'da': - // languageType = LanguageType.danish; - // break; - // } - // return languageType; - // } - static LanguageType fromLocale(Locale locale) { LanguageType languageType = LanguageType.english; final String code = locale.languageCode; @@ -529,7 +415,206 @@ extension ExtensionLanguageType on LanguageType { case 'uk': languageType = LanguageType.ukrainian; break; + default: + languageType = LanguageType.english; + break; } return languageType; } + + static Locale fromLanguageType(LanguageType languageType) { + for (Locale locale in appDept.deptSupportedLocales) { + switch (languageType) { + case LanguageType.english: + if (locale.languageCode == 'en' && locale.countryCode == 'US') { + return locale; + } + break; + case LanguageType.chinese: + if (locale.languageCode == 'zh' && locale.countryCode == 'CN') { + return locale; + } + break; + case LanguageType.traditionalChineseTW: + if (locale.languageCode == 'zh' && locale.countryCode == 'TW') { + return locale; + } + break; + case LanguageType.traditionalChineseHK: + if (locale.languageCode == 'zh' && locale.countryCode == 'HK') { + return locale; + } + break; + case LanguageType.french: + if (locale.languageCode == 'fr' && locale.countryCode == 'FR') { + return locale; + } + break; + case LanguageType.russian: + if (locale.languageCode == 'ru' && locale.countryCode == 'RU') { + return locale; + } + break; + case LanguageType.german: + if (locale.languageCode == 'de' && locale.countryCode == 'DE') { + return locale; + } + break; + case LanguageType.japanese: + if (locale.languageCode == 'ja' && locale.countryCode == 'JP') { + return locale; + } + break; + case LanguageType.korean: + if (locale.languageCode == 'ko' && locale.countryCode == 'KR') { + return locale; + } + break; + case LanguageType.italian: + if (locale.languageCode == 'it' && locale.countryCode == 'IT') { + return locale; + } + break; + case LanguageType.portuguese: + if (locale.languageCode == 'pt' && locale.countryCode == 'PT') { + return locale; + } + break; + case LanguageType.spanish: + if (locale.languageCode == 'es' && locale.countryCode == 'ES') { + return locale; + } + break; + case LanguageType.arabic: + if (locale.languageCode == 'ar' && locale.countryCode == 'SA') { + return locale; + } + break; + case LanguageType.vietnamese: + if (locale.languageCode == 'vi' && locale.countryCode == 'VN') { + return locale; + } + break; + case LanguageType.malay: + if (locale.languageCode == 'ms' && locale.countryCode == 'MY') { + return locale; + } + break; + case LanguageType.dutch: + if (locale.languageCode == 'nl' && locale.countryCode == 'NL') { + return locale; + } + break; + case LanguageType.romanian: + if (locale.languageCode == 'ro' && locale.countryCode == 'RO') { + return locale; + } + break; + case LanguageType.lithuanian: + if (locale.languageCode == 'lt' && locale.countryCode == 'LT') { + return locale; + } + break; + case LanguageType.swedish: + if (locale.languageCode == 'sv' && locale.countryCode == 'SE') { + return locale; + } + break; + case LanguageType.estonian: + if (locale.languageCode == 'et' && locale.countryCode == 'EE') { + return locale; + } + break; + case LanguageType.polish: + if (locale.languageCode == 'pl' && locale.countryCode == 'PL') { + return locale; + } + break; + case LanguageType.slovak: + if (locale.languageCode == 'sk' && locale.countryCode == 'SK') { + return locale; + } + break; + case LanguageType.czech: + if (locale.languageCode == 'cs' && locale.countryCode == 'CZ') { + return locale; + } + break; + case LanguageType.greek: + if (locale.languageCode == 'el' && locale.countryCode == 'GR') { + return locale; + } + break; + case LanguageType.hebrew: + if (locale.languageCode == 'he' && locale.countryCode == 'IL') { + return locale; + } + break; + case LanguageType.serbian: + if (locale.languageCode == 'sr' && locale.countryCode == 'RS') { + return locale; + } + break; + case LanguageType.turkish: + if (locale.languageCode == 'tr' && locale.countryCode == 'TR') { + return locale; + } + break; + case LanguageType.hungarian: + if (locale.languageCode == 'hu' && locale.countryCode == 'HU') { + return locale; + } + break; + case LanguageType.bulgarian: + if (locale.languageCode == 'bg' && locale.countryCode == 'BG') { + return locale; + } + break; + case LanguageType.kazakh: + if (locale.languageCode == 'kk' && locale.countryCode == 'KZ') { + return locale; + } + break; + case LanguageType.bengali: + if (locale.languageCode == 'bn' && locale.countryCode == 'BD') { + return locale; + } + break; + case LanguageType.croatian: + if (locale.languageCode == 'hr' && locale.countryCode == 'BA') { + return locale; + } + break; + case LanguageType.thai: + if (locale.languageCode == 'th' && locale.countryCode == 'TH') { + return locale; + } + break; + case LanguageType.indonesian: + if (locale.languageCode == 'id' && locale.countryCode == 'ID') { + return locale; + } + break; + case LanguageType.finnish: + if (locale.languageCode == 'fi' && locale.countryCode == 'FI') { + return locale; + } + break; + case LanguageType.danish: + if (locale.languageCode == 'da' && locale.countryCode == 'DK') { + return locale; + } + break; + case LanguageType.ukrainian: + if (locale.languageCode == 'uk' && locale.countryCode == 'UA') { + return locale; + } + break; + case LanguageType.system: + // TODO: Handle this case. + break; + } + } + return const Locale('en', 'US'); + } } diff --git a/lib/translations/current_locale_tool.dart b/lib/translations/current_locale_tool.dart new file mode 100644 index 00000000..cc883bd4 --- /dev/null +++ b/lib/translations/current_locale_tool.dart @@ -0,0 +1,79 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../app_settings/app_settings.dart'; +import '../tools/store_service.dart'; +import 'app_dept.dart'; + +class CurrentLocaleTool { + /// 获取当前语言的Locale字符串,没有的话获取系统的 + static String getCurrentLocaleString() { + AppLog.log( + '11111StoreService.to.getLanguageCode():${StoreService.to.getLanguageCode()}'); + final Locale locale = StoreService.to.getLanguageCode()!.isNotEmpty + ? appDept.deptSupportedLocales + .where((Locale element) => + element.languageCode.toString() == + getCurrentLocaleWithLanguageCode( + StoreService.to.getLanguageCode()!) + .languageCode) + .first + : Get.deviceLocale!; // Get.deviceLocale; + final String languageCode = convertLocale(locale).toString(); + AppLog.log( + '11111locale.toString(): ${locale.toString()} locale: $locale languageCode:$languageCode'); + return languageCode; + } + + /// 获取当前储存的Locale,没有的话获取系统的 + static Locale getCurrentLocale() { + AppLog.log( + '222StoreService.to.getLanguageCode():${StoreService.to.getLanguageCode()}'); + final Locale locale = StoreService.to.getLanguageCode()!.isNotEmpty + ? appDept.deptSupportedLocales + .where((Locale element) => + element.languageCode.toString() == + getCurrentLocaleWithLanguageCode( + StoreService.to.getLanguageCode()!) + .languageCode) + .first + : Get.deviceLocale!; // Get.deviceLocale; + final Locale getLocale = convertLocale(locale); + AppLog.log( + '222locale.toString(): ${locale.toString()} locale: $locale getLocale:$getLocale'); + return getLocale; + } + + static Locale getCurrentLocaleWithLanguageCode(String languageCode) { + final List parts = languageCode.split('_'); + final String language = parts[0]; + final String country = parts.length > 1 ? parts[1] : ''; + + for (Locale locale in appDept.deptSupportedLocales) { + if (locale.languageCode == language && locale.countryCode == country) { + return locale; + } + } + + return const Locale('en', 'US'); + } + + /// 国际化中文繁体及中文的转化 + static Locale convertLocale(Locale locale) { + if (locale.languageCode == 'zh') { + if (locale.scriptCode == 'Hans') { + // 简体中文 + return const Locale('zh', 'CN'); + } else if (locale.scriptCode == 'Hant') { + // 繁体中文 + if (locale.countryCode == 'CN') { + return const Locale('zh', 'TW'); + } else if (locale.countryCode == 'HK') { + return const Locale('zh', 'HK'); + } + } + } + // 默认返回 Locale 的完整格式 + return locale; + } +} diff --git a/lib/translations/translation_message.dart b/lib/translations/translation_message.dart index 8c31cb3a..eafecdf9 100755 --- a/lib/translations/translation_message.dart +++ b/lib/translations/translation_message.dart @@ -10,36 +10,36 @@ class TranslationMessage extends Translations { 'fr_FR': TranslationLoader.frDic, 'ru_RU': TranslationLoader.ruDic, 'de_DE': TranslationLoader.deDic, - 'ja_JA': TranslationLoader.jaDic, - 'ko_KO': TranslationLoader.koDic, + 'ja_JP': TranslationLoader.jaDic, + 'ko_KR': TranslationLoader.koDic, 'it_IT': TranslationLoader.itDic, - 'uk_UK': TranslationLoader.ukDic, + 'uk_UA': TranslationLoader.ukDic, 'pt_PT': TranslationLoader.ptDic, 'es_ES': TranslationLoader.esDic, - 'ar_AR': TranslationLoader.arDic, - 'vi_VI': TranslationLoader.viDic, - 'ms_MS': TranslationLoader.msDic, + 'ar_SA': TranslationLoader.arDic, + 'vi_VN': TranslationLoader.viDic, + 'ms_MY': TranslationLoader.msDic, 'nl_NL': TranslationLoader.nlDic, 'ro_RO': TranslationLoader.roDic, 'lt_LT': TranslationLoader.ltDic, - 'sv_SV': TranslationLoader.svDic, - 'et_ET': TranslationLoader.etDic, + 'sv_SE': TranslationLoader.svDic, + 'et_EE': TranslationLoader.etDic, 'pl_PL': TranslationLoader.plDic, 'sk_SK': TranslationLoader.skDic, - 'cs_CS': TranslationLoader.csDic, - 'el_EL': TranslationLoader.elDic, - 'he_HE': TranslationLoader.heDic, - 'sr_SR': TranslationLoader.srDic, + 'cs_CZ': TranslationLoader.csDic, + 'el_GR': TranslationLoader.elDic, + 'he_IL': TranslationLoader.heDic, + 'sr_RS': TranslationLoader.srDic, 'tr_TR': TranslationLoader.trDic, 'hu_HU': TranslationLoader.huDic, 'bg_BG': TranslationLoader.bgDic, - 'kk_KK': TranslationLoader.kkDic, - 'bn_BN': TranslationLoader.bnDic, - 'hr_HR': TranslationLoader.hrDic, + 'kk_KZ': TranslationLoader.kkDic, + 'bn_BD': TranslationLoader.bnDic, + 'hr_BA': TranslationLoader.hrDic, 'th_TH': TranslationLoader.thDic, 'id_ID': TranslationLoader.idDic, 'fi_FI': TranslationLoader.fiDic, - 'da_DA': TranslationLoader.daDic, + 'da_DK': TranslationLoader.daDic, }; void updateLocal(Locale l) => Get.updateLocale(l);