完成视频日志、监控模块的UI

This commit is contained in:
魏少阳 2023-11-18 10:38:13 +08:00
parent d3eb981844
commit 8dfd3d717c
63 changed files with 2548 additions and 145 deletions

View File

@ -0,0 +1,7 @@
WEBVTT
00:00:00.200 --> 00:00:01.750
[ Birds chirping ]
00:00:02.300 --> 00:00:05.000
[ Buzzing ]

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -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()),
];
}

View File

@ -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);
}
}

View File

@ -16,7 +16,7 @@ class SenderConfiguringWifiCommand extends SenderProtocol {
String? ssid;
String? password;
int? numberOfServers;
int? listOfServers;
List<int>? listOfServers;
List<int>? token;
int? needAuthor;
List<int>? publicKey;
@ -76,7 +76,7 @@ class SenderConfiguringWifiCommand extends SenderProtocol {
subData.add(numberOfServers!);
// listOfServers
subData.add(listOfServers!);
subData.addAll(listOfServers!);
// token
// subData.addAll(token!);

View File

@ -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<String> changeIntListToStringList(List<int> list){
List<String> strList = [];

View File

@ -252,6 +252,12 @@ class CommandReciverManager {
reply = SenderReferEventRecordTimeReply.parseData(commandType, data);
}
break;
// case 50:
// {
// // wifi配网
// reply = SenderConfiguringWifiReply.parseData(commandType, data);
// }
// break;
case 51:
{
// wifi配网结果

View File

@ -516,7 +516,7 @@ class IoSenderManage {
required String? ssid,
required String? password,
required int? numberOfServers,
required int? listOfServers,
required List<int>? listOfServers,
required List<int>? token,
required int? needAuthor,
required List<int>? publicKey,

View File

@ -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 = <int>[];
// for(int i = 0; i<state.configuringWifiEntity.value.data!.serviceList!.length; i++){
// var item = state.configuringWifiEntity.value.data!.serviceList![i];
// var itemList = item.serviceIp!.split(".");
// itemList.forEach((element) {
// serversList.add(int.parse(element));
// });
// // serversList.add(int.parse(item.port!));
//
// double typeDouble = int.parse(item.port!) / 256;
// int type1 = typeDouble.toInt();
// int type2 = int.parse(item.port!) % 256;
// serversList.add(type1);
// serversList.add(type2);
// }
// print("serversListserversList:$serversList");
}
}
@ -31,26 +49,15 @@ class ConfiguringWifiLogic extends BaseGetXController{
late StreamSubscription<Reply> _replySubscription;
void _initReplySubscription() {
_replySubscription = EventBusManager().eventBus!.on<Reply>().listen((reply) async {
// wifi
// WIFI配网结果
if(reply is SenderConfiguringWifiReply) {
_replySenderConfiguringWifi(reply);
}
});
}
//
// WIFI配网结果
Future<void> _replySenderConfiguringWifi(Reply reply) async {
var privateKey = await Storage.getStringList(saveBluePrivateKey);
List<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
var signKey = await Storage.getStringList(saveBlueSignKey);
List<int> 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<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
var publicKey = await Storage.getStringList(saveBluePublicKey);
List<int> publicKeyDataList = changeStringListToIntList(publicKey!);
var tokenData = reply.data.sublist(7, 10);
var saveStrList = changeIntListToStringList(tokenData);
print("openDoorToken:$tokenData");
Storage.setStringList(saveBlueToken, saveStrList);
var serversList = <int>[];
for(int i = 0; i<state.configuringWifiEntity.value.data!.serviceList!.length; i++){
var item = state.configuringWifiEntity.value.data!.serviceList![i];
var itemList = item.serviceIp!.split(".");
itemList.forEach((element) {
serversList.add(int.parse(element));
});
double typeDouble = int.parse(item.port!) / 256;
int type1 = typeDouble.toInt();
int type2 = int.parse(item.port!) % 256;
serversList.add(type1);
serversList.add(type2);
}
IoSenderManage.senderConfiguringWifiCommand(
keyID: state.lockSetInfoData.value.lockBasicInfo!.keyId.toString(),
userID: await Storage.getUid(),
openMode: 1,
openTime: DateTime.now().millisecondsSinceEpoch,
ssid: state.wifiNameController.text,
password: state.wifiPWDController.text,
numberOfServers: state.configuringWifiEntity.value.data!.serviceNum,
listOfServers: serversList,
token: tokenData,
needAuthor: 1,
signKey: signKeyDataList,
publicKey: publicKeyDataList,
privateKey: getPrivateKeyList,
);
@ -109,13 +144,28 @@ class ConfiguringWifiLogic extends BaseGetXController{
print("openDoorTokenPubToken:$getTokenList");
// print("millisecondsSinceEpoch/1000:${DateTime.now().millisecondsSinceEpoch~/1000}");
var serversList = <int>[];
for(int i = 0; i<state.configuringWifiEntity.value.data!.serviceList!.length; i++){
var item = state.configuringWifiEntity.value.data!.serviceList![i];
var itemList = item.serviceIp!.split(".");
itemList.forEach((element) {
serversList.add(int.parse(element));
});
double typeDouble = int.parse(item.port!) / 256;
int type1 = typeDouble.toInt();
int type2 = int.parse(item.port!) % 256;
serversList.add(type1);
serversList.add(type2);
}
IoSenderManage.senderConfiguringWifiCommand(
keyID: "1",
keyID: state.lockSetInfoData.value.lockBasicInfo!.keyId.toString(),
userID: await Storage.getUid(),
ssid: state.wifiNameController.text,
password: state.wifiPWDController.text,
numberOfServers: state.configuringWifiEntity.value.data!.serviceNum,
listOfServers: 0,
listOfServers: serversList,
token: getTokenList,
needAuthor: 1,
publicKey: publicKeyDataList,

View File

@ -36,7 +36,7 @@ class _ConfiguringWifiPageState extends State<ConfiguringWifiPage> {
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<ConfiguringWifiPage> {
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<ConfiguringWifiPage> {
child: TextField(
//
maxLines: 1,
// controller: _controller,
controller: controller,
autofocus: false,
textAlign: TextAlign.end,
decoration: InputDecoration(

View File

@ -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!;
}
}

View File

@ -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<LockSetPage> 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(() =>
//

View File

@ -81,16 +81,16 @@ class _MsgNotificationPageState extends State<MsgNotificationPage> {
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,
),

View File

@ -72,7 +72,10 @@ class _LockDetailPageState extends State<LockDetailPage>
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<LockDetailPage>
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<LockDetailPage>
))),
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<LockDetailPage>
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<LockDetailPage>
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);
}),
//

View File

@ -0,0 +1,9 @@
import '../../../../tools/baseGetXController.dart';
import 'lockMonitoring_state.dart';
class LockMonitoringLogic extends BaseGetXController {
final LockMonitoringState state = LockMonitoringState();
}

View File

@ -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<LockMonitoringPage> createState() => _LockMonitoringPageState();
}
class _LockMonitoringPageState extends State<LockMonitoringPage> {
final logic = Get.put(LockMonitoringLogic());
final state = Get.find<LockMonitoringLogic>().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))
],
)),
);
}
}

View File

@ -0,0 +1,7 @@
import 'package:get/get.dart';
class LockMonitoringState {
var isOpenVoice = false.obs;
}

View File

@ -0,0 +1,8 @@
import 'package:star_lock/tools/baseGetXController.dart';
import 'monitoringRealTimeScreen_state.dart';
class MonitoringRealTimeScreenLogic extends BaseGetXController{
MonitoringRealTimeScreenState state = MonitoringRealTimeScreenState();
}

View File

@ -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<MonitoringRealTimeScreenPage> createState() => _MonitoringRealTimeScreenPageState();
}
class _MonitoringRealTimeScreenPageState extends State<MonitoringRealTimeScreenPage> {
final logic = Get.put(MonitoringRealTimeScreenLogic());
final state = Get.find<MonitoringRealTimeScreenLogic>().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))
],
)),
);
}
}

View File

@ -0,0 +1,7 @@
import 'package:get/get.dart';
class MonitoringRealTimeScreenState{
var isOpenVoice = false.obs;
}

View File

@ -0,0 +1,12 @@
import 'package:flutter/material.dart';
mixin AfterLayoutMixin<T extends StatefulWidget> on State<T> {
@override
void initState() {
super.initState();
WidgetsBinding.instance
.addPostFrameCallback((_) => afterFirstLayout(context));
}
void afterFirstLayout(BuildContext context);
}

View File

@ -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<VideoPlayerControlState> 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<ControllerWidget>();
}
@override
bool updateShouldNotify(InheritedWidget oldWidget) {
// TODO: implement updateShouldNotify
return false;
}
}

View File

@ -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<VideoPlayerUI> {
final GlobalKey<VideoPlayerControlState> _key =
GlobalKey<VideoPlayerControlState>();
///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,
);
}
}
}
}

View File

@ -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<VideoPlayerControl> {
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: <Widget>[_top(), _middle(), _bottom(context)],
),
),
),
onWillPop: _onWillPop,
),
),
);
}
//
Future<bool> _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: <Widget>[
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: <Widget>[
//
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(); //
});
}
}

View File

@ -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<VideoPlayerControlState> controlKey;
final Widget child;
@override
_VideoPlayerPanState createState() => _VideoPlayerPanState();
}
class _VideoPlayerPanState extends State<VideoPlayerPan>
with AfterLayoutMixin<VideoPlayerPan> {
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>[
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;
}
}

View File

@ -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<VideoPlayerSlider> {
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',
);
});
}
}

View File

@ -0,0 +1,8 @@
import 'package:star_lock/tools/baseGetXController.dart';
import 'editVideoLog_state.dart';
class EditVideoLogLogic extends BaseGetXController{
EditVideoLogState state = EditVideoLogState();
}

View File

@ -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<EditVideoLogPage> createState() => _EditVideoLogPageState();
}
class _EditVideoLogPageState extends State<EditVideoLogPage> {
final logic = Get.put(EditVideoLogLogic());
final state = Get.find<EditVideoLogLogic>().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))
],
)),
);
}
}

View File

@ -0,0 +1,10 @@
import 'package:get/get.dart';
class EditVideoLogState{
var seletVideoLog = 0.obs;
var isSeletAll = false.obs;
}

View File

@ -0,0 +1,8 @@
import 'package:star_lock/tools/baseGetXController.dart';
import 'videoLog_state.dart';
class VideoLogLogic extends BaseGetXController{
VideoLogState state = VideoLogState();
}

View File

@ -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<VideoLogPage> createState() => _VideoLogPageState();
}
class _VideoLogPageState extends State<VideoLogPage> {
final logic = Get.put(VideoLogLogic());
final state = Get.find<VideoLogLogic>().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))
],
),
),
);
}
}

View File

@ -0,0 +1,8 @@
import 'package:get/get.dart';
class VideoLogState{
var isNavLocal = false.obs;
var localList = [];
}

View File

@ -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<Duration> _exampleCaptionOffsets = <Duration>[
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<double> _examplePlaybackRates = <double>[
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: <Widget>[
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<Duration>(
// initialValue: controller.value.captionOffset,
// tooltip: 'Caption Offset',
// onSelected: (Duration delay) {
// controller.setCaptionOffset(delay);
// },
// itemBuilder: (BuildContext context) {
// return <PopupMenuItem<Duration>>[
// for (final Duration offsetDuration in _exampleCaptionOffsets)
// PopupMenuItem<Duration>(
// 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<double>(
// initialValue: controller.value.playbackSpeed,
// tooltip: 'Playback speed',
// onSelected: (double speed) {
// controller.setPlaybackSpeed(speed);
// },
// itemBuilder: (BuildContext context) {
// return <PopupMenuItem<double>>[
// for (final double speed in _examplePlaybackRates)
// PopupMenuItem<double>(
// 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;
}
}

View File

@ -0,0 +1,10 @@
import 'package:star_lock/tools/baseGetXController.dart';
import 'videoLogDetail_state.dart';
class VideoLogDetailLogic extends BaseGetXController{
VideoLogDetailState state = VideoLogDetailState();
}

View File

@ -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<VideoLogDetailPage> createState() => _VideoLogDetailPageState();
}
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),
);
_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: <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),
],
),
),
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();
}
}

View File

@ -0,0 +1,5 @@
class VideoLogDetailState{
}

View File

@ -0,0 +1,9 @@
import 'package:star_lock/tools/baseGetXController.dart';
import 'videoLogDownLoad_state.dart';
class VideoLogDownLoadLogic extends BaseGetXController{
VideoLogDownLoadState state = VideoLogDownLoadState();
}

View File

@ -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<VideoLogDownLoadPage> createState() => _VideoLogDownLoadPageState();
}
class _VideoLogDownLoadPageState extends State<VideoLogDownLoadPage> {
final logic = Get.put(VideoLogDownLoadLogic());
final state = Get.find<VideoLogDownLoadLogic>().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))
],
),
],
),
);
}
}

View File

@ -0,0 +1,5 @@
class VideoLogDownLoadState{
var localList = [];
}

View File

@ -323,6 +323,15 @@ class _DemoModeLockDetailPageState extends State<DemoModeLockDetailPage> {
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,

View File

@ -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<DemoModeLockSetPage> {
// 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<DemoModeLockSetPage> {
}),
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<DemoModeLockSetPage> {
isHaveLine: true,
action: () {
gotoAddLock();
}
),
// ),
// Obx(() =>
}),
CommonItem(
leftTitel: '电机功率设置',
rightTitle: "",
@ -214,11 +206,18 @@ class _DemoModeLockSetPageState extends State<DemoModeLockSetPage> {
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<DemoModeLockSetPage> {
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<DemoModeLockSetPage> {
action: () {
gotoAddLock();
}),
//
CommonItem(
leftTitel: TranslationLoader.lanKeys!.lockTime!.tr,
rightTitle: "",
@ -261,6 +262,7 @@ class _DemoModeLockSetPageState extends State<DemoModeLockSetPage> {
action: () {
gotoAddLock();
}),
//
CommonItem(
leftTitel: TranslationLoader.lanKeys!.diagnose!.tr,
rightTitle: "",
@ -269,6 +271,7 @@ class _DemoModeLockSetPageState extends State<DemoModeLockSetPage> {
action: () {
gotoAddLock();
}),
//
CommonItem(
leftTitel: TranslationLoader.lanKeys!.uploadData!.tr,
rightTitle: "",
@ -277,15 +280,16 @@ class _DemoModeLockSetPageState extends State<DemoModeLockSetPage> {
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<DemoModeLockSetPage> {
);
}
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: "演示模式");

View File

@ -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}");

View File

@ -128,7 +128,7 @@ class _StarLockMinePageState extends State<StarLockMinePage> 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<StarLockMinePage> 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<StarLockMinePage> 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);
}),
],
),

View File

@ -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'),

View File

@ -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);

View File

@ -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,

View File

@ -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