From 10f1496d57045d296c0023c89968c0ce1b90e52e Mon Sep 17 00:00:00 2001 From: Daisy <> Date: Tue, 9 Apr 2024 17:20:14 +0800 Subject: [PATCH 1/6] =?UTF-8?q?1=EF=BC=8C=E9=94=81=E8=AF=A6=E6=83=85?= =?UTF-8?q?=E9=A1=B5=E6=96=B0=E5=A2=9E=E8=99=B9=E8=86=9C=E3=80=81=E6=89=8B?= =?UTF-8?q?=E6=8E=8C=E7=9A=84=E5=85=A5=E5=8F=A3=202=EF=BC=8C=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E8=99=B9=E8=86=9C=E5=88=97=E8=A1=A8=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=203=EF=BC=8C=E6=96=B0=E5=A2=9E=E6=B7=BB=E5=8A=A0=E6=B0=B8?= =?UTF-8?q?=E4=B9=85=E3=80=81=E9=99=90=E6=97=B6=E3=80=81=E5=BE=AA=E7=8E=AF?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E8=99=B9=E8=86=9C=E7=95=8C=E9=9D=A2=204?= =?UTF-8?q?=EF=BC=8C=E6=96=B0=E5=A2=9E=E6=B7=BB=E5=8A=A0=E8=99=B9=E8=86=9C?= =?UTF-8?q?=E6=89=8B=E5=8A=BF=E8=BF=87=E7=A8=8B=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../face/faceList/faceList_page.dart | 8 +- .../iris/addIris/addIris_logic.dart | 301 ++++++++++++ .../lockDetail/iris/addIris/addIris_page.dart | 95 ++++ .../iris/addIris/addIris_state.dart | 37 ++ .../addIrisTypeManage_page.dart | 45 ++ .../addIrisTypeManage_tabbar.dart | 138 ++++++ .../iris/addIrisType/addIrisType_logic.dart | 99 ++++ .../iris/addIrisType/addIrisType_page.dart | 322 +++++++++++++ .../iris/addIrisType/addIrisType_state.dart | 33 ++ .../iris/irisDetail/irisDetail_logic.dart | 0 .../iris/irisDetail/irisDetail_page.dart | 0 .../iris/irisDetail/irisDetail_state.dart | 0 .../iris/irisList/irisList_logic.dart | 445 ++++++++++++++++++ .../iris/irisList/irisList_page.dart | 280 +++++++++++ .../iris/irisList/irisList_state.dart | 24 + .../lockDetail/lockDetail_page.dart | 23 +- .../monitoring/lockMonitoring_page.dart | 2 +- .../demoModeLockDetail_page.dart | 2 +- 18 files changed, 1845 insertions(+), 9 deletions(-) create mode 100644 star_lock/lib/main/lockDetail/iris/addIris/addIris_logic.dart create mode 100644 star_lock/lib/main/lockDetail/iris/addIris/addIris_page.dart create mode 100644 star_lock/lib/main/lockDetail/iris/addIris/addIris_state.dart create mode 100644 star_lock/lib/main/lockDetail/iris/addIrisType/addIrisTypeManage/addIrisTypeManage_page.dart create mode 100644 star_lock/lib/main/lockDetail/iris/addIrisType/addIrisTypeManage/addIrisTypeManage_tabbar.dart create mode 100644 star_lock/lib/main/lockDetail/iris/addIrisType/addIrisType_logic.dart create mode 100644 star_lock/lib/main/lockDetail/iris/addIrisType/addIrisType_page.dart create mode 100644 star_lock/lib/main/lockDetail/iris/addIrisType/addIrisType_state.dart create mode 100644 star_lock/lib/main/lockDetail/iris/irisDetail/irisDetail_logic.dart create mode 100644 star_lock/lib/main/lockDetail/iris/irisDetail/irisDetail_page.dart create mode 100644 star_lock/lib/main/lockDetail/iris/irisDetail/irisDetail_state.dart create mode 100644 star_lock/lib/main/lockDetail/iris/irisList/irisList_logic.dart create mode 100644 star_lock/lib/main/lockDetail/iris/irisList/irisList_page.dart create mode 100644 star_lock/lib/main/lockDetail/iris/irisList/irisList_state.dart diff --git a/star_lock/lib/main/lockDetail/face/faceList/faceList_page.dart b/star_lock/lib/main/lockDetail/face/faceList/faceList_page.dart index 04c429a1..f2d79311 100644 --- a/star_lock/lib/main/lockDetail/face/faceList/faceList_page.dart +++ b/star_lock/lib/main/lockDetail/face/faceList/faceList_page.dart @@ -16,14 +16,14 @@ import '../../../../tools/titleAppBar.dart'; import '../../../../translations/trans_lib.dart'; import 'faceList_logic.dart'; -class FaceList extends StatefulWidget { - const FaceList({Key? key}) : super(key: key); +class FaceListPage extends StatefulWidget { + const FaceListPage({Key? key}) : super(key: key); @override - State createState() => _FaceListState(); + State createState() => _FaceListPageState(); } -class _FaceListState extends State { +class _FaceListPageState extends State { final logic = Get.put(FaceListLogic()); final state = Get.find().state; diff --git a/star_lock/lib/main/lockDetail/iris/addIris/addIris_logic.dart b/star_lock/lib/main/lockDetail/iris/addIris/addIris_logic.dart new file mode 100644 index 00000000..4404283e --- /dev/null +++ b/star_lock/lib/main/lockDetail/iris/addIris/addIris_logic.dart @@ -0,0 +1,301 @@ +import 'dart:async'; + +// import 'package:flutter_reactive_ble/flutter_reactive_ble.dart'; +import 'package:flutter_blue_plus/flutter_blue_plus.dart'; +import 'package:get/get.dart'; +import 'package:star_lock/blue/io_protocol/io_addFace.dart'; +import 'package:star_lock/blue/io_type.dart'; +import 'package:star_lock/main/lockDetail/face/addFace/addFace_state.dart'; +import 'package:star_lock/tools/eventBusEventManage.dart'; + +import '../../../../../blue/blue_manage.dart'; +import '../../../../../blue/io_reply.dart'; +import '../../../../../blue/io_tool/io_tool.dart'; +import '../../../../../blue/io_tool/manager_event_bus.dart'; +import '../../../../../blue/sender_manage.dart'; +import '../../../../../network/api_repository.dart'; +import '../../../../../tools/baseGetXController.dart'; +import '../../../../../tools/storage.dart'; + +class AddIrisLogic extends BaseGetXController { + final AddFaceState state = AddFaceState(); + + // 监听设备返回的数据 + late StreamSubscription _replySubscription; + void _initReplySubscription() { + _replySubscription = + EventBusManager().eventBus!.on().listen((reply) async { + // 添加人脸开始 + if (reply is SenderAddFaceReply) { + _replyAddFaceBegin(reply); + } + + // 添加指纹过程 + if (reply is SenderAddFaceProcessReply) { + _replyAddFaceProcess(reply); + } + + // 添加指纹确认 + if (reply is SenderAddFaceConfirmationReply) { + _replyAddFaceConfirmation(reply); + } + }); + } + + Future _replyAddFaceBegin(Reply reply) async { + int status = reply.data[2]; + print("status:$status"); + + switch (status) { + case 0x00: + //成功 + // print("${reply.commandType!.typeValue} 人脸开始数据解析成功"); + state.ifConnectScuess.value = true; + + // 最大图片数 + state.maxRegCount.value = reply.data[10]; + print("人脸开始state.maxRegCount.value:${state.maxRegCount.value}"); + // state.fingerprintNumber.value = reply.data.last.toString(); + break; + case 0x06: + //无权限 + print("${reply.commandType!.typeValue} 需要鉴权"); + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + + var publicKey = await Storage.getStringList(saveBluePublicKey); + List publicKeyDataList = changeStringListToIntList(publicKey!); + + var token = reply.data.sublist(5, 9); + var saveStrList = changeIntListToStringList(token); + print("_replyAddFaceReplyToken:$token"); + Storage.setStringList(saveBlueToken, saveStrList); + + IoSenderManage.senderAddFaceCommand( + keyID: "1", + userID: await Storage.getUid(), + faceNo: 1, + useCountLimit: 0xff, + // startTime:0x11223344, + // endTime:0x11223344, + startTime: state.startDate.value ~/ 1000, + endTime: state.endDate.value ~/ 1000, + needAuthor: 1, + publicKey: publicKeyDataList, + privateKey: getPrivateKeyList, + token: token, + ); + break; + case 0x07: + //无权限 + print("${reply.commandType!.typeValue} 用户无权限"); + + break; + case 0x09: + // 权限校验错误 + print("${reply.commandType!.typeValue} 权限校验错误"); + + break; + default: + //失败 + print("${reply.commandType!.typeValue} 失败"); + + break; + } + } + + Future _replyAddFaceProcess(Reply reply) async { + int status = reply.data[2]; + print("******33 status:$status"); + + switch (status) { + case 0x00: + //成功 + print("${reply.commandType!.typeValue} 注册人脸过程数据解析成功"); + if (reply.data[5] == 255) { + // 注册人脸失败 + print("${reply.commandType!.typeValue} 注册人脸过程失败"); + showToast("添加失败"); + Get.close(2); + } else { + // state.addFaceProcessNumber.value++; + + // 当前注册数 + state.regIndex.value = reply.data[6]; + print("注册人脸过程state.regIndex.value:${state.regIndex.value}"); + } + break; + case 0x06: + //需要权限 + + break; + case 0x07: + //无权限 + print("${reply.commandType!.typeValue} 用户无权限"); + + break; + case 0x09: + // 权限校验错误 + print("${reply.commandType!.typeValue} 权限校验错误"); + + break; + default: + //失败 + print("${reply.commandType!.typeValue} 注册人脸过程default失败"); + + break; + } + } + + Future _replyAddFaceConfirmation(Reply reply) async { + int status = reply.data[2]; + print("status:$status"); + + switch (status) { + case 0x00: + //成功 + print("${reply.commandType!.typeValue} 人脸确认数据解析成功"); + // print("添加人脸确认成功,调用添加指纹接口"); + if (state.faceNumber.value == (reply.data[6]).toString()) { + return; + } else { + state.faceNumber.value = (reply.data[6]).toString(); + } + addFaceData(); + break; + case 0x06: + //需要权限 + + break; + case 0x07: + //无权限 + print("${reply.commandType!.typeValue} 用户无权限"); + + break; + case 0x09: + // 权限校验错误 + print("${reply.commandType!.typeValue} 权限校验错误"); + + break; + default: + //失败 + print("${reply.commandType!.typeValue} 人脸确认default失败"); + + break; + } + } + + // 添加人脸开始 + Future senderAddFace() async { + showBlueConnetctToastTimer(action: () { + Get.close(1); + }); + BlueManage().bludSendData(BlueManage().connectDeviceName, + (BluetoothConnectionState deviceConnectionState) async { + if (deviceConnectionState == BluetoothConnectionState.connected) { + cancelBlueConnetctToastTimer(); + var publicKey = await Storage.getStringList(saveBluePublicKey); + List publicKeyDataList = changeStringListToIntList(publicKey!); + + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + + var token = await Storage.getStringList(saveBlueToken); + List getTokenList = changeStringListToIntList(token!); + print( + "openDoorTokenPubToken:$getTokenList state.startDate.value:${state.startDate.value}"); + print( + "限时人脸开始时间:${state.startDate.value ~/ 1000} 限时人脸结束时间:${state.endDate.value ~/ 1000}"); + + IoSenderManage.senderAddFaceCommand( + keyID: "1", + userID: await Storage.getUid(), + faceNo: state.isAdministrator.value == true ? 254 : 1, + useCountLimit: 0xff, + // startTime:0x11223344, + // endTime:0x11223344, + startTime: state.startDate.value ~/ 1000, + endTime: state.endDate.value ~/ 1000, + needAuthor: 1, + publicKey: publicKeyDataList, + privateKey: getPrivateKeyList, + token: getTokenList, + ); + } else if (deviceConnectionState == + BluetoothConnectionState.disconnected) { + if (state.ifCurrentScreen.value == true) { + showBlueConnetctToast(); + } + cancelBlueConnetctToastTimer(); + Get.close(1); + } + }); + } + + // 添加人脸 + void addFaceData() async { + var entity = await ApiRepository.to.addFaceData( + lockId: state.lockId.value, + faceName: state.faceName.value, + faceNumber: state.faceNumber.value, + faceType: state.faceType.value, + startDate: state.startDate.value, + endDate: state.endDate.value, + featureData: state.featureData.value, + addType: state.addType.value, + cyclicConfig: state.cyclicConfig.value, + faceRight: state.isAdministrator.value == true ? 1 : 0, + ); + + if (entity.errorCode!.codeIsSuccessful) { + // Toast.show(msg: "添加成功"); + print('更新人脸用户账号成功了么1'); + updateFaceUserNoLoadData(entity.data!.faceId!); + } + } + + // 更新人脸用户账号 + void updateFaceUserNoLoadData(int faceId) async { + var entity = await ApiRepository.to.updateFaceUserNo( + faceId: faceId, + lockId: state.lockId.value, + faceUserNo: state.faceNumber.value, + ); + if (entity.errorCode!.codeIsSuccessful) { + print('更新人脸用户账号成功了么2'); + showToast("添加成功"); + if (state.fromType.value == 2) { + // 回调人脸号 + eventBus.fire(ChickInAddStaffCardAndFingerprintBlockNumberEvent( + state.faceNumber.value)); + } else if (state.fromType.value == 1) { + eventBus.fire(OtherTypeRefreshListEvent()); + } + Get.close(2); + } + } + + @override + void onReady() { + // TODO: implement onReady + super.onReady(); + + // _initReplySubscription(); + } + + @override + void onInit() { + // TODO: implement onInit + super.onInit(); +//开始添加后发送指令 + // senderAddFace(); + } + + @override + void onClose() { + // TODO: implement onClose + super.onClose(); + + // _replySubscription.cancel(); + } +} diff --git a/star_lock/lib/main/lockDetail/iris/addIris/addIris_page.dart b/star_lock/lib/main/lockDetail/iris/addIris/addIris_page.dart new file mode 100644 index 00000000..552898ae --- /dev/null +++ b/star_lock/lib/main/lockDetail/iris/addIris/addIris_page.dart @@ -0,0 +1,95 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:star_lock/main/lockDetail/iris/addIris/addIris_logic.dart'; + +import '../../../../../app_settings/app_colors.dart'; +import '../../../../../tools/submitBtn.dart'; +import '../../../../../tools/titleAppBar.dart'; +import '../../../../../translations/trans_lib.dart'; + +class AddIrisPage extends StatefulWidget { + const AddIrisPage({Key? key}) : super(key: key); + + @override + State createState() => _AddIrisPageState(); +} + +class _AddIrisPageState extends State { + final logic = Get.put(AddIrisLogic()); + final state = Get.find().state; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: TitleAppBar( + barTitle: "${TranslationLoader.lanKeys!.addTip!.tr}虹膜", + haveBack: true, + backgroundColor: AppColors.mainColor), + body: ListView( + children: [ + SizedBox( + height: 50.h, + ), + Obx(() => Image.asset( + state.isClickAddFace.value == false + ? 'images/main/icon_addFace_step1.png' + : 'images/main/icon_addFace_step2.png', + width: 100.w, + height: 457.h, + fit: BoxFit.fitHeight, + )), + SizedBox( + height: 60.h, + ), + Container( + padding: EdgeInsets.only(left: 20.w, right: 20.w), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Text( + "请单人正对门锁,距离一个成年人手臂长度\n(约0.6米)。\n保持脸部无遮挡,露出五官。", + textAlign: TextAlign.left, + maxLines: null, + style: + TextStyle(fontSize: 24.sp, fontWeight: FontWeight.w600), + ), + ), + ], + ), + ), + SizedBox( + height: 120.h, + ), + Obx( + () => state.isClickAddFace.value == false + ? Container( + padding: EdgeInsets.only(left: 20.w, right: 20.w), + child: SubmitBtn( + btnName: "准备好了,开始添加", + borderRadius: 20.w, + onClick: () { + state.isClickAddFace.value = true; + logic.senderAddFace(); + }), + ) + : Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + '正在录入中...', + style: TextStyle( + color: AppColors.darkGrayTextColor, + fontSize: 22.sp), + textAlign: TextAlign.center, + ) + ], + ), + ) + ], + ), + ); + } +} diff --git a/star_lock/lib/main/lockDetail/iris/addIris/addIris_state.dart b/star_lock/lib/main/lockDetail/iris/addIris/addIris_state.dart new file mode 100644 index 00000000..6dbf77d0 --- /dev/null +++ b/star_lock/lib/main/lockDetail/iris/addIris/addIris_state.dart @@ -0,0 +1,37 @@ +import 'package:get/get.dart'; + +class AddIrisState { + var ifCurrentScreen = true.obs; // 是否是当前界面,用于判断是否需要针对当前界面进行展示 + + var ifConnectScuess = false.obs; + var maxRegCount = 0.obs; // 最大注册次数 + var regIndex = 0.obs; // 当前注册次数 + + var faceNumber = "".obs; + + final lockId = 0.obs; + final endDate = 0.obs; + final addType = "".obs; + final faceName = "".obs; + final faceType = 0.obs; + final startDate = 0.obs; + final cyclicConfig = [].obs; + final fromType = 1.obs; + final featureData = ''.obs; + final isClickAddFace = false.obs; + final isAdministrator = false.obs; + + AddIrisState() { + Map map = Get.arguments; + lockId.value = map["lockId"]; + endDate.value = map["endDate"]; + addType.value = map["addType"]; + faceName.value = map["faceName"]; + faceType.value = map["faceType"]; + startDate.value = map["startDate"]; + lockId.value = map["lockId"]; + cyclicConfig.value = map["cyclicConfig"]; + fromType.value = map["fromType"]; + isAdministrator.value = map["isAdministrator"]; + } +} diff --git a/star_lock/lib/main/lockDetail/iris/addIrisType/addIrisTypeManage/addIrisTypeManage_page.dart b/star_lock/lib/main/lockDetail/iris/addIrisType/addIrisTypeManage/addIrisTypeManage_page.dart new file mode 100644 index 00000000..7ee02f0b --- /dev/null +++ b/star_lock/lib/main/lockDetail/iris/addIrisType/addIrisTypeManage/addIrisTypeManage_page.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:star_lock/main/lockDetail/iris/addIrisType/addIrisTypeManage/addIrisTypeManage_tabbar.dart'; + +import '../../../../../app_settings/app_colors.dart'; +import '../../../../../tools/titleAppBar.dart'; +import '../../../../../translations/trans_lib.dart'; + +class AddIrisTypeManagePage extends StatefulWidget { + const AddIrisTypeManagePage({Key? key}) : super(key: key); + + @override + State createState() => _AddIrisTypeManagePageState(); +} + +class _AddIrisTypeManagePageState extends State { + var index = 0; + + @override + Widget build(BuildContext context) { + Map map = Get.arguments; + var lockId = map["lockId"]; + var fromType = map["fromType"]; // 1从添加钥匙列表进入 2从考勤添加员工入口进入 + var fromTypeTwoStaffName = ""; + if (fromType == 2) { + fromTypeTwoStaffName = map["fromTypeTwoStaffName"]; // 从添加员工进入 传入员工名字 + } + return Scaffold( + backgroundColor: AppColors.mainBackgroundColor, + appBar: TitleAppBar( + barTitle: "${TranslationLoader.lanKeys!.addTip!.tr}虹膜", + haveBack: true, + backgroundColor: AppColors.mainColor), + body: Column( + children: [ + AddIrisTypeManageTabbar( + lockId: lockId, + fromType: fromType, + fromTypeTwoStaffName: fromTypeTwoStaffName, + initialIndex: index), + ], + ), + ); + } +} diff --git a/star_lock/lib/main/lockDetail/iris/addIrisType/addIrisTypeManage/addIrisTypeManage_tabbar.dart b/star_lock/lib/main/lockDetail/iris/addIrisType/addIrisTypeManage/addIrisTypeManage_tabbar.dart new file mode 100644 index 00000000..fa1f94e8 --- /dev/null +++ b/star_lock/lib/main/lockDetail/iris/addIrisType/addIrisTypeManage/addIrisTypeManage_tabbar.dart @@ -0,0 +1,138 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:star_lock/main/lockDetail/iris/addIrisType/addIrisType_page.dart'; + +import '../../../../../app_settings/app_colors.dart'; +import '../../../../../tools/CustomUnderlineTabIndicator.dart'; +import '../../../../../translations/trans_lib.dart'; + +class AddIrisTypeManageTabbar extends StatefulWidget { + var initialIndex = 1; + var lockId = 0; + var fromType = 1; // 1从添加钥匙列表进入 2从考勤添加员工入口进入 + var fromTypeTwoStaffName = ""; // 从添加员工进入 传入员工名字 + AddIrisTypeManageTabbar( + {Key? key, + required this.lockId, + required this.fromType, + required this.fromTypeTwoStaffName, + required this.initialIndex}) + : super(key: key); + + @override + State createState() => + _AddFaceTypeManageTabbarState(); +} + +class _AddFaceTypeManageTabbarState extends State + with SingleTickerProviderStateMixin { + late TabController _tabController; + + final List _itemTabs = [ + ItemView(title: TranslationLoader.lanKeys!.permanent!.tr, selectType: "0"), + ItemView(title: TranslationLoader.lanKeys!.timeLimit!.tr, selectType: "1"), + ItemView( + title: TranslationLoader.lanKeys!.circulation!.tr, selectType: "2"), + ]; + + final List _fromCheckInTypeItemTabs = [ + ItemView(title: TranslationLoader.lanKeys!.permanent!.tr, selectType: "0"), + ItemView(title: TranslationLoader.lanKeys!.timeLimit!.tr, selectType: "1"), + ]; + + @override + void initState() { + // TODO: implement initState + super.initState(); + _tabController = TabController( + vsync: this, + length: _itemTabs.length, + initialIndex: widget.initialIndex); + + _tabController.addListener(() { + // print("_tabController.animation!.value:${_tabController.animation!.value} _tabController.index:${_tabController.index}"); + if (_tabController.animation!.value == _tabController.index) { + FocusScope.of(context).requestFocus(FocusNode()); + } + }); + } + + @override + Widget build(BuildContext context) { + return Expanded( + child: Column( + children: [ + _tabBar(), + _pageWidget(), + ], + )); + } + + TabBar _tabBar() { + return TabBar( + controller: _tabController, + tabs: widget.fromType == 1 + ? _itemTabs.map((ItemView item) => _tab(item)).toList() + : _fromCheckInTypeItemTabs + .map((ItemView item) => _tab(item)) + .toList(), + isScrollable: true, + indicatorColor: Colors.red, + unselectedLabelColor: Colors.black, + unselectedLabelStyle: TextStyle( + color: AppColors.mainColor, + fontSize: 24.sp, + ), + automaticIndicatorColorAdjustment: true, + labelColor: AppColors.mainColor, + labelStyle: TextStyle( + color: AppColors.mainColor, + fontSize: 24.sp, + fontWeight: FontWeight.w600), + indicator: CustomUnderlineTabIndicator( + borderSide: BorderSide(color: AppColors.mainColor, width: 4.w), + strokeCap: StrokeCap.round, + width: 30.w), + ); + } + + Tab _tab(ItemView item) { + return Tab( + child: SizedBox( + width: 1.sw / 5, + child: Text(item.title, textAlign: TextAlign.center))); + } + + Widget _pageWidget() { + return Expanded( + child: TabBarView( + controller: _tabController, + children: widget.fromType == 1 + ? _itemTabs + .map((ItemView item) => AddIrisTypePage( + selectType: item.selectType, + lockId: widget.lockId, + fromType: widget.fromType, + fromTypeTwoStaffName: widget.fromTypeTwoStaffName)) + .toList() + : _itemTabs + .map((ItemView item) => AddIrisTypePage( + selectType: item.selectType, + lockId: widget.lockId, + fromType: widget.fromType, + fromTypeTwoStaffName: widget.fromTypeTwoStaffName)) + .toList(), + + // _itemTabs.map((ItemView item) => AddFaceTypePage(selectType: item.selectType, lockId: widget.lockId, fromType: widget.fromType, fromTypeTwoStaffName:widget.fromTypeTwoStaffName)).toList(), + ), + ); + } +} + +class ItemView { + const ItemView({required this.title, required this.selectType}); + + final String title; + final String selectType; +} diff --git a/star_lock/lib/main/lockDetail/iris/addIrisType/addIrisType_logic.dart b/star_lock/lib/main/lockDetail/iris/addIrisType/addIrisType_logic.dart new file mode 100644 index 00000000..5a6972b4 --- /dev/null +++ b/star_lock/lib/main/lockDetail/iris/addIrisType/addIrisType_logic.dart @@ -0,0 +1,99 @@ +import 'package:get/get.dart'; +import 'package:star_lock/main/lockDetail/face/addFaceType/addFaceType_state.dart'; +import 'package:star_lock/tools/baseGetXController.dart'; +import '../../../../appRouters.dart'; +import '../../../../network/api_repository.dart'; + +class AddIrisTypeLogic extends BaseGetXController { + AddFaceTypeState state = AddFaceTypeState(); + + // 添加指纹 + void addFaceData() async { + var faceType = 0; // 永久:1;限时2,单次3,循环:4 + var startDate = ""; + var endDate = ""; + if (state.seletType.value == "0") { + faceType = 1; + startDate = "0"; + endDate = "0"; + } else if (state.seletType.value == "1") { + faceType = 2; + if (state.beginTimeTimestamp.value.isEmpty) { + showToast("请选择开始时间"); + return; + } + if (state.endTimeTimestamp.value.isEmpty) { + showToast("请选择结束时间"); + return; + } + + // if(DateTime.now().millisecondsSinceEpoch > int.parse(state.beginTimeTimestamp.value)){ + // Toast.show(msg: "生效时间要大于当前时间"); + // return; + // } + + if (int.parse(state.beginTimeTimestamp.value) >= + int.parse(state.endTimeTimestamp.value)) { + showToast("失效时间要大于生效时间"); + return; + } + + startDate = state.beginTimeTimestamp.value; + endDate = state.endTimeTimestamp.value; + } else if (state.seletType.value == "2") { + if (state.effectiveDateTime.value <= 0) { + showToast("请选择生效时间"); + return; + } + if (state.failureDateTime.value <= 0) { + showToast("请选择失效时间"); + return; + } + + if (state.weekdaysList.value.isEmpty) { + showToast("请选择有效日"); + return; + } + + // if(DateTime.now().millisecondsSinceEpoch >= state.effectiveDateTime.value){ + // Toast.show(msg: "生效时间要大于当前时间"); + // return; + // } + + if (state.effectiveDateTime.value >= state.failureDateTime.value) { + showToast("失效时间要大于生效时间"); + return; + } + startDate = state.effectiveDateTime.value.toString(); + endDate = state.failureDateTime.value.toString(); + faceType = 4; + } + + print( + "传出去的给你限时人脸开始时间:${int.parse(startDate) ~/ 1000} 限时人脸结束时间:${int.parse(endDate) ~/ 1000}"); + // 人脸 + Get.toNamed(Routers.addIrisPage, arguments: { + "lockId": state.lockId.value, + "endDate": int.parse(endDate), + "addType": "1", + "faceName": state.nameController.text, + "faceNumber": "123456", + "faceType": faceType, + "startDate": int.parse(startDate), + "cyclicConfig": state.weekdaysList.value, + "fromType": state.fromType.value, + "isAdministrator": state.isAdministrator.value, + }); + } + + // 校验指纹名字是否重复 + void checkFaceNameDuplicated(String faceName) async { + var entity = await ApiRepository.to.checkFaceNameDuplicatedData( + lockId: state.lockId.value.toString(), + faceName: faceName, + ); + if (entity.errorCode!.codeIsSuccessful) { + addFaceData(); + } + } +} diff --git a/star_lock/lib/main/lockDetail/iris/addIrisType/addIrisType_page.dart b/star_lock/lib/main/lockDetail/iris/addIrisType/addIrisType_page.dart new file mode 100644 index 00000000..7decf64e --- /dev/null +++ b/star_lock/lib/main/lockDetail/iris/addIrisType/addIrisType_page.dart @@ -0,0 +1,322 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:star_lock/main/lockDetail/iris/addIrisType/addIrisType_logic.dart'; +import 'package:star_lock/tools/pickers/pickers.dart'; +import 'package:star_lock/tools/pickers/time_picker/model/date_mode.dart'; + +import '../../../../appRouters.dart'; +import '../../../../app_settings/app_colors.dart'; +import '../../../../tools/commonItem.dart'; +import '../../../../tools/storage.dart'; +import '../../../../tools/submitBtn.dart'; +import '../../../../translations/trans_lib.dart'; + +class AddIrisTypePage extends StatefulWidget { + final String selectType; // 永久限时循环下标 + final int lockId; + final int fromType; // // 1从添加钥匙列表进入 2从考勤添加员工入口进入 + final String fromTypeTwoStaffName; // 从添加员工进入 传入员工名字 + + const AddIrisTypePage( + {Key? key, + required this.selectType, + required this.lockId, + required this.fromType, + required this.fromTypeTwoStaffName}) + : super(key: key); + + @override + State createState() => _AddFaceTypePageState(); +} + +class _AddFaceTypePageState extends State { + final logic = Get.put(AddIrisTypeLogic()); + final state = Get.find().state; + + @override + Widget build(BuildContext context) { + state.seletType.value = widget.selectType; + state.lockId.value = widget.lockId; + if (widget.fromTypeTwoStaffName.isNotEmpty) { + state.nameController.text = widget.fromTypeTwoStaffName; + } + state.fromType.value = widget.fromType; + + return indexChangeWidget(); + } + + Widget indexChangeWidget() { + switch (int.parse(widget.selectType)) { + case 0: + { + // 永久 + // return sendElectronicKeySucceed(); + return Column( + children: [ + perpetualKeyWidget( + TranslationLoader.lanKeys!.name!.tr, + TranslationLoader.lanKeys!.pleaseEnter!.tr, + state.nameController), + keyBottomWidget() + ], + ); + } + case 1: + { + // 限时 + return Column( + children: [ + perpetualKeyWidget( + TranslationLoader.lanKeys!.name!.tr, + TranslationLoader.lanKeys!.pleaseEnter!.tr, + state.nameController), + keyTimeLimitWidget(), + keyBottomWidget() + ], + ); + } + case 2: + { + // 循环 + return Column( + children: [ + perpetualKeyWidget( + TranslationLoader.lanKeys!.name!.tr, + TranslationLoader.lanKeys!.pleaseEnter!.tr, + state.nameController), + CommonItem( + leftTitel: TranslationLoader.lanKeys!.periodValidity!.tr, + rightTitle: "", + isHaveDirection: true, + action: () async { + Map result = await Get.toNamed( + Routers.electronicKeyPeriodValidityPage); + state.weekdaysList.value = result['validityValue']; + state.effectiveDateTime.value = + result['starDate'].millisecondsSinceEpoch; + state.failureDateTime.value = + result['endDate'].millisecondsSinceEpoch; + print( + '得到的有效期数据:${state.weekdaysList.value} == ${state.effectiveDateTime.value} == ${state.failureDateTime.value}'); + }), + SizedBox(height: 10.h), + keyBottomWidget() + ], + ); + } + default: + return Container(); + } + } + + // 密码命名输入框 + Widget perpetualKeyWidget( + String titleStr, String rightTitle, TextEditingController controller) { + return Column( + children: [ + Container(height: 10.h), + CommonItem( + leftTitel: titleStr, + rightTitle: "", + isHaveRightWidget: true, + rightWidget: getTFWidget(rightTitle)), + Container(height: 10.h), + ], + ); + } + + // 限时顶部选择日期 + Widget keyTimeLimitWidget() { + return Column( + children: [ + Obx(() => CommonItem( + leftTitel: TranslationLoader.lanKeys!.effectiveTime!.tr, + rightTitle: state.beginTime.value, + isHaveLine: true, + isHaveDirection: true, + action: () async { + Pickers.showDatePicker(context, mode: DateMode.YMDHM, + onConfirm: (p) { + state.beginTime.value = + '${p.year}-${p.month!.toString().padLeft(2, '0')}-${p.day!.toString().padLeft(2, '0')} ${p.hour!.toString().padLeft(2, '0')}:${p.minute!.toString().padLeft(2, '0')}'; + state.beginTimeTimestamp.value = + DateTime.parse(state.beginTime.value) + .millisecondsSinceEpoch + .toString(); + }); + })), + Obx(() => CommonItem( + leftTitel: TranslationLoader.lanKeys!.failureTime!.tr, + rightTitle: state.endTime.value, + isHaveDirection: true, + action: () { + Pickers.showDatePicker(context, mode: DateMode.YMDHM, + onConfirm: (p) { + state.endTime.value = + '${p.year}-${p.month!.toString().padLeft(2, '0')}-${p.day!.toString().padLeft(2, '0')} ${p.hour!.toString().padLeft(2, '0')}:${p.minute!.toString().padLeft(2, '0')}'; + state.endTimeTimestamp.value = + DateTime.parse(state.endTime.value) + .millisecondsSinceEpoch + .toString(); + }); + })), + Container(height: 10.h), + ], + ); + } + + Widget keyBottomWidget() { + return Column( + children: [ + // CommonItem( + // leftTitel: TranslationLoader.lanKeys!.face!.tr, + // rightTitle: "", + // isTipsImg: false, + // isHaveRightWidget: true, + // rightWidget: SizedBox( + // width: 60.w, height: 50.h, child: _isStressFingerprint())), + CommonItem( + leftTitel: "是否是管理员", + rightTitle: "", + isTipsImg: false, + isHaveRightWidget: true, + rightWidget: SizedBox( + width: 60.w, height: 50.h, child: Obx(() => _isAdmin()))), + SizedBox(height: 30.h), + SubmitBtn( + btnName: TranslationLoader.lanKeys!.next!.tr, + onClick: () async { + var isDemoMode = await Storage.getBool(ifIsDemoModeOrNot); + if (isDemoMode == false) { + // print("state.selectType:${state.selectType.value}"); + if (state.nameController.text.isEmpty) { + logic.showToast("请输入姓名"); + return; + } + logic.checkFaceNameDuplicated(state.nameController.text); + } else { + // Get.toNamed(Routers.selectLockTypePage); + logic.showToast("演示模式"); + } + }), + ], + ); + } + + // 发送电子钥匙成功 + Widget sendElectronicKeySucceed() { + return Column( + children: [ + Container( + height: 300.h, + width: 1.sw, + color: Colors.white, + child: Column( + children: [ + SizedBox( + height: 30.h, + ), + Image.asset( + 'images/main/icon_main_addLock.png', + width: 150.w, + height: 150.w, + color: AppColors.mainColor, + ), + SizedBox( + height: 20.h, + ), + Text( + "操作成功,密码为", + style: TextStyle( + fontSize: 32.sp, + color: Colors.black, + fontWeight: FontWeight.w500), + ), + SizedBox( + height: 10.h, + ), + Text( + "62689876", + style: TextStyle( + fontSize: 60.sp, + color: Colors.black, + fontWeight: FontWeight.w500), + ), + ], + ), + ), + SizedBox( + height: 20.h, + ), + SubmitBtn( + btnName: '完成', + fontSize: 28.sp, + borderRadius: 20.w, + margin: EdgeInsets.only(left: 30.w, right: 30.w, top: 30.w), + padding: EdgeInsets.only(top: 25.w, bottom: 25.w), + onClick: () {}), + SubmitBtn( + btnName: '分享', + fontSize: 28.sp, + borderRadius: 20.w, + margin: EdgeInsets.only(left: 30.w, right: 30.w, top: 30.w), + padding: EdgeInsets.only(top: 25.w, bottom: 25.w), + onClick: () {}), + SubmitBtn( + btnName: '标记为:已入住', + fontSize: 28.sp, + borderRadius: 20.w, + margin: EdgeInsets.only(left: 30.w, right: 30.w, top: 30.w), + padding: EdgeInsets.only(top: 25.w, bottom: 25.w), + onClick: () {}), + ], + ); + } + + // 接受者信息输入框 + Widget getTFWidget(String tfStr) { + return Container( + height: 50.h, + width: 300.w, + child: Row( + children: [ + Expanded( + child: TextField( + //输入框一行 + maxLines: 1, + controller: state.nameController, + autofocus: false, + textAlign: TextAlign.end, + decoration: InputDecoration( + //输入里面输入文字内边距设置 + contentPadding: const EdgeInsets.only(top: 12.0, bottom: 8.0), + hintText: tfStr, + hintStyle: TextStyle(fontSize: 24.sp), + //不需要输入框下划线 + border: InputBorder.none, + ), + ), + ), + SizedBox( + width: 10.w, + ), + ], + ), + ); + } + + // 是否是管理员 + CupertinoSwitch _isAdmin() { + return CupertinoSwitch( + activeColor: CupertinoColors.activeBlue, + trackColor: CupertinoColors.systemGrey5, + thumbColor: CupertinoColors.white, + value: state.isAdministrator.value, + onChanged: (value) { + state.isAdministrator.value = value; + }, + ); + } +} diff --git a/star_lock/lib/main/lockDetail/iris/addIrisType/addIrisType_state.dart b/star_lock/lib/main/lockDetail/iris/addIrisType/addIrisType_state.dart new file mode 100644 index 00000000..412ed2d0 --- /dev/null +++ b/star_lock/lib/main/lockDetail/iris/addIrisType/addIrisType_state.dart @@ -0,0 +1,33 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class AddFaceTypeState { + final lockId = 0.obs; + final seletType = "0".obs; // 0永久 1显示 2循环 + final fromType = 1.obs; // // 1从添加钥匙列表进入 2从考勤添加员工入口进入 + var fromTypeTwoStaffName = "".obs; // 考勤添加人脸员工名字 + final isStressFingerprint = false.obs; + final isAdministrator = false.obs; // 是否是管理员 + + var beginTime = "".obs; // 开始时间 + var endTime = "".obs; // 结束时间 + var beginTimeTimestamp = "".obs; // 开始时间时间戳 + var endTimeTimestamp = "".obs; // 结束时间时间戳 + + var effectiveDateTime = 0.obs; // 生效时间 + var failureDateTime = 0.obs; // 失效时间 + var weekdaysList = [].obs; + + final TextEditingController nameController = TextEditingController(); + AddFaceTypeState() { + // Map map = Get.arguments; + // lockId.value = map["lockId"]; + // fromType.value = map["fromType"]; + // if(fromType.value == 2){ + // fromTypeTwoStaffName = map["fromTypeTwoStaffName"]; // 从添加员工进入 传入员工名字 + // // nameController.text = fromTypeTwoStaffName.value; + // } + + // print("lockId:${lockId.value} fromType:${fromType.value}"); + } +} diff --git a/star_lock/lib/main/lockDetail/iris/irisDetail/irisDetail_logic.dart b/star_lock/lib/main/lockDetail/iris/irisDetail/irisDetail_logic.dart new file mode 100644 index 00000000..e69de29b diff --git a/star_lock/lib/main/lockDetail/iris/irisDetail/irisDetail_page.dart b/star_lock/lib/main/lockDetail/iris/irisDetail/irisDetail_page.dart new file mode 100644 index 00000000..e69de29b diff --git a/star_lock/lib/main/lockDetail/iris/irisDetail/irisDetail_state.dart b/star_lock/lib/main/lockDetail/iris/irisDetail/irisDetail_state.dart new file mode 100644 index 00000000..e69de29b diff --git a/star_lock/lib/main/lockDetail/iris/irisList/irisList_logic.dart b/star_lock/lib/main/lockDetail/iris/irisList/irisList_logic.dart new file mode 100644 index 00000000..42722238 --- /dev/null +++ b/star_lock/lib/main/lockDetail/iris/irisList/irisList_logic.dart @@ -0,0 +1,445 @@ +import 'dart:async'; + +import 'package:flutter_blue_plus/flutter_blue_plus.dart'; +import 'package:star_lock/blue/io_protocol/io_addFace.dart'; +import 'package:star_lock/blue/io_protocol/io_queryingFaceStatus.dart'; +import 'package:star_lock/blue/io_type.dart'; +import 'package:star_lock/main/lockDetail/iris/irisList/irisList_state.dart'; +import 'package:star_lock/tools/baseGetXController.dart'; +import '../../../../blue/blue_manage.dart'; +import '../../../../blue/io_protocol/io_checkingUserInfoCount.dart'; +import '../../../../blue/io_reply.dart'; +import '../../../../blue/io_tool/io_tool.dart'; +import '../../../../blue/io_tool/manager_event_bus.dart'; +import '../../../../blue/sender_manage.dart'; +import '../../../../network/api_repository.dart'; +import '../../../../tools/eventBusEventManage.dart'; +import '../../../../tools/storage.dart'; + +class IrisListLogic extends BaseGetXController { + IrisListState state = IrisListState(); + + // 获取解析后的数据 + late StreamSubscription _replySubscription; + void _initReplySubscription() { + _replySubscription = + EventBusManager().eventBus!.on().listen((reply) { + // 添加人脸开始(此处用作删除人脸) + if ((reply is SenderAddFaceReply) && (state.isDeletFaceData == true)) { + _replyAddFaceBegin(reply); + } + + if (reply is SenderQueryingFaceStatusReply) { + // 获取人脸状态 + _replyQueryingFaceStatus(reply); + } + + if (reply is SenderCheckingUserInfoCountReply) { + _replyCheckingUserInfoCount(reply); + } + }); + } + + // 添加人脸开始---这里用作删除人脸 + Future _replyAddFaceBegin(Reply reply) async { + int status = reply.data[2]; + print("status:$status"); + + switch (status) { + case 0x00: + //成功 + print("${reply.commandType!.typeValue} list人脸数据解析成功"); + state.isDeletFaceData = false; + cancelBlueConnetctToastTimer(); + dismissEasyLoading(); + if (state.isDeletAll == false) { + deletFacesData(); + } else { + clearAllFacesData(); + } + break; + case 0x06: + //无权限 + print("${reply.commandType!.typeValue} 需要鉴权"); + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + + var publicKey = await Storage.getStringList(saveBluePublicKey); + List publicKeyDataList = changeStringListToIntList(publicKey!); + + var token = await Storage.getStringList(saveBlueToken); + List getTokenList = changeStringListToIntList(token!); + + IoSenderManage.senderAddFaceCommand( + keyID: state.deletKeyID, + userID: state.deletUserID, + faceNo: state.deletFaceNo, + useCountLimit: 0, + startTime: 0x11223344, + endTime: 0x11223344, + needAuthor: 1, + publicKey: publicKeyDataList, + privateKey: getPrivateKeyList, + token: getTokenList, + ); + break; + case 0x07: + //无权限 + print("${reply.commandType!.typeValue} 用户无权限"); + + break; + case 0x09: + // 权限校验错误 + print("${reply.commandType!.typeValue} 权限校验错误"); + + break; + default: + //失败 + print("${reply.commandType!.typeValue} list人脸失败"); + + break; + } + } + + // 获取人脸状态 + Future _replyQueryingFaceStatus(Reply reply) async { + int status = reply.data[2]; + + switch (status) { + case 0x00: + //成功 + print("${reply.commandType}数据解析成功"); + // _getLockStatus(); + break; + case 0x06: + //无权限 + print("${reply.commandType}需要鉴权"); + + break; + case 0x07: + //无权限 + print("${reply.commandType}用户无权限"); + + break; + case 0x09: + // 权限校验错误 + print("${reply.commandType}权限校验错误"); + + break; + default: + //失败 + print("${reply.commandType}失败"); + + break; + } + } + + // 获取卡片状态 + Future _replyReferEventRecordNumber(Reply reply) async { + int status = reply.data[2]; + switch (status) { + case 0x00: + //成功 + print("${reply.commandType}数据解析成功"); + // _getLockStatus(); + break; + case 0x06: + //无权限 + print("${reply.commandType}需要鉴权"); + + break; + case 0x07: + //无权限 + print("${reply.commandType}用户无权限"); + + break; + case 0x09: + // 权限校验错误 + print("${reply.commandType}权限校验错误"); + + break; + default: + //失败 + print("${reply.commandType}失败"); + + break; + } + } + + // 查询用户、指纹、密码、卡片数量(用于判断是否同步) + Future _replyCheckingUserInfoCount(Reply reply) async { + int status = reply.data[2]; + + // 用户数量 + int userNum = reply.data[5]; + // print("userNum:$userNum"); + + // 指纹数量 + int fingerNum = reply.data[6]; + // print("fingerNum:$fingerNum"); + + // 密码数量 + int pwdNum = reply.data[7]; + + // 卡片数量 + int cardNum = reply.data[8]; + + // 记录数量 + int logsNum = reply.data[9]; + + // 版本 + int verNo = reply.data[10]; + + // 最大管理员指纹数量 + int maxAdminFingerNum = reply.data[11]; + + // 最大用户指纹数量 + int maxUserFingerNum = reply.data[12]; + + // 最大管理员密码数量 + int maxAdminPassNum = reply.data[13]; + + // 最大用户密码数量 + int maxUserPassNum = reply.data[14]; + + // 最大管理员卡片数量 + int maxAdminCardNum = reply.data[15]; + + // 最大用户卡片数量 + int maxUserCardNum = reply.data[16]; + + // 序列号 + var serialNo = reply.data.sublist(17, 21); + print("serialNo:$serialNo"); + + switch (status) { + case 0x00: + //成功 + print("${reply.commandType}数据解析成功"); + // _getLockStatus(); + break; + case 0x06: + //无权限 + print("${reply.commandType}需要鉴权"); + + break; + case 0x07: + //无权限 + print("${reply.commandType}用户无权限"); + + break; + case 0x09: + // 权限校验错误 + print("${reply.commandType}权限校验错误"); + + break; + default: + //失败 + print("${reply.commandType}失败"); + + break; + } + } + + // 获取人脸状态 + Future senderQueryingFaceStatus() async { + BlueManage().bludSendData(BlueManage().connectDeviceName, + (BluetoothConnectionState state) async { + if (state == BluetoothConnectionState.connected) { + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + + var token = await Storage.getStringList(saveBlueToken); + List getTokenList = changeStringListToIntList(token!); + + var publicKey = await Storage.getStringList(saveBluePublicKey); + List getPublicKeyList = changeStringListToIntList(publicKey!); + + IoSenderManage.senderQueryingFaceStatusCommand( + keyID: BlueManage().connectDeviceName, + userID: await Storage.getUid(), + role: 0xff, + faceCount: 20, + faceNo: 1, + token: getTokenList, + needAuthor: 1, + publicKey: getPublicKeyList, + privateKey: getPrivateKeyList, + ); + } + }); + } + + // 查询用户、指纹、密码、卡片数量(用于判断是否同步) + Future senderCheckingUserInfoCount() async { + BlueManage().bludSendData(BlueManage().connectDeviceName, + (BluetoothConnectionState state) async { + if (state == BluetoothConnectionState.connected) { + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + + var token = await Storage.getStringList(saveBlueToken); + List getTokenList = changeStringListToIntList(token!); + + var publicKey = await Storage.getStringList(saveBluePublicKey); + List getPublicKeyList = changeStringListToIntList(publicKey!); + + IoSenderManage.senderCheckingUserInfoCountCommand( + keyID: BlueManage().connectDeviceName, + userID: await Storage.getUid(), + role: 0xff, + nowTime: DateTime.now().millisecondsSinceEpoch ~/ 1000, + token: getTokenList, + needAuthor: 1, + publicKey: getPublicKeyList, + privateKey: getPrivateKeyList, + ); + } + }); + } + + // 删除人脸 + Future senderAddFace() async { + showEasyLoading(); + showBlueConnetctToastTimer(action: () { + dismissEasyLoading(); + }); + BlueManage().bludSendData(BlueManage().connectDeviceName, + (BluetoothConnectionState deviceConnectionState) async { + if (deviceConnectionState == BluetoothConnectionState.connected) { + var publicKey = await Storage.getStringList(saveBluePublicKey); + List publicKeyDataList = changeStringListToIntList(publicKey!); + + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + + var token = await Storage.getStringList(saveBlueToken); + List getTokenList = changeStringListToIntList(token!); + + IoSenderManage.senderAddFaceCommand( + keyID: state.deletKeyID, + userID: state.deletUserID, + faceNo: state.deletFaceNo, + useCountLimit: 0, + startTime: 0x11223344, + endTime: 0x11223344, + needAuthor: 1, + publicKey: publicKeyDataList, + privateKey: getPrivateKeyList, + token: getTokenList, + ); + } else if (deviceConnectionState == + BluetoothConnectionState.disconnected) { + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + if (state.ifCurrentScreen.value == true) { + showBlueConnetctToast(); + } + } + }); + } + + // 获取人脸列表 + void getFaceListData() async { + var entity = await ApiRepository.to.getFaceListData( + lockId: state.lockId.value.toString(), + pageNo: '1', + pageSize: '20', + searchStr: state.searchController.text, + ); + if (entity.errorCode!.codeIsSuccessful) { + state.faceItemListData.value = entity.data!.list!; + } + } + + // 删除的人脸 + void deletFacesData() async { + var faceId = ""; + var type = "1"; + if (state.isDeletAll == false) { + faceId = state.deletKeyID; + type = "0"; + } + print("delet faceId $faceId"); + var entity = await ApiRepository.to.deleteFaceData( + faceId: int.parse(faceId), + lockId: state.lockId.value, + ); + if (entity.errorCode!.codeIsSuccessful) { + showToast("删除成功"); + state.isDeletFaceData = false; + getFaceListData(); + } + } + + // 重置所有的人脸 + void clearAllFacesData() async { + var faceId = ""; + var type = "1"; + if (state.isDeletAll == false) { + faceId = state.deletKeyID; + type = "0"; + } + print("delet faceId $faceId"); + var entity = await ApiRepository.to.clearFaceData( + lockId: state.lockId.value, + ); + if (entity.errorCode!.codeIsSuccessful) { + showToast("重置成功"); + state.isDeletFaceData = false; + getFaceListData(); + } + } + + // 监听修改完详情之后刷新列表 + late StreamSubscription _teamEvent; + void _initRefreshAction() { + _teamEvent = eventBus.on().listen((event) { + getFaceListData(); + }); + } + + @override + Future onReady() async { + // TODO: implement onReady + super.onReady(); + print("onReady()"); + + // 获取是否是演示模式 演示模式不获取接口 + var isDemoMode = await Storage.getBool(ifIsDemoModeOrNot); + // print("aaaaaaa:$isDemoMode"); + if (isDemoMode == false) { + _initReplySubscription(); + + _initRefreshAction(); + + getFaceListData(); + } + } + + @override + Future onInit() async { + // TODO: implement onInit + super.onInit(); + print("onInit()"); + var isDemoMode = await Storage.getBool(ifIsDemoModeOrNot); + if (isDemoMode == false) { + // senderQueryingFingerprintStatus(); + // senderCheckingCardStatus(); + + // senderCheckingUserInfoCount(); + } + } + + @override + Future onClose() async { + // TODO: implement onClose + super.onClose(); + + var isDemoMode = await Storage.getBool(ifIsDemoModeOrNot); + if (isDemoMode == false) { + _replySubscription.cancel(); + _teamEvent.cancel(); + } + } +} diff --git a/star_lock/lib/main/lockDetail/iris/irisList/irisList_page.dart b/star_lock/lib/main/lockDetail/iris/irisList/irisList_page.dart new file mode 100644 index 00000000..da59cf6d --- /dev/null +++ b/star_lock/lib/main/lockDetail/iris/irisList/irisList_page.dart @@ -0,0 +1,280 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:star_lock/main/lockDetail/fingerprint/fingerprintList/fingerprintListData_entity.dart'; +import 'package:star_lock/main/lockDetail/iris/irisList/irisList_logic.dart'; +import 'package:star_lock/tools/keySearchWidget.dart'; +import 'package:star_lock/tools/left_slide_actions.dart'; + +import '../../../../appRouters.dart'; +import '../../../../app_settings/app_colors.dart'; +import '../../../../tools/noData.dart'; +import '../../../../tools/showIosTipView.dart'; +import '../../../../tools/storage.dart'; +import '../../../../tools/submitBtn.dart'; +import '../../../../tools/titleAppBar.dart'; +import '../../../../translations/trans_lib.dart'; + +class IrisListPage extends StatefulWidget { + const IrisListPage({Key? key}) : super(key: key); + + @override + State createState() => _IrisListPageState(); +} + +class _IrisListPageState extends State { + final logic = Get.put(IrisListLogic()); + final state = Get.find().state; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColors.mainBackgroundColor, + appBar: TitleAppBar( + barTitle: '虹膜', + haveBack: true, + backgroundColor: AppColors.mainColor, + actionsList: [ + TextButton( + child: Text( + TranslationLoader.lanKeys!.reset!.tr, + style: TextStyle(color: Colors.white, fontSize: 24.sp), + ), + onPressed: () async { + var isDemoMode = await Storage.getBool(ifIsDemoModeOrNot); + if (isDemoMode == false) { + showDeletAlertDialog(context); + } else { + // Get.toNamed(Routers.selectLockTypePage); + logic.showToast("演示模式"); + } + }, + ), + ], + ), + body: Column( + children: [ + KeySearchWidget( + editingController: state.searchController, + onSubmittedAction: () { + logic.getFaceListData(); + }, + ), + SizedBox( + height: 20.h, + ), + Expanded(child: _buildMainUI()), + AddBottomWhiteBtn( + btnName: '${TranslationLoader.lanKeys!.add!.tr}虹膜', + onClick: () async { + // var data = + // await Get.toNamed(Routers.addFaceTypeManagePage, arguments: { + // "lockId": state.lockId.value, + // "fromType": 1 // 1从添加钥匙列表进入 2从考勤添加员工入口进入 + // }); + var data = + await Get.toNamed(Routers.addIrisTypeManagePage, arguments: { + "lockId": state.lockId.value, + "fromType": 1 // 1从添加钥匙列表进入 2从考勤添加员工入口进入 + }); + if (data != null) { + logic.getFaceListData(); + } + }, + ), + SizedBox(height: 64.h) + ], + ), + ); + } + + Widget _buildMainUI() { + { + return Obx(() => state.faceItemListData.value.isNotEmpty + ? ListView.separated( + itemCount: state.faceItemListData.value.length, + itemBuilder: (c, index) { + FingerprintItemData getFaceItemData = + state.faceItemListData.value[index]; + // 人脸 + if (index < state.faceItemListData.value.length) { + return LeftSlideActions( + key: Key(getFaceItemData.faceName!), + actionsWidth: 60, + actions: [ + _buildDeleteBtn(getFaceItemData), + ], + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(1)), + ), + child: _keyItem( + 'images/icon_face.png', + getFaceItemData.faceName!, + (getFaceItemData.faceType! != 1) + ? (getFaceItemData.endDate! < + DateTime.now().millisecondsSinceEpoch + ? "已失效" + : "") + : "", + getFaceItemData.validTimeStr!, + // fingerprintItemData.fingerprintType! == 1 + // ? "永久" + // : "${DateTool().dateToYMDHNString(fingerprintItemData.startDate.toString())} - ${DateTool().dateToYMDHNString(fingerprintItemData.endDate.toString())}", + () async { + var data = + await Get.toNamed(Routers.faceDetailPage, arguments: { + "faceItemData": getFaceItemData, + }); + if (data != null) { + logic.getFaceListData(); + } + }), + ); + } + return const SizedBox.shrink(); + }, + separatorBuilder: (BuildContext context, int index) { + return const Divider( + height: 1, + color: AppColors.greyLineColor, + ); + }, + ) + : NoData(noDataHeight: 1.sh - ScreenUtil().statusBarHeight - 170.h)); + } + } + + Widget _buildDeleteBtn(FingerprintItemData faceItemData) { + return GestureDetector( + onTap: () { + // 省略: 弹出是否删除的确认对话框。 + state.deletKeyID = faceItemData.faceId.toString(); + state.deletFaceNo = int.parse(faceItemData.faceNumber!); + showIosTipViewDialog(context); + }, + child: Container( + width: 60, + color: const Color(0xFFF20101), + alignment: Alignment.center, + child: const Text( + '删除', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.white, + height: 1, + ), + ), + ), + ); + } + + void showIosTipViewDialog(BuildContext context) { + showDialog( + context: context, + builder: (BuildContext context) { + return ShowIosTipView( + title: "提示", + tipTitle: "确定要删除吗?", + sureClick: () async { + Get.back(); + state.isDeletFaceData = true; + state.isDeletAll = false; + state.deletUserID = (await Storage.getUid())!; + logic.senderAddFace(); + }, + cancelClick: () { + Get.back(); + }, + ); + }, + ); + } + + Widget _keyItem(String lockTypeIcon, String lockTypeTitle, + String ifInvalidation, String showTime, Function() action) { + return GestureDetector( + onTap: action, + child: Container( + height: 90.h, + // margin: EdgeInsets.only(left: 20.w, right: 20.w, top: 20.w), + color: Colors.white, + // decoration: BoxDecoration( + // color: Colors.white, + // // borderRadius: BorderRadius.circular(10.w), + // ), + child: Row( + children: [ + SizedBox(width: 30.w), + Image.asset(lockTypeIcon, width: 60.w, height: 60.w), + SizedBox(width: 20.w), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(lockTypeTitle, + style: TextStyle( + fontSize: 24.sp, color: AppColors.blackColor)), + Expanded(child: Container()), + Text(ifInvalidation, + style: TextStyle(fontSize: 22.sp, color: Colors.red)), + SizedBox(width: 10.w), + ], + ), + SizedBox(height: 5.h), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text(showTime, + style: TextStyle( + fontSize: 18.sp, + color: AppColors.placeholderTextColor)), + ], + ), + SizedBox(width: 20.h), + ], + ), + ), + SizedBox(width: 20.h), + ], + ), + ), + ); + } + + void showDeletAlertDialog(BuildContext context) { + showCupertinoDialog( + context: context, + builder: (context) { + return CupertinoAlertDialog( + title: const Text("提示"), + content: const Text('重置后,该锁的人脸都将被删除哦,确认要重置吗?'), + actions: [ + CupertinoDialogAction( + child: Text(TranslationLoader.lanKeys!.cancel!.tr), + onPressed: () { + Navigator.pop(context); + }, + ), + CupertinoDialogAction( + child: Text(TranslationLoader.lanKeys!.sure!.tr), + onPressed: () { + Navigator.pop(context); + state.isDeletFaceData = true; + state.isDeletAll = true; + state.deletKeyID = "1"; + state.deletUserID = "DeleteAll!@#"; + state.deletFaceNo = 255; + logic.senderAddFace(); + }, + ), + ], + ); + }, + ); + } +} diff --git a/star_lock/lib/main/lockDetail/iris/irisList/irisList_state.dart b/star_lock/lib/main/lockDetail/iris/irisList/irisList_state.dart new file mode 100644 index 00000000..ac926272 --- /dev/null +++ b/star_lock/lib/main/lockDetail/iris/irisList/irisList_state.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:star_lock/main/lockDetail/fingerprint/fingerprintList/fingerprintListData_entity.dart'; + +class IrisListState { + final TextEditingController searchController = TextEditingController(); + final lockId = 0.obs; + + // 因为删除跟添加人脸用的同一个协议 所以这里用做判断 + var isDeletFaceData = false; + var isDeletAll = false; + var deletKeyID = ""; + var deletUserID = "DeleteAll!@#"; + var deletFaceNo = 0; + + final faceItemListData = [].obs; + + var ifCurrentScreen = true.obs; // 是否是当前界面,用于判断是否需要针对当前界面进行展示 + + IrisListState() { + Map map = Get.arguments; + lockId.value = map["lockId"]; + } +} diff --git a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart index db14ee45..6e51f024 100644 --- a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart +++ b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart @@ -1,6 +1,5 @@ import 'dart:async'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; @@ -672,13 +671,31 @@ class _LockDetailPageState extends State TranslationLoader.lanKeys!.humanFace!.tr, state.openDoorBtnisUneable.value, state.bottomBtnisEable.value, () { - Get.toNamed(Routers.faceList, arguments: { + Get.toNamed(Routers.faceListPage, arguments: { "lockId": state.keyInfos.value.lockId, - }); // Toast.show(msg: "功能暂未开放"); + }); }), ); } + showWidgetArr.add( + bottomItem('images/main/icon_face.png', '虹膜', + state.openDoorBtnisUneable.value, state.bottomBtnisEable.value, () { + Get.toNamed(Routers.irisListPage, arguments: { + "lockId": state.keyInfos.value.lockId, + }); + }), + ); + + showWidgetArr.add( + bottomItem( + 'images/main/icon_face.png', + '手掌', + state.openDoorBtnisUneable.value, + state.bottomBtnisEable.value, + () {}), + ); + //可视对讲门锁新增->监控 if (state.keyInfos.value.lockFeature!.videoIntercom == 1) { showWidgetArr.add( diff --git a/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart index 77b6edf8..5cd40acc 100644 --- a/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart +++ b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart @@ -46,7 +46,7 @@ class _LockMonitoringPageState extends State { child: Container( width: 1.sw, height: 1.sh, - color: Colors.white, + // color: Colors.white, child: Stack( children: [ Obx(() { diff --git a/star_lock/lib/main/lockMian/demoMode/demoModeLockDetail/demoModeLockDetail_page.dart b/star_lock/lib/main/lockMian/demoMode/demoModeLockDetail/demoModeLockDetail_page.dart index ef881d66..39568fe0 100644 --- a/star_lock/lib/main/lockMian/demoMode/demoModeLockDetail/demoModeLockDetail_page.dart +++ b/star_lock/lib/main/lockMian/demoMode/demoModeLockDetail/demoModeLockDetail_page.dart @@ -292,7 +292,7 @@ class _DemoModeLockDetailPageState extends State { bottomItem('images/main/icon_face.png', '人脸', () { // gotoLogin(); - Get.toNamed(Routers.faceList, arguments: { + Get.toNamed(Routers.faceListPage, arguments: { "lockId": 1, }); }), From 6edb1c7719181846b72290478b3da62c53b09eac Mon Sep 17 00:00:00 2001 From: Daisy <> Date: Tue, 9 Apr 2024 17:21:56 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E5=88=A0=E6=8E=89=E6=97=A0=E7=94=A8g711=5F?= =?UTF-8?q?flutter=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- star_lock/pubspec.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/star_lock/pubspec.yaml b/star_lock/pubspec.yaml index 96f5c2bb..56920739 100644 --- a/star_lock/pubspec.yaml +++ b/star_lock/pubspec.yaml @@ -131,7 +131,6 @@ dependencies: #控制横竖屏控件 auto_orientation: ^2.3.1 audioplayers: ^5.2.1 - g711_flutter: ^2.0.0 ffi: ^2.1.0 flutter_mjpeg: ^2.0.4 image_gallery_saver: ^2.0.3 From 68f5eaddb3c7ff9d61168c7df1b27b995f429942 Mon Sep 17 00:00:00 2001 From: Daisy <> Date: Tue, 9 Apr 2024 18:08:03 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E8=B7=AF=E7=94=B1?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- star_lock/lib/appRouters.dart | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/star_lock/lib/appRouters.dart b/star_lock/lib/appRouters.dart index 91b1675e..32a3a3c1 100644 --- a/star_lock/lib/appRouters.dart +++ b/star_lock/lib/appRouters.dart @@ -9,6 +9,9 @@ import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/ma import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/massSendLockGroupList/massSendLockGroupList_page.dart'; import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/massSendLockGroupList/massSendReceiver/massSendReceiver_page.dart'; import 'package:star_lock/main/lockDetail/face/faceDetail/faceDetail_page.dart'; +import 'package:star_lock/main/lockDetail/iris/addIris/addIris_page.dart'; +import 'package:star_lock/main/lockDetail/iris/addIrisType/addIrisTypeManage/addIrisTypeManage_page.dart'; +import 'package:star_lock/main/lockDetail/iris/irisList/irisList_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/addFamily/addFamily_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'; @@ -414,10 +417,14 @@ abstract class Routers { static const addFingerprintTypeManagePage = '/AddFingerprintTypeManagePage'; // 添加指纹 static const fingerprintDetailPage = '/FingerprintDetailPage'; // 指纹详情 - static const faceList = '/FaceList'; // 人脸列表 + static const faceListPage = '/FaceListPage'; // 人脸列表 static const addFaceTypeManagePage = '/AddFaceTypeManagePage'; // 添加人脸 static const faceDetailPage = '/faceDetailPage'; // 人脸详情 + static const irisListPage = '/IrisListPage'; // 虹膜列表 + static const addIrisTypeManagePage = '/AddIrisTypeManagePage'; // 添加虹膜 + static const addIrisPage = '/AddIrisPage'; // 添加虹膜 + static const passwordKeyDetailChangeDatePage = '/passwordKeyDetailChangeDatePage'; //密码更改时间 static const realTimePicturePage = '/realTimePicturePage'; //实时监控画面 @@ -427,7 +434,8 @@ abstract class Routers { static const liveVideoPage = '/liveVideoPage'; //实时画面 static const accessoriesListPage = '/accessoriesListPage'; //配件列表 - static const seletKeyCyclicDatePage = '/SeletKeyCyclicDatePage';// 电子钥匙、授权管理员、卡、指纹、遥控等添加添加循环日期公共界面 + static const seletKeyCyclicDatePage = + '/SeletKeyCyclicDatePage'; // 电子钥匙、授权管理员、卡、指纹、遥控等添加添加循环日期公共界面 } abstract class AppRouters { @@ -1005,7 +1013,7 @@ abstract class AppRouters { GetPage( name: Routers.fingerprintDetailPage, page: () => const FingerprintDetailPage()), - GetPage(name: Routers.faceList, page: () => const FaceList()), + GetPage(name: Routers.faceListPage, page: () => const FaceListPage()), GetPage( name: Routers.addFaceTypeManagePage, page: () => const AddFaceTypeManagePage()), @@ -1028,11 +1036,14 @@ abstract class AppRouters { GetPage( name: Routers.accessoriesListPage, page: (() => const AccessoriesListPage())), - GetPage( - name: Routers.wifiListPage, - page: (() => const WifiListPage())), + GetPage(name: Routers.wifiListPage, page: (() => const WifiListPage())), GetPage( name: Routers.seletKeyCyclicDatePage, - page: (() => const SeletKeyCyclicDatePage())) + page: (() => const SeletKeyCyclicDatePage())), + GetPage(name: Routers.irisListPage, page: (() => const IrisListPage())), + GetPage( + name: Routers.addIrisTypeManagePage, + page: (() => const AddIrisTypeManagePage())), + GetPage(name: Routers.addIrisPage, page: (() => const AddIrisPage())) ]; } From fd6cd49325c32cd1894b958925562365ae69cd35 Mon Sep 17 00:00:00 2001 From: GeJiaXiang <353358601@qq.com> Date: Tue, 9 Apr 2024 18:23:02 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E6=B7=BB=E5=8A=A0docker=E9=95=9C=E5=83=8F?= =?UTF-8?q?=E6=9E=84=E5=BB=BA=E8=AF=B4=E6=98=8E3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- star_lock/.docker/.env.example | 7 ++ star_lock/.docker/.gitignore | 1 + star_lock/.docker/README.md | 95 ++++++++++++++++++++- star_lock/.docker/gradle.properties.example | 4 + 4 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 star_lock/.docker/gradle.properties.example diff --git a/star_lock/.docker/.env.example b/star_lock/.docker/.env.example index 48431d73..46afd189 100644 --- a/star_lock/.docker/.env.example +++ b/star_lock/.docker/.env.example @@ -1,2 +1,9 @@ FLUTTER_STORAGE_BASE_URL="https://mirrors.tuna.tsinghua.edu.cn/flutter" PUB_HOSTED_URL="https://mirrors.tuna.tsinghua.edu.cn/dart-pub" + +HTTP_PROXY=http://127.0.0.1:1080/``` +HTTPS_PROXY=http://127.0.0.1:1080/ + +# curl只支持小写 +http_proxy=http://127.0.0.1:1080/ +https_proxy=http://127.0.0.1:1080/ diff --git a/star_lock/.docker/.gitignore b/star_lock/.docker/.gitignore index 4c49bd78..f0ea8dc6 100644 --- a/star_lock/.docker/.gitignore +++ b/star_lock/.docker/.gitignore @@ -1 +1,2 @@ .env +gradle.properties diff --git a/star_lock/.docker/README.md b/star_lock/.docker/README.md index 8dd913e2..102e0201 100644 --- a/star_lock/.docker/README.md +++ b/star_lock/.docker/README.md @@ -2,17 +2,31 @@ 构建镜像来自:https://github.com/MobileDevOps/flutter-sdk-image/ ## 使用方法 -1. 复制.env文件,并编辑其中的代理设置 +1. 复制文件,并编辑其中的代理设置 ```bash cp .docker/.env.example .docker/.env +# ~/.gradle 如不存在请新建,该目录缓存一些gradle包 +mkdir -p ~/.gradle && chmod -R 777 ~/.gradle +cp .docker/gradle.properties.example ~/.gradle/gradle.properties ``` 2. 构建命令 ```bash cd +# 构建目录,防止目录权限问题 +mkdir /tmp/build-cache +echo 'hello!' > /tmp/build-cache/isMe.txt +chown -R 999:996 /tmp/build-cache + # 构建sky版本APK -docker run --env-file .docker/.env --rm -it -v .:/home/mobiledevops/app mobiledevops/flutter-sdk-image:3.16.4 \ +docker run --rm -it \ +--env-file .docker/.env \ +-v .:/home/mobiledevops/app \ +-v /tmp/build-cache/:/home/mobiledevops/app/build/ \ +-v ~/.gradle/:/home/mobiledevops/.gradle/ \ +-v ~/android-sdk-linux:/opt/android-sdk-linux \ +mobiledevops/flutter-sdk-image:3.16.4 \ flutter build apk --release --flavor sky -t lib/main_sky_full.dart ``` @@ -21,8 +35,83 @@ flutter build apk --release --flavor sky -t lib/main_sky_full.dart ## 排除故障 -测试谷歌连接 +### 内存要求 +4G内存下经常有异常崩溃,建议虚拟机8G内存 + +### 测试谷歌连接 ```bash # flutter以及maven 下载地址是否正常 curl -i https://storage.googleapis.com/flutter_infra_release/ ``` + +### 卡在Running Gradle task 'assembleSkyRelease'... +这一步最耗时的是在下载maven仓库的依赖,如果卡在这里,可能是代理设置有问题, +请检查代理~/.gradle/gradle.properties中配置的代理,代理面板是否有请求输出 + +在网络请求平息了之后,又进入了漫长到令人绝望的等待中,这时候你可能会怀疑地球是否仍在转动,我们是否陷入了是时空停滞,别担心,这大概是由于计算机性能太低,或者在CPU受限的虚拟机中导致的,你可以在另外的窗口运行htop命令,或直接查看宿主机的CPU使用率,来观察系统是否处于卡顿(多线程编译导致的)以及进程树列表是否在变动,这些观察可以让你继续耐心等待,直到屏幕出现一片红色的报错信息。 + +如果在报错信息中看到正在编译XX或者下载XX,没有看到任何错误但是终止了,这可能是内存不够导致的崩溃。 + +参考的信息 +```bash +# du -sh ~/android-sdk-linux/ +7.1G /root/android-sdk-linux/ + +# du -sh ~/.gradle/ +4.6G /root/.gradle/ + +# du -sh /tmp/build-cache +514M /tmp/build-cache + +``` + +正常的输出 +```bash +mobiledevops@946e5e22d9c5:~/app$ flutter build apk --release --flavor sky -t lib/main_sky_full.dart +Flutter assets will be downloaded from https://mirrors.tuna.tsinghua.edu.cn/flutter. Make sure you trust this source! + +Warning: The plugin camera_android requires Android SDK version 34. +For more information about build configuration, see https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. +Warning: The plugin flutter_local_notifications requires Android SDK version 34. +For more information about build configuration, see https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. +Warning: The plugin fluwx requires Android SDK version 34. +For more information about build configuration, see https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. +Warning: The plugin google_maps_flutter_android requires Android SDK version 34. +For more information about build configuration, see https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. +Warning: The plugin image_picker_android requires Android SDK version 34. +For more information about build configuration, see https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. +Warning: The plugin url_launcher_android requires Android SDK version 34. +For more information about build configuration, see https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. +Warning: The plugin video_player_android requires Android SDK version 34. +For more information about build configuration, see https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. +Warning: The plugin webview_flutter_android requires Android SDK version 34. +For more information about build configuration, see https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. +One or more plugins require a higher Android SDK version. +Fix this issue by adding the following to /home/mobiledevops/app/android/app/build.gradle: +android { + compileSdkVersion 34 + ... +} + +Flutter assets will be downloaded from https://mirrors.tuna.tsinghua.edu.cn/flutter. Make sure you trust this source! +Font asset "MaterialIcons-Regular.otf" was tree-shaken, reducing it from 1645184 to 2388 bytes (99.9% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app. +WARNING: [Processor] Library '/home/mobiledevops/.gradle/caches/modules-2/files-2.1/androidx.media2/media2-session/1.2.1/f927563711e36371c19b2e86fb7ccf1c3f259ca4/media2-session-1.2.1.aar' contains references to both AndroidX and old support library. This seems like the library is partially migrated. Jetifier will try to rewrite the library anyway. + Example of androidX reference: 'androidx/media2/session/MediaBrowser$Builder' + Example of support library reference: 'android/support/v4/media/session/MediaSessionCompat$Token' +Note: Some input files use or override a deprecated API. +Note: Recompile with -Xlint:deprecation for details. +Note: Some input files use unchecked or unsafe operations. +Note: Recompile with -Xlint:unchecked for details. +Note: Some input files use unchecked or unsafe operations. +Note: Recompile with -Xlint:unchecked for details. +Running Gradle task 'assembleSkyRelease'... 257.0s +✓ Built build/app/outputs/flutter-apk/app-sky-release.apk (45.3MB). +mobiledevops@946e5e22d9c5:~/app$ +exit +``` + +### 手动编译 +```bash +cd android +./gradlew assembleSkyRelease +``` diff --git a/star_lock/.docker/gradle.properties.example b/star_lock/.docker/gradle.properties.example new file mode 100644 index 00000000..e44bd6eb --- /dev/null +++ b/star_lock/.docker/gradle.properties.example @@ -0,0 +1,4 @@ +systemProp.http.proxyHost=127.0.0.1 +systemProp.http.proxyPort=1080 +systemProp.https.proxyHost=127.0.0.1 +systemProp.https.proxyPort=1080 From d76f52a0816ab4ac59146885cd1c368395b7f152 Mon Sep 17 00:00:00 2001 From: Daisy <> Date: Tue, 9 Apr 2024 18:29:54 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E8=99=B9=E8=86=9C=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E6=9A=82=E6=97=A0=E5=8D=8F=E8=AE=AE=EF=BC=8C=E5=88=A0=E5=8E=BB?= =?UTF-8?q?=E6=97=A0=E7=94=A8=E5=8D=8F=E8=AE=AE=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iris/addIris/addIris_logic.dart | 255 ------------------ .../lockDetail/iris/addIris/addIris_page.dart | 1 - 2 files changed, 256 deletions(-) diff --git a/star_lock/lib/main/lockDetail/iris/addIris/addIris_logic.dart b/star_lock/lib/main/lockDetail/iris/addIris/addIris_logic.dart index 4404283e..4020fd9e 100644 --- a/star_lock/lib/main/lockDetail/iris/addIris/addIris_logic.dart +++ b/star_lock/lib/main/lockDetail/iris/addIris/addIris_logic.dart @@ -20,261 +20,6 @@ import '../../../../../tools/storage.dart'; class AddIrisLogic extends BaseGetXController { final AddFaceState state = AddFaceState(); - // 监听设备返回的数据 - late StreamSubscription _replySubscription; - void _initReplySubscription() { - _replySubscription = - EventBusManager().eventBus!.on().listen((reply) async { - // 添加人脸开始 - if (reply is SenderAddFaceReply) { - _replyAddFaceBegin(reply); - } - - // 添加指纹过程 - if (reply is SenderAddFaceProcessReply) { - _replyAddFaceProcess(reply); - } - - // 添加指纹确认 - if (reply is SenderAddFaceConfirmationReply) { - _replyAddFaceConfirmation(reply); - } - }); - } - - Future _replyAddFaceBegin(Reply reply) async { - int status = reply.data[2]; - print("status:$status"); - - switch (status) { - case 0x00: - //成功 - // print("${reply.commandType!.typeValue} 人脸开始数据解析成功"); - state.ifConnectScuess.value = true; - - // 最大图片数 - state.maxRegCount.value = reply.data[10]; - print("人脸开始state.maxRegCount.value:${state.maxRegCount.value}"); - // state.fingerprintNumber.value = reply.data.last.toString(); - break; - case 0x06: - //无权限 - print("${reply.commandType!.typeValue} 需要鉴权"); - var privateKey = await Storage.getStringList(saveBluePrivateKey); - List getPrivateKeyList = changeStringListToIntList(privateKey!); - - var publicKey = await Storage.getStringList(saveBluePublicKey); - List publicKeyDataList = changeStringListToIntList(publicKey!); - - var token = reply.data.sublist(5, 9); - var saveStrList = changeIntListToStringList(token); - print("_replyAddFaceReplyToken:$token"); - Storage.setStringList(saveBlueToken, saveStrList); - - IoSenderManage.senderAddFaceCommand( - keyID: "1", - userID: await Storage.getUid(), - faceNo: 1, - useCountLimit: 0xff, - // startTime:0x11223344, - // endTime:0x11223344, - startTime: state.startDate.value ~/ 1000, - endTime: state.endDate.value ~/ 1000, - needAuthor: 1, - publicKey: publicKeyDataList, - privateKey: getPrivateKeyList, - token: token, - ); - break; - case 0x07: - //无权限 - print("${reply.commandType!.typeValue} 用户无权限"); - - break; - case 0x09: - // 权限校验错误 - print("${reply.commandType!.typeValue} 权限校验错误"); - - break; - default: - //失败 - print("${reply.commandType!.typeValue} 失败"); - - break; - } - } - - Future _replyAddFaceProcess(Reply reply) async { - int status = reply.data[2]; - print("******33 status:$status"); - - switch (status) { - case 0x00: - //成功 - print("${reply.commandType!.typeValue} 注册人脸过程数据解析成功"); - if (reply.data[5] == 255) { - // 注册人脸失败 - print("${reply.commandType!.typeValue} 注册人脸过程失败"); - showToast("添加失败"); - Get.close(2); - } else { - // state.addFaceProcessNumber.value++; - - // 当前注册数 - state.regIndex.value = reply.data[6]; - print("注册人脸过程state.regIndex.value:${state.regIndex.value}"); - } - break; - case 0x06: - //需要权限 - - break; - case 0x07: - //无权限 - print("${reply.commandType!.typeValue} 用户无权限"); - - break; - case 0x09: - // 权限校验错误 - print("${reply.commandType!.typeValue} 权限校验错误"); - - break; - default: - //失败 - print("${reply.commandType!.typeValue} 注册人脸过程default失败"); - - break; - } - } - - Future _replyAddFaceConfirmation(Reply reply) async { - int status = reply.data[2]; - print("status:$status"); - - switch (status) { - case 0x00: - //成功 - print("${reply.commandType!.typeValue} 人脸确认数据解析成功"); - // print("添加人脸确认成功,调用添加指纹接口"); - if (state.faceNumber.value == (reply.data[6]).toString()) { - return; - } else { - state.faceNumber.value = (reply.data[6]).toString(); - } - addFaceData(); - break; - case 0x06: - //需要权限 - - break; - case 0x07: - //无权限 - print("${reply.commandType!.typeValue} 用户无权限"); - - break; - case 0x09: - // 权限校验错误 - print("${reply.commandType!.typeValue} 权限校验错误"); - - break; - default: - //失败 - print("${reply.commandType!.typeValue} 人脸确认default失败"); - - break; - } - } - - // 添加人脸开始 - Future senderAddFace() async { - showBlueConnetctToastTimer(action: () { - Get.close(1); - }); - BlueManage().bludSendData(BlueManage().connectDeviceName, - (BluetoothConnectionState deviceConnectionState) async { - if (deviceConnectionState == BluetoothConnectionState.connected) { - cancelBlueConnetctToastTimer(); - var publicKey = await Storage.getStringList(saveBluePublicKey); - List publicKeyDataList = changeStringListToIntList(publicKey!); - - var privateKey = await Storage.getStringList(saveBluePrivateKey); - List getPrivateKeyList = changeStringListToIntList(privateKey!); - - var token = await Storage.getStringList(saveBlueToken); - List getTokenList = changeStringListToIntList(token!); - print( - "openDoorTokenPubToken:$getTokenList state.startDate.value:${state.startDate.value}"); - print( - "限时人脸开始时间:${state.startDate.value ~/ 1000} 限时人脸结束时间:${state.endDate.value ~/ 1000}"); - - IoSenderManage.senderAddFaceCommand( - keyID: "1", - userID: await Storage.getUid(), - faceNo: state.isAdministrator.value == true ? 254 : 1, - useCountLimit: 0xff, - // startTime:0x11223344, - // endTime:0x11223344, - startTime: state.startDate.value ~/ 1000, - endTime: state.endDate.value ~/ 1000, - needAuthor: 1, - publicKey: publicKeyDataList, - privateKey: getPrivateKeyList, - token: getTokenList, - ); - } else if (deviceConnectionState == - BluetoothConnectionState.disconnected) { - if (state.ifCurrentScreen.value == true) { - showBlueConnetctToast(); - } - cancelBlueConnetctToastTimer(); - Get.close(1); - } - }); - } - - // 添加人脸 - void addFaceData() async { - var entity = await ApiRepository.to.addFaceData( - lockId: state.lockId.value, - faceName: state.faceName.value, - faceNumber: state.faceNumber.value, - faceType: state.faceType.value, - startDate: state.startDate.value, - endDate: state.endDate.value, - featureData: state.featureData.value, - addType: state.addType.value, - cyclicConfig: state.cyclicConfig.value, - faceRight: state.isAdministrator.value == true ? 1 : 0, - ); - - if (entity.errorCode!.codeIsSuccessful) { - // Toast.show(msg: "添加成功"); - print('更新人脸用户账号成功了么1'); - updateFaceUserNoLoadData(entity.data!.faceId!); - } - } - - // 更新人脸用户账号 - void updateFaceUserNoLoadData(int faceId) async { - var entity = await ApiRepository.to.updateFaceUserNo( - faceId: faceId, - lockId: state.lockId.value, - faceUserNo: state.faceNumber.value, - ); - if (entity.errorCode!.codeIsSuccessful) { - print('更新人脸用户账号成功了么2'); - showToast("添加成功"); - if (state.fromType.value == 2) { - // 回调人脸号 - eventBus.fire(ChickInAddStaffCardAndFingerprintBlockNumberEvent( - state.faceNumber.value)); - } else if (state.fromType.value == 1) { - eventBus.fire(OtherTypeRefreshListEvent()); - } - Get.close(2); - } - } - @override void onReady() { // TODO: implement onReady diff --git a/star_lock/lib/main/lockDetail/iris/addIris/addIris_page.dart b/star_lock/lib/main/lockDetail/iris/addIris/addIris_page.dart index 552898ae..72787529 100644 --- a/star_lock/lib/main/lockDetail/iris/addIris/addIris_page.dart +++ b/star_lock/lib/main/lockDetail/iris/addIris/addIris_page.dart @@ -72,7 +72,6 @@ class _AddIrisPageState extends State { borderRadius: 20.w, onClick: () { state.isClickAddFace.value = true; - logic.senderAddFace(); }), ) : Row( From 96e6fd54633acf3684d6af956ad8ecbed797950f Mon Sep 17 00:00:00 2001 From: anfe <448468458@qq.com> Date: Wed, 10 Apr 2024 09:47:05 +0800 Subject: [PATCH 6/6] =?UTF-8?q?feat:=E7=BB=9F=E4=B8=80=E6=9D=83=E9=99=90di?= =?UTF-8?q?alog=E7=9A=84=E6=8E=A7=E5=88=B6=EF=BC=8C=E9=92=88=E5=AF=B9andro?= =?UTF-8?q?id=E5=8D=8E=E4=B8=BA=E7=9A=84=E8=BF=87=E5=AE=A1=E8=A6=81?= =?UTF-8?q?=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/permission/permission_dialog.dart | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 star_lock/lib/permission/permission_dialog.dart diff --git a/star_lock/lib/permission/permission_dialog.dart b/star_lock/lib/permission/permission_dialog.dart new file mode 100644 index 00000000..12b4a80a --- /dev/null +++ b/star_lock/lib/permission/permission_dialog.dart @@ -0,0 +1,84 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:star_lock/app_settings/app_settings.dart'; + +class PermissionDialog { + static Map titles = { + Permission.camera: '相机', + Permission.photos: '相册', + Permission.storage: '读写', + Permission.location: '定位', + }; + + static Map contents = { + Permission.camera: '需要访问相机权限才能拍照上传文件例如头像上传', + Permission.photos: '需要访问相机权限才能使用相册图片上传文件上传头像', + Permission.storage: '需要访问读写权限才能使用本地图片上传头像', + Permission.location: '需要访问定位权限才能使用添加钥匙功能的位置信息', + }; + + //显示权限判断申请框 + static Future request(Permission permission) async { + if (Get.context == null) { + return false; + } + bool application = true; + if (AppPlatform.isAndroid) { + application = await showDialog( + context: Get.context!, + builder: (BuildContext context) { + return AlertDialog( + title: Text('申请${titles[permission] ?? ''}权限'), + content: Text(contents[permission] ?? ''), + actions: [ + TextButton( + child: const Text('不允许'), + onPressed: () { + Get.back(result: false); + }, + ), + TextButton( + child: const Text('允许'), + onPressed: () { + Get.back(result: true); + }, + ), + ], + ); + }, + ); + } + if (!application) { + showSet(permission); + return false; + } else { + return await permission.request().isGranted; + } + } + + //显示设置页面 + static Future showSet(Permission permission) async { + if (Get.context == null) { + return; + } + showDialog( + context: Get.context!, + builder: (BuildContext context) { + return AlertDialog( + title: Text('${titles[permission] ?? ''}权限被拒绝'), + content: Text('${contents[permission] ?? ''},请手动在系统设置中开启${titles[permission]}权限以继续使用应用。'), + actions: [ + TextButton( + child: Text('去设置'), + onPressed: () { + Get.back(); // 关闭对话框 + openAppSettings(); // 打开系统设置页面 + }, + ), + ], + ); + }, + ); + } +}