diff --git a/star_lock/images/bumble_bee_captions.vtt b/star_lock/images/bumble_bee_captions.vtt new file mode 100644 index 00000000..1dca2c58 --- /dev/null +++ b/star_lock/images/bumble_bee_captions.vtt @@ -0,0 +1,7 @@ +WEBVTT + +00:00:00.200 --> 00:00:01.750 +[ Birds chirping ] + +00:00:02.300 --> 00:00:05.000 +[ Buzzing ] diff --git a/star_lock/images/icon_round_white_unSelet.png b/star_lock/images/icon_round_white_unSelet.png new file mode 100644 index 00000000..99135fc4 Binary files /dev/null and b/star_lock/images/icon_round_white_unSelet.png differ diff --git a/star_lock/images/icon_test20231113.png b/star_lock/images/icon_test20231113.png new file mode 100644 index 00000000..f30018c7 Binary files /dev/null and b/star_lock/images/icon_test20231113.png differ diff --git a/star_lock/images/main/icon_lockDetail_messageReminding.png b/star_lock/images/main/icon_lockDetail_messageReminding.png new file mode 100644 index 00000000..3c819abd Binary files /dev/null and b/star_lock/images/main/icon_lockDetail_messageReminding.png differ diff --git a/star_lock/images/main/icon_lockDetail_monitoringCloseVoice.png b/star_lock/images/main/icon_lockDetail_monitoringCloseVoice.png new file mode 100644 index 00000000..50257dc2 Binary files /dev/null and b/star_lock/images/main/icon_lockDetail_monitoringCloseVoice.png differ diff --git a/star_lock/images/main/icon_lockDetail_monitoringDeletVideo.png b/star_lock/images/main/icon_lockDetail_monitoringDeletVideo.png new file mode 100644 index 00000000..02fac231 Binary files /dev/null and b/star_lock/images/main/icon_lockDetail_monitoringDeletVideo.png differ diff --git a/star_lock/images/main/icon_lockDetail_monitoringDeletVideo_white.png b/star_lock/images/main/icon_lockDetail_monitoringDeletVideo_white.png new file mode 100644 index 00000000..2ac7f119 Binary files /dev/null and b/star_lock/images/main/icon_lockDetail_monitoringDeletVideo_white.png differ diff --git a/star_lock/images/main/icon_lockDetail_monitoringDownloadVideo.png b/star_lock/images/main/icon_lockDetail_monitoringDownloadVideo.png new file mode 100644 index 00000000..a9d81f74 Binary files /dev/null and b/star_lock/images/main/icon_lockDetail_monitoringDownloadVideo.png differ diff --git a/star_lock/images/main/icon_lockDetail_monitoringDownloadVideo_white.png b/star_lock/images/main/icon_lockDetail_monitoringDownloadVideo_white.png new file mode 100644 index 00000000..94c4fbb6 Binary files /dev/null and b/star_lock/images/main/icon_lockDetail_monitoringDownloadVideo_white.png differ diff --git a/star_lock/images/main/icon_lockDetail_monitoringEditVoice.png b/star_lock/images/main/icon_lockDetail_monitoringEditVoice.png new file mode 100644 index 00000000..3a08ea9f Binary files /dev/null and b/star_lock/images/main/icon_lockDetail_monitoringEditVoice.png differ diff --git a/star_lock/images/main/icon_lockDetail_monitoringOpenVoice.png b/star_lock/images/main/icon_lockDetail_monitoringOpenVoice.png new file mode 100644 index 00000000..fb125d67 Binary files /dev/null and b/star_lock/images/main/icon_lockDetail_monitoringOpenVoice.png differ diff --git a/star_lock/images/main/icon_lockDetail_monitoringScreenRecording.png b/star_lock/images/main/icon_lockDetail_monitoringScreenRecording.png new file mode 100644 index 00000000..a4e6605b Binary files /dev/null and b/star_lock/images/main/icon_lockDetail_monitoringScreenRecording.png differ diff --git a/star_lock/images/main/icon_lockDetail_monitoringScreenshot.png b/star_lock/images/main/icon_lockDetail_monitoringScreenshot.png new file mode 100644 index 00000000..c0660ed5 Binary files /dev/null and b/star_lock/images/main/icon_lockDetail_monitoringScreenshot.png differ diff --git a/star_lock/images/main/icon_lockDetail_monitoringShareVideo_white.png b/star_lock/images/main/icon_lockDetail_monitoringShareVideo_white.png new file mode 100644 index 00000000..888d3992 Binary files /dev/null and b/star_lock/images/main/icon_lockDetail_monitoringShareVideo_white.png differ diff --git a/star_lock/images/main/icon_lockDetail_monitoringTalkback.png b/star_lock/images/main/icon_lockDetail_monitoringTalkback.png new file mode 100644 index 00000000..8398fbcb Binary files /dev/null and b/star_lock/images/main/icon_lockDetail_monitoringTalkback.png differ diff --git a/star_lock/images/main/icon_lockDetail_monitoringUnlock.png b/star_lock/images/main/icon_lockDetail_monitoringUnlock.png new file mode 100644 index 00000000..d885721e Binary files /dev/null and b/star_lock/images/main/icon_lockDetail_monitoringUnlock.png differ diff --git a/star_lock/images/main/icon_lockDetail_monitoringvoiceFrist.png b/star_lock/images/main/icon_lockDetail_monitoringvoiceFrist.png new file mode 100644 index 00000000..cc5f8781 Binary files /dev/null and b/star_lock/images/main/icon_lockDetail_monitoringvoiceFrist.png differ diff --git a/star_lock/images/main/icon_lockDetail_videoLog.png b/star_lock/images/main/icon_lockDetail_videoLog.png new file mode 100644 index 00000000..532004cf Binary files /dev/null and b/star_lock/images/main/icon_lockDetail_videoLog.png differ diff --git a/star_lock/lib/appRouters.dart b/star_lock/lib/appRouters.dart index 914718d7..40ddf2ff 100644 --- a/star_lock/lib/appRouters.dart +++ b/star_lock/lib/appRouters.dart @@ -84,11 +84,17 @@ import 'main/lockDetail/lcokSet/wirelessKeyboard/addWirelessKeyboard/addWireless import 'main/lockDetail/lcokSet/wirelessKeyboard/addWirelessKeyboardScreenNotLightOn/addWirelessKeyboardScreenNotLightOn_page.dart'; import 'main/lockDetail/lcokSet/wirelessKeyboard/seletWirelessKeyboard/seletWirelessKeyboard_page.dart'; import 'main/lockDetail/lcokSet/wirelessKeyboard/wirelessKeyboardList/wirelessKeyboard_page.dart'; +import 'main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart'; +import 'main/lockDetail/monitoring/monitoringRealTimeScreen/monitoringRealTimeScreen_page.dart'; import 'main/lockDetail/otherTypeKey/addFingerprint/addFingerprint/addFingerprint_page.dart'; import 'main/lockDetail/otherTypeKey/addFingerprint/addFingerprintTip/addFingerprintTip_page.dart'; import 'main/lockDetail/otherTypeKey/addICCard/addICCard_page.dart'; import 'main/lockDetail/otherTypeKey/otherTypeKeyChangeDate/otherTypeKeyChangeDate_page.dart'; import 'main/lockDetail/otherTypeKey/otherTypeKeyChangeValidityDate/otherTypeKeyChangeValidityDate_page.dart'; +import 'main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart'; +import 'main/lockDetail/videoLog/videoLog/videoLog_page.dart'; +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 'mine/about/about_page.dart'; @@ -371,6 +377,12 @@ abstract class Routers { static const coerceFingerprintPage = '/coerceFingerprintPage'; //胁迫指纹 static const lowBatteryReminderPage = '/lowBatteryReminderPage'; //低电量提醒 static const coerceFingerprintListPage = '/coerceFingerprintListPage'; //指纹列表 + static const lockMonitoringPage = '/LockMonitoringPage'; //监控 + static const monitoringRealTimeScreenPage = '/MonitoringRealTimeScreenPage'; //实时画面 + static const videoLogPage = '/VideoLogPage'; // 视频日志 + static const editVideoLogPage = '/EditVideoLogPage'; // 编辑视频日志 + static const videoLogDetailPage = '/VideoLogDetailPage'; // 视频日志详情 + static const videoLogDownLoadPage = '/VideoLogDownLoadPage'; // 视频下载列表 } abstract class AppRouters { @@ -911,6 +923,24 @@ abstract class AppRouters { page: () => const LowBatteryReminderPage()), GetPage( name: Routers.coerceFingerprintListPage, - page: () => const CoerceFingerprintListPage()) + page: () => const CoerceFingerprintListPage()), + GetPage( + name: Routers.lockMonitoringPage, + page: () => const LockMonitoringPage()), + GetPage( + name: Routers.monitoringRealTimeScreenPage, + page: () => const MonitoringRealTimeScreenPage()), + GetPage( + name: Routers.videoLogPage, + page: () => const VideoLogPage()), + GetPage( + name: Routers.editVideoLogPage, + page: () => const EditVideoLogPage()), + GetPage( + name: Routers.videoLogDetailPage, + page: () => const VideoLogDetailPage()), + GetPage( + name: Routers.videoLogDownLoadPage, + page: () => const VideoLogDownLoadPage()), ]; } diff --git a/star_lock/lib/blue/blue_manage.dart b/star_lock/lib/blue/blue_manage.dart index 773bf791..0ca50143 100644 --- a/star_lock/lib/blue/blue_manage.dart +++ b/star_lock/lib/blue/blue_manage.dart @@ -82,6 +82,7 @@ class BlueManage{ } else { _scanDevices.add(device); } + scanResultCallBack(_scanDevices); } }else{ @@ -94,6 +95,7 @@ class BlueManage{ } else { _scanDevices.add(device); } + // print("_scanDevices:$_scanDevices"); scanResultCallBack(_scanDevices); } } diff --git a/star_lock/lib/blue/io_protocol/io_configuringWifi.dart b/star_lock/lib/blue/io_protocol/io_configuringWifi.dart index 00575c68..d7865623 100644 --- a/star_lock/lib/blue/io_protocol/io_configuringWifi.dart +++ b/star_lock/lib/blue/io_protocol/io_configuringWifi.dart @@ -16,7 +16,7 @@ class SenderConfiguringWifiCommand extends SenderProtocol { String? ssid; String? password; int? numberOfServers; - int? listOfServers; + List? listOfServers; List? token; int? needAuthor; List? publicKey; @@ -76,7 +76,7 @@ class SenderConfiguringWifiCommand extends SenderProtocol { subData.add(numberOfServers!); // listOfServers - subData.add(listOfServers!); + subData.addAll(listOfServers!); // token // subData.addAll(token!); diff --git a/star_lock/lib/blue/io_tool/io_tool.dart b/star_lock/lib/blue/io_tool/io_tool.dart index 3d20b000..18fc8e69 100644 --- a/star_lock/lib/blue/io_tool/io_tool.dart +++ b/star_lock/lib/blue/io_tool/io_tool.dart @@ -3,7 +3,6 @@ import 'dart:typed_data'; import 'package:crypto/crypto.dart'; import 'package:flutter/services.dart'; -import 'package:encrypt/encrypt.dart' as ddd; List changeIntListToStringList(List list){ List strList = []; diff --git a/star_lock/lib/blue/reciver_data.dart b/star_lock/lib/blue/reciver_data.dart index 9776e72b..4f3c34f3 100644 --- a/star_lock/lib/blue/reciver_data.dart +++ b/star_lock/lib/blue/reciver_data.dart @@ -252,6 +252,12 @@ class CommandReciverManager { reply = SenderReferEventRecordTimeReply.parseData(commandType, data); } break; + // case 50: + // { + // // wifi配网 + // reply = SenderConfiguringWifiReply.parseData(commandType, data); + // } + // break; case 51: { // wifi配网结果 diff --git a/star_lock/lib/blue/sender_manage.dart b/star_lock/lib/blue/sender_manage.dart index 13ea1133..35fdc17f 100644 --- a/star_lock/lib/blue/sender_manage.dart +++ b/star_lock/lib/blue/sender_manage.dart @@ -516,7 +516,7 @@ class IoSenderManage { required String? ssid, required String? password, required int? numberOfServers, - required int? listOfServers, + required List? listOfServers, required List? token, required int? needAuthor, required List? publicKey, diff --git a/star_lock/lib/main/lockDetail/lcokSet/configuringWifi/configuringWifi_logic.dart b/star_lock/lib/main/lockDetail/lcokSet/configuringWifi/configuringWifi_logic.dart index a9464f88..2573a862 100644 --- a/star_lock/lib/main/lockDetail/lcokSet/configuringWifi/configuringWifi_logic.dart +++ b/star_lock/lib/main/lockDetail/lcokSet/configuringWifi/configuringWifi_logic.dart @@ -5,6 +5,7 @@ import 'package:flutter_reactive_ble/flutter_reactive_ble.dart'; import 'package:network_info_plus/network_info_plus.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:star_lock/tools/baseGetXController.dart'; +import 'package:star_lock/tools/toast.dart'; import '../../../../blue/blue_manage.dart'; import '../../../../blue/io_protocol/io_configuringWifi.dart'; @@ -24,6 +25,23 @@ class ConfiguringWifiLogic extends BaseGetXController{ var entity = await ApiRepository.to.getWifiLockServiceIpAndPort(); if(entity.errorCode! == 0){ state.configuringWifiEntity.value = entity; + + // var serversList = []; + // for(int i = 0; i _replySubscription; void _initReplySubscription() { _replySubscription = EventBusManager().eventBus!.on().listen((reply) async { - // 配置wifi + // WIFI配网结果 if(reply is SenderConfiguringWifiReply) { _replySenderConfiguringWifi(reply); } }); } - // 开门数据解析 + // WIFI配网结果 Future _replySenderConfiguringWifi(Reply reply) async { - var privateKey = await Storage.getStringList(saveBluePrivateKey); - List getPrivateKeyList = changeStringListToIntList(privateKey!); - - var signKey = await Storage.getStringList(saveBlueSignKey); - List signKeyDataList = changeStringListToIntList(signKey!); - - var tokenData = reply.data.sublist(2, 6); - var saveStrList = changeIntListToStringList(tokenData); - print("openDoorToken:$tokenData"); - Storage.setStringList(saveBlueToken, saveStrList); - int status = reply.data[6]; print("status:$status"); @@ -58,20 +65,48 @@ class ConfiguringWifiLogic extends BaseGetXController{ case 0x00: //成功 print("${reply.commandType}数据解析成功"); - + Toast.show(msg: "配网成功"); break; case 0x06: //无权限 print("${reply.commandType}需要鉴权"); - IoSenderManage.senderOpenLock( - keyID: "1", + var privateKey = await Storage.getStringList(saveBluePrivateKey); + List getPrivateKeyList = changeStringListToIntList(privateKey!); + + var publicKey = await Storage.getStringList(saveBluePublicKey); + List publicKeyDataList = changeStringListToIntList(publicKey!); + + var tokenData = reply.data.sublist(7, 10); + var saveStrList = changeIntListToStringList(tokenData); + print("openDoorToken:$tokenData"); + Storage.setStringList(saveBlueToken, saveStrList); + + var serversList = []; + for(int i = 0; i[]; + for(int i = 0; i { configuringWifiTFWidget(TranslationLoader.lanKeys!.wifiPassward!.tr, TranslationLoader.lanKeys!.pleaseEnterWifiPwd!.tr, state.wifiPWDController), SizedBox(height: 50.h,), SubmitBtn(btnName: TranslationLoader.lanKeys!.sure!.tr, onClick: () { - + logic.senderConfiguringWifiAction(); }), ], )); @@ -51,14 +51,14 @@ class _ConfiguringWifiPageState extends State { leftTitel: titleStr, rightTitle: "", isHaveRightWidget: true, - rightWidget: getTFWidget(rightTitle)), + rightWidget: getTFWidget(rightTitle, controller)), Container(height: 10.h), ], ); } // 接受者信息输入框 - Widget getTFWidget(String tfStr) { + Widget getTFWidget(String tfStr, TextEditingController controller) { return Container( height: 50.h, width: 300.w, @@ -68,7 +68,7 @@ class _ConfiguringWifiPageState extends State { child: TextField( //输入框一行 maxLines: 1, - // controller: _controller, + controller: controller, autofocus: false, textAlign: TextAlign.end, decoration: InputDecoration( diff --git a/star_lock/lib/main/lockDetail/lcokSet/configuringWifi/configuringWifi_state.dart b/star_lock/lib/main/lockDetail/lcokSet/configuringWifi/configuringWifi_state.dart index a7b72204..011dae01 100644 --- a/star_lock/lib/main/lockDetail/lcokSet/configuringWifi/configuringWifi_state.dart +++ b/star_lock/lib/main/lockDetail/lcokSet/configuringWifi/configuringWifi_state.dart @@ -3,15 +3,20 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import '../lockSet/lockSetInfo_entity.dart'; import 'configuringWifiEntity.dart'; class ConfiguringWifiState{ var configuringWifiEntity = ConfiguringWifiEntity().obs; + var lockSetInfoData = LockSetInfoData().obs; + var lockBasicInfo = LockBasicInfo().obs; TextEditingController wifiNameController = TextEditingController(); TextEditingController wifiPWDController = TextEditingController(); ConfiguringWifiState() { - // wifiNameController.text = emailOrPhone.value; + var map = Get.arguments; + lockSetInfoData.value = map["lockSetInfoData"]; + lockBasicInfo.value = lockSetInfoData.value.lockBasicInfo!; } } \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/lcokSet/lockSet/lockSet_page.dart b/star_lock/lib/main/lockDetail/lcokSet/lockSet/lockSet_page.dart index fe56b58b..f8a1b2e3 100644 --- a/star_lock/lib/main/lockDetail/lcokSet/lockSet/lockSet_page.dart +++ b/star_lock/lib/main/lockDetail/lcokSet/lockSet/lockSet_page.dart @@ -1,4 +1,3 @@ -import 'dart:async'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -421,14 +420,20 @@ class _LockSetPageState extends State with RouteAware { () => Visibility( visible: state.lockFeature.value.wifi == 1 ? true : false, - child: CommonItem( + child: + CommonItem( leftTitel: TranslationLoader.lanKeys!.wifiDistributionNetwork!.tr, rightTitle: "", isHaveLine: true, isHaveDirection: true, action: () { - Get.toNamed(Routers.configuringWifiPage); - })), + Get.toNamed(Routers.configuringWifiPage, + arguments: { + 'lockSetInfoData': + state.lockSetInfoData.value + }); + }) + ), ), // Obx(() => // 锁时间 diff --git a/star_lock/lib/main/lockDetail/lcokSet/msgNotification/msgNotification_page.dart b/star_lock/lib/main/lockDetail/lcokSet/msgNotification/msgNotification_page.dart index de53e6b6..e65d973c 100644 --- a/star_lock/lib/main/lockDetail/lcokSet/msgNotification/msgNotification_page.dart +++ b/star_lock/lib/main/lockDetail/lcokSet/msgNotification/msgNotification_page.dart @@ -81,16 +81,16 @@ class _MsgNotificationPageState extends State { Get.toNamed(Routers.nDaysUnopenedPage); }, ), - SizedBox( - height: 20.h, - ), - Obx(() => CommonItem( - leftTitel: '离家开门', - rightTitle: "", - isHaveLine: false, - isHaveRightWidget: true, - rightWidget: - SizedBox(width: 60.w, height: 50.h, child: _switch(1)))), + // SizedBox( + // height: 20.h, + // ), + // Obx(() => CommonItem( + // leftTitel: '离家开门', + // rightTitle: "", + // isHaveLine: false, + // isHaveRightWidget: true, + // rightWidget: + // SizedBox(width: 60.w, height: 50.h, child: _switch(1)))), SizedBox( height: 20.h, ), diff --git a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart index ef19d95a..7d8f8e8d 100644 --- a/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart +++ b/star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart @@ -72,7 +72,10 @@ class _LockDetailPageState extends State height: 1.sh - ScreenUtil().statusBarHeight * 2, color: Colors.white, child: Column( - children: [topWidget(), Expanded(child: bottomWidget())], + children: [ + topWidget(), + Expanded(child: bottomWidget()) + ], ), ); } @@ -114,7 +117,7 @@ class _LockDetailPageState extends State Stack( alignment: Alignment.center, children: [ - Container( + SizedBox( width: 1.sw - 120.w * 2, child: Center( child: Text( @@ -124,22 +127,15 @@ class _LockDetailPageState extends State ))), Positioned( child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Text( - "100%", - style: TextStyle( - fontSize: 18.sp, color: AppColors.darkGrayTextColor), - ), - SizedBox(width: 2.w), - Image.asset( - 'images/main/icon_main_cell.png', - width: 30.w, - height: 24.w, - ), - SizedBox(width: 30.w), - ], - )) + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text("100%", style: TextStyle(fontSize: 18.sp, color: AppColors.darkGrayTextColor)), + SizedBox(width: 2.w), + Image.asset('images/main/icon_main_cell.png', width: 30.w, height: 24.w), + SizedBox(width: 30.w), + ], + ) + ) ], ), SizedBox(height: 30.h), @@ -383,7 +379,10 @@ class _LockDetailPageState extends State bottomItem('images/main/icon_catEyes.png', '监控', () { // Navigator.pushNamed(context, Routers.otherTypeKeyListPage, // arguments: 1); - Toast.show(msg: "功能暂未开放"); + // Toast.show(msg: "功能暂未开放"); + Get.toNamed(Routers.lockMonitoringPage, arguments: { + "lockId": widget.lockListInfoItemEntity.lockId + }); }), ); } @@ -402,11 +401,12 @@ class _LockDetailPageState extends State arguments: {"keyInfo": widget.lockListInfoItemEntity}); }), // 视频日志 - bottomItem('images/main/icon_main_set.png', "视频日志", () { + bottomItem('images/main/icon_lockDetail_videoLog.png', "视频日志", () { //视频日志 + Get.toNamed(Routers.videoLogPage); }), // 消息提醒 - bottomItem('images/main/icon_main_set.png', "消息提醒", () { + bottomItem('images/main/icon_lockDetail_messageReminding.png', "消息提醒", () { Get.toNamed(Routers.msgNotificationPage); }), // 设置 diff --git a/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_logic.dart b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_logic.dart new file mode 100644 index 00000000..4ddd39ef --- /dev/null +++ b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_logic.dart @@ -0,0 +1,9 @@ + +import '../../../../tools/baseGetXController.dart'; +import 'lockMonitoring_state.dart'; + +class LockMonitoringLogic extends BaseGetXController { + final LockMonitoringState state = LockMonitoringState(); + + +} \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart new file mode 100644 index 00000000..c4cfd9c6 --- /dev/null +++ b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_page.dart @@ -0,0 +1,170 @@ + +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; + +import '../../../../appRouters.dart'; +import '../../../../app_settings/app_colors.dart'; +import 'lockMonitoring_logic.dart'; + + +class LockMonitoringPage extends StatefulWidget { + const LockMonitoringPage({Key? key}) : super(key: key); + + @override + State createState() => _LockMonitoringPageState(); +} + +class _LockMonitoringPageState extends State { + final logic = Get.put(LockMonitoringLogic()); + final state = Get.find().state; + + @override + Widget build(BuildContext context) { + return Container( + width: 1.sw, + height: 1.sh, + color: Colors.white, + child: Column( + children: [ + Stack( + // alignment: Alignment.bottomCenter, + children: [ + Image.asset("images/icon_test20231113.png", width: 1.sw, height: 1.sh, fit: BoxFit.cover), + Positioned( + top: ScreenUtil().statusBarHeight + 30.h, + child: Row( + children: [ + SizedBox(width: 30.w), + GestureDetector( + onTap: () { + Get.back(); + }, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(30.h) + ), + padding: EdgeInsets.all(10.w), + child: Image(width: 40.w, height: 40.w, image: const AssetImage("images/icon_left_black.png"),), + ), + ), + ]), + ), + Positioned( + bottom: 10.w, + child: Container( + width: 1.sw - 30.w*2, + // height: 300.h, + margin: EdgeInsets.all(30.w), + decoration: BoxDecoration( + color: const Color(0xC83C3F41), + borderRadius: BorderRadius.circular(20.h) + ), + child: Column( + children: [ + SizedBox(height: 20.h), + bottomTopBtnWidget(), + SizedBox(height: 20.h), + bottomBottomBtnWidget(), + SizedBox(height: 20.h), + ], + ), + )) + ], + ), + ], + ), + ); + } + + Widget bottomTopBtnWidget(){ + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // 打开关闭声音 + GestureDetector( + onTap: () { + state.isOpenVoice.value = !state.isOpenVoice.value; + }, + child: Container( + width: 50.w, + height: 50.w, + padding: EdgeInsets.all(5.w), + child: Obx(() => Image( + width: 40.w, + height: 40.w, + image: state.isOpenVoice.value + ? const AssetImage("images/main/icon_lockDetail_monitoringCloseVoice.png") + : const AssetImage("images/main/icon_lockDetail_monitoringOpenVoice.png") + )), + ), + ), + SizedBox(width: 60.w), + // 截图 + GestureDetector( + onTap: () { + // Get.toNamed(Routers.monitoringRealTimeScreenPage); + }, + child: Container( + width: 50.w, + height: 50.w, + padding: EdgeInsets.all(5.w), + child: Image(width: 40.w, height: 40.w, image: const AssetImage("images/main/icon_lockDetail_monitoringScreenshot.png")), + ), + ), + SizedBox(width: 60.w), + // 录制 + GestureDetector( + onTap: () { + // Get.toNamed(Routers.monitoringRealTimeScreenPage); + }, + child: Container( + width: 50.w, + height: 50.w, + padding: EdgeInsets.all(5.w), + child: Image(width: 40.w, height: 40.w, image: const AssetImage("images/main/icon_lockDetail_monitoringScreenRecording.png")), + ), + ), + ]); + } + + Widget bottomBottomBtnWidget(){ + return Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + bottomBtnItemWidget("images/main/icon_lockDetail_monitoringTalkback.png", "点击对讲", Colors.white,(){ + + }), + bottomBtnItemWidget("images/main/icon_lockDetail_monitoringUnlock.png", "长按开锁", AppColors.mainColor,(){ + + }) + ]); + } + + Widget bottomBtnItemWidget(String iconUrl, String name, Color backgroundColor, Function() onClick) { + var wh = 80.w; + return GestureDetector( + onTap: onClick, + child: SizedBox( + height: 140.h, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: wh, + height: wh, + decoration: BoxDecoration( + color: backgroundColor, + borderRadius: BorderRadius.circular((wh+ 10.w*2)/2) + ), + padding: EdgeInsets.all(20.w), + child: Image.asset(iconUrl, fit: BoxFit.fitWidth), + ), + SizedBox(height: 20.w), + Expanded(child: Text(name, style: TextStyle(fontSize: 20.sp, color: Colors.white), textAlign: TextAlign.center)) + ], + )), + ); + } +} diff --git a/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_state.dart b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_state.dart new file mode 100644 index 00000000..991d59bf --- /dev/null +++ b/star_lock/lib/main/lockDetail/monitoring/monitoring/lockMonitoring_state.dart @@ -0,0 +1,7 @@ + +import 'package:get/get.dart'; + +class LockMonitoringState { + var isOpenVoice = false.obs; + +} \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/monitoring/monitoringRealTimeScreen/monitoringRealTimeScreen_logic.dart b/star_lock/lib/main/lockDetail/monitoring/monitoringRealTimeScreen/monitoringRealTimeScreen_logic.dart new file mode 100644 index 00000000..954a497a --- /dev/null +++ b/star_lock/lib/main/lockDetail/monitoring/monitoringRealTimeScreen/monitoringRealTimeScreen_logic.dart @@ -0,0 +1,8 @@ + +import 'package:star_lock/tools/baseGetXController.dart'; +import 'monitoringRealTimeScreen_state.dart'; + +class MonitoringRealTimeScreenLogic extends BaseGetXController{ + MonitoringRealTimeScreenState state = MonitoringRealTimeScreenState(); + +} \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/monitoring/monitoringRealTimeScreen/monitoringRealTimeScreen_page.dart b/star_lock/lib/main/lockDetail/monitoring/monitoringRealTimeScreen/monitoringRealTimeScreen_page.dart new file mode 100644 index 00000000..5a27981c --- /dev/null +++ b/star_lock/lib/main/lockDetail/monitoring/monitoringRealTimeScreen/monitoringRealTimeScreen_page.dart @@ -0,0 +1,142 @@ + +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; + +import '../../../../app_settings/app_colors.dart'; +import '../../../../tools/titleAppBar.dart'; +import 'monitoringRealTimeScreen_logic.dart'; + +class MonitoringRealTimeScreenPage extends StatefulWidget { + const MonitoringRealTimeScreenPage({Key? key}) : super(key: key); + + @override + State createState() => _MonitoringRealTimeScreenPageState(); +} + +class _MonitoringRealTimeScreenPageState extends State { + final logic = Get.put(MonitoringRealTimeScreenLogic()); + final state = Get.find().state; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColors.mainBackgroundColor, + appBar: TitleAppBar( + barTitle: "实时播放", + haveBack: true, + backgroundColor: AppColors.mainColor, + ), + body: Stack( + alignment: Alignment.bottomCenter, + children: [ + Column( + children: [ + Image.asset("images/icon_test20231113.png", width: 1.sw, height: 1.sw/5*4, fit: BoxFit.cover), + middleWidget(), + ], + ), + Positioned( + bottom: 60.h, + child: bottomBtnWidget() + ), + ], + ), + ); + } + + Widget middleWidget(){ + return Container( + color: Colors.grey, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + // 打开关闭声音 + GestureDetector( + onTap: () { + state.isOpenVoice.value = !state.isOpenVoice.value; + }, + child: Container( + width: 50.w, + height: 50.w, + padding: EdgeInsets.all(5.w), + child: Obx(() => Image( + width: 40.w, + height: 40.w, + image: state.isOpenVoice.value + ? const AssetImage("images/main/icon_lockDetail_monitoringCloseVoice.png") + : const AssetImage("images/main/icon_lockDetail_monitoringOpenVoice.png") + )), + ), + ), + // SizedBox(width: 60.w), + // 截图 + GestureDetector( + onTap: () { + + }, + child: Container( + width: 50.w, + height: 50.w, + padding: EdgeInsets.all(5.w), + child: Image(width: 40.w, height: 40.w, image: const AssetImage("images/main/icon_lockDetail_monitoringScreenshot.png")), + ), + ), + // SizedBox(width: 60.w), + // 录制 + GestureDetector( + onTap: () { + + }, + child: Container( + width: 50.w, + height: 50.w, + padding: EdgeInsets.all(5.w), + child: Image(width: 40.w, height: 40.w, image: const AssetImage("images/main/icon_lockDetail_monitoringScreenRecording.png")), + ), + ), + ]), + ); + } + + Widget bottomBtnWidget(){ + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + bottomBtnItemWidget("images/main/icon_lockDetail_monitoringTalkback.png", "点击对讲", Colors.white, (){ + + }), + SizedBox(width: (1.sw - 80.w)/3), + bottomBtnItemWidget("images/main/icon_lockDetail_monitoringUnlock.png", "长按开锁", AppColors.mainColor, (){ + + }) + ]); + } + + Widget bottomBtnItemWidget(String iconUrl, String name, Color backgroundColor, Function() onClick) { + var wh = 80.w; + return GestureDetector( + onTap: onClick, + child: SizedBox( + height: 140.h, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: wh, + height: wh, + decoration: BoxDecoration( + color: backgroundColor, + borderRadius: BorderRadius.circular((wh+ 10.w*2)/2) + ), + padding: EdgeInsets.all(20.w), + child: Image.asset(iconUrl, fit: BoxFit.fitWidth), + ), + SizedBox(height: 20.w), + Expanded(child: Text(name, style: TextStyle(fontSize: 20.sp, color: Colors.black), textAlign: TextAlign.center)) + ], + )), + ); + } + +} diff --git a/star_lock/lib/main/lockDetail/monitoring/monitoringRealTimeScreen/monitoringRealTimeScreen_state.dart b/star_lock/lib/main/lockDetail/monitoring/monitoringRealTimeScreen/monitoringRealTimeScreen_state.dart new file mode 100644 index 00000000..66a5461e --- /dev/null +++ b/star_lock/lib/main/lockDetail/monitoring/monitoringRealTimeScreen/monitoringRealTimeScreen_state.dart @@ -0,0 +1,7 @@ + +import 'package:get/get.dart'; + +class MonitoringRealTimeScreenState{ + var isOpenVoice = false.obs; + +} \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/videoLog/common/after_layout.dart b/star_lock/lib/main/lockDetail/videoLog/common/after_layout.dart new file mode 100644 index 00000000..343b6357 --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/common/after_layout.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; + +mixin AfterLayoutMixin on State { + @override + void initState() { + super.initState(); + WidgetsBinding.instance + .addPostFrameCallback((_) => afterFirstLayout(context)); + } + + void afterFirstLayout(BuildContext context); +} \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/videoLog/common/video/controller_widget.dart b/star_lock/lib/main/lockDetail/videoLog/common/video/controller_widget.dart new file mode 100644 index 00000000..d342986b --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/common/video/controller_widget.dart @@ -0,0 +1,33 @@ +import 'package:flutter/material.dart'; +import 'package:video_player/video_player.dart'; + +import 'video_player_control.dart'; + +class ControllerWidget extends InheritedWidget { + final String title; + final GlobalKey controlKey; + final Widget child; + final VideoPlayerController controller; + final bool videoInit; + + ControllerWidget( + {Key? key, + required this.controlKey, + required this.child, + required this.controller, + required this.videoInit, + required this.title + }) : super(key: key, child: child); + + //定义一个便捷方法,方便子树中的widget获取共享数据 + static ControllerWidget? of(BuildContext context) { + return context.dependOnInheritedWidgetOfExactType(); + } + + @override + bool updateShouldNotify(InheritedWidget oldWidget) { + // TODO: implement updateShouldNotify + return false; + } + +} \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/videoLog/common/video/video_player_UI.dart b/star_lock/lib/main/lockDetail/videoLog/common/video/video_player_UI.dart new file mode 100644 index 00000000..2b32e04d --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/common/video/video_player_UI.dart @@ -0,0 +1,209 @@ +import 'dart:io'; +import 'dart:ui'; +import 'package:flutter/material.dart'; +// import 'package:screen/screen.dart'; +import 'package:video_player/video_player.dart'; +import 'controller_widget.dart'; +import 'video_player_control.dart'; +import 'video_player_pan.dart'; + +enum VideoPlayerType { network, asset, file } + +class VideoPlayerUI extends StatefulWidget { + VideoPlayerUI.network({ + Key? key, + required String this.url, // 当前需要播放的地址 + required this.width, // 播放器尺寸(大于等于视频播放区域) + required this.height, + this.title = '', // 视频需要显示的标题 + }) : type = VideoPlayerType.network, + super(key: key); + + VideoPlayerUI.asset({ + Key? key, + required String dataSource, // 当前需要播放的地址 + this.width = double.infinity, // 播放器尺寸(大于等于视频播放区域) + this.height = double.infinity, + this.title = '', // 视频需要显示的标题 + }) : type = VideoPlayerType.asset, + url = dataSource, + super(key: key); + + const VideoPlayerUI.file({ + Key? key, + required File file, // 当前需要播放的地址 + this.width = double.infinity, // 播放器尺寸(大于等于视频播放区域) + this.height = double.infinity, + this.title = '', // 视频需要显示的标题 + }) : type = VideoPlayerType.file, + url = file, + super(key: key); + + final url; + final VideoPlayerType type; + final double width; + final double height; + final String title; + + @override + _VideoPlayerUIState createState() => _VideoPlayerUIState(); +} + +class _VideoPlayerUIState extends State { + final GlobalKey _key = + GlobalKey(); + + ///指示video资源是否加载完成,加载完成后会获得总时长和视频长宽比等信息 + bool _videoInit = false; + bool _videoError = false; + + late VideoPlayerController _controller; // video控件管理器 + + /// 记录是否全屏 + bool get _isFullScreen => + MediaQuery.of(context).orientation == Orientation.landscape; + + Size get _window => MediaQueryData.fromWindow(window).size; + + @override + void initState() { + super.initState(); + _urlChange(); // 初始进行一次url加载 + // Screen.keepOn(true); // 设置屏幕常亮 + } + + @override + void didUpdateWidget(VideoPlayerUI oldWidget) { + if (oldWidget.url != widget.url) { + _urlChange(); // url变化时重新执行一次url加载 + } + super.didUpdateWidget(oldWidget); + } + + @override + void dispose() async { + super.dispose(); + if (_controller != null) { + _controller.removeListener(_videoListener); + _controller.dispose(); + } + // Screen.keepOn(false); + } + + @override + Widget build(BuildContext context) { + return SafeArea( + top: !_isFullScreen, + bottom: !_isFullScreen, + left: !_isFullScreen, + right: !_isFullScreen, + child: Container( + width: _isFullScreen ? _window.width : widget.width, + height: _isFullScreen ? _window.height : widget.height, + child: _isHadUrl(), + ), + ); + } + +// 判断是否有url + Widget _isHadUrl() { + if (widget.url != null) { + return ControllerWidget( + controlKey: _key, + controller: _controller, + videoInit: _videoInit, + title: widget.title, + child: VideoPlayerPan( + child: Container( + alignment: Alignment.center, + width: double.infinity, + height: double.infinity, + color: Colors.black, + child: _isVideoInit(), + ), + ), + ); + } else { + return Center( + child: Text( + '暂无视频信息', + style: TextStyle(color: Colors.white), + ), + ); + } + } + +// 加载url成功时,根据视频比例渲染播放器 + Widget _isVideoInit() { + if (_videoInit) { + return AspectRatio( + aspectRatio: _controller.value.aspectRatio, + child: VideoPlayer(_controller), + ); + } else if (_controller != null && _videoError) { + return Text( + '加载出错', + style: TextStyle(color: Colors.white), + ); + } else { + return SizedBox( + width: 30, + height: 30, + child: CircularProgressIndicator( + strokeWidth: 2, + ), + ); + } + } + + void _urlChange() async { + if (widget.url == null || widget.url == '') return; + if (_controller != null) { + /// 如果控制器存在,清理掉重新创建 + _controller.removeListener(_videoListener); + _controller.dispose(); + } + setState(() { + /// 重置组件参数 + _videoInit = false; + _videoError = false; + }); + if (widget.type == VideoPlayerType.file) { + _controller = VideoPlayerController.file(widget.url); + } else if (widget.type == VideoPlayerType.asset) { + _controller = VideoPlayerController.asset(widget.url); + } else { + _controller = VideoPlayerController.network(widget.url); + } + + /// 加载资源完成时,监听播放进度,并且标记_videoInit=true加载完成 + _controller.addListener(_videoListener); + await _controller.initialize(); + setState(() { + _videoInit = true; + _videoError = false; + _controller.play(); + }); + } + + void _videoListener() async { + if (_controller.value.hasError) { + setState(() { + _videoError = true; + }); + } else { + Duration? res = await _controller.position; + if (res! >= _controller.value.duration) { + await _controller.seekTo(Duration(seconds: 0)); + await _controller.pause(); + } + if (_controller.value.isPlaying && _key.currentState != null) { + /// 减少build次数 + _key.currentState!.setPosition( + position: res, + totalDuration: _controller.value.duration, + ); + } + } + } +} diff --git a/star_lock/lib/main/lockDetail/videoLog/common/video/video_player_control.dart b/star_lock/lib/main/lockDetail/videoLog/common/video/video_player_control.dart new file mode 100644 index 00000000..94cb335b --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/common/video/video_player_control.dart @@ -0,0 +1,273 @@ +import 'dart:async'; + +import 'package:auto_orientation/auto_orientation.dart'; +import 'package:common_utils/common_utils.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:video_player/video_player.dart'; + +import 'controller_widget.dart'; +import 'video_player_slider.dart'; + +class VideoPlayerControl extends StatefulWidget { + VideoPlayerControl({ + Key? key, + }) : super(key: key); + + @override + VideoPlayerControlState createState() => VideoPlayerControlState(); +} + +class VideoPlayerControlState extends State { + VideoPlayerController get controller => ControllerWidget.of(context)!.controller; + bool get videoInit => ControllerWidget.of(context)!.videoInit; + String get title=>ControllerWidget.of(context)!.title; + // 记录video播放进度 + Duration _position = Duration(seconds: 0); + Duration _totalDuration = Duration(seconds: 0); + late Timer _timer; // 计时器,用于延迟隐藏控件ui + bool _hidePlayControl = true; // 控制是否隐藏控件ui + double _playControlOpacity = 0; // 通过透明度动画显示/隐藏控件ui + /// 记录是否全屏 + bool get _isFullScreen => + MediaQuery.of(context).orientation == Orientation.landscape; + + @override + void dispose() { + super.dispose(); + if (_timer != null) { + _timer.cancel(); + } + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onDoubleTap: _playOrPause, + onTap: _togglePlayControl, + child: Container( + width: double.infinity, + height: double.infinity, + color: Colors.transparent, + child: WillPopScope( + child: Offstage( + offstage: _hidePlayControl, + child: AnimatedOpacity( + // 加入透明度动画 + opacity: _playControlOpacity, + duration: Duration(milliseconds: 300), + child: Column( + children: [_top(), _middle(), _bottom(context)], + ), + ), + ), + onWillPop: _onWillPop, + ), + ), + ); + } + + // 拦截返回键 + Future _onWillPop() async { + if (_isFullScreen) { + _toggleFullScreen(); + return false; + } + return true; + } + + // 供父组件调用刷新页面,减少父组件的build + void setPosition({position, totalDuration}) { + setState(() { + _position = position; + _totalDuration = totalDuration; + }); + } + + Widget _bottom(BuildContext context) { + return Container( + // 底部控件的容器 + width: double.infinity, + height: 40, + decoration: BoxDecoration( + gradient: LinearGradient( + // 来点黑色到透明的渐变优雅一下 + begin: Alignment.bottomCenter, + end: Alignment.topCenter, + colors: [Color.fromRGBO(0, 0, 0, .7), Color.fromRGBO(0, 0, 0, .1)], + ), + ), + child: Row( + // 加载完成时才渲染,flex布局 + children: [ + IconButton( + // 播放按钮 + padding: EdgeInsets.zero, + iconSize: 26, + icon: Icon( + // 根据控制器动态变化播放图标还是暂停 + controller.value.isPlaying ? Icons.pause : Icons.play_arrow, + color: Colors.white, + ), + onPressed: _playOrPause, + ), + Expanded( + // 相当于前端的flex: 1 + child: VideoPlayerSlider( + startPlayControlTimer: _startPlayControlTimer, + timer: _timer, + ), + ), + Container( + // 播放时间 + margin: EdgeInsets.only(left: 10), + child: Text( + '${DateUtil.formatDateMs( + _position!.inMilliseconds, + format: 'mm:ss', + )}/${DateUtil.formatDateMs( + _totalDuration!.inMilliseconds, + format: 'mm:ss', + )}', + style: TextStyle(color: Colors.white), + ), + ), + IconButton( + // 全屏/横屏按钮 + padding: EdgeInsets.zero, + iconSize: 26, + icon: Icon( + // 根据当前屏幕方向切换图标 + _isFullScreen ? Icons.fullscreen_exit : Icons.fullscreen, + color: Colors.white, + ), + onPressed: () { + // 点击切换是否全屏 + _toggleFullScreen(); + }, + ), + ], + ), + ); + } + + Widget _middle() { + return Expanded( + child: Container(), + ); + } + + Widget _top() { + return Container( + width: double.infinity, + height: 40, + decoration: BoxDecoration( + gradient: LinearGradient( + // 来点黑色到透明的渐变优雅一下 + begin: Alignment.bottomCenter, + end: Alignment.topCenter, + colors: [Color.fromRGBO(0, 0, 0, .7), Color.fromRGBO(0, 0, 0, .1)], + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + //在最上层或者不是横屏则隐藏按钮 + ModalRoute.of(context)!.isFirst && !_isFullScreen + ? Container() + : IconButton( + icon: Icon( + Icons.arrow_back, + color: Colors.white, + ), + onPressed: backPress), + Text( + title, + style: TextStyle(color: Colors.white), + ), + //在最上层或者不是横屏则隐藏按钮 + ModalRoute.of(context)!.isFirst && !_isFullScreen + ? Container() + : IconButton( + icon: Icon( + Icons.arrow_back, + color: Colors.transparent, + ), + onPressed: () {}, + ), + ], + ), + ); + } + + void backPress() { + print(_isFullScreen); + // 如果是全屏,点击返回键则关闭全屏,如果不是,则系统返回键 + if (_isFullScreen) { + _toggleFullScreen(); + } else if(ModalRoute.of(context)!.isFirst) { + SystemNavigator.pop(); + }else{ + Navigator.pop(context); + } + } + + void _playOrPause() { + /// 同样的,点击动态播放或者暂停 + if (videoInit) { + controller.value.isPlaying ? controller.pause() : controller.play(); + _startPlayControlTimer(); // 操作控件后,重置延迟隐藏控件的timer + } + } + + void _togglePlayControl() { + setState(() { + if (_hidePlayControl) { + /// 如果隐藏则显示 + _hidePlayControl = false; + _playControlOpacity = 1; + _startPlayControlTimer(); // 开始计时器,计时后隐藏 + } else { + /// 如果显示就隐藏 + if (_timer != null) _timer.cancel(); // 有计时器先移除计时器 + _playControlOpacity = 0; + Future.delayed(Duration(milliseconds: 500)).whenComplete(() { + _hidePlayControl = true; // 延迟500ms(透明度动画结束)后,隐藏 + }); + } + }); + } + + void _startPlayControlTimer() { + /// 计时器,用法和前端js的大同小异 + if (_timer != null) _timer.cancel(); + _timer = Timer(Duration(seconds: 3), () { + /// 延迟3s后隐藏 + setState(() { + _playControlOpacity = 0; + Future.delayed(Duration(milliseconds: 500)).whenComplete(() { + _hidePlayControl = true; + }); + }); + }); + } + + void _toggleFullScreen() { + setState(() { + if (_isFullScreen) { + /// 如果是全屏就切换竖屏 + AutoOrientation.portraitAutoMode(); + + ///显示状态栏,与底部虚拟操作按钮 + SystemChrome.setEnabledSystemUIMode( + SystemUiMode.manual, overlays: [SystemUiOverlay.top, SystemUiOverlay.bottom]); + } else { + AutoOrientation.landscapeAutoMode(); + + ///关闭状态栏,与底部虚拟操作按钮 + SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); + } + _startPlayControlTimer(); // 操作完控件开始计时隐藏 + }); + } +} diff --git a/star_lock/lib/main/lockDetail/videoLog/common/video/video_player_pan.dart b/star_lock/lib/main/lockDetail/videoLog/common/video/video_player_pan.dart new file mode 100644 index 00000000..bbbb43c1 --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/common/video/video_player_pan.dart @@ -0,0 +1,246 @@ +import 'package:common_utils/common_utils.dart'; +import 'package:flutter/material.dart'; + +//import 'package:screen/screen.dart'; +import 'package:video_player/video_player.dart'; + +import '../after_layout.dart'; +import 'controller_widget.dart'; +import 'video_player_control.dart'; + +class VideoPlayerPan extends StatefulWidget { + VideoPlayerPan({ +// this.controlKey, + required this.child, + }); + +// final GlobalKey controlKey; + final Widget child; + + @override + _VideoPlayerPanState createState() => _VideoPlayerPanState(); +} + +class _VideoPlayerPanState extends State + with AfterLayoutMixin { + late Offset startPosition; // 起始位置 + late double movePan; // 偏移量累计总和 + late double layoutWidth; // 组件宽度 + late double layoutHeight; // 组件高度 + String volumePercentage = ''; // 组件位移描述 + double playDialogOpacity = 0.0; + bool allowHorizontal = false; // 是否允许快进 + Duration position = Duration(seconds: 0); // 当前时间 + double brightness = 0.0; //亮度 + bool brightnessOk = false; // 是否允许调节亮度 + + VideoPlayerController get controller => ControllerWidget.of(context)!.controller; + bool get videoInit => ControllerWidget.of(context)!.videoInit; + String get title=>ControllerWidget.of(context)!.title; + + @override + void afterFirstLayout(BuildContext context) { + _reset(context); + } + + @override + void dispose() { + super.dispose(); + brightnessOk = false; + allowHorizontal = false; + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onVerticalDragStart: _onVerticalDragStart, + onVerticalDragUpdate: _onVerticalDragUpdate, + onVerticalDragEnd: _onVerticalDragEnd, + onHorizontalDragStart: _onHorizontalDragStart, + onHorizontalDragUpdate: _onHorizontalDragUpdate, + onHorizontalDragEnd: _onHorizontalDragEnd, + child: Container( + child: Stack( + children: [ + widget.child, + Center( + child: AnimatedOpacity( + opacity: playDialogOpacity, + duration: Duration(milliseconds: 500), + child: Container( + padding: EdgeInsets.symmetric(vertical: 5.0, horizontal: 6.0), + decoration: BoxDecoration( + color: Colors.black87, + borderRadius: BorderRadius.all(Radius.circular(5.0))), + child: Text( + volumePercentage, + style: TextStyle(color: Colors.white, fontSize: 12), + ), + ), + ), + ), + VideoPlayerControl( + key: ControllerWidget.of(context)!.controlKey, + ) + ], + ), + ), + ); + } + + void _onVerticalDragStart(details) async { + _reset(context); + startPosition = details.globalPosition; + if (startPosition.dx < (layoutWidth / 2)) { + /// 左边触摸 + // brightness = await Screen.brightness; + brightnessOk = true; + } + } + + void _onVerticalDragUpdate(details) { + if (!videoInit) { + return; + } + + /// 累计计算偏移量(下滑减少百分比,上滑增加百分比) + movePan += (-details.delta.dy); + if (startPosition.dx < (layoutWidth / 2)) { + /// 左边触摸 + if (brightnessOk = true) { + setState(() { + volumePercentage = '亮度:${(_setBrightnessValue() * 100).toInt()}%'; + playDialogOpacity = 1.0; + }); + } + } else { + /// 右边触摸 + setState(() { + volumePercentage = '音量:${(_setVerticalValue(num: 2) * 100).toInt()}%'; + playDialogOpacity = 1.0; + }); + } + } + + void _onVerticalDragEnd(_) async { + if (!videoInit) { + return; + } + if (startPosition.dx < (layoutWidth / 2)) { + if (brightnessOk) { + // await Screen.setBrightness(_setBrightnessValue()); + brightnessOk = false; + // 左边触摸 + setState(() { + playDialogOpacity = 0.0; + }); + } + } else { + // 右边触摸 + await controller.setVolume(_setVerticalValue()); + setState(() { + playDialogOpacity = 0.0; + }); + } + } + + double _setBrightnessValue() { + // 亮度百分控制 + double value = + double.parse((movePan / layoutHeight + brightness).toStringAsFixed(2)); + if (value >= 1.00) { + value = 1.00; + } else if (value <= 0.00) { + value = 0.00; + } + return value; + } + + double _setVerticalValue({int num = 1}) { + // 声音亮度百分控制 + double value = double.parse( + (movePan / layoutHeight + controller.value.volume) + .toStringAsFixed(num)); + if (value >= 1.0) { + value = 1.0; + } else if (value <= 0.0) { + value = 0.0; + } + return value; + } + + void _reset(BuildContext context) { + startPosition = Offset(0, 0); + movePan = 0; + layoutHeight = context.size!.height; + layoutWidth = context.size!.width; + volumePercentage = ''; + } + + void _onHorizontalDragStart(DragStartDetails details) async { + _reset(context); + if (!videoInit) { + return; + } + // 获取当前时间 + position = controller.value.position; + // 暂停成功后才允许快进手势 + allowHorizontal = true; + } + + void _onHorizontalDragUpdate(DragUpdateDetails details) { + if (!videoInit && !allowHorizontal) { + return; + } + // 累计计算偏移量 + movePan += details.delta.dx; + double value = _setHorizontalValue(); + // 用百分比计算出当前的秒数 + String currentSecond = DateUtil.formatDateMs( + (value * controller.value.duration.inMilliseconds).toInt(), + format: 'mm:ss', + ); + if (value >= 0) { + setState(() { + volumePercentage = '快进至:$currentSecond'; + playDialogOpacity = 1.0; + }); + } else { + setState(() { + volumePercentage = '快退至:${(value * 100).toInt()}%'; + playDialogOpacity = 1.0; + }); + } + } + + void _onHorizontalDragEnd(DragEndDetails details) async { + if (!videoInit && !allowHorizontal) { + return; + } + double value = _setHorizontalValue(); + int current = + (value * controller.value.duration.inMilliseconds).toInt(); + await controller.seekTo(Duration(milliseconds: current)); + allowHorizontal = false; + setState(() { + playDialogOpacity = 0.0; + }); + } + + double _setHorizontalValue() { + // 进度条百分控制 + double valueHorizontal = + double.parse((movePan / layoutWidth).toStringAsFixed(2)); + // 当前进度条百分比 + double currentValue = position.inMilliseconds / + controller.value.duration.inMilliseconds; + double value = + double.parse((currentValue + valueHorizontal).toStringAsFixed(2)); + if (value >= 1.00) { + value = 1.00; + } else if (value <= 0.00) { + value = 0.00; + } + return value; + } +} diff --git a/star_lock/lib/main/lockDetail/videoLog/common/video/video_player_slider.dart b/star_lock/lib/main/lockDetail/videoLog/common/video/video_player_slider.dart new file mode 100644 index 00000000..190abe6b --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/common/video/video_player_slider.dart @@ -0,0 +1,131 @@ +import 'dart:async'; + +import 'package:common_utils/common_utils.dart'; +import 'package:flutter/material.dart'; +import 'package:video_player/video_player.dart'; + +import 'controller_widget.dart'; + +class VideoPlayerSlider extends StatefulWidget { + final Function startPlayControlTimer; + final Timer timer; + + VideoPlayerSlider({required this.startPlayControlTimer, required this.timer}); + + @override + _VideoPlayerSliderState createState() => _VideoPlayerSliderState(); +} + +class _VideoPlayerSliderState extends State { + VideoPlayerController get controller => + ControllerWidget.of(context)!.controller; + + bool get videoInit => ControllerWidget.of(context)!.videoInit; + late double progressValue; //进度 + late String labelProgress; //tip内容 + bool handle = false; //判断是否在滑动的标识 + + @override + void initState() { + super.initState(); + progressValue = 0.0; + labelProgress = '00:00'; + } + + @override + void didUpdateWidget(VideoPlayerSlider oldWidget) { + super.didUpdateWidget(oldWidget); + if (!handle && videoInit) { + int position = controller.value.position.inMilliseconds; + int duration = controller.value.duration.inMilliseconds; + if(position>=duration){ + position=duration; + } + setState(() { + progressValue = position / duration * 100; + labelProgress = DateUtil.formatDateMs( + progressValue.toInt(), + format: 'mm:ss', + ); + }); + } + } + + @override + Widget build(BuildContext context) { + return SliderTheme( + //自定义风格 + data: SliderTheme.of(context).copyWith( + //进度条滑块左边颜色 + inactiveTrackColor: Colors.white, + overlayShape: RoundSliderOverlayShape( + //可继承SliderComponentShape自定义形状 + overlayRadius: 10, //滑块外圈大小 + ), + thumbShape: RoundSliderThumbShape( + //可继承SliderComponentShape自定义形状 + disabledThumbRadius: 7, //禁用是滑块大小 + enabledThumbRadius: 7, //滑块大小 + ), + ), + child: Slider( + value: progressValue, + label: labelProgress, + divisions: 100, + onChangeStart: _onChangeStart, + onChangeEnd: _onChangeEnd, + onChanged: _onChanged, + min: 0, + max: 100, + ), + ); + } + + void _onChangeEnd(_) { + if (!videoInit) { + return; + } + widget.startPlayControlTimer(); + // 关闭手动操作标识 + handle = false; + // 跳转到滑动时间 + int duration = controller.value.duration.inMilliseconds; + controller.seekTo( + Duration(milliseconds: (progressValue / 100 * duration).toInt()), + ); +// if (!controller.value.isPlaying) { +// controller.play(); +// } + } + + void _onChangeStart(_) { + if (!videoInit) { + return; + } + if (widget.timer != null) { + widget.timer.cancel(); + } + // 开始手动操作标识 + handle = true; +// if (controller.value.isPlaying) { +// controller.pause(); +// } + } + + void _onChanged(double value) { + if (!videoInit) { + return; + } + if (widget.timer != null) { + widget.timer.cancel(); + } + int duration = controller.value.duration.inMilliseconds; + setState(() { + progressValue = value; + labelProgress = DateUtil.formatDateMs( + (value / 100 * duration).toInt(), + format: 'mm:ss', + ); + }); + } +} diff --git a/star_lock/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_logic.dart b/star_lock/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_logic.dart new file mode 100644 index 00000000..8d45d5c7 --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_logic.dart @@ -0,0 +1,8 @@ + +import 'package:star_lock/tools/baseGetXController.dart'; +import 'editVideoLog_state.dart'; + +class EditVideoLogLogic extends BaseGetXController{ + EditVideoLogState state = EditVideoLogState(); + +} \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart b/star_lock/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart new file mode 100644 index 00000000..3fb69069 --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart @@ -0,0 +1,162 @@ + +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; + +import '../../../../app_settings/app_colors.dart'; +import '../../../../tools/titleAppBar.dart'; +import 'editVideoLog_logic.dart'; + +class EditVideoLogPage extends StatefulWidget { + const EditVideoLogPage({Key? key}) : super(key: key); + + @override + State createState() => _EditVideoLogPageState(); +} + +class _EditVideoLogPageState extends State { + final logic = Get.put(EditVideoLogLogic()); + final state = Get.find().state; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: TitleAppBar( + barTitle: "已选${state.seletVideoLog.value}项", + haveBack: true, + backgroundColor: AppColors.mainColor, + actionsList: [ + TextButton( + child: Text( + "全选", + style: TextStyle(color: Colors.white, fontSize: 24.sp), + ), + onPressed: () async { + state.isSeletAll.value = !state.isSeletAll.value; + }, + ), + ], + ), + body: Column( + children: [ + Expanded( + child: ListView.builder( + itemCount: 5, + itemBuilder: (c, index) { + return Column(children: [ + Container( + margin: EdgeInsets.only(left:20.w, top: 15.w, bottom: 15.w), + child: Row( + children: [ + Text("2023.10.23", style: TextStyle(fontSize: 20.sp)), + ] + )), + mainListView(index) + ],); + }), + ), + bottomBottomBtnWidget() + ], + ), + ); + } + + var itemW = (1.sw - 15.w*4)/3; + var itemH = (1.sw - 15.w*4)/3+40.h; + Widget mainListView(int index){ + return Container( + // margin: EdgeInsets.only(left: 10.w, right: 10.w, top: 40.h), + // color: Colors.blue, + child: GridView.builder( + padding: EdgeInsets.only(left: 15.w, right: 15.w), + itemCount: index+1, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + //横轴元素个数 + crossAxisCount: 3, + //纵轴间距 + mainAxisSpacing: 10.w, + // 横轴间距 + crossAxisSpacing: 15.w, + //子组件宽高长度比例 + childAspectRatio: itemW/itemH + ), + itemBuilder: (context, index) { + return Obx(() => videoItem()); + }, + ), + ); + } + + Widget videoItem(){ + return SizedBox( + width: itemW, + height: itemH, + child: Stack( + children: [ + Column( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(10.w), + child: Image(width: itemW, height: itemW, fit: BoxFit.fill, image: const AssetImage("images/main/icon_lockDetail_monitoringvoiceFrist.png")), + ), + SizedBox(height:5.h), + Text("2023.10.23 10:00", style: TextStyle(fontSize: 20.sp)) + ], + ), + Visibility( + visible: true, + child: Positioned( + top: 0.w, + right: 0.w, + child: GestureDetector( + onTap: (){ + + }, + child: Image(width: 40.w, height: 40.w, image: state.isSeletAll.value ? const AssetImage("images/icon_round_selet.png") : const AssetImage("images/icon_round_unSelet.png")) + ) + ), + ) + ], + ), + ); + } + + Widget bottomBottomBtnWidget(){ + return Container( + width: 1.sw, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + bottomBtnItemWidget("images/main/icon_lockDetail_monitoringDownloadVideo.png", "下载", Colors.white,(){ + + }), + SizedBox(width:100.w), + bottomBtnItemWidget("images/main/icon_lockDetail_monitoringDeletVideo.png", "删除", AppColors.mainColor,(){ + + }) + ]), + ); + } + + Widget bottomBtnItemWidget(String iconUrl, String name, Color backgroundColor, Function() onClick) { + var wh = 40.w; + return GestureDetector( + onTap: onClick, + child: Container( + height: 140.h, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox(height: 30.w), + Image.asset(iconUrl, width: wh, height: wh, fit: BoxFit.fitWidth), + SizedBox(height: 10.w), + Expanded(child: Text(name, style: TextStyle(fontSize: 22.sp), textAlign: TextAlign.center)) + ], + )), + ); + } + +} diff --git a/star_lock/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_state.dart b/star_lock/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_state.dart new file mode 100644 index 00000000..a5f8f4f5 --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_state.dart @@ -0,0 +1,10 @@ + + +import 'package:get/get.dart'; + +class EditVideoLogState{ + + var seletVideoLog = 0.obs; + var isSeletAll = false.obs; + +} \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart b/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart new file mode 100644 index 00000000..c4ce560c --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart @@ -0,0 +1,8 @@ + +import 'package:star_lock/tools/baseGetXController.dart'; +import 'videoLog_state.dart'; + +class VideoLogLogic extends BaseGetXController{ + VideoLogState state = VideoLogState(); + +} \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart b/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart new file mode 100644 index 00000000..73ee4ad7 --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart @@ -0,0 +1,262 @@ + +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/tools/noData.dart'; + +import '../../../../app_settings/app_colors.dart'; +import '../../../../tools/titleAppBar.dart'; +import 'videoLog_logic.dart'; + +class VideoLogPage extends StatefulWidget { + const VideoLogPage({Key? key}) : super(key: key); + + @override + State createState() => _VideoLogPageState(); +} + +class _VideoLogPageState extends State { + final logic = Get.put(VideoLogLogic()); + final state = Get.find().state; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: TitleAppBar( + haveTitleWidget: true, + titleWidget: navBtn(), + haveBack: true, + backgroundColor: AppColors.mainColor, + ), + body: Column( + children: [ + // 云存顶部 + Visibility( + visible: !state.isNavLocal.value, + child: vipTip() + ), + // 本地顶部 + Visibility( + visible: state.isNavLocal.value, + child: localTip() + ), + // title加编辑按钮 + editVideoTip(), + Visibility( + visible: !state.isNavLocal.value, + child: Expanded( + child: ListView.builder( + itemCount: 5, + itemBuilder: (c, index) { + return Column(children: [ + Container( + margin: EdgeInsets.only(left:20.w, top: 15.w, bottom: 15.w), + child: Row( + children: [ + Text("2023.10.2$index", style: TextStyle(fontSize: 20.sp)), + ] + )), + mainListView(index) + ],); + }) + ) + ), + // 本地顶部 + Visibility( + visible: state.isNavLocal.value, + child: Expanded( + child: state.localList.isNotEmpty ? ListView.builder( + itemCount: 5, + itemBuilder: (c, index) { + return Column(children: [ + Container( + margin: EdgeInsets.only(left:20.w, top: 15.w, bottom: 15.w), + child: Row( + children: [ + Text("2023.10.2$index", style: TextStyle(fontSize: 20.sp)), + ] + )), + mainListView(index) + ],); + }): const NoData() + ) + ), + ], + ), + ); + } + + // nav按钮 + Widget navBtn(){ + return SizedBox( + width: 300.w, + // color: Colors.white, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TextButton( + onPressed: (){ + setState(() { + state.isNavLocal.value = false; + }); + }, + child: Obx(() => Text("云存", style: state.isNavLocal.value == true ? TextStyle(color: Colors.grey, fontSize: 26.sp) : TextStyle(color: Colors.white, fontSize: 28.sp))) + ), + TextButton( + onPressed: (){ + setState(() { + state.isNavLocal.value = true; + }); + }, + child: Obx(() => Text("本地", style: state.isNavLocal.value == true ? TextStyle(color: Colors.white, fontSize: 28.sp) : TextStyle(color: Colors.grey, fontSize: 26.sp))) + ), + ], + ), + ); + } + + // 云存顶部视频 + Widget vipTip(){ + return GestureDetector( + onTap: (){ + Get.toNamed(Routers.valueAddedServicesHighFunctionPage); + }, + child: Container( + height: 150.h, + margin: EdgeInsets.all(15.w), + padding: EdgeInsets.only(left:20.w, top:20.w, bottom:20.w, right: 10.w), + decoration: BoxDecoration( + color: const Color(0xFFF6F7F8), + borderRadius: BorderRadius.circular(20.h) + ), + child: Row( + children: [ + Expanded(child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("3天滚动储存", style: TextStyle(fontSize: 26.sp)), + SizedBox(height: 10.h), + Text("星锁已为本设备免费提供3大滚动视频储存服务", style: TextStyle(fontSize: 22.sp, color: Colors.grey)), + ], + )), + SizedBox(width: 15.w), + Text("去升级", style: TextStyle(fontSize: 24.sp)), + Image(width: 40.w, height: 24.w, image: const AssetImage("images/icon_right_black.png")) + ], + ), + ), + ); + } + + // 本地顶部 + Widget localTip(){ + return GestureDetector( + onTap: (){ + Get.toNamed(Routers.videoLogDownLoadPage); + }, + child: Container( + // height: 130.h, + margin: EdgeInsets.all(15.w), + padding: EdgeInsets.only(left:20.w, top:30.w, bottom:30.w, right: 10.w), + decoration: BoxDecoration( + color: const Color(0xFFF6F7F8), + borderRadius: BorderRadius.circular(20.h) + ), + child: Row( + children: [ + Expanded(child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // SizedBox(height: 20.h), + Text("下载列表", style: TextStyle(fontSize: 26.sp)), + SizedBox(height: 15.h), + Text("暂无下载内容", style: TextStyle(fontSize: 22.sp, color: Colors.grey)), + ], + )), + SizedBox(width: 15.w), + // Text("去升级", style: TextStyle(fontSize: 24.sp)), + Image(width: 40.w, height: 24.w, image: const AssetImage("images/icon_right_black.png")) + ], + ), + ), + ); + } + + // 标题加编辑按钮 + Widget editVideoTip(){ + return Container( + margin: EdgeInsets.only(left:20.w), + child: Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(state.isNavLocal.value == true ? "已下载":"全部视频", style: TextStyle(fontSize: 28.sp)), + Expanded(child: SizedBox(width: 10.w)), + IconButton( + icon: Image(width: 40.w, height: 40.w, image: const AssetImage("images/main/icon_lockDetail_monitoringEditVoice.png")), + iconSize: 30, + color: Colors.black54, onPressed: () { + Get.toNamed(Routers.editVideoLogPage); + }, + ) + // TextButton( + // onPressed: (){ + // + // }, + // child: Image(width: 40.w, height: 40.w, image: const AssetImage("images/main/icon_lockDetail_monitoringEditVoice.png"),) + // ), + ], + ), + ); + } + + var itemW = (1.sw - 15.w*4)/3; + var itemH = (1.sw - 15.w*4)/3+40.h; + + // 云存列表 + Widget mainListView(int index){ + return GridView.builder( + padding: EdgeInsets.only(left: 15.w, right: 15.w), + itemCount: index+1, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + //横轴元素个数 + crossAxisCount: 3, + //纵轴间距 + mainAxisSpacing: 15.w, + // 横轴间距 + crossAxisSpacing: 15.w, + //子组件宽高长度比例 + childAspectRatio: itemW/itemH + ), + itemBuilder: (context, index) { + return videoItem((){ + Get.toNamed(Routers.videoLogDetailPage); + }); + }, + ); + } + + Widget videoItem(Function() action){ + return GestureDetector( + onTap: action, + child: SizedBox( + width: itemW, + height: itemH, + child: Column( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(10.w), + child: Image(width: itemW, height: itemW, fit: BoxFit.fill, image: const AssetImage("images/main/icon_lockDetail_monitoringvoiceFrist.png")), + ), + SizedBox(height:5.h), + Text("2023.10.23 10:00", style: TextStyle(fontSize: 20.sp)) + ], + ), + ), + ); + } + +} diff --git a/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_state.dart b/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_state.dart new file mode 100644 index 00000000..a2c060ed --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_state.dart @@ -0,0 +1,8 @@ + +import 'package:get/get.dart'; + +class VideoLogState{ + + var isNavLocal = false.obs; + var localList = []; +} \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/controlsOverlay_page.dart b/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/controlsOverlay_page.dart new file mode 100644 index 00000000..f6a7d75d --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/controlsOverlay_page.dart @@ -0,0 +1,264 @@ + +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:video_player/video_player.dart'; + +class ControlsOverlay extends StatelessWidget { + const ControlsOverlay({required this.controller}); + + static const List _exampleCaptionOffsets = [ + Duration(seconds: -10), + Duration(seconds: -3), + Duration(seconds: -1, milliseconds: -500), + Duration(milliseconds: -250), + Duration.zero, + Duration(milliseconds: 250), + Duration(seconds: 1, milliseconds: 500), + Duration(seconds: 3), + Duration(seconds: 10), + ]; + static const List _examplePlaybackRates = [ + 0.25, + 0.5, + 1.0, + 1.5, + 2.0, + 3.0, + 5.0, + 10.0, + ]; + + final VideoPlayerController controller; + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + AnimatedSwitcher( + duration: const Duration(milliseconds: 50), + reverseDuration: const Duration(milliseconds: 200), + child: controller.value.isPlaying + ? const SizedBox.shrink() + : Container( + color: Colors.black26, + child: const Center( + child: + // CircularProgressIndicator() + Icon( + Icons.play_arrow, + color: Colors.white, + size: 60.0, + semanticLabel: 'Play', + ), + ), + ), + ), + GestureDetector( + onTap: () { + controller.value.isPlaying ? controller.pause() : controller.play(); + }, + ), + + // Align( + // alignment: Alignment.topLeft, + // child: PopupMenuButton( + // initialValue: controller.value.captionOffset, + // tooltip: 'Caption Offset', + // onSelected: (Duration delay) { + // controller.setCaptionOffset(delay); + // }, + // itemBuilder: (BuildContext context) { + // return >[ + // for (final Duration offsetDuration in _exampleCaptionOffsets) + // PopupMenuItem( + // value: offsetDuration, + // child: Text('${offsetDuration.inMilliseconds}ms'), + // ) + // ]; + // }, + // child: Padding( + // padding: const EdgeInsets.symmetric( + // // Using less vertical padding as the text is also longer + // // horizontally, so it feels like it would need more spacing + // // horizontally (matching the aspect ratio of the video). + // vertical: 12, + // horizontal: 16, + // ), + // child: Text('${controller.value.captionOffset.inMilliseconds}ms'), + // ), + // ), + // ), + // Align( + // alignment: Alignment.topRight, + // child: PopupMenuButton( + // initialValue: controller.value.playbackSpeed, + // tooltip: 'Playback speed', + // onSelected: (double speed) { + // controller.setPlaybackSpeed(speed); + // }, + // itemBuilder: (BuildContext context) { + // return >[ + // for (final double speed in _examplePlaybackRates) + // PopupMenuItem( + // value: speed, + // child: Text('${speed}x'), + // ) + // ]; + // }, + // child: Padding( + // padding: const EdgeInsets.symmetric( + // // Using less vertical padding as the text is also longer + // // horizontally, so it feels like it would need more spacing + // // horizontally (matching the aspect ratio of the video). + // vertical: 12, + // horizontal: 16, + // ), + // child: Text('${controller.value.playbackSpeed}x'), + // ), + // ), + // ), + + Positioned( + top: 0.h, + left: 0.h, + right: 0.h, + child: Container( + margin: EdgeInsets.only(left:20.w, right:20.w), + // color: const Color(0xC83C3F41), + child: Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("星锁 2023/10/23", style: TextStyle(color: Colors.white, fontSize: 20.sp)), + Expanded(child: SizedBox(width: 10.w)), + Container( + width: 50.w, + height: 50.w, + padding: EdgeInsets.all(10.w), + child: Image(width: 50.w, height: 50.w, image: const AssetImage("images/main/icon_lockDetail_monitoringShareVideo_white.png")), + ), + SizedBox(width: 20.w), + Container( + width: 50.w, + height: 50.w, + padding: EdgeInsets.all(10.w), + child: Image(width: 50.w, height: 50.w, image: const AssetImage("images/main/icon_lockDetail_monitoringDownloadVideo_white.png")), + ), + SizedBox(width: 20.w), + Container( + width: 50.w, + height: 50.w, + padding: EdgeInsets.all(10.w), + child: Image(width: 50.w, height: 50.w, image: const AssetImage("images/main/icon_lockDetail_monitoringDeletVideo_white.png")), + ), + ], + ), + ), + ), + + Positioned( + bottom: 0, + left: 0, + right: 0, + child: Container( + padding: EdgeInsets.only(right: 10.w, left: 10.w), + color: const Color.fromRGBO(0, 0, 0, 0.5), + height: 60.h, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + //暂停按钮 + InkWell( + child: controller.value.isPlaying ? const Icon(Icons.pause, size: 30, color: Color(0xffefefef)) : const Icon(Icons.play_arrow, size: 30, color: Color(0xffefefef)), + onTap: () { + // if(controller.value.isBuffering == false){ + // return; + // } + controller.value.isPlaying ? controller.pause() : controller.play(); + }, + ), + //当前播放进度 + Text(formatString(controller.value.position), style: TextStyle(fontSize: 22.sp, color: const Color(0xffefefef)),), + //进度条 + Expanded( + + child: Slider(activeColor: const Color(0xFFFFFFFF), max: controller.value.duration.inMilliseconds.truncateToDouble(), + value: controller.value.position.inMilliseconds.truncateToDouble(), + onChanged: (newRating) { + controller + .seekTo(Duration( + milliseconds: + newRating + .truncate())); + }, + ), + ), + //总视频进度 + Text(formatString(controller.value.duration), style: TextStyle(fontSize: 22.sp, color: const Color(0xffefefef)),), + //倍速下拉菜单 + // DropdownButtonHideUnderline( + // child: DropdownButton2( + // hint: Text( + // _selectedValue, + // style: TextStyle( + // fontSize: 18, + // color: + // Color(0xffefefef), + // ), + // ), + // items: items + // .map((item) => + // DropdownMenuItem< + // String>( + // value: item, + // child: Text( + // '${item}x', + // style: + // const TextStyle( + // fontSize: + // 16, + // ), + // ), + // )) + // .toList(), + // // value: _selectedValue, + // // icon: Visibility( + // // visible: false, + // // child: Icon(Icons + // // .arrow_downward)), + // onChanged: (value) async { + // double val = + // double.parse(value + // as String); + // _videoPlayerController + // .setPlaybackSpeed(val); + // setState(() { + // if (val == 1.0) { + // _selectedValue = + // '倍速'; + // } else { + // _selectedValue = + // '${value as String}x'; + // } + // }); + // }, + // // dropdownWidth: 100, + // // buttonWidth: 60, + // // iconSize: 36, + // // iconEnabledColor:Colors.white, + // // buttonPadding:const EdgeInsets.only(left: 10), + // ), + // ), + ], + ), + ), + ) + ], + ); + } + + String formatString(time) { + var shortName = time.toString().substring(2, 7); + return shortName; + } +} \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_logic.dart b/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_logic.dart new file mode 100644 index 00000000..42374bb1 --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_logic.dart @@ -0,0 +1,10 @@ + +import 'package:star_lock/tools/baseGetXController.dart'; + +import 'videoLogDetail_state.dart'; + +class VideoLogDetailLogic extends BaseGetXController{ + VideoLogDetailState state = VideoLogDetailState(); + + +} \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart b/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart new file mode 100644 index 00000000..8ddc5a56 --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart @@ -0,0 +1,191 @@ + +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; + +import '../../../../app_settings/app_colors.dart'; +import '../../../../tools/titleAppBar.dart'; +import 'controlsOverlay_page.dart'; +import 'videoLogDetail_logic.dart'; +import 'package:video_player/video_player.dart'; + +class VideoLogDetailPage extends StatefulWidget { + const VideoLogDetailPage({Key? key}) : super(key: key); + + @override + State createState() => _VideoLogDetailPageState(); +} + +class _VideoLogDetailPageState extends State { + final logic = Get.put(VideoLogDetailLogic()); + final state = Get.find().state; + + late VideoPlayerController _controller; + + // Future _loadCaptions() async { + // final String fileContents = await DefaultAssetBundle.of(context) + // .loadString('images/bumble_bee_captions.vtt'); + // return WebVTTCaptionFile( + // fileContents); // For vtt files, use WebVTTCaptionFile + // } + + @override + void initState() { + super.initState(); + _controller = VideoPlayerController.networkUrl( + Uri.parse('https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4'), + // closedCaptionFile: _loadCaptions(), + // videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true), + ); + + _controller.addListener(() { + setState(() { + print("controller.value.isBuffering:${_controller.value.isBuffering}"); + }); + }); + + _controller.setLooping(false); + // _controller.setVolume(1); + _controller.initialize(); + + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: TitleAppBar( + barTitle: "本地视频播放", + haveBack: true, + backgroundColor: AppColors.mainColor, + ), + body: Column( + children: [ + AspectRatio( + aspectRatio: 16/9, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + VideoPlayer(_controller), + // ClosedCaption(text: _controller.value.caption.text), + ControlsOverlay(controller: _controller), + (_controller.value.isPlaying || _controller.value.isBuffering) ? Container() : VideoProgressIndicator(_controller, colors:VideoProgressColors(playedColor:AppColors.mainColor), allowScrubbing: true), + ], + ), + ), + Container( + margin: EdgeInsets.only(left:20.w, top: 15.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + children: [ + Text("2023.10.23", style: TextStyle(fontSize: 20.sp)), + ], + ), + SizedBox(height: 15.h), + Row( + children: [ + videoItem(true), + ], + ), + ], + )), + Expanded( + child: ListView.builder( + itemCount: 4, + itemBuilder: (c, index) { + return Column(children: [ + Container( + margin: EdgeInsets.only(left:20.w, top: 15.w, bottom: 15.w), + child: Row( + children: [ + Text("2023.10.23", style: TextStyle(fontSize: 20.sp)), + ] + )), + mainListView() + ],); + }), + ), + ], + ), + ); + } + + + var itemW = (1.sw - 15.w*4)/3; + var itemH = (1.sw - 15.w*4)/3+40.h; + Widget mainListView(){ + return GridView.builder( + padding: EdgeInsets.only(left: 15.w, right: 15.w), + itemCount: 4, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + //横轴元素个数 + crossAxisCount: 3, + //纵轴间距 + mainAxisSpacing: 10.w, + // 横轴间距 + crossAxisSpacing: 15.w, + //子组件宽高长度比例 + childAspectRatio: itemW/itemH + ), + itemBuilder: (context, index) { + return videoItem(false); + }, + ); + } + + Widget videoItem(bool isPlay){ + return SizedBox( + width: itemW, + height: itemH, + child: Stack( + children: [ + Column( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(10.w), + child: Stack( + children: [ + Image(width: itemW, height: itemW, fit: BoxFit.fill, image: const AssetImage("images/main/icon_lockDetail_monitoringvoiceFrist.png")), + Positioned( + left: 8.w, + bottom: 5.h, + child: Text("00:06", style: TextStyle(color: Colors.white, fontSize: 20.sp)) + ), + Visibility( + visible: isPlay, + child: Positioned( + left: 0, + right: 0, + top: 0, + bottom: 0, + child: Container( + // padding: EdgeInsets.only(right: 10.w, left: 10.w), + color: const Color.fromRGBO(0, 0, 0, 0.3), + child: Center(child: Text("播放中", style: TextStyle(color: Colors.white, fontSize: 22.sp))), + ) + ), + ) + ] + ), + ), + SizedBox(height:5.h), + Text("2023.10.23 10:00", style: TextStyle(fontSize: 20.sp)) + ], + ), + ], + ), + ); + } + + @override + void dispose() { + super.dispose(); + _controller.dispose(); + } + +} diff --git a/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_state.dart b/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_state.dart new file mode 100644 index 00000000..b4240f09 --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_state.dart @@ -0,0 +1,5 @@ + + +class VideoLogDetailState{ + +} \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/videoLog/videoLogDownLoad/videoLogDownLoad_logic.dart b/star_lock/lib/main/lockDetail/videoLog/videoLogDownLoad/videoLogDownLoad_logic.dart new file mode 100644 index 00000000..5d8b977e --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/videoLogDownLoad/videoLogDownLoad_logic.dart @@ -0,0 +1,9 @@ + +import 'package:star_lock/tools/baseGetXController.dart'; +import 'videoLogDownLoad_state.dart'; + +class VideoLogDownLoadLogic extends BaseGetXController{ + VideoLogDownLoadState state = VideoLogDownLoadState(); + + +} \ No newline at end of file diff --git a/star_lock/lib/main/lockDetail/videoLog/videoLogDownLoad/videoLogDownLoad_page.dart b/star_lock/lib/main/lockDetail/videoLog/videoLogDownLoad/videoLogDownLoad_page.dart new file mode 100644 index 00000000..d5916fc1 --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/videoLogDownLoad/videoLogDownLoad_page.dart @@ -0,0 +1,103 @@ + + +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; + +import '../../../../app_settings/app_colors.dart'; +import '../../../../tools/noData.dart'; +import '../../../../tools/titleAppBar.dart'; +import 'videoLogDownLoad_logic.dart'; + +class VideoLogDownLoadPage extends StatefulWidget { + const VideoLogDownLoadPage({Key? key}) : super(key: key); + + @override + State createState() => _VideoLogDownLoadPageState(); +} + +class _VideoLogDownLoadPageState extends State { + final logic = Get.put(VideoLogDownLoadLogic()); + final state = Get.find().state; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: TitleAppBar( + barTitle: "下载列表", + haveBack: true, + backgroundColor: AppColors.mainColor, + ), + body: Column( + children: [ + Expanded( + child: state.localList.isNotEmpty ? ListView.builder( + itemCount: 5, + itemBuilder: (c, index) { + return Column(children: [ + Container( + margin: EdgeInsets.only(left:20.w, top: 15.w, bottom: 15.w), + child: Row( + children: [ + Text("2023.10.23", style: TextStyle(fontSize: 20.sp)), + ] + )), + mainListView(index) + ],); + }): const NoData(), + ), + ], + ), + ); + } + + var itemW = (1.sw - 15.w*4)/3; + var itemH = (1.sw - 15.w*4)/3+40.h; + Widget mainListView(int index){ + return Container( + // margin: EdgeInsets.only(left: 10.w, right: 10.w, top: 40.h), + // color: Colors.blue, + child: GridView.builder( + padding: EdgeInsets.only(left: 15.w, right: 15.w), + itemCount: index+1, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + //横轴元素个数 + crossAxisCount: 3, + //纵轴间距 + mainAxisSpacing: 10.w, + // 横轴间距 + crossAxisSpacing: 15.w, + //子组件宽高长度比例 + childAspectRatio: itemW/itemH + ), + itemBuilder: (context, index) { + return videoItem(); + }, + ), + ); + } + + Widget videoItem(){ + return SizedBox( + width: itemW, + height: itemH, + child: Stack( + children: [ + Column( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(10.w), + child: Image(width: itemW, height: itemW, fit: BoxFit.fill, image: const AssetImage("images/main/icon_lockDetail_monitoringvoiceFrist.png")), + ), + SizedBox(height:5.h), + Text("2023.10.23 10:00", style: TextStyle(fontSize: 20.sp)) + ], + ), + ], + ), + ); + } +} diff --git a/star_lock/lib/main/lockDetail/videoLog/videoLogDownLoad/videoLogDownLoad_state.dart b/star_lock/lib/main/lockDetail/videoLog/videoLogDownLoad/videoLogDownLoad_state.dart new file mode 100644 index 00000000..3e60e4d5 --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/videoLogDownLoad/videoLogDownLoad_state.dart @@ -0,0 +1,5 @@ + + +class VideoLogDownLoadState{ + var localList = []; +} \ No newline at end of file diff --git a/star_lock/lib/main/lockMian/demoMode/demoModeLockDetail/demoModeLockDetail_page.dart b/star_lock/lib/main/lockMian/demoMode/demoModeLockDetail/demoModeLockDetail_page.dart index 52747a4a..a43409ab 100644 --- a/star_lock/lib/main/lockMian/demoMode/demoModeLockDetail/demoModeLockDetail_page.dart +++ b/star_lock/lib/main/lockMian/demoMode/demoModeLockDetail/demoModeLockDetail_page.dart @@ -323,6 +323,15 @@ class _DemoModeLockDetailPageState extends State { Get.toNamed(Routers.lockOperatingRecordPage, arguments: {"keyInfo": LockListInfoItemEntity()}); }), + // 视频日志 + bottomItem('images/main/icon_lockDetail_videoLog.png', "视频日志", () { + //视频日志 + Get.toNamed(Routers.videoLogPage); + }), + // 消息提醒 + bottomItem('images/main/icon_lockDetail_messageReminding.png', "消息提醒", () { + Get.toNamed(Routers.msgNotificationPage); + }), // 设置 bottomItem( 'images/main/icon_main_set.png', TranslationLoader.lanKeys!.set!.tr, diff --git a/star_lock/lib/main/lockMian/demoMode/demoModeLockSet/demoModeLockSet_page.dart b/star_lock/lib/main/lockMian/demoMode/demoModeLockSet/demoModeLockSet_page.dart index 90faba47..16700a59 100644 --- a/star_lock/lib/main/lockMian/demoMode/demoModeLockSet/demoModeLockSet_page.dart +++ b/star_lock/lib/main/lockMian/demoMode/demoModeLockSet/demoModeLockSet_page.dart @@ -11,6 +11,7 @@ import '../../../../tools/submitBtn.dart'; import '../../../../tools/titleAppBar.dart'; import '../../../../tools/toast.dart'; import '../../../../translations/trans_lib.dart'; +import '../../../lockDetail/lcokSet/lockSet/lockSetInfo_entity.dart'; class DemoModeLockSetPage extends StatefulWidget { const DemoModeLockSetPage({Key? key}) : super(key: key); @@ -78,6 +79,24 @@ class _DemoModeLockSetPageState extends State { // Get.toNamed(Routers.wirelessKeyboardPage); // Toast.show(msg: "功能暂未开放"); }), + // 照明 + CommonItem( + leftTitel: '照明', + rightTitle: "", + isHaveLine: true, + isHaveDirection: true, + action: () { + gotoAddLock(); + }), + // 开门器 + CommonItem( + leftTitel: '开门器', + rightTitle: "", + isHaveLine: false, + isHaveDirection: true, + action: () { + gotoAddLock(); + }), SizedBox(height: 10.h), // 自动闭锁 CommonItem( @@ -148,54 +167,30 @@ class _DemoModeLockSetPageState extends State { }), SizedBox(height: 10.h), //---田总新增展示 - // Obx(() => CommonItem( leftTitel: '面容开锁', rightTitle: "", isHaveLine: true, - isHaveRightWidget: true, - rightWidget: - SizedBox(width: 60.w, child: _otherUnHaveDoneSwitch())), - // ), - // Obx(() => - CommonItem( - leftTitel: '感应距离', - rightTitle: "", - isHaveLine: true, isHaveDirection: true, action: () { gotoAddLock(); - } - ), - // ), - // Obx(() => + }), CommonItem( - leftTitel: '自动亮屏', + leftTitel: '消息提醒', rightTitle: "", isHaveLine: true, - isHaveRightWidget: true, - rightWidget: - SizedBox(width: 60.w, child: _otherUnHaveDoneSwitch())), - // ), - // Obx(() => + isHaveDirection: true, + action: () { + gotoAddLock(); + }), CommonItem( - leftTitel: '逗留警告', + leftTitel: '猫眼设置', rightTitle: "", isHaveLine: true, - isHaveRightWidget: true, - rightWidget: - SizedBox(width: 60.w, child: _otherUnHaveDoneSwitch())), - // ), - // Obx(() => - CommonItem( - leftTitel: '异常警告', - rightTitle: "", - isHaveLine: true, - isHaveRightWidget: true, - rightWidget: - SizedBox(width: 60.w, child: _otherUnHaveDoneSwitch())), - // ), - // Obx(() => + isHaveDirection: true, + action: () { + gotoAddLock(); + }), CommonItem( leftTitel: '开门方向设置', rightTitle: "", @@ -203,10 +198,7 @@ class _DemoModeLockSetPageState extends State { isHaveLine: true, action: () { gotoAddLock(); - } - ), - // ), - // Obx(() => + }), CommonItem( leftTitel: '电机功率设置', rightTitle: "", @@ -214,11 +206,18 @@ class _DemoModeLockSetPageState extends State { isHaveDirection: true, action: () { gotoAddLock(); - } - ), + }), + // 支持蓝牙广播(关闭则不能使用蓝牙主动开锁) + CommonItem( + leftTitel: '蓝牙广播', + rightTitle: "", + isHaveLine: false, + isHaveRightWidget: true, + rightWidget: _lockRemindSwitch()), // ), SizedBox(height: 10.h), //-----新增至此 + // 标记房态 CommonItem( leftTitel: TranslationLoader.lanKeys!.markedHouseState!.tr, @@ -228,22 +227,23 @@ class _DemoModeLockSetPageState extends State { action: () { gotoAddLock(); }), + // 考勤 CommonItem( leftTitel: TranslationLoader.lanKeys!.checkingIn!.tr, rightTitle: "", isHaveLine: true, isHaveRightWidget: true, - rightWidget: - SizedBox(width: 60.w, child: _openCheckInSwitch()) + rightWidget: _openCheckInSwitch() ), + // 开锁提醒 CommonItem( leftTitel: TranslationLoader.lanKeys!.unlockReminder!.tr, rightTitle: "", isHaveLine: false, isHaveRightWidget: true, - rightWidget: - SizedBox(width: 60.w, child: _lockRemindSwitch())), + rightWidget: _lockRemindSwitch()), SizedBox(height: 10.h), + // wifi配网 CommonItem( leftTitel: TranslationLoader .lanKeys!.wifiDistributionNetwork!.tr, @@ -253,6 +253,7 @@ class _DemoModeLockSetPageState extends State { action: () { gotoAddLock(); }), + // 锁时间 CommonItem( leftTitel: TranslationLoader.lanKeys!.lockTime!.tr, rightTitle: "", @@ -261,6 +262,7 @@ class _DemoModeLockSetPageState extends State { action: () { gotoAddLock(); }), + // 诊断 CommonItem( leftTitel: TranslationLoader.lanKeys!.diagnose!.tr, rightTitle: "", @@ -269,6 +271,7 @@ class _DemoModeLockSetPageState extends State { action: () { gotoAddLock(); }), + // 上传数据 CommonItem( leftTitel: TranslationLoader.lanKeys!.uploadData!.tr, rightTitle: "", @@ -277,15 +280,16 @@ class _DemoModeLockSetPageState extends State { action: () { gotoAddLock(); }), - CommonItem( - leftTitel: - TranslationLoader.lanKeys!.importOtherLockData!.tr, - rightTitle: "", - isHaveLine: true, - isHaveDirection: true, - action: () { - gotoAddLock(); - }), + // CommonItem( + // leftTitel: + // TranslationLoader.lanKeys!.importOtherLockData!.tr, + // rightTitle: "", + // isHaveLine: true, + // isHaveDirection: true, + // action: () { + // gotoAddLock(); + // }), + // 锁升级 CommonItem( leftTitel: TranslationLoader.lanKeys!.lockEscalation!.tr, rightTitle: "", @@ -335,18 +339,6 @@ class _DemoModeLockSetPageState extends State { ); } - CupertinoSwitch _otherUnHaveDoneSwitch() { - return CupertinoSwitch( - activeColor: CupertinoColors.activeBlue, - trackColor: CupertinoColors.systemGrey5, - thumbColor: CupertinoColors.white, - value: false, - onChanged: (value) { - gotoAddLock(); - }, - ); - } - void gotoAddLock(){ // Get.toNamed(Routers.seletLockTypePage); Toast.show(msg: "演示模式"); diff --git a/star_lock/lib/mine/addLock/saveLock/saveLock_logic.dart b/star_lock/lib/mine/addLock/saveLock/saveLock_logic.dart index 64b1397e..519ce1d9 100644 --- a/star_lock/lib/mine/addLock/saveLock/saveLock_logic.dart +++ b/star_lock/lib/mine/addLock/saveLock/saveLock_logic.dart @@ -110,6 +110,7 @@ class SaveLockLogic extends BaseGetXController { // 厂商名称 var vendor = reply.data.sublist(3, 23); + print("vendor:$vendor reply.data:${reply.data}"); var vendorStr = utf8String(vendor); state.lockInfo["vendor"] = vendorStr; // print("vendor:$vendor vendorStr:$vendorStr vendorStr.length${vendorStr.length}"); diff --git a/star_lock/lib/mine/mine/starLockMine_page.dart b/star_lock/lib/mine/mine/starLockMine_page.dart index 8ed2988b..20053c4d 100644 --- a/star_lock/lib/mine/mine/starLockMine_page.dart +++ b/star_lock/lib/mine/mine/starLockMine_page.dart @@ -128,7 +128,7 @@ class _StarLockMinePageState extends State with BaseWidget { // }), mineItem('images/mine/icon_mine_main_addLock.png', TranslationLoader.lanKeys!.addDevice!.tr, () { - Navigator.pushNamed(context, Routers.seletLockTypePage); + Get.toNamed(Routers.seletLockTypePage); }), // mineItem('images/mine/icon_mine_main_gateway.png', // TranslationLoader.lanKeys!.gateway!.tr, () { @@ -136,7 +136,7 @@ class _StarLockMinePageState extends State with BaseWidget { // }), mineItem('images/mine/icon_mine_main_message.png', TranslationLoader.lanKeys!.message!.tr, () { - Navigator.pushNamed(context, Routers.messageListPage); + Get.toNamed(Routers.messageListPage); // Toast.show(msg: "功能暂未开放"); }), //删除“客服”行 @@ -146,15 +146,15 @@ class _StarLockMinePageState extends State with BaseWidget { // }), mineItem('images/mine/icon_mine_main_set.png', TranslationLoader.lanKeys!.set!.tr, () { - Navigator.pushNamed(context, Routers.mineSetPage); + Get.toNamed(Routers.mineSetPage); }), mineItem('images/mine/icon_mine_main_vip.png', TranslationLoader.lanKeys!.valueAddedServices!.tr, () { - Navigator.pushNamed(context, Routers.valueAddedServicesPage); + Get.toNamed(Routers.valueAddedServicesPage); }), mineItem('images/mine/icon_mine_main_about.png', TranslationLoader.lanKeys!.about!.tr, () { - Navigator.pushNamed(context, Routers.abountPage); + Get.toNamed(Routers.abountPage); }), ], ), diff --git a/star_lock/lib/mine/valueAddedServices/valueAddedServicesList/valueAddedServicesList_page.dart b/star_lock/lib/mine/valueAddedServices/valueAddedServicesList/valueAddedServicesList_page.dart index d9be9057..8c4b4661 100644 --- a/star_lock/lib/mine/valueAddedServices/valueAddedServicesList/valueAddedServicesList_page.dart +++ b/star_lock/lib/mine/valueAddedServices/valueAddedServicesList/valueAddedServicesList_page.dart @@ -43,17 +43,14 @@ class _ValueAddedServicesPageListState // arguments: 2); // }), _valueAddedServicesItem( - Image.asset( - 'images/mine/icon_mine_valueAddedServices_realName.png'), + Image.asset('images/mine/icon_mine_valueAddedServices_realName.png'), TranslationLoader.lanKeys!.realNameAuthentication!.tr, () { - Navigator.pushNamed( - context, Routers.valueAddedServicesRealNamePage); + Get.toNamed(Routers.valueAddedServicesRealNamePage); }), _valueAddedServicesItem( Image.asset('images/mine/icon_mine_valueAddedServices_vip.png'), TranslationLoader.lanKeys!.advancedFunction!.tr, () { - Navigator.pushNamed( - context, Routers.valueAddedServicesHighFunctionPage); + Get.toNamed(Routers.valueAddedServicesHighFunctionPage); }), // _valueAddedServicesItem( // Image.asset('images/mine/icon_mine_valueAddedServices_push.png'), diff --git a/star_lock/lib/network/api_provider_base.dart b/star_lock/lib/network/api_provider_base.dart index f39f9f6f..e00ac289 100644 --- a/star_lock/lib/network/api_provider_base.dart +++ b/star_lock/lib/network/api_provider_base.dart @@ -55,6 +55,8 @@ class BaseProvider extends GetConnect with Api { body: rs as T, statusText: res.statusText, ); + }else{ + } // print('得到的数据======>bodyString:${res.bodyString} body:${res.body} bodyBytes:${res.bodyBytes} status:${res.status} statusText:${res.statusText} statusCode:${res.statusCode}'); getDataResult(res.body); diff --git a/star_lock/lib/tools/noData.dart b/star_lock/lib/tools/noData.dart index 062dc3e9..95435546 100644 --- a/star_lock/lib/tools/noData.dart +++ b/star_lock/lib/tools/noData.dart @@ -9,7 +9,8 @@ class NoData extends StatelessWidget { Widget build(BuildContext context) { return SizedBox( width: 1.sw, - height: 1.sh - ScreenUtil().statusBarHeight, + // height: 1.sh - ScreenUtil().statusBarHeight, + height: 1.sw, child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, diff --git a/star_lock/pubspec.yaml b/star_lock/pubspec.yaml index d6ef4834..92daab09 100644 --- a/star_lock/pubspec.yaml +++ b/star_lock/pubspec.yaml @@ -112,7 +112,12 @@ dependencies: cached_network_image: ^3.2.0 webview_flutter: ^4.2.3 aliyun_push: ^0.1.6 - + + #视频播放器 + video_player: ^2.7.2 + #控制横竖屏控件 + auto_orientation: ^2.3.1 + dev_dependencies: flutter_test: sdk: flutter