From 95325f3a39ed83346c604343a7291d0ad4218734 Mon Sep 17 00:00:00 2001 From: liyi Date: Sat, 12 Jul 2025 15:50:03 +0800 Subject: [PATCH 01/25] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E4=BA=91=E5=AD=98w?= =?UTF-8?q?ebview=E7=9A=84=E6=94=AF=E4=BB=98=E9=A1=B5=E9=9D=A2=E3=80=81?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=AF=AD=E9=9F=B3=E5=8C=85=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/appRouters.dart | 13 + lib/blue/io_protocol/io_getDeviceModel.dart | 48 +++ .../io_protocol/io_voicePackageConfigure.dart | 163 +++++++++ .../io_voicePackageConfigureProcess.dart | 73 ++++ lib/blue/io_tool/io_tool.dart | 27 +- lib/blue/io_type.dart | 50 +++ lib/blue/reciver_data.dart | 25 ++ .../XSConstantMacro/XSConstantMacro.dart | 1 + .../lockDetail/lockDetail_logic.dart | 56 ++- .../lockDetail/passthrough_item.dart | 281 +++++++++++++++ .../lockSet/lockSet/lockSetInfo_entity.dart | 48 ++- .../lockSet/lockSet/lockSet_page.dart | 14 + .../speech_language_settings_logic.dart | 334 ++++++++++++++++++ .../speech_language_settings_page.dart | 127 +++++++ .../speech_language_settings_state.dart | 44 +++ .../videoLog/videoLog/videoLog_logic.dart | 45 ++- .../videoLog/videoLog/videoLog_page.dart | 290 +++++++++------ .../videoLog/videoLog/videoLog_state.dart | 6 + .../videoLogDetail/videoLogDetail_state.dart | 1 - .../advancedFeaturesWeb_entity.dart | 8 + .../advancedFeaturesWeb_logic.dart | 3 + .../advancedFeaturesWeb_state.dart | 2 + .../cloudStorage/cloud_storage_logic.dart | 6 + .../cloudStorage/cloud_storage_page.dart | 150 ++++++++ .../cloudStorage/cloud_storage_state.dart | 13 + lib/network/api.dart | 7 + lib/network/api_provider.dart | 65 ++++ lib/network/api_repository.dart | 51 +++ .../starChart/command/message_command.dart | 6 +- 29 files changed, 1824 insertions(+), 133 deletions(-) create mode 100644 lib/blue/io_protocol/io_getDeviceModel.dart create mode 100644 lib/blue/io_protocol/io_voicePackageConfigure.dart create mode 100644 lib/blue/io_protocol/io_voicePackageConfigureProcess.dart create mode 100644 lib/main/lockDetail/lockDetail/passthrough_item.dart create mode 100644 lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart create mode 100644 lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart create mode 100644 lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart create mode 100644 lib/mine/valueAddedServices/cloudStorage/cloud_storage_logic.dart create mode 100644 lib/mine/valueAddedServices/cloudStorage/cloud_storage_page.dart create mode 100644 lib/mine/valueAddedServices/cloudStorage/cloud_storage_state.dart diff --git a/lib/appRouters.dart b/lib/appRouters.dart index 6ff7ac91..f0acd63c 100755 --- a/lib/appRouters.dart +++ b/lib/appRouters.dart @@ -26,6 +26,7 @@ import 'package:star_lock/main/lockDetail/lockSet/faceUnlock/faceUnlock_page.dar import 'package:star_lock/main/lockDetail/lockSet/liveVideo/liveVideo_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/motorPower/motorPower_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/openDoorDirection/openDoorDirection_page.dart'; +import 'package:star_lock/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart'; import 'package:star_lock/main/lockDetail/messageWarn/addFamily/addFamily_page.dart'; import 'package:star_lock/main/lockDetail/messageWarn/lockUser/lockUser_page.dart'; import 'package:star_lock/main/lockDetail/messageWarn/msgNotification/coerceOpenDoor/coerceFingerprint/coerceFingerprint_page.dart'; @@ -59,6 +60,7 @@ import 'package:star_lock/mine/mineSet/transferSmartLock/selectBranch/selectBran import 'package:star_lock/mine/mineSet/transferSmartLock/transferSmartLockList/transferSmartLock_page.dart'; import 'package:star_lock/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_page.dart'; import 'package:star_lock/mine/valueAddedServices/advancedFunctionRecord/advancedFunctionRecord_page.dart'; +import 'package:star_lock/mine/valueAddedServices/cloudStorage/cloud_storage_page.dart'; import 'package:star_lock/mine/valueAddedServices/valueAddedServicesRecord/value_added_services_record_page.dart'; import 'package:star_lock/talk/starChart/views/guide/permission_guidance_page.dart'; import 'package:star_lock/talk/starChart/views/native/talk_view_native_decode_page.dart'; @@ -368,6 +370,8 @@ abstract class Routers { '/valueAddedServicesRecordPage'; // 增值服务-记录 static const String valueAddedServicesHighFunctionPage = '/ValueAddedServicesHighFunctionPage'; // 增值服务-高级功能 + static const String valueAddedCloudStoragePage = + '/valueAddedCloudStoragePage'; // 增值服务-云存 static const String valueAddedServicesBuyPage = '/ValueAddedServicesBuyPage'; // 增值服务-购买服务 static const String customSMSTemplateListPage = @@ -436,6 +440,8 @@ abstract class Routers { '/AddLockSelectCountryPage'; // 演示模式锁设置页 static const String faceUnlockPage = '/faceUnlockPage'; //面容开锁设置 static const String motorPowerPage = '/motorPowerPage'; //电机功率设置 + static const String speechLanguageSettingsPage = + '/speechLanguageSettingsPage'; //锁语音包设置 static const String openDoorDirectionPage = '/openDoorDirectionPage'; //开门方向设置 static const String catEyeWorkModePage = '/catEyeWorkModePage'; //猫眼工作模式 static const String msgNotificationPage = '/msgNotificationPage'; //消息提醒 @@ -904,6 +910,10 @@ abstract class AppRouters { name: Routers.valueAddedServicesHighFunctionPage, page: () => const ValueAddedServicesHighFunctionPage(), ), + GetPage( + name: Routers.valueAddedCloudStoragePage, + page: () => const CloudStoragePage(), + ), GetPage( name: Routers.customSMSTemplateListPage, page: () => const CustomSMSTemplateListPage(), @@ -1024,6 +1034,9 @@ abstract class AppRouters { name: Routers.faceUnlockPage, page: () => const FaceUnlockPage()), GetPage( name: Routers.motorPowerPage, page: () => const MotorPowerPage()), + GetPage( + name: Routers.speechLanguageSettingsPage, + page: () => const SpeechLanguageSettingsPage()), GetPage( name: Routers.openDoorDirectionPage, page: () => const OpenDoorDirectionPage()), diff --git a/lib/blue/io_protocol/io_getDeviceModel.dart b/lib/blue/io_protocol/io_getDeviceModel.dart new file mode 100644 index 00000000..0a086e05 --- /dev/null +++ b/lib/blue/io_protocol/io_getDeviceModel.dart @@ -0,0 +1,48 @@ + +import 'dart:convert'; + +import '../io_reply.dart'; +import '../io_sender.dart'; +import '../io_tool/io_tool.dart'; +import '../io_type.dart'; + +class GetDeviceModelCommand extends SenderProtocol { + GetDeviceModelCommand({ + this.lockID, + }) : super(CommandType.getDeviceModel); + String? lockID; + + + @override + String toString() { + return 'GetDeviceModelCommand{lockID: $lockID}'; + } + + @override + List messageDetail() { + List data = []; + + // 指令类型 + final int type = commandType!.typeValue; + final double typeDouble = type / 256; + final int type1 = typeDouble.toInt(); + final int type2 = type % 256; + data.add(type1); + data.add(type2); + + final int length = utf8.encode(lockID!).length; + data.addAll(utf8.encode(lockID!)); + data = getFixedLengthList(data, 40 - length); + + printLog(data); + return data; + } +} + +class GetDeviceModelReply extends Reply { + GetDeviceModelReply.parseData(CommandType commandType, List dataDetail) + : super.parseData(commandType, dataDetail) { + status = dataDetail[2]; + data = dataDetail; + } +} diff --git a/lib/blue/io_protocol/io_voicePackageConfigure.dart b/lib/blue/io_protocol/io_voicePackageConfigure.dart new file mode 100644 index 00000000..c43d56ab --- /dev/null +++ b/lib/blue/io_protocol/io_voicePackageConfigure.dart @@ -0,0 +1,163 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:crypto/crypto.dart' as crypto; + +import '../io_reply.dart'; +import '../io_sender.dart'; +import '../io_tool/io_tool.dart'; +import '../io_type.dart'; +import '../sm4Encipher/sm4.dart'; + +//oat升级 +class VoicePackageConfigure extends SenderProtocol { + VoicePackageConfigure( + {this.lockID, + this.userID, + this.keyID, + this.platform, + this.product, + this.fwSize, + this.fwMD5, + this.needAuthor, + this.signKey, + this.privateKey, + this.token, + this.encrypt = true}) + : super(CommandType.startVoicePackageConfigure); + String? lockID; + String? userID; + String? keyID; + int? platform; + int? product; + int? fwSize; + String? fwMD5; + int? needAuthor; + List? signKey; + List? privateKey; + List? token; + bool encrypt; + + @override + String toString() { + return 'VoicePackageConfigure{lockID: $lockID, userID: $userID, ' + 'keyID: $keyID, platform: $platform, product: $product, ' + ' fwSize: $fwSize, ' + 'fwMD5: $fwMD5, needAuthor: $needAuthor, signKey: $signKey, ' + 'privateKey: $privateKey, token: $token}'; + } + + @override + int identifierValue() { + if (encrypt) { + return super.identifierValue(); + } else { + return 0x20; + } + } + + @override + List messageDetail() { + List data = []; + List ebcData = []; + + // 指令类型 + final int type = commandType!.typeValue; + final double typeDouble = type / 256; + final int type1 = typeDouble.toInt(); + final int type2 = type % 256; + data.add(type1); + data.add(type2); + + // 锁id 40 + final int lockIDLength = utf8.encode(lockID!).length; + data.addAll(utf8.encode(lockID!)); + data = getFixedLengthList(data, 40 - lockIDLength); + + //userID 20 + final int userIDLength = utf8.encode(userID!).length; + data.addAll(utf8.encode(userID!)); + data = getFixedLengthList(data, 20 - userIDLength); + + //platform 2 + final int platform0 = (platform! & 0xFF00) >> 8; + final int platform1 = platform! & 0xFF; + data.add(platform0); + data.add(platform1); + + //product 2 + data.addAll([0, 1]); //先默认是 01 + + + //fwSize 4 + final ByteData bytes = ByteData(4); // 创建一个长度为4的字节数据 + bytes.setInt32(0, fwSize!); + final List byteList = bytes.buffer.asUint8List(); + data.addAll(byteList); + + // 创建一个16字节的字节数组 + final Uint8List result = Uint8List(16); + // 将每个十六进制字符转换为4位二进制数据,并将其存储到结果字节数组中 + for (int i = 0; i < fwMD5!.length; i += 2) { + final String hex = fwMD5!.substring(i, i + 2); + final int byteValue = int.parse(hex, radix: 16); + result[i ~/ 2] = byteValue; + } + data.addAll(result); + // token 长度4 首次请求 Token 填 0,如果锁需要鉴权 操作者身份,则会分配动态口令并在应答消息中返回,二次请求时带上。 当token失效或者第一次发送的时候token为0 + data.addAll(token!); + if (needAuthor == 0) { + //AuthCodeLen 1 + data.add(0); + } else { + final List authCodeData = []; + + //KeyID + authCodeData.addAll(utf8.encode(keyID!)); + + //UserID + authCodeData.addAll(utf8.encode(userID!)); + + //token 4 首次请求 Token 填 0,如果锁需要鉴权操作者身份,则会分配动态口令并在应答消息中返回,二次请求时带上。 + authCodeData.addAll(token ?? []); + + authCodeData.addAll(signKey ?? []); + + // 把KeyID、authUserID、时间戳、公钥通过md5加密之后就是authCode + final crypto.Digest authCode = crypto.md5.convert(authCodeData); + + data.add(authCode.bytes.length); + data.addAll(authCode.bytes); + } + + if ((data.length % 16) != 0) { + final int add = 16 - data.length % 16; + for (int i = 0; i < add; i++) { + data.add(0); + } + } + printLog(data); + + if (encrypt) { + // 拿到数据之后通过LockId进行SM4 ECB加密 key:544d485f633335373034383064613864 + ebcData = SM4.encrypt(data, key: privateKey, mode: SM4CryptoMode.ECB); + return ebcData; + } else { + data.add(0); + return data; + } + } +} + +class VoicePackageConfigureReply extends Reply { + VoicePackageConfigureReply.parseData( + CommandType commandType, List dataDetail) + : super.parseData(commandType, dataDetail) { + data = dataDetail; + token = data.sublist(2, 6); + status = data[6]; + errorWithStstus(status); + } + + List token = []; +} diff --git a/lib/blue/io_protocol/io_voicePackageConfigureProcess.dart b/lib/blue/io_protocol/io_voicePackageConfigureProcess.dart new file mode 100644 index 00000000..44d1ca18 --- /dev/null +++ b/lib/blue/io_protocol/io_voicePackageConfigureProcess.dart @@ -0,0 +1,73 @@ +import 'dart:typed_data'; + +import '../io_reply.dart'; +import '../io_sender.dart'; +import '../io_type.dart'; + +//oat升级 +class VoicePackageConfigureProcess extends SenderProtocol { + VoicePackageConfigureProcess({ + this.index, + this.size, + this.data, + }) : super(CommandType.voicePackageConfigureProcess); + int? index; + int? size; + List? data; + + @override + String toString() { + return 'VoicePackageConfigureProcess{index: $index, size: $size, data: $data}'; + } + + @override + List messageDetail() { + final List data = []; + + // 指令类型 + final int type = commandType!.typeValue; + final double typeDouble = type / 256; + final int type1 = typeDouble.toInt(); + final int type2 = type % 256; + data.add(type1); + data.add(type2); + + //index 2 + final ByteData indexBytes = ByteData(2); // 创建一个长度为4的字节数据 + indexBytes.setInt16(0, index!); + final List indexList = indexBytes.buffer.asUint8List(); + data.addAll(indexList); + + //size 2 + final ByteData bytes = ByteData(2); // 创建一个长度为4的字节数据 + bytes.setInt16(0, size!); + final List byteList = bytes.buffer.asUint8List(); + data.addAll(byteList); + + data.addAll(this.data!); + + printLog(data); + //不加密 + return data; + } +} + +class VoicePackageConfigureProcessReply extends Reply { + VoicePackageConfigureProcessReply.parseData( + CommandType commandType, List dataDetail) + : super.parseData(commandType, dataDetail) { + data = dataDetail; + status = data[2]; + errorWithStstus(status); + } +} + +class VoicePackageConfigureConfirmationReply extends Reply { + VoicePackageConfigureConfirmationReply.parseData( + CommandType commandType, List dataDetail) + : super.parseData(commandType, dataDetail) { + data = dataDetail; + status = data[2]; + errorWithStstus(status); + } +} diff --git a/lib/blue/io_tool/io_tool.dart b/lib/blue/io_tool/io_tool.dart index 7720ad67..981b1e8c 100755 --- a/lib/blue/io_tool/io_tool.dart +++ b/lib/blue/io_tool/io_tool.dart @@ -288,16 +288,27 @@ String asciiString(List codeUnits) { } String utf8String(List codeUnits) { - codeUnits.reversed; - final List uniqueList = []; - for (int i = 0; i < codeUnits.length; i++) { - if (codeUnits[i] != 0) { - uniqueList.add(codeUnits[i]); - } + try { + // 只去除结尾的0(常见填充方式) + int realLen = codeUnits.indexWhere((b) => b == 0); + List validBytes = (realLen == -1) ? codeUnits : codeUnits.sublist(0, realLen); + return utf8.decode(validBytes); + } catch (e) { + // 容错处理 + return ''; } - uniqueList.reversed; - return utf8.decode(uniqueList).toString(); } +// String utf8String(List codeUnits) { +// codeUnits.reversed; +// final List uniqueList = []; +// for (int i = 0; i < codeUnits.length; i++) { +// if (codeUnits[i] != 0) { +// uniqueList.add(codeUnits[i]); +// } +// } +// uniqueList.reversed; +// return utf8.decode(uniqueList).toString(); +// } bool compareTwoList({List? list1, List? list2}) { if (list1!.length != list2!.length) { diff --git a/lib/blue/io_type.dart b/lib/blue/io_type.dart index a5f523b4..6a4ceffa 100755 --- a/lib/blue/io_type.dart +++ b/lib/blue/io_type.dart @@ -41,6 +41,10 @@ enum CommandType { startOATUpgrade, //OTA升级开始 0x30E0 processOTAUpgrade, //OTA升级过程 0x30E1 confirmationOTAUpgrade, //OTA升级确认 0x30E2 + startVoicePackageConfigure, //语音包配置开始 0x30A1 + voicePackageConfigureProcess, //语音包配置过程 0x30A2 + voicePackageConfigureConfirmation, //语音包配置确认 0x30A3 + getDeviceModel, //获取设备型号 0x30A4 gatewayConfiguringWifi, //网关配网 0x30F4 gatewayConfiguringWifiResult, //网关配网结果 0x30F5 @@ -189,6 +193,26 @@ extension ExtensionCommandType on CommandType { type = CommandType.confirmationOTAUpgrade; } break; + case 0x30A1: + { + type = CommandType.startVoicePackageConfigure; + } + break; + case 0x30A2: + { + type = CommandType.voicePackageConfigureProcess; + } + break; + case 0x30A3: + { + type = CommandType.voicePackageConfigureConfirmation; + } + break; + case 0x30A4: + { + type = CommandType.getDeviceModel; + } + break; case 0x30F4: { type = CommandType.gatewayConfiguringWifi; @@ -307,6 +331,18 @@ extension ExtensionCommandType on CommandType { case CommandType.gatewayGetStatus: type = 0x30F8; break; + case CommandType.startVoicePackageConfigure: + type = 0x30A1; + break; + case CommandType.voicePackageConfigureProcess: + type = 0x30A2; + break; + case CommandType.voicePackageConfigureConfirmation: + type = 0x30A3; + break; + case CommandType.getDeviceModel: + type = 0x30A4; + break; default: type = 0x300A; break; @@ -322,9 +358,11 @@ extension ExtensionCommandType on CommandType { switch (this) { case CommandType.getLockPublicKey: case CommandType.processOTAUpgrade: + case CommandType.voicePackageConfigureProcess: case CommandType.gatewayGetWifiList: case CommandType.gatewayConfiguringWifi: case CommandType.gatewayGetStatus: + case CommandType.getDeviceModel: //不加密 type = 0x20; break; @@ -428,6 +466,18 @@ extension ExtensionCommandType on CommandType { case 0x30F8: t = '获取网关状态'; break; + case 0x30A1: + t = '语音包配置开始'; + break; + case 0x30A2: + t = '语音包配置过程'; + break; + case 0x30A3: + t = '语音包配置确认'; + break; + case 0x30A4: + t = '获取设备型号'; + break; default: t = '读星锁状态信息'; break; diff --git a/lib/blue/reciver_data.dart b/lib/blue/reciver_data.dart index 0b0f4c61..1a2006e0 100755 --- a/lib/blue/reciver_data.dart +++ b/lib/blue/reciver_data.dart @@ -12,6 +12,7 @@ import 'package:star_lock/blue/io_protocol/io_cleanUpUsers.dart'; import 'package:star_lock/blue/io_protocol/io_deletUser.dart'; import 'package:star_lock/blue/io_protocol/io_editUser.dart'; import 'package:star_lock/blue/io_protocol/io_factoryDataReset.dart'; +import 'package:star_lock/blue/io_protocol/io_getDeviceModel.dart'; import 'package:star_lock/blue/io_protocol/io_otaUpgrade.dart'; import 'package:star_lock/blue/io_protocol/io_processOtaUpgrade.dart'; import 'package:star_lock/blue/io_protocol/io_readAdminPassword.dart'; @@ -21,6 +22,8 @@ import 'package:star_lock/blue/io_protocol/io_referEventRecordTime.dart'; import 'package:star_lock/blue/io_protocol/io_setSupportFunctionsNoParameters.dart'; import 'package:star_lock/blue/io_protocol/io_setSupportFunctionsWithParameters.dart'; import 'package:star_lock/blue/io_protocol/io_timing.dart'; +import 'package:star_lock/blue/io_protocol/io_voicePackageConfigure.dart'; +import 'package:star_lock/blue/io_protocol/io_voicePackageConfigureProcess.dart'; import '../tools/storage.dart'; import 'io_gateway/io_gateway_getStatus.dart'; @@ -292,6 +295,28 @@ class CommandReciverManager { reply = GatewayGetStatusReply.parseData(commandType, data); } break; + case CommandType.getDeviceModel: + { + reply = GetDeviceModelReply.parseData(commandType, data); + } + break; + case CommandType.startVoicePackageConfigure: + { + reply = VoicePackageConfigureReply.parseData(commandType, data); + } + break; + case CommandType.voicePackageConfigureProcess: + { + reply = + VoicePackageConfigureProcessReply.parseData(commandType, data); + } + break; + case CommandType.voicePackageConfigureConfirmation: + { + reply = VoicePackageConfigureConfirmationReply.parseData( + commandType, data); + } + break; case CommandType.generalExtendedCommond: { // 子命令类型 diff --git a/lib/common/XSConstantMacro/XSConstantMacro.dart b/lib/common/XSConstantMacro/XSConstantMacro.dart index e10177c2..5ee8df23 100755 --- a/lib/common/XSConstantMacro/XSConstantMacro.dart +++ b/lib/common/XSConstantMacro/XSConstantMacro.dart @@ -90,6 +90,7 @@ class XSConstantMacro { static int webBuyTypeVip = 3; //VIP购买 static int webBuyTypeAuth = 4; //实名购买 static int webBuyTypeShop = 5; //商城购买 + static int webBuyTypeCloudStorage = 6; //云存购买 //设备类型信息 Future> getDeviceInfoData() async { diff --git a/lib/main/lockDetail/lockDetail/lockDetail_logic.dart b/lib/main/lockDetail/lockDetail/lockDetail_logic.dart index 1155117f..da62eff6 100755 --- a/lib/main/lockDetail/lockDetail/lockDetail_logic.dart +++ b/lib/main/lockDetail/lockDetail/lockDetail_logic.dart @@ -783,7 +783,7 @@ class LockDetailLogic extends BaseGetXController { // } /// 发送监控消息 - void sendMonitorMessage() { + void sendMonitorMessage() async { final catEyeConfig = state.keyInfos.value.lockSetting?.catEyeConfig ?? []; final network = state.keyInfos.value.network; if (catEyeConfig.isNotEmpty && @@ -840,24 +840,48 @@ class LockDetailLogic extends BaseGetXController { state.DetailLockInfo = eventBus .on() .listen((PassCurrentLockInformationEvent event) { - if (event.lockSetInfoData.lockSettingInfo != null && - event.lockSetInfoData.lockSettingInfo!.catEyeConfig != null && - event.lockSetInfoData.lockSettingInfo!.catEyeConfig!.length > 0) { - if (state.keyInfos.value.lockSetting!.catEyeConfig == null || - state.keyInfos.value.lockSetting!.catEyeConfig!.length == 0) { - state.keyInfos.value.lockSetting!.catEyeConfig!.add(CatEyeConfig( + // 提取重复表达式为局部变量,避免多次解包 + final lockSettingInfo = event.lockSetInfoData.lockSettingInfo; + final lockBasicInfo = event.lockSetInfoData.lockBasicInfo; + final networkInfo = lockBasicInfo?.networkInfo; + final targetCatEyeConfig = lockSettingInfo?.catEyeConfig; + + if (lockBasicInfo != null && networkInfo != null) { + state.keyInfos.value.network?.peerId = networkInfo.peerId; + state.keyInfos.value.network?.wifiName = networkInfo.wifiName; + } + + // 检查前置条件:事件数据有效且 catEyeConfig 非空且非空列表 + if (lockSettingInfo != null && + targetCatEyeConfig != null && + targetCatEyeConfig.isNotEmpty) { + // 当前状态的 catEyeConfig + final stateCatEyeConfig = + state.keyInfos.value.lockSetting?.catEyeConfig; + + // 如果状态中的 catEyeConfig 为空或空列表,则初始化默认配置 + if (stateCatEyeConfig == null || stateCatEyeConfig.isEmpty) { + state.keyInfos.value.lockSetting?.catEyeConfig ??= []; + state.keyInfos.value.lockSetting!.catEyeConfig!.add( + CatEyeConfig( catEyeMode: 0, catEyeModeConfig: CatEyeModeConfig( - realTimeMode: 0, - recordEndTime: 0, - recordMode: 0, - recordStartTime: 0, - recordTime: '0', - detectionDistance: '0'))); + realTimeMode: 0, + recordEndTime: 0, + recordMode: 0, + recordStartTime: 0, + recordTime: '0', + detectionDistance: '0', + ), + ), + ); } - state.keyInfos.value.lockSetting!.catEyeConfig![0].catEyeMode = event - .lockSetInfoData.lockSettingInfo!.catEyeConfig![0].catEyeMode ?? - 1; + + // 更新 catEyeMode,使用空值合并提供默认值 1 + state.keyInfos.value.lockSetting!.catEyeConfig![0].catEyeMode = + targetCatEyeConfig[0].catEyeMode ?? 1; + + // 刷新状态 state.keyInfos.refresh(); } }); diff --git a/lib/main/lockDetail/lockDetail/passthrough_item.dart b/lib/main/lockDetail/lockDetail/passthrough_item.dart new file mode 100644 index 00000000..bb9a910c --- /dev/null +++ b/lib/main/lockDetail/lockDetail/passthrough_item.dart @@ -0,0 +1,281 @@ +// 音色项类 +import 'package:get/get.dart'; + +class TimbreItem { + final String timbre; + final String name; + final String timbrePackUrl; + + TimbreItem({ + required this.timbre, + required this.name, + required this.timbrePackUrl, + }); + + factory TimbreItem.fromJson(Map json) { + return TimbreItem( + timbre: json['timbre'] ?? '', + name: json['name'] ?? '', + timbrePackUrl: json['timbrePackUrl'] ?? '', + ); + } + + Map toJson() { + return { + 'timbre': timbre, + 'name': name, + 'timbrePackUrl': timbrePackUrl, + }; + } + + @override + String toString() { + return 'TimbreItem{timbre: $timbre, name: $name, timbrePackUrl: $timbrePackUrl}'; + } +} + +// 透传项主类 +class PassthroughItem { + final String lang; + final List timbres; + + PassthroughItem({ + required this.lang, + required this.timbres, + }); + + factory PassthroughItem.fromJson(Map json) { + var timbresJson = json['timbres'] as List?; + List timbresList = timbresJson != null + ? timbresJson + .map((e) => TimbreItem.fromJson(e as Map)) + .toList() + : []; + return PassthroughItem( + lang: json['lang'] ?? '', + timbres: timbresList, + ); + } + + Map toJson() { + return { + 'lang': lang, + 'timbres': timbres.map((e) => e.toJson()).toList(), + }; + } + + @override + String toString() { + return 'PassthroughItem{lang: $lang, timbres: $timbres}'; + } +} + +class PassthroughListResponse { + PassthroughListResponse({ + this.description, + this.errorCode, + this.data, + this.errorMsg, + }); + + String? description; + int? errorCode; + List? data; + String? errorMsg; + + PassthroughListResponse.fromJson(dynamic json) { + description = json['description']; + errorCode = json['errorCode']; + if (json['data'] != null && json['data'] is List) { + data = (json['data'] as List) + .map((e) => PassthroughItem.fromJson(e as Map)) + .toList(); + } else { + data = null; + } + errorMsg = json['errorMsg']; + } + + Map toJson() { + final map = {}; + map['description'] = description; + map['errorCode'] = errorCode; + if (data != null) { + map['data'] = data!.map((e) => e.toJson()).toList(); + } + map['errorMsg'] = errorMsg; + return map; + } +} + +/// 工具方法:通过语言编码获取本地化文本 +/// 例如:'zh_CN' -> '简体中文'.tr,'en_US' -> '英文'.tr +class PassthroughLangHelper { + static String getLangText(String langCode) { + switch (langCode.toLowerCase()) { + case 'zh_cn': + return '简体中文'.tr; + case 'zh_tw': + return '繁体中文(中国台湾)'.tr; + case 'zh_hk': + return '繁体中文(中国香港)'.tr; + case 'en_us': + return '英文'.tr; + case 'fr_fr': + return '法语'.tr; + case 'ru_ru': + return '俄语'.tr; + case 'de_de': + return '德语'.tr; + case 'ja_jp': + return '日语'.tr; + case 'ko_kr': + return '韩语'.tr; + case 'it_it': + return '意大利语'.tr; + case 'pt_pt': + return '葡萄牙语'.tr; + case 'es_es': + return '西班牙语'.tr; + case 'ar_sa': + return '阿拉伯语'.tr; + case 'vi_vn': + return '越南语'.tr; + case 'ms_my': + return '马来语'.tr; + case 'nl_nl': + return '荷兰语'.tr; + case 'ro_ro': + return '罗马尼亚语'.tr; + case 'lt_lt': + return '立陶宛语'.tr; + case 'sv_se': + return '瑞典语'.tr; + case 'et_ee': + return '爱沙尼亚语'.tr; + case 'pl_pl': + return '波兰语'.tr; + case 'sk_sk': + return '斯洛伐克语'.tr; + case 'cs_cz': + return '捷克语'.tr; + case 'el_gr': + return '希腊语'.tr; + case 'he_il': + return '希伯来语'.tr; + case 'sr_rs': + return '塞尔维亚语'.tr; + case 'tr_tr': + return '土耳其语'.tr; + case 'hu_hu': + return '匈牙利语'.tr; + case 'bg_bg': + return '保加利亚语'.tr; + case 'kk_kz': + return '哈萨克斯坦语'.tr; + case 'bn_bd': + return '孟加拉语'.tr; + case 'hr_hr': + return '克罗地亚语'.tr; + case 'th_th': + return '泰语'.tr; + case 'id_id': + return '印度尼西亚语'.tr; + case 'fi_fi': + return '芬兰语'.tr; + case 'da_dk': + return '丹麦语'.tr; + case 'uk_ua': + return '乌克兰语'.tr; + case 'hi_in': + return '印地语'.tr; + case 'ur_pk': + return '乌尔都语'.tr; + case 'hy_am': + return '亚美尼亚语'.tr; + case 'ka_ge': + return '格鲁吉亚语'.tr; + default: + return '未知语言'.tr; + } + } +} + +class ValidityPeriodResponse { + ValidityPeriodResponse({ + this.description, + this.errorCode, + this.data, + this.errorMsg, + }); + + String? description; + int? errorCode; + ValidityPeriod? data; + String? errorMsg; + + ValidityPeriodResponse.fromJson(dynamic json) { + description = json['description']; + errorCode = json['errorCode']; + if (json['data'] != null) { + data = ValidityPeriod.fromJson(json['data']); + } else { + data = null; + } + errorMsg = json['errorMsg']; + } + + Map toJson() { + final map = {}; + map['description'] = description; + map['errorCode'] = errorCode; + if (data != null) { + map['data'] = data!.toJson(); + } + map['errorMsg'] = errorMsg; + return map; + } +} + +class ValidityPeriod { + final int lockId; + final int status; + final String validityPeriodStart; + final String validityPeriodEnd; + final int rollingStorageDays; + final int remainingDays; + + ValidityPeriod({ + required this.lockId, + required this.status, + required this.validityPeriodStart, + required this.validityPeriodEnd, + required this.rollingStorageDays, + required this.remainingDays, + }); + + // 反序列化方法 + factory ValidityPeriod.fromJson(Map json) { + return ValidityPeriod( + lockId: json['lockId'] as int? ?? 0, + // 默认值为 0 + status: json['status'] as int? ?? 0, + validityPeriodStart: json['validityPeriodStart'] as String? ?? '', + validityPeriodEnd: json['validityPeriodEnd'] as String? ?? '', + rollingStorageDays: json['rollingStorageDays'] as int? ?? 0, + remainingDays: json['remainingDays'] as int? ?? 0, + ); + } + + // 序列化方法 + Map toJson() { + return { + 'lockId': lockId, + 'status': status, + 'validityPeriodStart': validityPeriodStart, + 'validityPeriodEnd': validityPeriodEnd, + 'rollingStorageDays': rollingStorageDays, + 'remainingDays': remainingDays, + }; + } +} diff --git a/lib/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart b/lib/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart index 5127c0b5..ccda689f 100755 --- a/lib/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart +++ b/lib/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart @@ -158,6 +158,7 @@ class LockFeature { this.isElectronicAntiLock, this.isVisualDoorBellCode, this.isDoubleLockLinkage, + this.languageSpeech, }); LockFeature.fromJson(Map json) { @@ -218,6 +219,7 @@ class LockFeature { isElectronicAntiLock = json['isElectronicAntiLock']; isVisualDoorBellCode = json['isVisualDoorBellCode']; isDoubleLockLinkage = json['isDoubleLockLinkage']; + languageSpeech = json['languageSpeech']; } int? password; @@ -277,6 +279,7 @@ class LockFeature { int? isElectronicAntiLock; int? isVisualDoorBellCode; int? isDoubleLockLinkage; + int? languageSpeech; Map toJson() { final Map data = {}; @@ -337,6 +340,7 @@ class LockFeature { data['isElectronicAntiLock'] = isElectronicAntiLock; data['isVisualDoorBellCode'] = isVisualDoorBellCode; data['isDoubleLockLinkage'] = isDoubleLockLinkage; + data['languageSpeech'] = languageSpeech; return data; } } @@ -348,6 +352,8 @@ class LockBasicInfo { this.keyId, this.model, this.electricQuantity, + this.hwVersion, + this.fwVersion, this.electricQuantityStandby, this.indate, this.isLockOwner, @@ -376,6 +382,8 @@ class LockBasicInfo { keyId = json['keyId']; model = json['model']; electricQuantity = json['electricQuantity']; + hwVersion = json['hwVersion']; + fwVersion = json['fwVersion']; electricQuantityStandby = json['electricQuantityStandby']; indate = json['indate']; isLockOwner = json['isLockOwner']; @@ -411,6 +419,8 @@ class LockBasicInfo { int? keyId; String? model; int? electricQuantity; + String? fwVersion; + String? hwVersion; int? electricQuantityStandby; int? indate; int? isLockOwner; @@ -440,6 +450,8 @@ class LockBasicInfo { data['keyId'] = keyId; data['model'] = model; data['electricQuantity'] = electricQuantity; + data['hwVersion'] = hwVersion; + data['fwVersion'] = fwVersion; data['electricQuantityStandby'] = electricQuantityStandby; data['indate'] = indate; data['isLockOwner'] = isLockOwner; @@ -523,6 +535,7 @@ class LockSettingInfo { this.autoLightScreen, this.autoLightScreenTime, this.faceEnErrUnlock, + this.currentVoiceTimbre, }); LockSettingInfo.fromJson(Map json) { @@ -570,6 +583,10 @@ class LockSettingInfo { autoLightScreen = json['autoLightScreen']; autoLightScreenTime = json['autoLightScreenTime']; faceEnErrUnlock = json['faceEnErrUnlock']; + if (json['currentVoiceTimbre'] != null) { + currentVoiceTimbre = + CurrentVoiceTimbre.fromJson(json['currentVoiceTimbre']); + } } int? remoteUnlock; @@ -605,6 +622,7 @@ class LockSettingInfo { int? autoLightScreen; //猫眼-自动亮屏开关 0:关闭 1:开启 int? autoLightScreenTime; //猫眼-自动亮屏时间 int? faceEnErrUnlock; + CurrentVoiceTimbre? currentVoiceTimbre; Map toJson() { final Map data = {}; @@ -645,7 +663,9 @@ class LockSettingInfo { data['autoLightScreen'] = autoLightScreen; data['autoLightScreenTime'] = autoLightScreenTime; data['faceEnErrUnlock'] = faceEnErrUnlock; - + if (currentVoiceTimbre != null) { + data['currentVoiceTimbre'] = currentVoiceTimbre!.toJson(); + } return data; } } @@ -757,3 +777,29 @@ class CatEyeModeConfig { return data; } } + +class CurrentVoiceTimbre { + String? lang; + String? timbre; + + CurrentVoiceTimbre({ + this.lang, + this.timbre, + }); + + // 将对象转换为 JSON 数据 + Map toJson() { + final Map data = {}; + data['lang'] = lang; + data['timbre'] = timbre; + return data; + } + + // 从 JSON 数据构造对象 + factory CurrentVoiceTimbre.fromJson(Map json) { + return CurrentVoiceTimbre( + timbre: json['timbre'], + lang: json['lang'], + ); + } +} diff --git a/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart b/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart index e4d22536..43cbc989 100755 --- a/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart +++ b/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart @@ -526,6 +526,20 @@ class _LockSetPageState extends State 'lockSetInfoData': state.lockSetInfoData.value }); })), + // 锁语音包设置 + Visibility( + visible: state.lockFeature.value.languageSpeech == 1, + child: CommonItem( + leftTitel: '语音包设置'.tr, + rightTitle: '', + isHaveLine: true, + isHaveDirection: true, + action: () { + Get.toNamed(Routers.speechLanguageSettingsPage, + arguments: { + 'lockSetInfoData': state.lockSetInfoData.value + }); + })), // 蓝牙广播(关闭则不能使用蓝牙主动开锁) /* 2024-01-12 会议确定去掉“蓝牙广播” by DaisyWu Obx(() => Visibility( diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart new file mode 100644 index 00000000..a42f4776 --- /dev/null +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart @@ -0,0 +1,334 @@ +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:crypto/crypto.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_blue_plus/flutter_blue_plus.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:get/get.dart'; +import 'package:star_lock/app_settings/app_settings.dart'; +import 'package:star_lock/blue/blue_manage.dart'; +import 'package:star_lock/blue/io_protocol/io_getDeviceModel.dart'; +import 'package:star_lock/blue/io_protocol/io_otaUpgrade.dart'; +import 'package:star_lock/blue/io_protocol/io_processOtaUpgrade.dart'; +import 'package:star_lock/blue/io_protocol/io_voicePackageConfigure.dart'; +import 'package:star_lock/blue/io_protocol/io_voicePackageConfigureProcess.dart'; +import 'package:star_lock/blue/io_reply.dart'; +import 'package:star_lock/blue/io_tool/io_tool.dart'; +import 'package:star_lock/blue/io_tool/manager_event_bus.dart'; +import 'package:star_lock/login/login/entity/LoginEntity.dart'; +import 'package:star_lock/login/selectCountryRegion/common/index.dart'; +import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart'; +import 'package:star_lock/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart'; +import 'package:star_lock/network/api_repository.dart'; +import 'package:star_lock/tools/baseGetXController.dart'; +import 'package:http/http.dart' as http; +import 'package:star_lock/tools/commonDataManage.dart'; +import 'package:star_lock/tools/storage.dart'; + +class SpeechLanguageSettingsLogic extends BaseGetXController { + final SpeechLanguageSettingsState state = SpeechLanguageSettingsState(); + StreamSubscription? _replySubscription; + + @override + void onInit() async { + super.onInit(); + _replySubscription = + EventBusManager().eventBus!.on().listen((Reply reply) async { + if (reply is GetDeviceModelReply) { + // 获取设备型号 + _handlerDeviceModelReply(reply); + } + if (reply is VoicePackageConfigureReply) { + // 语言包配置开始 + _handlerStartVoicePackageConfigure(reply); + } else if (reply is VoicePackageConfigureProcessReply) { + _handlerVoicePackageConfigureProcess(reply); + } else if (reply is VoicePackageConfigureConfirmationReply) { + final PassthroughItem item = + state.languages[state.selectPassthroughListIndex.value]; + final timbre = item.timbres[state.selectLanguageIndex.value]; + final LoginEntity entity = + await ApiRepository.to.settingCurrentVoiceTimbre( + data: { + 'lang': item.lang, + 'timbre': timbre.timbre, + }, + lockId: state.lockSetInfoData.value.lockId!, + ); + if (entity.errorCode!.codeIsSuccessful) { + showSuccess('设置成功'.tr); + } + dismissEasyLoading(); + } + }); + await sendGetDeviceModelBleMessage(); + } + + @override + void onClose() { + _replySubscription?.cancel(); + } + + /// 获取列表 + initList() async { + showEasyLoading(); + try { + final PassthroughListResponse entity = await ApiRepository.to + .getPassthroughList(data: {'deviceType': state.deviceModel.value}); + if (entity.errorCode!.codeIsSuccessful) { + state.languages.value = entity.data!!; + final oldTimbre = state + .lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre; + final oldLang = state + .lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang; + + for (int index = 0; index < state.languages.value.length; index++) { + final element = state.languages.value[index]; + final timbres = element.timbres; + for (int i = 0; i < timbres.length; i++) { + final timbre = timbres[i].timbre; + if ((oldLang != null && oldLang == element.lang) && + (oldTimbre != null && oldTimbre == timbre)) { + state.selectPassthroughListIndex.value = index; + state.selectLanguageIndex.value = i; + } + } + } + } + } catch (e) { + debugPrint('获取语音包出现错误:$e'); + } finally { + dismissEasyLoading(); + } + } + + void saveSpeechLanguageSettings() async { + // 如果已经开始发送中则不处理保存点击事件 + if (state.progress.value > 0) { + return; + } + final oldTimbre = + state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre; + final oldLang = + state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang; + + EasyLoading.showProgress(state.progress.value, status: '正在发送数据'); + final PassthroughItem item = + state.languages[state.selectPassthroughListIndex.value]; + final timbre = item.timbres[state.selectLanguageIndex.value]; + debugPrint('选中的语音是:${timbre}'); + if ((oldLang != null && oldLang == item.lang) && + (oldTimbre != null && oldTimbre == timbre.timbre)) { + showToast('已设置为当前选择的语音包'.tr); + } + await downloadFile(timbre.timbrePackUrl); + } + + void changeSelectIndex(int index) { + state.selectLanguageIndex.value = index; + } + + //下载语音包 + Future downloadFile(String url) async { + final http.Response response = await http.get(Uri.parse(url)); + if (response.statusCode == 200) { + state.data = response.bodyBytes; + sendFileToDevice(response.bodyBytes, [0, 0, 0, 0]); + } + } + + sendFileToDevice(Uint8List data, List token) { + BlueManage().blueSendData(BlueManage().connectDeviceName, + (BluetoothConnectionState deviceConnectionState) async { + if (deviceConnectionState == BluetoothConnectionState.connected) { + final List? privateKey = + await Storage.getStringList(saveBluePrivateKey); + final List getPrivateKeyList = + changeStringListToIntList(privateKey!); + final List? signKey = + await Storage.getStringList(saveBlueSignKey); + final List signKeyDataList = changeStringListToIntList(signKey!); + final String uid = await Storage.getUid() ?? ''; + final String md5Str = md5.convert(data).toString().toUpperCase(); + BlueManage().writeCharacteristicWithResponse( + VoicePackageConfigure( + lockID: BlueManage().connectDeviceName, + userID: uid, + keyID: BlueManage().connectDeviceName, + platform: 0, + product: 0, + fwSize: data.length, + fwMD5: md5Str, + needAuthor: 1, + token: token, + signKey: signKeyDataList, + privateKey: getPrivateKeyList) + .packageData(), + ); + } else if (deviceConnectionState == + BluetoothConnectionState.disconnected) {} + }); + } + + // 发送获取型号蓝牙命令 + sendGetDeviceModelBleMessage() { + showEasyLoading(); + showBlueConnetctToastTimer(action: () { + dismissEasyLoading(); + }); + BlueManage().blueSendData(BlueManage().connectDeviceName, + (BluetoothConnectionState deviceConnectionState) async { + if (deviceConnectionState == BluetoothConnectionState.connected) { + BlueManage().writeCharacteristicWithResponse( + GetDeviceModelCommand( + lockID: BlueManage().connectDeviceName, + ).packageData(), + ); + } else if (deviceConnectionState == + BluetoothConnectionState.disconnected) { + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + showBlueConnetctToast(); + } + }); + } + + void _handlerDeviceModelReply(GetDeviceModelReply reply) async { + final int status = reply.data[2]; + switch (status) { + case 0x00: + //成功 + cancelBlueConnetctToastTimer(); + // 3. 解析DeviceModel(40字节,索引3~42) + int startIndex = 3; + int length = 40; + List deviceModelBytes = + reply.data.sublist(startIndex, startIndex + length); + + String rawData = String.fromCharCodes(deviceModelBytes); + int firstNullIndex = rawData.indexOf('\u0000'); + String deviceModel = rawData.substring(0, firstNullIndex); + print(deviceModel); // 输出: 2403 + print('获取到 DeviceModel (原始): $deviceModel'); + state.deviceModel.value = deviceModel; + await initList(); + break; + default: + showToast('获取设备型号失败'.tr); + break; + } + } + + // 开始配置语音包 + void _handlerStartVoicePackageConfigure( + VoicePackageConfigureReply reply) async { + final int status = reply.data[6]; + switch (status) { + case 0x00: + //成功 + cancelBlueConnetctToastTimer(); + + _startSendLanguageFile(); + + break; + case 0x06: + //无权限 + final List token = reply.data.sublist(2, 6); + print('收到token:$token'); + if (state.data != null) { + sendFileToDevice(state.data!, token); + } + break; + default: + showToast('获取设备型号失败'.tr); + break; + } + } + + void _startSendLanguageFile() { + if (state.data == null) return; + state.voiceSubcontractingIndex = 0; + state.voiceSubcontractingCount = + (state.data!.length + state.voiceSubcontractingSize - 1) ~/ + state.voiceSubcontractingSize; + state.progress.value = 0.0; // 开始前重置进度 + _sendNextPackage(); + } + + void _sendNextPackage() { + if (state.voiceSubcontractingIndex >= state.voiceSubcontractingCount) { + print('所有分包已发送完成'); + state.progress.value = 1.0; // 发送完成 + // 可在此处通知UI或做后续处理 + return; + } + + int start = state.voiceSubcontractingIndex * state.voiceSubcontractingSize; + int end = start + state.voiceSubcontractingSize; + if (end > state.data!.length) end = state.data!.length; + Uint8List packageData = state.data!.sublist(start, end); + + // 更新分包进度 + state.progress.value = + (state.voiceSubcontractingIndex + 1) / state.voiceSubcontractingCount; + EasyLoading.showProgress(state.progress.value, + status: '正在发送数据 ${(state.progress.value * 100).toStringAsFixed(0)}%'); + _sendLanguageFileBleMessage( + index: state.voiceSubcontractingIndex, + data: packageData, + ); + } + + _sendLanguageFileBleMessage({required int index, required Uint8List data}) { + BlueManage().blueSendData(BlueManage().connectDeviceName, + (BluetoothConnectionState deviceConnectionState) async { + if (deviceConnectionState == BluetoothConnectionState.connected) { + BlueManage().writeCharacteristicWithResponse( + VoicePackageConfigureProcess( + index: index, + size: data.length, + data: data, + ).packageData(), + ); + } else if (deviceConnectionState == + BluetoothConnectionState.disconnected) { + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + showBlueConnetctToast(); + } + }); + } + + void _handlerVoicePackageConfigureProcess( + VoicePackageConfigureProcessReply reply) { + final int status = reply.data[2]; + switch (status) { + case 0x00: + cancelBlueConnetctToastTimer(); + state.voiceSubcontractingIndex++; + _sendNextPackage(); + break; + default: + showToast('发送分包数据不成功'.tr); + break; + } + } + + @override + void dispose() async { + super.dispose(); + await _replySubscription?.cancel(); + _replySubscription = null; + await BlueManage().disconnect(); + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + EasyLoading.dismiss(); + // 清理分包相关状态 + state.progress.value = 0.0; + state.voiceSubcontractingIndex = 0; + state.voiceSubcontractingCount = 0; + state.data = null; + } +} diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart new file mode 100644 index 00000000..cbb030bd --- /dev/null +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart @@ -0,0 +1,127 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.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/lockDetail/passthrough_item.dart'; +import 'package:star_lock/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart'; +import 'package:star_lock/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart'; +import 'package:star_lock/tools/titleAppBar.dart'; + +class SpeechLanguageSettingsPage extends StatefulWidget { + const SpeechLanguageSettingsPage(); + + @override + State createState() => + _SpeechLanguageSettingsPageState(); +} + +class _SpeechLanguageSettingsPageState + extends State { + final SpeechLanguageSettingsLogic logic = + Get.put(SpeechLanguageSettingsLogic()); + final SpeechLanguageSettingsState state = + Get.find().state; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColors.mainBackgroundColor, + appBar: TitleAppBar( + barTitle: '锁语音包设置'.tr, + haveBack: true, + backgroundColor: AppColors.mainColor, + actionsList: [ + TextButton( + onPressed: logic.saveSpeechLanguageSettings, + child: Text( + '保存'.tr, + style: TextStyle( + color: Colors.white, + fontSize: 24.sp, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + body: _buildBody(), + ); + } + + Widget _buildBody() { + return Obx( + () => Stack( + children: [ + Column( + children: [ + ..._buildList(), + ], + ), + // 移除进度条显示 + ], + ), + ); + } + + List _buildList() { + final languages = state.languages; + return List.generate( + languages.length, + (index) => _buildItem(languages[index], index), + ); + } + + _buildItem(PassthroughItem language, int index) { + final timbres = language.timbres; + final isSelected = state.selectPassthroughListIndex == index; + return ExpansionTile( + title: Text( + PassthroughLangHelper.getLangText(language.lang), + style: TextStyle( + fontSize: 24.sp, + fontWeight: isSelected ? FontWeight.bold : null, + ), + ), + onExpansionChanged: (bool expanded) {}, + initiallyExpanded: true, + backgroundColor: Colors.white, + collapsedBackgroundColor: Colors.white, + expandedCrossAxisAlignment: CrossAxisAlignment.center, + expandedAlignment: Alignment.center, + shape: InputBorder.none, + maintainState: true, + // 去除展开状态下的边框 + collapsedShape: InputBorder.none, + // 去除折叠状态下的边框 + childrenPadding: EdgeInsets.only(left: 12.w), + children: List.generate( + timbres.length, + (int languageIndex) => ListTile( + title: Text( + timbres[languageIndex].name, + style: TextStyle( + fontSize: 22.sp, + fontWeight: + state.selectLanguageIndex == languageIndex && isSelected + ? FontWeight.bold + : null, + ), + ), + trailing: state.selectLanguageIndex == languageIndex && isSelected + ? Icon( + Icons.check_circle, + color: AppColors.mainColor, + ) // 仅当选中时显示图标 + : null, // 默认不显示 + onTap: () { + // 更新选中的语音包 + state.selectLanguageIndex.value = languageIndex; + // 更新选中的语言 + state.selectPassthroughListIndex.value = index; + }, // 默认图标, // 右侧的图标 + ), + ), + ); + } +} diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart new file mode 100644 index 00000000..8bcaa4e7 --- /dev/null +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart @@ -0,0 +1,44 @@ +import 'dart:typed_data'; + +import 'package:flutter/widgets.dart'; +import 'package:get/get.dart'; +import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart'; +import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart'; + +class SpeechLanguageSettingsState { + SpeechLanguageSettingsState() { + final map = Get.arguments; + lockSetInfoData.value = map['lockSetInfoData']; + } + + Rx lockSetInfoData = LockSetInfoData().obs; + + // 选中的语音包列表下标 + RxInt selectPassthroughListIndex = 0.obs; + + // 选中的语音下标 + RxInt selectLanguageIndex = 0.obs; + + final RxList languages = [].obs; + + Map languageSpeechDeviceTypeMapping = {0: '2403'}; + + RxBool otaUpdateIng = false.obs; + RxDouble otaProgress = 0.00.obs; + RxString deviceModel = '2403'.obs; + Uint8List? data; + + // 语音包最大大小 + int voiceSubcontractingSize = 256; + + // 总数据包数量 + int voiceSubcontractingCount = 0; + + // 数据包序列号 + int voiceSubcontractingIndex = 0; + + // 分包发送进度(0.0~1.0) + RxDouble progress = 0.0.obs; + + +} diff --git a/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart b/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart index e90c9793..35bc490c 100755 --- a/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart +++ b/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart @@ -2,8 +2,12 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; +import 'package:get/get.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:star_lock/appRouters.dart'; +import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart'; import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart'; +import 'package:star_lock/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_entity.dart'; import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/tools/baseGetXController.dart'; @@ -142,10 +146,45 @@ class VideoLogLogic extends BaseGetXController { } } - @override - onReady() { - super.onReady(); + getLockPassthroughInfo() async { + showEasyLoading(); + try { + var entity = await ApiRepository.to.getValidityPeriodInfo( + lockId: state.getLockId.value, + ); + if (entity.errorCode!.codeIsSuccessful) { + state.validityPeriodInfo.value = entity.data!; + } + } catch (e) { + } finally { + dismissEasyLoading(); + } + } + @override + void onInit() async { + await getLockPassthroughInfo(); + super.onInit(); + } + + @override + onReady() async { + super.onReady(); getLockCloudStorageList(); } + + getWebPlayUrl() async { + final AdvancedFeaturesWebEntity entity = + await ApiRepository.to.getServicePackageBuyUrl(); + if (entity.errorCode!.codeIsSuccessful) { + state.cloudStorageWebViewUrl.value = entity.data!.cloudStorage!; + final uploadReportBuyRequest = await ApiRepository.to + .uploadReportBuyRequest(lockId: state.getLockId.value); + if (uploadReportBuyRequest.errorCode!.codeIsSuccessful) { + Get.toNamed(Routers.advancedFeaturesWebPage, arguments: { + 'webBuyType': XSConstantMacro.webBuyTypeCloudStorage, + }); + } + } + } } diff --git a/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart b/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart index 5e83bee2..0167d59b 100755 --- a/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart +++ b/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart @@ -26,7 +26,9 @@ class VideoLogPage extends StatefulWidget { class _VideoLogPageState extends State { final VideoLogLogic logic = Get.put(VideoLogLogic()); - final VideoLogState state = Get.find().state; + final VideoLogState state = Get + .find() + .state; @override void initState() { @@ -54,64 +56,66 @@ class _VideoLogPageState extends State { // title加编辑按钮 editVideoTip(), Obx( - () => Visibility( - visible: !state.isNavLocal.value, - child: state.videoLogList.length > 0 - ? Expanded( - child: ListView.builder( - itemCount: state.videoLogList.length, - itemBuilder: (BuildContext c, int index) { - final CloudStorageData item = - state.videoLogList[index]; - return Column( - children: [ - Container( - margin: EdgeInsets.only( - left: 20.w, top: 15.w, bottom: 15.w), - child: Row(children: [ - Text(item.date ?? '', - style: TextStyle(fontSize: 20.sp)), - ])), - mainListView(index, item) - ], - ); - }, - ), - ) - : _buildNotData(), - ), + () => + Visibility( + visible: !state.isNavLocal.value, + child: state.videoLogList.length > 0 + ? Expanded( + child: ListView.builder( + itemCount: state.videoLogList.length, + itemBuilder: (BuildContext c, int index) { + final CloudStorageData item = + state.videoLogList[index]; + return Column( + children: [ + Container( + margin: EdgeInsets.only( + left: 20.w, top: 15.w, bottom: 15.w), + child: Row(children: [ + Text(item.date ?? '', + style: TextStyle(fontSize: 20.sp)), + ])), + mainListView(index, item) + ], + ); + }, + ), + ) + : _buildNotData(), + ), ), // 本地顶部 Obx( - () => Visibility( - visible: state.isNavLocal.value, - child: state.lockVideoList.length > 0 - ? Expanded( - child: ListView.builder( - itemCount: state.lockVideoList.length, - itemBuilder: (BuildContext c, int index) { - final CloudStorageData item = - state.lockVideoList[index]; - return Column( - children: [ - Container( - margin: EdgeInsets.only( - left: 20.w, top: 15.w, bottom: 15.w), - child: Row( - children: [ - Text(item.date ?? '', - style: TextStyle(fontSize: 20.sp)), - ], - ), + () => + Visibility( + visible: state.isNavLocal.value, + child: state.lockVideoList.length > 0 + ? Expanded( + child: ListView.builder( + itemCount: state.lockVideoList.length, + itemBuilder: (BuildContext c, int index) { + final CloudStorageData item = + state.lockVideoList[index]; + return Column( + children: [ + Container( + margin: EdgeInsets.only( + left: 20.w, top: 15.w, bottom: 15.w), + child: Row( + children: [ + Text(item.date ?? '', + style: TextStyle(fontSize: 20.sp)), + ], ), - lockMainListView(index, item) - ], - ); - }, - ), - ) - : _buildNotData(), - ), + ), + lockMainListView(index, item) + ], + ); + }, + ), + ) + : _buildNotData(), + ), ), ], ), @@ -157,13 +161,14 @@ class _VideoLogPageState extends State { // logic.clearDownloads(); }); }, - child: Obx(() => Text('云存'.tr, - style: state.isNavLocal.value == true - ? TextStyle( + child: Obx(() => + Text('云存'.tr, + style: state.isNavLocal.value == true + ? TextStyle( color: Colors.grey, fontSize: 26.sp, fontWeight: FontWeight.w600) - : TextStyle( + : TextStyle( color: Colors.white, fontSize: 28.sp, fontWeight: FontWeight.w600)))), @@ -175,18 +180,19 @@ class _VideoLogPageState extends State { }); }, child: Obx( - () => Text( - '已下载'.tr, - style: state.isNavLocal.value == true - ? TextStyle( + () => + Text( + '已下载'.tr, + style: state.isNavLocal.value == true + ? TextStyle( color: Colors.white, fontSize: 28.sp, fontWeight: FontWeight.w600) - : TextStyle( + : TextStyle( color: Colors.grey, fontSize: 26.sp, fontWeight: FontWeight.w600), - ), + ), ), ), ], @@ -197,41 +203,120 @@ class _VideoLogPageState extends State { // 云存顶部视频 Widget vipTip() { return GestureDetector( - onTap: () { - Get.toNamed(Routers.valueAddedServicesHighFunctionPage); + onTap: () async { + await logic.getWebPlayUrl(); + // Get.toNamed(Routers.valueAddedCloudStoragePage); + // Get.toNamed(Routers.valueAddedServicesHighFunctionPage); }, child: Container( // height: 150.h, margin: EdgeInsets.all(15.w), padding: - EdgeInsets.only(left: 20.w, top: 20.w, bottom: 20.w, right: 10.w), + EdgeInsets.only(left: 20.w, top: 20.w, bottom: 20.w, right: 10.w), decoration: BoxDecoration( color: const Color(0xFFF6F7F8), borderRadius: BorderRadius.circular(20.h)), - child: Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('3天滚动储存'.tr, style: TextStyle(fontSize: 24.sp)), - SizedBox(height: 10.h), - Text("${F.navTitle}${"已为本设备免费提供3大滚动视频储存服务".tr}", - style: TextStyle(fontSize: 22.sp, color: Colors.grey)), - ], - )), - SizedBox(width: 15.w), - Text('去升级'.tr, style: TextStyle(fontSize: 22.sp)), - Image( - width: 40.w, - height: 24.w, - image: const AssetImage('images/icon_right_black.png')) - ], + child: Obx( + () => + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('3天滚动储存'.tr, + style: TextStyle(fontSize: 24.sp)), + SizedBox(height: 10.h), + Text("${F + .navTitle}${"已为本设备免费提供3大滚动视频储存服务" + .tr}", + style: + TextStyle(fontSize: 22.sp, color: Colors + .grey)), + ], + )), + SizedBox(width: 15.w), + Text('去升级'.tr, style: TextStyle(fontSize: 22.sp)), + Image( + width: 40.w, + height: 24.w, + image: const AssetImage( + 'images/icon_right_black.png')) + ], + ), + SizedBox( + height: 16.h, + ), + Text( + '云存服务状态:${_handlerValidityPeriodStatsText()}', + style: TextStyle( + fontSize: 24.sp, + ), + ), + SizedBox( + height: 8.h, + ), + Visibility( + visible: state.validityPeriodInfo.value != null && + state.validityPeriodInfo.value?.status == 1, + child: Text( + '过期时间:${state.validityPeriodInfo.value + ?.validityPeriodEnd}', + style: TextStyle( + fontSize: 24.sp, + ), + ), + ), + SizedBox( + height: 8.h, + ), + Visibility( + visible: state.validityPeriodInfo.value != null && + state.validityPeriodInfo.value?.status == 1, + child: Text( + '滚动存储天数:${state.validityPeriodInfo.value?.rollingStorageDays} 天', + style: TextStyle( + fontSize: 24.sp, + ), + ), + ), + SizedBox( + height: 8.h, + ), + Visibility( + visible: state.validityPeriodInfo.value != null && + state.validityPeriodInfo.value?.status == 1, + child: Text( + '剩余天数:${state.validityPeriodInfo.value + ?.remainingDays} 天', + style: TextStyle( + fontSize: 24.sp, + ), + ), + ), + ], + ), ), ), ); } + _handlerValidityPeriodStatsText() { + if (state.validityPeriodInfo.value == null) { + return ''; + } + if (state.validityPeriodInfo.value?.status == 1) { + return '已开通'.tr; + } else if (state.validityPeriodInfo.value?.status == 2) { + return '已过期'.tr; + } else { + return '未开通'.tr; + } + } + // 本地顶部 Widget localTip() { return GestureDetector( @@ -244,7 +329,7 @@ class _VideoLogPageState extends State { // height: 130.h, margin: EdgeInsets.all(15.w), padding: - EdgeInsets.only(left: 20.w, top: 30.w, bottom: 30.w, right: 10.w), + EdgeInsets.only(left: 20.w, top: 30.w, bottom: 30.w, right: 10.w), decoration: BoxDecoration( color: const Color(0xFFF6F7F8), borderRadius: BorderRadius.circular(20.h)), @@ -252,15 +337,15 @@ class _VideoLogPageState extends State { children: [ Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // SizedBox(height: 20.h), - Text('下载列表'.tr, style: TextStyle(fontSize: 24.sp)), - SizedBox(height: 15.h), - Text('暂无下载内容'.tr, - style: TextStyle(fontSize: 22.sp, color: Colors.grey)), - ], - )), + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // SizedBox(height: 20.h), + Text('下载列表'.tr, style: TextStyle(fontSize: 24.sp)), + SizedBox(height: 15.h), + Text('暂无下载内容'.tr, + style: TextStyle(fontSize: 22.sp, color: Colors.grey)), + ], + )), SizedBox(width: 15.w), // Text("去升级", style: TextStyle(fontSize: 24.sp)), Image( @@ -334,7 +419,7 @@ class _VideoLogPageState extends State { shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - //横轴元素个数 + //横轴元素个数 crossAxisCount: 3, //纵轴间距 mainAxisSpacing: 15.w, @@ -356,7 +441,7 @@ class _VideoLogPageState extends State { shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - //横轴元素个数 + //横轴元素个数 crossAxisCount: 3, //纵轴间距 mainAxisSpacing: 15.w, @@ -384,9 +469,10 @@ class _VideoLogPageState extends State { Navigator.push( context, MaterialPageRoute( - builder: (context) => FullScreenImagePage( - imageUrl: recordData.imagesUrl!, - ), + builder: (context) => + FullScreenImagePage( + imageUrl: recordData.imagesUrl!, + ), ), ); } diff --git a/lib/main/lockDetail/videoLog/videoLog/videoLog_state.dart b/lib/main/lockDetail/videoLog/videoLog/videoLog_state.dart index 8b2a7960..cfa0c232 100755 --- a/lib/main/lockDetail/videoLog/videoLog/videoLog_state.dart +++ b/lib/main/lockDetail/videoLog/videoLog/videoLog_state.dart @@ -1,6 +1,8 @@ import 'dart:typed_data'; import 'package:get/get.dart'; +import 'package:get/get_rx/get_rx.dart'; +import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart'; import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart'; class VideoLogState { @@ -17,4 +19,8 @@ class VideoLogState { getLockId.value = map['lockId']; } } + +// 声明响应式变量 + final validityPeriodInfo = Rx(null); + RxString cloudStorageWebViewUrl = ''.obs; } diff --git a/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_state.dart b/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_state.dart index 45afb135..a936dd64 100755 --- a/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_state.dart +++ b/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_state.dart @@ -16,6 +16,5 @@ class VideoLogDetailState { if (map['videoDataList'] != null) { videoLogList.value = map['videoDataList']; } - print('object'); } } diff --git a/lib/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_entity.dart b/lib/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_entity.dart index 15a4fe3c..b27a5066 100755 --- a/lib/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_entity.dart +++ b/lib/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_entity.dart @@ -32,12 +32,16 @@ class Data { String? vipBuyUrl; String? cloudauthBuyUrl; String? shopList; + String? cloudStorage; + String? valueAddServiceLimitFree; Data( {this.smsBuyUrl, this.emailBuyUrl, this.vipBuyUrl, this.cloudauthBuyUrl, + this.cloudStorage, + this.valueAddServiceLimitFree, this.shopList}); Data.fromJson(Map json) { @@ -46,6 +50,8 @@ class Data { vipBuyUrl = json['vip_buy_url']; cloudauthBuyUrl = json['cloudauth_buy_url']; shopList = json['shopList']; + cloudStorage = json['cloud_storage']; + valueAddServiceLimitFree = json['value_add_service_limit_free']; } Map toJson() { @@ -55,6 +61,8 @@ class Data { data['vip_buy_url'] = vipBuyUrl; data['cloudauth_buy_url'] = cloudauthBuyUrl; data['shopList'] = shopList; + data['cloud_storage'] = cloudStorage; + data['value_add_service_limit_free'] = valueAddServiceLimitFree; return data; } } diff --git a/lib/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_logic.dart b/lib/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_logic.dart index ab7d83f8..1b43d893 100755 --- a/lib/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_logic.dart +++ b/lib/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_logic.dart @@ -40,6 +40,9 @@ class AdvancedFeaturesWebLogic extends BaseGetXController { } else if (state.webBuyType.value == XSConstantMacro.webBuyTypeShop) { state.webBuyUrl.value = entity.data!.shopList!; state.webBuyTitle.value = '商城购买'.tr; + }else if (state.webBuyType.value == XSConstantMacro.webBuyTypeCloudStorage) { + state.webBuyUrl.value = entity.data!.cloudStorage!; + state.webBuyTitle.value = '云存购买'.tr; } state.webBuyView.setNavigationDelegate( diff --git a/lib/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_state.dart b/lib/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_state.dart index c478181a..86b95a3e 100755 --- a/lib/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_state.dart +++ b/lib/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_state.dart @@ -19,6 +19,8 @@ class AdvancedFeaturesWebState { webBuyTitle.value = '邮件购买'.tr; } else if (webBuyType.value == XSConstantMacro.webBuyTypeShop) { webBuyTitle.value = '商城购买'.tr; + }else if (webBuyType.value == XSConstantMacro.webBuyTypeCloudStorage) { + webBuyTitle.value = '云存购买'.tr; } } } diff --git a/lib/mine/valueAddedServices/cloudStorage/cloud_storage_logic.dart b/lib/mine/valueAddedServices/cloudStorage/cloud_storage_logic.dart new file mode 100644 index 00000000..0f37573e --- /dev/null +++ b/lib/mine/valueAddedServices/cloudStorage/cloud_storage_logic.dart @@ -0,0 +1,6 @@ +import 'package:star_lock/mine/valueAddedServices/cloudStorage/cloud_storage_state.dart'; +import 'package:star_lock/tools/baseGetXController.dart'; + +class CloudStorageLogic extends BaseGetXController { + CloudStorageState state = CloudStorageState(); +} diff --git a/lib/mine/valueAddedServices/cloudStorage/cloud_storage_page.dart b/lib/mine/valueAddedServices/cloudStorage/cloud_storage_page.dart new file mode 100644 index 00000000..0ed05870 --- /dev/null +++ b/lib/mine/valueAddedServices/cloudStorage/cloud_storage_page.dart @@ -0,0 +1,150 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.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/mine/valueAddedServices/cloudStorage/cloud_storage_logic.dart'; +import 'package:star_lock/mine/valueAddedServices/cloudStorage/cloud_storage_state.dart'; +import 'package:star_lock/tools/titleAppBar.dart'; + +class CloudStoragePage extends StatefulWidget { + const CloudStoragePage(); + + @override + State createState() => _CloudStoragePageState(); +} + +class _CloudStoragePageState extends State { + final CloudStorageLogic logic = Get.put(CloudStorageLogic()); + final CloudStorageState state = Get.find().state; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: TitleAppBar( + barTitle: '云存储购买'.tr, + haveBack: true, + iconColor: Colors.black, + titleColor: Colors.black, + backgroundColor: Colors.white, + ), + body: SafeArea( + child: _buildBody(), + ), + ); + } + + Widget _buildBody() { + return Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.center, + colors: [Color(0xFFC5F0E7), Color(0xFFF7F7F7)], + ), + ), + child: Column( + children: [ + // 购买套餐选项卡 + _buildPurchasePackage() + ], + ), + ); + } + + Widget _buildPurchasePackage() { + return Container( + width: 1.sw, + margin: EdgeInsets.symmetric( + vertical: 12.h, + horizontal: 14.w, + ), + decoration: BoxDecoration( + color: const Color(0xFFF7F7F7), + borderRadius: BorderRadiusDirectional.all( + Radius.circular(16.r), + ), + ), + child: Column( + children: [ + _buildTabs(), + _buildTabContent(), + ], + ), + ); + } + + Widget _buildTabs() { + return Obx( + () => Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: List.generate( + state.tabs.length, + (int index) => _buildTabItem(index), + ), + ), + ); + } + + Widget _buildTabItem(int index) { + return Expanded( + child: GestureDetector( + onTap: () { + state.selectedIndex.value = index; + }, + child: Container( + height: 68.h, + decoration: BoxDecoration( + color: _isSelectTabBgColor(index), + borderRadius: BorderRadiusDirectional.only( + topStart: Radius.circular(16.r), + topEnd: Radius.circular(16.r), + ), + ), + child: Center( + child: Text( + state.tabs[index], + style: _isSelectTabTitle(index), + ), + ), + ), + ), + ); + } + + TextStyle _isSelectTabTitle(int index) { + if (state.selectedIndex.value == index) { + return TextStyle( + color: const Color(0xFF040404), + fontWeight: FontWeight.w600, + fontSize: 28.sp, + ); + } + return TextStyle( + color: const Color(0xFF8F8F8F), + fontSize: 28.sp, + ); + } + + Color _isSelectTabBgColor(int index) { + if (state.selectedIndex.value == index) { + return Colors.white; + } + return const Color(0xFFF7F7F7); + } + + Widget _buildTabContent() { + return Container( + width: 1.sw, + padding: EdgeInsets.symmetric( + vertical: 12.h, + horizontal: 14.w, + ), + decoration: BoxDecoration( + color: Colors.white, + ), + child: Text('asd'), + ); + } +} diff --git a/lib/mine/valueAddedServices/cloudStorage/cloud_storage_state.dart b/lib/mine/valueAddedServices/cloudStorage/cloud_storage_state.dart new file mode 100644 index 00000000..93879f8a --- /dev/null +++ b/lib/mine/valueAddedServices/cloudStorage/cloud_storage_state.dart @@ -0,0 +1,13 @@ +import 'package:get/get.dart'; + +class CloudStorageState { + // 选中的索引 + RxInt selectedIndex = 0.obs; + + // 选项卡标题 + final List tabs = ['7天滚动存储', '30天滚动存储']; + final List> tabContent = [ + {'title': '连续包月', 'price': '1', 'price2': '188', 'discount': '立省188元'}, + {'title': '连续包月', 'price': '1', 'price2': '188', 'discount': '立省188元'} + ]; +} diff --git a/lib/network/api.dart b/lib/network/api.dart index db9ccf33..412af193 100755 --- a/lib/network/api.dart +++ b/lib/network/api.dart @@ -265,6 +265,8 @@ abstract class Api { final String getServiceUserPackageURL = '/v2/service/getUserPackage'; //获取增值服务用户余量包 + final String getValidityPeriodInfoURL = '/passthrough'; + //获取云存储服务信息 final String getlockCloudStorageListURL = '/lockCloudStorage/list'; //获取云存列表 final String deleteLockCloudStorageURL = '/lockCloudStorage/delete'; //删除云存 @@ -298,4 +300,9 @@ abstract class Api { '/SL-A-1.0/peer/nslookup'; // 星图--解析对端信息 final String bindUserStarchartURL = '/userStarchart/bindUserStarchart'; // 绑定星图配置 + final String getPassthroughListURL = '/passthrough'; // 获取语音列表 + final String updateCurrentVoiceTimbre = + '/lockSetting/updateLockSetting'; // 设置语音包 + final String reportBuyRequestURL = + '/service/reportBuyRequest'; // 上报增值服务购买请求 } diff --git a/lib/network/api_provider.dart b/lib/network/api_provider.dart index 01aabb37..0325b302 100755 --- a/lib/network/api_provider.dart +++ b/lib/network/api_provider.dart @@ -2400,6 +2400,22 @@ class ApiProvider extends BaseProvider { 'searchStr': searchStr })); + // 获取云存列表 + Future getValidityPeriodInfo( + int lockId, { + String request_method = 'POST', + String request_uri = '/api/v1/cloudStorage/getStorageServiceInfo', + required Map post_args, + }) => + post( + getValidityPeriodInfoURL.toUrl, + jsonEncode({ + 'lockId': lockId, + 'request_method': request_method, + 'request_uri': request_uri, + 'post_args': post_args, + })); + // 获取云存列表 Future getLockCloudStorageList(int lockId) => post(getlockCloudStorageListURL.toUrl, jsonEncode({'lockId': lockId})); @@ -2773,6 +2789,55 @@ class ApiProvider extends BaseProvider { isShowNetworkErrorMsg: false, isShowErrMsg: false, isUnShowLoading: true); + + /// 获取设备配网信息 + Future getPassthroughList( + String requestMethod, + String requestUri, + Map data, + ) => + post( + getPassthroughListURL.toUrl, + jsonEncode({ + 'request_method': requestMethod, + 'request_uri': requestUri, + 'post_args': data, + }), + isShowNetworkErrorMsg: false, + isShowErrMsg: false, + isUnShowLoading: true); + + /// 设置语音包 + Future settingCurrentVoiceTimbre( + int lockId, + Map data, + ) => + post( + updateCurrentVoiceTimbre.toUrl, + jsonEncode({ + 'lockId': lockId, + 'currentVoiceTimbre': data, + }), + isShowNetworkErrorMsg: false, + isShowErrMsg: false, + isUnShowLoading: true); + + /// 设置语音包 + Future reportBuyRequest( + int lockId, + String type, + ) => + post( + reportBuyRequestURL.toUrl, + jsonEncode({ + 'lockId': lockId, + 'type': type, + }), + isShowNetworkErrorMsg: false, + isShowErrMsg: false, + isUnShowLoading: true); + + } extension ExtensionString on String { diff --git a/lib/network/api_repository.dart b/lib/network/api_repository.dart index 86d3c604..f3e2587a 100755 --- a/lib/network/api_repository.dart +++ b/lib/network/api_repository.dart @@ -13,6 +13,7 @@ import 'package:star_lock/main/lockDetail/electronicKey/sendEmailNotification/se import 'package:star_lock/main/lockDetail/face/addFace/addFace_entity.dart'; import 'package:star_lock/main/lockDetail/fingerprint/fingerprintList/fingerprint_entity.dart'; import 'package:star_lock/main/lockDetail/lockDetail/device_network_info.dart'; +import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart'; import 'package:star_lock/main/lockDetail/lockSet/basicInformation/basicInformation/KeyDetailEntity.dart'; import 'package:star_lock/main/lockDetail/lockSet/lockEscalation/updateLockInfo_entity.dart'; import 'package:star_lock/main/lockDetail/lockSet/lockEscalation/version_entity.dart'; @@ -2435,6 +2436,30 @@ class ApiRepository { return CoerceFingerprintListEntity.fromJson(res.body); } + // 获取云存储服务信息 + Future getValidityPeriodInfo({ + required int lockId, + }) async { + Map post_args = Map.of({'lockId': lockId}); + final res = await apiProvider.getValidityPeriodInfo( + lockId, + post_args: post_args, + ); + return ValidityPeriodResponse.fromJson(res.body); + } + + // 上报增值服务购买请求 + Future uploadReportBuyRequest({ + required int lockId, + String type = 'cloud_storage', + }) async { + final res = await apiProvider.reportBuyRequest( + lockId, + type, + ); + return LoginEntity.fromJson(res.body); + } + // 获取云存列表 Future getLockCloudStorageList({required int lockId}) async { final res = await apiProvider.getLockCloudStorageList(lockId); @@ -2770,4 +2795,30 @@ class ApiRepository { ); return DeviceNetwork.fromJson(res.body); } + + // 获取语音列表 + Future getPassthroughList({ + String requestMethod = 'POST', + String requestUri = '/api/v1/voice/packs', + required Map data, + }) async { + final res = await apiProvider.getPassthroughList( + requestMethod, + requestUri, + data, + ); + return PassthroughListResponse.fromJson(res.body); + } + + // 设置语音 + Future settingCurrentVoiceTimbre({ + required int lockId, + required Map data, + }) async { + final res = await apiProvider.settingCurrentVoiceTimbre( + lockId, + data, + ); + return LoginEntity.fromJson(res.body); + } } diff --git a/lib/talk/starChart/command/message_command.dart b/lib/talk/starChart/command/message_command.dart index 06dcb314..71abb50e 100644 --- a/lib/talk/starChart/command/message_command.dart +++ b/lib/talk/starChart/command/message_command.dart @@ -174,7 +174,10 @@ class MessageCommand { required String ToPeerId, int? MessageId, }) { - final talkReq = TalkReq(); + final talkReq = TalkReq( + callerName: 'app', + callerType: TalkReq_CallerTypeE.App, + ); final payload = talkReq.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, @@ -277,7 +280,6 @@ class MessageCommand { int? SpTotal, int? SpIndex, }) { - final payload = talkData.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, From 2feb1fb2fc28051e09ec74adfc7334c1c55324e4 Mon Sep 17 00:00:00 2001 From: liyi Date: Sat, 12 Jul 2025 15:50:31 +0800 Subject: [PATCH 02/25] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E9=85=8D=E7=BD=91?= =?UTF-8?q?=E5=90=8E=E5=8F=8A=E6=97=B6=E6=9B=B4=E6=96=B0=E9=94=81=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../configuringWifi_logic.dart | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart b/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart index 6f0a4570..6b3451fe 100755 --- a/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart +++ b/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart @@ -161,11 +161,12 @@ class ConfiguringWifiLogic extends BaseGetXController { // 上报服务器 - 注意: sureBtnState 状态将在 updateNetworkInfo 方法中或其回调中完成重置 final info = await updateNetworkInfo( - peerId: peerId, - wifiName: wifiName ?? '', - secretKey: secretKey, - deviceMac: deviceMac ?? '', - networkMac: networkMac ?? ''); + peerId: peerId, + wifiName: wifiName ?? '', + secretKey: secretKey, + deviceMac: deviceMac ?? '', + networkMac: networkMac ?? '', + ); if (info.errorCode!.codeIsSuccessful) { // 设置锁的peerID StartChartManage().lockNetworkInfo = DeviceNetworkInfo( @@ -175,6 +176,11 @@ class ConfiguringWifiLogic extends BaseGetXController { peerId: peerId, ); + state.lockSetInfoData.value?.lockBasicInfo?.networkInfo?.peerId = + peerId; + state.lockSetInfoData.value?.lockBasicInfo?.networkInfo?.wifiName = + wifiName; + /// 配网成功后,赋值锁的peerId StartChartManage().lockPeerId = peerId; @@ -189,7 +195,9 @@ class ConfiguringWifiLogic extends BaseGetXController { Get.offAllNamed(Routers.starLockMain); } eventBus.fire(SuccessfulDistributionNetwork()); - eventBus.fire(RefreshLockListInfoDataEvent(clearScanDevices: true,isUnShowLoading: true)); + eventBus.fire(RefreshLockListInfoDataEvent( + clearScanDevices: true, isUnShowLoading: true)); + eventBus.fire(RefreshLockDetailInfoDataEvent()); }); // 获取锁设置 @@ -589,7 +597,6 @@ class ConfiguringWifiLogic extends BaseGetXController { recordType: recordType, records: records, isUnShowLoading: true); - if (entity.errorCode!.codeIsSuccessful) { eventBus .fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value)); From c221e2cbdfce1f7075fbaf5c11d848693c5fb13d Mon Sep 17 00:00:00 2001 From: liyi Date: Sat, 12 Jul 2025 15:51:05 +0800 Subject: [PATCH 03/25] =?UTF-8?q?fix:=E6=8E=A8=E5=87=BA=E5=AF=B9=E8=AE=B2?= =?UTF-8?q?=E9=A1=B5=E6=97=B6=E5=81=9C=E6=AD=A2=E5=8F=91=E9=80=81=E6=9C=9F?= =?UTF-8?q?=E6=9C=9B=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../starChart/views/native/talk_view_native_decode_logic.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/talk/starChart/views/native/talk_view_native_decode_logic.dart b/lib/talk/starChart/views/native/talk_view_native_decode_logic.dart index 17651ddf..b58ebe56 100644 --- a/lib/talk/starChart/views/native/talk_view_native_decode_logic.dart +++ b/lib/talk/starChart/views/native/talk_view_native_decode_logic.dart @@ -630,6 +630,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { // 重置期望数据 StartChartManage().reSetDefaultTalkExpect(); + StartChartManage().stopTalkExpectMessageTimer(); VideoDecodePlugin.releaseDecoder(); // 取消批处理定时器 From e2dc776fd1b25b48e5549139bae2cd700da5fa9b Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 15 Jul 2025 15:07:32 +0800 Subject: [PATCH 04/25] =?UTF-8?q?fix:=E8=AE=BE=E7=BD=AE=E8=AF=AD=E8=A8=80?= =?UTF-8?q?=E5=8C=85=E4=B9=8B=E5=90=8E=E5=90=8C=E6=AD=A5=E9=94=81=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../speech_language_settings_logic.dart | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart index a42f4776..081e3b32 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart @@ -25,6 +25,7 @@ import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/tools/baseGetXController.dart'; import 'package:http/http.dart' as http; import 'package:star_lock/tools/commonDataManage.dart'; +import 'package:star_lock/tools/eventBusEventManage.dart'; import 'package:star_lock/tools/storage.dart'; class SpeechLanguageSettingsLogic extends BaseGetXController { @@ -58,7 +59,12 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { lockId: state.lockSetInfoData.value.lockId!, ); if (entity.errorCode!.codeIsSuccessful) { - showSuccess('设置成功'.tr); + showSuccess('设置成功'.tr, something: () { + state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang=item.lang; + state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre=timbre.timbre; + eventBus + .fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value)); + }); } dismissEasyLoading(); } From 30cb3a7ac37c48c29e59d05c613e54de68415b77 Mon Sep 17 00:00:00 2001 From: liyi Date: Wed, 16 Jul 2025 18:01:07 +0800 Subject: [PATCH 05/25] =?UTF-8?q?fix:=E6=81=A2=E5=A4=8D=E5=AF=B9=E8=AE=B2?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E6=B6=88=E6=81=AFpayload=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/talk/starChart/command/message_command.dart | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/talk/starChart/command/message_command.dart b/lib/talk/starChart/command/message_command.dart index 71abb50e..25e3eb18 100644 --- a/lib/talk/starChart/command/message_command.dart +++ b/lib/talk/starChart/command/message_command.dart @@ -174,10 +174,7 @@ class MessageCommand { required String ToPeerId, int? MessageId, }) { - final talkReq = TalkReq( - callerName: 'app', - callerType: TalkReq_CallerTypeE.App, - ); + final talkReq = TalkReq(); final payload = talkReq.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, From ccad385a805bfb5004d9446bee8bb1cefb6cea46 Mon Sep 17 00:00:00 2001 From: liyi Date: Thu, 17 Jul 2025 14:56:56 +0800 Subject: [PATCH 06/25] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E8=AF=AD=E9=9F=B3?= =?UTF-8?q?=E5=8C=85=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../speech_language_settings_page.dart | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart index cbb030bd..646f7853 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:star_lock/app_settings/app_colors.dart'; @@ -51,15 +52,10 @@ class _SpeechLanguageSettingsPageState Widget _buildBody() { return Obx( - () => Stack( - children: [ - Column( - children: [ - ..._buildList(), - ], - ), - // 移除进度条显示 - ], + () => SingleChildScrollView( + child: Column( + children: _buildList(), + ), ), ); } @@ -84,7 +80,7 @@ class _SpeechLanguageSettingsPageState ), ), onExpansionChanged: (bool expanded) {}, - initiallyExpanded: true, + initiallyExpanded: false, backgroundColor: Colors.white, collapsedBackgroundColor: Colors.white, expandedCrossAxisAlignment: CrossAxisAlignment.center, @@ -124,4 +120,14 @@ class _SpeechLanguageSettingsPageState ), ); } + + + @override + void dispose() { + // TODO: implement dispose + super.dispose(); + if (EasyLoading.isShow) { + EasyLoading.dismiss(animation: true); + } + } } From b2952b3c726ccbe08d7e9b36bf7bbb71b8b3f4cc Mon Sep 17 00:00:00 2001 From: liyi Date: Fri, 18 Jul 2025 10:40:41 +0800 Subject: [PATCH 07/25] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E9=94=81=E6=97=B6=E9=85=8D=E7=BD=AE=E8=AF=AD=E9=9F=B3=E5=8C=85?= =?UTF-8?q?=E7=9A=84=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/appRouters.dart | 6 + .../lockSet/lockSet/lockSet_logic.dart | 55 +++ .../speech_language_settings_logic.dart | 21 +- .../speech_language_settings_page.dart | 9 +- .../lock_voice_setting_logic.dart | 332 ++++++++++++++++++ .../lock_voice_setting_page.dart | 150 ++++++++ .../lock_voice_setting_state.dart | 47 +++ lib/mine/addLock/saveLock/saveLock_logic.dart | 14 +- lib/tools/storage.dart | 1 + 9 files changed, 624 insertions(+), 11 deletions(-) create mode 100644 lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart create mode 100644 lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart create mode 100644 lib/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart diff --git a/lib/appRouters.dart b/lib/appRouters.dart index f0acd63c..1bba3087 100755 --- a/lib/appRouters.dart +++ b/lib/appRouters.dart @@ -42,6 +42,7 @@ import 'package:star_lock/main/lockDetail/palm/palmList/palmList_page.dart'; import 'package:star_lock/main/lockDetail/passwordKey/passwordKeyDetailChangeDate/passwordKeyDetailChangeDate_page.dart'; 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/addLock/lock_voice_setting/lock_voice_setting_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'; @@ -527,6 +528,8 @@ abstract class Routers { '/imageTransmissionView'; //星图对讲页面(图传) static const String permissionGuidancePage = '/permissionGuidancePage'; // 锁屏权限通知引导页面 + static const String lockVoiceSettingPage = + '/lockVoiceSetting'; // 锁屏权限通知引导页面 } abstract class AppRouters { @@ -1214,6 +1217,9 @@ abstract class AppRouters { GetPage( name: Routers.permissionGuidancePage, page: () => PermissionGuidancePage()), + GetPage( + name: Routers.lockVoiceSettingPage, + page: () => LockVoiceSetting()), // 插件播放页面 // GetPage(name: Routers.h264View, page: () => H264WebView()), // webview播放页面 ]; diff --git a/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart b/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart index 7d6b4a65..e27e1b4d 100755 --- a/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart +++ b/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart @@ -4,6 +4,7 @@ import 'package:flutter/scheduler.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:get/get.dart'; import 'package:star_lock/apm/apm_helper.dart'; +import 'package:star_lock/blue/io_protocol/io_getDeviceModel.dart'; import 'package:star_lock/login/login/entity/LoginEntity.dart'; import 'package:star_lock/main/lockMian/entity/lockListInfo_entity.dart'; @@ -66,6 +67,11 @@ class LockSetLogic extends BaseGetXController { (state.ifCurrentScreen.value == true)) { _replyUpdataLockSetReply(reply); } + + if (reply is GetDeviceModelReply) { + // 获取设备型号 + _handlerDeviceModelReply(reply); + } }); } @@ -728,6 +734,7 @@ class LockSetLogic extends BaseGetXController { getUpdataLockSet(); _initReplySubscription(); + sendGetDeviceModelBleMessage(); // _scanListDiscoveredDeviceSubscriptionAction(); } @@ -737,4 +744,52 @@ class LockSetLogic extends BaseGetXController { _passCurrentLockInformationEvent!.cancel(); // _scanListDiscoveredDeviceSubscription.cancel(); } + + // 发送获取型号蓝牙命令 + sendGetDeviceModelBleMessage() { + showEasyLoading(); + showBlueConnetctToastTimer(action: () { + dismissEasyLoading(); + }); + BlueManage().blueSendData(BlueManage().connectDeviceName, + (BluetoothConnectionState deviceConnectionState) async { + if (deviceConnectionState == BluetoothConnectionState.connected) { + BlueManage().writeCharacteristicWithResponse( + GetDeviceModelCommand( + lockID: BlueManage().connectDeviceName, + ).packageData(), + ); + } else if (deviceConnectionState == + BluetoothConnectionState.disconnected) { + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + showBlueConnetctToast(); + } + }); + } + + void _handlerDeviceModelReply(GetDeviceModelReply reply) async { + final int status = reply.data[2]; + switch (status) { + case 0x00: + //成功 + cancelBlueConnetctToastTimer(); + // 3. 解析DeviceModel(40字节,索引3~42) + int startIndex = 3; + int length = 40; + List deviceModelBytes = + reply.data.sublist(startIndex, startIndex + length); + + String rawData = String.fromCharCodes(deviceModelBytes); + int firstNullIndex = rawData.indexOf('\u0000'); + String deviceModelValue = rawData.substring(0, firstNullIndex); + print(deviceModelValue); // 输出: 2403 + print('获取到 DeviceModel (原始): $deviceModelValue'); + await Storage.setString(deviceModel, deviceModelValue); + break; + default: + showToast('获取设备型号失败'.tr); + break; + } + } } diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart index 081e3b32..d96a065a 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart @@ -60,16 +60,23 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { ); if (entity.errorCode!.codeIsSuccessful) { showSuccess('设置成功'.tr, something: () { - state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang=item.lang; - state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre=timbre.timbre; - eventBus - .fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value)); + state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre + ?.lang = item.lang; + state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre + ?.timbre = timbre.timbre; + eventBus.fire( + PassCurrentLockInformationEvent(state.lockSetInfoData.value)); }); } dismissEasyLoading(); } }); - await sendGetDeviceModelBleMessage(); + state.deviceModel.value = await Storage.getString(deviceModel) ?? ''; + debugPrint('设备型号:${state.deviceModel.value}'); + if (state.deviceModel.value != null) { + await initList(); + } + // await sendGetDeviceModelBleMessage(); } @override @@ -146,6 +153,10 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { } sendFileToDevice(Uint8List data, List token) { + showEasyLoading(); + showBlueConnetctToastTimer(action: () { + dismissEasyLoading(); + }); BlueManage().blueSendData(BlueManage().connectDeviceName, (BluetoothConnectionState deviceConnectionState) async { if (deviceConnectionState == BluetoothConnectionState.connected) { diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart index 646f7853..86149fd9 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart @@ -7,6 +7,7 @@ import 'package:star_lock/app_settings/app_colors.dart'; import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart'; import 'package:star_lock/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart'; import 'package:star_lock/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart'; +import 'package:star_lock/tools/EasyRefreshTool.dart'; import 'package:star_lock/tools/titleAppBar.dart'; class SpeechLanguageSettingsPage extends StatefulWidget { @@ -46,7 +47,12 @@ class _SpeechLanguageSettingsPageState ), ], ), - body: _buildBody(), + body: EasyRefreshTool( + child: _buildBody(), + onRefresh: () { + logic.sendGetDeviceModelBleMessage(); + }, + ), ); } @@ -121,7 +127,6 @@ class _SpeechLanguageSettingsPageState ); } - @override void dispose() { // TODO: implement dispose diff --git a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart new file mode 100644 index 00000000..16e4fdb1 --- /dev/null +++ b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart @@ -0,0 +1,332 @@ +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:crypto/crypto.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_blue_plus/flutter_blue_plus.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:get/get.dart'; +import 'package:star_lock/blue/blue_manage.dart'; +import 'package:star_lock/blue/io_protocol/io_getDeviceModel.dart'; +import 'package:star_lock/blue/io_protocol/io_voicePackageConfigure.dart'; +import 'package:star_lock/blue/io_protocol/io_voicePackageConfigureProcess.dart'; +import 'package:star_lock/blue/io_reply.dart'; +import 'package:star_lock/blue/io_tool/io_tool.dart'; +import 'package:star_lock/blue/io_tool/manager_event_bus.dart'; +import 'package:star_lock/login/login/entity/LoginEntity.dart'; +import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart'; +import 'package:star_lock/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart'; +import 'package:star_lock/network/api_repository.dart'; +import 'package:star_lock/tools/baseGetXController.dart'; +import 'package:star_lock/tools/eventBusEventManage.dart'; +import 'package:star_lock/tools/storage.dart'; +import 'package:http/http.dart' as http; + +class LockVoiceSettingLogic extends BaseGetXController { + LockVoiceSettingState state = LockVoiceSettingState(); + StreamSubscription? _replySubscription; + + @override + void onInit() async { + super.onInit(); + _replySubscription = + EventBusManager().eventBus!.on().listen((Reply reply) async { + if (reply is GetDeviceModelReply) { + // 获取设备型号 + _handlerDeviceModelReply(reply); + } + if (reply is VoicePackageConfigureReply) { + // 语言包配置开始 + _handlerStartVoicePackageConfigure(reply); + } else if (reply is VoicePackageConfigureProcessReply) { + _handlerVoicePackageConfigureProcess(reply); + } else if (reply is VoicePackageConfigureConfirmationReply) { + final PassthroughItem item = + state.languages[state.selectPassthroughListIndex.value]; + final timbre = item.timbres[state.selectLanguageIndex.value]; + final LoginEntity entity = + await ApiRepository.to.settingCurrentVoiceTimbre( + data: { + 'lang': item.lang, + 'timbre': timbre.timbre, + }, + lockId: state.lockSetInfoData.value.lockId!, + ); + if (entity.errorCode!.codeIsSuccessful) { + showSuccess('设置成功'.tr, something: () { + state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre + ?.lang = item.lang; + state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre + ?.timbre = timbre.timbre; + eventBus.fire( + PassCurrentLockInformationEvent(state.lockSetInfoData.value)); + }); + } + dismissEasyLoading(); + } + }); + await sendGetDeviceModelBleMessage(); + } + + void saveSpeechLanguageSettings() async { + // 如果已经开始发送中则不处理保存点击事件 + if (state.progress.value > 0) { + return; + } + final oldTimbre = + state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre; + final oldLang = + state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang; + + EasyLoading.showProgress(state.progress.value, status: '正在发送数据'); + final PassthroughItem item = + state.languages[state.selectPassthroughListIndex.value]; + final timbre = item.timbres[state.selectLanguageIndex.value]; + debugPrint('选中的语音是:${timbre}'); + if ((oldLang != null && oldLang == item.lang) && + (oldTimbre != null && oldTimbre == timbre.timbre)) { + showToast('已设置为当前选择的语音包'.tr); + } + await downloadFile(timbre.timbrePackUrl); + } + + //下载语音包 + Future downloadFile(String url) async { + final http.Response response = await http.get(Uri.parse(url)); + if (response.statusCode == 200) { + state.data = response.bodyBytes; + sendFileToDevice(response.bodyBytes, [0, 0, 0, 0]); + } + } + + sendFileToDevice(Uint8List data, List token) { + showEasyLoading(); + showBlueConnetctToastTimer(action: () { + dismissEasyLoading(); + }); + BlueManage().blueSendData(BlueManage().connectDeviceName, + (BluetoothConnectionState deviceConnectionState) async { + if (deviceConnectionState == BluetoothConnectionState.connected) { + final List? privateKey = + await Storage.getStringList(saveBluePrivateKey); + final List getPrivateKeyList = + changeStringListToIntList(privateKey!); + final List? signKey = + await Storage.getStringList(saveBlueSignKey); + final List signKeyDataList = changeStringListToIntList(signKey!); + final String uid = await Storage.getUid() ?? ''; + final String md5Str = md5.convert(data).toString().toUpperCase(); + BlueManage().writeCharacteristicWithResponse( + VoicePackageConfigure( + lockID: BlueManage().connectDeviceName, + userID: uid, + keyID: BlueManage().connectDeviceName, + platform: 0, + product: 0, + fwSize: data.length, + fwMD5: md5Str, + needAuthor: 1, + token: token, + signKey: signKeyDataList, + privateKey: getPrivateKeyList) + .packageData(), + ); + } else if (deviceConnectionState == + BluetoothConnectionState.disconnected) {} + }); + } + + void _handlerVoicePackageConfigureProcess( + VoicePackageConfigureProcessReply reply) { + final int status = reply.data[2]; + switch (status) { + case 0x00: + cancelBlueConnetctToastTimer(); + state.voiceSubcontractingIndex++; + _sendNextPackage(); + break; + default: + showToast('发送分包数据不成功'.tr); + break; + } + } + + // 开始配置语音包 + void _handlerStartVoicePackageConfigure( + VoicePackageConfigureReply reply) async { + final int status = reply.data[6]; + switch (status) { + case 0x00: + //成功 + cancelBlueConnetctToastTimer(); + + _startSendLanguageFile(); + + break; + case 0x06: + //无权限 + final List token = reply.data.sublist(2, 6); + print('收到token:$token'); + if (state.data != null) { + sendFileToDevice(state.data!, token); + } + break; + default: + showToast('获取设备型号失败'.tr); + break; + } + } + + void _handlerDeviceModelReply(GetDeviceModelReply reply) async { + final int status = reply.data[2]; + switch (status) { + case 0x00: + //成功 + cancelBlueConnetctToastTimer(); + // 3. 解析DeviceModel(40字节,索引3~42) + int startIndex = 3; + int length = 40; + List deviceModelBytes = + reply.data.sublist(startIndex, startIndex + length); + + String rawData = String.fromCharCodes(deviceModelBytes); + int firstNullIndex = rawData.indexOf('\u0000'); + String deviceModel = rawData.substring(0, firstNullIndex); + print('获取到 DeviceModel (原始): $deviceModel'); + state.deviceModel.value = deviceModel; + await initList(); + break; + default: + showToast('获取设备型号失败'.tr); + break; + } + } + + /// 获取列表 + initList() async { + showEasyLoading(); + try { + final PassthroughListResponse entity = await ApiRepository.to + .getPassthroughList(data: {'deviceType': state.deviceModel.value}); + if (entity.errorCode!.codeIsSuccessful) { + state.languages.value = entity.data!!; + final oldTimbre = state + .lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre; + final oldLang = state + .lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang; + + for (int index = 0; index < state.languages.value.length; index++) { + final element = state.languages.value[index]; + final timbres = element.timbres; + for (int i = 0; i < timbres.length; i++) { + final timbre = timbres[i].timbre; + if ((oldLang != null && oldLang == element.lang) && + (oldTimbre != null && oldTimbre == timbre)) { + state.selectPassthroughListIndex.value = index; + state.selectLanguageIndex.value = i; + } + } + } + } + } catch (e) { + debugPrint('获取语音包出现错误:$e'); + } finally { + dismissEasyLoading(); + } + } + + // 发送获取型号蓝牙命令 + sendGetDeviceModelBleMessage() { + showEasyLoading(); + showBlueConnetctToastTimer(action: () { + dismissEasyLoading(); + }); + BlueManage().blueSendData( + BlueManage().connectDeviceName, + (BluetoothConnectionState deviceConnectionState) async { + if (deviceConnectionState == BluetoothConnectionState.connected) { + BlueManage().writeCharacteristicWithResponse( + GetDeviceModelCommand( + lockID: BlueManage().connectDeviceName, + ).packageData(), + ); + } else if (deviceConnectionState == + BluetoothConnectionState.disconnected) { + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + showBlueConnetctToast(); + } + }, + ); + } + + void _startSendLanguageFile() { + if (state.data == null) return; + state.voiceSubcontractingIndex = 0; + state.voiceSubcontractingCount = + (state.data!.length + state.voiceSubcontractingSize - 1) ~/ + state.voiceSubcontractingSize; + state.progress.value = 0.0; // 开始前重置进度 + _sendNextPackage(); + } + + void _sendNextPackage() { + if (state.voiceSubcontractingIndex >= state.voiceSubcontractingCount) { + print('所有分包已发送完成'); + state.progress.value = 1.0; // 发送完成 + // 可在此处通知UI或做后续处理 + return; + } + + int start = state.voiceSubcontractingIndex * state.voiceSubcontractingSize; + int end = start + state.voiceSubcontractingSize; + if (end > state.data!.length) end = state.data!.length; + Uint8List packageData = state.data!.sublist(start, end); + + // 更新分包进度 + state.progress.value = + (state.voiceSubcontractingIndex + 1) / state.voiceSubcontractingCount; + EasyLoading.showProgress(state.progress.value, + status: '正在发送数据 ${(state.progress.value * 100).toStringAsFixed(0)}%'); + _sendLanguageFileBleMessage( + index: state.voiceSubcontractingIndex, + data: packageData, + ); + } + + _sendLanguageFileBleMessage({required int index, required Uint8List data}) { + BlueManage().blueSendData(BlueManage().connectDeviceName, + (BluetoothConnectionState deviceConnectionState) async { + if (deviceConnectionState == BluetoothConnectionState.connected) { + BlueManage().writeCharacteristicWithResponse( + VoicePackageConfigureProcess( + index: index, + size: data.length, + data: data, + ).packageData(), + ); + } else if (deviceConnectionState == + BluetoothConnectionState.disconnected) { + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + showBlueConnetctToast(); + } + }); + } + + @override + void dispose() async { + super.dispose(); + await _replySubscription?.cancel(); + _replySubscription = null; + await BlueManage().disconnect(); + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + EasyLoading.dismiss(); + // 清理分包相关状态 + state.progress.value = 0.0; + state.voiceSubcontractingIndex = 0; + state.voiceSubcontractingCount = 0; + state.data = null; + } +} diff --git a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart new file mode 100644 index 00000000..39facc57 --- /dev/null +++ b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart @@ -0,0 +1,150 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:get/get_utils/get_utils.dart'; +import 'package:star_lock/appRouters.dart'; +import 'package:star_lock/app_settings/app_colors.dart'; +import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart'; +import 'package:star_lock/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart'; +import 'package:star_lock/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart'; +import 'package:star_lock/tools/EasyRefreshTool.dart'; +import 'package:star_lock/tools/titleAppBar.dart'; + +class LockVoiceSetting extends StatefulWidget { + const LockVoiceSetting(); + + @override + State createState() => _LockVoiceSettingState(); +} + +class _LockVoiceSettingState extends State { + final LockVoiceSettingLogic logic = Get.put(LockVoiceSettingLogic()); + final LockVoiceSettingState state = Get.find().state; + + @override + Widget build(BuildContext context) { + return EasyRefreshTool( + onRefresh: () { + logic.sendGetDeviceModelBleMessage(); + }, + child: Scaffold( + backgroundColor: AppColors.mainBackgroundColor, + appBar: TitleAppBar( + barTitle: '锁语音包设置'.tr, + haveBack: false, + haveOtherLeftWidget: true, + leftWidget: TextButton( + onPressed: () { + Get.offAllNamed(Routers.starLockMain); + }, + child: Text( + '跳过', + style: TextStyle( + color: Colors.white, + fontSize: 24.sp, + fontWeight: FontWeight.w500, + ), + ), + ), + backgroundColor: AppColors.mainColor, + actionsList: [ + TextButton( + onPressed: logic.saveSpeechLanguageSettings, + child: Text( + '保存'.tr, + style: TextStyle( + color: Colors.white, + fontSize: 24.sp, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + body: _buildBody(), + ), + ); + } + + Widget _buildBody() { + return Obx( + () => SingleChildScrollView( + child: Column( + children: _buildList(), + ), + ), + ); + } + + List _buildList() { + final languages = state.languages; + return List.generate( + languages.length, + (index) => _buildItem(languages[index], index), + ); + } + + _buildItem(PassthroughItem language, int index) { + final timbres = language.timbres; + final isSelected = state.selectPassthroughListIndex == index; + return ExpansionTile( + title: Text( + PassthroughLangHelper.getLangText(language.lang), + style: TextStyle( + fontSize: 24.sp, + fontWeight: isSelected ? FontWeight.bold : null, + ), + ), + onExpansionChanged: (bool expanded) {}, + initiallyExpanded: false, + backgroundColor: Colors.white, + collapsedBackgroundColor: Colors.white, + expandedCrossAxisAlignment: CrossAxisAlignment.center, + expandedAlignment: Alignment.center, + shape: InputBorder.none, + maintainState: true, + // 去除展开状态下的边框 + collapsedShape: InputBorder.none, + // 去除折叠状态下的边框 + childrenPadding: EdgeInsets.only(left: 12.w), + children: List.generate( + timbres.length, + (int languageIndex) => ListTile( + title: Text( + timbres[languageIndex].name, + style: TextStyle( + fontSize: 22.sp, + fontWeight: + state.selectLanguageIndex == languageIndex && isSelected + ? FontWeight.bold + : null, + ), + ), + trailing: state.selectLanguageIndex == languageIndex && isSelected + ? Icon( + Icons.check_circle, + color: AppColors.mainColor, + ) // 仅当选中时显示图标 + : null, // 默认不显示 + onTap: () { + // 更新选中的语音包 + state.selectLanguageIndex.value = languageIndex; + // 更新选中的语言 + state.selectPassthroughListIndex.value = index; + }, // 默认图标, // 右侧的图标 + ), + ), + ); + } + + @override + void dispose() { + // TODO: implement dispose + super.dispose(); + if (EasyLoading.isShow) { + EasyLoading.dismiss(animation: true); + } + } +} diff --git a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart new file mode 100644 index 00000000..e70c6b2a --- /dev/null +++ b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart @@ -0,0 +1,47 @@ +import 'dart:typed_data'; + +import 'package:get/get.dart'; +import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart'; +import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart'; + +class LockVoiceSettingState { + LockVoiceSettingState() { + final map = Get.arguments; + lockSetInfoData.value = map['lockSetInfoData']; + + lockBasicInfo.value = lockSetInfoData.value.lockBasicInfo!; + } + + Rx lockSetInfoData = LockSetInfoData().obs; + Rx lockBasicInfo = LockBasicInfo().obs; + + + + // 选中的语音包列表下标 + RxInt selectPassthroughListIndex = 0.obs; + + // 选中的语音下标 + RxInt selectLanguageIndex = 0.obs; + + final RxList languages = [].obs; + + Map languageSpeechDeviceTypeMapping = {0: '2403'}; + + RxBool otaUpdateIng = false.obs; + RxDouble otaProgress = 0.00.obs; + RxString deviceModel = '2403'.obs; + Uint8List? data; + + // 语音包最大大小 + int voiceSubcontractingSize = 256; + + // 总数据包数量 + int voiceSubcontractingCount = 0; + + // 数据包序列号 + int voiceSubcontractingIndex = 0; + + // 分包发送进度(0.0~1.0) + RxDouble progress = 0.0.obs; + +} diff --git a/lib/mine/addLock/saveLock/saveLock_logic.dart b/lib/mine/addLock/saveLock/saveLock_logic.dart index 6facc933..e5de0c33 100755 --- a/lib/mine/addLock/saveLock/saveLock_logic.dart +++ b/lib/mine/addLock/saveLock/saveLock_logic.dart @@ -486,7 +486,6 @@ class SaveLockLogic extends BaseGetXController { // } void backAction() async { - // BlueManage().disconnect(); // 查询锁设置信息 @@ -502,13 +501,19 @@ class SaveLockLogic extends BaseGetXController { 'lockSetInfoData': state.lockSetInfoData.value, 'pageName': 'saveLock' }); + } else if (state.lockSetInfoData.value.lockFeature?.languageSpeech == 1) { + Get.toNamed(Routers.lockVoiceSettingPage, arguments: { + 'lockSetInfoData': state.lockSetInfoData.value, + 'pageName': 'saveLock' + }); } else { - eventBus.fire(RefreshLockListInfoDataEvent(clearScanDevices: true,isUnShowLoading: true)); + eventBus.fire(RefreshLockListInfoDataEvent( + clearScanDevices: true, isUnShowLoading: true)); Future.delayed(const Duration(seconds: 1), () { // Get.close(state.isFromMap == 1 // ? (CommonDataManage().seletLockType == 0 ? 4 : 5) // : (CommonDataManage().seletLockType == 0 ? 5 : 6)); - Get.until((route) => route.isFirst); + Get.until((route) => route.isFirst); }); //刚刚配对完,需要对开锁页锁死 2 秒 Future.delayed(const Duration(milliseconds: 200), () { @@ -520,7 +525,8 @@ class SaveLockLogic extends BaseGetXController { }); } } else { - eventBus.fire(RefreshLockListInfoDataEvent(clearScanDevices: true,isUnShowLoading: true)); + eventBus.fire(RefreshLockListInfoDataEvent( + clearScanDevices: true, isUnShowLoading: true)); Future.delayed(const Duration(seconds: 1), () { // Get.close(state.isFromMap == 1 // ? (CommonDataManage().seletLockType == 0 ? 4 : 5) diff --git a/lib/tools/storage.dart b/lib/tools/storage.dart index 8f20526a..7918a0f5 100755 --- a/lib/tools/storage.dart +++ b/lib/tools/storage.dart @@ -40,6 +40,7 @@ const String lockNetWorkInfo = 'lockNetWorkInfo'; //锁板配网信息 const String appVersionHistoryUrl = 'appVersionHistoryUrl'; //是否同意隐私协议弹窗 const String voipToken = 'voipToken'; //是否同意隐私协议弹窗 +const String deviceModel = 'deviceModel'; //设备型号 class Storage { factory Storage() => _instance; From 4045adf0b20fe5079a42a25ee5330b9c09ebc863 Mon Sep 17 00:00:00 2001 From: liyi Date: Wed, 23 Jul 2025 09:52:58 +0800 Subject: [PATCH 08/25] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E9=94=81=E6=97=B6=E9=80=89=E6=8B=A9=E8=AF=AD=E9=9F=B3=E5=8C=85?= =?UTF-8?q?=E7=9A=84=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lan/lan_en.json | 3 +- lan/lan_keys.json | 5 +- lan/lan_zh.json | 3 +- .../speech_language_settings_logic.dart | 27 +++- .../speech_language_settings_page.dart | 33 ++++- .../speech_language_settings_state.dart | 4 +- .../lock_voice_setting_logic.dart | 124 ++++++++++++++---- .../lock_voice_setting_page.dart | 2 +- .../selectLockType/selectLockType_page.dart | 33 +++-- 9 files changed, 183 insertions(+), 51 deletions(-) diff --git a/lan/lan_en.json b/lan/lan_en.json index e9cf111d..2e60a8c3 100644 --- a/lan/lan_en.json +++ b/lan/lan_en.json @@ -1159,5 +1159,6 @@ "请确认后再继续": "Please confirm before continuing", "需要相机权限": "Camera permission required", "此功能的开启和关闭只能在锁附近通过手机蓝牙进行": "The activation and deactivation of this feature can only be done through Bluetooth on the phone near the lock", - "网关添加成功": "Gateway added successfully" + "网关添加成功": "Gateway added successfully", + "语音包设置": "Voice packet settings" } diff --git a/lan/lan_keys.json b/lan/lan_keys.json index c289bd0e..9f4edfab 100755 --- a/lan/lan_keys.json +++ b/lan/lan_keys.json @@ -1101,7 +1101,7 @@ "支持的国家": "支持的国家", "支持的国家值": "美国、加拿大、英国、澳大利亚、印度、德国、法国、意大利、西班牙、日本", "操作流程": "操作流程", - "操作流程值":"1 用智能锁APP添加锁和网关\n\n2 在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Alexa \n\n3 在Alexa中添加Skill,并用智能锁APP的账号和密码进行授权。授权成功后就可以发现账号下的设备\n\n4 在Alexa app里找到锁,开启语音开锁的功能,并设置语言密码\n\n5 可以通过Alexa操作锁了", + "操作流程值": "1 用智能锁APP添加锁和网关\n\n2 在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Alexa \n\n3 在Alexa中添加Skill,并用智能锁APP的账号和密码进行授权。授权成功后就可以发现账号下的设备\n\n4 在Alexa app里找到锁,开启语音开锁的功能,并设置语言密码\n\n5 可以通过Alexa操作锁了", "Google Home": "Google Home", "Action name": "Action name", "ScienerSmart": "ScienerSmart", @@ -1164,5 +1164,6 @@ "请确认后再继续": "请确认后再继续", "需要相机权限": "需要相机权限", "此功能的开启和关闭只能在锁附近通过手机蓝牙进行": "此功能的开启和关闭只能在锁附近通过手机蓝牙进行", - "网关添加成功": "网关添加成功" + "网关添加成功": "网关添加成功", + "语音包设置": "语音包设置", } diff --git a/lan/lan_zh.json b/lan/lan_zh.json index c856e8bb..633e2931 100755 --- a/lan/lan_zh.json +++ b/lan/lan_zh.json @@ -1166,5 +1166,6 @@ "请确认后再继续": "请确认后再继续", "需要相机权限": "需要相机权限", "一键登录": "一键登录", - "网关添加成功": "网关添加成功" + "网关添加成功": "网关添加成功", + "语音包设置": "语音包设置" } diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart index d96a065a..921a8ef8 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart @@ -79,10 +79,6 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { // await sendGetDeviceModelBleMessage(); } - @override - void onClose() { - _replySubscription?.cancel(); - } /// 获取列表 initList() async { @@ -185,7 +181,10 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { .packageData(), ); } else if (deviceConnectionState == - BluetoothConnectionState.disconnected) {} + BluetoothConnectionState.disconnected) { + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + } }); } @@ -335,7 +334,6 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { @override void dispose() async { - super.dispose(); await _replySubscription?.cancel(); _replySubscription = null; await BlueManage().disconnect(); @@ -347,5 +345,22 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { state.voiceSubcontractingIndex = 0; state.voiceSubcontractingCount = 0; state.data = null; + super.dispose(); + } + + @override + void onClose() async { + await _replySubscription?.cancel(); + _replySubscription = null; + await BlueManage().disconnect(); + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + EasyLoading.dismiss(); + // 清理分包相关状态 + state.progress.value = 0.0; + state.voiceSubcontractingIndex = 0; + state.voiceSubcontractingCount = 0; + state.data = null; + super.onClose(); } } diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart index 86149fd9..bb5275a8 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart @@ -60,7 +60,38 @@ class _SpeechLanguageSettingsPageState return Obx( () => SingleChildScrollView( child: Column( - children: _buildList(), + children: [ + // Container( + // width: 1.sw, + // decoration: BoxDecoration(color: Colors.white), + // child: Column( + // children: [ + // RadioListTile( + // title: Text("男声".tr), + // value: 1, + // groupValue: state.selectedValue.value, + // onChanged: (value) { + // state.selectedValue.value = int.parse(value.toString()); + // }, + // ), + // RadioListTile( + // title: Text("女声".tr), + // value: 2, + // groupValue: state.selectedValue.value, + // onChanged: (value) { + // state.selectedValue.value = int.parse(value.toString()); + // }, + // ) + // ], + // ), + // ), + SizedBox( + height: 8.h, + ), + Column( + children: _buildList(), + ), + ], ), ), ); diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart index 8bcaa4e7..02079884 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart @@ -40,5 +40,7 @@ class SpeechLanguageSettingsState { // 分包发送进度(0.0~1.0) RxDouble progress = 0.0.obs; - + RxInt selectedValue = 1.obs; + + } diff --git a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart index 16e4fdb1..fd30419f 100644 --- a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart +++ b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart @@ -2,10 +2,13 @@ import 'dart:async'; import 'dart:typed_data'; import 'package:crypto/crypto.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:get/get.dart'; +import 'package:star_lock/appRouters.dart'; +import 'package:star_lock/app_settings/app_colors.dart'; import 'package:star_lock/blue/blue_manage.dart'; import 'package:star_lock/blue/io_protocol/io_getDeviceModel.dart'; import 'package:star_lock/blue/io_protocol/io_voicePackageConfigure.dart'; @@ -19,12 +22,14 @@ import 'package:star_lock/mine/addLock/lock_voice_setting/lock_voice_setting_sta import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/tools/baseGetXController.dart'; import 'package:star_lock/tools/eventBusEventManage.dart'; +import 'package:star_lock/tools/showTipView.dart'; import 'package:star_lock/tools/storage.dart'; import 'package:http/http.dart' as http; class LockVoiceSettingLogic extends BaseGetXController { LockVoiceSettingState state = LockVoiceSettingState(); StreamSubscription? _replySubscription; + bool _isThrottled = false; @override void onInit() async { @@ -41,33 +46,81 @@ class LockVoiceSettingLogic extends BaseGetXController { } else if (reply is VoicePackageConfigureProcessReply) { _handlerVoicePackageConfigureProcess(reply); } else if (reply is VoicePackageConfigureConfirmationReply) { - final PassthroughItem item = - state.languages[state.selectPassthroughListIndex.value]; - final timbre = item.timbres[state.selectLanguageIndex.value]; - final LoginEntity entity = - await ApiRepository.to.settingCurrentVoiceTimbre( - data: { - 'lang': item.lang, - 'timbre': timbre.timbre, - }, - lockId: state.lockSetInfoData.value.lockId!, - ); - if (entity.errorCode!.codeIsSuccessful) { - showSuccess('设置成功'.tr, something: () { - state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre - ?.lang = item.lang; - state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre - ?.timbre = timbre.timbre; - eventBus.fire( - PassCurrentLockInformationEvent(state.lockSetInfoData.value)); - }); - } - dismissEasyLoading(); + handleVoiceConfigureThrottled(reply); } }); await sendGetDeviceModelBleMessage(); } + void handleVoiceConfigureThrottled( + VoicePackageConfigureConfirmationReply reply, + ) { + if (_isThrottled) return; + + _isThrottled = true; + + // 执行你的逻辑 + _executeLogic(reply); + + // 设置节流时间(比如 1 秒) + Future.delayed(Duration(seconds: 1), () { + _isThrottled = false; + }); + } + + Future _executeLogic( + VoicePackageConfigureConfirmationReply reply) async { + final PassthroughItem item = + state.languages[state.selectPassthroughListIndex.value]; + final timbre = item.timbres[state.selectLanguageIndex.value]; + final LoginEntity entity = await ApiRepository.to.settingCurrentVoiceTimbre( + data: { + 'lang': item.lang, + 'timbre': timbre.timbre, + }, + lockId: state.lockSetInfoData.value.lockId!, + ); + if (entity.errorCode!.codeIsSuccessful) { + showCupertinoDialog( + context: Get.context!, + builder: (BuildContext context) { + return CupertinoAlertDialog( + title: Text('语音设置'.tr), + content: Text('语音设置成功'.tr), + actions: [ + CupertinoDialogAction( + child: Text( + '取消'.tr, + style: TextStyle(color: AppColors.mainColor), + ), + onPressed: () { + Get.back(); + }, + ), + CupertinoDialogAction( + child: Text( + '返回主页'.tr, + style: TextStyle(color: AppColors.mainColor), + ), + onPressed: () { + state.lockSetInfoData.value.lockSettingInfo + ?.currentVoiceTimbre?.lang = item.lang; + state.lockSetInfoData.value.lockSettingInfo + ?.currentVoiceTimbre?.timbre = timbre.timbre; + + eventBus.fire(PassCurrentLockInformationEvent( + state.lockSetInfoData.value)); + Get.offAllNamed(Routers.starLockMain); + }, + ), + ], + ); + }, + ); + } + dismissEasyLoading(); + } + void saveSpeechLanguageSettings() async { // 如果已经开始发送中则不处理保存点击事件 if (state.progress.value > 0) { @@ -132,7 +185,11 @@ class LockVoiceSettingLogic extends BaseGetXController { .packageData(), ); } else if (deviceConnectionState == - BluetoothConnectionState.disconnected) {} + BluetoothConnectionState.disconnected) { + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + // showBlueConnetctToast(); + } }); } @@ -309,14 +366,13 @@ class LockVoiceSettingLogic extends BaseGetXController { BluetoothConnectionState.disconnected) { dismissEasyLoading(); cancelBlueConnetctToastTimer(); - showBlueConnetctToast(); + // showBlueConnetctToast(); } }); } @override void dispose() async { - super.dispose(); await _replySubscription?.cancel(); _replySubscription = null; await BlueManage().disconnect(); @@ -328,5 +384,23 @@ class LockVoiceSettingLogic extends BaseGetXController { state.voiceSubcontractingIndex = 0; state.voiceSubcontractingCount = 0; state.data = null; + + super.dispose(); + } + + @override + void onClose() async { + await _replySubscription?.cancel(); + _replySubscription = null; + await BlueManage().disconnect(); + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + EasyLoading.dismiss(); + // 清理分包相关状态 + state.progress.value = 0.0; + state.voiceSubcontractingIndex = 0; + state.voiceSubcontractingCount = 0; + state.data = null; + super.onClose(); } } diff --git a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart index 39facc57..543f0903 100644 --- a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart +++ b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart @@ -40,7 +40,7 @@ class _LockVoiceSettingState extends State { Get.offAllNamed(Routers.starLockMain); }, child: Text( - '跳过', + '跳过'.tr, style: TextStyle( color: Colors.white, fontSize: 24.sp, diff --git a/lib/mine/addLock/selectLockType/selectLockType_page.dart b/lib/mine/addLock/selectLockType/selectLockType_page.dart index 3688d0ae..fdc9ad60 100755 --- a/lib/mine/addLock/selectLockType/selectLockType_page.dart +++ b/lib/mine/addLock/selectLockType/selectLockType_page.dart @@ -84,17 +84,17 @@ class _SelectLockTypePageState extends State arguments: {'getLockType': 1}); }), // if (!F.isLite) - lockTypeItem('images/lockType/lockType_NFCLock.png', 'NFC无源锁'.tr, () { - CommonDataManage().seletLockType = 2; - // Navigator.pushNamed(context, Routers.addLockPage); - logic.getNearByLimits(); - }), + lockTypeItem('images/lockType/lockType_NFCLock.png', 'NFC无源锁'.tr, () { + CommonDataManage().seletLockType = 2; + // Navigator.pushNamed(context, Routers.addLockPage); + logic.getNearByLimits(); + }), // if (!F.isLite) - lockTypeItem('images/lockType/lockType_padlock.png', '挂锁'.tr, () { - CommonDataManage().seletLockType = 3; - // Navigator.pushNamed(context, Routers.addLockPage); - logic.getNearByLimits(); - }), + lockTypeItem('images/lockType/lockType_padlock.png', '挂锁'.tr, () { + CommonDataManage().seletLockType = 3; + // Navigator.pushNamed(context, Routers.addLockPage); + logic.getNearByLimits(); + }), lockTypeItem('images/lockType/lockType_safeLock.png', '保险箱锁'.tr, () { CommonDataManage().seletLockType = 4; Navigator.pushNamed(context, Routers.addLockPage, @@ -223,9 +223,16 @@ class _SelectLockTypePageState extends State mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(lockTypeTitle, - style: TextStyle( - fontSize: 22.sp, color: AppColors.blackColor)), + Text( + lockTypeTitle, + maxLines: 2, // 最大行数 + overflow: TextOverflow.ellipsis, // 超出显示省略号 + softWrap: true, // 自动换行 + style: TextStyle( + fontSize: 22.sp, + color: AppColors.blackColor, + ), + ), ], ), ), From 139d16387c5e3f78c03c139bd2df46271b9ffcf3 Mon Sep 17 00:00:00 2001 From: liyi Date: Wed, 23 Jul 2025 10:58:03 +0800 Subject: [PATCH 09/25] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E5=88=B0=E7=BD=91=E5=85=B3=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/blue/blue_manage.dart | 50 +++++++++++++------ .../selectGatewayList_logic.dart | 5 +- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/lib/blue/blue_manage.dart b/lib/blue/blue_manage.dart index d3d4d587..450bdfe7 100755 --- a/lib/blue/blue_manage.dart +++ b/lib/blue/blue_manage.dart @@ -348,21 +348,43 @@ class BlueManage { } else { // 128位,判断前8位的第3、第4位 if (cleanUuid.length >= 32) { - final String thirdAndFourth = cleanUuid.substring(2, 4); // 索引2和3 - for (final prefix in prefixes) { - if (thirdAndFourth == prefix) { - if (isSingle) { - return true; // isSingle为true,前缀匹配即返回true - } else { - // 判断配对状态(带横杠UUID的第31、32位,从1开始计数) - if (cleanUuid.length >= 32) { - String pairStatus = - cleanUuid.substring(30, 32); // 第31、32位(从1开始计数) - // 00=未配对,01=已配对 - if (pairStatus == '00') { - return true; // 未配对才返回true + if (deviceType == DeviceType.blue) { + final String thirdAndFourth = cleanUuid.substring(2, 4); // 索引2和3 + for (final prefix in prefixes) { + if (thirdAndFourth == prefix) { + if (isSingle) { + return true; // isSingle为true,前缀匹配即返回true + } else { + // 判断配对状态(带横杠UUID的第31、32位,从1开始计数) + if (cleanUuid.length >= 32) { + String pairStatus = + cleanUuid.substring(30, 32); // 第31、32位(从1开始计数) + // 00=未配对,01=已配对 + if (pairStatus == '00') { + return true; // 未配对才返回true + } + // 已配对(01)不返回true,继续判断下一个uuid + } + } + } + } + } else if (deviceType == DeviceType.gateway) { + final String thirdAndFourth = cleanUuid.substring(2, 8); // 索引2和3 + for (final prefix in prefixes) { + if (thirdAndFourth == prefix) { + if (isSingle) { + return true; // isSingle为true,前缀匹配即返回true + } else { + // 判断配对状态(带横杠UUID的第31、32位,从1开始计数) + if (cleanUuid.length >= 32) { + String pairStatus = + cleanUuid.substring(30, 32); // 第31、32位(从1开始计数) + // 00=未配对,01=已配对 + if (pairStatus == '00') { + return true; // 未配对才返回true + } + // 已配对(01)不返回true,继续判断下一个uuid } - // 已配对(01)不返回true,继续判断下一个uuid } } } diff --git a/lib/mine/gateway/addGateway/selectGateway/selectGatewayList_logic.dart b/lib/mine/gateway/addGateway/selectGateway/selectGatewayList_logic.dart index 3de08509..cf94b296 100644 --- a/lib/mine/gateway/addGateway/selectGateway/selectGatewayList_logic.dart +++ b/lib/mine/gateway/addGateway/selectGateway/selectGatewayList_logic.dart @@ -99,7 +99,7 @@ class SelectGatewayListLogic extends BaseGetXController { void startScanBlueList() { state.devices.clear(); BlueManage().startScan(2000, DeviceType.gateway, (List list) { - AppLog.log('ScanResultList:$list'); + // AppLog.log('ScanResultList:$list'); for (int i = 0; i < list.length; i++) { final ScanResult device = list[i]; // if ((device.advertisementData.serviceUuids.isNotEmpty @@ -211,7 +211,8 @@ class SelectGatewayListLogic extends BaseGetXController { @override void dispose() { - super.dispose(); _replySubscription.cancel(); + super.dispose(); + } } From 5e1d1bd0c113ae5101375b0caded714447a36d49 Mon Sep 17 00:00:00 2001 From: liyi Date: Wed, 23 Jul 2025 11:33:42 +0800 Subject: [PATCH 10/25] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E5=88=B0=E7=BD=91=E5=85=B3=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/blue/blue_manage.dart | 4 ++-- lib/blue/io_type.dart | 4 ++-- .../addLock/nearbyLock/nearbyLock_logic.dart | 20 +++++++++---------- .../selectGatewayList_logic.dart | 8 ++++++-- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/lib/blue/blue_manage.dart b/lib/blue/blue_manage.dart index 450bdfe7..29ea09f3 100755 --- a/lib/blue/blue_manage.dart +++ b/lib/blue/blue_manage.dart @@ -349,7 +349,7 @@ class BlueManage { // 128位,判断前8位的第3、第4位 if (cleanUuid.length >= 32) { if (deviceType == DeviceType.blue) { - final String thirdAndFourth = cleanUuid.substring(2, 4); // 索引2和3 + final String thirdAndFourth = cleanUuid.substring(6, 8); // 索引2和3 for (final prefix in prefixes) { if (thirdAndFourth == prefix) { if (isSingle) { @@ -369,7 +369,7 @@ class BlueManage { } } } else if (deviceType == DeviceType.gateway) { - final String thirdAndFourth = cleanUuid.substring(2, 8); // 索引2和3 + final String thirdAndFourth = cleanUuid.substring(6, 8); // 索引2和3 for (final prefix in prefixes) { if (thirdAndFourth == prefix) { if (isSingle) { diff --git a/lib/blue/io_type.dart b/lib/blue/io_type.dart index 6a4ceffa..ac261daf 100755 --- a/lib/blue/io_type.dart +++ b/lib/blue/io_type.dart @@ -9,10 +9,10 @@ List getDeviceType(DeviceType deviceType) { List t = ['758824']; switch (deviceType) { case DeviceType.blue: - t = ['758824', '75', '768824', '76']; + t = ['758824', '75', '768824', '76','24']; break; case DeviceType.gateway: - t = ['758825']; + t = ['758825','25']; break; } return t; diff --git a/lib/mine/addLock/nearbyLock/nearbyLock_logic.dart b/lib/mine/addLock/nearbyLock/nearbyLock_logic.dart index 0b0952f5..34d9b240 100755 --- a/lib/mine/addLock/nearbyLock/nearbyLock_logic.dart +++ b/lib/mine/addLock/nearbyLock/nearbyLock_logic.dart @@ -337,17 +337,15 @@ class NearbyLockLogic extends BaseGetXController { // 'featureSettingValue': state.featureSettingValue, // 'featureSettingParams': state.featureSettingParams, // }); - Get.toNamed(Routers.saveLockPage, - arguments: { - 'addressInfo': {}, - 'pwdTimestamp': state.timestampValue * 1000, - 'lockInfo': state.lockInfo, - 'featureValue': state.featureValue, - 'featureSettingValue': state.featureSettingValue, - 'featureSettingParams': state.featureSettingParams, - 'isFromMap': 0, - }); - + Get.toNamed(Routers.saveLockPage, arguments: { + 'addressInfo': {}, + 'pwdTimestamp': state.timestampValue * 1000, + 'lockInfo': state.lockInfo, + 'featureValue': state.featureValue, + 'featureSettingValue': state.featureSettingValue, + 'featureSettingParams': state.featureSettingParams, + 'isFromMap': 0, + }); break; case 0x06: diff --git a/lib/mine/gateway/addGateway/selectGateway/selectGatewayList_logic.dart b/lib/mine/gateway/addGateway/selectGateway/selectGatewayList_logic.dart index cf94b296..db6b4565 100644 --- a/lib/mine/gateway/addGateway/selectGateway/selectGatewayList_logic.dart +++ b/lib/mine/gateway/addGateway/selectGateway/selectGatewayList_logic.dart @@ -25,6 +25,7 @@ class SelectGatewayListLogic extends BaseGetXController { // 监听设备返回的数据 late StreamSubscription _replySubscription; + void _initReplySubscription() { _replySubscription = EventBusManager().eventBus!.on().listen((Reply reply) async { @@ -35,7 +36,6 @@ class SelectGatewayListLogic extends BaseGetXController { }); } - // WIFI配网结果 Future _replyGatewayGetStatusReply(Reply reply) async { final int status = reply.data[2]; @@ -213,6 +213,10 @@ class SelectGatewayListLogic extends BaseGetXController { void dispose() { _replySubscription.cancel(); super.dispose(); - + } + @override + void onClose() { + _replySubscription.cancel(); + super.onClose(); } } From 26e0f4d3bbfa78ef1486b17681d1bed60697d2a2 Mon Sep 17 00:00:00 2001 From: liyi Date: Thu, 24 Jul 2025 11:28:59 +0800 Subject: [PATCH 11/25] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4firebase=E5=BF=85?= =?UTF-8?q?=E9=A1=BB=E5=9C=A8Android=E5=92=8C=E7=94=9F=E4=BA=A7=E7=8E=AF?= =?UTF-8?q?=E5=A2=83=E6=89=8D=E7=94=9F=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/apm/firebase/firebase_helper.dart | 36 ++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/lib/apm/firebase/firebase_helper.dart b/lib/apm/firebase/firebase_helper.dart index cb354174..e49d3842 100644 --- a/lib/apm/firebase/firebase_helper.dart +++ b/lib/apm/firebase/firebase_helper.dart @@ -71,21 +71,45 @@ class FirebaseHelper { } Future initSdk() async { - FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(true); + const bool isProductVmMode = bool.fromEnvironment('dart.vm.product'); + if (F.isProductionEnv && + isProductVmMode && + defaultTargetPlatform == TargetPlatform.android) { + FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(true); + } } Future login(String userId) async { - FirebaseAnalytics.instance.setUserId(id: userId); + const bool isProductVmMode = bool.fromEnvironment('dart.vm.product'); + if (F.isProductionEnv && + isProductVmMode && + defaultTargetPlatform == TargetPlatform.android) { + FirebaseAnalytics.instance.setUserId(id: userId); + } } Future trackEvent( - String eventName, Map? parameters) async { - FirebaseAnalytics.instance - .logEvent(name: eventName, parameters: parameters); + String eventName, + Map? parameters, + ) async { + const bool isProductVmMode = bool.fromEnvironment('dart.vm.product'); + if (F.isProductionEnv && + isProductVmMode && + defaultTargetPlatform == TargetPlatform.android) { + FirebaseAnalytics.instance.logEvent( + name: eventName, + parameters: parameters, + ); + } } Future logout() async { - FirebaseAnalytics.instance.setUserId(id: ''); + const bool isProductVmMode = bool.fromEnvironment('dart.vm.product'); + if (F.isProductionEnv && + isProductVmMode && + defaultTargetPlatform == TargetPlatform.android) { + FirebaseAnalytics.instance.setUserId(id: ''); + } } } // From 2e3bc1156364ad2d740dd3ed6f20cec77da3d97c Mon Sep 17 00:00:00 2001 From: liyi Date: Thu, 24 Jul 2025 16:17:49 +0800 Subject: [PATCH 12/25] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E7=AC=AC=E4=B8=89?= =?UTF-8?q?=E6=96=B9=E5=B9=B3=E5=8F=B0=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lockSet/lockSet/lockSet_page.dart | 15 ++- .../third_party_platform_logic.dart | 8 ++ .../third_party_platform_page.dart | 92 +++++++++++++++++++ .../third_party_platform_state.dart | 18 ++++ 4 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart create mode 100644 lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_page.dart create mode 100644 lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart diff --git a/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart b/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart index 43cbc989..045b2b2c 100755 --- a/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart +++ b/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart @@ -540,6 +540,19 @@ class _LockSetPageState extends State 'lockSetInfoData': state.lockSetInfoData.value }); })), + // 锁语音包设置 + CommonItem( + leftTitel: '第三方平台'.tr, + rightTitle: '', + isHaveLine: true, + isHaveDirection: true, + action: () { + Get.toNamed(Routers.thirdPartyPlatformPage, + arguments: { + 'lockSetInfoData': state.lockSetInfoData.value + }); + }, + ), // 蓝牙广播(关闭则不能使用蓝牙主动开锁) /* 2024-01-12 会议确定去掉“蓝牙广播” by DaisyWu Obx(() => Visibility( @@ -606,7 +619,7 @@ class _LockSetPageState extends State state.lockFeature.value.appUnlockOnline == 1, child: otherItem( leftTitle: '开锁时是否需联网'.tr, - isHaveLine: false, + isHaveLine: true, rightWidget: _openLockNeedOnlineSwitch()), ), ), diff --git a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart new file mode 100644 index 00000000..b73156e2 --- /dev/null +++ b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart @@ -0,0 +1,8 @@ +import 'package:star_lock/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart'; + +class ThirdPartyPlatformLogic { + ThirdPartyPlatformState state = ThirdPartyPlatformState(); + + void savePlatFormSetting() { + } +} diff --git a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_page.dart b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_page.dart new file mode 100644 index 00000000..6d7d1919 --- /dev/null +++ b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_page.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.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/thirdPartyPlatform/third_party_platform_logic.dart'; +import 'package:star_lock/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart'; +import 'package:star_lock/tools/titleAppBar.dart'; + +class ThirdPartyPlatformPage extends StatefulWidget { + const ThirdPartyPlatformPage(); + + @override + State createState() => _ThirdPartyPlatformPageState(); +} + +class _ThirdPartyPlatformPageState extends State { + final ThirdPartyPlatformLogic logic = Get.put(ThirdPartyPlatformLogic()); + final ThirdPartyPlatformState state = + Get.find().state; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: TitleAppBar( + barTitle: '第三方平台设置'.tr, + haveBack: true, + backgroundColor: AppColors.mainColor, + actionsList: [ + TextButton( + onPressed: logic.savePlatFormSetting, + child: Text( + '保存'.tr, + style: TextStyle( + color: Colors.white, + fontSize: 24.sp, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + body: _buildBody(), + ); + } + + Widget _buildBody() { + return ListView.builder( + itemCount: state.platFormSet.length, + itemBuilder: (BuildContext context, int index) { + return InkWell( + onTap: () { + setState(() { + state.selectPlatFormIndex.value = index; + }); + }, + child: Container( + width: 1.sw, + padding: EdgeInsets.symmetric( + vertical: 12.h, + horizontal: 24.w, + ), + decoration: BoxDecoration( + color: Colors.white, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + state.platFormSet[index], + style: TextStyle( + wordSpacing: 2.w, + ), + ), + Visibility( + visible: state.selectPlatFormIndex.value == index, + child: Icon( + Icons.check_circle, + color: AppColors.mainColor, + size: 30.sp, + ), + ), + ], + ), + ), + ); + }, + shrinkWrap: true, + physics: const AlwaysScrollableScrollPhysics(), + ); + } +} diff --git a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart new file mode 100644 index 00000000..65bc92b8 --- /dev/null +++ b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart @@ -0,0 +1,18 @@ +import 'package:get/get.dart'; +import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart'; + +class ThirdPartyPlatformState { + ThirdPartyPlatformState() { + final map = Get.arguments; + lockSetInfoData.value = map['lockSetInfoData']; + } + + Rx lockSetInfoData = LockSetInfoData().obs; + + // 响应式字符串集合(自动触发 UI 更新) + final RxList platFormSet = List.of({ + '涂鸦智能'.tr, + }).obs; + + RxInt selectPlatFormIndex = 999.obs; +} From 7937ff5b7b9ba40044e5339eb6c7abb016ec7dfb Mon Sep 17 00:00:00 2001 From: liyi Date: Thu, 24 Jul 2025 16:18:03 +0800 Subject: [PATCH 13/25] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E7=AC=AC=E4=B8=89?= =?UTF-8?q?=E6=96=B9=E5=B9=B3=E5=8F=B0=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/appRouters.dart | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/appRouters.dart b/lib/appRouters.dart index 1bba3087..1293063f 100755 --- a/lib/appRouters.dart +++ b/lib/appRouters.dart @@ -27,6 +27,7 @@ import 'package:star_lock/main/lockDetail/lockSet/liveVideo/liveVideo_page.dart' import 'package:star_lock/main/lockDetail/lockSet/motorPower/motorPower_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/openDoorDirection/openDoorDirection_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart'; +import 'package:star_lock/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_page.dart'; import 'package:star_lock/main/lockDetail/messageWarn/addFamily/addFamily_page.dart'; import 'package:star_lock/main/lockDetail/messageWarn/lockUser/lockUser_page.dart'; import 'package:star_lock/main/lockDetail/messageWarn/msgNotification/coerceOpenDoor/coerceFingerprint/coerceFingerprint_page.dart'; @@ -443,6 +444,8 @@ abstract class Routers { static const String motorPowerPage = '/motorPowerPage'; //电机功率设置 static const String speechLanguageSettingsPage = '/speechLanguageSettingsPage'; //锁语音包设置 + static const String thirdPartyPlatformPage = + '/thirdPartyPlatformPage'; //第三方平台设置 static const String openDoorDirectionPage = '/openDoorDirectionPage'; //开门方向设置 static const String catEyeWorkModePage = '/catEyeWorkModePage'; //猫眼工作模式 static const String msgNotificationPage = '/msgNotificationPage'; //消息提醒 @@ -528,8 +531,7 @@ abstract class Routers { '/imageTransmissionView'; //星图对讲页面(图传) static const String permissionGuidancePage = '/permissionGuidancePage'; // 锁屏权限通知引导页面 - static const String lockVoiceSettingPage = - '/lockVoiceSetting'; // 锁屏权限通知引导页面 + static const String lockVoiceSettingPage = '/lockVoiceSetting'; // 锁屏权限通知引导页面 } abstract class AppRouters { @@ -1218,8 +1220,10 @@ abstract class AppRouters { name: Routers.permissionGuidancePage, page: () => PermissionGuidancePage()), GetPage( - name: Routers.lockVoiceSettingPage, - page: () => LockVoiceSetting()), + name: Routers.lockVoiceSettingPage, page: () => LockVoiceSetting()), + GetPage( + name: Routers.thirdPartyPlatformPage, + page: () => ThirdPartyPlatformPage()), // 插件播放页面 // GetPage(name: Routers.h264View, page: () => H264WebView()), // webview播放页面 ]; From f037cb3c2873623b9fad415f7ccd23b3bd674e75 Mon Sep 17 00:00:00 2001 From: liyi Date: Fri, 25 Jul 2025 14:59:54 +0800 Subject: [PATCH 14/25] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E8=AF=AD=E8=A8=80?= =?UTF-8?q?=E5=8C=85=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lockDetail/passthrough_item.dart | 11 +- .../lockSet/lockSet/lockSet_logic.dart | 24 ++- .../speech_language_settings_logic.dart | 161 ++++++++++----- .../speech_language_settings_page.dart | 165 +++++++-------- .../speech_language_settings_state.dart | 34 ++- .../lock_voice_setting_logic.dart | 75 ++++--- .../lock_voice_setting_page.dart | 195 ++++++++++-------- .../lock_voice_setting_state.dart | 27 +++ 8 files changed, 417 insertions(+), 275 deletions(-) diff --git a/lib/main/lockDetail/lockDetail/passthrough_item.dart b/lib/main/lockDetail/lockDetail/passthrough_item.dart index bb9a910c..2d54fa3e 100644 --- a/lib/main/lockDetail/lockDetail/passthrough_item.dart +++ b/lib/main/lockDetail/lockDetail/passthrough_item.dart @@ -5,11 +5,13 @@ class TimbreItem { final String timbre; final String name; final String timbrePackUrl; + final int isFemale; TimbreItem({ required this.timbre, required this.name, required this.timbrePackUrl, + required this.isFemale, }); factory TimbreItem.fromJson(Map json) { @@ -17,6 +19,7 @@ class TimbreItem { timbre: json['timbre'] ?? '', name: json['name'] ?? '', timbrePackUrl: json['timbrePackUrl'] ?? '', + isFemale: json['isFemale'] ?? 0, ); } @@ -25,23 +28,27 @@ class TimbreItem { 'timbre': timbre, 'name': name, 'timbrePackUrl': timbrePackUrl, + 'isFemale': isFemale, }; } @override String toString() { - return 'TimbreItem{timbre: $timbre, name: $name, timbrePackUrl: $timbrePackUrl}'; + return 'TimbreItem{timbre: $timbre, name: $name, timbrePackUrl: ' + '$timbrePackUrl},isFemale: $isFemale}'; } } // 透传项主类 class PassthroughItem { final String lang; + final String langText; final List timbres; PassthroughItem({ required this.lang, required this.timbres, + required this.langText, }); factory PassthroughItem.fromJson(Map json) { @@ -53,6 +60,7 @@ class PassthroughItem { : []; return PassthroughItem( lang: json['lang'] ?? '', + langText: json['langText'] ?? '', timbres: timbresList, ); } @@ -60,6 +68,7 @@ class PassthroughItem { Map toJson() { return { 'lang': lang, + 'langText': langText, 'timbres': timbres.map((e) => e.toJson()).toList(), }; } diff --git a/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart b/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart index e27e1b4d..7fe7f771 100755 --- a/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart +++ b/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart @@ -686,7 +686,7 @@ class LockSetLogic extends BaseGetXController { updataLockSet(getTokenList); } else if (connectionState == BluetoothConnectionState.disconnected) { // cancelBlueConnetctToastTimer(); - // if(state.ifCurrentScreen.value == true){ + // if (state.ifCurrentScreen.value == true) { // showBlueConnetctToast(); // } } @@ -745,12 +745,13 @@ class LockSetLogic extends BaseGetXController { // _scanListDiscoveredDeviceSubscription.cancel(); } + // 发送获取型号蓝牙命令 sendGetDeviceModelBleMessage() { - showEasyLoading(); - showBlueConnetctToastTimer(action: () { - dismissEasyLoading(); - }); + // showEasyLoading(); + // showBlueConnetctToastTimer(action: () { + // dismissEasyLoading(); + // }); BlueManage().blueSendData(BlueManage().connectDeviceName, (BluetoothConnectionState deviceConnectionState) async { if (deviceConnectionState == BluetoothConnectionState.connected) { @@ -761,13 +762,19 @@ class LockSetLogic extends BaseGetXController { ); } else if (deviceConnectionState == BluetoothConnectionState.disconnected) { - dismissEasyLoading(); - cancelBlueConnetctToastTimer(); - showBlueConnetctToast(); + // dismissEasyLoading(); + // cancelBlueConnetctToastTimer(); + // showBlueConnetctToast(); } }); } + @override + void dispose() { + _replySubscription.cancel(); + super.dispose(); + } + void _handlerDeviceModelReply(GetDeviceModelReply reply) async { final int status = reply.data[2]; switch (status) { @@ -783,7 +790,6 @@ class LockSetLogic extends BaseGetXController { String rawData = String.fromCharCodes(deviceModelBytes); int firstNullIndex = rawData.indexOf('\u0000'); String deviceModelValue = rawData.substring(0, firstNullIndex); - print(deviceModelValue); // 输出: 2403 print('获取到 DeviceModel (原始): $deviceModelValue'); await Storage.setString(deviceModel, deviceModelValue); break; diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart index 921a8ef8..d6301406 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart @@ -27,6 +27,7 @@ import 'package:http/http.dart' as http; import 'package:star_lock/tools/commonDataManage.dart'; import 'package:star_lock/tools/eventBusEventManage.dart'; import 'package:star_lock/tools/storage.dart'; +import 'package:star_lock/translations/app_dept.dart'; class SpeechLanguageSettingsLogic extends BaseGetXController { final SpeechLanguageSettingsState state = SpeechLanguageSettingsState(); @@ -34,6 +35,8 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { @override void onInit() async { + final findLocaleIndex = _findLocaleIndex(); + state.selectPassthroughListIndex.value = findLocaleIndex; super.onInit(); _replySubscription = EventBusManager().eventBus!.on().listen((Reply reply) async { @@ -47,28 +50,7 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { } else if (reply is VoicePackageConfigureProcessReply) { _handlerVoicePackageConfigureProcess(reply); } else if (reply is VoicePackageConfigureConfirmationReply) { - final PassthroughItem item = - state.languages[state.selectPassthroughListIndex.value]; - final timbre = item.timbres[state.selectLanguageIndex.value]; - final LoginEntity entity = - await ApiRepository.to.settingCurrentVoiceTimbre( - data: { - 'lang': item.lang, - 'timbre': timbre.timbre, - }, - lockId: state.lockSetInfoData.value.lockId!, - ); - if (entity.errorCode!.codeIsSuccessful) { - showSuccess('设置成功'.tr, something: () { - state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre - ?.lang = item.lang; - state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre - ?.timbre = timbre.timbre; - eventBus.fire( - PassCurrentLockInformationEvent(state.lockSetInfoData.value)); - }); - } - dismissEasyLoading(); + _handlerVoicePackageConfigureConfirmation(reply); } }); state.deviceModel.value = await Storage.getString(deviceModel) ?? ''; @@ -76,35 +58,37 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { if (state.deviceModel.value != null) { await initList(); } + // await sendGetDeviceModelBleMessage(); } - /// 获取列表 + /// //{ "vendor": "XL", "model": "JL-BLE-01"} initList() async { showEasyLoading(); try { - final PassthroughListResponse entity = await ApiRepository.to - .getPassthroughList(data: {'deviceType': state.deviceModel.value}); + final vendor = state.lockSetInfoData.value.lockBasicInfo?.vendor; + final model = state.lockSetInfoData.value.lockBasicInfo?.model; + + final PassthroughListResponse entity = + await ApiRepository.to.getPassthroughList(data: { + 'vendor': vendor!, + 'model': model!, + }); if (entity.errorCode!.codeIsSuccessful) { state.languages.value = entity.data!!; - final oldTimbre = state - .lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre; - final oldLang = state + final lang = state .lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang; - - for (int index = 0; index < state.languages.value.length; index++) { - final element = state.languages.value[index]; + final timbre = state + .lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre; + state.languages.value.forEach((element) { final timbres = element.timbres; - for (int i = 0; i < timbres.length; i++) { - final timbre = timbres[i].timbre; - if ((oldLang != null && oldLang == element.lang) && - (oldTimbre != null && oldTimbre == timbre)) { - state.selectPassthroughListIndex.value = index; - state.selectLanguageIndex.value = i; + timbres.forEach((item) { + if (lang == element.lang && item.timbre == timbre) { + state.selectSoundTypeIndex.value = item.isFemale; } - } - } + }); + }); } } catch (e) { debugPrint('获取语音包出现错误:$e'); @@ -113,26 +97,56 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { } } - void saveSpeechLanguageSettings() async { - // 如果已经开始发送中则不处理保存点击事件 - if (state.progress.value > 0) { - return; - } - final oldTimbre = - state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre; - final oldLang = + /// 查找 locales 中 code 等于 lang 的元素下标(不存在返回 -1) + int _findLocaleIndex() { + // 1. 获取 lang(可能为 null) + final lang = state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang; - EasyLoading.showProgress(state.progress.value, status: '正在发送数据'); - final PassthroughItem item = - state.languages[state.selectPassthroughListIndex.value]; - final timbre = item.timbres[state.selectLanguageIndex.value]; - debugPrint('选中的语音是:${timbre}'); - if ((oldLang != null && oldLang == item.lang) && - (oldTimbre != null && oldTimbre == timbre.timbre)) { - showToast('已设置为当前选择的语音包'.tr); - } - await downloadFile(timbre.timbrePackUrl); + // 2. 如果 lang 为 null,直接返回 -1 + if (lang == null) return -1; + + // 3. 获取 locales 集合(假设非空,若可能为空需额外判空) + final locales = appDept.deptSupportedLocales; + + // 4. 遍历查找符合条件的下标(使用 indexWhere 高效实现) + return locales.indexWhere((element) { + // 处理 countryCode 可能为 null 的情况(根据业务需求调整) + if (element.countryCode == null) return false; + + // 构造当前 locale 的 code(格式:languageCode_countryCode) + final currentCode = '${element.languageCode}_${element.countryCode}'; + + // 比较是否等于目标 lang + return currentCode == lang; + }); + } + + void saveSpeechLanguageSettings() async { + final language = + state.appLocalLanguages[state.selectPassthroughListIndex.value]; + // 从选中的语言中获取languageCode和countryCode + final locales = appDept.deptSupportedLocales; + locales.forEach((element) { + final lanTitle = ExtensionLanguageType.fromLocale(element).lanTitle; + if (lanTitle == language) { + if (element.countryCode != null) { + String code = element.languageCode + '_' + element.countryCode!; + + state.languages.forEach((item) async { + if (item.lang == code) { + item.timbres.forEach((timbre) async { + if (timbre.isFemale == state.selectSoundTypeIndex.value) { + state.tempLangStr.value = item.lang; + state.tempTimbreStr.value = timbre.timbre; + await downloadFile(timbre.timbrePackUrl); + } + }); + } + }); + } + } + }); } void changeSelectIndex(int index) { @@ -363,4 +377,37 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { state.data = null; super.onClose(); } + + void _handlerVoicePackageConfigureConfirmation( + VoicePackageConfigureConfirmationReply reply, + ) async { + final int status = reply.data[2]; + switch (status) { + case 0x00: + cancelBlueConnetctToastTimer(); + final LoginEntity entity = + await ApiRepository.to.settingCurrentVoiceTimbre( + data: { + 'lang': state.tempLangStr.value, + 'timbre': state.tempTimbreStr.value, + }, + lockId: state.lockSetInfoData.value.lockId!, + ); + if (entity.errorCode!.codeIsSuccessful) { + showSuccess('设置成功'.tr, something: () { + state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre + ?.lang = state.tempLangStr.value; + state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre + ?.timbre = state.tempTimbreStr.value; + eventBus.fire( + PassCurrentLockInformationEvent(state.lockSetInfoData.value)); + }); + } + dismissEasyLoading(); + break; + default: + showToast('语音设置失败'.tr); + break; + } + } } diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart index bb5275a8..d78b91d7 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart @@ -8,6 +8,7 @@ import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart'; import 'package:star_lock/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart'; import 'package:star_lock/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart'; import 'package:star_lock/tools/EasyRefreshTool.dart'; +import 'package:star_lock/tools/commonItem.dart'; import 'package:star_lock/tools/titleAppBar.dart'; class SpeechLanguageSettingsPage extends StatefulWidget { @@ -47,12 +48,7 @@ class _SpeechLanguageSettingsPageState ), ], ), - body: EasyRefreshTool( - child: _buildBody(), - onRefresh: () { - logic.sendGetDeviceModelBleMessage(); - }, - ), + body: _buildBody(), ); } @@ -61,30 +57,57 @@ class _SpeechLanguageSettingsPageState () => SingleChildScrollView( child: Column( children: [ - // Container( - // width: 1.sw, - // decoration: BoxDecoration(color: Colors.white), - // child: Column( - // children: [ - // RadioListTile( - // title: Text("男声".tr), - // value: 1, - // groupValue: state.selectedValue.value, - // onChanged: (value) { - // state.selectedValue.value = int.parse(value.toString()); - // }, - // ), - // RadioListTile( - // title: Text("女声".tr), - // value: 2, - // groupValue: state.selectedValue.value, - // onChanged: (value) { - // state.selectedValue.value = int.parse(value.toString()); - // }, - // ) - // ], - // ), - // ), + Container( + width: 1.sw, + decoration: BoxDecoration(color: Colors.white), + child: ListView.builder( + itemCount: state.soundTypeList.length, + itemBuilder: (BuildContext context, int index) { + // 判断是否是最后一个元素(索引等于 itemCount - 1) + final isLastItem = index == state.soundTypeList.length - 1; + + // 获取当前平台数据(假设 platFormSet 是 RxList) + final platform = state.soundTypeList.value[index]; + return CommonItem( + leftTitel: state.soundTypeList.value[index], + rightTitle: '', + isHaveLine: !isLastItem, + // 最后一个元素不显示分割线(取反) + isHaveDirection: false, + isHaveRightWidget: true, + rightWidget: Radio( + // Radio 的值:使用平台的唯一标识(如 id) + value: platform, + // 当前选中的值:与 selectPlatFormIndex 关联的 id + groupValue: state.soundTypeList + .value[state.selectSoundTypeIndex.value], + // 选中颜色(可选,默认主题色) + activeColor: AppColors.mainColor, + // 点击 Radio 时回调(更新选中索引) + onChanged: (value) { + if (value != null) { + setState(() { + // 找到当前选中平台的索引(根据 id 匹配) + final newIndex = state.soundTypeList.value + .indexWhere((p) => p == value); + if (newIndex != -1) { + state.selectSoundTypeIndex.value = newIndex; + } + }); + } + }, + ), + action: () { + setState(() { + state.selectSoundTypeIndex.value = index; + }); + }, + ); + }, + shrinkWrap: true, + physics: const AlwaysScrollableScrollPhysics(), + ), + ), SizedBox( height: 8.h, ), @@ -98,72 +121,42 @@ class _SpeechLanguageSettingsPageState } List _buildList() { - final languages = state.languages; + final appLocalLanguages = state.appLocalLanguages; return List.generate( - languages.length, - (index) => _buildItem(languages[index], index), - ); - } - - _buildItem(PassthroughItem language, int index) { - final timbres = language.timbres; - final isSelected = state.selectPassthroughListIndex == index; - return ExpansionTile( - title: Text( - PassthroughLangHelper.getLangText(language.lang), - style: TextStyle( - fontSize: 24.sp, - fontWeight: isSelected ? FontWeight.bold : null, - ), - ), - onExpansionChanged: (bool expanded) {}, - initiallyExpanded: false, - backgroundColor: Colors.white, - collapsedBackgroundColor: Colors.white, - expandedCrossAxisAlignment: CrossAxisAlignment.center, - expandedAlignment: Alignment.center, - shape: InputBorder.none, - maintainState: true, - // 去除展开状态下的边框 - collapsedShape: InputBorder.none, - // 去除折叠状态下的边框 - childrenPadding: EdgeInsets.only(left: 12.w), - children: List.generate( - timbres.length, - (int languageIndex) => ListTile( - title: Text( - timbres[languageIndex].name, - style: TextStyle( - fontSize: 22.sp, - fontWeight: - state.selectLanguageIndex == languageIndex && isSelected - ? FontWeight.bold - : null, - ), - ), - trailing: state.selectLanguageIndex == languageIndex && isSelected - ? Icon( - Icons.check_circle, - color: AppColors.mainColor, - ) // 仅当选中时显示图标 - : null, // 默认不显示 - onTap: () { - // 更新选中的语音包 - state.selectLanguageIndex.value = languageIndex; - // 更新选中的语言 - state.selectPassthroughListIndex.value = index; - }, // 默认图标, // 右侧的图标 - ), + appLocalLanguages.length, + (index) => _buildItem( + appLocalLanguages[index], + index, ), ); } @override void dispose() { - // TODO: implement dispose super.dispose(); if (EasyLoading.isShow) { EasyLoading.dismiss(animation: true); } } + + _buildItem(String appLocalLanguages, index) { + return CommonItem( + leftTitel: appLocalLanguages, + rightTitle: '', + isHaveLine: true, + isHaveDirection: false, + isHaveRightWidget: true, + rightWidget: state.selectPassthroughListIndex.value == index + ? Image( + image: const AssetImage('images/icon_item_checked.png'), + width: 30.w, + height: 30.w, + fit: BoxFit.contain, + ) + : Container(), + action: () { + state.selectPassthroughListIndex.value = index; + }, + ); + } } diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart index 02079884..da705c38 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart @@ -4,6 +4,7 @@ import 'package:flutter/widgets.dart'; import 'package:get/get.dart'; import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart'; import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart'; +import 'package:star_lock/translations/app_dept.dart'; class SpeechLanguageSettingsState { SpeechLanguageSettingsState() { @@ -11,6 +12,25 @@ class SpeechLanguageSettingsState { lockSetInfoData.value = map['lockSetInfoData']; } + List get appLocalLanguages { + final locales = appDept.deptSupportedLocales; + + final languageCode = locales[1].languageCode; + final countryCode = locales[1].countryCode; + String localeStr = ''; + if (countryCode != null) { + localeStr = languageCode + '_' + countryCode; + appLocalLanguageCodes.add(localeStr); + } + + final list = locales + .map((e) => ExtensionLanguageType.fromLocale(e).lanTitle) + .toList(); + return list; + } + + List appLocalLanguageCodes = []; + Rx lockSetInfoData = LockSetInfoData().obs; // 选中的语音包列表下标 @@ -21,8 +41,6 @@ class SpeechLanguageSettingsState { final RxList languages = [].obs; - Map languageSpeechDeviceTypeMapping = {0: '2403'}; - RxBool otaUpdateIng = false.obs; RxDouble otaProgress = 0.00.obs; RxString deviceModel = '2403'.obs; @@ -40,7 +58,17 @@ class SpeechLanguageSettingsState { // 分包发送进度(0.0~1.0) RxDouble progress = 0.0.obs; - RxInt selectedValue = 1.obs; + RxInt selectedValue = 1.obs; + + // 响应式字符串集合(自动触发 UI 更新) + final RxList soundTypeList = List.of({ + '男声'.tr, + '女声'.tr, + }).obs; + + RxInt selectSoundTypeIndex = 0.obs; + RxString tempLangStr=''.obs; + RxString tempTimbreStr=''.obs; } diff --git a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart index fd30419f..46e68efd 100644 --- a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart +++ b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart @@ -25,6 +25,7 @@ import 'package:star_lock/tools/eventBusEventManage.dart'; import 'package:star_lock/tools/showTipView.dart'; import 'package:star_lock/tools/storage.dart'; import 'package:http/http.dart' as http; +import 'package:star_lock/translations/app_dept.dart'; class LockVoiceSettingLogic extends BaseGetXController { LockVoiceSettingState state = LockVoiceSettingState(); @@ -122,25 +123,30 @@ class LockVoiceSettingLogic extends BaseGetXController { } void saveSpeechLanguageSettings() async { - // 如果已经开始发送中则不处理保存点击事件 - if (state.progress.value > 0) { - return; - } - final oldTimbre = - state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre; - final oldLang = - state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang; + final language = + state.appLocalLanguages[state.selectPassthroughListIndex.value]; + // 从选中的语言中获取languageCode和countryCode + final locales = appDept.deptSupportedLocales; + locales.forEach((element) { + final lanTitle = ExtensionLanguageType.fromLocale(element).lanTitle; + if (lanTitle == language) { + if (element.countryCode != null) { + String code = element.languageCode + '_' + element.countryCode!; - EasyLoading.showProgress(state.progress.value, status: '正在发送数据'); - final PassthroughItem item = - state.languages[state.selectPassthroughListIndex.value]; - final timbre = item.timbres[state.selectLanguageIndex.value]; - debugPrint('选中的语音是:${timbre}'); - if ((oldLang != null && oldLang == item.lang) && - (oldTimbre != null && oldTimbre == timbre.timbre)) { - showToast('已设置为当前选择的语音包'.tr); - } - await downloadFile(timbre.timbrePackUrl); + state.languages.forEach((item) async { + if (item.lang == code) { + item.timbres.forEach((timbre) async { + if (timbre.isFemale == state.selectSoundTypeIndex.value) { + state.tempLangStr.value = item.lang; + state.tempTimbreStr.value = timbre.timbre; + await downloadFile(timbre.timbrePackUrl); + } + }); + } + }); + } + } + }); } //下载语音包 @@ -263,27 +269,28 @@ class LockVoiceSettingLogic extends BaseGetXController { initList() async { showEasyLoading(); try { - final PassthroughListResponse entity = await ApiRepository.to - .getPassthroughList(data: {'deviceType': state.deviceModel.value}); + final vendor = state.lockSetInfoData.value.lockBasicInfo?.vendor; + final model = state.lockSetInfoData.value.lockBasicInfo?.model; + + final PassthroughListResponse entity = + await ApiRepository.to.getPassthroughList(data: { + 'vendor': vendor!, + 'model': model!, + }); if (entity.errorCode!.codeIsSuccessful) { state.languages.value = entity.data!!; - final oldTimbre = state - .lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre; - final oldLang = state + final lang = state .lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang; - - for (int index = 0; index < state.languages.value.length; index++) { - final element = state.languages.value[index]; + final timbre = state + .lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre; + state.languages.value.forEach((element) { final timbres = element.timbres; - for (int i = 0; i < timbres.length; i++) { - final timbre = timbres[i].timbre; - if ((oldLang != null && oldLang == element.lang) && - (oldTimbre != null && oldTimbre == timbre)) { - state.selectPassthroughListIndex.value = index; - state.selectLanguageIndex.value = i; + timbres.forEach((item) { + if (lang == element.lang && item.timbre == timbre) { + state.selectSoundTypeIndex.value = item.isFemale; } - } - } + }); + }); } } catch (e) { debugPrint('获取语音包出现错误:$e'); diff --git a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart index 543f0903..4b6a3ace 100644 --- a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart +++ b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart @@ -10,6 +10,7 @@ import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart'; import 'package:star_lock/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart'; import 'package:star_lock/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart'; import 'package:star_lock/tools/EasyRefreshTool.dart'; +import 'package:star_lock/tools/commonItem.dart'; import 'package:star_lock/tools/titleAppBar.dart'; class LockVoiceSetting extends StatefulWidget { @@ -25,22 +26,31 @@ class _LockVoiceSettingState extends State { @override Widget build(BuildContext context) { - return EasyRefreshTool( - onRefresh: () { - logic.sendGetDeviceModelBleMessage(); - }, - child: Scaffold( - backgroundColor: AppColors.mainBackgroundColor, - appBar: TitleAppBar( - barTitle: '锁语音包设置'.tr, - haveBack: false, - haveOtherLeftWidget: true, - leftWidget: TextButton( - onPressed: () { - Get.offAllNamed(Routers.starLockMain); - }, + return Scaffold( + backgroundColor: AppColors.mainBackgroundColor, + appBar: TitleAppBar( + barTitle: '锁语音包设置'.tr, + haveBack: false, + haveOtherLeftWidget: true, + leftWidget: TextButton( + onPressed: () { + Get.offAllNamed(Routers.starLockMain); + }, + child: Text( + '跳过'.tr, + style: TextStyle( + color: Colors.white, + fontSize: 24.sp, + fontWeight: FontWeight.w500, + ), + ), + ), + backgroundColor: AppColors.mainColor, + actionsList: [ + TextButton( + onPressed: logic.saveSpeechLanguageSettings, child: Text( - '跳过'.tr, + '保存'.tr, style: TextStyle( color: Colors.white, fontSize: 24.sp, @@ -48,23 +58,9 @@ class _LockVoiceSettingState extends State { ), ), ), - backgroundColor: AppColors.mainColor, - actionsList: [ - TextButton( - onPressed: logic.saveSpeechLanguageSettings, - child: Text( - '保存'.tr, - style: TextStyle( - color: Colors.white, - fontSize: 24.sp, - fontWeight: FontWeight.w500, - ), - ), - ), - ], - ), - body: _buildBody(), + ], ), + body: _buildBody(), ); } @@ -72,70 +68,99 @@ class _LockVoiceSettingState extends State { return Obx( () => SingleChildScrollView( child: Column( - children: _buildList(), + children: [ + Container( + width: 1.sw, + decoration: BoxDecoration(color: Colors.white), + child: ListView.builder( + itemCount: state.soundTypeList.length, + itemBuilder: (BuildContext context, int index) { + // 判断是否是最后一个元素(索引等于 itemCount - 1) + final isLastItem = index == state.soundTypeList.length - 1; + + // 获取当前平台数据(假设 platFormSet 是 RxList) + final platform = state.soundTypeList.value[index]; + return CommonItem( + leftTitel: state.soundTypeList.value[index], + rightTitle: '', + isHaveLine: !isLastItem, + // 最后一个元素不显示分割线(取反) + isHaveDirection: false, + isHaveRightWidget: true, + rightWidget: Radio( + // Radio 的值:使用平台的唯一标识(如 id) + value: platform, + // 当前选中的值:与 selectPlatFormIndex 关联的 id + groupValue: state.soundTypeList + .value[state.selectSoundTypeIndex.value], + // 选中颜色(可选,默认主题色) + activeColor: AppColors.mainColor, + // 点击 Radio 时回调(更新选中索引) + onChanged: (value) { + if (value != null) { + setState(() { + // 找到当前选中平台的索引(根据 id 匹配) + final newIndex = state.soundTypeList.value + .indexWhere((p) => p == value); + if (newIndex != -1) { + state.selectSoundTypeIndex.value = newIndex; + } + }); + } + }, + ), + action: () { + setState(() { + state.selectSoundTypeIndex.value = index; + }); + }, + ); + }, + shrinkWrap: true, + physics: const AlwaysScrollableScrollPhysics(), + ), + ), + SizedBox( + height: 8.h, + ), + Column( + children: _buildList(), + ), + ], ), ), ); } List _buildList() { - final languages = state.languages; + final appLocalLanguages = state.appLocalLanguages; return List.generate( - languages.length, - (index) => _buildItem(languages[index], index), + appLocalLanguages.length, + (index) => _buildItem( + appLocalLanguages[index], + index, + ), ); } - _buildItem(PassthroughItem language, int index) { - final timbres = language.timbres; - final isSelected = state.selectPassthroughListIndex == index; - return ExpansionTile( - title: Text( - PassthroughLangHelper.getLangText(language.lang), - style: TextStyle( - fontSize: 24.sp, - fontWeight: isSelected ? FontWeight.bold : null, - ), - ), - onExpansionChanged: (bool expanded) {}, - initiallyExpanded: false, - backgroundColor: Colors.white, - collapsedBackgroundColor: Colors.white, - expandedCrossAxisAlignment: CrossAxisAlignment.center, - expandedAlignment: Alignment.center, - shape: InputBorder.none, - maintainState: true, - // 去除展开状态下的边框 - collapsedShape: InputBorder.none, - // 去除折叠状态下的边框 - childrenPadding: EdgeInsets.only(left: 12.w), - children: List.generate( - timbres.length, - (int languageIndex) => ListTile( - title: Text( - timbres[languageIndex].name, - style: TextStyle( - fontSize: 22.sp, - fontWeight: - state.selectLanguageIndex == languageIndex && isSelected - ? FontWeight.bold - : null, - ), - ), - trailing: state.selectLanguageIndex == languageIndex && isSelected - ? Icon( - Icons.check_circle, - color: AppColors.mainColor, - ) // 仅当选中时显示图标 - : null, // 默认不显示 - onTap: () { - // 更新选中的语音包 - state.selectLanguageIndex.value = languageIndex; - // 更新选中的语言 - state.selectPassthroughListIndex.value = index; - }, // 默认图标, // 右侧的图标 - ), - ), + _buildItem(String appLocalLanguages, index) { + return CommonItem( + leftTitel: appLocalLanguages, + rightTitle: '', + isHaveLine: true, + isHaveDirection: false, + isHaveRightWidget: true, + rightWidget: state.selectPassthroughListIndex.value == index + ? Image( + image: const AssetImage('images/icon_item_checked.png'), + width: 30.w, + height: 30.w, + fit: BoxFit.contain, + ) + : Container(), + action: () { + state.selectPassthroughListIndex.value = index; + }, ); } diff --git a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart index e70c6b2a..15b73e01 100644 --- a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart +++ b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart @@ -3,6 +3,7 @@ import 'dart:typed_data'; import 'package:get/get.dart'; import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart'; import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart'; +import 'package:star_lock/translations/app_dept.dart'; class LockVoiceSettingState { LockVoiceSettingState() { @@ -17,6 +18,24 @@ class LockVoiceSettingState { + List get appLocalLanguages { + final locales = appDept.deptSupportedLocales; + + final languageCode = locales[1].languageCode; + final countryCode = locales[1].countryCode; + String localeStr = ''; + if (countryCode != null) { + localeStr = languageCode + '_' + countryCode; + appLocalLanguageCodes.add(localeStr); + } + + final list = locales + .map((e) => ExtensionLanguageType.fromLocale(e).lanTitle) + .toList(); + return list; + } + + List appLocalLanguageCodes = []; // 选中的语音包列表下标 RxInt selectPassthroughListIndex = 0.obs; @@ -43,5 +62,13 @@ class LockVoiceSettingState { // 分包发送进度(0.0~1.0) RxDouble progress = 0.0.obs; + // 响应式字符串集合(自动触发 UI 更新) + final RxList soundTypeList = List.of({ + '男声'.tr, + '女声'.tr, + }).obs; + RxInt selectSoundTypeIndex = 0.obs; + RxString tempLangStr=''.obs; + RxString tempTimbreStr=''.obs; } From ba2eac4cee0d80233a45a11fdeaad4a4212dd671 Mon Sep 17 00:00:00 2001 From: liyi Date: Fri, 25 Jul 2025 15:00:07 +0800 Subject: [PATCH 15/25] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E7=AC=AC=E4=B8=89?= =?UTF-8?q?=E6=96=B9=E5=B9=B3=E5=8F=B0=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../third_party_platform_logic.dart | 13 +++- .../third_party_platform_page.dart | 67 ++++++++++--------- .../third_party_platform_state.dart | 8 ++- 3 files changed, 55 insertions(+), 33 deletions(-) diff --git a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart index b73156e2..b34b4995 100644 --- a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart +++ b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart @@ -1,8 +1,19 @@ +import 'package:get/get.dart'; import 'package:star_lock/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart'; +import 'package:star_lock/tools/baseGetXController.dart'; -class ThirdPartyPlatformLogic { +class ThirdPartyPlatformLogic extends BaseGetXController { ThirdPartyPlatformState state = ThirdPartyPlatformState(); void savePlatFormSetting() { + // showEasyLoading(); + // showToast('功能暂未开放'.tr); + // dismissEasyLoading(); + } + + @override + void dispose() { + dismissEasyLoading(); + super.dispose(); } } diff --git a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_page.dart b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_page.dart index 6d7d1919..da90cd82 100644 --- a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_page.dart +++ b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_page.dart @@ -5,6 +5,7 @@ import 'package:get/get.dart'; import 'package:star_lock/app_settings/app_colors.dart'; import 'package:star_lock/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart'; import 'package:star_lock/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart'; +import 'package:star_lock/tools/commonItem.dart'; import 'package:star_lock/tools/titleAppBar.dart'; class ThirdPartyPlatformPage extends StatefulWidget { @@ -48,41 +49,45 @@ class _ThirdPartyPlatformPageState extends State { return ListView.builder( itemCount: state.platFormSet.length, itemBuilder: (BuildContext context, int index) { - return InkWell( - onTap: () { + // 判断是否是最后一个元素(索引等于 itemCount - 1) + final isLastItem = index == state.platFormSet.length - 1; + + // 获取当前平台数据(假设 platFormSet 是 RxList) + final platform = state.platFormSet.value[index]; + return CommonItem( + leftTitel: state.platFormSet.value[index], + rightTitle: '', + isHaveLine: !isLastItem, + // 最后一个元素不显示分割线(取反) + isHaveDirection: false, + isHaveRightWidget: true, + rightWidget: Radio( + // Radio 的值:使用平台的唯一标识(如 id) + value: platform, + // 当前选中的值:与 selectPlatFormIndex 关联的 id + groupValue: + state.platFormSet.value[state.selectPlatFormIndex.value], + // 选中颜色(可选,默认主题色) + activeColor: AppColors.mainColor, + // 点击 Radio 时回调(更新选中索引) + onChanged: (value) { + if (value != null) { + setState(() { + // 找到当前选中平台的索引(根据 id 匹配) + final newIndex = + state.platFormSet.value.indexWhere((p) => p == value); + if (newIndex != -1) { + state.selectPlatFormIndex.value = newIndex; + } + }); + } + }, + ), + action: () { setState(() { state.selectPlatFormIndex.value = index; }); }, - child: Container( - width: 1.sw, - padding: EdgeInsets.symmetric( - vertical: 12.h, - horizontal: 24.w, - ), - decoration: BoxDecoration( - color: Colors.white, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - state.platFormSet[index], - style: TextStyle( - wordSpacing: 2.w, - ), - ), - Visibility( - visible: state.selectPlatFormIndex.value == index, - child: Icon( - Icons.check_circle, - color: AppColors.mainColor, - size: 30.sp, - ), - ), - ], - ), - ), ); }, shrinkWrap: true, diff --git a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart index 65bc92b8..325b8ba1 100644 --- a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart +++ b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart @@ -1,5 +1,8 @@ +import 'dart:ui'; + import 'package:get/get.dart'; import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart'; +import 'package:star_lock/translations/app_dept.dart'; class ThirdPartyPlatformState { ThirdPartyPlatformState() { @@ -11,8 +14,11 @@ class ThirdPartyPlatformState { // 响应式字符串集合(自动触发 UI 更新) final RxList platFormSet = List.of({ + '锁通通'.tr, '涂鸦智能'.tr, }).obs; - RxInt selectPlatFormIndex = 999.obs; + RxInt selectPlatFormIndex = 0.obs; + + } From 42d1ea52d4db3adb0f6aec1fe1d0804029c53560 Mon Sep 17 00:00:00 2001 From: liyi Date: Fri, 25 Jul 2025 15:00:29 +0800 Subject: [PATCH 16/25] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E7=AC=AC=E4=B8=89?= =?UTF-8?q?=E6=96=B9=E5=B9=B3=E5=8F=B0=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lockSet/thirdPartyPlatform/third_party_platform_logic.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart index b34b4995..ddd118a4 100644 --- a/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart +++ b/lib/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart @@ -7,7 +7,7 @@ class ThirdPartyPlatformLogic extends BaseGetXController { void savePlatFormSetting() { // showEasyLoading(); - // showToast('功能暂未开放'.tr); + showToast('功能待开放'.tr); // dismissEasyLoading(); } From b8fd34c23231825ef8a0f1df9c3b83318a0b4dcf Mon Sep 17 00:00:00 2001 From: liyi Date: Fri, 25 Jul 2025 17:10:20 +0800 Subject: [PATCH 17/25] =?UTF-8?q?fix:=E8=B7=B3=E8=BD=AC=E8=AF=AD=E9=9F=B3?= =?UTF-8?q?=E5=8C=85=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lock_voice_setting_page.dart | 57 ++++++++++--------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart index 4b6a3ace..3b0c83b3 100644 --- a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart +++ b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart @@ -26,31 +26,22 @@ class _LockVoiceSettingState extends State { @override Widget build(BuildContext context) { - return Scaffold( - backgroundColor: AppColors.mainBackgroundColor, - appBar: TitleAppBar( - barTitle: '锁语音包设置'.tr, - haveBack: false, - haveOtherLeftWidget: true, - leftWidget: TextButton( - onPressed: () { - Get.offAllNamed(Routers.starLockMain); - }, - child: Text( - '跳过'.tr, - style: TextStyle( - color: Colors.white, - fontSize: 24.sp, - fontWeight: FontWeight.w500, - ), - ), - ), - backgroundColor: AppColors.mainColor, - actionsList: [ - TextButton( - onPressed: logic.saveSpeechLanguageSettings, + return WillPopScope( + onWillPop: () async { + return false; + }, + child: Scaffold( + backgroundColor: AppColors.mainBackgroundColor, + appBar: TitleAppBar( + barTitle: '锁语音包设置'.tr, + haveBack: false, + haveOtherLeftWidget: true, + leftWidget: TextButton( + onPressed: () { + Get.offAllNamed(Routers.starLockMain); + }, child: Text( - '保存'.tr, + '跳过'.tr, style: TextStyle( color: Colors.white, fontSize: 24.sp, @@ -58,9 +49,23 @@ class _LockVoiceSettingState extends State { ), ), ), - ], + backgroundColor: AppColors.mainColor, + actionsList: [ + TextButton( + onPressed: logic.saveSpeechLanguageSettings, + child: Text( + '保存'.tr, + style: TextStyle( + color: Colors.white, + fontSize: 24.sp, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + body: _buildBody(), ), - body: _buildBody(), ); } From f7199fdc981fd99b7c31ae7fd7081b047e4e7032 Mon Sep 17 00:00:00 2001 From: liyi Date: Sat, 26 Jul 2025 16:11:58 +0800 Subject: [PATCH 18/25] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E5=A4=9A=E5=9B=BD?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E8=AF=8D=E6=9D=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lan/lan_ar.json | 8 +- lan/lan_bg.json | 9 +- lan/lan_bn.json | 9 +- lan/lan_cs.json | 9 +- lan/lan_da.json | 9 +- lan/lan_de.json | 9 +- lan/lan_el.json | 9 +- lan/lan_en.json | 8 +- lan/lan_es.json | 9 +- lan/lan_et.json | 9 +- lan/lan_fi.json | 9 +- lan/lan_fr.json | 9 +- lan/lan_he.json | 9 +- lan/lan_hi.json | 9 +- lan/lan_hk.json | 9 +- lan/lan_hr.json | 9 +- lan/lan_hu.json | 9 +- lan/lan_hy.json | 9 +- lan/lan_id.json | 9 +- lan/lan_it.json | 9 +- lan/lan_ja.json | 9 +- lan/lan_ka.json | 9 +- lan/lan_keys.json | 7 +- lan/lan_kk.json | 9 +- lan/lan_ko.json | 9 +- lan/lan_lt.json | 9 +- lan/lan_ms.json | 9 +- lan/lan_nl.json | 9 +- lan/lan_pl.json | 9 +- lan/lan_pt.json | 9 +- lan/lan_ro.json | 9 +- lan/lan_ru.json | 9 +- lan/lan_sk.json | 9 +- lan/lan_sr_cyrl.json | 9 +- lan/lan_sv.json | 9 +- lan/lan_th.json | 9 +- lan/lan_tr.json | 9 +- lan/lan_tw.json | 9 +- lan/lan_uk.json | 9 +- lan/lan_ur.json | 9 +- lan/lan_vi.json | 9 +- lan/lan_zh.json | 7 +- .../lockDetail/passthrough_item.dart | 8 +- .../lockSet/lockSet/lockSet_logic.dart | 55 +----- .../lockSet/lockSet/lockSet_page.dart | 2 +- .../speech_language_settings_logic.dart | 162 ++++++++---------- .../speech_language_settings_page.dart | 8 +- .../speech_language_settings_state.dart | 17 -- .../lock_voice_setting_logic.dart | 155 +++++++---------- .../lock_voice_setting_page.dart | 11 +- .../lock_voice_setting_state.dart | 20 +-- 51 files changed, 483 insertions(+), 327 deletions(-) diff --git a/lan/lan_ar.json b/lan/lan_ar.json index 13ff3453..edaa6c96 100644 --- a/lan/lan_ar.json +++ b/lan/lan_ar.json @@ -1153,5 +1153,11 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. تمكين وظيفة الفتح عن بعد للقفل في APP (يتم إيقاف هذه الوظيفة بشكل افتراضي). إذا كان هذا الخيار غير متاح، لن يدعم القفل جوجل هوم", "3.安装Google Home APP,点击左上角的加号按钮": "3. قم بتثبيت تطبيق Google Home وانقر فوق الزر زائد في الزاوية العلوية اليسرى", "暂无最新记录": "لا توجد حاليا أحدث السجلات المتاحة", - "请将手机切换至2.4G WiFi进行手动连接": "الرجاء تحويل هاتفك إلى \"واي فاي 2.4\" للاتصال اليدوي" + "请将手机切换至2.4G WiFi进行手动连接": "الرجاء تحويل هاتفك إلى \"واي فاي 2.4\" للاتصال اليدوي", + "第三方平台设置": "الطرف الثالث منصة الإعداد", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "قفل مجموعة صوت", + "(中国台湾)": "(中国台湾)", + "男声": "ذكر صوت", + "女声": "صوت بنات" } \ No newline at end of file diff --git a/lan/lan_bg.json b/lan/lan_bg.json index 8f3f1831..ac8022fe 100644 --- a/lan/lan_bg.json +++ b/lan/lan_bg.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Активирайте функцията за дистанционно отключване на ключалката в приложението (тази функция е изключена по подразбиране). Ако тази опция не е налице, заключването няма да поддържа Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. Инсталирайте приложението Google Home и щракнете върху бутона плюс в горния ляв ъгъл", "暂无最新记录": "В момента няма най-новите налични записи", - "请将手机切换至2.4G WiFi进行手动连接": "Моля, превключете телефона си на 2.4G WiFi за ръчно свързване" + "请将手机切换至2.4G WiFi进行手动连接": "Моля, превключете телефона си на 2.4G WiFi за ръчно свързване", + "语音包设置": "Настройки на гласовите пакети", + "第三方平台设置": "Настройки на платформи на трети страни", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Заключване на настройките на гласовия пакет", + "(中国台湾)": "(中国台湾)", + "男声": "Мъжки глас", + "女声": "Женски глас" } \ No newline at end of file diff --git a/lan/lan_bn.json b/lan/lan_bn.json index b2eb7414..a1efaa72 100644 --- a/lan/lan_bn.json +++ b/lan/lan_bn.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. অ্যাপে লকের রিমোট আনলকিং ফাংশন সক্ষম করুন (এই ফাংশনটি ডিফল্টরূপে বন্ধ রয়েছে)। যদি এই বিকল্পটি উপলভ্য না হয় তবে লকটি গুগল হোম সমর্থন করবে না", "3.安装Google Home APP,点击左上角的加号按钮": "গুগল হোম অ্যাপ্লিকেশনটি ইনস্টল করুন এবং উপরের বাম কোণে প্লাস বোতামটি ক্লিক করুন", "暂无最新记录": "বর্তমানে কোনও সাম্প্রতিকতম রেকর্ড সুলভ নেই", - "请将手机切换至2.4G WiFi进行手动连接": "ম্যানুয়াল সংযোগের জন্য দয়া করে আপনার ফোনটি 2.4 জি ওয়াইফাইতে স্যুইচ করুন" + "请将手机切换至2.4G WiFi进行手动连接": "ম্যানুয়াল সংযোগের জন্য দয়া করে আপনার ফোনটি 2.4 জি ওয়াইফাইতে স্যুইচ করুন", + "语音包设置": "ভয়েস প্যাকেজ সেটিংস", + "第三方平台设置": "তৃতীয় পক্ষের প্ল্যাটফর্ম সেটিংস", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "ভয়েস প্যাকেজ সেটিংস লক করুন", + "(中国台湾)": "(中国台湾)", + "男声": "পুরুষের কণ্ঠ", + "女声": "নারী কণ্ঠ" } \ No newline at end of file diff --git a/lan/lan_cs.json b/lan/lan_cs.json index 6c3889e7..27fbd5b3 100644 --- a/lan/lan_cs.json +++ b/lan/lan_cs.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Povolte funkci dálkového odemykání zámku v APP (tato funkce je ve výchozím nastavení vypnutá). Pokud tato možnost není k dispozici, zámek nebude podporovat Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. Nainstalujte aplikaci Google Home a klikněte na tlačítko plus v levém horním rohu", "暂无最新记录": "Momentálně nejsou k dispozici žádné nejnovější záznamy", - "请将手机切换至2.4G WiFi进行手动连接": "Přepněte prosím svůj telefon na 2.4G WiFi pro ruční připojení" + "请将手机切换至2.4G WiFi进行手动连接": "Přepněte prosím svůj telefon na 2.4G WiFi pro ruční připojení", + "语音包设置": "Nastavení hlasového balíčku", + "第三方平台设置": "Nastavení platformy třetích stran", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Zamknout nastavení hlasového balíčku", + "(中国台湾)": "(中国台湾)", + "男声": "Mužský hlas", + "女声": "Ženský hlas" } \ No newline at end of file diff --git a/lan/lan_da.json b/lan/lan_da.json index 8982bdfa..b76a4fc6 100644 --- a/lan/lan_da.json +++ b/lan/lan_da.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Aktiver fjernoplåsningsfunktionen for låsen i APP'en (denne funktion er slået fra som standard). Hvis denne mulighed ikke er tilgængelig, understøtter låsen ikke Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. Installer Google Home-appen, og klik på plusknappen i øverste venstre hjørne", "暂无最新记录": "Der er i øjeblikket ingen nyeste optegnelser tilgængelige", - "请将手机切换至2.4G WiFi进行手动连接": "Skift venligst din telefon til 2.4G WiFi for manuel forbindelse" + "请将手机切换至2.4G WiFi进行手动连接": "Skift venligst din telefon til 2.4G WiFi for manuel forbindelse", + "语音包设置": "Indstillinger af stemmepakke", + "第三方平台设置": "Indstillinger af tredjepartsplatforme", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Lås stemmepakkeindstillinger", + "(中国台湾)": "(中国台湾)", + "男声": "Mandlige stemmer", + "女声": "Kvindelige stemmer" } \ No newline at end of file diff --git a/lan/lan_de.json b/lan/lan_de.json index 5954553f..0348fcdf 100644 --- a/lan/lan_de.json +++ b/lan/lan_de.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Entsichern in einer APP, die ein schloss öffnet (standard abschalten) Wenn diese option nicht verfügbar ist, wird das schloss google nicht unterstützen", "3.安装Google Home APP,点击左上角的加号按钮": "3. Installiert die google-app und klicken auf den knopf hinzufügen in der oberen linken ecke", "暂无最新记录": "Wir haben keine neuen daten", - "请将手机切换至2.4G WiFi进行手动连接": "Wenn manuelle verbindung hergestellt wird, schalten sie das handy auf 2,4 G WiFi" + "请将手机切换至2.4G WiFi进行手动连接": "Wenn manuelle verbindung hergestellt wird, schalten sie das handy auf 2,4 G WiFi", + "语音包设置": "Sprachpaketeinstellungen", + "第三方平台设置": "Einstellungen von Drittanbieterplattformen", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Sperren von Sprachpaketeinstellungen", + "(中国台湾)": "(中国台湾)", + "男声": "Männliche Stimme", + "女声": "Frauenstimme" } \ No newline at end of file diff --git a/lan/lan_el.json b/lan/lan_el.json index 0d416138..b9867673 100644 --- a/lan/lan_el.json +++ b/lan/lan_el.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Ενεργοποιήστε τη λειτουργία απομακρυσμένου ξεκλειδώματος της κλειδαριάς στην εφαρμογή (αυτή η λειτουργία είναι απενεργοποιημένη από προεπιλογή). Εάν αυτή η επιλογή δεν είναι διαθέσιμη, το κλείδωμα δεν θα υποστηρίζει το Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. Εγκαταστήστε την εφαρμογή Google Home και κάντε κλικ στο κουμπί συν στην επάνω αριστερή γωνία", "暂无最新记录": "Προς το παρόν δεν υπάρχουν διαθέσιμες τελευταίες εγγραφές", - "请将手机切换至2.4G WiFi进行手动连接": "Αλλάξτε το τηλέφωνό σας σε 2.4G WiFi για χειροκίνητη σύνδεση" + "请将手机切换至2.4G WiFi进行手动连接": "Αλλάξτε το τηλέφωνό σας σε 2.4G WiFi για χειροκίνητη σύνδεση", + "语音包设置": "Ρυθμίσεις πακέτου φωνής", + "第三方平台设置": "Ρυθμίσεις πλατφόρμας τρίτων", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Ρυθμίσεις κλειδώματος πακέτου φωνής", + "(中国台湾)": "(中国台湾)", + "男声": "Ανδρική φωνή", + "女声": "Γυναικεία φωνή" } \ No newline at end of file diff --git a/lan/lan_en.json b/lan/lan_en.json index 2e60a8c3..b6c9f65a 100644 --- a/lan/lan_en.json +++ b/lan/lan_en.json @@ -1160,5 +1160,11 @@ "需要相机权限": "Camera permission required", "此功能的开启和关闭只能在锁附近通过手机蓝牙进行": "The activation and deactivation of this feature can only be done through Bluetooth on the phone near the lock", "网关添加成功": "Gateway added successfully", - "语音包设置": "Voice packet settings" + "语音包设置": "Voice packet settings", + "第三方平台设置": "Third party platform settings", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Lock voice package settings", + "(中国台湾)": "(中国台湾)", + "男声": "male voice", + "女声": "female voice" } diff --git a/lan/lan_es.json b/lan/lan_es.json index e5fe58a3..4e83680c 100644 --- a/lan/lan_es.json +++ b/lan/lan_es.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Habilitar la función de desbloqueo remoto del bloqueo en la aplicación (esta función se desactiva por defecto). Si esta opción no está disponible, el bloqueo no será compatible con Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. Instale la aplicación de Google Home y haga clic en el botón más en la esquina superior izquierda", "暂无最新记录": "Actualmente no hay registros más recientes disponibles", - "请将手机切换至2.4G WiFi进行手动连接": "Por favor cambia tu teléfono a 2.4G WiFi para la conexión manual" + "请将手机切换至2.4G WiFi进行手动连接": "Por favor cambia tu teléfono a 2.4G WiFi para la conexión manual", + "语音包设置": "Configuración del paquete de voz", + "第三方平台设置": "Configuración de la Plataforma de terceros", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Configuración del paquete de voz de bloqueo", + "(中国台湾)": "(中国台湾)", + "男声": "Voz masculina", + "女声": "Voz femenina" } \ No newline at end of file diff --git a/lan/lan_et.json b/lan/lan_et.json index 0cafa914..7447f012 100644 --- a/lan/lan_et.json +++ b/lan/lan_et.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Lubage rakenduses APP luku kaugavamise funktsioon (see funktsioon on vaikimisi välja lülitatud). Kui see valik pole saadaval, ei toeta lukk Google Home'i", "3.安装Google Home APP,点击左上角的加号按钮": "3. Installige rakendus Google Home ja klõpsake vasakus ülanurgas plussnuppu", "暂无最新记录": "Praegu pole uusimaid andmeid saadaval", - "请将手机切换至2.4G WiFi进行手动连接": "Käsitsi ühendamiseks lülitage telefon 2.4G WiFi-le" + "请将手机切换至2.4G WiFi进行手动连接": "Käsitsi ühendamiseks lülitage telefon 2.4G WiFi-le", + "语音包设置": "Häälepaketi seadistused", + "第三方平台设置": "Kolmanda osapoole platvormi seaded", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Lukustage häälepaketi seaded", + "(中国台湾)": "(中国台湾)", + "男声": "Meeste hääl", + "女声": "Naiste hääl" } \ No newline at end of file diff --git a/lan/lan_fi.json b/lan/lan_fi.json index 8176e263..46d37502 100644 --- a/lan/lan_fi.json +++ b/lan/lan_fi.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Ota lukon etälukituksen avaustoiminto käyttöön APP:ssa (tämä toiminto on oletuksena pois päältä). Jos tämä vaihtoehto ei ole käytettävissä, lukko ei tue Google Homea", "3.安装Google Home APP,点击左上角的加号按钮": "3. Asenna Google Home -sovellus ja napsauta vasemmassa yläkulmassa olevaa pluspainiketta", "暂无最新记录": "Viimeisimpiä tietoja ei ole tällä hetkellä saatavilla", - "请将手机切换至2.4G WiFi进行手动连接": "Vaihda puhelimesi 2.4G WiFi-verkkoon manuaalista yhteyttä varten" + "请将手机切换至2.4G WiFi进行手动连接": "Vaihda puhelimesi 2.4G WiFi-verkkoon manuaalista yhteyttä varten", + "语音包设置": "Äänipaketin asetukset", + "第三方平台设置": "Kolmannen osapuolen alustan asetukset", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Lukitse äänipaketin asetukset", + "(中国台湾)": "(中国台湾)", + "男声": "Miehen ääni", + "女声": "Naisten ääni" } \ No newline at end of file diff --git a/lan/lan_fr.json b/lan/lan_fr.json index db76ec5a..4430ef1f 100644 --- a/lan/lan_fr.json +++ b/lan/lan_fr.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Activez la fonction de déverrouillage à distance de la serrure dans l’application (cette fonction est désactivée par défaut). Si cette option n’est pas disponible, le verrou ne prendra pas en charge Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. Installez l’application Google Home et cliquez sur le bouton plus dans le coin supérieur gauche", "暂无最新记录": "Il n’y a actuellement aucun dernier enregistrement disponible", - "请将手机切换至2.4G WiFi进行手动连接": "Veuillez passer votre téléphone à 2.4G WiFi pour une connexion manuelle" + "请将手机切换至2.4G WiFi进行手动连接": "Veuillez passer votre téléphone à 2.4G WiFi pour une connexion manuelle", + "语音包设置": "Paramètres du pack vocal", + "第三方平台设置": "Paramètres de plate - forme tierce", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Paramètres du pack Lock Voice", + "(中国台湾)": "(中国台湾)", + "男声": "Voix masculine", + "女声": "Voix de femmes" } \ No newline at end of file diff --git a/lan/lan_he.json b/lan/lan_he.json index 2ba7d747..230e3a86 100644 --- a/lan/lan_he.json +++ b/lan/lan_he.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. הפעל את פונקציית ביטול הנעילה מרחוק של המנעול באפליקציה (פונקציה זו כבויה כברירת מחדל). אם אפשרות זו אינה זמינה, המנעול לא יתמוך ב-Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. התקן את אפליקציית Google Home ולחץ על כפתור הפלוס בפינה השמאלית העליונה", "暂无最新记录": "אין כרגע רשומות עדכניות זמינות", - "请将手机切换至2.4G WiFi进行手动连接": "אנא העבר את הטלפון שלך ל- WiFi 2.4G לחיבור ידני" + "请将手机切换至2.4G WiFi进行手动连接": "אנא העבר את הטלפון שלך ל- WiFi 2.4G לחיבור ידני", + "语音包设置": "הגדרות חבילת קול", + "第三方平台设置": "הגדרות פלטפורמות של צד שלישי", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "הגדרות חבילת קול לנעול", + "(中国台湾)": "(中国台湾)", + "男声": "קול גבר", + "女声": "קול נשי" } \ No newline at end of file diff --git a/lan/lan_hi.json b/lan/lan_hi.json index 8e2a9118..766c91ef 100644 --- a/lan/lan_hi.json +++ b/lan/lan_hi.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. एप्लिकेशन में लॉक का रिमोट अनलॉकिंग फ़ंक्शन सक्षम करें (यह फ़ंक्शन डिफ़ॉल्ट रूप से बंद है). यदि यह विकल्प उपलब्ध नहीं है, तो लॉक आपके गूगल होम को सपोर्ट नहीं करेगा।", "3.安装Google Home APP,点击左上角的加号按钮": "3. गूगल होम ऐप को इंस्टॉल करें और ऊपरी बाएं कोने में प्लस बटन पर क्लिक करें।", "暂无最新记录": "वर्तमान में कोई नवीनतम रिकॉर्ड उपलब्ध नहीं हैं", - "请将手机切换至2.4G WiFi进行手动连接": "मैन्युअल कनेक्शन के लिए कृपया अपना फोन 2.4 जी वाईफ़ाई पर स्विच करें।" + "请将手机切换至2.4G WiFi进行手动连接": "मैन्युअल कनेक्शन के लिए कृपया अपना फोन 2.4 जी वाईफ़ाई पर स्विच करें।", + "语音包设置": "आवाज पैकेज सेटिंग्स", + "第三方平台设置": "तृतीय पक्ष मंच सेटिंग्स", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "आवाज पैकेज सेटिंग्स ताला लगाएँ", + "(中国台湾)": "(中国台湾)", + "男声": "पुरुष आवाज", + "女声": "महिला आवाज" } \ No newline at end of file diff --git a/lan/lan_hk.json b/lan/lan_hk.json index b13dacc9..4e21afc2 100644 --- a/lan/lan_hk.json +++ b/lan/lan_hk.json @@ -1154,5 +1154,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2.喺APP中開啟鎖嘅遠程解鎖功能(此功能默認關閉)。 如果此選項不可用,則鎖將唔撐Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3.安裝Google Home應用,點擊左上角嘅加號掣", "暂无最新记录": "目前冇可用嘅最新記錄", - "请将手机切换至2.4G WiFi进行手动连接": "請把手機切換到2.4G WiFi進行手動連接" + "请将手机切换至2.4G WiFi进行手动连接": "請把手機切換到2.4G WiFi進行手動連接", + "语音包设置": "語音包設定", + "第三方平台设置": "協力廠商領獎臺設定", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "鎖語音包設定", + "(中国台湾)": "(中国台湾)", + "男声": "男聲", + "女声": "女聲" } \ No newline at end of file diff --git a/lan/lan_hr.json b/lan/lan_hr.json index 0393309c..00dfc10c 100644 --- a/lan/lan_hr.json +++ b/lan/lan_hr.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Omogućite funkciju daljinskog otključavanja brave u APP-u (ova je funkcija prema zadanim postavkama isključena). Ako ova opcija nije dostupna, zaključavanje neće podržavati Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. Instalirajte aplikaciju Google Home i kliknite gumb plus u gornjem lijevom kutu", "暂无最新记录": "Trenutno nema dostupnih najnovijih podataka", - "请将手机切换至2.4G WiFi进行手动连接": "Prebacite telefon na 2.4G WiFi za ručno povezivanje" + "请将手机切换至2.4G WiFi进行手动连接": "Prebacite telefon na 2.4G WiFi za ručno povezivanje", + "语音包设置": "Postavke glasovnog paketa", + "第三方平台设置": "Postavljanje podiuma treće strane", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Postavke zaključavanja glasovnog paketa", + "(中国台湾)": "(中国台湾)", + "男声": "Muški glas", + "女声": "Ženski glas" } \ No newline at end of file diff --git a/lan/lan_hu.json b/lan/lan_hu.json index f49cf759..9d160938 100644 --- a/lan/lan_hu.json +++ b/lan/lan_hu.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Engedélyezze a zár távoli feloldási funkcióját az APP-ban (ez a funkció alapértelmezés szerint ki van kapcsolva). Ha ez az opció nem érhető el, a zár nem támogatja a Google Home szolgáltatást", "3.安装Google Home APP,点击左上角的加号按钮": "3. Telepítse a Google Home alkalmazást, és kattintson a plusz gombra a bal felső sarokban", "暂无最新记录": "Jelenleg nem állnak rendelkezésre legfrissebb rekordok", - "请将手机切换至2.4G WiFi进行手动连接": "Kérjük, kapcsolja át telefonját 2.4G WiFi-re a kézi csatlakozáshoz" + "请将手机切换至2.4G WiFi进行手动连接": "Kérjük, kapcsolja át telefonját 2.4G WiFi-re a kézi csatlakozáshoz", + "语音包设置": "Hangcsomag beállításai", + "第三方平台设置": "Harmadik fél platformjának beállítása", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Hangcsomag zárolási beállításai", + "(中国台湾)": "(中国台湾)", + "男声": "Férfi hang", + "女声": "női hang" } \ No newline at end of file diff --git a/lan/lan_hy.json b/lan/lan_hy.json index b1fe549f..e64c57d8 100644 --- a/lan/lan_hy.json +++ b/lan/lan_hy.json @@ -1159,5 +1159,12 @@ "请确认后再继续": "Խնդրում ենք հաստատել շարունակելուց առաջ", "需要相机权限": "Պահանջվում է տեսախցիկի թույլտվություն", "此功能的开启和关闭只能在锁附近通过手机蓝牙进行": "Այս գործառույթի ակտիվացումը եւ ապաակտիվացումը կարելի է կատարել միայն կողպեքի մոտ գտնվող հեռախոսի Bluetooth-ի միջոցով", - "网关添加成功": "Gateway հաջողությամբ ավելացվել է" + "网关添加成功": "Gateway հաջողությամբ ավելացվել է", + "语音包设置": "Ձայնային փաթեթի պարամետրեր", + "第三方平台设置": "Երրորդ կողմի հարթակի կարգավորումներ", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Փակել ձայնային փաթեթի պարամետրերը", + "(中国台湾)": "(中国台湾)", + "男声": "տղամարդկանց ձայն", + "女声": "կանանց ձայն" } \ No newline at end of file diff --git a/lan/lan_id.json b/lan/lan_id.json index 5a5ff0a2..8ce5e598 100644 --- a/lan/lan_id.json +++ b/lan/lan_id.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Aktifkan fungsi kunci pengunci jarak jauh di aplikasi (fungsi ini dimatikan secara standar). Jika opsi ini tidak tersedia, kunci tidak akan mendukung Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. Instal aplikasi Google Home dan klik tombol plus di sudut kiri atas", "暂无最新记录": "Saat ini tidak ada catatan terbaru yang tersedia", - "请将手机切换至2.4G WiFi进行手动连接": "Silahkan beralih ke 2.4G WiFi untuk koneksi manual" + "请将手机切换至2.4G WiFi进行手动连接": "Silahkan beralih ke 2.4G WiFi untuk koneksi manual", + "语音包设置": "Pengaturan paket suara", + "第三方平台设置": "Platform pihak ketiga diatur", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Mengunci paket suara", + "(中国台湾)": "(中国台湾)", + "男声": "6 tahun sebelumnya", + "女声": "Suara wanita" } \ No newline at end of file diff --git a/lan/lan_it.json b/lan/lan_it.json index 8bbf6061..3662ffaa 100644 --- a/lan/lan_it.json +++ b/lan/lan_it.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Abilita la funzione di sblocco remoto del lock nella APP (questa funzione è disattivata in modo predefinito). Se questa opzione non è disponibile, il lock non supporta Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. Installa l’applicazione Home di Google e fai clic sul pulsante più nell’angolo in alto a sinistra", "暂无最新记录": "Attualmente non sono disponibili dati più recenti", - "请将手机切换至2.4G WiFi进行手动连接": "Passa il telefono a 2,4g WiFi per la connessione manuale" + "请将手机切换至2.4G WiFi进行手动连接": "Passa il telefono a 2,4g WiFi per la connessione manuale", + "语音包设置": "Impostazioni pacchetto vocalea", + "第三方平台设置": "Impostazioni di piattaforme di terze parti", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Impostazioni pacchetto vocale blocco", + "(中国台湾)": "(中国台湾)", + "男声": "voce maschile", + "女声": "voce femminile" } \ No newline at end of file diff --git a/lan/lan_ja.json b/lan/lan_ja.json index 3ceaab59..9499d560 100644 --- a/lan/lan_ja.json +++ b/lan/lan_ja.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. アプリでロックのリモートロック解除機能を有効にします(この機能はデフォルトでオフになっています)。このオプションが利用できない場合、ロックはgoogle homeをサポートしません", "3.安装Google Home APP,点击左上角的加号按钮": "3. google homeアプリをインストールし、左上隅のプラスボタンをクリックします", "暂无最新记录": "最新の記録は残っていない", - "请将手机切换至2.4G WiFi进行手动连接": "手動接続のため、携帯電話を2.4 g wifiに切り替えてください" + "请将手机切换至2.4G WiFi进行手动连接": "手動接続のため、携帯電話を2.4 g wifiに切り替えてください", + "语音包设置": "ボイスパックの設定", + "第三方平台设置": "サードパーティ製プラットフォームの設定", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "ロック音声パケット設定", + "(中国台湾)": "(中国台湾)", + "男声": "男声", + "女声": "女声" } \ No newline at end of file diff --git a/lan/lan_ka.json b/lan/lan_ka.json index f7ee8e99..e370fea9 100644 --- a/lan/lan_ka.json +++ b/lan/lan_ka.json @@ -1159,5 +1159,12 @@ "请确认后再继续": "გაგრძელებამდე გთხოვთ დაადასტუროთ", "需要相机权限": "კამერის ნებართვა საჭიროა", "此功能的开启和关闭只能在锁附近通过手机蓝牙进行": "ამ ფუნქციის გააქტიურება და დეაქტივაცია შეიძლება გაკეთდეს მხოლოდ Bluetooth– ის საშუალებით ტელეფონით დაბლოკვის მახლობლად", - "网关添加成功": "კარიბჭე წარმატებით დაემატა" + "网关添加成功": "კარიბჭე წარმატებით დაემატა", + "语音包设置": "ხმის პაკეტის პარამეტრები", + "第三方平台设置": "მესამე მხარის პლატფორმის პარამეტრები", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "ხმის პაკეტის პარამეტრები", + "(中国台湾)": "(中国台湾)", + "男声": "მამაკაცის ხმა", + "女声": "ქალის ხმა" } \ No newline at end of file diff --git a/lan/lan_keys.json b/lan/lan_keys.json index 9f4edfab..f695a426 100755 --- a/lan/lan_keys.json +++ b/lan/lan_keys.json @@ -1165,5 +1165,10 @@ "需要相机权限": "需要相机权限", "此功能的开启和关闭只能在锁附近通过手机蓝牙进行": "此功能的开启和关闭只能在锁附近通过手机蓝牙进行", "网关添加成功": "网关添加成功", - "语音包设置": "语音包设置", + "第三方平台设置": "第三方平台设置", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "锁语音包设置", + "(中国台湾)": "(中国台湾)", + "男声": "男声", + "女声": "女声" } diff --git a/lan/lan_kk.json b/lan/lan_kk.json index 4fa1cffd..3b4f69ed 100644 --- a/lan/lan_kk.json +++ b/lan/lan_kk.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. APP бағдарламасында құлыпты қашықтан ашу функциясын қосу (бұл функция әдепкі бойынша өшіріледі). Егер бұл параметр қол жетімді болмаса, бұғаттау Google Home-ды қолдамайды", "3.安装Google Home APP,点击左上角的加号按钮": "3. Google Home бағдарламасын орнатып, жоғарғы сол жақ бұрыштағы қосу түймешігін басыңыз", "暂无最新记录": "Қазіргі уақытта қол жетімді соңғы жазбалар жоқ", - "请将手机切换至2.4G WiFi进行手动连接": "Телефонды қолмен қосу үшін 2.4G WiFi бағдарламасына ауыстыруыңызды сұраймыз" + "请将手机切换至2.4G WiFi进行手动连接": "Телефонды қолмен қосу үшін 2.4G WiFi бағдарламасына ауыстыруыңызды сұраймыз", + "语音包设置": "Дауыстық бума параметрлері", + "第三方平台设置": "Үшінші тарап платформасының параметрлері", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Дауыстық бума параметрлерін құлыптау", + "(中国台湾)": "(中国台湾)", + "男声": "ер дауысы", + "女声": "Әйел дауысы" } \ No newline at end of file diff --git a/lan/lan_ko.json b/lan/lan_ko.json index 8e6b36a6..46580f02 100644 --- a/lan/lan_ko.json +++ b/lan/lan_ko.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. 앱에서 잠금의 원격 잠금 해제 기능을 활성화합니다 (이 기능은 기본적으로 꺼져 있습니다).이 옵션을 사용할 수 없는 경우 잠금은 Google Home을 지원하지 않습니다", "3.安装Google Home APP,点击左上角的加号按钮": "3. 구글 홈 앱을 설치하고 왼쪽 상단 모서리에 있는 더하기 버튼을 클릭합니다", "暂无最新记录": "현재 사용 가능한 최신 레코드가 없습니다", - "请将手机切换至2.4G WiFi进行手动连接": "수동 연결을 위해 핸드폰을 2.4G WiFi로 바꿔주세요" + "请将手机切换至2.4G WiFi进行手动连接": "수동 연결을 위해 핸드폰을 2.4G WiFi로 바꿔주세요", + "语音包设置": "음성 팩 설정", + "第三方平台设置": "타사 플랫폼 설정", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "음성팩 설정 잠금", + "(中国台湾)": "(中国台湾)", + "男声": "남성", + "女声": "여성 목소리" } \ No newline at end of file diff --git a/lan/lan_lt.json b/lan/lan_lt.json index bd42405a..bffeb650 100644 --- a/lan/lan_lt.json +++ b/lan/lan_lt.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Įjunkite užrakto nuotolinio atrakinimo funkciją APP (ši funkcija yra išjungta pagal numatytuosius nustatymus). Jei ši parinktis nepasiekiama, užraktas nepalaikys \"Google Home\"", "3.安装Google Home APP,点击左上角的加号按钮": "3. Įdiekite \"Google Home\" programą ir spustelėkite pliuso mygtuką viršutiniame kairiajame kampe", "暂无最新记录": "Šiuo metu nėra naujausių įrašų", - "请将手机切换至2.4G WiFi进行手动连接": "Perjunkite telefoną į 2.4G WiFi, kad galėtumėte prisijungti rankiniu būdu" + "请将手机切换至2.4G WiFi进行手动连接": "Perjunkite telefoną į 2.4G WiFi, kad galėtumėte prisijungti rankiniu būdu", + "语音包设置": "Balso paketo nustatymai", + "第三方平台设置": "Trečiosios šalies platformos nustatymai", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Balso paketo nustatymų užrakinimas", + "(中国台湾)": "(中国台湾)", + "男声": "vyriškas balsas", + "女声": "Moteriškas balsas" } \ No newline at end of file diff --git a/lan/lan_ms.json b/lan/lan_ms.json index f0cbbe1a..62f5aa32 100644 --- a/lan/lan_ms.json +++ b/lan/lan_ms.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Dayakan fungsi buka kunci jauh kunci dalam APP (fungsi ini dimatikan secara lalai). Jika pilihan ini tidak tersedia, kunci tidak akan menyokong Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. Pasang apl Google Home dan klik butang tambah di penjuru kiri sebelah atas", "暂无最新记录": "Pada masa ini tiada rekod terkini tersedia", - "请将手机切换至2.4G WiFi进行手动连接": "Sila tukar telefon anda kepada WiFi 2.4G untuk sambungan manual" + "请将手机切换至2.4G WiFi进行手动连接": "Sila tukar telefon anda kepada WiFi 2.4G untuk sambungan manual", + "语音包设置": "Balso paketo nustatymai", + "第三方平台设置": "Trečiosios šalies platformos nustatymai", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Balso paketo nustatymų užrakinimas", + "(中国台湾)": "(中国台湾)", + "男声": "vyriškas balsas", + "女声": "Moteriškas balsas" } \ No newline at end of file diff --git a/lan/lan_nl.json b/lan/lan_nl.json index d34f3376..42d0e892 100644 --- a/lan/lan_nl.json +++ b/lan/lan_nl.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Open het slot op afstand in de APP (standaard uitgeschakeld). Als deze optie niet beschikbaar is, wordt google Home niet ondersteund", "3.安装Google Home APP,点击左上角的加号按钮": "3. Installeer de google home-app en klik op de plus-knop in de linkerbovenhoek", "暂无最新记录": "Er zijn momenteel geen recente gegevens beschikbaar", - "请将手机切换至2.4G WiFi进行手动连接": "Stel uw telefoon in op 2. 4g WiFi bij handmatige verbinding" + "请将手机切换至2.4G WiFi进行手动连接": "Stel uw telefoon in op 2. 4g WiFi bij handmatige verbinding", + "语音包设置": "Voice Pack-instellingen", + "第三方平台设置": "Instellingen voor platforms van derden", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Instellingen voor spraakpakket vergrendelen", + "(中国台湾)": "(中国台湾)", + "男声": "mannelijke stem", + "女声": "Vrouwelijke stem" } \ No newline at end of file diff --git a/lan/lan_pl.json b/lan/lan_pl.json index 32ca73b2..1748be43 100644 --- a/lan/lan_pl.json +++ b/lan/lan_pl.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Włącz funkcję zdalnego odblokowywania zamka w aplikacji (ta funkcja jest domyślnie wyłączona). Jeśli ta opcja nie jest dostępna, zamek nie będzie obsługiwał Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. Zainstaluj aplikację Google Home i kliknij przycisk plusa w lewym górnym rogu", "暂无最新记录": "Obecnie nie ma dostępnych najnowszych rekordów", - "请将手机切换至2.4G WiFi进行手动连接": "Przełącz telefon na 2.4G Wi-Fi, aby uzyskać ręczne połączenie" + "请将手机切换至2.4G WiFi进行手动连接": "Przełącz telefon na 2.4G Wi-Fi, aby uzyskać ręczne połączenie", + "语音包设置": "Ustawienia pakietu głosowego", + "第三方平台设置": "Ustawienia platformy stron trzecich", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Ustawienia blokowania pakietu głosowego", + "(中国台湾)": "(中国台湾)", + "男声": "Mężczyzna", + "女声": "Głos kobiecy" } \ No newline at end of file diff --git a/lan/lan_pt.json b/lan/lan_pt.json index c76c6fe3..7e2cc1b8 100644 --- a/lan/lan_pt.json +++ b/lan/lan_pt.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Ative a função de desbloqueio remoto da fechadura no APP (esta função está desativada por padrão). Se esta opção não estiver disponível, o bloqueio não será compatível com o Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. Instale o aplicativo Google Home e clique no botão de adição no canto superior esquerdo", "暂无最新记录": "Atualmente não há registros mais recentes disponíveis", - "请将手机切换至2.4G WiFi进行手动连接": "Mude seu telefone para WiFi 2.4G para conexão manual" + "请将手机切换至2.4G WiFi进行手动连接": "Mude seu telefone para WiFi 2.4G para conexão manual", + "语音包设置": "Configurações do pacote de voz", + "第三方平台设置": "Configurações de plataformas de terceiros", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Configurações do pacote de voz bloqueada", + "(中国台湾)": "(中国台湾)", + "男声": "Voz masculina", + "女声": "voz feminina" } \ No newline at end of file diff --git a/lan/lan_ro.json b/lan/lan_ro.json index 9b8eb31d..578b4c07 100644 --- a/lan/lan_ro.json +++ b/lan/lan_ro.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Activați funcția de deblocare de la distanță a încuietorului în aplicație (această funcție este dezactivată în mod implicit). Dacă această opțiune nu este disponibilă, blocarea nu va accepta Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. Instalați aplicația Google Home și faceți clic pe butonul plus din colțul din stânga sus", "暂无最新记录": "În prezent nu există cele mai recente înregistrări disponibile", - "请将手机切换至2.4G WiFi进行手动连接": "Vă rugăm să comutați telefonul la WiFi 2.4G pentru conectarea manuală" + "请将手机切换至2.4G WiFi进行手动连接": "Vă rugăm să comutați telefonul la WiFi 2.4G pentru conectarea manuală", + "语音包设置": "Setări pachet vocal", + "第三方平台设置": "Setarea platformei terțelor părți", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Configurarea pachetului vocal de blocare", + "(中国台湾)": "(中国台湾)", + "男声": "vocea bărbatului", + "女声": "Voce feminină" } \ No newline at end of file diff --git a/lan/lan_ru.json b/lan/lan_ru.json index c54d0e64..ed10bb80 100644 --- a/lan/lan_ru.json +++ b/lan/lan_ru.json @@ -1157,5 +1157,12 @@ "请确保网络是2.4GHz Wi-Fi": "Убедитесь, что сеть имеет 2,4 ГГц Wi - Fi", "已选": "Выбранные", "是否要远程开锁": "Нужно ли удалённо открывать замок", - "请将手机切换至2.4G WiFi进行手动连接": "Пожалуйста, переключите телефон на 2.4G WiFi для ручного подключения" + "请将手机切换至2.4G WiFi进行手动连接": "Пожалуйста, переключите телефон на 2.4G WiFi для ручного подключения", + "语音包设置": "Настройка голосового пакета", + "第三方平台设置": "Настройка платформы третьей стороны", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Запустить настройки голосового пакета", + "(中国台湾)": "(中国台湾)", + "男声": "Мужской голос", + "女声": "Женские голоса" } \ No newline at end of file diff --git a/lan/lan_sk.json b/lan/lan_sk.json index 77e88410..1334958f 100644 --- a/lan/lan_sk.json +++ b/lan/lan_sk.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Povoľte funkciu diaľkového odomykania zámku v aplikácii APP (táto funkcia je predvolene vypnutá). Ak táto možnosť nie je k dispozícii, zámok nebude podporovať Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. Nainštalujte si aplikáciu Google Home a kliknite na tlačidlo plus v ľavom hornom rohu", "暂无最新记录": "Momentálne nie sú k dispozícii žiadne najnovšie záznamy", - "请将手机切换至2.4G WiFi进行手动连接": "Pre manuálne pripojenie prepnite telefón na 2.4G WiFi" + "请将手机切换至2.4G WiFi进行手动连接": "Pre manuálne pripojenie prepnite telefón na 2.4G WiFi", + "语音包设置": "Nastavenie hlasového balíka", + "第三方平台设置": "Nastavenie platformy tretích strán", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Zamknutie nastavení hlasového balíka", + "(中国台湾)": "(中国台湾)", + "男声": "mužský hlas", + "女声": "Ženský hlas" } \ No newline at end of file diff --git a/lan/lan_sr_cyrl.json b/lan/lan_sr_cyrl.json index 23cece71..21305eb3 100644 --- a/lan/lan_sr_cyrl.json +++ b/lan/lan_sr_cyrl.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2 . Омогућите функцију даљинског откључавања браве у АПП-у (ова функција је подразумевано искључена). Ако ова опција није доступна, брава неће подржати Гоогле Хоме", "3.安装Google Home APP,点击左上角的加号按钮": "3 . Инсталирајте апликацију Гоогле Хоме и кликните на дугме плус у горњем левом углу", "暂无最新记录": "Тренутно нема доступних најновијих података", - "请将手机切换至2.4G WiFi进行手动连接": "Пребаците телефон на КСНУМКСГ ВиФи за ручно повезивање" + "请将手机切换至2.4G WiFi进行手动连接": "Пребаците телефон на КСНУМКСГ ВиФи за ручно повезивање", + "语音包设置": "Подешавања гласовног пакета", + "第三方平台设置": "Подешавања платформе трећих страна", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Закључајте подешавања говорног пакета", + "(中国台湾)": "(中国台湾)", + "男声": "мушки глас", + "女声": "женски глас" } \ No newline at end of file diff --git a/lan/lan_sv.json b/lan/lan_sv.json index ade05b71..a6274e34 100644 --- a/lan/lan_sv.json +++ b/lan/lan_sv.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Aktivera fjärrupplåsningsfunktionen för låset i APP (den här funktionen är avstängd som standard). Om det här alternativet inte är tillgängligt kommer låset inte att stödja Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. Installera Google Home-appen och klicka på plusknappen i det övre vänstra hörnet", "暂无最新记录": "Det finns för närvarande inga senaste poster tillgängliga", - "请将手机切换至2.4G WiFi进行手动连接": "Byt din telefon till 2.4G WiFi för manuell anslutning" + "请将手机切换至2.4G WiFi进行手动连接": "Byt din telefon till 2.4G WiFi för manuell anslutning", + "语音包设置": "Inställningar för röstpaket", + "第三方平台设置": "Inställningar för tredjepartsplattformar", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Lås inställningar för röstpaket", + "(中国台湾)": "(中国台湾)", + "男声": "Mänsklig röst", + "女声": "Kvinnlig röst" } \ No newline at end of file diff --git a/lan/lan_th.json b/lan/lan_th.json index b913a437..24617315 100644 --- a/lan/lan_th.json +++ b/lan/lan_th.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. เปิดใช้งานฟังก์ชันการปลดล็อคระยะไกลของการล็อคในแอพ (ฟังก์ชันนี้ จะถูกปิดโดยค่าเริ่มต้น) หากไม่มีตัวเลือกนี้ การล็อคจะไม่สนับสนุนกูเกิ้ลโฮม", "3.安装Google Home APP,点击左上角的加号按钮": "3. ติดตั้ง googlehome แอพ และคลิกปุ่มบวก ที่มุมบนซ้าย", "暂无最新记录": "ปัจจุบันยังไม่มีบันทึกล่าสุด ที่มีอยู่", - "请将手机切换至2.4G WiFi进行手动连接": "กรุณาเปลี่ยนโทรศัพท์เป็น 2.4 GWiFi สำหรับการเชื่อมต่อด้วยตนเอง" + "请将手机切换至2.4G WiFi进行手动连接": "กรุณาเปลี่ยนโทรศัพท์เป็น 2.4 GWiFi สำหรับการเชื่อมต่อด้วยตนเอง", + "语音包设置": "การตั้งค่าแพ็กเกจเสียง", + "第三方平台设置": "การตั้งค่าแพลตฟอร์มของบุคคลที่สาม", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "ล็อคการตั้งค่า Voice Pack", + "(中国台湾)": "(中国台湾)", + "男声": "เสียงผู้ชาย", + "女声": "เสียงผู้หญิง" } \ No newline at end of file diff --git a/lan/lan_tr.json b/lan/lan_tr.json index 6a45e2c5..e0a6f17a 100644 --- a/lan/lan_tr.json +++ b/lan/lan_tr.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. APP'de kilidin uzaktan kilit açma işlevini etkinleştirin (bu işlev varsayılan olarak kapalıdır). Bu seçenek mevcut değilse, kilit Google Home'u desteklemeyecektir", "3.安装Google Home APP,点击左上角的加号按钮": "3. Google Home uygulamasını yükleyin ve sol üst köşedeki artı düğmesini tıklayın", "暂无最新记录": "Şu anda en son kayıt mevcut değil", - "请将手机切换至2.4G WiFi进行手动连接": "Manuel bağlantı için lütfen telefonunuzu 2.4G WiFi'ye getirin" + "请将手机切换至2.4G WiFi进行手动连接": "Manuel bağlantı için lütfen telefonunuzu 2.4G WiFi'ye getirin", + "语音包设置": "Ses Paketi Ayarları", + "第三方平台设置": "Üçüncü Taraf Platform Ayarları", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Ses Paketi Ayarlarını Kilitle", + "(中国台湾)": "(中国台湾)", + "男声": "Erkek Sesi", + "女声": "Kadın Sesi" } \ No newline at end of file diff --git a/lan/lan_tw.json b/lan/lan_tw.json index bb78df34..90d9e0f3 100644 --- a/lan/lan_tw.json +++ b/lan/lan_tw.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. 在APP中開啓鎖的遠程開鎖功能(默認關閉)。如果這個選項不可用,鎖將不支持谷歌Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. 安裝谷歌Home應用程序並單擊左上角的加號按鈕", "暂无最新记录": "目前沒有最新的記錄", - "请将手机切换至2.4G WiFi进行手动连接": "手動連接時請將手機調至2.4G WiFi" + "请将手机切换至2.4G WiFi进行手动连接": "手動連接時請將手機調至2.4G WiFi", + "语音包设置": "語音包設定", + "第三方平台设置": "協力廠商領獎臺設定", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "鎖語音包設定", + "(中国台湾)": "(中国台湾)", + "男声": "男聲", + "女声": "女聲" } \ No newline at end of file diff --git a/lan/lan_uk.json b/lan/lan_uk.json index 153f8e96..bacfed39 100644 --- a/lan/lan_uk.json +++ b/lan/lan_uk.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Увімкніть функцію дистанційного розблокування замка в APP (ця функція вимкнена за замовчуванням). Якщо ця опція недоступна, замок не підтримуватиме Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. Встановіть програму Google Home і натисніть кнопку плюс у верхньому лівому кутку", "暂无最新记录": "Наразі немає останніх доступних записів", - "请将手机切换至2.4G WiFi进行手动连接": "Будь ласка, перемкніть свій телефон на 2.4G WiFi для ручного підключення" + "请将手机切换至2.4G WiFi进行手动连接": "Будь ласка, перемкніть свій телефон на 2.4G WiFi для ручного підключення", + "语音包设置": "Параметри голосового пакету", + "第三方平台设置": "Налаштування платформи третьої сторони", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Параметри блокування голосового пакету", + "(中国台湾)": "(中国台湾)", + "男声": "Чоловічий голос", + "女声": "жіночий голос" } \ No newline at end of file diff --git a/lan/lan_ur.json b/lan/lan_ur.json index ec81c584..bd08e555 100644 --- a/lan/lan_ur.json +++ b/lan/lan_ur.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. اے پی پی میں لاک کے ریموٹ ان لاکنگ فنکشن کو فعال کریں (یہ فنکشن ڈیفالٹ طور پر بند ہے)۔ اگر یہ آپشن دستیاب نہیں ہے تو ، لاک گوگل ہوم کو سپورٹ نہیں کرے گا۔", "3.安装Google Home APP,点击左上角的加号按钮": "3. گوگل ہوم ایپ انسٹال کریں اور اوپری بائیں کونے میں پلس بٹن پر کلک کریں۔", "暂无最新记录": "فی الحال کوئی تازہ ترین ریکارڈ دستیاب نہیں ہے", - "请将手机切换至2.4G WiFi进行手动连接": "براہ کرم دستی کنکشن کے لئے اپنے فون کو 2.4 جی وائی فائی پر سوئچ کریں" + "请将手机切换至2.4G WiFi进行手动连接": "براہ کرم دستی کنکشن کے لئے اپنے فون کو 2.4 جی وائی فائی پر سوئچ کریں", + "语音包设置": "صوتی پیکیج ترتیبات", + "第三方平台设置": "تھرڈ پارٹی پلیٹ فارم کی ترتیبات", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "صوتی پیکیج کی ترتیبات لاک کریں", + "(中国台湾)": "(中国台湾)", + "男声": "مردوں کی آواز", + "女声": "خواتین کی آواز" } \ No newline at end of file diff --git a/lan/lan_vi.json b/lan/lan_vi.json index 32b63705..1270fc98 100644 --- a/lan/lan_vi.json +++ b/lan/lan_vi.json @@ -1153,5 +1153,12 @@ "2.在APP里开启锁的远程开锁功能(这个功能默认是关闭的)。如果没有这个选项,则锁不支持Google Home": "2. Kích hoạt chức năng mở khóa từ xa trong ứng dụng (chức năng này bị tắt theo mặc định). Nếu tùy chọn này không có sẵn, khóa sẽ không hỗ trợ Google Home", "3.安装Google Home APP,点击左上角的加号按钮": "3. Cài đặt ứng dụng Google Home và nhấn nút Plus ở góc trên bên trái", "暂无最新记录": "Hiện tại không có hồ sơ mới nhất", - "请将手机切换至2.4G WiFi进行手动连接": "Vui lòng chuyển điện thoại sang 2.4G WiFi để kết nối bằng tay" + "请将手机切换至2.4G WiFi进行手动连接": "Vui lòng chuyển điện thoại sang 2.4G WiFi để kết nối bằng tay", + "语音包设置": "Thiết lập gói thoại", + "第三方平台设置": "Cài đặt nền tảng của bên thứ ba", + "涂鸦智能": "Tuya Smart", + "锁语音包设置": "Khóa cài đặt gói thoại", + "(中国台湾)": "(中国台湾)", + "男声": "Giọng nam", + "女声": "Giọng nữ" } \ No newline at end of file diff --git a/lan/lan_zh.json b/lan/lan_zh.json index 633e2931..424a13ec 100755 --- a/lan/lan_zh.json +++ b/lan/lan_zh.json @@ -1167,5 +1167,10 @@ "需要相机权限": "需要相机权限", "一键登录": "一键登录", "网关添加成功": "网关添加成功", - "语音包设置": "语音包设置" + "第三方平台设置": "第三方平台设置", + "涂鸦智能": "涂鸦智能", + "锁语音包设置": "锁语音包设置", + "(中国台湾)": "(中国台湾)", + "男声": "男声", + "女声": "女声" } diff --git a/lib/main/lockDetail/lockDetail/passthrough_item.dart b/lib/main/lockDetail/lockDetail/passthrough_item.dart index 2d54fa3e..f8d798ee 100644 --- a/lib/main/lockDetail/lockDetail/passthrough_item.dart +++ b/lib/main/lockDetail/lockDetail/passthrough_item.dart @@ -43,12 +43,14 @@ class TimbreItem { class PassthroughItem { final String lang; final String langText; + final String name; final List timbres; PassthroughItem({ required this.lang, required this.timbres, required this.langText, + required this.name, }); factory PassthroughItem.fromJson(Map json) { @@ -61,6 +63,7 @@ class PassthroughItem { return PassthroughItem( lang: json['lang'] ?? '', langText: json['langText'] ?? '', + name: json['name'] ?? '', timbres: timbresList, ); } @@ -69,13 +72,16 @@ class PassthroughItem { return { 'lang': lang, 'langText': langText, + 'name': name, 'timbres': timbres.map((e) => e.toJson()).toList(), }; } @override String toString() { - return 'PassthroughItem{lang: $lang, timbres: $timbres}'; + return 'PassthroughItem{lang: $lang, name: $name, timbres: $timbres, ' + 'langText: ' + '$langText}'; } } diff --git a/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart b/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart index 7fe7f771..ca5d7a9d 100755 --- a/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart +++ b/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart @@ -67,11 +67,6 @@ class LockSetLogic extends BaseGetXController { (state.ifCurrentScreen.value == true)) { _replyUpdataLockSetReply(reply); } - - if (reply is GetDeviceModelReply) { - // 获取设备型号 - _handlerDeviceModelReply(reply); - } }); } @@ -734,7 +729,7 @@ class LockSetLogic extends BaseGetXController { getUpdataLockSet(); _initReplySubscription(); - sendGetDeviceModelBleMessage(); + // _scanListDiscoveredDeviceSubscriptionAction(); } @@ -745,57 +740,9 @@ class LockSetLogic extends BaseGetXController { // _scanListDiscoveredDeviceSubscription.cancel(); } - - // 发送获取型号蓝牙命令 - sendGetDeviceModelBleMessage() { - // showEasyLoading(); - // showBlueConnetctToastTimer(action: () { - // dismissEasyLoading(); - // }); - BlueManage().blueSendData(BlueManage().connectDeviceName, - (BluetoothConnectionState deviceConnectionState) async { - if (deviceConnectionState == BluetoothConnectionState.connected) { - BlueManage().writeCharacteristicWithResponse( - GetDeviceModelCommand( - lockID: BlueManage().connectDeviceName, - ).packageData(), - ); - } else if (deviceConnectionState == - BluetoothConnectionState.disconnected) { - // dismissEasyLoading(); - // cancelBlueConnetctToastTimer(); - // showBlueConnetctToast(); - } - }); - } - @override void dispose() { _replySubscription.cancel(); super.dispose(); } - - void _handlerDeviceModelReply(GetDeviceModelReply reply) async { - final int status = reply.data[2]; - switch (status) { - case 0x00: - //成功 - cancelBlueConnetctToastTimer(); - // 3. 解析DeviceModel(40字节,索引3~42) - int startIndex = 3; - int length = 40; - List deviceModelBytes = - reply.data.sublist(startIndex, startIndex + length); - - String rawData = String.fromCharCodes(deviceModelBytes); - int firstNullIndex = rawData.indexOf('\u0000'); - String deviceModelValue = rawData.substring(0, firstNullIndex); - print('获取到 DeviceModel (原始): $deviceModelValue'); - await Storage.setString(deviceModel, deviceModelValue); - break; - default: - showToast('获取设备型号失败'.tr); - break; - } - } } diff --git a/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart b/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart index 045b2b2c..f3577276 100755 --- a/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart +++ b/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart @@ -542,7 +542,7 @@ class _LockSetPageState extends State })), // 锁语音包设置 CommonItem( - leftTitel: '第三方平台'.tr, + leftTitel: '第三方平台设置'.tr, rightTitle: '', isHaveLine: true, isHaveDirection: true, diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart index d6301406..781df709 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart @@ -28,6 +28,7 @@ import 'package:star_lock/tools/commonDataManage.dart'; import 'package:star_lock/tools/eventBusEventManage.dart'; import 'package:star_lock/tools/storage.dart'; import 'package:star_lock/translations/app_dept.dart'; +import 'package:star_lock/translations/current_locale_tool.dart'; class SpeechLanguageSettingsLogic extends BaseGetXController { final SpeechLanguageSettingsState state = SpeechLanguageSettingsState(); @@ -35,15 +36,9 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { @override void onInit() async { - final findLocaleIndex = _findLocaleIndex(); - state.selectPassthroughListIndex.value = findLocaleIndex; super.onInit(); _replySubscription = EventBusManager().eventBus!.on().listen((Reply reply) async { - if (reply is GetDeviceModelReply) { - // 获取设备型号 - _handlerDeviceModelReply(reply); - } if (reply is VoicePackageConfigureReply) { // 语言包配置开始 _handlerStartVoicePackageConfigure(reply); @@ -53,13 +48,8 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { _handlerVoicePackageConfigureConfirmation(reply); } }); - state.deviceModel.value = await Storage.getString(deviceModel) ?? ''; - debugPrint('设备型号:${state.deviceModel.value}'); - if (state.deviceModel.value != null) { - await initList(); - } - // await sendGetDeviceModelBleMessage(); + await initList(); } /// 获取列表 @@ -76,7 +66,46 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { 'model': model!, }); if (entity.errorCode!.codeIsSuccessful) { - state.languages.value = entity.data!!; + final data = entity.data; + final locales = appDept.deptSupportedLocales; + state.languages.clear(); + + state.languages.add( + PassthroughItem( + lang: 'system', + timbres: [], + langText: '跟随系统'.tr, + name: '跟随系统'.tr, + ), + ); + + data?.forEach((element) { + final lang = element.lang; + if (lang == 'zh_TW') { + // 如果是台湾的话应该显示未简体中文 + List parts = lang.split('_'); + final indexOf = locales.indexOf(Locale(parts[0], parts[1])); + final passthroughItem = PassthroughItem( + lang: element.lang, + timbres: element.timbres, + langText: '简体中文'.tr + '(中国台湾)'.tr, + name: element.name, + ); + state.languages.add(passthroughItem); + } else { + List parts = lang.split('_'); + final indexOf = locales.indexOf(Locale(parts[0], parts[1])); + final passthroughItem = PassthroughItem( + lang: element.lang, + timbres: element.timbres, + langText: + ExtensionLanguageType.fromLocale(locales[indexOf]).lanTitle, + name: element.name, + ); + state.languages.add(passthroughItem); + } + }); + state.languages.refresh(); final lang = state .lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang; final timbre = state @@ -97,54 +126,30 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { } } - /// 查找 locales 中 code 等于 lang 的元素下标(不存在返回 -1) - int _findLocaleIndex() { - // 1. 获取 lang(可能为 null) - final lang = - state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang; - - // 2. 如果 lang 为 null,直接返回 -1 - if (lang == null) return -1; - - // 3. 获取 locales 集合(假设非空,若可能为空需额外判空) - final locales = appDept.deptSupportedLocales; - - // 4. 遍历查找符合条件的下标(使用 indexWhere 高效实现) - return locales.indexWhere((element) { - // 处理 countryCode 可能为 null 的情况(根据业务需求调整) - if (element.countryCode == null) return false; - - // 构造当前 locale 的 code(格式:languageCode_countryCode) - final currentCode = '${element.languageCode}_${element.countryCode}'; - - // 比较是否等于目标 lang - return currentCode == lang; - }); - } - void saveSpeechLanguageSettings() async { - final language = - state.appLocalLanguages[state.selectPassthroughListIndex.value]; - // 从选中的语言中获取languageCode和countryCode - final locales = appDept.deptSupportedLocales; - locales.forEach((element) { - final lanTitle = ExtensionLanguageType.fromLocale(element).lanTitle; - if (lanTitle == language) { - if (element.countryCode != null) { - String code = element.languageCode + '_' + element.countryCode!; + var language = state.languages[state.selectPassthroughListIndex.value]; + if (language.lang == 'system') { + // 如果选择了跟随系统 + // 系统层的语言 + // print(CurrentLocaleTool.convertLocale(Get.deviceLocale!)); - state.languages.forEach((item) async { - if (item.lang == code) { - item.timbres.forEach((timbre) async { - if (timbre.isFemale == state.selectSoundTypeIndex.value) { - state.tempLangStr.value = item.lang; - state.tempTimbreStr.value = timbre.timbre; - await downloadFile(timbre.timbrePackUrl); - } - }); - } - }); - } + // APP层的语言 + Locale? currentLocale = Get.locale; // 直接获取最新语言 + if (currentLocale != null) { + final indexWhere = state.languages + .indexWhere((element) => element.lang == currentLocale.toString()); + state.selectPassthroughListIndex.value = indexWhere; + } + } + language = state.languages[state.selectPassthroughListIndex.value]; + final value = state.selectSoundTypeIndex.value; + state.tempLangStr.value = language.lang; + AppLog.log('下载的语言是:${state.tempLangStr}'); + language.timbres.forEach((element) async { + if (element.isFemale == value) { + await downloadFile(element.timbrePackUrl); + state.tempTimbreStr.value = element.timbre; + return; } }); } @@ -225,32 +230,6 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { }); } - void _handlerDeviceModelReply(GetDeviceModelReply reply) async { - final int status = reply.data[2]; - switch (status) { - case 0x00: - //成功 - cancelBlueConnetctToastTimer(); - // 3. 解析DeviceModel(40字节,索引3~42) - int startIndex = 3; - int length = 40; - List deviceModelBytes = - reply.data.sublist(startIndex, startIndex + length); - - String rawData = String.fromCharCodes(deviceModelBytes); - int firstNullIndex = rawData.indexOf('\u0000'); - String deviceModel = rawData.substring(0, firstNullIndex); - print(deviceModel); // 输出: 2403 - print('获取到 DeviceModel (原始): $deviceModel'); - state.deviceModel.value = deviceModel; - await initList(); - break; - default: - showToast('获取设备型号失败'.tr); - break; - } - } - // 开始配置语音包 void _handlerStartVoicePackageConfigure( VoicePackageConfigureReply reply) async { @@ -287,7 +266,7 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { _sendNextPackage(); } - void _sendNextPackage() { + void _sendNextPackage() async { if (state.voiceSubcontractingIndex >= state.voiceSubcontractingCount) { print('所有分包已发送完成'); state.progress.value = 1.0; // 发送完成 @@ -305,17 +284,18 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { (state.voiceSubcontractingIndex + 1) / state.voiceSubcontractingCount; EasyLoading.showProgress(state.progress.value, status: '正在发送数据 ${(state.progress.value * 100).toStringAsFixed(0)}%'); - _sendLanguageFileBleMessage( + await _sendLanguageFileBleMessage( index: state.voiceSubcontractingIndex, data: packageData, ); } - _sendLanguageFileBleMessage({required int index, required Uint8List data}) { - BlueManage().blueSendData(BlueManage().connectDeviceName, + _sendLanguageFileBleMessage( + {required int index, required Uint8List data}) async { + await BlueManage().blueSendData(BlueManage().connectDeviceName, (BluetoothConnectionState deviceConnectionState) async { if (deviceConnectionState == BluetoothConnectionState.connected) { - BlueManage().writeCharacteristicWithResponse( + await BlueManage().writeCharacteristicWithResponse( VoicePackageConfigureProcess( index: index, size: data.length, @@ -406,7 +386,7 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { dismissEasyLoading(); break; default: - showToast('语音设置失败'.tr); + showToast('设置'.tr + '失败'.tr); break; } } diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart index d78b91d7..94e602cd 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart @@ -38,7 +38,7 @@ class _SpeechLanguageSettingsPageState TextButton( onPressed: logic.saveSpeechLanguageSettings, child: Text( - '保存'.tr, + '下载'.tr, style: TextStyle( color: Colors.white, fontSize: 24.sp, @@ -121,7 +121,7 @@ class _SpeechLanguageSettingsPageState } List _buildList() { - final appLocalLanguages = state.appLocalLanguages; + final appLocalLanguages = state.languages; return List.generate( appLocalLanguages.length, (index) => _buildItem( @@ -139,9 +139,9 @@ class _SpeechLanguageSettingsPageState } } - _buildItem(String appLocalLanguages, index) { + _buildItem(PassthroughItem item, index) { return CommonItem( - leftTitel: appLocalLanguages, + leftTitel: item.langText, rightTitle: '', isHaveLine: true, isHaveDirection: false, diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart index da705c38..1bd4ee55 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart @@ -12,24 +12,7 @@ class SpeechLanguageSettingsState { lockSetInfoData.value = map['lockSetInfoData']; } - List get appLocalLanguages { - final locales = appDept.deptSupportedLocales; - final languageCode = locales[1].languageCode; - final countryCode = locales[1].countryCode; - String localeStr = ''; - if (countryCode != null) { - localeStr = languageCode + '_' + countryCode; - appLocalLanguageCodes.add(localeStr); - } - - final list = locales - .map((e) => ExtensionLanguageType.fromLocale(e).lanTitle) - .toList(); - return list; - } - - List appLocalLanguageCodes = []; Rx lockSetInfoData = LockSetInfoData().obs; diff --git a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart index 46e68efd..dff888e9 100644 --- a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart +++ b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart @@ -37,10 +37,6 @@ class LockVoiceSettingLogic extends BaseGetXController { super.onInit(); _replySubscription = EventBusManager().eventBus!.on().listen((Reply reply) async { - if (reply is GetDeviceModelReply) { - // 获取设备型号 - _handlerDeviceModelReply(reply); - } if (reply is VoicePackageConfigureReply) { // 语言包配置开始 _handlerStartVoicePackageConfigure(reply); @@ -50,7 +46,7 @@ class LockVoiceSettingLogic extends BaseGetXController { handleVoiceConfigureThrottled(reply); } }); - await sendGetDeviceModelBleMessage(); + initList(); } void handleVoiceConfigureThrottled( @@ -71,80 +67,51 @@ class LockVoiceSettingLogic extends BaseGetXController { Future _executeLogic( VoicePackageConfigureConfirmationReply reply) async { - final PassthroughItem item = - state.languages[state.selectPassthroughListIndex.value]; - final timbre = item.timbres[state.selectLanguageIndex.value]; final LoginEntity entity = await ApiRepository.to.settingCurrentVoiceTimbre( data: { - 'lang': item.lang, - 'timbre': timbre.timbre, + 'lang': state.tempLangStr.value, + 'timbre': state.tempTimbreStr.value, }, lockId: state.lockSetInfoData.value.lockId!, ); if (entity.errorCode!.codeIsSuccessful) { - showCupertinoDialog( - context: Get.context!, - builder: (BuildContext context) { - return CupertinoAlertDialog( - title: Text('语音设置'.tr), - content: Text('语音设置成功'.tr), - actions: [ - CupertinoDialogAction( - child: Text( - '取消'.tr, - style: TextStyle(color: AppColors.mainColor), - ), - onPressed: () { - Get.back(); - }, - ), - CupertinoDialogAction( - child: Text( - '返回主页'.tr, - style: TextStyle(color: AppColors.mainColor), - ), - onPressed: () { - state.lockSetInfoData.value.lockSettingInfo - ?.currentVoiceTimbre?.lang = item.lang; - state.lockSetInfoData.value.lockSettingInfo - ?.currentVoiceTimbre?.timbre = timbre.timbre; + showSuccess('设置成功'.tr, something: () { + state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang = + state.tempLangStr.value; + state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre + ?.timbre = state.tempTimbreStr.value; - eventBus.fire(PassCurrentLockInformationEvent( - state.lockSetInfoData.value)); - Get.offAllNamed(Routers.starLockMain); - }, - ), - ], - ); - }, - ); + eventBus + .fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value)); + Get.offAllNamed(Routers.starLockMain); + }); } dismissEasyLoading(); } void saveSpeechLanguageSettings() async { - final language = - state.appLocalLanguages[state.selectPassthroughListIndex.value]; - // 从选中的语言中获取languageCode和countryCode - final locales = appDept.deptSupportedLocales; - locales.forEach((element) { - final lanTitle = ExtensionLanguageType.fromLocale(element).lanTitle; - if (lanTitle == language) { - if (element.countryCode != null) { - String code = element.languageCode + '_' + element.countryCode!; + var language = state.languages[state.selectPassthroughListIndex.value]; + if (language.lang == 'system') { + // 如果选择了跟随系统 + // 系统层的语言 + // print(CurrentLocaleTool.convertLocale(Get.deviceLocale!)); - state.languages.forEach((item) async { - if (item.lang == code) { - item.timbres.forEach((timbre) async { - if (timbre.isFemale == state.selectSoundTypeIndex.value) { - state.tempLangStr.value = item.lang; - state.tempTimbreStr.value = timbre.timbre; - await downloadFile(timbre.timbrePackUrl); - } - }); - } - }); - } + // APP层的语言 + Locale? currentLocale = Get.locale; // 直接获取最新语言 + if (currentLocale != null) { + final indexWhere = state.languages + .indexWhere((element) => element.lang == currentLocale.toString()); + state.selectPassthroughListIndex.value = indexWhere; + } + } + language = state.languages[state.selectPassthroughListIndex.value]; + final value = state.selectSoundTypeIndex.value; + state.tempLangStr.value = language.lang; + language.timbres.forEach((element) async { + if (element.isFemale == value) { + await downloadFile(element.timbrePackUrl); + state.tempTimbreStr.value = element.timbre; + return; } }); } @@ -229,7 +196,6 @@ class LockVoiceSettingLogic extends BaseGetXController { case 0x06: //无权限 final List token = reply.data.sublist(2, 6); - print('收到token:$token'); if (state.data != null) { sendFileToDevice(state.data!, token); } @@ -240,31 +206,6 @@ class LockVoiceSettingLogic extends BaseGetXController { } } - void _handlerDeviceModelReply(GetDeviceModelReply reply) async { - final int status = reply.data[2]; - switch (status) { - case 0x00: - //成功 - cancelBlueConnetctToastTimer(); - // 3. 解析DeviceModel(40字节,索引3~42) - int startIndex = 3; - int length = 40; - List deviceModelBytes = - reply.data.sublist(startIndex, startIndex + length); - - String rawData = String.fromCharCodes(deviceModelBytes); - int firstNullIndex = rawData.indexOf('\u0000'); - String deviceModel = rawData.substring(0, firstNullIndex); - print('获取到 DeviceModel (原始): $deviceModel'); - state.deviceModel.value = deviceModel; - await initList(); - break; - default: - showToast('获取设备型号失败'.tr); - break; - } - } - /// 获取列表 initList() async { showEasyLoading(); @@ -273,12 +214,38 @@ class LockVoiceSettingLogic extends BaseGetXController { final model = state.lockSetInfoData.value.lockBasicInfo?.model; final PassthroughListResponse entity = - await ApiRepository.to.getPassthroughList(data: { + await ApiRepository.to.getPassthroughList(data: { 'vendor': vendor!, 'model': model!, }); if (entity.errorCode!.codeIsSuccessful) { - state.languages.value = entity.data!!; + final data = entity.data; + final locales = appDept.deptSupportedLocales; + state.languages.clear(); + + state.languages.add( + PassthroughItem( + lang: 'system', + timbres: [], + langText: '跟随系统'.tr, + name: '跟随系统'.tr, + ), + ); + + data?.forEach((element) { + final lang = element.lang; + List parts = lang.split('_'); + final indexOf = locales.indexOf(Locale(parts[0], parts[1])); + final passthroughItem = PassthroughItem( + lang: element.lang, + timbres: element.timbres, + langText: + ExtensionLanguageType.fromLocale(locales[indexOf]).lanTitle, + name: element.name, + ); + state.languages.add(passthroughItem); + }); + state.languages.refresh(); final lang = state .lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang; final timbre = state diff --git a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart index 3b0c83b3..e4fc66ff 100644 --- a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart +++ b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart @@ -11,6 +11,7 @@ import 'package:star_lock/mine/addLock/lock_voice_setting/lock_voice_setting_log import 'package:star_lock/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart'; import 'package:star_lock/tools/EasyRefreshTool.dart'; import 'package:star_lock/tools/commonItem.dart'; +import 'package:star_lock/tools/eventBusEventManage.dart'; import 'package:star_lock/tools/titleAppBar.dart'; class LockVoiceSetting extends StatefulWidget { @@ -38,6 +39,8 @@ class _LockVoiceSettingState extends State { haveOtherLeftWidget: true, leftWidget: TextButton( onPressed: () { + eventBus + .fire(RefreshLockListInfoDataEvent(isUnShowLoading: true)); Get.offAllNamed(Routers.starLockMain); }, child: Text( @@ -54,7 +57,7 @@ class _LockVoiceSettingState extends State { TextButton( onPressed: logic.saveSpeechLanguageSettings, child: Text( - '保存'.tr, + '下载'.tr, style: TextStyle( color: Colors.white, fontSize: 24.sp, @@ -138,7 +141,7 @@ class _LockVoiceSettingState extends State { } List _buildList() { - final appLocalLanguages = state.appLocalLanguages; + final appLocalLanguages = state.languages; return List.generate( appLocalLanguages.length, (index) => _buildItem( @@ -148,9 +151,9 @@ class _LockVoiceSettingState extends State { ); } - _buildItem(String appLocalLanguages, index) { + _buildItem(PassthroughItem passthroughItem, index) { return CommonItem( - leftTitel: appLocalLanguages, + leftTitel: passthroughItem.langText, rightTitle: '', isHaveLine: true, isHaveDirection: false, diff --git a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart index 15b73e01..ca6785e7 100644 --- a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart +++ b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart @@ -18,24 +18,6 @@ class LockVoiceSettingState { - List get appLocalLanguages { - final locales = appDept.deptSupportedLocales; - - final languageCode = locales[1].languageCode; - final countryCode = locales[1].countryCode; - String localeStr = ''; - if (countryCode != null) { - localeStr = languageCode + '_' + countryCode; - appLocalLanguageCodes.add(localeStr); - } - - final list = locales - .map((e) => ExtensionLanguageType.fromLocale(e).lanTitle) - .toList(); - return list; - } - - List appLocalLanguageCodes = []; // 选中的语音包列表下标 RxInt selectPassthroughListIndex = 0.obs; @@ -68,7 +50,7 @@ class LockVoiceSettingState { '女声'.tr, }).obs; - RxInt selectSoundTypeIndex = 0.obs; + RxInt selectSoundTypeIndex = 1.obs; RxString tempLangStr=''.obs; RxString tempTimbreStr=''.obs; } From e57e7de6f77d82284f255c32573981bf30676976 Mon Sep 17 00:00:00 2001 From: liyi Date: Mon, 28 Jul 2025 09:12:13 +0800 Subject: [PATCH 19/25] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E5=A4=9A=E5=9B=BD?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E8=AF=8D=E6=9D=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lan/lan_keys.json | 1 + lan/lan_zh.json | 1 + 2 files changed, 2 insertions(+) diff --git a/lan/lan_keys.json b/lan/lan_keys.json index f695a426..aff5bacc 100755 --- a/lan/lan_keys.json +++ b/lan/lan_keys.json @@ -1168,6 +1168,7 @@ "第三方平台设置": "第三方平台设置", "涂鸦智能": "Tuya Smart", "锁语音包设置": "锁语音包设置", + "语音包设置": "语音包设置", "(中国台湾)": "(中国台湾)", "男声": "男声", "女声": "女声" diff --git a/lan/lan_zh.json b/lan/lan_zh.json index 424a13ec..c1b24478 100755 --- a/lan/lan_zh.json +++ b/lan/lan_zh.json @@ -1170,6 +1170,7 @@ "第三方平台设置": "第三方平台设置", "涂鸦智能": "涂鸦智能", "锁语音包设置": "锁语音包设置", + "语音包设置": "语音包设置", "(中国台湾)": "(中国台湾)", "男声": "男声", "女声": "女声" From a5006b28fab53459c8a5a894c859f3f7f54abd33 Mon Sep 17 00:00:00 2001 From: liyi Date: Mon, 28 Jul 2025 10:00:56 +0800 Subject: [PATCH 20/25] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4ios=E5=92=8Candroid?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E4=B8=8D=E4=B8=80=E8=87=B4=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../speech_language_settings_page.dart | 94 ++++++++++++++++--- 1 file changed, 83 insertions(+), 11 deletions(-) diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart index 94e602cd..ef590be8 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart @@ -48,7 +48,86 @@ class _SpeechLanguageSettingsPageState ), ], ), - body: _buildBody(), + body: Obx( + () => ListView( + padding: EdgeInsets.zero, + children: [ + // 语音类型选择区 + Container( + color: Colors.white, + child: Column( + children: List.generate( + state.soundTypeList.length, + (index) { + final isLastItem = index == state.soundTypeList.length - 1; + final soundType = state.soundTypeList.value[index]; + return CommonItem( + leftTitel: soundType, + rightTitle: '', + isHaveLine: !isLastItem, + isHaveDirection: false, + isHaveRightWidget: true, + rightWidget: Radio( + value: soundType, + groupValue: state.soundTypeList + .value[state.selectSoundTypeIndex.value], + activeColor: AppColors.mainColor, + onChanged: (value) { + if (value != null) { + final newIndex = state.soundTypeList.value + .indexWhere((p) => p == value); + if (newIndex != -1) { + state.selectSoundTypeIndex.value = newIndex; + } + } + }, + ), + action: () { + state.selectSoundTypeIndex.value = index; + }, + ); + }, + ), + ), + ), + SizedBox( + height: 8.h, + ), + // 语言包列表区 + Container( + color: Colors.transparent, + child: Column( + children: List.generate( + state.languages.length, + (index) { + final item = state.languages[index]; + return CommonItem( + leftTitel: item.langText, + rightTitle: '', + isHaveLine: true, + isHaveDirection: false, + isHaveRightWidget: true, + rightWidget: + state.selectPassthroughListIndex.value == index + ? Image( + image: const AssetImage( + 'images/icon_item_checked.png'), + width: 30.w, + height: 30.w, + fit: BoxFit.contain, + ) + : Container(), + action: () { + state.selectPassthroughListIndex.value = index; + }, + ); + }, + ), + ), + ), + ], + ), + ), ); } @@ -57,10 +136,7 @@ class _SpeechLanguageSettingsPageState () => SingleChildScrollView( child: Column( children: [ - Container( - width: 1.sw, - decoration: BoxDecoration(color: Colors.white), - child: ListView.builder( + ListView.builder( itemCount: state.soundTypeList.length, itemBuilder: (BuildContext context, int index) { // 判断是否是最后一个元素(索引等于 itemCount - 1) @@ -105,12 +181,8 @@ class _SpeechLanguageSettingsPageState ); }, shrinkWrap: true, - physics: const AlwaysScrollableScrollPhysics(), - ), - ), - SizedBox( - height: 8.h, - ), + physics: const NeverScrollableScrollPhysics() //add this line, + ), Column( children: _buildList(), ), From 02d395b7a4799f17204a4499c4015ff0fca5bce5 Mon Sep 17 00:00:00 2001 From: liyi Date: Mon, 28 Jul 2025 11:49:39 +0800 Subject: [PATCH 21/25] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E5=88=86=E4=BA=AB?= =?UTF-8?q?=E5=AF=86=E7=A0=81=E6=97=B6=E6=94=B9=E4=B8=BA=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../passwordKeyDetail_page.dart | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/main/lockDetail/passwordKey/passwordKeyDetail/passwordKeyDetail_page.dart b/lib/main/lockDetail/passwordKey/passwordKeyDetail/passwordKeyDetail_page.dart index 03c36a5c..f236265c 100755 --- a/lib/main/lockDetail/passwordKey/passwordKeyDetail/passwordKeyDetail_page.dart +++ b/lib/main/lockDetail/passwordKey/passwordKeyDetail/passwordKeyDetail_page.dart @@ -1,8 +1,8 @@ - import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:fluwx/fluwx.dart'; import 'package:get/get.dart'; import 'package:star_lock/flavors.dart'; import 'package:star_lock/main/lockDetail/passwordKey/passwordKeyDetail/passwordKeyDetail_logic.dart'; @@ -84,8 +84,8 @@ class _PasswordKeyDetailPageState extends State // showCupertinoAlertDialog( // context, state.inputNameController); // })), - Obx(() => lockDataListItem('姓名'.tr, - state.keyboardPwdName.value, () { + Obx(() => + lockDataListItem('姓名'.tr, state.keyboardPwdName.value, () { showCupertinoAlertDialog( context, state.inputNameController); })), @@ -436,7 +436,18 @@ class _PasswordKeyDetailPageState extends State final String pwdShareStr = logic.getShareContentStr(); switch (itemIndex) { case 0: //微信好友 - NativeInteractionTool().loadNativeShare(shareText: pwdShareStr); + Fluwx fluwx = Fluwx(); + fluwx.registerApi( + appId: F.wechatAppInfo.wechatAppId, + universalLink: F.wechatAppInfo.universalLink, + ); + fluwx.share( + WeChatShareTextModel( + pwdShareStr, + scene: WeChatScene.session, + ), + ); + // NativeInteractionTool().loadNativeShare(shareText: pwdShareStr); break; case 1: //短信 case 2: //邮件 From b06e3b61c89ab174e157bea5928aada49d4fdfab Mon Sep 17 00:00:00 2001 From: liyi Date: Mon, 28 Jul 2025 15:07:03 +0800 Subject: [PATCH 22/25] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E8=BF=9B=E5=85=A5?= =?UTF-8?q?=E8=AF=AD=E9=9F=B3=E5=8C=85=E8=AE=BE=E7=BD=AE=E6=97=B6=E4=B8=8D?= =?UTF-8?q?=E8=BF=9B=E8=A1=8C=E6=9B=B4=E6=96=B0=E9=80=89=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../speech_language_settings_logic.dart | 51 +++++++++++++++---- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart index 781df709..8a75a1bd 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart @@ -45,10 +45,9 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { } else if (reply is VoicePackageConfigureProcessReply) { _handlerVoicePackageConfigureProcess(reply); } else if (reply is VoicePackageConfigureConfirmationReply) { - _handlerVoicePackageConfigureConfirmation(reply); + handleVoiceConfigureThrottled(reply); } }); - await initList(); } @@ -110,14 +109,22 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { .lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang; final timbre = state .lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre; - state.languages.value.forEach((element) { - final timbres = element.timbres; - timbres.forEach((item) { - if (lang == element.lang && item.timbre == timbre) { - state.selectSoundTypeIndex.value = item.isFemale; + // 传统 for 循环,直接通过索引访问 + for (int i = 0; i < state.languages.length; i++) { + final language = state.languages[i]; // 当前元素 + if (language.lang == lang) { + print('匹配到下标:$i,元素:$language'); + final timbres = language.timbres; + for (int j = 0; j < timbres.length; j++) { + final item = timbres[j]; + if (lang == language.lang && item.timbre == timbre) { + state.selectSoundTypeIndex.value = item.isFemale; + state.selectPassthroughListIndex.value = i; + break; + } } - }); - }); + } + } } } catch (e) { debugPrint('获取语音包出现错误:$e'); @@ -358,7 +365,31 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { super.onClose(); } - void _handlerVoicePackageConfigureConfirmation( + bool _isThrottled = false; + + void handleVoiceConfigureThrottled( + VoicePackageConfigureConfirmationReply reply, + ) { + if (_isThrottled) return; + + _isThrottled = true; + + // 执行你的逻辑 + _executeLogic(reply); + + // 设置节流时间(比如 1 秒) + Future.delayed(Duration(seconds: 1), () { + _isThrottled = false; + }); + } + + Future _executeLogic( + VoicePackageConfigureConfirmationReply reply) async { + await _handlerVoicePackageConfigureConfirmation(reply); + dismissEasyLoading(); + } + + _handlerVoicePackageConfigureConfirmation( VoicePackageConfigureConfirmationReply reply, ) async { final int status = reply.data[2]; From 617c7ad9b62b3c517d58775b33ae8ef425386f54 Mon Sep 17 00:00:00 2001 From: liyi Date: Mon, 28 Jul 2025 15:58:28 +0800 Subject: [PATCH 23/25] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E5=8F=91=E9=80=81?= =?UTF-8?q?=E8=BF=87=E7=A8=8B=E4=B8=AD=E8=B6=85=E6=97=B6=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../speech_language_settings_logic.dart | 42 ++++++++++++++++++- .../lock_voice_setting_logic.dart | 33 +++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart index 8a75a1bd..4422954f 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart @@ -34,6 +34,12 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { final SpeechLanguageSettingsState state = SpeechLanguageSettingsState(); StreamSubscription? _replySubscription; +// 超时定时器(用于检测是否未收到回复) + Timer? _sendTimeoutTimer; + +// 超时标志位(可选,防止重复处理) + bool _isTimeout = false; + @override void onInit() async { super.onInit(); @@ -273,7 +279,39 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { _sendNextPackage(); } + void _handleSendTimeout() { + _isTimeout = true; // 标记超时状态 + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + showBlueConnetctToast(); + + // 重置状态,避免后续错误操作 + state.voiceSubcontractingIndex = 0; + state.voiceSubcontractingCount = 0; + state.data = null; + state.progress.value = 0.0; + _isTimeout = false; // 标记超时状态 + } + void _sendNextPackage() async { + // 若已超时,直接返回 + if (_isTimeout) return; + + // 取消上一次未完成的定时器(避免重复触发) + _sendTimeoutTimer?.cancel(); + + // 检查是否已完成所有分包发送 + if (state.voiceSubcontractingIndex >= state.voiceSubcontractingCount) { + print('所有分包已发送完成'); + state.progress.value = 1.0; + return; + } + + // 启动 3 秒超时定时器 + _sendTimeoutTimer = Timer(Duration(seconds: 3), () { + _handleSendTimeout(); // 触发超时处理 + }); + if (state.voiceSubcontractingIndex >= state.voiceSubcontractingCount) { print('所有分包已发送完成'); state.progress.value = 1.0; // 发送完成 @@ -320,6 +358,9 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { void _handlerVoicePackageConfigureProcess( VoicePackageConfigureProcessReply reply) { + // 取消超时定时器(已收到回复,无需继续等待) + _sendTimeoutTimer?.cancel(); + _isTimeout = false; // 重置超时标志 final int status = reply.data[2]; switch (status) { case 0x00: @@ -386,7 +427,6 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { Future _executeLogic( VoicePackageConfigureConfirmationReply reply) async { await _handlerVoicePackageConfigureConfirmation(reply); - dismissEasyLoading(); } _handlerVoicePackageConfigureConfirmation( diff --git a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart index dff888e9..4b0b156b 100644 --- a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart +++ b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart @@ -31,6 +31,11 @@ class LockVoiceSettingLogic extends BaseGetXController { LockVoiceSettingState state = LockVoiceSettingState(); StreamSubscription? _replySubscription; bool _isThrottled = false; +// 超时定时器(用于检测是否未收到回复) + Timer? _sendTimeoutTimer; + +// 超时标志位(可选,防止重复处理) + bool _isTimeout = false; @override void onInit() async { @@ -168,6 +173,9 @@ class LockVoiceSettingLogic extends BaseGetXController { void _handlerVoicePackageConfigureProcess( VoicePackageConfigureProcessReply reply) { + // 取消超时定时器(已收到回复,无需继续等待) + _sendTimeoutTimer?.cancel(); + _isTimeout = false; // 重置超时标志 final int status = reply.data[2]; switch (status) { case 0x00: @@ -300,8 +308,27 @@ class LockVoiceSettingLogic extends BaseGetXController { state.progress.value = 0.0; // 开始前重置进度 _sendNextPackage(); } + void _handleSendTimeout() { + _isTimeout = true; // 标记超时状态 + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + showBlueConnetctToast(); + + // 重置状态,避免后续错误操作 + state.voiceSubcontractingIndex = 0; + state.voiceSubcontractingCount = 0; + state.data = null; + state.progress.value = 0.0; + _isTimeout = false; // 标记超时状态 + } void _sendNextPackage() { + // 若已超时,直接返回 + if (_isTimeout) return; + + // 取消上一次未完成的定时器(避免重复触发) + _sendTimeoutTimer?.cancel(); + if (state.voiceSubcontractingIndex >= state.voiceSubcontractingCount) { print('所有分包已发送完成'); state.progress.value = 1.0; // 发送完成 @@ -309,6 +336,12 @@ class LockVoiceSettingLogic extends BaseGetXController { return; } + // 启动 3 秒超时定时器 + _sendTimeoutTimer = Timer(Duration(seconds: 3), () { + _handleSendTimeout(); // 触发超时处理 + }); + + int start = state.voiceSubcontractingIndex * state.voiceSubcontractingSize; int end = start + state.voiceSubcontractingSize; if (end > state.data!.length) end = state.data!.length; From a5b817ffb34027cf78fc8a3244c7524bb165aec4 Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 29 Jul 2025 13:59:52 +0800 Subject: [PATCH 24/25] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E9=94=81=E5=90=8E=E8=BF=9B=E8=A1=8C=E8=93=9D=E7=89=99=E4=BA=A4?= =?UTF-8?q?=E4=BA=92=E5=87=BA=E7=8E=B0=E9=94=81=E5=B7=B2=E9=87=8D=E7=BD=AE?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lock_voice_setting/lock_voice_setting_logic.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart index 4b0b156b..017f6dc9 100644 --- a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart +++ b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart @@ -166,6 +166,12 @@ class LockVoiceSettingLogic extends BaseGetXController { BluetoothConnectionState.disconnected) { dismissEasyLoading(); cancelBlueConnetctToastTimer(); + // 延迟1秒后重试(避免频繁请求) + Future.delayed(const Duration(seconds: 2), () { + // 递归调用自身,重试次数+1 + sendFileToDevice(data, token); + }); + // showBlueConnetctToast(); } }); From 493241b8adb6a4eaac232d7a80a4466f59c88b06 Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 29 Jul 2025 14:00:07 +0800 Subject: [PATCH 25/25] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E5=88=86=E4=BA=AB?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E4=B8=BA=E6=8F=92=E4=BB=B6=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../passwordKey_perpetual_page.dart | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart b/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart index edb88de7..7b99294e 100755 --- a/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart +++ b/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart @@ -3,9 +3,11 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:fluwx/fluwx.dart'; import 'package:get/get.dart'; import 'package:star_lock/app_settings/app_colors.dart'; import 'package:star_lock/app_settings/app_settings.dart'; +import 'package:star_lock/flavors.dart'; import 'package:star_lock/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_logic.dart'; import 'package:star_lock/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_state.dart'; import 'package:star_lock/tools/commonDataManage.dart'; @@ -859,7 +861,18 @@ class _PasswordKeyPerpetualPageState extends State final String pwdShareStr = logic.getShareContentStr(); switch (itemIndex) { case 0: //微信好友 - NativeInteractionTool().loadNativeShare(shareText: pwdShareStr); + Fluwx fluwx = Fluwx(); + fluwx.registerApi( + appId: F.wechatAppInfo.wechatAppId, + universalLink: F.wechatAppInfo.universalLink, + ); + fluwx.share( + WeChatShareTextModel( + pwdShareStr, + scene: WeChatScene.session, + ), + ); + // NativeInteractionTool().loadNativeShare(shareText: pwdShareStr); break; case 1: //短信 case 2: //邮件