1,更新视频播放器插件版本
2,新增视频日志云存列表接口对接及视频列表逻辑处理 3,完成点击云存列表播放当前MP4格式的视频以及页面完善逻辑处理 4,新增编辑视频页面数据接口对接
This commit is contained in:
parent
7fdc1e6e6d
commit
af59247c46
@ -46,7 +46,7 @@
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
|
||||
|
||||
|
||||
<application android:label="@string/app_name" android:name="android.app.Application" android:icon="@mipmap/ic_launcher">
|
||||
<application android:usesCleartextTraffic="true" android:label="@string/app_name" android:name="android.app.Application" android:icon="@mipmap/ic_launcher">
|
||||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
|
||||
BIN
star_lock/images/icon_video_placeholder.jpg
Normal file
BIN
star_lock/images/icon_video_placeholder.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.4 KiB |
@ -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"
|
||||
}
|
||||
|
||||
@ -778,5 +778,13 @@
|
||||
"经过以上设定的时间,锁没有被开启,系统会给指定对象发送提醒消息,该功能需要锁联网":"经过以上设定的时间,锁没有被开启,系统会给指定对象发送提醒消息,该功能需要锁联网",
|
||||
"打开提醒后,当锁电量低于20%、10%和5%,系统会给指定对象发送提醒消息。电量读取方式:网关读取或APP读取。":"打开提醒后,当锁电量低于20%、10%和5%,系统会给指定对象发送提醒消息。电量读取方式:网关读取或APP读取。",
|
||||
"门未开时间":"门未开时间",
|
||||
"添加和使用面容开锁时:":"添加和使用面容开锁时:"
|
||||
"添加和使用面容开锁时:":"添加和使用面容开锁时:",
|
||||
"云存":"云存",
|
||||
"本地":"本地",
|
||||
"3天滚动储存":"3天滚动储存",
|
||||
"去升级":"去升级",
|
||||
"下载列表":"下载列表",
|
||||
"已下载":"已下载",
|
||||
"全部视频":"全部视频",
|
||||
"已为本设备免费提供3大滚动视频储存服务":"已为本设备免费提供3大滚动视频储存服务"
|
||||
}
|
||||
|
||||
@ -781,5 +781,13 @@
|
||||
"经过以上设定的时间,锁没有被开启,系统会给指定对象发送提醒消息,该功能需要锁联网":"经过以上设定的时间,锁没有被开启,系统会给指定对象发送提醒消息,该功能需要锁联网",
|
||||
"打开提醒后,当锁电量低于20%、10%和5%,系统会给指定对象发送提醒消息。电量读取方式:网关读取或APP读取。":"打开提醒后,当锁电量低于20%、10%和5%,系统会给指定对象发送提醒消息。电量读取方式:网关读取或APP读取。",
|
||||
"门未开时间":"门未开时间",
|
||||
"添加和使用面容开锁时:":"添加和使用面容开锁时:"
|
||||
"添加和使用面容开锁时:":"添加和使用面容开锁时:",
|
||||
"云存":"云存",
|
||||
"本地":"本地",
|
||||
"3天滚动储存":"3天滚动储存",
|
||||
"去升级":"去升级",
|
||||
"下载列表":"下载列表",
|
||||
"已下载":"已下载",
|
||||
"全部视频":"全部视频",
|
||||
"已为本设备免费提供3大滚动视频储存服务":"已为本设备免费提供3大滚动视频储存服务"
|
||||
}
|
||||
|
||||
@ -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<EditVideoLogPage> {
|
||||
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<EditVideoLogPage> {
|
||||
);
|
||||
}
|
||||
|
||||
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<EditVideoLogPage> {
|
||||
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<EditVideoLogPage> {
|
||||
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<EditVideoLogPage> {
|
||||
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))
|
||||
],
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,90 @@
|
||||
class VideoLogEntity {
|
||||
int? errorCode;
|
||||
String? description;
|
||||
String? errorMsg;
|
||||
List<CloudStorageData>? data;
|
||||
|
||||
VideoLogEntity({this.errorCode, this.description, this.errorMsg, this.data});
|
||||
|
||||
VideoLogEntity.fromJson(Map<String, dynamic> json) {
|
||||
errorCode = json['errorCode'];
|
||||
description = json['description'];
|
||||
errorMsg = json['errorMsg'];
|
||||
if (json['data'] != null) {
|
||||
data = <CloudStorageData>[];
|
||||
json['data'].forEach((v) {
|
||||
data!.add(CloudStorageData.fromJson(v));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
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<RecordListData>? recordList;
|
||||
|
||||
CloudStorageData({this.date, this.recordList});
|
||||
|
||||
CloudStorageData.fromJson(Map<String, dynamic> json) {
|
||||
date = json['date'];
|
||||
if (json['recordList'] != null) {
|
||||
recordList = <RecordListData>[];
|
||||
json['recordList'].forEach((v) {
|
||||
recordList!.add(RecordListData.fromJson(v));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
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<String, dynamic> json) {
|
||||
recordId = json['recordId'];
|
||||
operateDate = json['operateDate'];
|
||||
imagesUrl = json['imagesUrl'];
|
||||
videoUrl = json['videoUrl'];
|
||||
recordType = json['recordType'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['recordId'] = recordId;
|
||||
data['operateDate'] = operateDate;
|
||||
data['imagesUrl'] = imagesUrl;
|
||||
data['videoUrl'] = videoUrl;
|
||||
data['recordType'] = recordType;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<VideoLogPage> {
|
||||
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<VideoLogPage> {
|
||||
Text("2023.10.2$index",
|
||||
style: TextStyle(fontSize: 20.sp)),
|
||||
])),
|
||||
mainListView(index)
|
||||
mainListView(index, CloudStorageData()),
|
||||
],
|
||||
);
|
||||
})
|
||||
@ -103,7 +107,7 @@ class _VideoLogPageState extends State<VideoLogPage> {
|
||||
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<VideoLogPage> {
|
||||
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<VideoLogPage> {
|
||||
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<VideoLogPage> {
|
||||
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<VideoLogPage> {
|
||||
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<VideoLogPage> {
|
||||
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<VideoLogPage> {
|
||||
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<VideoLogPage> {
|
||||
//子组件宽高长度比例
|
||||
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))
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@ -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<Duration> _exampleCaptionOffsets = <Duration>[
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<VideoLogDetailPage> {
|
||||
final logic = Get.put(VideoLogDetailLogic());
|
||||
final state = Get.find<VideoLogDetailLogic>().state;
|
||||
|
||||
late VideoPlayerController _controller;
|
||||
|
||||
// Future<ClosedCaptionFile> _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<VideoLogDetailPage> {
|
||||
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: <Widget>[
|
||||
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<VideoLogDetailPage> {
|
||||
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<VideoLogDetailPage> {
|
||||
);
|
||||
}
|
||||
|
||||
String formatString(time) {
|
||||
var shortName = time.toString().substring(2, 7);
|
||||
return shortName;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
_controller.dispose();
|
||||
state.videoController.dispose();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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'];
|
||||
}
|
||||
|
||||
}
|
||||
if (map['videoDataList'] != null) {
|
||||
videoLogList.value = map['videoDataList'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<CoerceFingerprintListEntity> getLockCloudStorageList(
|
||||
{required int lockId}) async {
|
||||
Future<VideoLogEntity> getLockCloudStorageList({required int lockId}) async {
|
||||
final res = await apiProvider.getLockCloudStorageList(lockId);
|
||||
return CoerceFingerprintListEntity.fromJson(res.body);
|
||||
return VideoLogEntity.fromJson(res.body);
|
||||
}
|
||||
|
||||
// 设置微信公众号推送
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user