diff --git a/.DS_Store b/.DS_Store index 46477568..c406a585 100755 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/images/lan/lan_en.json b/images/lan/lan_en.json index cb39e17a..41bfb321 100755 --- a/images/lan/lan_en.json +++ b/images/lan/lan_en.json @@ -2,14 +2,14 @@ "starLock": "Star Lock", "lockThrough": "Lock Through", "clickUnlockAndHoldDownClose": "Click To Unlock And Hold Down to Close", - "checkingIn": "Checking In", - "electronicKey": "Electronic Key", + "checkingIn": "CheckIn", + "electronicKey": "KeyCard", "password": "Password", "card": "Card", - "fingerprint": "Fingerprint", - "remoteControl": "RemoteControl", + "fingerprint": "Finger", + "remoteControl": "RemCtrl", "face": "face", - "operatingRecord": "Operating Record", + "operatingRecord": "OpLog", "doorLockLog": "Door lock log", "number": "Number", "additive": "Additive", @@ -217,7 +217,7 @@ "aboutToExpire": "About to expire", "deAuthorize": "de-authorize", "changeName": "Change name", - "authorizedAdmin": "Authorized Admin", + "authorizedAdmin": "Admin", "addAuthorizedAdmin": "Adding an Authorized Administrator", "lockGroup": "Lock Group", "transferSmartLock": "Transfer Smart Lock", @@ -407,10 +407,10 @@ "getFingerprint": "Get Fingerprint", "safeVerify": "Security verification", "deleteAccountTips": "After deleting the account, all your information and related records will be completely deleted from the platform, and can not be recovered, delete or not", - "humanFace": "Human Face", + "humanFace": "HmFace", "monitoring": "Monitoring", "videoLog": "Video Log", - "messageReminding": "Message Reminding", + "messageReminding": "Notice", "superAdmin": "Super Admin", "normalUser": "Normal User", "gatewayDevice": "Gateway Device", @@ -454,7 +454,7 @@ "videoSlot": "Video slot", "密码": "Password", "卡": "Card", - "指纹": "Fingerprint", + "指纹": "Finger", "人脸": "Face", "配件商城": "Lock Mall", "公司名称": "Company Name", @@ -487,7 +487,7 @@ "钥匙将在": "The key will be in", "天后失效": "Days later invalid", "电量更新时间:": "Power update time:", - "新增配件": "Add accessories", + "新增配件": "Add", "请在锁旁边完成第一次开锁": "Please complete the first unlock next to the lock", "正在开锁中...": "Unlocking...", "你的钥匙": "Your key", @@ -906,5 +906,20 @@ "转移成功": "Transfer success", "该已锁被删除": "The locked is deleted", "授权管理员只能查看和管理自己下发的钥匙、密码等权限": "Authorized administrators can only view and manage the keys, passwords, etc. they issued", - "添加授权管理员": "Add authorized administrator" + "添加授权管理员": "Add authorized administrator", + "导出记录":"Export record", + "选择时间段":"Select time period", + "导出":"Export", + "批量导出":"Batch export", + "读取记录":"Read record", + "手机需联网":"NeedNet", + "设备":"Device", + "消息":"Message", + "智能分析":"Intelligent analytics", + "精准识别设备事件,过滤无效信息":"Accurately identify device events and filter out invalid information", + "系统设置":"System settings", + "系统的全局配置在此项内进行设置":"The global configuration of the system is set in this item", + "导出操作记录":"Export operation record", + "立即查看":"View now", + "导出成功":"Export success" } diff --git a/images/lan/lan_keys.json b/images/lan/lan_keys.json index 49d763d5..33c7a7d9 100755 --- a/images/lan/lan_keys.json +++ b/images/lan/lan_keys.json @@ -938,5 +938,20 @@ "转移成功": "转移成功", "该已锁被删除": "该已锁被删除", "授权管理员只能查看和管理自己下发的钥匙、密码等权限": "授权管理员只能查看和管理自己下发的钥匙、密码等权限", - "添加授权管理员": "添加授权管理员" + "添加授权管理员": "添加授权管理员", + "导出记录":"导出记录", + "选择时间段":"选择时间段", + "导出":"导出", + "批量导出":"批量导出", + "读取记录":"读取记录", + "手机需联网":"手机需联网", + "设备":"设备", + "消息":"消息", + "智能分析":"智能分析", + "精准识别设备事件,过滤无效信息":"精准识别设备事件,过滤无效信息", + "系统设置":"系统设置", + "系统的全局配置在此项内进行设置":"系统的全局配置在此项内进行设置", + "导出操作记录":"导出操作记录", + "立即查看":"立即查看", + "导出成功":"导出成功" } diff --git a/images/lan/lan_zh.json b/images/lan/lan_zh.json index 91ab9c85..0450840d 100755 --- a/images/lan/lan_zh.json +++ b/images/lan/lan_zh.json @@ -903,5 +903,20 @@ "转移成功": "转移成功", "该已锁被删除": "该已锁被删除", "授权管理员只能查看和管理自己下发的钥匙、密码等权限": "授权管理员只能查看和管理自己下发的钥匙、密码等权限", - "添加授权管理员": "添加授权管理员" + "添加授权管理员": "添加授权管理员", + "导出记录":"导出记录", + "选择时间段":"选择时间段", + "导出":"导出", + "批量导出":"批量导出", + "读取记录":"读取记录", + "手机需联网":"手机需联网", + "设备":"设备", + "消息":"消息", + "智能分析":"智能分析", + "精准识别设备事件,过滤无效信息":"精准识别设备事件,过滤无效信息", + "系统设置":"系统设置", + "系统的全局配置在此项内进行设置":"系统的全局配置在此项内进行设置", + "导出操作记录":"导出操作记录", + "立即查看":"立即查看", + "导出成功":"导出成功" } diff --git a/ios/.DS_Store b/ios/.DS_Store index 80df6dcc..bc9ad5a5 100755 Binary files a/ios/.DS_Store and b/ios/.DS_Store differ diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 101a2449..4f61f0ae 100755 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -121,6 +121,10 @@ UIViewControllerBasedStatusBarAppearance + NSFileProtectionKey + NSFileProtectionCompleteUntilFirstUserAuthentication + UIFileSharingEnabled + io.flutter.embedded_views_preview diff --git a/ios/Runner/XSFlutterManager.m b/ios/Runner/XSFlutterManager.m index e371a2c3..b33e8d5c 100755 --- a/ios/Runner/XSFlutterManager.m +++ b/ios/Runner/XSFlutterManager.m @@ -48,12 +48,19 @@ self.textToShare = paramDic[@"shareText"]; self.urlToShare = paramDic[@"urlToShare"]; } - //分享的url - NSURL *urlToShare = [NSURL URLWithString:self.urlToShare]; -// NSURL *urlToShare = [NSURL URLWithString:@"https://pre.lock.star-lock.cn:8093/login"]; + if ([self.urlToShare isEqualToString:"fileShare"]) { + // 创建要分享或操作的文件对象 + let fileURL = URL(fileURLWithPath: "/path/to/file.pdf") - //在这里呢 如果想分享图片 就把图片添加进去 文字什么的通上 - NSArray *activityItems = @[self.textToShare,urlToShare]; + // 将文件对象添加到数组中 + let activityItems = [fileURL] + } else { + //分享的url + NSURL *urlToShare = [NSURL URLWithString:self.urlToShare]; + + //在这里呢 如果想分享图片 就把图片添加进去 文字什么的通上 + NSArray *activityItems = @[self.textToShare,urlToShare]; + } UIActivityViewController *activityVC = [[UIActivityViewController alloc]initWithActivityItems:activityItems applicationActivities:nil]; diff --git a/lib/appRouters.dart b/lib/appRouters.dart index 48d10243..e5d54058 100755 --- a/lib/appRouters.dart +++ b/lib/appRouters.dart @@ -6,8 +6,10 @@ import 'package:star_lock/login/login/starLock_login_xhj_page.dart'; import 'package:star_lock/login/register/starLock_register_binding.dart'; import 'package:star_lock/login/register/starLock_register_xhj_page.dart'; import 'package:star_lock/main/lockDetail/accessoriesList/accessoriesList_page.dart'; +import 'package:star_lock/main/lockDetail/doorLockLog/batchExportLog/batchExportLog_page.dart'; import 'package:star_lock/main/lockDetail/doorLockLog/doorLockLog_page.dart'; - +import 'package:star_lock/main/lockDetail/doorLockLog/exportSuccess/exportSuccess_page.dart'; +import 'package:star_lock/main/lockDetail/doorLockLog/viewExportRecord/viewExportRecord_page.dart'; import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/massSendLockGroupList/lockUserList/lockUserList_page.dart'; 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'; @@ -15,6 +17,7 @@ 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/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'; @@ -22,7 +25,6 @@ import 'package:star_lock/main/lockDetail/lockSet/faceUnlock/faceUnlock_page.dar import 'package:star_lock/main/lockDetail/lockSet/liveVideo/liveVideo_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/motorPower/motorPower_page.dart'; import 'package:star_lock/main/lockDetail/lockSet/openDoorDirection/openDoorDirection_page.dart'; -import 'package:star_lock/main/lockDetail/lockDetail/lockDetail_main_page.dart'; import 'package:star_lock/main/lockDetail/messageWarn/addFamily/addFamily_page.dart'; import 'package:star_lock/main/lockDetail/messageWarn/lockUser/lockUser_page.dart'; import 'package:star_lock/main/lockDetail/messageWarn/msgNotification/coerceOpenDoor/coerceFingerprint/coerceFingerprint_page.dart'; @@ -62,6 +64,8 @@ import 'login/login/starLock_login_page.dart'; import 'login/register/starLock_register_page.dart'; import 'login/selectCountryRegion/selectCountryRegion_page.dart'; import 'main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_page.dart'; +import 'main/lockDetail/authorizedAdmin/authorizedAdminList/authorizedAdminList_page.dart'; +import 'main/lockDetail/authorizedAdmin/volumeAuthorizationLock/volumeAuthorizationLockManage/volumeAuthorizationLockManage_page.dart'; import 'main/lockDetail/card/addCardType/addCardType_page.dart'; import 'main/lockDetail/card/addICCard/addICCard_page.dart'; import 'main/lockDetail/card/cardDetail/cardDetail_page.dart'; @@ -79,9 +83,13 @@ import 'main/lockDetail/checkingIn/checkingInSetWorkdaySet/checkingInSetWorkdayS import 'main/lockDetail/checkingIn/checkingInStaff/checkingInSetAddStaff/checkingInAddStaff_page.dart'; import 'main/lockDetail/checkingIn/checkingInStaff/checkingInSetStaffList/checkingInStaffList_page.dart'; import 'main/lockDetail/checkingIn/checkingInStaff/checkingInStaffDetail/checkingInStaffDetail_page.dart'; +import 'main/lockDetail/electronicKey/electronicKeyDetail/electronicKeyDetail/electronicKeyDetail_page.dart'; +import 'main/lockDetail/electronicKey/electronicKeyDetail/electronicKeyDetailChangeDate/electronicKeyDetailChangeDate_page.dart'; import 'main/lockDetail/electronicKey/electronicKeyDetail/electronicKeyPeriodValidity/electronicKeyPeriodValidity_page.dart'; +import 'main/lockDetail/electronicKey/electronicKeyList/electronicKeyList_page.dart'; import 'main/lockDetail/electronicKey/massSendElectronicKey/massSendElectronicKey/massSendElectronicManageKey/massSendElectronicKeyManage_page.dart'; import 'main/lockDetail/electronicKey/sendElectronicKey/sendElectronicKey/sendElectronicKey_page.dart'; +import 'main/lockDetail/electronicKey/sendEmailNotification/sendEmailNotification_page.dart'; import 'main/lockDetail/face/addFace/addFace_page.dart'; import 'main/lockDetail/face/addFaceType/addFaceType_page.dart'; import 'main/lockDetail/face/faceList/faceList_page.dart'; @@ -90,6 +98,7 @@ import 'main/lockDetail/fingerprint/addFingerprintSelectType/addFingerprintType_ import 'main/lockDetail/fingerprint/addFingerprintTip/addFingerprintTip_page.dart'; import 'main/lockDetail/fingerprint/fingerprintDetail/fingerprintDetail_page.dart'; import 'main/lockDetail/fingerprint/fingerprintList/fingerprintList_page.dart'; +import 'main/lockDetail/lockOperatingRecord/lockOperatingRecord_page.dart'; import 'main/lockDetail/lockSet/automaticBlocking/automaticBlocking_page.dart'; import 'main/lockDetail/lockSet/basicInformation/adminOpenLockPassword/adminOpenLockPassword_page.dart'; import 'main/lockDetail/lockSet/basicInformation/basicInformation/basicInformation_page.dart'; @@ -122,6 +131,8 @@ import 'main/lockDetail/lockSet/wirelessKeyboard/selectWirelessKeyboard/selectWi import 'main/lockDetail/lockSet/wirelessKeyboard/wirelessKeyboardList/wirelessKeyboard_page.dart'; import 'main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart'; import 'main/lockDetail/monitoring/monitoringRealTimeScreen/monitoringRealTimeScreen_page.dart'; +import 'main/lockDetail/passwordKey/passwordKeyDetail/passwordKeyDetail_page.dart'; +import 'main/lockDetail/passwordKey/passwordKeyList/passwordKeyList_page.dart'; import 'main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart'; import 'main/lockDetail/realTimePicture/realTimePicture_page.dart'; import 'main/lockDetail/remoteControl/addRemoteControl/addRemoteControl_page.dart'; @@ -132,18 +143,9 @@ import 'main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart'; import 'main/lockDetail/videoLog/videoLogDownLoad/videoLogDownLoad_page.dart'; import 'main/lockMian/demoMode/demoModeLockDetail/demoModeLockDetail_page.dart'; import 'main/lockMian/demoMode/demoModeLockSet/demoModeLockSet_page.dart'; +import 'main/lockMian/lockMain/lockMain_page.dart'; import 'mine/about/about_page.dart'; import 'mine/addLock/addLock/addLock_page.dart'; -import 'main/lockDetail/authorizedAdmin/authorizedAdminList/authorizedAdminList_page.dart'; -import 'main/lockDetail/authorizedAdmin/volumeAuthorizationLock/volumeAuthorizationLockManage/volumeAuthorizationLockManage_page.dart'; -import 'main/lockDetail/electronicKey/electronicKeyDetail/electronicKeyDetail/electronicKeyDetail_page.dart'; -import 'main/lockDetail/electronicKey/electronicKeyDetail/electronicKeyDetailChangeDate/electronicKeyDetailChangeDate_page.dart'; -import 'main/lockDetail/electronicKey/electronicKeyList/electronicKeyList_page.dart'; -import 'main/lockDetail/electronicKey/sendEmailNotification/sendEmailNotification_page.dart'; -import 'main/lockDetail/lockOperatingRecord/lockOperatingRecord_page.dart'; -import 'main/lockDetail/passwordKey/passwordKeyDetail/passwordKeyDetail_page.dart'; -import 'main/lockDetail/passwordKey/passwordKeyList/passwordKeyList_page.dart'; -import 'main/lockMian/lockMain/lockMain_page.dart'; import 'mine/addLock/addLockSelectCountry/addLockSelectCountry_page.dart'; import 'mine/addLock/lockAddress/gaode/lockAddressGaoDe_page.dart'; import 'mine/addLock/lockAddress/lockAddress/lockAddress_page.dart'; @@ -162,11 +164,11 @@ import 'mine/message/messageDetail/messageDetail_page.dart'; import 'mine/message/messageList/messageList_page.dart'; import 'mine/mine/starLockMine_page.dart'; import 'mine/mineMultiLanguage/mineMultiLanguage_page.dart'; -import 'mine/minePersonInfo/minePersonInfoPage/minePersonInfo_page.dart'; import 'mine/minePersonInfo/minePersonInfoEditAccount/minePersonInfoEditAccount/mineUnbindPhoneOrEmail_page.dart'; import 'mine/minePersonInfo/minePersonInfoEditAccount/minePersonInfoEditAccountNext/minePersonInfoEditAccountNext_page.dart'; import 'mine/minePersonInfo/minePersonInfoEditIphone/minePersonInfoEditIphone_page.dart'; import 'mine/minePersonInfo/minePersonInfoEditName/minePersonInfoEditName_page.dart'; +import 'mine/minePersonInfo/minePersonInfoPage/minePersonInfo_page.dart'; import 'mine/minePersonInfo/minePersonInfoResetPassword/minePersonInfoResetPassword_page.dart'; import 'mine/minePersonInfo/minePersonInfoSetSafetyProblem/minePersonInfoSetSafetyProblem_page.dart'; import 'mine/mineSet/appUnlockNeedMobileNetworkingLock/appUnlockNeedMobileNetworkingLock_page.dart'; @@ -174,6 +176,7 @@ import 'mine/mineSet/authorityManagement/authorityManagement_page.dart'; import 'mine/mineSet/authorityManagement/getDeviceList_page.dart'; import 'mine/mineSet/authorityManagement/getNameList_page.dart'; import 'mine/mineSet/authorizedAdministrator/addAuthorizedAdministrator/addAuthorizedAdministratorManage/addAuthorizedAdministratorManage_page.dart'; +import 'mine/mineSet/authorizedAdministrator/authorizedAdministrator/authorizedAdministratorList_page.dart'; import 'mine/mineSet/hideInvalidUnlockPermissions/hideInvalidUnlockPermissions_page.dart'; import 'mine/mineSet/lockGroup/groupEditLock/groupEditLock_page.dart'; import 'mine/mineSet/lockGroup/lockGroupDetailList/lockItemList_page.dart'; @@ -192,7 +195,6 @@ import 'mine/valueAddedServices/valueAddedServicesNoteAndEmailDetail/valueAddedS import 'mine/valueAddedServices/valueAddedServicesRealName/value_added_services_real_name_page.dart'; import 'mine/valueAddedServices/valueAddedServicesSMSTemplate/valueAddedServicesAddSMSTemplate/newSMSTemplate_page.dart'; import 'mine/valueAddedServices/valueAddedServicesSMSTemplate/valueAddedServicesListSMSTemplate/customSMSTemplateList_page.dart'; -import 'mine/mineSet/authorizedAdministrator/authorizedAdministrator/authorizedAdministratorList_page.dart'; import 'starLockApplication/starLockApplication.dart'; import 'tools/seletKeyCyclicDate/seletKeyCyclicDate_page.dart'; @@ -486,6 +488,9 @@ abstract class Routers { '/advancedFunctionRecordPage'; //高级功能购买记录 static const String administratorAssociationLockPage = '/administratorAssociationLockPage'; //我的设置-授权管理员-关联锁 + static const String batchExportLogPage = '/batchExportLogPage'; //批量导出操作记录 + static const String exportSuccessPage = '/exportSuccessPage'; //导出成功 + static const String viewExportRecordPage = '/viewExportRecordPage'; //查看导出记录 static const String login = '/login'; //登录 } @@ -498,7 +503,7 @@ abstract class AppRouters { ), GetPage( name: Routers.login, - page: () => F.sw( + page: () => F.sw( skyCall: () => const StarLockLoginPage(), xhjCall: () => const StarLockLoginXHJPage()), ), @@ -1143,8 +1148,16 @@ abstract class AppRouters { GetPage( name: Routers.administratorAssociationLockPage, page: () => const AdministratorAssociationLockPage()), - GetPage( + GetPage( name: Routers.expireKeyChangeDatePage, page: () => const ExpireKeyChangeDatePage()), + GetPage( + name: Routers.batchExportLogPage, + page: () => const BatchExportLogPage()), + GetPage( + name: Routers.exportSuccessPage, page: () => const ExportSuccessPage()), + GetPage( + name: Routers.viewExportRecordPage, + page: () => const ViewExportRecordPage()), ]; } diff --git a/lib/blue/io_modelVendor.dart b/lib/blue/io_modelVendor.dart index 268b206b..1900ebfe 100755 --- a/lib/blue/io_modelVendor.dart +++ b/lib/blue/io_modelVendor.dart @@ -4,7 +4,7 @@ class IoModelVendor { static String vendor_XHJ = 'XHJ'; - static String model_XHJ_SYD = 'SYD-BLE-01'; + static String model_XHJ_SYD = 'SYD8811-751'; static String model_XHJ_JL = 'JL-BLE-01'; static String vendor_XL = 'XL'; diff --git a/lib/main/lockDetail/doorLockLog/batchExportLog/batchExportLog_logic.dart b/lib/main/lockDetail/doorLockLog/batchExportLog/batchExportLog_logic.dart new file mode 100644 index 00000000..35103fda --- /dev/null +++ b/lib/main/lockDetail/doorLockLog/batchExportLog/batchExportLog_logic.dart @@ -0,0 +1,48 @@ +import 'dart:io'; + +import 'package:get/get.dart'; +import 'package:http/http.dart' as http; +import 'package:path_provider/path_provider.dart'; +import 'package:star_lock/appRouters.dart'; +import 'package:star_lock/main/lockDetail/doorLockLog/batchExportLog/batchExportLog_state.dart'; +import 'package:star_lock/main/lockDetail/doorLockLog/exportRecordDialog/exportRecord_entity.dart'; +import 'package:star_lock/network/api_repository.dart'; +import 'package:star_lock/tools/baseGetXController.dart'; + +class BatchExportLogLogic extends BaseGetXController { + BatchExportLogState state = BatchExportLogState(); + + //操作记录-导出锁记录 + Future exportLockRecordsRequest() async { + final ExportRecordEntity entity = + await ApiRepository.to.batchExportLockRecords( + lockIds: state.lockIdList, + startDate: + DateTime.tryParse(state.beginTime.value)!.millisecondsSinceEpoch, + endDate: DateTime.tryParse(state.endTime.value)!.millisecondsSinceEpoch, + ); + + if (entity.errorCode!.codeIsSuccessful) { + final String url = entity.data!.fileUrl!; + //下载文件地址 + final String filePath = await downloadAndSaveFile(url); + Get.toNamed(Routers.exportSuccessPage, + arguments: {'filePath': filePath}); + } else { + throw 'Export failed with error code ${entity.errorCode}'; + } + } + + // 下载并保存文件 + Future downloadAndSaveFile(String url) async { + final http.Response response = await http.get(Uri.parse(url)); + if (response.statusCode == 200) { + final Directory directory = await getApplicationDocumentsDirectory(); + final File file = File('${directory.path}/exported_file.pdf'); + await file.writeAsBytes(response.bodyBytes); + return file.path; + } else { + throw 'Failed to download file'; + } + } +} diff --git a/lib/main/lockDetail/doorLockLog/batchExportLog/batchExportLog_page.dart b/lib/main/lockDetail/doorLockLog/batchExportLog/batchExportLog_page.dart new file mode 100644 index 00000000..973e2e9b --- /dev/null +++ b/lib/main/lockDetail/doorLockLog/batchExportLog/batchExportLog_page.dart @@ -0,0 +1,120 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:star_lock/appRouters.dart'; +import 'package:star_lock/app_settings/app_colors.dart'; +import 'package:star_lock/main/lockDetail/doorLockLog/batchExportLog/batchExportLog_logic.dart'; +import 'package:star_lock/main/lockDetail/doorLockLog/batchExportLog/batchExportLog_state.dart'; +import 'package:star_lock/tools/commonItem.dart'; +import 'package:star_lock/tools/dateTool.dart'; +import 'package:star_lock/tools/pickers/pickers.dart'; +import 'package:star_lock/tools/pickers/time_picker/model/date_mode.dart'; +import 'package:star_lock/tools/pickers/time_picker/model/pduration.dart'; +import 'package:star_lock/tools/submitBtn.dart'; +import 'package:star_lock/tools/titleAppBar.dart'; +import 'package:star_lock/translations/trans_lib.dart'; + +class BatchExportLogPage extends StatefulWidget { + const BatchExportLogPage({Key? key}) : super(key: key); + + @override + State createState() => _BatchExportLogPageState(); +} + +class _BatchExportLogPageState extends State + with RouteAware { + final BatchExportLogLogic logic = Get.put(BatchExportLogLogic()); + final BatchExportLogState state = Get.find().state; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColors.mainBackgroundColor, + appBar: TitleAppBar( + barTitle: '导出操作记录'.tr, + haveBack: true, + backgroundColor: AppColors.mainColor, + ), + body: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + CommonItem( + leftTitel: TranslationLoader.lanKeys!.lock!.tr, + rightTitle: state.lockIdList.isEmpty + ? TranslationLoader.lanKeys!.pleaseSelect!.tr + : state.lockIdList.length.toString(), + isHaveDirection: true, + action: () async { + final result = await Get.toNamed( + Routers.massSendLockGroupListPage, + arguments: { + 'keyLimits': '1', + 'lockIdList': state.lockIdList + }); + if (result != null && result.isNotEmpty) { + final List selectLockIdList = result['selectLockIdList']; + state.lockIdList.clear(); + selectLockIdList.forEach((element) { + state.lockIdList.add(element); + }); + setState(() {}); + } + }), + SizedBox( + height: 10.h, + ), + keyTimeWidget(), + SizedBox( + height: 60.h, + ), + SubmitBtn( + btnName: '导出'.tr, + onClick: () { + if (state.lockIdList.isEmpty) { + logic.showToast('请选择锁'.tr); + return; + } + logic.exportLockRecordsRequest(); + }), + ], + ), + ); + } + + // 生效失效时间 + Widget keyTimeWidget() { + return Column( + children: [ + Obx(() => CommonItem( + leftTitel: TranslationLoader.lanKeys!.effectiveTime!.tr, + rightTitle: state.beginTime.value, + isHaveLine: true, + isHaveDirection: true, + action: () { + final PDuration selectDate = + PDuration.parse(DateTime.tryParse(state.beginTime.value)); + Pickers.showDatePicker(context, + selectDate: selectDate, + mode: DateMode.YMD, onConfirm: (PDuration p) { + state.beginTime.value = DateTool().getYMDHNDateString(p, 2); + }); + })), + Obx(() => CommonItem( + leftTitel: TranslationLoader.lanKeys!.failureTime!.tr, + rightTitle: state.endTime.value, + isHaveDirection: true, + action: () { + final PDuration selectDate = + PDuration.parse(DateTime.tryParse(state.endTime.value)); + Pickers.showDatePicker(context, + selectDate: selectDate, + mode: DateMode.YMD, onConfirm: (PDuration p) { + state.endTime.value = DateTool().getYMDHNDateString(p, 2); + }); + })), + Container(height: 10.h), + ], + ); + } +} diff --git a/lib/main/lockDetail/doorLockLog/batchExportLog/batchExportLog_state.dart b/lib/main/lockDetail/doorLockLog/batchExportLog/batchExportLog_state.dart new file mode 100644 index 00000000..2e44ae4a --- /dev/null +++ b/lib/main/lockDetail/doorLockLog/batchExportLog/batchExportLog_state.dart @@ -0,0 +1,11 @@ +import 'package:get/get.dart'; +import 'package:intl/intl.dart'; + +class BatchExportLogState { + List lockIdList = []; //选中的锁ID列表 + + RxString beginTime = + DateFormat('yyyy-MM-dd').format(DateTime.now()).obs; //默认为当前时间 开始时间 + RxString endTime = + DateFormat('yyyy-MM-dd').format(DateTime.now()).obs; //默认为当前时间 结束时间 +} diff --git a/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart b/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart index 662a4248..63c87ed3 100755 --- a/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart +++ b/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart @@ -6,6 +6,7 @@ import 'package:star_lock/appRouters.dart'; import 'package:star_lock/main/lockDetail/doorLockLog/doorLockLog_entity.dart'; import 'package:star_lock/main/lockDetail/doorLockLog/doorLockLog_logic.dart'; import 'package:star_lock/main/lockDetail/doorLockLog/doorLockLog_state.dart'; +import 'package:star_lock/main/lockDetail/doorLockLog/exportRecordDialog/exportRecordDialog_page.dart'; import 'package:star_lock/tools/EasyRefreshTool.dart'; import 'package:star_lock/tools/advancedCalendar/src/widget.dart'; import 'package:star_lock/tools/commonDataManage.dart'; @@ -41,7 +42,8 @@ class _DoorLockLogPageState extends State with RouteAware { backgroundColor: AppColors.mainColor, actionsList: [ Visibility( - visible: CommonDataManage().currentKeyInfo.isLockOwner == 1, + visible: CommonDataManage().currentKeyInfo.isLockOwner == 1 || + CommonDataManage().currentKeyInfo.keyRight == 1, child: GestureDetector( child: Image.asset( 'images/icon_tips_Q.png', @@ -53,19 +55,22 @@ class _DoorLockLogPageState extends State with RouteAware { ShowTipView().showSureAlertDialog( '1.锁没有联网,密码、IC卡、指纹等开门记录无法实时上传,可以点击右上角按钮,然后读取记录。\n2.只能保留一定时间内的记录,如果您需要保留历史记录,可以点击右上角按钮,然后导出记录', tipTitle: '看不到操作记录,可能原因有', - sureStr: '我知道了'); + sureStr: '我知道了'.tr); }, )), Visibility( - visible: CommonDataManage().currentKeyInfo.isLockOwner == 1, + visible: CommonDataManage().currentKeyInfo.isLockOwner == 1 || + CommonDataManage().currentKeyInfo.keyRight == 1, child: PopupMenuButton( onSelected: _onMenuItemSelected, color: Colors.black, itemBuilder: (BuildContext context) { return >[ _buildCustomPopupMenuItem('读取记录'), - const PopupMenuDivider(), - _buildCustomPopupMenuItem('清空记录'), + if (CommonDataManage().currentKeyInfo.isLockOwner == 1) + const PopupMenuDivider(), + if (CommonDataManage().currentKeyInfo.isLockOwner == 1) + _buildCustomPopupMenuItem('清空记录'), const PopupMenuDivider(), _buildCustomPopupMenuItem('导出记录'), ]; @@ -131,7 +136,19 @@ class _DoorLockLogPageState extends State with RouteAware { } break; case '导出记录': - {} + { + showDialog( + context: context, + builder: (BuildContext context) { + return ExportRecordDialog( + onExport: (String filePath) { + Get.toNamed(Routers.exportSuccessPage, + arguments: {'filePath': filePath}); + }, + ); + }, + ); + } break; } } @@ -264,7 +281,7 @@ class _DoorLockLogPageState extends State with RouteAware { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - '$formattedTime ${timelineData.username!.isNotEmpty ? "${timelineData.username}用" : ""}${timelineData.recordTypeName}', + '$formattedTime ${timelineData.username!.isNotEmpty ? "${timelineData.username}操作" : ""}${timelineData.recordTypeName}', textAlign: TextAlign.left, style: TextStyle( color: Colors.black, diff --git a/lib/main/lockDetail/doorLockLog/doorLockLog_state.dart b/lib/main/lockDetail/doorLockLog/doorLockLog_state.dart index 5cfeda59..9baea876 100755 --- a/lib/main/lockDetail/doorLockLog/doorLockLog_state.dart +++ b/lib/main/lockDetail/doorLockLog/doorLockLog_state.dart @@ -7,59 +7,63 @@ import 'package:star_lock/tools/menuItem/dropDownItem.dart'; import '../../lockMian/entity/lockListInfo_entity.dart'; class DoorLockLogState { - final lockLogEntity = DoorLockLogEntity().obs; - final keyInfos = LockListInfoItemEntity().obs; - final lockLogItemList = [].obs; - final calendarControllerToday = AdvancedCalendarController.today(); - final calendarControllerCustom = AdvancedCalendarController.today(); - final events = [ + // 当前选择的日期 + + DoorLockLogState() { + keyInfos.value = Get.arguments['keyInfo']; + } + final Rx lockLogEntity = DoorLockLogEntity().obs; + final Rx keyInfos = LockListInfoItemEntity().obs; + final RxList lockLogItemList = + [].obs; + final AdvancedCalendarController calendarControllerToday = + AdvancedCalendarController.today(); + final AdvancedCalendarController calendarControllerCustom = + AdvancedCalendarController.today(); + final List events = [ DateTime.now(), DateTime(2024, 10, 10), ]; - final startDate = + final RxInt startDate = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day) .millisecondsSinceEpoch .obs; - final endDate = (DateTime( - DateTime.now().year, DateTime.now().month, DateTime.now().day + 1) - .subtract(const Duration(milliseconds: 1))) + final RxInt endDate = DateTime( + DateTime.now().year, DateTime.now().month, DateTime.now().day + 1) + .subtract(const Duration(milliseconds: 1)) .millisecondsSinceEpoch .obs; - var dropdownTitle = '全部事件'.tr.obs; - var dropdownValue = XSConstantMacro.lockEventTypeAll.obs; + RxString dropdownTitle = '全部事件'.tr.obs; + RxInt dropdownValue = XSConstantMacro.lockEventTypeAll.obs; - List getDropDownItemList = [ + List getDropDownItemList = [ DropDownItem( - itemTitle: "全部事件".tr, + itemTitle: '全部事件'.tr, itemValue: XSConstantMacro.lockEventTypeAll.toString(), isCheked: false), DropDownItem( - itemTitle: "开锁事件".tr, + itemTitle: '开锁事件'.tr, itemValue: XSConstantMacro.lockEventTypeOpenDoor.toString(), isCheked: false), DropDownItem( - itemTitle: "异常事件".tr, + itemTitle: '异常事件'.tr, itemValue: XSConstantMacro.lockEventTypeAbnormal.toString(), isCheked: false), DropDownItem( - itemTitle: "门铃事件".tr, + itemTitle: '门铃事件'.tr, itemValue: XSConstantMacro.lockEventTypeDoorbell.toString(), isCheked: false), DropDownItem( - itemTitle: "视频事件".tr, + itemTitle: '视频事件'.tr, itemValue: XSConstantMacro.lockEventTypeVideo.toString(), isCheked: false), ]; - var ifCurrentScreen = true.obs; // 是否是当前界面,用于判断是否需要针对当前界面进行展示 - var operateDate = 0; // 按日期查询消息记录的时间戳 - var ifHaveNext = false; // 页码 - var logCountPage = 10; // 蓝牙记录一页多少个 - var currentSelectDate = DateTime.now().obs; // 当前选择的日期 - - DoorLockLogState() { - keyInfos.value = Get.arguments["keyInfo"]; - } + RxBool ifCurrentScreen = true.obs; // 是否是当前界面,用于判断是否需要针对当前界面进行展示 + int operateDate = 0; // 按日期查询消息记录的时间戳 + bool ifHaveNext = false; // 页码 + int logCountPage = 10; // 蓝牙记录一页多少个 + Rx currentSelectDate = DateTime.now().obs; } diff --git a/lib/main/lockDetail/doorLockLog/exportRecordDialog/exportRecordDialog_logic.dart b/lib/main/lockDetail/doorLockLog/exportRecordDialog/exportRecordDialog_logic.dart new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/lib/main/lockDetail/doorLockLog/exportRecordDialog/exportRecordDialog_logic.dart @@ -0,0 +1 @@ + diff --git a/lib/main/lockDetail/doorLockLog/exportRecordDialog/exportRecordDialog_page.dart b/lib/main/lockDetail/doorLockLog/exportRecordDialog/exportRecordDialog_page.dart new file mode 100644 index 00000000..8b7a4f6a --- /dev/null +++ b/lib/main/lockDetail/doorLockLog/exportRecordDialog/exportRecordDialog_page.dart @@ -0,0 +1,235 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:http/http.dart' as http; +import 'package:intl/intl.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:star_lock/appRouters.dart'; +import 'package:star_lock/app_settings/app_colors.dart'; +import 'package:star_lock/main/lockDetail/doorLockLog/exportRecordDialog/exportRecord_entity.dart'; +import 'package:star_lock/network/api_repository.dart'; +import 'package:star_lock/tools/baseGetXController.dart'; +import 'package:star_lock/tools/commonDataManage.dart'; +import 'package:star_lock/tools/pickers/pickers.dart'; +import 'package:star_lock/tools/pickers/time_picker/model/date_mode.dart'; +import 'package:star_lock/tools/pickers/time_picker/model/pduration.dart'; +import 'package:star_lock/tools/showTipView.dart'; +import 'package:star_lock/tools/submitBtn.dart'; + +class ExportRecordDialog extends StatelessWidget { + const ExportRecordDialog({required this.onExport, Key? key}) + : super(key: key); + final Function(String) onExport; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () { + Navigator.of(context).pop(); + }, + child: Container( + color: Colors.transparent, + child: GestureDetector( + onTap: () {}, + child: Center( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 60.w), + child: _DerivedRecordWidget(onExport: onExport), + ), + ), + ), + ), + ); + } +} + +class _DerivedRecordWidget extends StatefulWidget { + const _DerivedRecordWidget({required this.onExport, Key? key}) + : super(key: key); + final Function(String) onExport; + + @override + __DerivedRecordWidgetState createState() => __DerivedRecordWidgetState(); +} + +class __DerivedRecordWidgetState extends State<_DerivedRecordWidget> { + DateTime? startDate = DateTime.now(); + DateTime? endDate = DateTime.now(); + + @override + Widget build(BuildContext context) { + return Center( + child: IntrinsicHeight( + child: Container( + padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 20.h), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16.w), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + '导出记录'.tr, + style: TextStyle(fontSize: 22.sp), + ), + SizedBox(height: 16.h), + Text( + '选择时间段'.tr, + style: TextStyle(fontSize: 24.sp, fontWeight: FontWeight.bold), + ), + SizedBox(height: 26.h), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _buildDateContainer( + DateFormat('yyyy-MM-dd').format(startDate!), + _showStartDatePicker), + Text( + '--', + style: TextStyle(fontSize: 24.sp), + ), + _buildDateContainer(DateFormat('yyyy-MM-dd').format(endDate!), + _showEndDatePicker), + ], + ), + SizedBox(height: 26.h), + Divider( + height: 1.sp, + color: AppColors.greyLineColor, + ), + SizedBox(height: 26.h), + SubmitBtn( + btnName: '导出'.tr, + onClick: _handleExport, + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + Get.toNamed(Routers.batchExportLogPage); + }, + child: Text( + '批量导出'.tr, + style: TextStyle( + fontSize: 22.sp, + color: AppColors.mainColor, + ), + ), + ), + ], + ), + ], + ), + ), + ), + ); + } + + Widget _buildDateContainer(String date, VoidCallback onPressed) { + return GestureDetector( + onTap: onPressed, + child: Container( + width: 200.w, + height: 60.h, + decoration: BoxDecoration( + border: Border.all( + color: AppColors.greyLineColor, + width: 1.w, + ), + borderRadius: BorderRadius.circular(8.w), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + date, + style: TextStyle(fontSize: 24.sp), + ), + Icon( + Icons.arrow_drop_down, + size: 30.w, + ), + ], + ), + ), + ); + } + + void _showStartDatePicker() { + final PDuration selectDate = PDuration.parse(startDate ?? DateTime.now()); + Pickers.showDatePicker( + context, + selectDate: selectDate, + mode: DateMode.YMD, + onConfirm: (PDuration p) { + setState(() { + startDate = DateTime(p.year!, p.month!, p.day!); + }); + }, + ); + } + + void _showEndDatePicker() { + final PDuration selectDate = PDuration.parse(endDate ?? DateTime.now()); + Pickers.showDatePicker( + context, + selectDate: selectDate, + mode: DateMode.YMD, + onConfirm: (PDuration p) { + setState(() { + endDate = DateTime(p.year!, p.month!, p.day!); + }); + }, + ); + } + + void _handleExport() { + if (startDate == null || endDate == null) { + ShowTipView().showSureAlertDialog( + '请选择开始和结束日期'.tr, + tipTitle: '提示'.tr, + sureStr: '我知道了'.tr, + ); + return; + } + + exportLockRecordsRequest(); + } + + //操作记录-导出锁记录 + Future exportLockRecordsRequest() async { + final ExportRecordEntity entity = await ApiRepository.to.exportLockRecords( + lockId: CommonDataManage().currentKeyInfo.lockId ?? 0, + startDate: startDate!.millisecondsSinceEpoch, + endDate: endDate!.millisecondsSinceEpoch, + ); + + if (entity.errorCode!.codeIsSuccessful) { + final String url = entity.data!.fileUrl!; + //下载文件地址 + final String filePath = await downloadAndSaveFile(url); + widget.onExport(filePath); + // return url; + } else { + throw 'Export failed with error code ${entity.errorCode}'; + } + } + + // 下载并保存文件 + Future downloadAndSaveFile(String url) async { + final http.Response response = await http.get(Uri.parse(url)); + if (response.statusCode == 200) { + final Directory directory = await getApplicationDocumentsDirectory(); + final File file = File('${directory.path}/exported_file.xlsx'); + await file.writeAsBytes(response.bodyBytes); + return file.path; + } else { + throw 'Failed to download file'; + } + } +} diff --git a/lib/main/lockDetail/doorLockLog/exportRecordDialog/exportRecordDialog_state.dart b/lib/main/lockDetail/doorLockLog/exportRecordDialog/exportRecordDialog_state.dart new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/lib/main/lockDetail/doorLockLog/exportRecordDialog/exportRecordDialog_state.dart @@ -0,0 +1 @@ + diff --git a/lib/main/lockDetail/doorLockLog/exportRecordDialog/exportRecord_entity.dart b/lib/main/lockDetail/doorLockLog/exportRecordDialog/exportRecord_entity.dart new file mode 100644 index 00000000..60fa2d09 --- /dev/null +++ b/lib/main/lockDetail/doorLockLog/exportRecordDialog/exportRecord_entity.dart @@ -0,0 +1,40 @@ +class ExportRecordEntity { + ExportRecordEntity( + {this.errorCode, this.description, this.errorMsg, this.data}); + ExportRecordEntity.fromJson(Map json) { + errorCode = json['errorCode']; + description = json['description']; + errorMsg = json['errorMsg']; + data = json['data'] != null ? Data.fromJson(json['data']) : null; + } + int? errorCode; + String? description; + String? errorMsg; + Data? data; + + Map toJson() { + final Map data = {}; + data['errorCode'] = errorCode; + data['description'] = description; + data['errorMsg'] = errorMsg; + if (this.data != null) { + data['data'] = this.data!.toJson(); + } + return data; + } +} + +class Data { + Data({this.fileUrl}); + + Data.fromJson(Map json) { + fileUrl = json['fileUrl']; + } + String? fileUrl; + + Map toJson() { + final Map data = {}; + data['fileUrl'] = fileUrl; + return data; + } +} diff --git a/lib/main/lockDetail/doorLockLog/exportSuccess/exportSuccess_logic.dart b/lib/main/lockDetail/doorLockLog/exportSuccess/exportSuccess_logic.dart new file mode 100644 index 00000000..a341afc9 --- /dev/null +++ b/lib/main/lockDetail/doorLockLog/exportSuccess/exportSuccess_logic.dart @@ -0,0 +1,6 @@ +import 'package:star_lock/main/lockDetail/doorLockLog/exportSuccess/exportSuccess_state.dart'; +import 'package:star_lock/tools/baseGetXController.dart'; + +class ExportSuccessLogic extends BaseGetXController { + ExportSuccessState state = ExportSuccessState(); +} diff --git a/lib/main/lockDetail/doorLockLog/exportSuccess/exportSuccess_page.dart b/lib/main/lockDetail/doorLockLog/exportSuccess/exportSuccess_page.dart new file mode 100644 index 00000000..c04aa30d --- /dev/null +++ b/lib/main/lockDetail/doorLockLog/exportSuccess/exportSuccess_page.dart @@ -0,0 +1,243 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:star_lock/appRouters.dart'; +import 'package:star_lock/app_settings/app_colors.dart'; +import 'package:star_lock/main/lockDetail/doorLockLog/exportSuccess/exportSuccess_logic.dart'; +import 'package:star_lock/main/lockDetail/doorLockLog/exportSuccess/exportSuccess_state.dart'; +import 'package:star_lock/tools/NativeInteractionTool.dart'; +import 'package:star_lock/tools/commonDataManage.dart'; +import 'package:star_lock/tools/submitBtn.dart'; +import 'package:star_lock/tools/titleAppBar.dart'; +import 'package:url_launcher/url_launcher.dart'; +import 'package:open_file/open_file.dart'; + +class ExportSuccessPage extends StatefulWidget { + const ExportSuccessPage({Key? key}) : super(key: key); + + @override + State createState() => _ExportSuccessPageState(); +} + +class _ExportSuccessPageState extends State with RouteAware { + final ExportSuccessLogic logic = Get.put(ExportSuccessLogic()); + final ExportSuccessState state = Get.find().state; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColors.mainBackgroundColor, + appBar: TitleAppBar( + barTitle: '导出'.tr, + haveBack: true, + backgroundColor: AppColors.mainColor, + ), + body: sendElectronicKeySucceed(), + ); + } + + // 导出成功 + + Widget sendElectronicKeySucceed() { + return Column( + children: [ + Container( + height: 250.h, + width: 1.sw, + color: Colors.white, + child: Column( + children: [ + SizedBox( + height: 30.h, + ), + Image.asset( + 'images/icon_send_success.png', + width: 100.w, + height: 100.w, + ), + SizedBox( + height: 20.h, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + '导出成功'.tr, + style: TextStyle( + fontSize: 26.sp, + color: Colors.black, + fontWeight: FontWeight.w500), + ), + ], + ), + ], + ), + ), + SizedBox( + height: 60.h, + ), + SubmitBtn( + btnName: '立即查看'.tr, + onClick: () { + OpenFile.open(state.getFilePath.value); + NativeInteractionTool() + .loadNativeFileShare(shareText: state.getFilePath.value); + + // openFile(state.getFilePath.value); + // previewFile(); + // Get.toNamed(Routers.viewExportRecordPage, + // arguments: { + // 'filePath': state.getFilePath.value, + // }); + // Get.toNamed(Routers.webviewShowPage, arguments: { + // 'url': state.getFilePath.value, + // 'title': '查看操作记录'.tr + // }); + }), + SizedBox( + height: 20.h, + ), + OutLineBtn( + btnName: '分享'.tr, + onClick: () { + _openModalBottomSheet(); + }, + ), + ], + ); + } + + // Future openFile(String filePath) async { + // final File file = File(filePath); + // if (await file.exists()) { + // await launchUrl(Uri.parse('file://$filePath')); + // } else { + // throw 'File not found'; + // } + // } + + Future previewFile() async { + // 获取本地文件路径 + final Directory appDocDir = await getApplicationDocumentsDirectory(); + final String appDocPath = appDocDir.path; + final String filePath = '$appDocPath/exported_file.xlsx'; + + // 检查文件是否存在 + final File file = File(filePath); + if (await file.exists()) { + // 使用url_launcher打开文件 + final bool launched = await launchUrl(Uri.parse(filePath)); + if (!launched) { + throw 'Could not launch $filePath'; + } + } else { + print('File does not exist'); + } + } + + Future _openModalBottomSheet() async { + showModalBottomSheet( + context: context, + shape: RoundedRectangleBorder( + borderRadius: BorderRadiusDirectional.circular(10)), + constraints: BoxConstraints(maxHeight: 270.h), + builder: (BuildContext context) { + return Column( + children: [ + SizedBox( + width: ScreenUtil().screenWidth, + height: 160.h, + child: ListView( + scrollDirection: Axis.horizontal, //横向滚动 + children: initBottomSheetList()), + ), + Container( + height: 8.h, + color: AppColors.greyBackgroundColor, + ), + TextButton( + style: ButtonStyle( + overlayColor: + MaterialStateProperty.all(Colors.white)), + child: Text( + '取消'.tr, + style: TextStyle( + color: Colors.black, fontSize: ScreenUtil().setSp(24)), + ), + onPressed: () { + Navigator.pop(context); + }, + ) + ], + ); + }); + } + + List initBottomSheetList() { + final List widgetList = []; + + widgetList.add(buildCenter3('images/icon_wechat.png', '微信好友'.tr, 0)); + widgetList.add(buildCenter3('images/icon_message.png', '短信'.tr, 1)); + widgetList.add(buildCenter3('images/icon_email.png', '邮件'.tr, 2)); + widgetList.add(buildCenter3('images/icon_more.png', '更多'.tr, 3)); + + return widgetList; + } + + GestureDetector buildCenter3( + String imageName, String titleStr, int itemIndex) { + return GestureDetector( + child: Container( + width: 120.w, + // height: 64.h, + margin: + EdgeInsets.only(top: 20.w, bottom: 20.w, left: 10.w, right: 10.w), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + imageName, + width: 50.w, + height: 50.h, + ), + SizedBox( + height: 16.w, + ), + Text( + titleStr, + style: TextStyle( + fontSize: ScreenUtil().setSp(20), color: Colors.black), + ), + ], + ), + ), + onTap: () => jumpSmartDeviceRoute(itemIndex), + ); + } + + Future jumpSmartDeviceRoute(int itemIndex) async { + Get.back(); + // final String pwdShareStr = logic.getShareContentStr(); + switch (itemIndex) { + case 0: //微信好友 + // NativeInteractionTool().loadNativeShare(shareText: pwdShareStr); + break; + case 1: //短信 + case 2: //邮件 + Get.toNamed(Routers.sendEmailNotificationPage, + arguments: { + 'receiver': '', + 'channelType': itemIndex == 1 ? 1 : 2, + 'keyId': CommonDataManage().currentKeyInfo.keyId, + }); + break; + case 3: //更多 + // NativeInteractionTool().loadNativeShare(shareText: pwdShareStr); + break; + default: + } + } +} diff --git a/lib/main/lockDetail/doorLockLog/exportSuccess/exportSuccess_state.dart b/lib/main/lockDetail/doorLockLog/exportSuccess/exportSuccess_state.dart new file mode 100644 index 00000000..9cf091d0 --- /dev/null +++ b/lib/main/lockDetail/doorLockLog/exportSuccess/exportSuccess_state.dart @@ -0,0 +1,10 @@ +import 'package:get/get.dart'; + +class ExportSuccessState { + ExportSuccessState() { + final Map map = Get.arguments; + getFilePath.value = map['filePath']; + } + + RxString getFilePath = ''.obs; +} diff --git a/lib/main/lockDetail/doorLockLog/viewExportRecord/viewExportRecord_logic.dart b/lib/main/lockDetail/doorLockLog/viewExportRecord/viewExportRecord_logic.dart new file mode 100644 index 00000000..105d5263 --- /dev/null +++ b/lib/main/lockDetail/doorLockLog/viewExportRecord/viewExportRecord_logic.dart @@ -0,0 +1,6 @@ +import 'package:star_lock/main/lockDetail/doorLockLog/viewExportRecord/viewExportRecord_state.dart'; +import 'package:star_lock/tools/baseGetXController.dart'; + +class ViewExportRecordLogic extends BaseGetXController { + ViewExportRecordState state = ViewExportRecordState(); +} diff --git a/lib/main/lockDetail/doorLockLog/viewExportRecord/viewExportRecord_page.dart b/lib/main/lockDetail/doorLockLog/viewExportRecord/viewExportRecord_page.dart new file mode 100644 index 00000000..05c3c524 --- /dev/null +++ b/lib/main/lockDetail/doorLockLog/viewExportRecord/viewExportRecord_page.dart @@ -0,0 +1,70 @@ +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:star_lock/app_settings/app_colors.dart'; +import 'package:star_lock/app_settings/app_settings.dart'; +import 'package:star_lock/main/lockDetail/doorLockLog/viewExportRecord/viewExportRecord_logic.dart'; +import 'package:star_lock/main/lockDetail/doorLockLog/viewExportRecord/viewExportRecord_state.dart'; +import 'package:star_lock/tools/titleAppBar.dart'; + +class ViewExportRecordPage extends StatefulWidget { + const ViewExportRecordPage({Key? key}) : super(key: key); + + @override + State createState() => _ViewExportRecordPageState(); +} + +class _ViewExportRecordPageState extends State + with RouteAware { + final ViewExportRecordLogic logic = Get.put(ViewExportRecordLogic()); + final ViewExportRecordState state = Get.find().state; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColors.mainBackgroundColor, + appBar: TitleAppBar( + barTitle: '查看导出记录'.tr, + haveBack: true, + backgroundColor: AppColors.mainColor, + ), + body: Center( + child: state.excelData.isEmpty + ? const CircularProgressIndicator() + : SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: DataTable( + columns: List.generate( + state.excelData[0].length, + (int index) => DataColumn( + label: Text('${state.excelData[0][index]}'), + ), + ), + rows: List.generate( + state.excelData.length - 1, + (int index) => DataRow( + cells: List.generate( + state.excelData[index + 1].length, + (int cellIndex) => DataCell( + Text('${state.excelData[index + 1][cellIndex]}'), + ), + ), + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/main/lockDetail/doorLockLog/viewExportRecord/viewExportRecord_state.dart b/lib/main/lockDetail/doorLockLog/viewExportRecord/viewExportRecord_state.dart new file mode 100644 index 00000000..edf502fb --- /dev/null +++ b/lib/main/lockDetail/doorLockLog/viewExportRecord/viewExportRecord_state.dart @@ -0,0 +1,11 @@ +import 'package:get/get.dart'; + +class ViewExportRecordState { + ViewExportRecordState() { + final Map map = Get.arguments; + getFilePath.value = map['filePath']; + } + + RxString getFilePath = ''.obs; + List> excelData = []; +} diff --git a/lib/main/lockDetail/lockDetail/lockDetail_page.dart b/lib/main/lockDetail/lockDetail/lockDetail_page.dart index 0d398056..a4f4ec1d 100755 --- a/lib/main/lockDetail/lockDetail/lockDetail_page.dart +++ b/lib/main/lockDetail/lockDetail/lockDetail_page.dart @@ -778,7 +778,7 @@ class _LockDetailPageState extends State ? AppColors.mainColor : AppColors.btnDisableColor), ), - if (add) SizedBox(width: 20.w) else SizedBox(width: 40.w), + if (add) SizedBox(width: 20.w) else SizedBox(width: 20.w), FlavorsImg( child: Image.asset('images/main/icon_lockDetail_needNetwork.png', width: 24.w, @@ -789,7 +789,7 @@ class _LockDetailPageState extends State ), SizedBox(width: 6.w), Text( - '手机需联网', + '手机需联网'.tr, style: TextStyle( fontSize: 20.sp, color: state.isOpenLockNeedOnline.value == 1 diff --git a/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart b/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart index d7fa2731..4ac123e7 100755 --- a/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart +++ b/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart @@ -646,7 +646,10 @@ class LockSetLogic extends BaseGetXController { recordType: recordType, records: records, isUnShowLoading: true); - if (entity.errorCode!.codeIsSuccessful) {} + if (entity.errorCode!.codeIsSuccessful) { + await getLockSettingInfoData(); + update(); + } } @override diff --git a/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart b/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart index de208c97..c15dfa29 100755 --- a/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart +++ b/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart @@ -28,7 +28,9 @@ class LockSetPage extends StatefulWidget { class _LockSetPageState extends State with RouteAware { final LockSetLogic logic = Get.put(LockSetLogic()); - final LockSetState state = Get.find().state; + final LockSetState state = Get + .find() + .state; Future getHttpData() async { logic.getLockSettingInfoData().then((LockSetInfoEntity value) { @@ -49,26 +51,29 @@ class _LockSetPageState extends State with RouteAware { @override Widget build(BuildContext context) { - return Scaffold( - backgroundColor: AppColors.mainBackgroundColor, - appBar: TitleAppBar( - barTitle: TranslationLoader.lanKeys!.set!.tr, - haveBack: true, - backgroundColor: AppColors.mainColor), - body: EasyRefreshTool( - onRefresh: () { - getHttpData(); - }, - child: Column( - children: [ - Expanded( - child: Obx(() => ListView( - children: getListWidget(), - )), - ), - ], - ), - )); + return GetBuilder(builder: (LockSetLogic logic) { + return Scaffold( + backgroundColor: AppColors.mainBackgroundColor, + appBar: TitleAppBar( + barTitle: TranslationLoader.lanKeys!.set!.tr, + haveBack: true, + backgroundColor: AppColors.mainColor), + body: EasyRefreshTool( + onRefresh: () { + getHttpData(); + }, + child: Column( + children: [ + Expanded( + child: Obx(() => + ListView( + children: getListWidget(), + )), + ), + ], + ), + )); + }); } // 根据权限显示不同的列表 @@ -93,45 +98,53 @@ class _LockSetPageState extends State with RouteAware { isHaveDirection: true, action: () { Get.toNamed(Routers.basicInformationPage, - arguments: {'lockSetInfoData': state.lockSetInfoData.value}); + arguments: { + 'lockSetInfoData': state.lockSetInfoData.value + }); }), SizedBox(height: 10.h), // 自动闭锁 - Obx(() => Visibility( - visible: state.lockFeature.value.autoLock == 1, - child: CommonItem( - leftTitel: TranslationLoader.lanKeys!.automaticBlocking!.tr, - rightTitle: (state.lockSettingInfo.value.autoLock ?? 0) > 0 - ? '${state.lockSetInfoData.value.lockSettingInfo!.autoLockSecond ?? 0}s' - : TranslationLoader.lanKeys!.closed!.tr, - isHaveLine: true, - isHaveDirection: true, - // isHaveRightWidget: true, - // rightWidget: rightText((state.lockSetInfoData.value.lockSetting!.autoLock ?? 0) > 0 - // ? "${state.lockSetInfoData.value.lockSetting!.autoLockSecond ?? 0}s" - // : TranslationLoader.lanKeys!.closed!.tr), - action: () { - Get.toNamed(Routers.automaticBlockingPage, arguments: { - 'lockSetInfoData': state.lockSetInfoData.value, - // 'lockBasicInfo': state.lockBasicInfo.value - }); - }))), + Obx(() => + Visibility( + visible: state.lockFeature.value.autoLock == 1, + child: CommonItem( + leftTitel: TranslationLoader.lanKeys!.automaticBlocking!.tr, + rightTitle: (state.lockSettingInfo.value.autoLock ?? 0) > 0 + ? '${state.lockSetInfoData.value.lockSettingInfo! + .autoLockSecond ?? 0}s' + : TranslationLoader.lanKeys!.closed!.tr, + isHaveLine: true, + isHaveDirection: true, + // isHaveRightWidget: true, + // rightWidget: rightText((state.lockSetInfoData.value.lockSetting!.autoLock ?? 0) > 0 + // ? "${state.lockSetInfoData.value.lockSetting!.autoLockSecond ?? 0}s" + // : TranslationLoader.lanKeys!.closed!.tr), + action: () { + Get.toNamed(Routers.automaticBlockingPage, + arguments: { + 'lockSetInfoData': state.lockSetInfoData.value, + // 'lockBasicInfo': state.lockBasicInfo.value + }); + }))), // 常开模式 - Obx(() => Visibility( - visible: state.lockFeature.value.passageMode == 1, - child: CommonItem( - leftTitel: TranslationLoader.lanKeys!.normallyOpenMode!.tr, - rightTitle: (state.lockSettingInfo.value.passageMode ?? 0) == 1 - ? TranslationLoader.lanKeys!.opened!.tr - : TranslationLoader.lanKeys!.closed!.tr, - isHaveLine: true, - isHaveDirection: true, - action: () { - Get.toNamed(Routers.normallyOpenModePage, arguments: { - 'lockSetInfoData': state.lockSetInfoData.value, - 'lockBasicInfo': state.lockBasicInfo.value - }); - }))), + Obx(() => + Visibility( + visible: state.lockFeature.value.passageMode == 1, + child: CommonItem( + leftTitel: TranslationLoader.lanKeys!.normallyOpenMode!.tr, + rightTitle: (state.lockSettingInfo.value.passageMode ?? 0) == + 1 + ? TranslationLoader.lanKeys!.opened!.tr + : TranslationLoader.lanKeys!.closed!.tr, + isHaveLine: true, + isHaveDirection: true, + action: () { + Get.toNamed(Routers.normallyOpenModePage, + arguments: { + 'lockSetInfoData': state.lockSetInfoData.value, + 'lockBasicInfo': state.lockBasicInfo.value + }); + }))), Visibility( visible: true, child: CommonItem( @@ -140,7 +153,8 @@ class _LockSetPageState extends State with RouteAware { isHaveLine: true, isHaveDirection: true, action: () { - Get.toNamed(Routers.lockTimePage, arguments: { + Get.toNamed( + Routers.lockTimePage, arguments: { 'lockSetInfoData': state.lockSetInfoData.value }); })), @@ -174,7 +188,9 @@ class _LockSetPageState extends State with RouteAware { isHaveDirection: true, action: () { Get.toNamed(Routers.basicInformationPage, - arguments: {'lockSetInfoData': state.lockSetInfoData.value}); + arguments: { + 'lockSetInfoData': state.lockSetInfoData.value + }); }), SizedBox(height: 10.h), //by DaisyWu 田总:移至锁详情配件区 @@ -226,24 +242,27 @@ class _LockSetPageState extends State with RouteAware { // })), // SizedBox(height: 10.h), // 自动闭锁 - Obx(() => Visibility( - visible: state.lockFeature.value.autoLock == 1, - child: CommonItem( - leftTitel: TranslationLoader.lanKeys!.automaticBlocking!.tr, - rightTitle: state.lockSettingInfo.value.autoLock! > 0 - ? '${state.lockSetInfoData.value.lockSettingInfo!.autoLockSecond}s' - : TranslationLoader.lanKeys!.closed!.tr, - isHaveLine: true, - isHaveDirection: true, - // isHaveRightWidget: true, - // rightWidget: rightText((state.lockSetInfoData.value.lockSetting!.autoLock ?? 0) > 0 - // ? "${state.lockSetInfoData.value.lockSetting!.autoLockSecond ?? 0}s" - // : TranslationLoader.lanKeys!.closed!.tr), - action: () { - Get.toNamed(Routers.automaticBlockingPage, arguments: { - 'lockSetInfoData': state.lockSetInfoData.value - }); - }))), + Obx(() => + Visibility( + visible: state.lockFeature.value.autoLock == 1, + child: CommonItem( + leftTitel: TranslationLoader.lanKeys!.automaticBlocking!.tr, + rightTitle: state.lockSettingInfo.value.autoLock! > 0 + ? '${state.lockSetInfoData.value.lockSettingInfo! + .autoLockSecond}s' + : TranslationLoader.lanKeys!.closed!.tr, + isHaveLine: true, + isHaveDirection: true, + // isHaveRightWidget: true, + // rightWidget: rightText((state.lockSetInfoData.value.lockSetting!.autoLock ?? 0) > 0 + // ? "${state.lockSetInfoData.value.lockSetting!.autoLockSecond ?? 0}s" + // : TranslationLoader.lanKeys!.closed!.tr), + action: () { + Get.toNamed(Routers.automaticBlockingPage, + arguments: { + 'lockSetInfoData': state.lockSetInfoData.value + }); + }))), // 锁声音 Obx(() { String titleStr = ''; @@ -276,73 +295,87 @@ class _LockSetPageState extends State with RouteAware { isHaveLine: true, isHaveDirection: true, action: () { - Get.toNamed(Routers.lockSoundSetPage, arguments: { - 'lockSetInfoData': state.lockSetInfoData.value - }); + Get.toNamed(Routers.lockSoundSetPage, + arguments: { + 'lockSetInfoData': state.lockSetInfoData.value + }); })); }), // 防撬报警 - Obx(() => Visibility( - visible: state.lockFeature.value.antiPrySwitch == 1, - child: CommonItem( - leftTitel: TranslationLoader.lanKeys!.burglarAlarm!.tr, - rightTitle: (state.lockSettingInfo.value.antiPrySwitch ?? 0) == 1 - ? TranslationLoader.lanKeys!.opened!.tr - : TranslationLoader.lanKeys!.closed!.tr, - isHaveLine: true, - isHaveDirection: true, - action: () { - Get.toNamed(Routers.burglarAlarmPage, arguments: { - 'lockSetInfoData': state.lockSetInfoData.value - }); - }))), + Obx(() => + Visibility( + visible: state.lockFeature.value.antiPrySwitch == 1, + child: CommonItem( + leftTitel: TranslationLoader.lanKeys!.burglarAlarm!.tr, + rightTitle: (state.lockSettingInfo.value.antiPrySwitch ?? + 0) == 1 + ? TranslationLoader.lanKeys!.opened!.tr + : TranslationLoader.lanKeys!.closed!.tr, + isHaveLine: true, + isHaveDirection: true, + action: () { + Get.toNamed(Routers.burglarAlarmPage, + arguments: { + 'lockSetInfoData': state.lockSetInfoData.value + }); + }))), SizedBox(height: 10.h), // 常开模式 - Obx(() => Visibility( - visible: state.lockFeature.value.passageMode == 1, - // visible: true, - child: CommonItem( - leftTitel: TranslationLoader.lanKeys!.normallyOpenMode!.tr, - rightTitle: (state.lockSettingInfo.value.passageMode ?? 0) == 1 - ? TranslationLoader.lanKeys!.opened!.tr - : TranslationLoader.lanKeys!.closed!.tr, - isHaveLine: true, - isHaveDirection: true, - action: () { - Get.toNamed(Routers.normallyOpenModePage, arguments: { - 'lockSetInfoData': state.lockSetInfoData.value - }); - }))), + Obx(() => + Visibility( + visible: state.lockFeature.value.passageMode == 1, + // visible: true, + child: CommonItem( + leftTitel: TranslationLoader.lanKeys!.normallyOpenMode!.tr, + rightTitle: (state.lockSettingInfo.value.passageMode ?? 0) == + 1 + ? TranslationLoader.lanKeys!.opened!.tr + : TranslationLoader.lanKeys!.closed!.tr, + isHaveLine: true, + isHaveDirection: true, + action: () { + Get.toNamed(Routers.normallyOpenModePage, + arguments: { + 'lockSetInfoData': state.lockSetInfoData.value + }); + }))), // 远程开锁 - Obx(() => Visibility( - visible: state.lockFeature.value.remoteUnlock == 1, - child: CommonItem( - leftTitel: TranslationLoader.lanKeys!.remoteUnlocking!.tr, - rightTitle: (state.lockSettingInfo.value.remoteUnlock ?? 0) == 1 - ? TranslationLoader.lanKeys!.opened!.tr - : TranslationLoader.lanKeys!.closed!.tr, - isHaveLine: true, - isHaveDirection: true, - action: () { - Get.toNamed(Routers.remoteUnlockingPage, arguments: { - 'lockSetInfoData': state.lockSetInfoData.value - }); - }))), + Obx(() => + Visibility( + visible: state.lockFeature.value.remoteUnlock == 1, + child: CommonItem( + leftTitel: TranslationLoader.lanKeys!.remoteUnlocking!.tr, + rightTitle: (state.lockSettingInfo.value.remoteUnlock ?? 0) == + 1 + ? TranslationLoader.lanKeys!.opened!.tr + : TranslationLoader.lanKeys!.closed!.tr, + isHaveLine: true, + isHaveDirection: true, + action: () { + Get.toNamed(Routers.remoteUnlockingPage, + arguments: { + 'lockSetInfoData': state.lockSetInfoData.value + }); + }))), // 重置键 - Obx(() => Visibility( - visible: state.lockBasicInfo.value.isLockOwner == 1 && state.lockFeature.value.resetSwitch == 1, - child: CommonItem( - leftTitel: TranslationLoader.lanKeys!.resetButton!.tr, - rightTitle: (state.lockSettingInfo.value.resetSwitch ?? 0) == 1 - ? TranslationLoader.lanKeys!.opened!.tr - : TranslationLoader.lanKeys!.closed!.tr, - isHaveLine: true, - isHaveDirection: true, - action: () { - Get.toNamed(Routers.resetButtonPage, arguments: { - 'lockSetInfoData': state.lockSetInfoData.value - }); - }))), + Obx(() => + Visibility( + visible: state.lockBasicInfo.value.isLockOwner == 1 && + state.lockFeature.value.resetSwitch == 1, + child: CommonItem( + leftTitel: TranslationLoader.lanKeys!.resetButton!.tr, + rightTitle: (state.lockSettingInfo.value.resetSwitch ?? 0) == + 1 + ? TranslationLoader.lanKeys!.opened!.tr + : TranslationLoader.lanKeys!.closed!.tr, + isHaveLine: true, + isHaveDirection: true, + action: () { + Get.toNamed(Routers.resetButtonPage, + arguments: { + 'lockSetInfoData': state.lockSetInfoData.value + }); + }))), SizedBox(height: 10.h), //---田总新增展示 // Obx(() => @@ -355,9 +388,10 @@ class _LockSetPageState extends State with RouteAware { isHaveLine: true, isHaveDirection: true, action: () { - Get.toNamed(Routers.faceUnlockPage, arguments: { - 'lockSetInfoData': state.lockSetInfoData.value - }); + Get.toNamed(Routers.faceUnlockPage, + arguments: { + 'lockSetInfoData': state.lockSetInfoData.value + }); })), // ), // 消息提醒 @@ -370,21 +404,25 @@ class _LockSetPageState extends State with RouteAware { isHaveDirection: true, action: () { Get.toNamed(Routers.msgNotificationPage, - arguments: {'lockId': state.lockSetInfoData.value.lockId}); + arguments: { + 'lockId': state.lockSetInfoData.value.lockId + }); })), //猫眼设置 - Obx(() => Visibility( - visible: state.lockFeature.value.isSupportCatEye == 1, - child: CommonItem( - leftTitel: TranslationLoader.lanKeys!.catEyeSet!.tr, - rightTitle: '', - isHaveLine: true, - isHaveDirection: true, - action: () { - Get.toNamed(Routers.catEyeSetPage, arguments: { - 'lockSetInfoData': state.lockSetInfoData.value - }); - }))), + Obx(() => + Visibility( + visible: state.lockFeature.value.isSupportCatEye == 1, + child: CommonItem( + leftTitel: TranslationLoader.lanKeys!.catEyeSet!.tr, + rightTitle: '', + isHaveLine: true, + isHaveDirection: true, + action: () { + Get.toNamed(Routers.catEyeSetPage, + arguments: { + 'lockSetInfoData': state.lockSetInfoData.value + }); + }))), // Obx(() => //自动亮屏已包括至面容开锁模块 // Visibility( @@ -420,9 +458,10 @@ class _LockSetPageState extends State with RouteAware { isHaveDirection: true, isHaveLine: true, action: () { - Get.toNamed(Routers.openDoorDirectionPage, arguments: { - 'lockSetInfoData': state.lockSetInfoData.value - }); + Get.toNamed(Routers.openDoorDirectionPage, + arguments: { + 'lockSetInfoData': state.lockSetInfoData.value + }); })), // 电机功率设置 Visibility( @@ -472,58 +511,66 @@ class _LockSetPageState extends State with RouteAware { // }), // 考勤 Obx( - () => Visibility( - visible: state.lockBasicInfo.value.isLockOwner == 1 && state.lockFeature.value.attendance == 1, - child: CommonItem( - leftTitel: TranslationLoader.lanKeys!.checkingIn!.tr, - rightTitle: '', - isHaveLine: true, - isHaveRightWidget: true, - rightWidget: _openCheckInSwitch())), + () => + Visibility( + visible: state.lockBasicInfo.value.isLockOwner == 1 && + state.lockFeature.value.attendance == 1, + child: CommonItem( + leftTitel: TranslationLoader.lanKeys!.checkingIn!.tr, + rightTitle: '', + isHaveLine: true, + isHaveRightWidget: true, + rightWidget: _openCheckInSwitch())), ), // 开锁提醒 Obx( - () => Visibility( - visible: state.lockBasicInfo.value.isLockOwner == 1 && state.lockFeature.value.unlockReminder == 1, - child: CommonItem( - leftTitel: TranslationLoader.lanKeys!.unlockReminder!.tr, - rightTitle: '', - isHaveLine: true, - isHaveRightWidget: true, - rightWidget: _lockRemindSwitch())), + () => + Visibility( + visible: state.lockBasicInfo.value.isLockOwner == 1 && + state.lockFeature.value.unlockReminder == 1, + child: CommonItem( + leftTitel: TranslationLoader.lanKeys!.unlockReminder!.tr, + rightTitle: '', + isHaveLine: true, + isHaveRightWidget: true, + rightWidget: _lockRemindSwitch())), ), // APP开锁时是否需联网 Obx( - () => Visibility( - visible: state.lockBasicInfo.value.isLockOwner == 1 && state.lockFeature.value.appUnlockOnline == 1, - child: CommonItem( - leftTitel: TranslationLoader - .lanKeys!.whetherInternetRequiredWhenUnlocking!.tr, - rightTitle: '', - isHaveLine: false, - isHaveRightWidget: true, - rightWidget: _openLockNeedOnlineSwitch()), - ), + () => + Visibility( + visible: state.lockBasicInfo.value.isLockOwner == 1 && + state.lockFeature.value.appUnlockOnline == 1, + child: CommonItem( + leftTitel: TranslationLoader + .lanKeys!.whetherInternetRequiredWhenUnlocking!.tr, + rightTitle: '', + isHaveLine: false, + isHaveRightWidget: true, + rightWidget: _openLockNeedOnlineSwitch()), + ), ), SizedBox(height: 10.h), // wifi配网 Obx( - () => Visibility( - visible: state.lockFeature.value.wifi == 1, - child: CommonItem( - leftTitel: + () => + Visibility( + visible: state.lockFeature.value.wifi == 1, + child: CommonItem( + leftTitel: TranslationLoader.lanKeys!.wifiDistributionNetwork!.tr, - rightTitle: '', - isHaveLine: true, - isHaveDirection: true, - action: () { - Get.toNamed(Routers.wifiListPage, arguments: { - 'lockSetInfoData': state.lockSetInfoData.value - }); - // Get.toNamed(Routers.configuringWifiPage, arguments: { - // 'lockSetInfoData': state.lockSetInfoData.value - // }); - })), + rightTitle: '', + isHaveLine: true, + isHaveDirection: true, + action: () { + Get.toNamed(Routers.wifiListPage, + arguments: { + 'lockSetInfoData': state.lockSetInfoData.value + }); + // Get.toNamed(Routers.configuringWifiPage, arguments: { + // 'lockSetInfoData': state.lockSetInfoData.value + // }); + })), ), // Obx(() => // 锁时间 @@ -535,7 +582,8 @@ class _LockSetPageState extends State with RouteAware { isHaveLine: true, isHaveDirection: true, action: () { - Get.toNamed(Routers.lockTimePage, arguments: { + Get.toNamed( + Routers.lockTimePage, arguments: { 'lockSetInfoData': state.lockSetInfoData.value }); })), @@ -628,13 +676,17 @@ class _LockSetPageState extends State with RouteAware { thumbColor: CupertinoColors.white, value: state.isAttendance.value == 1, onChanged: (bool value) { - logic.openCheckingInData((CheckingInInfoDataEntity checkingInInfoDataEntity) { + logic.openCheckingInData(( + CheckingInInfoDataEntity checkingInInfoDataEntity) { if (checkingInInfoDataEntity.data!.companyId == 0) { // logic.showCupertinoAlertDialog(context); - ShowTipView().showIosTipWithContentDialog('创建公司后,考勤功能才能使用'.tr, () { + ShowTipView().showIosTipWithContentDialog( + '创建公司后,考勤功能才能使用'.tr, () { // 删除锁 Get.toNamed(Routers.checkInCreatCompanyPage, - arguments: {'lockSetInfoData': state.lockSetInfoData.value}); + arguments: { + 'lockSetInfoData': state.lockSetInfoData.value + }); }); } else { logic.setLockSetGeneralSetting(); diff --git a/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_logic.dart b/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_logic.dart index bd1bfaa1..e7e632c1 100755 --- a/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_logic.dart +++ b/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_logic.dart @@ -27,7 +27,7 @@ class PasswordKeyPerpetualLogic extends BaseGetXController { //获取密码请求 Future getKeyboardPwdRequest() async { int startDate = DateTool().dateToTimestamp(state.beginTime.value, 1); - final int endDate = DateTool().dateToTimestamp(state.endTime.value, 1); + int endDate = DateTool().dateToTimestamp(state.endTime.value, 1); final int lockId = state.keyInfo.value.lockId!; String getKeyType = '0'; @@ -55,6 +55,10 @@ class PasswordKeyPerpetualLogic extends BaseGetXController { showToast('失效时间要大于当前时间'.tr); return; } + //endDate 设置当天凌晨 0 点 + final DateTime now = DateTime.now(); + startDate = + DateTime(now.year, now.month, now.day).millisecondsSinceEpoch; } // 芯连需要生效时间 @@ -221,6 +225,7 @@ class PasswordKeyPerpetualLogic extends BaseGetXController { // late DateTime getStartDateTime; // 监听设备返回的数据 late StreamSubscription _replySubscription; + void _initReplySubscription() { _replySubscription = EventBusManager().eventBus!.on().listen((Reply reply) async { @@ -436,7 +441,8 @@ class PasswordKeyPerpetualLogic extends BaseGetXController { case 3: //自定义 if (state.isPermanent.value == false) { - useDateStr = '类型:自定义-限时\n有效期:${state.customBeginTime.value} -- ${state.customEndTime.value}'; + useDateStr = + '类型:自定义-限时\n有效期:${state.customBeginTime.value} -- ${state.customEndTime.value}'; } else { useDateStr = '类型:自定义-永久'; } diff --git a/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart b/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart index 0bd4700a..e39af607 100755 --- a/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart +++ b/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart @@ -225,7 +225,7 @@ class _PasswordKeyPerpetualPageState extends State return Column( children: [ Visibility( - visible: CommonDataManage().currentKeyInfo.vendor == 'XHJ', + visible: CommonDataManage().currentKeyInfo.vendor != 'XHJ', child: CommonItem( leftTitel: TranslationLoader.lanKeys!.effectiveTime!.tr, rightTitle: state.beginTime.value, diff --git a/lib/main/lockMian/lockMain/lockMain_logic.dart b/lib/main/lockMian/lockMain/lockMain_logic.dart index d1ee9dc2..2fa7974c 100755 --- a/lib/main/lockMian/lockMain/lockMain_logic.dart +++ b/lib/main/lockMian/lockMain/lockMain_logic.dart @@ -36,7 +36,7 @@ class LockMainLogic extends BaseGetXController { isUnShowLoading: isUnShowLoading, ); if (entity.errorCode!.codeIsSuccessful) { - await loadMainDataLogic(entity.data!); + await loadMainDataLogic(entity.data!); } return entity; } @@ -149,7 +149,8 @@ class LockMainLogic extends BaseGetXController { final LockListInfoEntity entity = await ApiRepository.to.getStarLockInfo( keyId: keyId, ); - if (entity.errorCode!.codeIsSuccessful) { + if (entity.errorCode!.codeIsSuccessful && + (entity.data?.groupList ?? []).isNotEmpty) { state.lockListInfoGroupEntity.value.groupList ??= []; final GroupList list = entity.data!.groupList!.first; final LockListInfoItemEntity listItem = diff --git a/lib/network/api.dart b/lib/network/api.dart index 620cb749..da15ded9 100755 --- a/lib/network/api.dart +++ b/lib/network/api.dart @@ -257,4 +257,5 @@ abstract class Api { final String keyNoticeTemplateURL = '/key/getNoticeTemplate'; //获取电子钥匙通知模板 final String keyNoticeSubmitURL = '/key/noticeSubmit'; //发送短信、邮件通知 final String lockUpdateLockInfo = '/lock/updateLockInfo'; //更新锁固件版本 + final String exportLockRecordsURL = '/lockRecords/export'; //导出锁操作记录 } diff --git a/lib/network/api_provider.dart b/lib/network/api_provider.dart index ae1bd47d..12eff33d 100755 --- a/lib/network/api_provider.dart +++ b/lib/network/api_provider.dart @@ -397,8 +397,12 @@ class ApiProvider extends BaseProvider { })); // 获取锁信息列表 - Future getStarLockListInfo(int pageNo, int pageSize, - {bool isUnShowLoading = true, int? keyId,}) => + Future getStarLockListInfo( + int pageNo, + int pageSize, { + bool isUnShowLoading = true, + int? keyId, + }) => post( getStarLockInfoURL.toUrl, jsonEncode({ @@ -1460,9 +1464,7 @@ class ApiProvider extends BaseProvider { // 获取转移锁锁列表 Future getTransferLockListData(String searchStr) => - post(transferLockListURL.toUrl, jsonEncode({ - "searchStr":searchStr - })); + post(transferLockListURL.toUrl, jsonEncode({"searchStr": searchStr})); // 转移智能锁确认 Future transferLockConfirmInfoData( @@ -2288,6 +2290,34 @@ class ApiProvider extends BaseProvider { 'fwVersion': fwVersion, }), ); + + Future> exportLockRecords( + int lockId, + int startDate, + int endDate, + ) => + post( + exportLockRecordsURL.toUrl, + jsonEncode({ + 'lockId': lockId, + 'startDate': startDate, + 'endDate': endDate, + }), + ); + + Future> batchExportLockRecords( + List lockIds, + int startDate, + int endDate, + ) => + post( + exportLockRecordsURL.toUrl, + jsonEncode({ + 'lockIds': lockIds, + 'startDate': startDate, + 'endDate': endDate, + }), + ); } extension ExtensionString on String { diff --git a/lib/network/api_repository.dart b/lib/network/api_repository.dart index 966f74c9..3065627b 100755 --- a/lib/network/api_repository.dart +++ b/lib/network/api_repository.dart @@ -4,6 +4,7 @@ import 'package:star_lock/login/login/app_get_version.dart'; import 'package:star_lock/login/selectCountryRegion/common/countryRegionEntity.dart'; import 'package:star_lock/main/lockDetail/authorizedAdmin/authorizedAdmin/notice_template_entity.dart'; import 'package:star_lock/main/lockDetail/doorLockLog/doorLockLog_entity.dart'; +import 'package:star_lock/main/lockDetail/doorLockLog/exportRecordDialog/exportRecord_entity.dart'; import 'package:star_lock/main/lockDetail/electronicKey/electronicKeyList/entity/ElectronicKeyEntity.dart'; import 'package:star_lock/main/lockDetail/electronicKey/electronicKeyList/entity/ElectronicKeyListEntity.dart'; import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/massSendLockGroupList/lockUserList/lockUserList_entity.dart'; @@ -1657,7 +1658,8 @@ class ApiRepository { } // 获取转移锁锁列表 - Future getTransferLockListData({required String searchStr}) async { + Future getTransferLockListData( + {required String searchStr}) async { final res = await apiProvider.getTransferLockListData(searchStr); return TransferSmartLockEntity.fromJson(res.body); } @@ -2302,4 +2304,26 @@ class ApiRepository { await apiProvider.getLockUpdateLockInfo(lockId, fwVersion); return UpdateLockInfoEntity.fromJson(res.body); } + + //导出锁记录 + Future exportLockRecords({ + required int lockId, + required int startDate, + required int endDate, + }) async { + final Response res = + await apiProvider.exportLockRecords(lockId, startDate, endDate); + return ExportRecordEntity.fromJson(res.body); + } + + //批量导出锁记录 + Future batchExportLockRecords({ + required List lockIds, + required int startDate, + required int endDate, + }) async { + final Response res = + await apiProvider.batchExportLockRecords(lockIds, startDate, endDate); + return ExportRecordEntity.fromJson(res.body); + } } diff --git a/lib/tools/NativeInteractionTool.dart b/lib/tools/NativeInteractionTool.dart index 2b667a9d..e8b0f338 100755 --- a/lib/tools/NativeInteractionTool.dart +++ b/lib/tools/NativeInteractionTool.dart @@ -21,8 +21,14 @@ class NativeInteractionTool { ///加载原生分享 void loadNativeShare({required String shareText}) { final String urlToShare = '${F.apiPrefix}/apps'; - sendChannel.invokeMethod( - 'loadNativeShare', {'shareText': shareText,'urlToShare':urlToShare}); + sendChannel.invokeMethod('loadNativeShare', + {'shareText': shareText, 'urlToShare': urlToShare}); + } + + ///加载原生文件分享 + void loadNativeFileShare({required String shareText}) { + sendChannel.invokeMethod('loadNativeShare', + {'shareText': shareText, 'urlToShare': 'fileShare'}); } ///获取设备蓝牙状态 diff --git a/lib/tools/push/message_management.dart b/lib/tools/push/message_management.dart index df2f6c01..429dcc36 100644 --- a/lib/tools/push/message_management.dart +++ b/lib/tools/push/message_management.dart @@ -74,15 +74,13 @@ class MessageManagement { case MessageConstant.lockSetChange: final int keyId = data['keyId']; final int lockId = data['lockId']; - final Map extra = data['updateFieldList']; - if (extra['appUnlockOnline'] != null) { - final String appUnlockOnline = extra['appUnlockOnline']; - eventBus.fire( - LockSetChangeSetRefreshLockDetailWithType(1, appUnlockOnline)); - eventBus.fire(RefreshLockInfoDataEvent(keyId: keyId, lockId: lockId)); - } + // 暂时只用刷新 + // final Map extra = data['updateFieldList']; + // if (extra['appUnlockOnline'] != null) { + // final String appUnlockOnline = extra['appUnlockOnline']!.toString(); + // } + eventBus.fire(RefreshLockInfoDataEvent(keyId: keyId, lockId: lockId)); break; - default: throw Exception('无法识别eventNo 参数:$eventNo'); } diff --git a/pubspec.yaml b/pubspec.yaml index 1e12ca07..84c22c7e 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -73,8 +73,9 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # 1.0.62+2024061301:xhj 线上环境,对外发布,提交测试:处理华为拒审 # 1.0.63+2024061302:xhj 线上环境,提交测试:回归 bug # 1.0.65+2024061801:xhj 线上环境,提交测试:回归 bug +# 1.0.66+2024061802:xhj 线上环境,提交测试:回归 bug -version: 1.0.65+2024061801 +version: 1.0.66+2024061802 environment: sdk: '>=2.12.0 <3.0.0' @@ -216,6 +217,7 @@ dependencies: file_picker: ^5.3.1 # 错误日志监控 flutter_bugly_plugin: ^0.0.9 + open_file: ^3.3.2 dependency_overrides: #强制设置google_maps_flutter_ios 为 2.5.2