From eb1c0185814203f2db73703addbf4c5254116107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CDaisyWu=E2=80=9D?= <“18682150237@163.com”> Date: Tue, 17 Dec 2024 17:07:59 +0800 Subject: [PATCH] =?UTF-8?q?feat:=201=EF=BC=8C=E6=96=B0=E5=A2=9E=E7=94=B5?= =?UTF-8?q?=E5=AD=90=E5=8F=8D=E9=94=81UI=E5=8F=8A=E6=9C=AC=E5=9C=B0?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=20=092=EF=BC=8C=E6=96=B0=E5=A2=9E=E5=8F=AF?= =?UTF-8?q?=E8=A7=86=E9=97=A8=E9=93=83=E7=A0=81=E5=9B=BD=E9=99=85=E5=8C=96?= =?UTF-8?q?UI=E5=8F=8A=E6=9C=AC=E5=9C=B0=E5=8A=9F=E8=83=BD=20=093=EF=BC=8C?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=8F=8C=E9=87=8D=E8=AE=A4=E8=AF=81UI?= =?UTF-8?q?=E5=8F=8A=E6=9C=AC=E5=9C=B0=E5=8A=9F=E8=83=BD=20=094=EF=BC=8C?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=8F=8C=E9=94=81=E8=81=94=E5=8A=A8UI?= =?UTF-8?q?=E5=8F=8A=E6=9C=AC=E5=9C=B0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/appRouters.dart | 5 + .../double_lock_link_logic.dart | 54 +++++++ .../double_lock_link_page.dart | 149 ++++++++++++++++++ .../double_lock_link_state.dart | 11 ++ .../lockSet/lockSet/lockSet_page.dart | 95 +++++++++++ .../lockSet/lockSet/lockSet_state.dart | 5 +- lib/tools/showCupertinoAlertView.dart | 105 +++++++++++- 7 files changed, 422 insertions(+), 2 deletions(-) create mode 100644 lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_logic.dart create mode 100644 lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_page.dart create mode 100644 lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_state.dart diff --git a/lib/appRouters.dart b/lib/appRouters.dart index 12fbb302..4a51db4e 100755 --- a/lib/appRouters.dart +++ b/lib/appRouters.dart @@ -21,6 +21,7 @@ import 'package:star_lock/main/lockDetail/lockDetail/lockDetail_main_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/catEyeSet/catEyeCustomMode/catEyeCustomMode_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/catEyeSet/videoSlot/videoSlot_page.dart'; +import 'package:star_lock/main/lockDetail/lockSet/double_lock_link/double_lock_link_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/faceUnlock/faceUnlock_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/liveVideo/liveVideo_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/motorPower/motorPower_page.dart'; @@ -509,6 +510,7 @@ abstract class Routers { static const String login = '/login'; //登录 static const String amazonAlexaPage = '/amazonAlexaPage'; //AmazonAlexa static const String googleHomePage = '/googleHomePage'; //GoogleHome + static const String doubleLockLinkPage = '/doubleLockLinkPage'; //双锁联动 } abstract class AppRouters { @@ -1183,5 +1185,8 @@ abstract class AppRouters { GetPage( name: Routers.gatewayGetWifiListPage, page: () => const GatewayGetWifiListPage()), + GetPage( + name: Routers.doubleLockLinkPage, + page: () => const DoubleLockLinkPage()), ]; } diff --git a/lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_logic.dart b/lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_logic.dart new file mode 100644 index 00000000..8652afa1 --- /dev/null +++ b/lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_logic.dart @@ -0,0 +1,54 @@ +import 'package:get/get.dart'; +import 'package:star_lock/main/lockDetail/lockSet/double_lock_link/double_lock_link_state.dart'; +import 'package:star_lock/main/lockMian/lockMain/lockMain_logic.dart'; +import 'package:star_lock/mine/mineSet/appUnlockNeedMobileNetworkingLock/selectLockListEntity.dart'; +import 'package:star_lock/network/api_repository.dart'; +import 'package:star_lock/tools/baseGetXController.dart'; + +class DoubleLockLinkLogic extends BaseGetXController { + final DoubleLockLinkState state = DoubleLockLinkState(); + + //请求锁列表 + Future mockNetworkDataRequest() async { + final SelectLockListEntity entity = await ApiRepository.to + .selectLockList(searchStr: state.searchController.text); + List dataList = []; + if (entity.errorCode!.codeIsSuccessful) { + dataList = entity.data!.list!; + state.lockItemList.value = dataList; + for (int i = 0; i < dataList.length; i++) { + final LockItemData itemData = dataList[i]; + if (itemData.appUnlockOnline == 1) { + state.selectLockIdList.add(itemData.lockId); + } + } + } + return entity; + } + + //APP开锁时需手机联网的锁 + Future setAppUnlockMustOnlineRequest() async { + final SelectLockListEntity entity = + await ApiRepository.to.setAppUnlockMustOnline(state.selectLockIdList); + if (entity.errorCode!.codeIsSuccessful) { + showToast('操作成功'.tr); + + //刷新锁列表,更新锁详情--手机需联网标识 + if (Get.isRegistered()) { + Get.find().getStarLockInfo(isUnShowLoading: true); + } + } + } + + @override + void onReady() { + super.onReady(); + + // mockNetworkDataRequest(); + } + + @override + void onInit() { + super.onInit(); + } +} diff --git a/lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_page.dart b/lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_page.dart new file mode 100644 index 00000000..9fb5a687 --- /dev/null +++ b/lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_page.dart @@ -0,0 +1,149 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:star_lock/app_settings/app_colors.dart'; +import 'package:star_lock/main/lockDetail/lockSet/double_lock_link/double_lock_link_logic.dart'; +import 'package:star_lock/main/lockDetail/lockSet/double_lock_link/double_lock_link_state.dart'; +import 'package:star_lock/mine/mineSet/appUnlockNeedMobileNetworkingLock/selectLockListEntity.dart'; +import 'package:star_lock/tools/keySearchWidget.dart'; +import 'package:star_lock/tools/noData.dart'; +import 'package:star_lock/tools/storage.dart'; +import 'package:star_lock/tools/submitBtn.dart'; +import 'package:star_lock/tools/titleAppBar.dart'; + +class DoubleLockLinkPage extends StatefulWidget { + const DoubleLockLinkPage({Key? key}) : super(key: key); + + @override + State createState() => _DoubleLockLinkPageState(); +} + +class _DoubleLockLinkPageState extends State { + final DoubleLockLinkLogic logic = Get.put(DoubleLockLinkLogic()); + final DoubleLockLinkState state = Get.find().state; + + // 定义一个状态变量来存储选中的锁的 ID + int? _selectedLockId; + + Future getHttpData() async { + final bool? isDemoMode = await Storage.getBool(ifIsDemoModeOrNot); + if (isDemoMode == false) { + logic.mockNetworkDataRequest().then((SelectLockListEntity value) { + setState(() {}); + }); + } + } + + @override + void initState() { + super.initState(); + getHttpData(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColors.mainBackgroundColor, + resizeToAvoidBottomInset: false, + appBar: TitleAppBar( + barTitle: '双锁联动'.tr, + haveBack: true, + backgroundColor: AppColors.mainColor, + ), + body: Obx( + () => state.lockItemList.value.isEmpty + ? NoData() + : Column( + children: [ + KeySearchWidget( + editingController: state.searchController, + onSubmittedAction: () { + state.lockItemList.value = []; + logic.mockNetworkDataRequest(); + }, + ), + Container( + padding: EdgeInsets.all(15.w), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Text( + '对于当前拥有的锁和选中的锁,其中任意一把开启/关闭,另外一把则自动开启/关闭'.tr, + style: TextStyle(fontSize: 22.sp), + ), + ), + ], + ), + ), + SizedBox(height: 15.h), + Expanded( + child: ListView.builder( + itemCount: state.lockItemList.value.length, + itemBuilder: (BuildContext c, int index) { + final LockItemData itemData = + state.lockItemList.value[index]; + return _gatewatListItem(itemData); + }, + ), + ), + SubmitBtn( + btnName: '确定'.tr, + onClick: () { + logic.showToast('关联成功'.tr); + Get.back(); + }, + ), + SizedBox( + height: 40.h, + ), + ], + ), + ), + ); + } + + Widget _gatewatListItem(LockItemData itemData) { + return GestureDetector( + onTap: () { + setState(() { + // 更新选中的锁的 ID + _selectedLockId = itemData.lockId; + }); + }, + child: Container( + height: 80.h, + margin: const EdgeInsets.only(bottom: 2), + padding: + EdgeInsets.only(left: 10.w, right: 20.w, top: 20.h, bottom: 20.h), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10.w), + ), + child: Row( + children: [ + SizedBox( + width: 15.w, + ), + Image.asset( + _selectedLockId == itemData.lockId + ? 'images/icon_round_select.png' + : 'images/icon_round_unSelect.png', + width: 30.w, + height: 30.w, + ), + SizedBox( + width: 10.w, + ), + Expanded( + child: Text( + itemData.lockAlias ?? '', + style: TextStyle(fontSize: 22.sp, fontWeight: FontWeight.w600), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_state.dart b/lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_state.dart new file mode 100644 index 00000000..277d735d --- /dev/null +++ b/lib/main/lockDetail/lockSet/double_lock_link/double_lock_link_state.dart @@ -0,0 +1,11 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:star_lock/mine/mineSet/appUnlockNeedMobileNetworkingLock/selectLockListEntity.dart'; + +class DoubleLockLinkState { + RxList lockItemList = [].obs; + List selectLockIdList = []; + RxBool isCheckAll = false.obs; + + final TextEditingController searchController = TextEditingController(); +} diff --git a/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart b/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart index 79302a59..ee76b954 100755 --- a/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart +++ b/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart @@ -3,9 +3,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; +import 'package:qr_flutter/qr_flutter.dart'; +import 'package:star_lock/blue/blue_manage.dart'; import 'package:star_lock/main/lockDetail/lockSet/lockSet/checkingInInfoData_entity.dart'; import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSet_state.dart'; import 'package:star_lock/main/lockMian/lockMain/lockMain_logic.dart'; +import 'package:star_lock/tools/showCupertinoAlertView.dart'; import '../../../../appRouters.dart'; import '../../../../app_settings/app_colors.dart'; @@ -317,6 +320,21 @@ class _LockSetPageState extends State 'lockSetInfoData': state.lockSetInfoData.value }); }))), + //todo 电子反锁、可视门铃码国际化 + // 电子反锁 + Obx(() => CommonItem( + leftTitel: '电子反锁'.tr, + rightTitle: '', + isHaveLine: true, + isHaveRightWidget: true, + rightWidget: _elecAntiLockSwitch())), + // 可视门铃码 + Obx(() => CommonItem( + leftTitel: '可视门铃码'.tr, + rightTitle: '', + isHaveLine: true, + isHaveRightWidget: true, + rightWidget: _visualDoorbellCodeSwitch())), SizedBox(height: 10.h), // 常开模式 Obx(() => Visibility( @@ -335,6 +353,25 @@ class _LockSetPageState extends State 'lockSetInfoData': state.lockSetInfoData.value }); }))), + //todo: 双重认证、双锁联动国际化、API接口 + //双重认证 + Obx(() => Visibility( + visible: true, + child: CommonItem( + leftTitel: '双重认证'.tr, + rightTitle: '', + isHaveLine: true, + isHaveRightWidget: true, + rightWidget: _dualAuthSwitch()))), + // 双锁联动 + CommonItem( + leftTitel: '双锁联动'.tr, + rightTitle: '未关联'.tr, + isHaveLine: true, + isHaveDirection: true, + action: () { + Get.toNamed(Routers.doubleLockLinkPage); + }), // 远程开锁 Obx(() => Visibility( visible: state.lockFeature.value.remoteUnlock == 1, @@ -710,6 +747,64 @@ class _LockSetPageState extends State ); } + // 电子反锁 + CupertinoSwitch _elecAntiLockSwitch() { + return CupertinoSwitch( + activeColor: CupertinoColors.activeBlue, + trackColor: CupertinoColors.systemGrey5, + thumbColor: CupertinoColors.white, + value: state.isElecAntiLock.value == 1, + onChanged: state.sureBtnState.value == 1 + ? null + : (bool value) { + setState(() { + state.isElecAntiLock.value = value ? 1 : 0; + }); + }, + ); + } + + // 可视门铃码 + CupertinoSwitch _visualDoorbellCodeSwitch() { + return CupertinoSwitch( + activeColor: CupertinoColors.activeBlue, + trackColor: CupertinoColors.systemGrey5, + thumbColor: CupertinoColors.white, + value: state.isVisualDoorbellCode.value == 1, + onChanged: state.sureBtnState.value == 1 + ? null + : (bool value) { + setState(() { + state.isVisualDoorbellCode.value = value ? 1 : 0; + if (state.isVisualDoorbellCode.value == 1) { + ShowCupertinoAlertView().showVisualDoorbellCodeAlert( + widgetContext: context, + qrCodeUrl: BlueManage().connectDeviceName, + qrCodeText: '请扫描可视门铃码二维码'.tr, + ); + } else {} + }); + }, + ); + } + + // 双重认证 + CupertinoSwitch _dualAuthSwitch() { + return CupertinoSwitch( + activeColor: CupertinoColors.activeBlue, + trackColor: CupertinoColors.systemGrey5, + thumbColor: CupertinoColors.white, + value: state.isDualAuth.value == 1, + onChanged: state.sureBtnState.value == 1 + ? null + : (bool value) { + setState(() { + state.isDualAuth.value = value ? 1 : 0; + }); + }, + ); + } + // 异常警告 // CupertinoSwitch _lockExceptionWarningsSwitch() { // return CupertinoSwitch( diff --git a/lib/main/lockDetail/lockSet/lockSet/lockSet_state.dart b/lib/main/lockDetail/lockSet/lockSet/lockSet_state.dart index 2713b51e..be7d054f 100755 --- a/lib/main/lockDetail/lockSet/lockSet/lockSet_state.dart +++ b/lib/main/lockDetail/lockSet/lockSet/lockSet_state.dart @@ -22,13 +22,16 @@ class LockSetState { RxInt isOpenBlueBroadcast = 0.obs; // 是否开启蓝牙广播 RxInt isOpenExceptionWarnings = 0.obs; // 是否开启异常警告 RxInt isOpenStayWarn = 0.obs; // 是否开启逗留警告 + RxInt isElecAntiLock = 0.obs; // 电子反锁 + RxInt isVisualDoorbellCode = 0.obs; // 电子可视门铃 + RxInt isDualAuth = 0.obs; // 双重认证 TextEditingController passwordTF = TextEditingController(); int settingUpSupportFeatures = 0; RxBool ifCurrentScreen = true.obs; // 是否是当前界面,用于判断是否需要针对当前界面进行展示 RxBool deleteAdministratorIsHaveAllData = false.obs; // 删除管理员是否有所有数据 - RxInt sureBtnState = 0.obs;// 0普通状态(可用) 1连接中(不可用) + RxInt sureBtnState = 0.obs; // 0普通状态(可用) 1连接中(不可用) final ShowTipView showTipView = ShowTipView(); LockSetState() { diff --git a/lib/tools/showCupertinoAlertView.dart b/lib/tools/showCupertinoAlertView.dart index 62a53f6f..607dc414 100755 --- a/lib/tools/showCupertinoAlertView.dart +++ b/lib/tools/showCupertinoAlertView.dart @@ -1,16 +1,24 @@ +import 'dart:typed_data'; +import 'dart:ui'; + import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; +import 'package:image_gallery_saver/image_gallery_saver.dart'; +import 'package:qr_flutter/qr_flutter.dart'; import 'package:star_lock/appRouters.dart'; import 'package:star_lock/app_settings/app_colors.dart'; import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart'; +import 'package:star_lock/tools/submitBtn.dart'; typedef AuthInfoCallback = void Function(String? idCard, String? name); class ShowCupertinoAlertView { bool isSystemEmailSelected = true; // 默认选中系统邮件 + final GlobalKey _repaintBoundaryKey = GlobalKey(); //微信公众号二维码弹窗 void showQRImageAlert( @@ -138,7 +146,7 @@ class ShowCupertinoAlertView { style: TextStyle(color: Colors.white, fontSize: 22.sp), )), ), - SizedBox(width:2.w) + SizedBox(width: 2.w) // Expanded( // child: SizedBox( // width: 2.w, @@ -395,6 +403,101 @@ class ShowCupertinoAlertView { ); } + //可视门铃二维码弹窗 + void showVisualDoorbellCodeAlert( + {required BuildContext widgetContext, + required String qrCodeUrl, + required String qrCodeText}) { + showCupertinoModalPopup( + context: widgetContext, + builder: (BuildContext context) { + return CupertinoActionSheet( + actions: [ + Container( + color: Colors.white, // 设置底色为白色 + child: CupertinoActionSheetAction( + child: Container( + margin: const EdgeInsets.all(0), + child: Column( + children: [ + SizedBox( + height: 60.h, + ), + if (qrCodeUrl.isNotEmpty) + RepaintBoundary( + key: _repaintBoundaryKey, + child: SizedBox( + width: 200, + height: 200, + child: QrImageView( + data: qrCodeUrl, + version: QrVersions.auto, + size: 200.0, + ), + ), + ) + else + Container(), + SizedBox( + height: 20.h, + ), + Padding( + padding: EdgeInsets.only( + left: 60.w, right: 60.w, bottom: 30), + child: Text( + qrCodeText, + style: + TextStyle(fontSize: 24.sp, color: Colors.black), + )), + Container( + margin: EdgeInsets.only(left: 60.w, right: 60.w), + child: OutLineBtn( + btnName: '保存到相册'.tr, + onClick: () async { + // 截图并保存到相册 + try { + final RenderRepaintBoundary boundary = + _repaintBoundaryKey.currentContext! + .findRenderObject()! + as RenderRepaintBoundary; + final image = await boundary.toImage(); + final ByteData? byteData = await image + .toByteData(format: ImageByteFormat.png); + final Uint8List pngBytes = + byteData!.buffer.asUint8List(); + + final result = + await ImageGallerySaver.saveImage( + Uint8List.fromList(pngBytes), + quality: 100, + name: 'qr_code'); + if (result['isSuccess']) { + EasyLoading.showToast('保存成功'.tr); + } else { + EasyLoading.showToast('保存失败'.tr); + } + } catch (e) { + EasyLoading.showToast('保存失败'.tr); + } + }), + ), + SizedBox( + height: 40.h, + ) + ], + ), + ), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ), + ], + ); + }, + ); + } + // //邮件通知类型选择弹窗 // void emailNotifyTypeSlectAlert() { // showCupertinoDialog(