import 'dart:io'; 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/main/lockDetail/videoLog/videoLog/videoLog_state.dart'; import 'package:star_lock/main/lockDetail/videoLog/widget/full_screenImage_page.dart'; import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail_image.dart'; import 'package:star_lock/tools/dateTool.dart'; import 'package:star_lock/tools/noData.dart'; import 'package:video_player/video_player.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 VideoLogLogic logic = Get.put(VideoLogLogic()); final VideoLogState state = Get.find().state; @override void initState() { // TODO: implement initState super.initState(); logic.groupDownloadsByDay(); } @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(), Obx( () => Visibility( visible: !state.isNavLocal.value, child: state.videoLogList.length > 0 ? Expanded( child: ListView.builder( itemCount: state.videoLogList.length, itemBuilder: (BuildContext c, int index) { final 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) ], ); }, ), ) : _buildNotData(), ), ), // 本地顶部 Obx( () => Visibility( visible: state.isNavLocal.value, child: state.lockVideoList.length > 0 ? Expanded( child: ListView.builder( itemCount: state.lockVideoList.length, itemBuilder: (BuildContext c, int index) { final CloudStorageData item = state.lockVideoList[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)), ], ), ), lockMainListView(index, item) ], ); }, ), ) : _buildNotData(), ), ), ], ), ); } Widget _buildNotData() { return Expanded( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Image.asset( 'images/icon_noData.png', width: 160.w, height: 180.h, ), Text( '暂无数据'.tr, style: TextStyle( color: AppColors.darkGrayTextColor, fontSize: 22.sp), ) ], ), ), ); } // nav按钮 Widget navBtn() { return Container( constraints: BoxConstraints(maxWidth: 310.w), // color: Colors.white, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ TextButton( onPressed: () { setState(() { state.isNavLocal.value = false; state.lockVideoList.clear(); // logic.clearDownloads(); }); }, child: Obx(() => Text('云存'.tr, style: state.isNavLocal.value == true ? TextStyle( color: Colors.grey, fontSize: 26.sp, fontWeight: FontWeight.w600) : TextStyle( color: Colors.white, fontSize: 28.sp, fontWeight: FontWeight.w600)))), TextButton( onPressed: () { setState(() { state.isNavLocal.value = true; logic.groupDownloadsByDay(); }); }, child: Obx( () => Text( '已下载'.tr, style: state.isNavLocal.value == true ? TextStyle( color: Colors.white, fontSize: 28.sp, fontWeight: FontWeight.w600) : TextStyle( color: Colors.grey, fontSize: 26.sp, fontWeight: FontWeight.w600), ), ), ), ], ), ); } // 云存顶部视频 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天滚动储存'.tr, style: TextStyle(fontSize: 24.sp)), SizedBox(height: 10.h), Text("${F.navTitle}${"已为本设备免费提供3大滚动视频储存服务".tr}", style: TextStyle(fontSize: 22.sp, color: Colors.grey)), ], )), SizedBox(width: 15.w), Text('去升级'.tr, style: TextStyle(fontSize: 22.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, arguments: { 'downloadVideoLogList': [], }); }, 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('下载列表'.tr, style: TextStyle(fontSize: 24.sp)), SizedBox(height: 15.h), Text('暂无下载内容'.tr, 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 ? '已下载'.tr : '全部视频'.tr, style: TextStyle(fontSize: 26.sp, fontWeight: FontWeight.w500), ), 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: () { if (state.isNavLocal.value) { Get.toNamed(Routers.editVideoLogPage, arguments: { 'videoDataList': state.lockVideoList.value, 'lockId': state.getLockId.value, 'isNavLocal': state.isNavLocal.value }); } else { Get.toNamed(Routers.editVideoLogPage, arguments: { 'videoDataList': state.videoLogList.value, 'lockId': state.getLockId.value, 'isNavLocal': state.isNavLocal.value }); } }, ) // TextButton( // onPressed: (){ // // }, // child: Image(width: 40.w, height: 40.w, image: const AssetImage("images/main/icon_lockDetail_monitoringEditVoice.png"),) // ), ], ), ); } double itemW = (1.sw - 15.w * 4) / 3; double 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: 15.w, // 横轴间距 crossAxisSpacing: 15.w, //子组件宽高长度比例 childAspectRatio: itemW / itemH), itemBuilder: (BuildContext context, int index) { final RecordListData recordData = itemData.recordList![index]; return videoItem(recordData); }, ); } Widget lockMainListView(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: 15.w, // 横轴间距 crossAxisSpacing: 15.w, //子组件宽高长度比例 childAspectRatio: itemW / itemH), itemBuilder: (BuildContext context, int index) { final RecordListData recordData = itemData.recordList![index]; return videoItem(recordData); }, ); } Widget videoItem(RecordListData recordData) { return GestureDetector( onTap: () { if (recordData.videoUrl != null && recordData.videoUrl!.isNotEmpty) { Get.toNamed(Routers.videoLogDetailPage, arguments: { 'recordData': recordData, 'videoDataList': state.videoLogList.value }); } else if (recordData.imagesUrl != null && recordData.imagesUrl!.isNotEmpty) { Navigator.push( context, MaterialPageRoute( builder: (context) => FullScreenImagePage( imageUrl: recordData.imagesUrl!, ), ), ); } }, child: SizedBox( width: itemW, height: itemH, child: Column( children: [ Container( width: itemW, height: itemW, margin: const EdgeInsets.all(0), color: Colors.white, child: ClipRRect( borderRadius: BorderRadius.circular(10.w), child: _buildImageOrVideoItem(recordData), ), ), SizedBox(height: 5.h), Text( DateTool().dateToYMDHNString(recordData.operateDate.toString()), textAlign: TextAlign.center, style: TextStyle(fontSize: 18.sp), ) ], ), ), ); } _buildImageOrVideoItem(RecordListData recordData) { if (recordData.videoUrl != null && recordData.videoUrl!.isNotEmpty) { return _buildVideoItem(recordData); } else { return _buildImageItem(recordData); } } _buildVideoItem(RecordListData recordData) { return VideoThumbnailImage(videoUrl: recordData.videoUrl!); } _buildImageItem(RecordListData recordData) { return RotatedBox( quarterTurns: -1, child: _buildImageWidget(recordData.imagesUrl), ); } // 根据图片路径构建对应的 Image Widget Widget _buildImageWidget(String? imageUrl) { if (imageUrl == null || imageUrl.isEmpty) { // 如果图片路径为空,返回错误图片 return Image.asset( 'images/icon_unHaveData.png', // 错误图片路径 fit: BoxFit.cover, ); } // 判断是否为网络地址 if (_isNetworkUrl(imageUrl)) { return Image.network( imageUrl, fit: BoxFit.cover, errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) { // 图片加载失败时显示错误图片 return Image.asset( 'images/icon_unHaveData.png', // 错误图片路径 fit: BoxFit.cover, ); }, ); } else { // 如果是本地文件路径,则使用 FileImage 加载图片 return Image.file( File(imageUrl), fit: BoxFit.cover, errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) { // 文件加载失败时显示错误图片 return Image.asset( 'images/icon_unHaveData.png', // 错误图片路径 fit: BoxFit.cover, ); }, ); } } // 判断是否为网络地址 bool _isNetworkUrl(String url) { final uri = Uri.tryParse(url); return uri != null && uri.scheme.isNotEmpty && uri.scheme.startsWith('http'); } }