app-starlock/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart
liyi b754d56b28 Merge remote-tracking branch 'origin/develop' into develop_liyi
# Conflicts:
#	lib/main.dart
#	lib/tools/storage.dart
2025-01-14 18:00:08 +08:00

463 lines
15 KiB
Dart
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:star_lock/appRouters.dart';
import 'package:star_lock/main/lockDetail/doorLockLog/doorLockLog_entity.dart';
import 'package:star_lock/main/lockDetail/doorLockLog/doorLockLog_logic.dart';
import 'package:star_lock/main/lockDetail/doorLockLog/doorLockLog_state.dart';
import 'package:star_lock/main/lockDetail/doorLockLog/exportRecordDialog/exportRecordDialog_page.dart';
import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart';
import 'package:star_lock/main/lockDetail/videoLog/widget/full_screenImage_page.dart';
import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail.dart';
import 'package:star_lock/tools/EasyRefreshTool.dart';
import 'package:star_lock/tools/advancedCalendar/src/widget.dart';
import 'package:star_lock/tools/commonDataManage.dart';
import 'package:star_lock/tools/dateTool.dart';
import 'package:star_lock/tools/menuItem/xsDropDownWidget.dart';
import 'package:star_lock/tools/noData.dart';
import 'package:star_lock/tools/showCupertinoAlertView.dart';
import 'package:star_lock/tools/showTipView.dart';
import 'package:timelines/timelines.dart';
import '../../../app_settings/app_colors.dart';
import '../../../tools/appRouteObserver.dart';
import '../../../tools/titleAppBar.dart';
class DoorLockLogPage extends StatefulWidget {
const DoorLockLogPage({Key? key}) : super(key: key);
@override
State<DoorLockLogPage> createState() => _DoorLockLogPageState();
}
class _DoorLockLogPageState extends State<DoorLockLogPage> with RouteAware {
final DoorLockLogLogic logic = Get.put(DoorLockLogLogic());
final DoorLockLogState state = Get.find<DoorLockLogLogic>().state;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.mainBackgroundColor,
appBar: TitleAppBar(
barTitle: '操作记录'.tr,
haveBack: true,
backgroundColor: AppColors.mainColor,
actionsList: <Widget>[
Visibility(
visible: CommonDataManage().currentKeyInfo.isLockOwner == 1 ||
CommonDataManage().currentKeyInfo.keyRight == 1,
child: GestureDetector(
child: Image.asset(
'images/icon_tips_Q.png',
width: 34.w,
height: 32.w,
color: Colors.white,
),
onTap: () {
ShowTipView().showSureAlertDialog(
'1.锁没有联网密码、IC卡、指纹等开门记录无法实时上传可以点击右上角按钮然后读取记录。'.tr +
'\n' +
'2.如果您需要保留历史记录,可以点击右上角按钮,然后导出记录'.tr,
tipTitle: '看不到操作记录,可能原因有'.tr,
sureStr: '我知道了'.tr);
},
)),
Visibility(
visible: CommonDataManage().currentKeyInfo.isLockOwner == 1 ||
CommonDataManage().currentKeyInfo.keyRight == 1,
child: PopupMenuButton<String>(
onSelected: _onMenuItemSelected,
color: Colors.black,
itemBuilder: (BuildContext context) {
return <PopupMenuEntry<String>>[
_buildCustomPopupMenuItem('读取记录'.tr),
if (CommonDataManage().currentKeyInfo.isLockOwner == 1)
const PopupMenuDivider(),
if (CommonDataManage().currentKeyInfo.isLockOwner == 1)
_buildCustomPopupMenuItem('清空记录'.tr),
const PopupMenuDivider(),
_buildCustomPopupMenuItem('导出记录'.tr),
];
},
icon: Image.asset(
'images/icon_bar_more.png',
height: 30.h,
width: 10.w,
),
offset: Offset(0, 70.h), // 设置弹出框位置偏移量
),
),
],
),
body: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
topAdvancedCalendarWidget(),
Divider(
height: 1,
color: AppColors.greyLineColor,
indent: 30.w,
endIndent: 30.w,
),
eventDropDownWidget(),
Expanded(child: timeLineView())
],
),
);
}
//
PopupMenuItem<String> _buildCustomPopupMenuItem(String value) {
return PopupMenuItem<String>(
value: value,
height: 46.h,
child: SizedBox(
height: 46.h,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(value, style: TextStyle(color: Colors.white, fontSize: 22.sp)),
],
),
),
);
}
void _onMenuItemSelected(String value) {
if (value == '读取记录'.tr) {
logic.getLockRecordLastUploadDataTime();
} else if (value == '清空记录'.tr) {
ShowCupertinoAlertView().showClearOperationRecordAlert(clearClick: () {
logic.clearOperationRecordRequest();
});
} else if (value == '导出记录'.tr) {
showDialog(
context: context,
builder: (BuildContext context) {
return ExportRecordDialog(
onExport: (String filePath) {
Get.toNamed(Routers.exportSuccessPage,
arguments: <String, String>{'filePath': filePath});
},
);
},
);
}
}
// switch (value) {
// case "读取记录".tr:
// {
// logic.mockNetworkDataRequest(isRefresh: true);
// }
// break;
// case '清空记录'.tr:
// {
// ShowCupertinoAlertView().showClearOperationRecordAlert(
// clearClick: () {
// logic.clearOperationRecordRequest();
// });
// }
// break;
// case '导出记录':
// {
// showDialog(
// context: context,
// builder: (BuildContext context) {
// return ExportRecordDialog(
// onExport: (String filePath) {
// Get.toNamed(Routers.exportSuccessPage,
// arguments: <String, String>{'filePath': filePath});
// },
// );
// },
// );
// }
// break;
// }
// }
//顶部日历小部件
Widget topAdvancedCalendarWidget() {
final ThemeData theme = Theme.of(context);
return Theme(
data: theme.copyWith(
textTheme: theme.textTheme.copyWith(
titleMedium: theme.textTheme.titleMedium!.copyWith(
fontSize: 16,
color: theme.colorScheme.secondary,
),
bodyLarge: theme.textTheme.bodyLarge!.copyWith(
fontSize: 14,
color: Colors.black54,
),
bodyMedium: theme.textTheme.bodyMedium!.copyWith(
fontSize: 12,
color: Colors.black87,
),
),
primaryColor: AppColors.mainColor,
highlightColor: Colors.yellow,
disabledColor: Colors.grey,
),
child: Stack(
children: <Widget>[
AdvancedCalendar(
controller: state.calendarControllerCustom,
events: state.events,
weekLineHeight: 48.0,
startWeekDay: 1,
innerDot: true,
keepLineSize: true,
calendarTextStyle: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w400,
height: 1.3125,
letterSpacing: 0,
),
),
Positioned(
top: 8.0,
right: 8.0,
child: Obx(() => Text(
'${state.currentSelectDate.value.year}${''.tr}${state.currentSelectDate.value.month}${''.tr}',
style: theme.textTheme.titleMedium!.copyWith(
fontSize: 16,
color: theme.colorScheme.secondary,
),
)),
),
],
),
);
}
//事件下拉框组件
Widget eventDropDownWidget() {
return Container(
margin: EdgeInsets.only(top: 20.h, left: 30.w, bottom: 10.h, right: 20.w),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Obx(() => XSDropDownWidget(
items: state.getDropDownItemList,
value: state.dropdownTitle.value,
valueChanged: (value) {
state.dropdownValue.value = int.parse(value);
logic.mockNetworkDataRequest(isRefresh: true);
})),
],
),
);
}
//时间轴组件
Widget timeLineView() {
return Container(
margin: EdgeInsets.only(left: 20.w, right: 20.w, bottom: 20.h, top: 20.h),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.w),
),
child: Obx(() => state.lockLogItemList.isNotEmpty
? Timeline.tileBuilder(
builder: _timelineBuilderWidget(),
theme: TimelineThemeData(
nodePosition: 0.04, //居左侧距离
connectorTheme: const ConnectorThemeData(
thickness: 1.0,
color: AppColors.greyLineColor,
indent: 0.5,
),
indicatorTheme: const IndicatorThemeData(
size: 8.0,
color: AppColors.greyLineColor,
position: 0.4,
),
),
)
: NoData()),
);
}
TimelineTileBuilder _timelineBuilderWidget() {
return TimelineTileBuilder.fromStyle(
contentsAlign: ContentsAlign.basic,
itemCount: state.lockLogItemList.length,
contentsBuilder: (BuildContext context, int index) {
final DoorLockLogDataItem timelineData = state.lockLogItemList[index];
final DateTime dateTime =
DateTime.fromMillisecondsSinceEpoch(timelineData.operateDate!);
final String formattedTime =
'${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}';
return GestureDetector(
onTap: () {
Get.toNamed(Routers.doorLockLogDetailPage,
arguments: {'doorLockLogDataItem': timelineData});
},
child: Padding(
padding: EdgeInsets.only(left: 20.w, top: 20.h),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
// '$formattedTime ${timelineData.username!.isNotEmpty ? "${timelineData.username}操作" : ""}${timelineData.recordTypeName}',
timelineData.recordStr ?? '',
textAlign: TextAlign.left,
style: TextStyle(
color: Colors.black,
fontSize: 24.sp,
fontWeight: FontWeight.w600,
),
),
SizedBox(
height: 10.h,
),
videoItem(RecordListData(
recordId: state.lockLogItemList.value[index].recordId,
recordType: state.lockLogItemList.value[index].recordType,
operateDate: state.lockLogItemList.value[index].operateDate,
imagesUrl: state.lockLogItemList.value[index].imagesUrl,
videoUrl: state.lockLogItemList.value[index].videoUrl,
)),
SizedBox(
height: 20.h,
),
],
),
),
);
},
);
}
Widget videoItem(RecordListData recordData) {
return GestureDetector(
onTap: () {
if (recordData.videoUrl != null && recordData.videoUrl!.isNotEmpty) {
final lockLogItemList = state.lockLogItemList.value;
final list = lockLogItemList
.map((e) => RecordListData(
videoUrl: e.videoUrl,
imagesUrl: e.imagesUrl,
operateDate: e.operateDate,
recordId: e.recordId,
recordType: e.recordType,
))
.toList();
final selectDateString =
DateTool().dateToYMDString(state.startDate.value.toString());
final cloudStorageData =
CloudStorageData(date: selectDateString, recordList: list);
Get.toNamed(Routers.videoLogDetailPage, arguments: <String, Object>{
'recordData': recordData,
'videoDataList': [cloudStorageData]
});
} else if (recordData.imagesUrl != null &&
recordData.imagesUrl!.isNotEmpty) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FullScreenImagePage(
imageUrl: recordData.imagesUrl!,
),
),
);
}
},
child: SizedBox(
width: 260.w,
height: 260.h,
child: Column(
children: <Widget>[
Container(
width: 260.w,
height: 260.h,
margin: const EdgeInsets.all(0),
color: Colors.white,
child: ClipRRect(
borderRadius: BorderRadius.circular(10.w),
child: _buildImageOrVideoItem(recordData),
),
),
],
),
),
);
}
_buildImageOrVideoItem(RecordListData recordData) {
if (recordData.videoUrl != null && recordData.videoUrl!.isNotEmpty) {
return _buildVideoItem(recordData);
} else {
return _buildImageItem(recordData);
}
}
_buildVideoItem(RecordListData recordData) {
return VideoThumbnail(videoUrl: recordData.videoUrl!);
}
_buildImageItem(RecordListData recordData) {
return Image.network(
recordData.imagesUrl!,
fit: BoxFit.cover,
);
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
/// 路由订阅
AppRouteObserver().routeObserver.subscribe(this, ModalRoute.of(context)!);
}
@override
void dispose() {
/// 取消路由订阅
AppRouteObserver().routeObserver.unsubscribe(this);
super.dispose();
}
/// 从上级界面进入 当前界面即将出现
@override
void didPush() {
super.didPush();
state.ifCurrentScreen.value = true;
}
/// 返回上一个界面 当前界面即将消失
@override
void didPop() {
super.didPop();
logic.cancelBlueConnetctToastTimer();
if (EasyLoading.isShow) {
EasyLoading.dismiss(animation: true);
}
state.ifCurrentScreen.value = false;
}
/// 从下级返回 当前界面即将出现
@override
void didPopNext() {
super.didPopNext();
state.ifCurrentScreen.value = true;
}
/// 进入下级界面 当前界面即将消失
@override
void didPushNext() {
super.didPushNext();
logic.cancelBlueConnetctToastTimer();
if (EasyLoading.isShow) {
EasyLoading.dismiss(animation: true);
}
state.ifCurrentScreen.value = false;
}
}