diff --git a/star_lock/android/app/src/main/AndroidManifest.xml b/star_lock/android/app/src/main/AndroidManifest.xml index 25a509a4..afb5fd51 100644 --- a/star_lock/android/app/src/main/AndroidManifest.xml +++ b/star_lock/android/app/src/main/AndroidManifest.xml @@ -46,7 +46,7 @@ - + diff --git a/star_lock/images/icon_video_placeholder.jpg b/star_lock/images/icon_video_placeholder.jpg new file mode 100644 index 00000000..161ad0f0 Binary files /dev/null and b/star_lock/images/icon_video_placeholder.jpg differ diff --git a/star_lock/images/lan/lan_en.json b/star_lock/images/lan/lan_en.json index 0ffa372b..625c2edd 100644 --- a/star_lock/images/lan/lan_en.json +++ b/star_lock/images/lan/lan_en.json @@ -779,5 +779,13 @@ "添加和使用面容开锁时:":"Add and use Face when unlocking:", "关锁":"close lock", "功能":"function", - "配件":"parts" + "配件":"parts", + "云存":"Cloud storage", + "本地":"This locality", + "3天滚动储存":"3 days rolling storage", + "去升级":"Upgrade Now", + "下载列表":"Download list", + "已下载":"Downloaded", + "全部视频":"All videos", + "已为本设备免费提供3大滚动视频储存服务":"Three scrolling video storage services have been provided for this device free of charge" } diff --git a/star_lock/images/lan/lan_keys.json b/star_lock/images/lan/lan_keys.json index 1a9e0990..66b4b37b 100644 --- a/star_lock/images/lan/lan_keys.json +++ b/star_lock/images/lan/lan_keys.json @@ -778,5 +778,13 @@ "经过以上设定的时间,锁没有被开启,系统会给指定对象发送提醒消息,该功能需要锁联网":"经过以上设定的时间,锁没有被开启,系统会给指定对象发送提醒消息,该功能需要锁联网", "打开提醒后,当锁电量低于20%、10%和5%,系统会给指定对象发送提醒消息。电量读取方式:网关读取或APP读取。":"打开提醒后,当锁电量低于20%、10%和5%,系统会给指定对象发送提醒消息。电量读取方式:网关读取或APP读取。", "门未开时间":"门未开时间", - "添加和使用面容开锁时:":"添加和使用面容开锁时:" + "添加和使用面容开锁时:":"添加和使用面容开锁时:", + "云存":"云存", + "本地":"本地", + "3天滚动储存":"3天滚动储存", + "去升级":"去升级", + "下载列表":"下载列表", + "已下载":"已下载", + "全部视频":"全部视频", + "已为本设备免费提供3大滚动视频储存服务":"已为本设备免费提供3大滚动视频储存服务" } diff --git a/star_lock/images/lan/lan_zh.json b/star_lock/images/lan/lan_zh.json index 12cbd4d7..a7ca0e21 100644 --- a/star_lock/images/lan/lan_zh.json +++ b/star_lock/images/lan/lan_zh.json @@ -781,5 +781,13 @@ "经过以上设定的时间,锁没有被开启,系统会给指定对象发送提醒消息,该功能需要锁联网":"经过以上设定的时间,锁没有被开启,系统会给指定对象发送提醒消息,该功能需要锁联网", "打开提醒后,当锁电量低于20%、10%和5%,系统会给指定对象发送提醒消息。电量读取方式:网关读取或APP读取。":"打开提醒后,当锁电量低于20%、10%和5%,系统会给指定对象发送提醒消息。电量读取方式:网关读取或APP读取。", "门未开时间":"门未开时间", - "添加和使用面容开锁时:":"添加和使用面容开锁时:" + "添加和使用面容开锁时:":"添加和使用面容开锁时:", + "云存":"云存", + "本地":"本地", + "3天滚动储存":"3天滚动储存", + "去升级":"去升级", + "下载列表":"下载列表", + "已下载":"已下载", + "全部视频":"全部视频", + "已为本设备免费提供3大滚动视频储存服务":"已为本设备免费提供3大滚动视频储存服务" } diff --git a/star_lock/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart b/star_lock/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart index 3889695f..a8f94f11 100644 --- a/star_lock/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart +++ b/star_lock/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart @@ -1,7 +1,8 @@ - import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; +import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart'; +import 'package:star_lock/tools/dateTool.dart'; import '../../../../app_settings/app_colors.dart'; import '../../../../tools/titleAppBar.dart'; @@ -41,20 +42,23 @@ class _EditVideoLogPageState extends State { body: Column( children: [ Expanded( - child: ListView.builder( - itemCount: 5, + child: Obx(() => ListView.builder( + itemCount: state.videoLogList.length, 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) - ],); - }), + CloudStorageData item = state.videoLogList[index]; + return Column( + children: [ + Container( + margin: EdgeInsets.only( + left: 20.w, top: 15.w, bottom: 15.w), + child: Row(children: [ + Text(item.date ?? "", + style: TextStyle(fontSize: 20.sp)), + ])), + mainListView(index, item) + ], + ); + })), ), bottomBottomBtnWidget() ], @@ -62,35 +66,31 @@ class _EditVideoLogPageState extends State { ); } - 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( + var itemW = (1.sw - 15.w * 4) / 3; + var itemH = (1.sw - 15.w * 4) / 3 + 40.h; + Widget mainListView(int index, CloudStorageData itemData) { + return GridView.builder( + padding: EdgeInsets.only(left: 15.w, right: 15.w), + itemCount: itemData.recordList!.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( //横轴元素个数 - crossAxisCount: 3, - //纵轴间距 - mainAxisSpacing: 10.w, - // 横轴间距 - crossAxisSpacing: 15.w, - //子组件宽高长度比例 - childAspectRatio: itemW/itemH - ), - itemBuilder: (context, index) { - return Obx(() => videoItem()); - }, - ), + crossAxisCount: 3, + //纵轴间距 + mainAxisSpacing: 10.w, + // 横轴间距 + crossAxisSpacing: 15.w, + //子组件宽高长度比例 + childAspectRatio: itemW / itemH), + itemBuilder: (context, index) { + RecordListData recordData = itemData.recordList![index]; + return videoItem(recordData, index); + }, ); } - Widget videoItem(){ + Widget videoItem(RecordListData recordData, int index) { return SizedBox( width: itemW, height: itemH, @@ -98,12 +98,26 @@ class _EditVideoLogPageState extends State { 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")), + Container( + width: itemW, + height: itemW, + margin: const EdgeInsets.all(0), + color: Colors.white, + child: ClipRRect( + borderRadius: BorderRadius.circular(10.w), + child: Image( + fit: BoxFit.cover, + image: Image.network(recordData.imagesUrl ?? + "images/icon_video_placeholder.jpg") + .image), + ), ), - SizedBox(height:5.h), - Text("2023.10.23 10:00", style: TextStyle(fontSize: 20.sp)) + SizedBox(height: 5.h), + Text( + DateTool() + .dateToYMDHNString(recordData.operateDate.toString()), + textAlign: TextAlign.center, + style: TextStyle(fontSize: 18.sp)) ], ), Visibility( @@ -112,36 +126,41 @@ class _EditVideoLogPageState extends State { top: 0.w, right: 0.w, child: GestureDetector( - onTap: (){ - - }, - child: Image(width: 40.w, height: 40.w, image: state.isSelectAll.value ? const AssetImage("images/icon_round_select.png") : const AssetImage("images/icon_round_unSelect.png")) - ) - ), + onTap: () {}, + child: Obx(() => Image( + width: 36.w, + height: 36.w, + image: state.isSelectAll.value + ? const AssetImage("images/icon_round_select.png") + : const AssetImage( + "images/icon_round_unSelect.png"))))), ) ], ), ); } - Widget bottomBottomBtnWidget(){ + 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,(){ - - }) - ]), + 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) { + Widget bottomBtnItemWidget( + String iconUrl, String name, Color backgroundColor, Function() onClick) { var wh = 40.w; return GestureDetector( onTap: onClick, @@ -153,10 +172,12 @@ class _EditVideoLogPageState extends State { 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)) + 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 index 900badec..7d4a7fe0 100644 --- a/star_lock/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_state.dart +++ b/star_lock/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_state.dart @@ -1,10 +1,15 @@ - - import 'package:get/get.dart'; -class EditVideoLogState{ - +class EditVideoLogState { var selectVideoLog = 0.obs; + var selectVideoLogList = [].obs; var isSelectAll = false.obs; + var videoLogList = [].obs; + EditVideoLogState() { + Map map = Get.arguments; + if (map['videoDataList'] != null) { + videoLogList.value = map['videoDataList']; + } + } } diff --git a/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_entity.dart b/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_entity.dart new file mode 100644 index 00000000..7c7a90fd --- /dev/null +++ b/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_entity.dart @@ -0,0 +1,90 @@ +class VideoLogEntity { + int? errorCode; + String? description; + String? errorMsg; + List? data; + + VideoLogEntity({this.errorCode, this.description, this.errorMsg, this.data}); + + VideoLogEntity.fromJson(Map json) { + errorCode = json['errorCode']; + description = json['description']; + errorMsg = json['errorMsg']; + if (json['data'] != null) { + data = []; + json['data'].forEach((v) { + data!.add(CloudStorageData.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = {}; + data['errorCode'] = errorCode; + data['description'] = description; + data['errorMsg'] = errorMsg; + if (this.data != null) { + data['data'] = this.data!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class CloudStorageData { + String? date; + List? recordList; + + CloudStorageData({this.date, this.recordList}); + + CloudStorageData.fromJson(Map json) { + date = json['date']; + if (json['recordList'] != null) { + recordList = []; + json['recordList'].forEach((v) { + recordList!.add(RecordListData.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = {}; + data['date'] = date; + if (recordList != null) { + data['recordList'] = recordList!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class RecordListData { + int? recordId; + int? operateDate; + String? imagesUrl; + String? videoUrl; + int? recordType; + + RecordListData( + {this.recordId, + this.operateDate, + this.imagesUrl, + this.videoUrl, + this.recordType}); + + RecordListData.fromJson(Map json) { + recordId = json['recordId']; + operateDate = json['operateDate']; + imagesUrl = json['imagesUrl']; + videoUrl = json['videoUrl']; + recordType = json['recordType']; + } + + Map toJson() { + final Map data = {}; + data['recordId'] = recordId; + data['operateDate'] = operateDate; + data['imagesUrl'] = imagesUrl; + data['videoUrl'] = videoUrl; + data['recordType'] = recordType; + return data; + } +} diff --git a/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart b/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart index 17418e0b..be027017 100644 --- a/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart +++ b/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart @@ -10,7 +10,7 @@ class VideoLogLogic extends BaseGetXController { lockId: state.getLockId.value, ); if (entity.errorCode!.codeIsSuccessful) { - state.videoLogList.value = entity.data!.list!; + state.videoLogList.value = entity.data!; state.videoLogList.refresh(); } } diff --git a/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart b/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart index 17ec61c8..44ce3e3f 100644 --- a/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart +++ b/star_lock/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart @@ -2,6 +2,9 @@ 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/flavors.dart'; +import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart'; +import 'package:star_lock/tools/dateTool.dart'; import 'package:star_lock/tools/noData.dart'; import '../../../../app_settings/app_colors.dart'; @@ -43,25 +46,26 @@ class _VideoLogPageState extends State { Visibility(visible: state.isNavLocal.value, child: localTip()), // title加编辑按钮 editVideoTip(), - Visibility( + Obx(() => Visibility( visible: !state.isNavLocal.value, child: Expanded( child: ListView.builder( - itemCount: 5, + itemCount: state.videoLogList.length, itemBuilder: (c, index) { + CloudStorageData item = state.videoLogList[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", + Text(item.date ?? "", style: TextStyle(fontSize: 20.sp)), ])), - mainListView(index) + mainListView(index, item) ], ); - }))), + })))), // 本地顶部 Visibility( visible: state.isNavLocal.value, @@ -79,7 +83,7 @@ class _VideoLogPageState extends State { Text("2023.10.2$index", style: TextStyle(fontSize: 20.sp)), ])), - mainListView(index) + mainListView(index, CloudStorageData()), ], ); }) @@ -103,7 +107,7 @@ class _VideoLogPageState extends State { state.isNavLocal.value = false; }); }, - child: Obx(() => Text("云存", + child: Obx(() => Text("云存".tr, style: state.isNavLocal.value == true ? TextStyle( color: Colors.grey, @@ -119,7 +123,7 @@ class _VideoLogPageState extends State { state.isNavLocal.value = true; }); }, - child: Obx(() => Text("本地", + child: Obx(() => Text("本地".tr, style: state.isNavLocal.value == true ? TextStyle( color: Colors.white, @@ -154,14 +158,14 @@ class _VideoLogPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("3天滚动储存", style: TextStyle(fontSize: 24.sp)), + Text("3天滚动储存".tr, style: TextStyle(fontSize: 24.sp)), SizedBox(height: 10.h), - Text("星锁已为本设备免费提供3大滚动视频储存服务", + Text("${F.navTitle}${"已为本设备免费提供3大滚动视频储存服务".tr}", style: TextStyle(fontSize: 22.sp, color: Colors.grey)), ], )), SizedBox(width: 15.w), - Text("去升级", style: TextStyle(fontSize: 22.sp)), + Text("去升级".tr, style: TextStyle(fontSize: 22.sp)), Image( width: 40.w, height: 24.w, @@ -193,9 +197,9 @@ class _VideoLogPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ // SizedBox(height: 20.h), - Text("下载列表", style: TextStyle(fontSize: 24.sp)), + Text("下载列表".tr, style: TextStyle(fontSize: 24.sp)), SizedBox(height: 15.h), - Text("暂无下载内容", + Text("暂无下载内容".tr, style: TextStyle(fontSize: 22.sp, color: Colors.grey)), ], )), @@ -218,7 +222,7 @@ class _VideoLogPageState extends State { child: Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(state.isNavLocal.value == true ? "已下载" : "全部视频", + Text(state.isNavLocal.value == true ? "已下载".tr : "全部视频".tr, style: TextStyle(fontSize: 26.sp, fontWeight: FontWeight.w500)), Expanded(child: SizedBox(width: 10.w)), IconButton( @@ -230,7 +234,8 @@ class _VideoLogPageState extends State { iconSize: 30, color: Colors.black54, onPressed: () { - Get.toNamed(Routers.editVideoLogPage); + Get.toNamed(Routers.editVideoLogPage, + arguments: {"videoDataList": state.videoLogList.value}); }, ) // TextButton( @@ -248,10 +253,10 @@ class _VideoLogPageState extends State { var itemH = (1.sw - 15.w * 4) / 3 + 40.h; // 云存列表 - Widget mainListView(int index) { + Widget mainListView(int index, CloudStorageData itemData) { return GridView.builder( padding: EdgeInsets.only(left: 15.w, right: 15.w), - itemCount: index + 1, + itemCount: itemData.recordList!.length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( @@ -264,32 +269,44 @@ class _VideoLogPageState extends State { //子组件宽高长度比例 childAspectRatio: itemW / itemH), itemBuilder: (context, index) { - return videoItem(() { - Get.toNamed(Routers.videoLogDetailPage); - }); + RecordListData recordData = itemData.recordList![index]; + return videoItem(recordData); }, ); } - Widget videoItem(Function() action) { + Widget videoItem(RecordListData recordData) { return GestureDetector( - onTap: action, + onTap: () { + Get.toNamed(Routers.videoLogDetailPage, arguments: { + "recordData": recordData, + "videoDataList": state.videoLogList.value + }); + }, 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")), + Container( + width: itemW, + height: itemW, + margin: const EdgeInsets.all(0), + color: Colors.white, + child: ClipRRect( + borderRadius: BorderRadius.circular(10.w), + child: Image( + fit: BoxFit.cover, + image: Image.network(recordData.imagesUrl ?? + "images/icon_video_placeholder.jpg") + .image), + ), ), SizedBox(height: 5.h), - Text("2023.10.23 10:00", style: TextStyle(fontSize: 20.sp)) + Text( + DateTool().dateToYMDHNString(recordData.operateDate.toString()), + textAlign: TextAlign.center, + style: TextStyle(fontSize: 18.sp)) ], ), ), diff --git a/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/controlsOverlay_page.dart b/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/controlsOverlay_page.dart index f6a7d75d..b1d56954 100644 --- a/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/controlsOverlay_page.dart +++ b/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/controlsOverlay_page.dart @@ -1,10 +1,13 @@ - import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart'; +import 'package:star_lock/tools/dateTool.dart'; import 'package:video_player/video_player.dart'; class ControlsOverlay extends StatelessWidget { - const ControlsOverlay({required this.controller}); + const ControlsOverlay( + {Key? key, required this.controller, required this.recordData}) + : super(key: key); static const List _exampleCaptionOffsets = [ Duration(seconds: -10), @@ -29,6 +32,7 @@ class ControlsOverlay extends StatelessWidget { ]; final VideoPlayerController controller; + final RecordListData recordData; @override Widget build(BuildContext context) { @@ -40,18 +44,18 @@ class ControlsOverlay extends StatelessWidget { 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', - ), - ), - ), + color: Colors.black26, + child: const Center( + child: + // CircularProgressIndicator() + Icon( + Icons.play_arrow, + color: Colors.white, + size: 60.0, + semanticLabel: 'Play', + ), + ), + ), ), GestureDetector( onTap: () { @@ -123,32 +127,47 @@ class ControlsOverlay extends StatelessWidget { left: 0.h, right: 0.h, child: Container( - margin: EdgeInsets.only(left:20.w, right:20.w), + 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)), + Text( + DateTool() + .dateToYMDHNString(recordData.operateDate.toString()), + 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")), + 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")), + 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")), + child: Image( + width: 50.w, + height: 50.w, + image: const AssetImage( + "images/main/icon_lockDetail_monitoringDeletVideo_white.png")), ), ], ), @@ -164,37 +183,50 @@ class ControlsOverlay extends StatelessWidget { color: const Color.fromRGBO(0, 0, 0, 0.5), height: 60.h, child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceEvenly, + 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)), + 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(); + controller.value.isPlaying + ? controller.pause() + : controller.play(); }, ), //当前播放进度 - Text(formatString(controller.value.position), style: TextStyle(fontSize: 22.sp, color: const Color(0xffefefef)),), + 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(), + 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())); + .seekTo(Duration(milliseconds: newRating.truncate())); }, ), ), //总视频进度 - Text(formatString(controller.value.duration), style: TextStyle(fontSize: 22.sp, color: const Color(0xffefefef)),), + Text( + formatString(controller.value.duration), + style: TextStyle( + fontSize: 22.sp, color: const Color(0xffefefef)), + ), //倍速下拉菜单 // DropdownButtonHideUnderline( // child: DropdownButton2( @@ -261,4 +293,4 @@ class ControlsOverlay extends StatelessWidget { 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_page.dart b/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart index 8ddc5a56..1f5a1d34 100644 --- a/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart +++ b/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart @@ -1,11 +1,12 @@ - import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; +import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart'; +import 'package:star_lock/main/lockDetail/videoLog/videoLogDetail/controlsOverlay_page.dart'; +import 'package:star_lock/tools/dateTool.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'; @@ -20,34 +21,20 @@ 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), + + state.videoController = VideoPlayerController.networkUrl( + Uri.parse(state.recordData.value.videoUrl!), + videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true), ); - _controller.addListener(() { - setState(() { - print("controller.value.isBuffering:${_controller.value.isBuffering}"); - }); + state.videoController.addListener(() { + setState(() {}); }); - - _controller.setLooping(false); - // _controller.setVolume(1); - _controller.initialize(); - + state.videoController.setLooping(false); + state.videoController.initialize(); } @override @@ -55,90 +42,119 @@ class _VideoLogDetailPageState extends State { return Scaffold( backgroundColor: Colors.white, appBar: TitleAppBar( - barTitle: "本地视频播放", + barTitle: "视频播放", haveBack: true, backgroundColor: AppColors.mainColor, ), body: Column( children: [ AspectRatio( - aspectRatio: 16/9, + aspectRatio: state.videoController.value.aspectRatio, 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), + VideoPlayer(state.videoController), + ControlsOverlay( + controller: state.videoController, + recordData: state.recordData.value, + ), + (state.videoController.value.isPlaying || + state.videoController.value.isBuffering) + ? Container() + : VideoProgressIndicator(state.videoController, + colors: VideoProgressColors( + playedColor: AppColors.mainColor), + allowScrubbing: true), ], ), ), Container( - margin: EdgeInsets.only(left:20.w, top: 15.w), + 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)), + Text( + DateTool().dateToYMDString( + state.recordData.value.operateDate.toString()), + style: TextStyle(fontSize: 20.sp)), ], ), SizedBox(height: 15.h), Row( children: [ - videoItem(true), + videoItem(true, state.recordData.value), ], ), ], )), 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() - ],); - }), - ), + child: ListView.builder( + itemCount: state.videoLogList.length, + itemBuilder: (c, index) { + CloudStorageData item = state.videoLogList[index]; + return Column( + children: [ + Container( + margin: EdgeInsets.only( + left: 20.w, top: 15.w, bottom: 15.w), + child: Row(children: [ + Text(item.date ?? "", + style: TextStyle(fontSize: 20.sp)), + ])), + mainListView(index, item) + ], + ); + })) + // Expanded( + // child: ListView.builder( + // itemCount: state.videoLogList.value.length, + // 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(){ + var itemW = (1.sw - 15.w * 4) / 3; + var itemH = (1.sw - 15.w * 4) / 3 + 40.h; + Widget mainListView(int index, CloudStorageData itemData) { return GridView.builder( padding: EdgeInsets.only(left: 15.w, right: 15.w), - itemCount: 4, + itemCount: itemData.recordList!.length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - //横轴元素个数 + //横轴元素个数 crossAxisCount: 3, //纵轴间距 mainAxisSpacing: 10.w, // 横轴间距 crossAxisSpacing: 15.w, //子组件宽高长度比例 - childAspectRatio: itemW/itemH - ), + childAspectRatio: itemW / itemH), itemBuilder: (context, index) { - return videoItem(false); + return videoItem(false, itemData.recordList![index]); }, ); } - Widget videoItem(bool isPlay){ + Widget videoItem(bool isPlay, RecordListData itemData) { return SizedBox( width: itemW, height: itemH, @@ -148,33 +164,50 @@ class _VideoLogDetailPageState extends State { 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))), - ) - ), - ) - ] - ), + child: Stack(children: [ + Container( + width: itemW, + height: itemW, + margin: const EdgeInsets.all(0), + color: Colors.white, + child: ClipRRect( + borderRadius: BorderRadius.circular(10.w), + child: Image( + fit: BoxFit.cover, + image: Image.network(itemData.imagesUrl ?? + "images/icon_video_placeholder.jpg") + .image), + ), + ), + Positioned( + left: 8.w, + bottom: 5.h, + child: Text( + formatString(state.videoController.value.duration), + style: + TextStyle(color: Colors.grey, 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)) + SizedBox(height: 5.h), + Text( + DateTool().dateToYMDHNString(itemData.operateDate.toString()), + style: TextStyle(fontSize: 18.sp)) ], ), ], @@ -182,10 +215,14 @@ class _VideoLogDetailPageState extends State { ); } + String formatString(time) { + var shortName = time.toString().substring(2, 7); + return shortName; + } + @override void dispose() { super.dispose(); - _controller.dispose(); + state.videoController.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 index b4240f09..a936dd64 100644 --- a/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_state.dart +++ b/star_lock/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_state.dart @@ -1,5 +1,20 @@ +import 'package:get/get.dart'; +import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart'; +import 'package:video_player/video_player.dart'; +class VideoLogDetailState { + var recordData = RecordListData().obs; + late VideoPlayerController videoController; + var videoLogList = [].obs; -class VideoLogDetailState{ + VideoLogDetailState() { + Map map = Get.arguments; + if (map['recordData'] != null) { + recordData.value = map['recordData']; + } -} \ No newline at end of file + if (map['videoDataList'] != null) { + videoLogList.value = map['videoDataList']; + } + } +} diff --git a/star_lock/lib/network/api_repository.dart b/star_lock/lib/network/api_repository.dart index e443848e..c29f283f 100644 --- a/star_lock/lib/network/api_repository.dart +++ b/star_lock/lib/network/api_repository.dart @@ -12,6 +12,7 @@ import 'package:star_lock/main/lockDetail/messageWarn/msgNotification/coerceOpen import 'package:star_lock/main/lockDetail/messageWarn/msgNotification/msgNotification/msgNotification_entity.dart'; import 'package:star_lock/main/lockDetail/passwordKey/passwordKeyList/passwordKeyListEntity.dart'; import 'package:star_lock/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKeyEntity.dart'; +import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart'; import 'package:star_lock/mine/mall/lockMall_entity.dart'; import 'package:star_lock/mine/minePersonInfo/minePersonInfoEditAccount/minePersonInfoEditAccount/mineUnbindPhoneOrEmail_entity.dart'; import 'package:star_lock/mine/minePersonInfo/minePersonInfoPage/minePersonInfo_entity.dart'; @@ -1961,10 +1962,9 @@ class ApiRepository { } // 获取云存列表 - Future getLockCloudStorageList( - {required int lockId}) async { + Future getLockCloudStorageList({required int lockId}) async { final res = await apiProvider.getLockCloudStorageList(lockId); - return CoerceFingerprintListEntity.fromJson(res.body); + return VideoLogEntity.fromJson(res.body); } // 设置微信公众号推送 diff --git a/star_lock/pubspec.yaml b/star_lock/pubspec.yaml index e4fb4ea6..611d3013 100644 --- a/star_lock/pubspec.yaml +++ b/star_lock/pubspec.yaml @@ -135,7 +135,7 @@ dependencies: jpush_flutter: ^2.5.1 #视频播放器 - video_player: ^2.7.1 + video_player: ^2.8.5 #控制横竖屏控件 auto_orientation: ^2.3.1 audioplayers: ^5.2.1