From 918deb65da264485d7b2cecabc1925a0d886c62f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AD=8F=E5=B0=91=E9=98=B3?= <786612630@qq.com> Date: Fri, 26 Jan 2024 14:10:57 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=85=A8=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E9=94=81=E8=BF=9E=E7=BB=AD=E5=BC=80=E9=94=815S?= =?UTF-8?q?=E6=8F=90=E9=86=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- star_lock/ios/Podfile.lock | 2 +- .../lockDetail/lockDetail_logic.dart | 43 ++++++++++++++++++- .../lockDetail/lockDetail_page.dart | 24 +++++------ .../lockDetail/lockDetail_state.dart | 3 ++ .../lockSet/lockSet/lockSetInfo_entity.dart | 14 +++++- .../lockSet/lockSet/lockSet_logic.dart | 8 ++-- .../lockSet/lockSet/lockSet_page.dart | 42 ++++++++++++------ star_lock/lib/mine/about/about_page.dart | 2 +- star_lock/lib/network/api.dart | 4 +- 9 files changed, 105 insertions(+), 37 deletions(-) diff --git a/star_lock/ios/Podfile.lock b/star_lock/ios/Podfile.lock index 2d0a0ce7..a072e55d 100644 --- a/star_lock/ios/Podfile.lock +++ b/star_lock/ios/Podfile.lock @@ -268,7 +268,7 @@ SPEC CHECKSUMS: ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 reactive_ble_mobile: 9ce6723d37ccf701dbffd202d487f23f5de03b4c shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 - sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a + sqflite: 50a33e1d72bd59ee092a519a35d107502757ebed SwiftProtobuf: 407a385e97fd206c4fbe880cc84123989167e0d1 Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812 diff --git a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart index b7d9343d..81f9f77e 100644 --- a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart +++ b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_logic.dart @@ -6,6 +6,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; +import '../../../appRouters.dart'; import '../../../app_settings/app_colors.dart'; import '../../../blue/blue_manage.dart'; import '../../../blue/io_protocol/io_addUser.dart'; @@ -132,6 +133,11 @@ class LockDetailLogic extends BaseGetXController { // 权限校验错误 print("${reply.commandType}校验错误"); + break; + case 0x16: + // 正在开锁中... + print("${reply.commandType}正在开锁中..."); + showToast("正在开锁中..."); break; default: //失败 @@ -331,7 +337,7 @@ class LockDetailLogic extends BaseGetXController { keyType: 0, startDate: DateTime.now().millisecondsSinceEpoch, expireDate: 0x11223344, - role: 0, + role: state.keyInfos.value.keyRight == 1 ? 1 : 0, password: "123456", needAuthor: 1, publicKey: publicKeyDataList, @@ -388,7 +394,7 @@ class LockDetailLogic extends BaseGetXController { keyType: 0, startDate: DateTime.now().millisecondsSinceEpoch, expireDate: 0x11223344, - role: 0, + role: state.keyInfos.value.keyRight == 1 ? 1 : 0, password: "123456", needAuthor: 1, publicKey: publicKeyDataList, @@ -592,6 +598,39 @@ class LockDetailLogic extends BaseGetXController { } } + // 0开锁 1长按闭锁 2密码 3卡 4指纹 5遥控 6人脸 7监控 8操作记录 9消息提醒 10设置 + clickItemBtnAction(int type){ + state.clickNextType = type; + if (state.lockUserNo == 0) { + // 电子钥匙lockUserNo为0 要先添加用户 + addUserConnectBlue(); + } else { + clickPushBtnAction(); + } + } + + clickPushBtnAction(){ + // 0开锁 1长按闭锁 2密码 3卡 4指纹 5遥控 6人脸 7监控 8操作记录 9消息提醒 10设置 + switch(state.clickNextType){ + case 0: + // 开锁 + startOpenLock(); + break; + case 1: + // 长按闭锁 + startUnLock(); + break; + case 2: + // 密码 + Get.toNamed(Routers.passwordKeyListPage, arguments: {"keyInfo": state.keyInfos.value}); + break; + case 3: + // 卡 + Get.toNamed(Routers.passwordKeyListPage, arguments: {"keyInfo": state.keyInfos.value}); + break; + } + } + // 获取手机联网token,根据锁设置里面获取的开锁时是否联网来判断是否调用这个接口 void getLockNetToken() async { LockNetTokenEntity entity = await ApiRepository.to.getLockNetToken(lockId: state.keyInfos.value.lockId.toString()); diff --git a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart index cba25cba..ae1a5472 100644 --- a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart +++ b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart @@ -314,13 +314,13 @@ class _LockDetailPageState extends State var showWidgetArr = [ // 操作记录 bottomItem('images/main/icon_main_operatingRecord.png', TranslationLoader.lanKeys!.operatingRecord!.tr, () { - Get.toNamed(Routers.lockOperatingRecordPage, arguments: {"keyInfo": widget.lockListInfoItemEntity}); + Get.toNamed(Routers.lockOperatingRecordPage, arguments: {"keyInfo": state.keyInfos.value}); }), // 设置 bottomItem('images/main/icon_main_set.png', TranslationLoader.lanKeys!.set!.tr, () { Get.toNamed(Routers.lockSetPage, arguments: { - "lockId": widget.lockListInfoItemEntity.lockId, + "lockId": state.keyInfos.value.lockId, "isOnlyOneData": widget.isOnlyOneData, }); }), @@ -344,14 +344,14 @@ class _LockDetailPageState extends State showWidgetArr.add(bottomItem('images/main/icon_main_electronicKey.png', TranslationLoader.lanKeys!.electronicKey!.tr, () { Get.toNamed(Routers.electronicKeyListPage, - arguments: {"keyInfo": widget.lockListInfoItemEntity}); + arguments: {"keyInfo": state.keyInfos.value}); })); // 密码 showWidgetArr.add(bottomItem('images/main/icon_main_password.png', TranslationLoader.lanKeys!.password!.tr, () { Get.toNamed(Routers.passwordKeyListPage, - arguments: {"keyInfo": widget.lockListInfoItemEntity}); + arguments: {"keyInfo": state.keyInfos.value}); })); // ic卡 @@ -361,7 +361,7 @@ class _LockDetailPageState extends State // logic.showEasyLoading(); // }); Get.toNamed(Routers.cardListPage, arguments: { - "lockId": widget.lockListInfoItemEntity.lockId, + "lockId": state.keyInfos.value.lockId, }); })); } @@ -371,7 +371,7 @@ class _LockDetailPageState extends State showWidgetArr.add(bottomItem('images/main/icon_main_fingerprint.png', TranslationLoader.lanKeys!.fingerprint!.tr, () { Get.toNamed(Routers.fingerprintListPage, arguments: { - "lockId": widget.lockListInfoItemEntity.lockId, + "lockId": state.keyInfos.value.lockId, }); })); } @@ -390,7 +390,7 @@ class _LockDetailPageState extends State bottomItem('images/main/icon_face.png', TranslationLoader.lanKeys!.humanFace!.tr, () { Get.toNamed(Routers.faceList, arguments: { - "lockId": widget.lockListInfoItemEntity.lockId, + "lockId": state.keyInfos.value.lockId, }); // Toast.show(msg: "功能暂未开放"); }), ); @@ -402,7 +402,7 @@ class _LockDetailPageState extends State bottomItem('images/main/icon_catEyes.png', TranslationLoader.lanKeys!.monitoring!.tr, () { Get.toNamed(Routers.realTimePicturePage, arguments: { - "lockName": widget.lockListInfoItemEntity.lockName, + "lockName": state.keyInfos.value.lockName, "isMonitoring": true }); }), @@ -414,15 +414,15 @@ class _LockDetailPageState extends State bottomItem('images/main/icon_main_authorizedAdmin.png', TranslationLoader.lanKeys!.authorizedAdmin!.tr, () { Get.toNamed(Routers.authorizedAdminListPage, - arguments: {"keyInfo": widget.lockListInfoItemEntity}); + arguments: {"keyInfo": state.keyInfos.value}); }), // 操作记录 bottomItem('images/main/icon_main_operatingRecord.png', TranslationLoader.lanKeys!.operatingRecord!.tr, () { // Get.toNamed(Routers.lockOperatingRecordPage, - // arguments: {"keyInfo": widget.lockListInfoItemEntity}); + // arguments: {"keyInfo": state.keyInfos.value}); Get.toNamed(Routers.doorLockLogPage, - arguments: {"keyInfo": widget.lockListInfoItemEntity}); + arguments: {"keyInfo": state.keyInfos.value}); }), // 视频日志 bottomItem('images/main/icon_lockDetail_videoLog.png', @@ -441,7 +441,7 @@ class _LockDetailPageState extends State () { // BlueManage().stopScan(); Get.toNamed(Routers.lockSetPage, arguments: { - "lockId": widget.lockListInfoItemEntity.lockId, + "lockId": state.keyInfos.value.lockId, "isOnlyOneData": widget.isOnlyOneData, }); }), diff --git a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_state.dart b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_state.dart index 4acdbaf2..7438c7b2 100644 --- a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_state.dart +++ b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_state.dart @@ -35,6 +35,9 @@ class LockDetailState { var iSOpenLock = true.obs; // 是开锁还是关锁 Timer? closedUnlockSuccessfulTimer; + // 0开锁 1长按闭锁 2密码 3卡 4指纹 5遥控 6人脸 7监控 8操作记录 9消息提醒 10设置 + var clickNextType = 0; + //过渡动画控制器 late AnimationController animationController; // var lockState = 0.obs;// 0未连接普通状态 1连接开锁中(展示动画) 2已连接开锁成功 3检测可用性 4连接失败 5连接失败重连中 diff --git a/star_lock/lib/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart b/star_lock/lib/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart index 059a7601..2e55d9b9 100644 --- a/star_lock/lib/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart +++ b/star_lock/lib/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart @@ -141,6 +141,9 @@ class LockFeature { int? appUnlockOnline; int? bluetoothBroadcast; int? attendance; + int? motorTorsion; + int? stayWarn; + int? abnormalWarn; LockFeature( {this.password, @@ -191,7 +194,10 @@ class LockFeature { this.hotelLockCardSystem, this.appUnlockOnline, this.bluetoothBroadcast, - this.attendance}); + this.attendance, + this.motorTorsion, + this.stayWarn, + this.abnormalWarn,}); LockFeature.fromJson(Map json) { password = json['password']; @@ -243,6 +249,9 @@ class LockFeature { appUnlockOnline = json['appUnlockOnline']; bluetoothBroadcast = json['bluetoothBroadcast']; attendance = json['attendance']; + motorTorsion = json['motorTorsion']; + stayWarn = json['stayWarn']; + abnormalWarn = json['abnormalWarn']; } Map toJson() { @@ -296,6 +305,9 @@ class LockFeature { data['appUnlockOnline'] = appUnlockOnline; data['bluetoothBroadcast'] = bluetoothBroadcast; data['attendance'] = attendance; + data['motorTorsion'] = motorTorsion; + data['stayWarn'] = stayWarn; + data['abnormalWarn'] = abnormalWarn; return data; } } diff --git a/star_lock/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart b/star_lock/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart index da55086b..915c18f9 100644 --- a/star_lock/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart +++ b/star_lock/lib/main/lockDetail/lockSet/lockSet/lockSet_logic.dart @@ -21,6 +21,7 @@ import '../../../../tools/showTFView.dart'; import '../../../../tools/storage.dart'; import '../../../../translations/trans_lib.dart'; import 'checkingInInfoData_entity.dart'; +import 'lockSetInfo_entity.dart'; import 'lockSet_state.dart'; typedef BlockSetStateCallback = void Function(); @@ -421,8 +422,8 @@ class LockSetLogic extends BaseGetXController { } // 获取锁设置信息 - void getLockSettingInfoData() async { - var entity = await ApiRepository.to.getLockSettingInfoData( + Future getLockSettingInfoData() async { + LockSetInfoEntity entity = await ApiRepository.to.getLockSettingInfoData( lockId: state.lockId.toString(), ); if (entity.errorCode!.codeIsSuccessful) { @@ -441,6 +442,7 @@ class LockSetLogic extends BaseGetXController { // await _readSupportFunctionsNoParameters(56); // _readSupportFunctionsNoParameters(62); } + return entity; } // 当是锁拥有者的时候,删除锁 @@ -736,8 +738,6 @@ class LockSetLogic extends BaseGetXController { // TODO: implement onReady super.onReady(); - getLockSettingInfoData(); - _initReplySubscription(); _scanListDiscoveredDeviceSubscriptionAction(); } diff --git a/star_lock/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart b/star_lock/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart index ee06c7af..8c4bb3bb 100644 --- a/star_lock/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart +++ b/star_lock/lib/main/lockDetail/lockSet/lockSet/lockSet_page.dart @@ -7,12 +7,14 @@ import 'package:star_lock/blue/blue_manage.dart'; import '../../../../appRouters.dart'; import '../../../../app_settings/app_colors.dart'; +import '../../../../tools/EasyRefreshTool.dart'; import '../../../../tools/appRouteObserver.dart'; import '../../../../tools/commonItem.dart'; import '../../../../tools/submitBtn.dart'; import '../../../../tools/titleAppBar.dart'; import '../../../../translations/trans_lib.dart'; +import 'lockSetInfo_entity.dart'; import 'lockSet_logic.dart'; // final RouteObserver routeObserver = RouteObserver(); @@ -27,6 +29,12 @@ class _LockSetPageState extends State with RouteAware { final logic = Get.put(LockSetLogic()); final state = Get.find().state; + Future getHttpData() async { + logic.getLockSettingInfoData().then((LockSetInfoEntity value){ + setState(() {}); + }); + } + @override void initState() { // TODO: implement initState @@ -35,6 +43,8 @@ class _LockSetPageState extends State with RouteAware { logic.initLoadDataAction(() { setState(() {}); }); + + getHttpData(); } @override @@ -45,14 +55,19 @@ class _LockSetPageState extends State with RouteAware { barTitle: TranslationLoader.lanKeys!.set!.tr, haveBack: true, backgroundColor: AppColors.mainColor), - body: Column( - children: [ - Expanded( - child: Obx(() => ListView( - children: getListWidget(), - )), - ), - ], + body: EasyRefreshTool( + onRefresh: (){ + getHttpData(); + }, + child: Column( + children: [ + Expanded( + child: Obx(() => ListView( + children: getListWidget(), + )), + ), + ], + ), )); } @@ -201,7 +216,7 @@ class _LockSetPageState extends State with RouteAware { }))), // 开门器 Visibility( - visible: true, + visible: state.lockFeature.value.doorStatus == 1 ? true : false, child: CommonItem( leftTitel: TranslationLoader.lanKeys!.doorOpener!.tr, rightTitle: "", @@ -285,8 +300,7 @@ class _LockSetPageState extends State with RouteAware { SizedBox(height: 10.h), // 常开模式 Obx(() => Visibility( - // visible: state.lockFeature.value.passageMode == 1 ? true : false, - visible:true, + visible: state.lockFeature.value.passageMode == 1 ? true : false, child: CommonItem( leftTitel: TranslationLoader.lanKeys!.normallyOpenMode!.tr, rightTitle: (state.lockSettingInfo.value.passageMode ?? 0) == 1 @@ -334,7 +348,7 @@ class _LockSetPageState extends State with RouteAware { // Obx(() => // 面容开锁 Visibility( - visible: true, + visible: state.lockFeature.value.d3Face == 1 ? true : false, child: CommonItem( leftTitel: TranslationLoader.lanKeys!.faceUnlocks!.tr, rightTitle: "", @@ -394,7 +408,7 @@ class _LockSetPageState extends State with RouteAware { // Obx(() => // 开门方向设置 Visibility( - visible: true, + visible: state.lockFeature.value.openDirection == 1 ? true : false, child: CommonItem( leftTitel: TranslationLoader.lanKeys!.openingDirectionSet!.tr, rightTitle: "", @@ -408,7 +422,7 @@ class _LockSetPageState extends State with RouteAware { })), // 电机功率设置 Visibility( - visible: true, + visible: state.lockFeature.value.motorTorsion == 1 ? true : false, child: CommonItem( leftTitel: TranslationLoader.lanKeys!.motorPowerSetting!.tr, rightTitle: "", diff --git a/star_lock/lib/mine/about/about_page.dart b/star_lock/lib/mine/about/about_page.dart index 81abcdf3..82283c67 100644 --- a/star_lock/lib/mine/about/about_page.dart +++ b/star_lock/lib/mine/about/about_page.dart @@ -38,7 +38,7 @@ class _AboutPageState extends State { ), SizedBox(height: 20.h), Text( - "星锁 1.0.0.08(preRelease-20240123)", + "星锁 1.0.0.09(preRelease-20240126-1)", style: TextStyle(fontSize: 24.sp, color: AppColors.blackColor), ), SizedBox(height: 20.h), diff --git a/star_lock/lib/network/api.dart b/star_lock/lib/network/api.dart index 5f658d46..0f0096cc 100644 --- a/star_lock/lib/network/api.dart +++ b/star_lock/lib/network/api.dart @@ -1,6 +1,6 @@ abstract class Api { - static String baseAddress = "https://pre.lock.star-lock.cn"; //预发布环境 - // static String baseAddress = "https://dev.lock.star-lock.cn"; //联调环境 + // static String baseAddress = "https://pre.lock.star-lock.cn"; //预发布环境 + static String baseAddress = "https://dev.lock.star-lock.cn"; //联调环境 // static String baseAddress = "http://192.168.1.15:8022"; //谢总本地 // static String baseAddress = "https://ge.lock.star-lock.cn"; //葛工开发环境地址 From c3d55d225b0d354f2557969b11157d770d72b7c4 Mon Sep 17 00:00:00 2001 From: Daisy <> Date: Fri, 26 Jan 2024 14:28:02 +0800 Subject: [PATCH 2/3] =?UTF-8?q?1=EF=BC=8C=E6=96=B0=E5=A2=9E=E9=97=A8?= =?UTF-8?q?=E9=94=81=E6=97=A5=E5=BF=97=E6=97=A5=E5=8E=86=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E6=BA=90=E6=96=87=E4=BB=B6=202=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E9=97=A8=E9=94=81=E6=97=A5=E5=BF=97UI=E5=8F=82=E8=80=83?= =?UTF-8?q?=E7=B1=B3=E5=AE=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../doorLockLog/doorLockLog_logic.dart | 8 +- .../doorLockLog/doorLockLog_page.dart | 21 +- .../doorLockLog/doorLockLog_state.dart | 2 +- .../flutter_advanced_calendar.dart | 4 + .../advancedCalendar/src/controller.dart | 15 + .../tools/advancedCalendar/src/date_box.dart | 94 ++++ .../advancedCalendar/src/datetime_util.dart | 56 +++ .../tools/advancedCalendar/src/handlebar.dart | 39 ++ .../tools/advancedCalendar/src/header.dart | 63 +++ .../advancedCalendar/src/month_view.dart | 62 +++ .../advancedCalendar/src/month_view_bean.dart | 40 ++ .../tools/advancedCalendar/src/week_days.dart | 36 ++ .../tools/advancedCalendar/src/week_view.dart | 137 ++++++ .../tools/advancedCalendar/src/widget.dart | 420 ++++++++++++++++++ star_lock/pubspec.yaml | 2 +- 15 files changed, 986 insertions(+), 13 deletions(-) create mode 100644 star_lock/lib/tools/advancedCalendar/flutter_advanced_calendar.dart create mode 100644 star_lock/lib/tools/advancedCalendar/src/controller.dart create mode 100644 star_lock/lib/tools/advancedCalendar/src/date_box.dart create mode 100644 star_lock/lib/tools/advancedCalendar/src/datetime_util.dart create mode 100644 star_lock/lib/tools/advancedCalendar/src/handlebar.dart create mode 100644 star_lock/lib/tools/advancedCalendar/src/header.dart create mode 100644 star_lock/lib/tools/advancedCalendar/src/month_view.dart create mode 100644 star_lock/lib/tools/advancedCalendar/src/month_view_bean.dart create mode 100644 star_lock/lib/tools/advancedCalendar/src/week_days.dart create mode 100644 star_lock/lib/tools/advancedCalendar/src/week_view.dart create mode 100644 star_lock/lib/tools/advancedCalendar/src/widget.dart diff --git a/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_logic.dart b/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_logic.dart index ceb96444..12910890 100644 --- a/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_logic.dart +++ b/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_logic.dart @@ -271,9 +271,9 @@ class DoorLockLogLogic extends BaseGetXController { super.onClose(); // 获取是否是演示模式 演示模式不获取接口 - var isDemoMode = await Storage.getBool(ifIsDemoModeOrNot); - if (isDemoMode == false) { - _replySubscription.cancel(); - } + // var isDemoMode = await Storage.getBool(ifIsDemoModeOrNot); + // if (isDemoMode == false) { + // _replySubscription.cancel(); + // } } } diff --git a/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart b/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart index 3c166332..6d3ea284 100644 --- a/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart +++ b/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:flutter_advanced_calendar/flutter_advanced_calendar.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:star_lock/main/lockDetail/doorLockLog/doorLockLog_logic.dart'; +import 'package:star_lock/tools/advancedCalendar/src/widget.dart'; import 'package:timelines/timelines.dart'; import '../../../app_settings/app_colors.dart'; @@ -64,10 +64,17 @@ class _DoorLockLogPageState extends State { endIndent: 30.w, ), eventDropDownWidget(), - SizedBox( - height: 20.h, - ), - Expanded(child: timeLineView()), + Expanded(child: timeLineView()) + // Expanded( + // // 添加 Expanded 来让 ListView 占据剩余的空间 + // child: ListView.builder( + // itemBuilder: (context, index) { + // // 返回你想要在 ListView 中显示的小部件 + // return timeLineView(); + // }, + // itemCount: 5, // 替换成你的列表项数量 + // ), + // ), ], ), ); @@ -123,7 +130,7 @@ class _DoorLockLogPageState extends State { value: state.dropdownValue.value, icon: const Icon(Icons.arrow_drop_down), iconSize: 40, - // elevation: 12, + elevation: 12, style: TextStyle( fontSize: 26.sp, color: Colors.black, @@ -149,7 +156,7 @@ class _DoorLockLogPageState extends State { //时间轴组件 Widget timeLineView() { return Container( - margin: EdgeInsets.only(left: 20.w, right: 20.w, bottom: 20.h), + margin: EdgeInsets.only(left: 20.w, right: 20.w, bottom: 20.h, top: 20.h), //给contain设置一个10像素的圆角 decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16.w)), diff --git a/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_state.dart b/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_state.dart index c37bece3..c89b39ce 100644 --- a/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_state.dart +++ b/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_state.dart @@ -1,5 +1,5 @@ -import 'package:flutter_advanced_calendar/flutter_advanced_calendar.dart'; import 'package:get/get.dart'; +import 'package:star_lock/tools/advancedCalendar/src/controller.dart'; import '../../lockMian/entity/lockListInfo_entity.dart'; import '../electronicKey/electronicKeyDetail/keyOperationRecordEntity.dart'; diff --git a/star_lock/lib/tools/advancedCalendar/flutter_advanced_calendar.dart b/star_lock/lib/tools/advancedCalendar/flutter_advanced_calendar.dart new file mode 100644 index 00000000..d7dff31b --- /dev/null +++ b/star_lock/lib/tools/advancedCalendar/flutter_advanced_calendar.dart @@ -0,0 +1,4 @@ +library flutter_advanced_calendar; + +export 'src/controller.dart'; +export 'src/widget.dart'; diff --git a/star_lock/lib/tools/advancedCalendar/src/controller.dart b/star_lock/lib/tools/advancedCalendar/src/controller.dart new file mode 100644 index 00000000..399ec83a --- /dev/null +++ b/star_lock/lib/tools/advancedCalendar/src/controller.dart @@ -0,0 +1,15 @@ +import 'package:flutter/widgets.dart'; + +import 'datetime_util.dart'; + +/// Advanced Calendar controller that manage selection date state. +class AdvancedCalendarController extends ValueNotifier { + /// Generates controller with custom date selected. + AdvancedCalendarController(DateTime value) : super(value); + + /// Generates controller with today date selected. + AdvancedCalendarController.today() : this(DateTime.now().toZeroTime()); + + @override + set value(DateTime newValue) => super.value = newValue.toZeroTime(); +} diff --git a/star_lock/lib/tools/advancedCalendar/src/date_box.dart b/star_lock/lib/tools/advancedCalendar/src/date_box.dart new file mode 100644 index 00000000..185b5d69 --- /dev/null +++ b/star_lock/lib/tools/advancedCalendar/src/date_box.dart @@ -0,0 +1,94 @@ +part of 'widget.dart'; + +/// Unit of calendar. +class DateBox extends StatelessWidget { + const DateBox({ + Key? key, + required this.child, + this.color, + this.width = 24.0, + this.height = 24.0, + this.borderRadius = const BorderRadius.all(Radius.circular(8.0)), + this.onPressed, + this.showDot = false, + this.isSelected = false, + this.isToday = false, + this.hasEvent = false, + }) : super(key: key); + + /// Child widget. + final Widget child; + + /// Background color. + final Color? color; + + /// Widget width. + final double width; + + /// Widget height. + final double height; + + /// Container border radius. + final BorderRadius borderRadius; + + /// Pressed callback function. + final VoidCallback? onPressed; + + /// Show DateBox event in container. + final bool showDot; + + /// DateBox is today. + final bool isToday; + + /// DateBox selection. + final bool isSelected; + + /// Show event in DateBox. + final bool hasEvent; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return UnconstrainedBox( + alignment: Alignment.center, + child: InkResponse( + onTap: onPressed, + radius: 16.0, + borderRadius: borderRadius, + highlightShape: BoxShape.rectangle, + child: AnimatedContainer( + duration: const Duration(milliseconds: 150), + width: width, + height: height, + alignment: Alignment.center, + decoration: BoxDecoration( + color: isSelected + ? theme.primaryColor + : isToday + ? theme.highlightColor + : null, + borderRadius: borderRadius, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + child, + if (showDot && hasEvent) + Container( + margin: const EdgeInsets.all(2.0), + height: 4, + width: 4, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: isSelected + ? theme.colorScheme.onPrimary + : theme.colorScheme.secondary, + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/star_lock/lib/tools/advancedCalendar/src/datetime_util.dart b/star_lock/lib/tools/advancedCalendar/src/datetime_util.dart new file mode 100644 index 00000000..ce4e2cd9 --- /dev/null +++ b/star_lock/lib/tools/advancedCalendar/src/datetime_util.dart @@ -0,0 +1,56 @@ +extension DateTimeUtil on DateTime { + /// Generate a new DateTime instance with a zero time. + DateTime toZeroTime() => DateTime.utc(year, month, day, 12); + + int findWeekIndex(List dates) { + return dates.indexWhere(isAtSameMomentAs) ~/ 7; + } + + /// Calculates first week date (Sunday) from this date. + DateTime firstDayOfWeek({int? startWeekDay}) { + final utcDate = DateTime.utc(year, month, day, 12); + if (startWeekDay != null && startWeekDay < 7) { + return utcDate.subtract(Duration(days: utcDate.weekday - startWeekDay)); + } + return utcDate.subtract(Duration(days: utcDate.weekday % 7)); + } + + /// Generates 7 dates according to this date. + /// (Supposed that this date is result of [firstDayOfWeek]) + List weekDates() { + return List.generate( + 7, + (index) => add(Duration(days: index)), + growable: false, + ); + } + + /// Generates list of list with [DateTime] + /// according to [date] and [weeksAmount]. + /// gives the beginning of the day of the week [startWeekDay] + List> generateWeeks(int weeksAmount, {int? startWeekDay}) { + final firstViewDate = firstDayOfWeek(startWeekDay: startWeekDay).subtract( + Duration( + days: (weeksAmount ~/ 2) * 7, + ), + ); + + return List.generate( + weeksAmount, + (weekIndex) { + final firstDateOfNextWeek = firstViewDate.add( + Duration( + days: weekIndex * 7, + ), + ); + + return firstDateOfNextWeek.weekDates(); + }, + growable: false, + ); + } + + bool isSameDate(DateTime other) { + return year == other.year && month == other.month && day == other.day; + } +} diff --git a/star_lock/lib/tools/advancedCalendar/src/handlebar.dart b/star_lock/lib/tools/advancedCalendar/src/handlebar.dart new file mode 100644 index 00000000..20154beb --- /dev/null +++ b/star_lock/lib/tools/advancedCalendar/src/handlebar.dart @@ -0,0 +1,39 @@ +part of 'widget.dart'; + +class HandleBar extends StatelessWidget { + const HandleBar({ + Key? key, + this.decoration, + this.margin = const EdgeInsets.only( + top: 8.0, + ), + this.onPressed, + }) : super(key: key); + + final BoxDecoration? decoration; + final EdgeInsetsGeometry margin; + final VoidCallback? onPressed; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onPressed, + behavior: HitTestBehavior.translucent, + child: Container( + margin: margin, + alignment: Alignment.center, + child: FractionallySizedBox( + widthFactor: 0.1, + child: Container( + height: 4.0, + decoration: decoration ?? + BoxDecoration( + color: Theme.of(context).dividerColor, + borderRadius: BorderRadius.circular(2.0), + ), + ), + ), + ), + ); + } +} diff --git a/star_lock/lib/tools/advancedCalendar/src/header.dart b/star_lock/lib/tools/advancedCalendar/src/header.dart new file mode 100644 index 00000000..bdc50a97 --- /dev/null +++ b/star_lock/lib/tools/advancedCalendar/src/header.dart @@ -0,0 +1,63 @@ +part of 'widget.dart'; + +class Header extends StatelessWidget { + const Header({ + Key? key, + required this.monthDate, + this.margin = const EdgeInsets.only( + left: 16.0, + right: 8.0, + top: 4.0, + bottom: 4.0, + ), + this.onPressed, + this.dateStyle, + this.todayStyle, + }) : super(key: key); + + static final _dateFormatter = DateFormat().add_yMMMM(); + // static final _dateFormatter = DateFormat('MM月dd日', 'zh_CN'); + final DateTime monthDate; + final EdgeInsetsGeometry margin; + final VoidCallback? onPressed; + final TextStyle? dateStyle; + final TextStyle? todayStyle; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + // initializeDateFormatting('zh_CN', null); + + return Container( + margin: margin, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // Text( + // _dateFormatter.format(monthDate), + // style: dateStyle ?? theme.textTheme.titleMedium, + // ), + InkWell( + onTap: onPressed, + borderRadius: const BorderRadius.all( + Radius.circular(4.0), + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + vertical: 4.0, + ), + child: Text( + '今天', + style: TextStyle( + color: Colors.black, + fontSize: 22.sp, + fontWeight: FontWeight.w600), + ), + ), + ), + ], + ), + ); + } +} diff --git a/star_lock/lib/tools/advancedCalendar/src/month_view.dart b/star_lock/lib/tools/advancedCalendar/src/month_view.dart new file mode 100644 index 00000000..fd1a0598 --- /dev/null +++ b/star_lock/lib/tools/advancedCalendar/src/month_view.dart @@ -0,0 +1,62 @@ +part of 'widget.dart'; + +class MonthView extends StatelessWidget { + const MonthView({ + Key? key, + required this.monthView, + required this.todayDate, + required this.selectedDate, + required this.weekLineHeight, + required this.weeksAmount, + required this.innerDot, + this.onChanged, + this.events, + required this.keepLineSize, + this.textStyle, + }) : super(key: key); + + final ViewRange monthView; + final DateTime? todayDate; + final DateTime selectedDate; + final double weekLineHeight; + final int weeksAmount; + final ValueChanged? onChanged; + final List? events; + final bool innerDot; + final bool keepLineSize; + final TextStyle? textStyle; + + @override + Widget build(BuildContext context) { + final index = selectedDate.findWeekIndex(monthView.dates); + final offset = index / (weeksAmount - 1) * 2 - 1.0; + + return OverflowBox( + alignment: Alignment(0, offset), + minHeight: weekLineHeight, + maxHeight: weekLineHeight * weeksAmount, + child: Column( + mainAxisSize: MainAxisSize.min, + children: List.generate( + 6, + (weekIndex) { + final weekStart = weekIndex * 7; + + return WeekView( + innerDot: innerDot, + dates: monthView.dates.sublist(weekStart, weekStart + 7), + selectedDate: selectedDate, + highlightMonth: monthView.firstDay.month, + lineHeight: weekLineHeight, + onChanged: onChanged, + events: events, + keepLineSize: keepLineSize, + textStyle: textStyle, + ); + }, + growable: false, + ), + ), + ); + } +} diff --git a/star_lock/lib/tools/advancedCalendar/src/month_view_bean.dart b/star_lock/lib/tools/advancedCalendar/src/month_view_bean.dart new file mode 100644 index 00000000..fef38b42 --- /dev/null +++ b/star_lock/lib/tools/advancedCalendar/src/month_view_bean.dart @@ -0,0 +1,40 @@ +part of 'widget.dart'; + +class ViewRange { + const ViewRange._(this.firstDay, this.dates); + + /// Creates custom filled [ViewRange] instance. + const ViewRange.custom( + DateTime firstDay, + List dates, + ) : this._(firstDay, dates); + + /// Generates [ViewRange] instance based on [date], + /// number of [month] and [weeksAmount]. + /// gives the beginning of the day of the week [startWeekDay] + factory ViewRange.generateDates( + DateTime date, + int month, + int weeksAmount, { + int? startWeekDay, + }) { + final firstMonthDate = DateTime.utc(date.year, month, 1); + final firstViewDate = + firstMonthDate.firstDayOfWeek(startWeekDay: startWeekDay); + + return ViewRange._( + firstMonthDate, + List.generate( + weeksAmount * 7, + (index) => firstViewDate.add(Duration(days: index)), + growable: false, + ), + ); + } + + /// Month view index. + final DateTime firstDay; + + /// Month view dates. + final List dates; +} diff --git a/star_lock/lib/tools/advancedCalendar/src/week_days.dart b/star_lock/lib/tools/advancedCalendar/src/week_days.dart new file mode 100644 index 00000000..e1f8ea87 --- /dev/null +++ b/star_lock/lib/tools/advancedCalendar/src/week_days.dart @@ -0,0 +1,36 @@ +part of 'widget.dart'; + +/// Week day names line. +class WeekDays extends StatelessWidget { + const WeekDays({ + Key? key, + this.weekNames = const ['日', '一', '二', '三', '四', '五', '六'], + this.style, + required this.keepLineSize, + }) : assert(weekNames.length == 7, '`weekNames` must have length 7'), + super(key: key); + + /// Week day names. + final List weekNames; + + /// Text style. + final TextStyle? style; + + final bool keepLineSize; + + @override + Widget build(BuildContext context) { + return DefaultTextStyle( + style: style!, + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: List.generate(weekNames.length, (index) { + return DateBox( + child: Text(weekNames[index]), + ); + }), + ), + ); + } +} diff --git a/star_lock/lib/tools/advancedCalendar/src/week_view.dart b/star_lock/lib/tools/advancedCalendar/src/week_view.dart new file mode 100644 index 00000000..725d04e3 --- /dev/null +++ b/star_lock/lib/tools/advancedCalendar/src/week_view.dart @@ -0,0 +1,137 @@ +part of 'widget.dart'; + +class WeekView extends StatelessWidget { + WeekView({ + Key? key, + required this.dates, + required this.selectedDate, + required this.lineHeight, + this.highlightMonth, + this.onChanged, + this.events, + required this.innerDot, + required this.keepLineSize, + this.textStyle, + }) : super(key: key); + + final DateTime todayDate = DateTime.now().toZeroTime(); + final List dates; + final double lineHeight; + final int? highlightMonth; + final DateTime selectedDate; + final ValueChanged? onChanged; + final List? events; + final bool innerDot; + final bool keepLineSize; + final TextStyle? textStyle; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return SizedBox( + height: lineHeight, + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.center, + children: List.generate( + 7, + (dayIndex) { + final date = dates[dayIndex]; + final isToday = date.isAtSameMomentAs(todayDate); + final isSelected = date.isAtSameMomentAs(selectedDate); + final isHighlight = highlightMonth == date.month; + + final hasEvent = + events!.indexWhere((element) => element.isSameDate(date)); + + if (keepLineSize) { + return InkResponse( + onTap: onChanged != null ? () => onChanged!(date) : null, + child: Container( + height: 36, + width: 36, + decoration: BoxDecoration( + color: isSelected + ? theme.primaryColor + : isToday + ? theme.highlightColor + : null, + borderRadius: BorderRadius.circular(18), + shape: BoxShape.rectangle, + ), + child: Column( + children: [ + Text( + '${date.day}', + style: textStyle?.copyWith( + color: isSelected || isToday + ? theme.colorScheme.onPrimary + : isHighlight || highlightMonth == null + ? null + : theme.disabledColor, + fontWeight: + isSelected && textStyle?.fontWeight != null + ? FontWeight + .values[textStyle!.fontWeight!.index + 2] + : textStyle?.fontWeight, + ), + ), + if (!hasEvent.isNegative) + Container( + height: 4, + width: 4, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(50), + color: isSelected + ? theme.colorScheme.onPrimary + : theme.colorScheme.secondary, + ), + ) + ], + ), + ), + ); + } + + return Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + DateBox( + width: innerDot ? 32 : 24, + height: innerDot ? 32 : 24, + showDot: innerDot, + onPressed: onChanged != null ? () => onChanged!(date) : null, + isSelected: isSelected, + isToday: isToday, + hasEvent: !hasEvent.isNegative, + child: Text( + '${date.day}', + maxLines: 1, + style: TextStyle( + color: isSelected || isToday + ? theme.colorScheme.onPrimary + : isHighlight || highlightMonth == null + ? null + : theme.disabledColor, + ), + ), + ), + if (!innerDot && !hasEvent.isNegative) + Container( + height: 6, + width: 6, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(50), + color: theme.primaryColor, + ), + ) + ], + ); + }, + growable: false, + ), + ), + ); + } +} diff --git a/star_lock/lib/tools/advancedCalendar/src/widget.dart b/star_lock/lib/tools/advancedCalendar/src/widget.dart new file mode 100644 index 00000000..0df0da71 --- /dev/null +++ b/star_lock/lib/tools/advancedCalendar/src/widget.dart @@ -0,0 +1,420 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:intl/date_symbol_data_local.dart'; +import 'package:intl/intl.dart'; + +import 'controller.dart'; +import 'datetime_util.dart'; + +part 'date_box.dart'; +part 'handlebar.dart'; +part 'header.dart'; +part 'month_view.dart'; +part 'month_view_bean.dart'; +part 'week_days.dart'; +part 'week_view.dart'; + +/// Advanced Calendar widget. +class AdvancedCalendar extends StatefulWidget { + const AdvancedCalendar({ + Key? key, + this.controller, + this.startWeekDay, + this.events, + this.weekLineHeight = 32.0, + this.preloadMonthViewAmount = 13, + this.preloadWeekViewAmount = 21, + this.weeksInMonthViewAmount = 6, + this.todayStyle, + this.headerStyle, + this.onHorizontalDrag, + this.innerDot = false, + this.keepLineSize = false, + this.calendarTextStyle, + }) : assert( + keepLineSize && innerDot || + innerDot && !keepLineSize || + !innerDot && !keepLineSize, + 'keepLineSize should be used only when innerDot is true', + ), + super(key: key); + + /// Calendar selection date controller. + final AdvancedCalendarController? controller; + + /// Executes on horizontal calendar swipe. Allows to load additional dates. + final Function(DateTime)? onHorizontalDrag; + + /// Height of week line. + final double weekLineHeight; + + /// Amount of months in month view to preload. + final int preloadMonthViewAmount; + + /// Amount of weeks in week view to preload. + final int preloadWeekViewAmount; + + /// Weeks lines amount in month view. + final int weeksInMonthViewAmount; + + /// List of points for the week and month + final List? events; + + /// The first day of the week starts[0-6] + final int? startWeekDay; + + /// Style of headers date + final TextStyle? headerStyle; + + /// Style of Today button + final TextStyle? todayStyle; + + /// Show DateBox event in container. + final bool innerDot; + + /// Keeps consistent line size for dates + /// Can't be used without innerDot + final bool keepLineSize; + + /// Text style for dates in calendar + final TextStyle? calendarTextStyle; + + @override + _AdvancedCalendarState createState() => _AdvancedCalendarState(); +} + +class _AdvancedCalendarState extends State + with SingleTickerProviderStateMixin { + late ValueNotifier _monthViewCurrentPage; + late AnimationController _animationController; + late AdvancedCalendarController _controller; + late double _animationValue; + late List _monthRangeList; + late List> _weekRangeList; + + PageController? _monthPageController; + PageController? _weekPageController; + Offset? _captureOffset; + DateTime? _todayDate; + List? _weekNames; + + @override + void initState() { + super.initState(); + + final monthPageIndex = widget.preloadMonthViewAmount ~/ 2; + + _monthViewCurrentPage = ValueNotifier(monthPageIndex); + + _monthPageController = PageController( + initialPage: monthPageIndex, + ); + + final weekPageIndex = widget.preloadWeekViewAmount ~/ 2; + + _weekPageController = PageController( + initialPage: weekPageIndex, + ); + + _animationController = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 300), + value: 0, + ); + + _animationValue = _animationController.value; + + _controller = widget.controller ?? AdvancedCalendarController.today(); + _todayDate = _controller.value; + + _monthRangeList = List.generate( + widget.preloadMonthViewAmount, + (index) => ViewRange.generateDates( + _todayDate!, + _todayDate!.month + (index - _monthPageController!.initialPage), + widget.weeksInMonthViewAmount, + startWeekDay: widget.startWeekDay, + ), + ); + + _weekRangeList = _controller.value.generateWeeks( + widget.preloadWeekViewAmount, + startWeekDay: widget.startWeekDay, + ); + _controller.addListener(() { + _weekRangeList = _controller.value.generateWeeks( + widget.preloadWeekViewAmount, + startWeekDay: widget.startWeekDay, + ); + _weekPageController!.jumpToPage(widget.preloadWeekViewAmount ~/ 2); + }); + if (widget.startWeekDay != null && widget.startWeekDay! < 7) { + final time = _controller.value.subtract( + Duration(days: _controller.value.weekday - widget.startWeekDay!), + ); + final list = List.generate( + 8, + (index) => time.add(Duration(days: index * 1)), + ).toList(); + // _weekNames = List.generate(7, (index) { + // return DateFormat("EEEE").format(list[index]).split('').first; + // } + // ); + //by DaisyWu 修改源文件为中文环境下 周一到周日 + _weekNames = List.generate(7, (index) { + String fullWeekName = + DateFormat.E('zh_CN').format(list[index]); // 获取星期的完整形式 + return fullWeekName + .substring(fullWeekName.length - 1); // 获取最后一个字符,即星期的简称 + }); + } + } + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return Material( + color: Colors.transparent, + child: DefaultTextStyle.merge( + style: theme.textTheme.bodyMedium, + child: GestureDetector( + onVerticalDragStart: (details) { + _captureOffset = details.globalPosition; + }, + onVerticalDragUpdate: (details) { + final moveOffset = details.globalPosition; + final diffY = moveOffset.dy - _captureOffset!.dy; + + _animationController.value = + _animationValue + diffY / (widget.weekLineHeight * 5); + }, + onVerticalDragEnd: (details) => _handleFinishDrag(), + onVerticalDragCancel: _handleFinishDrag, + child: Container( + color: Colors.transparent, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ValueListenableBuilder( + valueListenable: _monthViewCurrentPage, + builder: (_, value, __) { + return Header( + monthDate: + _monthRangeList[_monthViewCurrentPage.value].firstDay, + onPressed: _handleTodayPressed, + dateStyle: widget.headerStyle, + todayStyle: widget.todayStyle, + ); + }, + ), + WeekDays( + style: theme.textTheme.bodyLarge?.copyWith( + color: Colors.black, + ), + keepLineSize: widget.keepLineSize, + weekNames: _weekNames != null + ? _weekNames! + : const ['日', '一', '二', '三', '四', '五', '六'], + ), + AnimatedBuilder( + animation: _animationController, + builder: (_, __) { + final height = Tween( + begin: widget.weekLineHeight, + end: + widget.weekLineHeight * widget.weeksInMonthViewAmount, + ).transform(_animationController.value); + return SizedBox( + height: height, + child: ValueListenableBuilder( + valueListenable: _controller, + builder: (_, selectedDate, __) { + return Stack( + alignment: Alignment.center, + children: [ + IgnorePointer( + ignoring: _animationController.value == 0.0, + child: Opacity( + opacity: Tween( + begin: 0.0, + end: 1.0, + ).evaluate(_animationController), + child: PageView.builder( + onPageChanged: (pageIndex) { + if (widget.onHorizontalDrag != null) { + widget.onHorizontalDrag!( + _monthRangeList[pageIndex].firstDay, + ); + } + _monthViewCurrentPage.value = pageIndex; + }, + controller: _monthPageController, + physics: _animationController.value == 1.0 + ? const AlwaysScrollableScrollPhysics() + : const NeverScrollableScrollPhysics(), + itemCount: _monthRangeList.length, + itemBuilder: (_, pageIndex) { + return MonthView( + innerDot: widget.innerDot, + monthView: _monthRangeList[pageIndex], + todayDate: _todayDate, + selectedDate: selectedDate, + weekLineHeight: widget.weekLineHeight, + weeksAmount: + widget.weeksInMonthViewAmount, + onChanged: _handleDateChanged, + events: widget.events, + keepLineSize: widget.keepLineSize, + textStyle: widget.calendarTextStyle, + ); + }, + ), + ), + ), + ValueListenableBuilder( + valueListenable: _monthViewCurrentPage, + builder: (_, pageIndex, __) { + final index = selectedDate.findWeekIndex( + _monthRangeList[_monthViewCurrentPage.value] + .dates, + ); + final offset = index / + (widget.weeksInMonthViewAmount - 1) * + 2 - + 1.0; + return Align( + alignment: Alignment(0.0, offset), + child: IgnorePointer( + ignoring: + _animationController.value == 1.0, + child: Opacity( + opacity: Tween( + begin: 1.0, + end: 0.0, + ).evaluate(_animationController), + child: SizedBox( + height: widget.weekLineHeight, + child: PageView.builder( + onPageChanged: (indexPage) { + final pageIndex = + _monthRangeList.indexWhere( + (index) => + index.firstDay.month == + _weekRangeList[indexPage] + .first + .month, + ); + + if (widget.onHorizontalDrag != + null) { + widget.onHorizontalDrag!( + _monthRangeList[pageIndex] + .firstDay, + ); + } + _monthViewCurrentPage.value = + pageIndex; + }, + controller: _weekPageController, + itemCount: _weekRangeList.length, + physics: _closeMonthScroll(), + itemBuilder: (context, index) { + return WeekView( + innerDot: widget.innerDot, + dates: _weekRangeList[index], + selectedDate: selectedDate, + lineHeight: + widget.weekLineHeight, + onChanged: + _handleWeekDateChanged, + events: widget.events, + keepLineSize: + widget.keepLineSize, + textStyle: + widget.calendarTextStyle, + ); + }, + ), + ), + ), + ), + ); + }, + ), + ], + ); + }, + ), + ); + }, + ), + // HandleBar( + // onPressed: () async { + // await _animationController.forward(); + // _animationValue = 1.0; + // }, + // ), + ], + ), + ), + ), + ), + ); + } + + @override + void dispose() { + _animationController.dispose(); + _monthPageController!.dispose(); + _monthViewCurrentPage.dispose(); + + if (widget.controller == null) { + _controller.dispose(); + } + + super.dispose(); + } + + void _handleWeekDateChanged(DateTime date) { + _handleDateChanged(date); + + _monthViewCurrentPage.value = _monthRangeList + .lastIndexWhere((monthRange) => monthRange.dates.contains(date)); + } + + void _handleDateChanged(DateTime date) { + _controller.value = date; + } + + void _handleFinishDrag() async { + _captureOffset = null; + + if (_animationController.value > 0.5) { + await _animationController.forward(); + _animationValue = 1.0; + } else { + await _animationController.reverse(); + _animationValue = 0.0; + } + } + + void _handleTodayPressed() { + _controller.value = DateTime.now().toZeroTime(); + + _monthPageController!.jumpToPage(widget.preloadMonthViewAmount ~/ 2); + _weekPageController!.jumpToPage(widget.preloadWeekViewAmount ~/ 2); + } + + ScrollPhysics _closeMonthScroll() { + if ((_monthViewCurrentPage.value == + (widget.preloadMonthViewAmount ~/ 2) + 3 || + _monthViewCurrentPage.value == + (widget.preloadMonthViewAmount ~/ 2) - 3)) { + return const NeverScrollableScrollPhysics(); + } else { + return const AlwaysScrollableScrollPhysics(); + } + } +} diff --git a/star_lock/pubspec.yaml b/star_lock/pubspec.yaml index c42eeee6..a07283ec 100644 --- a/star_lock/pubspec.yaml +++ b/star_lock/pubspec.yaml @@ -134,7 +134,7 @@ dependencies: flutter_voice_processor: ^1.1.0 #监听网络连接状态 connectivity_plus: ^5.0.2 - flutter_advanced_calendar: ^1.4.1 + #flutter_advanced_calendar: ^1.4.1 timelines: ^0.1.0 #侧滑删除 flutter_slidable: ^3.0.1 From 60614a53b15ff8709576a3d1b255401c7c7664da Mon Sep 17 00:00:00 2001 From: Daisy <> Date: Fri, 26 Jan 2024 16:19:01 +0800 Subject: [PATCH 3/3] =?UTF-8?q?1=EF=BC=8C=E6=96=B0=E5=A2=9E=E4=B8=8B?= =?UTF-8?q?=E6=8B=89=E7=BB=84=E4=BB=B6=202=EF=BC=8C=E9=97=A8=E9=94=81?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E9=A1=B5=E9=9D=A2=E4=BC=98=E5=8C=96=E5=AE=8C?= =?UTF-8?q?=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- star_lock/images/main/icon_lockLog_play.png | Bin 0 -> 1319 bytes .../doorLockLog/doorLockLog_page.dart | 71 ++++---- .../doorLockLog/doorLockLog_state.dart | 12 +- star_lock/lib/network/api.dart | 4 +- .../tools/advancedCalendar/src/header.dart | 2 +- .../lib/tools/menuItem/dropDownItem.dart | 14 ++ .../lib/tools/menuItem/xsDropDownWidget.dart | 161 ++++++++++++++++++ 7 files changed, 226 insertions(+), 38 deletions(-) create mode 100644 star_lock/images/main/icon_lockLog_play.png create mode 100644 star_lock/lib/tools/menuItem/dropDownItem.dart create mode 100644 star_lock/lib/tools/menuItem/xsDropDownWidget.dart diff --git a/star_lock/images/main/icon_lockLog_play.png b/star_lock/images/main/icon_lockLog_play.png new file mode 100644 index 0000000000000000000000000000000000000000..fec3120cc1d64f47941d6e44464d21c3b8378e1c GIT binary patch literal 1319 zcmV+?1=#wDP)SFe8e>j!@zA}lX2->%o|o)ChRQpfTVLQuV4_m-EJZwI1Xo4H)>z;HQEFvgI})_Uzf8GMUU# zYdbX2XcSV)+|tt0Z#2w;S9#zH|B9TZ^3o_B?;`=_D%_geVD!Sb+^7%YwXJ?Vk zW})l)$P#LZMWfL`xm-r6R6-;Y8RgfK}rcF2%O)wP0Bm(&=<);Q<Aq0dFuq+Gte11FR z!Vo%*9z-B4`0VwzMq+bw6OQBH^5x5j$K#@0Z>}&(JCU87%pja&8%$X7_%R(ZN z7)q6@DN=i1CVirCrPS87Pbt9|LpGazFa8Xsr>BQoN({ruw)fwE-wGE6fWa^foIZUT z=g*(V$&)9CzBd@^9M~ES38e_SuER7&1O>-n0o6rxyIft(6+Y1yCkW3~~ zEEZwgHcF)uCMG71?}jECjlwidwA*b+DWU5+PMtc1bLYOo{Cs)zTgtEolF1}4Uc88S zJPy}&k;~;^+cr$o9JzR42oIp^I`a8EIOp(vABjW)nM`KnuT=sxIglbu8f9!N(-e!v zAG%71`}XZ$jEGRFRQ|MW z`^wnZ*iq{`6un*#^?JQpE|=#x0Mu%=Uz*LP^MBYI5D{LzdL`=h`p?@9M1=eI?_YoZ z{Q0}%e#Er8y87}mVUnvA;jOV z>sB{5HWsg4ySBL9XTPwyd-rZEl}ep^f6N+IRP3-e7-KQc`3J|hMC5y(x8XSNs<&?a d@M3qLe*q>1E1VI6bBzE1002ovPDHLkV1l8(Zt4I4 literal 0 HcmV?d00001 diff --git a/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart b/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart index 6d3ea284..57750ac2 100644 --- a/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart +++ b/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart @@ -1,8 +1,10 @@ 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/main/lockDetail/doorLockLog/doorLockLog_logic.dart'; import 'package:star_lock/tools/advancedCalendar/src/widget.dart'; +import 'package:star_lock/tools/menuItem/xsDropDownWidget.dart'; import 'package:timelines/timelines.dart'; import '../../../app_settings/app_colors.dart'; @@ -122,35 +124,18 @@ class _DoorLockLogPageState extends State { //事件下拉框组件 Widget eventDropDownWidget() { - return Row(children: [ - SizedBox( - width: 50.w, + return Container( + margin: EdgeInsets.only(top: 20.h, left: 30.w, bottom: 20.h), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Obx(() => XSDropDownWidget( + items: state.getDropDownItemList, + value: state.dropdownValue.value, + valueChanged: (value) {})), + ], ), - Obx(() => DropdownButton( - value: state.dropdownValue.value, - icon: const Icon(Icons.arrow_drop_down), - iconSize: 40, - elevation: 12, - style: TextStyle( - fontSize: 26.sp, - color: Colors.black, - fontWeight: FontWeight.w600), - iconEnabledColor: Colors.grey, - underline: Container( - height: 0, - ), - onChanged: (newValue) { - state.dropdownValue.value = newValue!; - }, - items: state.dropDownItemList.obs - .map>((item) { - return DropdownMenuItem( - value: item, - child: Text(item), - ); - }).toList(), - )) - ]); + ); } //时间轴组件 @@ -175,11 +160,31 @@ class _DoorLockLogPageState extends State { color: Colors.black, fontSize: 24.sp, fontWeight: FontWeight.w600)), - Image( - image: const AssetImage( - 'images/main/icon_lockDetail_monitoringvoiceFrist.png'), - width: 260.w, - height: 260.h, + GestureDetector( + onTap: () { + Get.toNamed(Routers.videoLogDetailPage); + }, + child: Stack( + children: [ + Image( + image: const AssetImage( + 'images/main/icon_lockDetail_monitoringvoiceFrist.png'), + width: 260.w, + height: 260.h, + ), + //在图片上添加一个三角视频图标 + Positioned( + top: 200.h, + left: 10.w, + child: Image( + image: const AssetImage( + 'images/main/icon_lockLog_play.png'), + width: 24.w, + height: 20.w, + ), + ), + ], + ), ), ], ), diff --git a/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_state.dart b/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_state.dart index c89b39ce..e3b30267 100644 --- a/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_state.dart +++ b/star_lock/lib/main/lockDetail/doorLockLog/doorLockLog_state.dart @@ -1,5 +1,7 @@ +import 'package:flutter/cupertino.dart'; import 'package:get/get.dart'; import 'package:star_lock/tools/advancedCalendar/src/controller.dart'; +import 'package:star_lock/tools/menuItem/dropDownItem.dart'; import '../../lockMian/entity/lockListInfo_entity.dart'; import '../electronicKey/electronicKeyDetail/keyOperationRecordEntity.dart'; @@ -14,8 +16,14 @@ class DoorLockLogState { DateTime(2024, 10, 10), ]; var dropdownValue = '全部事件'.obs; - final List dropDownItemList = - ['全部事件', '门锁异常', '有人出现', '有人按门铃', '一次性密码开门'].obs; + List getDropDownItemList = [ + DropDownItem(itemTitle: "全部事件", itemValue: '0', isCheked: false), + DropDownItem(itemTitle: "开锁事件", itemValue: '1', isCheked: false), + DropDownItem(itemTitle: "异常事件", itemValue: '2', isCheked: false), + DropDownItem(itemTitle: "门锁事件", itemValue: '3', isCheked: false), + DropDownItem(itemTitle: "视频事件", itemValue: '4', isCheked: false), + ]; + var currentStep = 0.obs; DoorLockLogState() { diff --git a/star_lock/lib/network/api.dart b/star_lock/lib/network/api.dart index 0f0096cc..5f658d46 100644 --- a/star_lock/lib/network/api.dart +++ b/star_lock/lib/network/api.dart @@ -1,6 +1,6 @@ abstract class Api { - // static String baseAddress = "https://pre.lock.star-lock.cn"; //预发布环境 - static String baseAddress = "https://dev.lock.star-lock.cn"; //联调环境 + static String baseAddress = "https://pre.lock.star-lock.cn"; //预发布环境 + // static String baseAddress = "https://dev.lock.star-lock.cn"; //联调环境 // static String baseAddress = "http://192.168.1.15:8022"; //谢总本地 // static String baseAddress = "https://ge.lock.star-lock.cn"; //葛工开发环境地址 diff --git a/star_lock/lib/tools/advancedCalendar/src/header.dart b/star_lock/lib/tools/advancedCalendar/src/header.dart index bdc50a97..1a09140e 100644 --- a/star_lock/lib/tools/advancedCalendar/src/header.dart +++ b/star_lock/lib/tools/advancedCalendar/src/header.dart @@ -51,7 +51,7 @@ class Header extends StatelessWidget { '今天', style: TextStyle( color: Colors.black, - fontSize: 22.sp, + fontSize: 24.sp, fontWeight: FontWeight.w600), ), ), diff --git a/star_lock/lib/tools/menuItem/dropDownItem.dart b/star_lock/lib/tools/menuItem/dropDownItem.dart new file mode 100644 index 00000000..b08b44c3 --- /dev/null +++ b/star_lock/lib/tools/menuItem/dropDownItem.dart @@ -0,0 +1,14 @@ +/// 通用菜单项 +class DropDownItem { + // 显示的文本 + String itemTitle = ''; + // 选中的值 + dynamic itemValue; + // 是否选中 + bool isCheked = false; + + DropDownItem( + {required this.itemTitle, + required this.itemValue, + required this.isCheked}); +} diff --git a/star_lock/lib/tools/menuItem/xsDropDownWidget.dart b/star_lock/lib/tools/menuItem/xsDropDownWidget.dart new file mode 100644 index 00000000..25ea1eb4 --- /dev/null +++ b/star_lock/lib/tools/menuItem/xsDropDownWidget.dart @@ -0,0 +1,161 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:star_lock/app_settings/app_colors.dart'; +import 'package:star_lock/tools/menuItem/dropDownItem.dart'; + +/// @author baorant +/// @创建时间:2024/4/11 +/// 下拉菜单按钮组件 +class XSDropDownWidget extends StatefulWidget { + // 显示的菜单项 + List items = []; + // 当前选中的值 + final dynamic value; + // 选择框前的标题 + final String? title; + // 提示语 + final String tooltip; + // 选中数据的回调事件 + final ValueChanged? valueChanged; + XSDropDownWidget( + {Key? key, + required this.items, + this.value, + this.valueChanged, + this.title, + this.tooltip = "点击选择"}) + : super(key: key); + + @override + State createState() => _XSDropDownWidgetState(); +} + +class _XSDropDownWidgetState extends State { + String label = '请选择'; + // 是否展开下拉按钮 + bool isExpand = false; + // 当前的值 + dynamic currentValue; + + @override + void initState() { + currentValue = widget.value; + super.initState(); + } + + /// 根据当前的value处理当前文本显示 + void initTitle() { + if (currentValue != null) { + // 有值查值 + for (DropDownItem item in widget.items) { + if (item.itemValue == currentValue) { + label = item.itemTitle; + return; + } + } + } + // 没值默认取第一个 + if (widget.items.isNotEmpty) { + label = widget.items[0].itemTitle; + } + } + + @override + Widget build(BuildContext context) { + initTitle(); + return Wrap( + children: [ + if (widget.title != null) + Text(widget.title!, + style: TextStyle( + fontSize: 26.sp, + color: Colors.black, + fontWeight: FontWeight.w600, + )), + PopupMenuButton( + color: Colors.white, + // initialValue: currentValue, + tooltip: widget.tooltip, + offset: const Offset(0, 30), + enableFeedback: true, + child: Listener( + // 使用listener事件能够继续传递 + onPointerDown: (event) { + setState(() { + isExpand = !isExpand; + }); + }, + child: Wrap( + children: [ + Text( + label, + style: TextStyle( + fontSize: 24.sp, + color: Colors.black, + fontWeight: FontWeight.w600, + ), + ), + isExpand + ? const Icon(Icons.arrow_drop_up) + : const Icon(Icons.arrow_drop_down) + ], + ), + ), + onSelected: (value) { + widget.valueChanged?.call(value); + setState(() { + currentValue = value; + isExpand = !isExpand; + }); + }, + onCanceled: () { + // 取消展开 + setState(() { + isExpand = false; + }); + }, + itemBuilder: (context) { + return widget.items.map((item) { + return PopupMenuItem( + value: item.itemValue, + child: Container( + margin: + EdgeInsets.only(left: 0.w, right: 0, top: 0, bottom: 0), + color: item.itemValue == currentValue + ? AppColors.mainColor + : null, // 设置选中项背景色为蓝色 + child: Text( + item.itemTitle, + style: TextStyle( + color: item.itemValue == currentValue + ? Colors.white + : Colors.black, // 设置选中项文字颜色为白色 + ), + ), + ), + ); + }).toList(); + }, + // itemBuilder: (context) { + // return widget.items + // .map( + // (item) => item.itemValue == currentValue + // ? PopupMenuItem( + // value: item.itemValue, + // child: Text( + // item.itemTitle, + // style: TextStyle(color: AppColors.mainColor), + // ), + // ) + // : PopupMenuItem( + // value: item.itemValue, + // child: Text(item.itemTitle), + // ), + // ) + // .toList(); + // }, + ) + ], + ); + } +}