diff --git a/lib/blue/sender_beforeDataManage.dart b/lib/blue/sender_beforeDataManage.dart index 79f30b4b..aa720d05 100755 --- a/lib/blue/sender_beforeDataManage.dart +++ b/lib/blue/sender_beforeDataManage.dart @@ -1,4 +1,3 @@ - import 'dart:async'; import 'package:star_lock/blue/entity/lock_user_no_list_entity.dart'; @@ -22,10 +21,10 @@ import 'io_tool/manager_event_bus.dart'; import 'sender_data.dart'; class SenderBeforeDataManage { - factory SenderBeforeDataManage() => shareManager()!; SenderBeforeDataManage._init(); + static SenderBeforeDataManage? _manager; static SenderBeforeDataManage? shareManager() { @@ -42,6 +41,7 @@ class SenderBeforeDataManage { // 监听设备返回的数据 StreamSubscription? _replySubscription; + // 是否是添加用户之前的调用 bool isBeforeAddUser = true; @@ -123,14 +123,14 @@ class SenderBeforeDataManage { final int status = reply.data[6]; switch (status) { case 0x00: - //成功 + //成功 CommonDataManage().initUserNo = 0; CommonDataManage().currentKeyInfo.initUserNo = 0; _updateLockInitUserNo(); break; case 0x06: - //无权限 + //无权限 final List token = reply.data.sublist(2, 6); final List strTokenList = changeIntListToStringList(token); Storage.setStringList(saveBlueToken, strTokenList); @@ -139,17 +139,15 @@ class SenderBeforeDataManage { CommandSenderManager().sendNormalData(transferSmartLockData); break; default: - //失败 + //失败 break; } } //获取清除用户列表指令 Future> getCleanUpUsers({List? tokenList}) async { - final LockUserNoListEntity entity = await ApiRepository.to - .getLockUserNoList(lockId: CommonDataManage().currentKeyInfo.lockId!); - if (!entity.errorCode!.codeIsSuccessful || - (entity.data?.userNos ?? []).isEmpty) { + final LockUserNoListEntity entity = await ApiRepository.to.getLockUserNoList(lockId: CommonDataManage().currentKeyInfo.lockId!); + if (!entity.errorCode!.codeIsSuccessful || (entity.data?.userNos ?? []).isEmpty) { throw Exception('ApiRepository.to.getLockUserNoList 访问失败'); } final List? privateKey = await Storage.getStringList(saveBluePrivateKey); @@ -197,27 +195,28 @@ class SenderBeforeDataManage { int endDateTime = 0; bool isRound = false; int useCountLimit = 0xffff; - if(currentKeyInfo.keyType == XSConstantMacro.keyTypeTime){ + if (currentKeyInfo.keyType == XSConstantMacro.keyTypeTime) { // 限时 startDateTime = currentKeyInfo.startDate! ~/ 1000; endDateTime = currentKeyInfo.endDate! ~/ 1000; - }else if(currentKeyInfo.keyType == XSConstantMacro.keyTypeLoop){ + } else if (currentKeyInfo.keyType == XSConstantMacro.keyTypeLoop) { // 循环 isRound = true; startTime = DateTime.fromMillisecondsSinceEpoch(currentKeyInfo.startDate!); endTime = DateTime.fromMillisecondsSinceEpoch(currentKeyInfo.endDate!); startDateTime = DateTool().dateToTimestamp(DateTool().dateToYMDString(currentKeyInfo.startDate!.toString()), 1) ~/ 1000; - endDateTime = (DateTool().dateToTimestamp(DateTool().dateToYMDString(currentKeyInfo.endDate!.toString()), 1) + CommonDataManage().dayLatestTime) ~/ 1000; - }else if(currentKeyInfo.keyType == XSConstantMacro.keyTypeOnce){ - // 单次 - useCountLimit = 1; - } + endDateTime = + (DateTool().dateToTimestamp(DateTool().dateToYMDString(currentKeyInfo.endDate!.toString()), 1) + CommonDataManage().dayLatestTime) ~/ 1000; + } else if (currentKeyInfo.keyType == XSConstantMacro.keyTypeOnce) { + // 单次 + useCountLimit = 1; + } - // AppLog.log("startTime.hour:${startTime!.hour} startTime.minute:${startTime!.minute} endTime.hour:${endTime!.hour} endTime.minute:${endTime!.minute}}"); + // AppLog.log("startTime.hour:${startTime!.hour} startTime.minute:${startTime!.minute} endTime.hour:${endTime!.hour} endTime.minute:${endTime!.minute}}"); final AddUserCommand addUserData = AddUserCommand( lockID: BlueManage().connectDeviceName, - authUserID: currentKeyInfo.senderUserId!.toString(), + authUserID: currentKeyInfo.senderUserId?.toString() ?? '1', keyID: currentKeyInfo.keyId.toString(), userID: await Storage.getUid(), openMode: 1, @@ -226,10 +225,7 @@ class SenderBeforeDataManage { expireDate: endDateTime, useCountLimit: useCountLimit, isRound: isRound ? 1 : 0, - weekRound: isRound - ? DateTool().accordingTheCycleIntoTheCorrespondingNumber( - currentKeyInfo.weekDays!) - : 0, + weekRound: isRound ? DateTool().accordingTheCycleIntoTheCorrespondingNumber(currentKeyInfo.weekDays!) : 0, startHour: isRound ? startTime!.hour : 0, startMin: isRound ? startTime!.minute : 0, endHour: isRound ? endTime!.hour : 0, @@ -271,8 +267,7 @@ class SenderBeforeDataManage { // 普通用户接收电子钥匙之后 更新锁用户NO Future _updateLockUserNo(List dataList) async { final LockNetTokenEntity entity = await ApiRepository.to.updateLockUserNo( - keyId: CommonDataManage().currentKeyInfo.keyId.toString(), - lockUserNo: CommonDataManage().currentKeyInfo.lockUserNo.toString()); + keyId: CommonDataManage().currentKeyInfo.keyId.toString(), lockUserNo: CommonDataManage().currentKeyInfo.lockUserNo.toString()); if (entity.errorCode!.codeIsSuccessful) { eventBus.fire(RefreshLockListInfoDataEvent()); eventBus.fire(LockAddUserSucceedEvent([0], 0)); @@ -281,9 +276,8 @@ class SenderBeforeDataManage { // 更新锁用户InitUserNo Future _updateLockInitUserNo() async { - final LockNetTokenEntity entity = await ApiRepository.to.updateLockInitUserNo( - lockId: CommonDataManage().currentKeyInfo.lockId ?? 0, - initUserNo: CommonDataManage().currentKeyInfo.initUserNo ?? 0); + final LockNetTokenEntity entity = await ApiRepository.to + .updateLockInitUserNo(lockId: CommonDataManage().currentKeyInfo.lockId ?? 0, initUserNo: CommonDataManage().currentKeyInfo.initUserNo ?? 0); if (entity.errorCode!.codeIsSuccessful) { eventBus.fire(RefreshLockListInfoDataEvent()); eventBus.fire(LockInitUserNoEvent()); diff --git a/lib/main/lockMian/lockList/lockList_logic.dart b/lib/main/lockMian/lockList/lockList_logic.dart index fb15f26f..e2ac2afd 100755 --- a/lib/main/lockMian/lockList/lockList_logic.dart +++ b/lib/main/lockMian/lockList/lockList_logic.dart @@ -88,17 +88,18 @@ class LockListLogic extends BaseGetXController { break; case 0x06: //无权限 - final List? token = await Storage.getStringList(saveBlueToken); - final List getTokenList = changeStringListToIntList(token!); - + final List tokenData = reply.data.sublist(2, 6); + final List saveStrList = changeIntListToStringList(tokenData); + Storage.setStringList(saveBlueToken, saveStrList); IoSenderManage.senderFactoryDataReset( - lockID: BlueManage().connectDeviceName, - userID: await Storage.getUid(), - keyID: '1', - needAuthor: 1, - publicKey: state.lockListInfoItemEntity.value.bluetooth!.publicKey!.cast(), - privateKey: state.lockListInfoItemEntity.value.bluetooth!.privateKey!.cast(), - token: getTokenList); + lockID: BlueManage().connectDeviceName, + userID: await Storage.getUid(), + keyID: '1', + needAuthor: 1, + publicKey: state.publicKey, + privateKey: state.privateKey, + token: tokenData, + ); break; case 0x07: //无权限 @@ -172,14 +173,14 @@ class LockListLogic extends BaseGetXController { } /// 以下为删除逻辑 - void deleyLockLogicOfRoles() { + void deleyLockLogicOfRoles(LockListInfoItemEntity keyInfo) { if (state.lockListInfoItemEntity.value.isLockOwner == 1) { // 超级管理员必须通过连接蓝牙删除 showTipView.showIosTipWithContentDialog('删除锁后,所有信息都会一起删除,确定删除锁吗?'.tr, () { // 删除锁 AppLog.log('调用了删除锁'); showTipView.resetGetController(); - showTipView.showTFViewAlertDialog(state.passwordTF, '请输入登录密码'.tr, '请输入登录密码'.tr, checkLoginPassword); + showTipView.showTFViewAlertDialog(state.passwordTF, '请输入登录密码'.tr, '请输入登录密码'.tr, () => checkLoginPassword(keyInfo)); }); } else if (state.lockListInfoItemEntity.value.keyRight == 1) { // 授权管理员弹框提示 @@ -195,13 +196,13 @@ class LockListLogic extends BaseGetXController { } // 查询账户密码 - Future checkLoginPassword() async { + Future checkLoginPassword(LockListInfoItemEntity keyInfo) async { final LockListInfoEntity entity = await ApiRepository.to.checkLoginPassword( password: state.passwordTF.text, ); if (entity.errorCode!.codeIsSuccessful) { Get.back(); - factoryDataResetAction(); + factoryDataResetAction(keyInfo); } } @@ -233,7 +234,7 @@ class LockListLogic extends BaseGetXController { } // 恢复出厂设置 - Future factoryDataResetAction() async { + Future factoryDataResetAction(LockListInfoItemEntity keyInfo) async { showEasyLoading(); showBlueConnetctToastTimer( isShowBlueConnetctToast: false, @@ -241,15 +242,13 @@ class LockListLogic extends BaseGetXController { dismissEasyLoading(); showDeletAlertTipDialog(); }); - BlueManage().blueSendData(state.lockListInfoItemEntity.value.lockName!, (BluetoothConnectionState connectionState) - async { + BlueManage().blueSendData(state.lockListInfoItemEntity.value.lockName!, (BluetoothConnectionState connectionState) async { if (connectionState == BluetoothConnectionState.connected) { final List publicKeyData = state.lockListInfoItemEntity.value.bluetooth!.publicKey!.cast(); final List saveStrList = changeIntListToStringList(publicKeyData); await Storage.setStringList(saveBluePublicKey, saveStrList); // 私钥 - final List? privateKey = await Storage.getStringList(saveBluePrivateKey); final List privateKeyData = state.lockListInfoItemEntity.value.bluetooth!.privateKey!.cast(); final List savePrivateKeyList = changeIntListToStringList(privateKeyData); await Storage.setStringList(saveBluePrivateKey, savePrivateKeyList); @@ -262,15 +261,18 @@ class LockListLogic extends BaseGetXController { final List saveTokenList = changeIntListToStringList([0, 0, 0, 0]); await Storage.setStringList(saveBlueToken, saveTokenList); - IoSenderManage.senderFactoryDataReset( lockID: BlueManage().connectDeviceName, userID: await Storage.getUid(), keyID: '1', needAuthor: 1, - publicKey: publicKeyData, - privateKey: privateKeyData, + publicKey: keyInfo.bluetooth?.publicKey ?? [], + privateKey: keyInfo.bluetooth?.privateKey ?? [], token: [0, 0, 0, 0]); + state.publicKey.value = keyInfo.bluetooth?.publicKey ?? []; + state.privateKey.value = keyInfo.bluetooth?.privateKey ?? []; + state.publicKey.refresh(); + state.privateKey.refresh(); } else if (connectionState == BluetoothConnectionState.disconnected) { dismissEasyLoading(); cancelBlueConnetctToastTimer(); diff --git a/lib/main/lockMian/lockList/lockList_page.dart b/lib/main/lockMian/lockList/lockList_page.dart index 2bade0dc..b8ef7fa2 100755 --- a/lib/main/lockMian/lockList/lockList_page.dart +++ b/lib/main/lockMian/lockList/lockList_page.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:get/get.dart'; +import 'package:star_lock/app_settings/app_settings.dart'; import 'package:star_lock/main/lockMian/lockList/lockList_state.dart'; import '../../../appRouters.dart'; @@ -14,8 +15,7 @@ import 'lockListGroup_view.dart'; import 'lockList_logic.dart'; class LockListPage extends StatefulWidget { - const LockListPage({required this.lockListInfoGroupEntity, Key? key}) - : super(key: key); + const LockListPage({required this.lockListInfoGroupEntity, Key? key}) : super(key: key); final LockListInfoGroupEntity lockListInfoGroupEntity; @override @@ -30,41 +30,41 @@ class _LockListPageState extends State with RouteAware { void initState() { super.initState(); logic = Get.put(LockListLogic(widget.lockListInfoGroupEntity)); - state = Get - .find() - .state; + state = Get.find().state; } @override Widget build(BuildContext context) { - return Obx(() => Scaffold( - body: ListView.separated( - itemCount: logic.groupDataListFiltered.length, - itemBuilder: (BuildContext context, int index) { - final GroupList itemData = logic.groupDataListFiltered[index]; - return _buildLockExpandedList(context, index, itemData, key: ValueKey(itemData.groupId)); - }, - shrinkWrap: true, - physics: const AlwaysScrollableScrollPhysics(), - separatorBuilder: (BuildContext context, int index) { - return const Divider( - height: 1, - color: AppColors.greyLineColor, - ); - }), - )); + return Obx( + () => Scaffold( + body: ListView.separated( + itemCount: logic.groupDataList.length, + itemBuilder: (BuildContext context, int index) { + final GroupList itemData = logic.groupDataListFiltered[index]; + return _buildLockExpandedList(context, index, itemData, key: ValueKey(itemData.groupId)); + }, + shrinkWrap: true, + physics: const AlwaysScrollableScrollPhysics(), + separatorBuilder: (BuildContext context, int index) { + return const Divider( + height: 1, + color: AppColors.greyLineColor, + ); + }, + ), + ), + ); } //设备多层级列表 - Widget _buildLockExpandedList(BuildContext context, int index, - GroupList itemData, {Key? key}) { - final List lockItemList = - itemData.lockList ?? []; + Widget _buildLockExpandedList(BuildContext context, int index, GroupList itemData, {Key? key}) { + final List lockItemList = itemData.lockList ?? []; return LockListGroupView( key: key, onTap: () { //是否选中组 - if (itemData.isChecked) {} else {} + if (itemData.isChecked) { + } else {} setState(() {}); }, typeImgList: const [], @@ -91,9 +91,12 @@ class _LockListPageState extends State with RouteAware { children: [ SlidableAction( onPressed: (BuildContext context) { + state.publicKey.value = keyInfo.bluetooth?.publicKey ?? []; + state.privateKey.value = keyInfo.bluetooth?.privateKey ?? []; state.lockListInfoItemEntity.value = keyInfo; state.lockListInfoItemEntity.refresh(); - logic.deleyLockLogicOfRoles(); + AppLog.log('msg=================:${state.lockListInfoItemEntity.value}'); + logic.deleyLockLogicOfRoles(keyInfo); }, backgroundColor: Colors.red, foregroundColor: Colors.white, @@ -103,58 +106,46 @@ class _LockListPageState extends State with RouteAware { ], ), child: lockInfoListItem(keyInfo, isLast, () { - if ((keyInfo.keyType == XSConstantMacro.keyTypeTime || - keyInfo.keyType == XSConstantMacro.keyTypeLoop) && - (keyInfo.keyStatus == - XSConstantMacro.keyStatusWaitIneffective)) { + if ((keyInfo.keyType == XSConstantMacro.keyTypeTime || keyInfo.keyType == XSConstantMacro.keyTypeLoop) && + (keyInfo.keyStatus == XSConstantMacro.keyStatusWaitIneffective)) { logic.showToast('您的钥匙未生效'.tr); return; } if ((keyInfo.keyType == XSConstantMacro.keyTypeTime || - keyInfo.keyType == XSConstantMacro.keyTypeLong || - keyInfo.keyType == XSConstantMacro.keyTypeLoop) && + keyInfo.keyType == XSConstantMacro.keyTypeLong || + keyInfo.keyType == XSConstantMacro.keyTypeLoop) && (keyInfo.keyStatus == XSConstantMacro.keyStatusFrozen)) { logic.showToast('您的钥匙已冻结'.tr); return; } - if ((keyInfo.keyType == XSConstantMacro.keyTypeTime || - keyInfo.keyType == XSConstantMacro.keyTypeLoop) && + if ((keyInfo.keyType == XSConstantMacro.keyTypeTime || keyInfo.keyType == XSConstantMacro.keyTypeLoop) && (keyInfo.keyStatus == XSConstantMacro.keyStatusExpired)) { logic.showToast('您的钥匙已过期'.tr); return; } - Get.toNamed(Routers.lockDetailMainPage, - arguments: { - // "lockMainEntity": widget.lockMainEntity, - 'keyInfo': keyInfo, - 'isOnlyOneData': false, - }); + Get.toNamed(Routers.lockDetailMainPage, arguments: { + // "lockMainEntity": widget.lockMainEntity, + 'keyInfo': keyInfo, + 'isOnlyOneData': false, + }); }), ); }), ); } - Widget lockInfoListItem(LockListInfoItemEntity keyInfo, bool isLast, - Function() action) { + Widget lockInfoListItem(LockListInfoItemEntity keyInfo, bool isLast, Function() action) { return GestureDetector( onTap: action, child: Container( // height: 122.h, - margin: isLast - ? EdgeInsets.only(left: 20.w, right: 20.w, top: 20.w, bottom: 20.w) - : EdgeInsets.only(left: 20.w, right: 20.w, top: 20.w), + margin: isLast ? EdgeInsets.only(left: 20.w, right: 20.w, top: 20.w, bottom: 20.w) : EdgeInsets.only(left: 20.w, right: 20.w, top: 20.w), decoration: BoxDecoration( - color: (((keyInfo.keyType == XSConstantMacro.keyTypeTime || - keyInfo.keyType == XSConstantMacro.keyTypeLoop) && - (keyInfo.keyStatus == - XSConstantMacro.keyStatusWaitIneffective || - keyInfo.keyStatus == - XSConstantMacro.keyStatusFrozen || - keyInfo.keyStatus == - XSConstantMacro.keyStatusExpired)) || - (keyInfo.keyType == XSConstantMacro.keyTypeLong && - keyInfo.keyStatus == XSConstantMacro.keyStatusFrozen)) + color: (((keyInfo.keyType == XSConstantMacro.keyTypeTime || keyInfo.keyType == XSConstantMacro.keyTypeLoop) && + (keyInfo.keyStatus == XSConstantMacro.keyStatusWaitIneffective || + keyInfo.keyStatus == XSConstantMacro.keyStatusFrozen || + keyInfo.keyStatus == XSConstantMacro.keyStatusExpired)) || + (keyInfo.keyType == XSConstantMacro.keyTypeLong && keyInfo.keyStatus == XSConstantMacro.keyStatusFrozen)) ? AppColors.greyBackgroundColor : Colors.white, borderRadius: BorderRadius.circular(20.w), @@ -178,9 +169,7 @@ class _LockListPageState extends State with RouteAware { style: TextStyle( fontSize: 24.sp, fontWeight: FontWeight.w500, - color: keyInfo.passageMode == 1 - ? AppColors.openPassageModeColor - : AppColors.darkGrayTextColor), + color: keyInfo.passageMode == 1 ? AppColors.openPassageModeColor : AppColors.darkGrayTextColor), ), ], ), @@ -194,8 +183,7 @@ class _LockListPageState extends State with RouteAware { SizedBox(width: 2.w), Text( '${keyInfo.electricQuantity!}%', - style: TextStyle( - fontSize: 18.sp, color: AppColors.darkGrayTextColor), + style: TextStyle(fontSize: 18.sp, color: AppColors.darkGrayTextColor), ), SizedBox(width: 30.w), ], @@ -212,10 +200,7 @@ class _LockListPageState extends State with RouteAware { borderRadius: BorderRadius.circular(5.w), color: AppColors.openPassageModeColor, ), - child: Text('常开模式开启'.tr, - style: TextStyle( - fontSize: 18.sp, - color: AppColors.appBarIconColor)), + child: Text('常开模式开启'.tr, style: TextStyle(fontSize: 18.sp, color: AppColors.appBarIconColor)), ), ], )), @@ -227,8 +212,7 @@ class _LockListPageState extends State with RouteAware { SizedBox(width: 30.w), Text( '远程开锁'.tr, - style: TextStyle( - fontSize: 18.sp, color: AppColors.darkGrayTextColor), + style: TextStyle(fontSize: 18.sp, color: AppColors.darkGrayTextColor), ), ], )), @@ -242,15 +226,11 @@ class _LockListPageState extends State with RouteAware { padding: EdgeInsets.only(right: 5.w, left: 5.w), decoration: BoxDecoration( borderRadius: BorderRadius.circular(5.w), - color: - DateTool().compareTimeIsOvertime(keyInfo.endDate!) - ? AppColors.listTimeYellowColor - : AppColors.mainColor, - ), - child: Text(logic.getKeyEffective(keyInfo), - style: TextStyle(fontSize: 18.sp, color: Colors.white) - // child: Text(logic.compareTimeIsOvertime(keyInfo.endDate!) ? "已过期" : "余${logic.compareTimeGetDaysFromNow(keyInfo.endDate!)}天", style: TextStyle(fontSize: 18.sp, color: Colors.white) + color: DateTool().compareTimeIsOvertime(keyInfo.endDate!) ? AppColors.listTimeYellowColor : AppColors.mainColor, ), + child: Text(logic.getKeyEffective(keyInfo), style: TextStyle(fontSize: 18.sp, color: Colors.white) + // child: Text(logic.compareTimeIsOvertime(keyInfo.endDate!) ? "已过期" : "余${logic.compareTimeGetDaysFromNow(keyInfo.endDate!)}天", style: TextStyle(fontSize: 18.sp, color: Colors.white) + ), ), ], )), @@ -259,13 +239,8 @@ class _LockListPageState extends State with RouteAware { children: [ SizedBox(width: 30.w), Text( - "${logic.getUseKeyTypeStr(keyInfo.startDate, keyInfo.endDate, - keyInfo.keyType)}/${keyInfo.isLockOwner == 1 - ? '超级管理员'.tr - : (keyInfo.keyRight == 1 ? "授权管理员".tr : "普通用户" - .tr)}", - style: TextStyle( - fontSize: 18.sp, color: AppColors.darkGrayTextColor), + "${logic.getUseKeyTypeStr(keyInfo.startDate, keyInfo.endDate, keyInfo.keyType)}/${keyInfo.isLockOwner == 1 ? '超级管理员'.tr : (keyInfo.keyRight == 1 ? "授权管理员".tr : "普通用户".tr)}", + style: TextStyle(fontSize: 18.sp, color: AppColors.darkGrayTextColor), ), ], ), @@ -287,13 +262,10 @@ class _LockListPageState extends State with RouteAware { @override void dispose() { Get.delete(); + /// 取消路由订阅 AppRouteObserver().routeObserver.unsubscribe(this); - super - . - dispose - ( - ); + super.dispose(); } /// 从上级界面进入 当前界面即将出现 diff --git a/lib/main/lockMian/lockList/lockList_state.dart b/lib/main/lockMian/lockList/lockList_state.dart index 223d99c7..8995d1e0 100755 --- a/lib/main/lockMian/lockList/lockList_state.dart +++ b/lib/main/lockMian/lockList/lockList_state.dart @@ -14,5 +14,7 @@ class LockListState{ RxBool ifCurrentScreen = true.obs; // 是否是当前界面,用于判断是否需要针对当前界面进行展示 RxBool showSearch = false.obs; // 是否是当前界面,用于判断是否需要针对当前界面进行展示 RxString searchStr = ''.obs; // 是否是当前界面,用于判断是否需要针对当前界面进行展示 + RxList publicKey=[].obs; + RxList privateKey=[].obs; } \ No newline at end of file diff --git a/lib/main/lockMian/lockList/lockList_xhj_page.dart b/lib/main/lockMian/lockList/lockList_xhj_page.dart index d799c903..5e1acb4c 100755 --- a/lib/main/lockMian/lockList/lockList_xhj_page.dart +++ b/lib/main/lockMian/lockList/lockList_xhj_page.dart @@ -194,7 +194,7 @@ class _LockListXHJPageState extends State with RouteAware { onPressed: (BuildContext context) { state.lockListInfoItemEntity.value = keyInfo; state.lockListInfoItemEntity.refresh(); - logic.deleyLockLogicOfRoles(); + logic.deleyLockLogicOfRoles(keyInfo); }, backgroundColor: Colors.red, foregroundColor: Colors.white, diff --git a/lib/talk/starChart/handle/impl/udp_talk_data_handler.dart b/lib/talk/starChart/handle/impl/udp_talk_data_handler.dart index 53479218..c85bb56c 100644 --- a/lib/talk/starChart/handle/impl/udp_talk_data_handler.dart +++ b/lib/talk/starChart/handle/impl/udp_talk_data_handler.dart @@ -36,7 +36,7 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle implements ScpMessageHandl if (scpMessage.Payload != null) { final TalkData talkData = scpMessage.Payload; - AppLog.log('收到数据'); + _handleTalkData( talkData: talkData, scpMessage: scpMessage, 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 7d0b99cf..9a646dfc 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 @@ -104,10 +104,8 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { codecType: 'h264', ); // 初始化解码器并获取textureId - AppLog.log( - 'StartChartManage().videoWidth:${StartChartManage().videoWidth}'); - AppLog.log( - 'StartChartManage().videoHeight:${StartChartManage().videoHeight}'); + AppLog.log('StartChartManage().videoWidth:${StartChartManage().videoWidth}'); + AppLog.log('StartChartManage().videoHeight:${StartChartManage().videoHeight}'); final textureId = await VideoDecodePlugin.initDecoder(config); if (textureId != null) { Future.microtask(() => state.textureId.value = textureId); @@ -172,15 +170,11 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { ScpMessage scpMessage, ) { // 动态回绕阈值判断,frameSeq较小时阈值也小 - if (!_pendingStreamReset && - _lastFrameSeq != null && - frameType == TalkDataH264Frame_FrameTypeE.I && - frameSeq < _lastFrameSeq!) { + if (!_pendingStreamReset && _lastFrameSeq != null && frameType == TalkDataH264Frame_FrameTypeE.I && frameSeq < _lastFrameSeq!) { int dynamicThreshold = _getFrameSeqRolloverThreshold(_lastFrameSeq!); if ((_lastFrameSeq! - frameSeq) > dynamicThreshold) { // 检测到新流I帧,frameSeq大幅回绕,进入loading并重置所有本地状态 - AppLog.log( - '检测到新流I帧,frameSeq大幅回绕,进入loading并重置: frameSeq=$frameSeq, lastFrameSeq=$_lastFrameSeq, 阈值=$dynamicThreshold'); + AppLog.log('检测到新流I帧,frameSeq大幅回绕,进入loading并重置: frameSeq=$frameSeq, lastFrameSeq=$_lastFrameSeq, 阈值=$dynamicThreshold'); Future.microtask(() => state.isLoading.value = true); _pendingStreamReset = true; // 先暂停帧处理定时器,防止竞态 @@ -197,8 +191,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { // 继续往下执行 } else { // 小幅度乱序,直接丢弃 - AppLog.log( - '检测到I帧乱序(未超过回绕阈值$dynamicThreshold),丢弃: frameSeq=$frameSeq, lastFrameSeq=$_lastFrameSeq'); + AppLog.log('检测到I帧乱序(未超过回绕阈值$dynamicThreshold),丢弃: frameSeq=$frameSeq, lastFrameSeq=$_lastFrameSeq'); return; } } @@ -238,8 +231,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { // 如果缓冲区超出最大大小,优先丢弃P/B帧 while (state.h264FrameBuffer.length >= state.maxFrameBufferSize) { - int pbIndex = state.h264FrameBuffer - .indexWhere((f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.P); + int pbIndex = state.h264FrameBuffer.indexWhere((f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.P); if (pbIndex != -1) { state.h264FrameBuffer.removeAt(pbIndex); } else { @@ -260,8 +252,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { final int intervalMs = (1000 / state.targetFps).round(); // 创建新定时器 - state.frameProcessTimer = - Timer.periodic(Duration(milliseconds: intervalMs), (timer) { + state.frameProcessTimer = Timer.periodic(Duration(milliseconds: intervalMs), (timer) { _processNextFrameFromBuffer(); }); AppLog.log('启动帧处理定时器,目标帧率: ${state.targetFps}fps,间隔: ${intervalMs}ms'); @@ -280,24 +271,18 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { } // 优先查找I帧,按frameSeq最小的I帧消费 - final iFrames = state.h264FrameBuffer - .where((f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.I) - .toList(); - iFrames - .sort((a, b) => (a['frameSeq'] as int).compareTo(b['frameSeq'] as int)); + final iFrames = state.h264FrameBuffer.where((f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.I).toList(); + iFrames.sort((a, b) => (a['frameSeq'] as int).compareTo(b['frameSeq'] as int)); if (iFrames.isNotEmpty) { // 有I帧,消费最小的I帧,并记录其frameSeq final minIFrame = iFrames.first; final minIFrameSeq = minIFrame['frameSeq']; final targetIndex = state.h264FrameBuffer.indexWhere( - (f) => - f['frameType'] == TalkDataH264Frame_FrameTypeE.I && - f['frameSeq'] == minIFrameSeq, + (f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.I && f['frameSeq'] == minIFrameSeq, ); state.isProcessingFrame = true; - final Map? frameMap = - state.h264FrameBuffer.removeAt(targetIndex); + final Map? frameMap = state.h264FrameBuffer.removeAt(targetIndex); if (frameMap == null) { state.isProcessingFrame = false; return; @@ -308,11 +293,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { final int? frameSeqI = frameMap['frameSeqI']; final int? pts = frameMap['pts']; final ScpMessage? scpMessage = frameMap['scpMessage']; - if (frameData == null || - frameType == null || - frameSeq == null || - frameSeqI == null || - pts == null) { + if (frameData == null || frameType == null || frameSeq == null || frameSeqI == null || pts == null) { state.isProcessingFrame = false; return; } @@ -321,11 +302,8 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { return; } lastDecodedIFrameSeq = minIFrameSeq; - // AppLog.log('送入解码器的P帧数据frameSeq:${frameSeq},frameSeqI:${frameSeqI},' - // 'frameType:${frameType},messageId:${scpMessage!.MessageId}'); - // final spsData = NaluUtils.filterNalusByType(frameData, 7); - // final ppsData = NaluUtils.filterNalusByType(frameData, 8); - // AppLog.log('SPSDATA:${spsData},ppsData:${ppsData}'); + AppLog.log('送入解码器的P帧数据frameSeq:${frameSeq},frameSeqI:${frameSeqI},' + 'frameType:${frameType},messageId:${scpMessage!.MessageId}'); await VideoDecodePlugin.sendFrame( frameData: frameData, frameType: 0, @@ -340,24 +318,16 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { // 没有I帧时,只消费refIFrameSeq等于lastDecodedIFrameSeq的P帧 if (lastDecodedIFrameSeq != null) { - final validPFrames = state.h264FrameBuffer - .where((f) => - f['frameType'] == TalkDataH264Frame_FrameTypeE.P && - f['frameSeqI'] == lastDecodedIFrameSeq) - .toList(); + final validPFrames = + state.h264FrameBuffer.where((f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.P && f['frameSeqI'] == lastDecodedIFrameSeq).toList(); if (validPFrames.isNotEmpty) { - validPFrames.sort( - (a, b) => (a['frameSeq'] as int).compareTo(b['frameSeq'] as int)); + validPFrames.sort((a, b) => (a['frameSeq'] as int).compareTo(b['frameSeq'] as int)); final minPFrame = validPFrames.first; final targetIndex = state.h264FrameBuffer.indexWhere( - (f) => - f['frameType'] == TalkDataH264Frame_FrameTypeE.P && - f['frameSeq'] == minPFrame['frameSeq'] && - f['frameSeqI'] == lastDecodedIFrameSeq, + (f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.P && f['frameSeq'] == minPFrame['frameSeq'] && f['frameSeqI'] == lastDecodedIFrameSeq, ); state.isProcessingFrame = true; - final Map? frameMap = - state.h264FrameBuffer.removeAt(targetIndex); + final Map? frameMap = state.h264FrameBuffer.removeAt(targetIndex); if (frameMap == null) { state.isProcessingFrame = false; return; @@ -368,11 +338,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { final int? frameSeqI = frameMap['frameSeqI']; final int? pts = frameMap['pts']; final ScpMessage? scpMessage = frameMap['scpMessage']; - if (frameData == null || - frameType == null || - frameSeq == null || - frameSeqI == null || - pts == null) { + if (frameData == null || frameType == null || frameSeq == null || frameSeqI == null || pts == null) { state.isProcessingFrame = false; return; } @@ -427,8 +393,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { AppLog.log("==== 启动新的数据流监听 ===="); _isListening = true; - _streamSubscription = state.talkDataRepository.talkDataStream - .listen((TalkDataModel talkDataModel) async { + _streamSubscription = state.talkDataRepository.talkDataStream.listen((TalkDataModel talkDataModel) async { _processFrame(talkDataModel); }); } @@ -437,8 +402,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { void _playAudioFrames() { // 如果缓冲区为空或未达到目标大小,不进行播放 // 音频缓冲区要求更小,以减少延迟 - if (state.audioBuffer.isEmpty || - state.audioBuffer.length < audioBufferSize) { + if (state.audioBuffer.isEmpty || state.audioBuffer.length < audioBufferSize) { return; } @@ -446,8 +410,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { TalkData? oldestFrame; int oldestIndex = -1; for (int i = 0; i < state.audioBuffer.length; i++) { - if (oldestFrame == null || - state.audioBuffer[i].durationMs < oldestFrame.durationMs) { + if (oldestFrame == null || state.audioBuffer[i].durationMs < oldestFrame.durationMs) { oldestFrame = state.audioBuffer[i]; oldestIndex = i; } @@ -477,8 +440,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { break; case TalkStatus.answeredSuccessfully: state.oneMinuteTimeTimer?.cancel(); // 取消旧定时器 - state.oneMinuteTimeTimer ??= - Timer.periodic(const Duration(seconds: 1), (Timer t) { + state.oneMinuteTimeTimer ??= Timer.periodic(const Duration(seconds: 1), (Timer t) { if (state.isLoading.isFalse) { state.oneMinuteTime.value++; } @@ -493,9 +455,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { /// 播放音频数据 void _playAudioData(TalkData talkData) async { - if (state.isOpenVoice.value && - state.isLoading.isFalse && - state.isRecordingAudio.value == false) { + if (state.isOpenVoice.value && state.isLoading.isFalse && state.isRecordingAudio.value == false) { List encodedData = G711Tool.decode(talkData.content, 0); // 0表示A-law // 将 PCM 数据转换为 PcmArrayInt16 final PcmArrayInt16 fromList = PcmArrayInt16.fromList(encodedData); @@ -670,11 +630,9 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { AppLog.log('截图失败: 未找到当前上下文'); return; } - final RenderRepaintBoundary boundary = state.globalKey.currentContext! - .findRenderObject()! as RenderRepaintBoundary; + final RenderRepaintBoundary boundary = state.globalKey.currentContext!.findRenderObject()! as RenderRepaintBoundary; final ui.Image image = await boundary.toImage(); - final ByteData? byteData = - await image.toByteData(format: ui.ImageByteFormat.png); + final ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png); if (byteData == null) { AppLog.log('截图失败: 图像数据为空'); @@ -702,15 +660,13 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { // 远程开锁 Future remoteOpenLock() async { - final LockListInfoItemEntity currentKeyInfo = - CommonDataManage().currentKeyInfo; + final LockListInfoItemEntity currentKeyInfo = CommonDataManage().currentKeyInfo; var lockId = currentKeyInfo.lockId ?? 0; var remoteUnlock = currentKeyInfo.lockSetting?.remoteUnlock ?? 0; final lockPeerId = StartChartManage().lockPeerId; - final LockListInfoGroupEntity? lockListInfoGroupEntity = - await Storage.getLockMainListData(); + final LockListInfoGroupEntity? lockListInfoGroupEntity = await Storage.getLockMainListData(); if (lockListInfoGroupEntity != null) { lockListInfoGroupEntity!.groupList?.forEach((element) { final lockList = element.lockList; @@ -728,8 +684,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { }); } if (remoteUnlock == 1) { - final LoginEntity entity = await ApiRepository.to - .remoteOpenLock(lockId: lockId.toString(), timeOut: 60); + final LoginEntity entity = await ApiRepository.to.remoteOpenLock(lockId: lockId.toString(), timeOut: 60); if (entity.errorCode!.codeIsSuccessful) { showToast('已开锁'.tr); StartChartManage().lockListPeerId = []; @@ -756,8 +711,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { state.startRecordingAudioTime.value = DateTime.now(); // 增加录音帧监听器和错误监听器 - state.voiceProcessor - ?.addFrameListeners([_onFrame]); + state.voiceProcessor?.addFrameListeners([_onFrame]); state.voiceProcessor?.addErrorListener(_onError); } else { // state.errorMessage.value = 'Recording permission not granted'; @@ -777,8 +731,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { state.endRecordingAudioTime.value = DateTime.now(); // 计算录音的持续时间 - final Duration duration = state.endRecordingAudioTime.value - .difference(state.startRecordingAudioTime.value); + final Duration duration = state.endRecordingAudioTime.value.difference(state.startRecordingAudioTime.value); state.recordingAudioTime.value = duration.inSeconds; } on PlatformException catch (ex) { @@ -848,10 +801,8 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { _bufferedAudioFrames.addAll(encodedData); // 启动定时发送器(仅启动一次) - if (_startProcessingAudioTimer == null && - _bufferedAudioFrames.length > chunkSize) { - _startProcessingAudioTimer = - Timer.periodic(Duration(milliseconds: intervalMs), _sendAudioChunk); + if (_startProcessingAudioTimer == null && _bufferedAudioFrames.length > chunkSize) { + _startProcessingAudioTimer = Timer.periodic(Duration(milliseconds: intervalMs), _sendAudioChunk); } } @@ -887,8 +838,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { } /// 修改发送预期数据 - StartChartManage().changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer( - talkExpect: talkExpectReq); + StartChartManage().changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer(talkExpect: talkExpectReq); // 不立即loading,继续解码旧流帧,等待frameSeq回绕检测 // 仅重置frameSeq回绕检测标志