fix:增加视频日志中的视频缩略图、修复监控时锁板不在线状态不变更的问题
This commit is contained in:
parent
2ee6782714
commit
5b96705633
@ -118,7 +118,10 @@ class _DoorLockLogPageState extends State<DoorLockLogPage> with RouteAware {
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(value, style: TextStyle(color: Colors.white, fontSize: 22.sp)),
|
||||
Text(
|
||||
value,
|
||||
style: TextStyle(color: Colors.white, fontSize: 22.sp),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -241,13 +244,16 @@ class _DoorLockLogPageState extends State<DoorLockLogPage> with RouteAware {
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Obx(() => XSDropDownWidget(
|
||||
Obx(
|
||||
() => XSDropDownWidget(
|
||||
items: state.getDropDownItemList,
|
||||
value: state.dropdownTitle.value,
|
||||
valueChanged: (value) {
|
||||
valueChanged: (value) async {
|
||||
state.dropdownValue.value = int.parse(value);
|
||||
logic.mockNetworkDataRequest(isRefresh: true);
|
||||
})),
|
||||
await logic.mockNetworkDataRequest(isRefresh: true);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
@ -261,24 +267,26 @@ class _DoorLockLogPageState extends State<DoorLockLogPage> with RouteAware {
|
||||
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,
|
||||
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.45,
|
||||
),
|
||||
),
|
||||
indicatorTheme: const IndicatorThemeData(
|
||||
size: 8.0,
|
||||
color: AppColors.greyLineColor,
|
||||
position: 0.4,
|
||||
),
|
||||
),
|
||||
)
|
||||
: NoData()),
|
||||
)
|
||||
: NoData(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -288,15 +296,12 @@ class _DoorLockLogPageState extends State<DoorLockLogPage> with RouteAware {
|
||||
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});
|
||||
Get.toNamed(
|
||||
Routers.doorLockLogDetailPage,
|
||||
arguments: {'doorLockLogDataItem': timelineData},
|
||||
);
|
||||
},
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 20.w, top: 20.h),
|
||||
@ -305,7 +310,6 @@ class _DoorLockLogPageState extends State<DoorLockLogPage> with RouteAware {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
// '$formattedTime ${timelineData.username!.isNotEmpty ? "${timelineData.username}操作" : ""}${timelineData.recordTypeName}',
|
||||
timelineData.recordStr ?? '',
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
@ -315,15 +319,17 @@ class _DoorLockLogPageState extends State<DoorLockLogPage> with RouteAware {
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10.h,
|
||||
height: 12.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,
|
||||
),
|
||||
),
|
||||
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,
|
||||
),
|
||||
@ -341,13 +347,15 @@ class _DoorLockLogPageState extends State<DoorLockLogPage> with RouteAware {
|
||||
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,
|
||||
))
|
||||
.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());
|
||||
@ -369,12 +377,9 @@ class _DoorLockLogPageState extends State<DoorLockLogPage> with RouteAware {
|
||||
);
|
||||
}
|
||||
},
|
||||
child: SizedBox(
|
||||
width: 260.w,
|
||||
height: 260.h,
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
child: ((recordData.imagesUrl != null && recordData.imagesUrl != '') ||
|
||||
(recordData.videoUrl != null && recordData.videoUrl != ''))
|
||||
? Container(
|
||||
width: 260.w,
|
||||
height: 260.h,
|
||||
margin: const EdgeInsets.all(0),
|
||||
@ -383,18 +388,19 @@ class _DoorLockLogPageState extends State<DoorLockLogPage> with RouteAware {
|
||||
borderRadius: BorderRadius.circular(10.w),
|
||||
child: _buildImageOrVideoItem(recordData),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
: SizedBox.shrink(),
|
||||
);
|
||||
}
|
||||
|
||||
_buildImageOrVideoItem(RecordListData recordData) {
|
||||
if (recordData.videoUrl != null && recordData.videoUrl!.isNotEmpty) {
|
||||
return _buildVideoItem(recordData);
|
||||
} else {
|
||||
} else if (recordData.imagesUrl != null &&
|
||||
recordData.imagesUrl!.isNotEmpty) {
|
||||
return _buildImageItem(recordData);
|
||||
} else {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
}
|
||||
|
||||
@ -411,12 +417,9 @@ class _DoorLockLogPageState extends State<DoorLockLogPage> with RouteAware {
|
||||
errorBuilder:
|
||||
(BuildContext context, Object error, StackTrace? stackTrace) {
|
||||
// 图片加载失败时显示错误图片
|
||||
return RotatedBox(
|
||||
quarterTurns: -1,
|
||||
child: Image.asset(
|
||||
'images/icon_unHaveData.png', // 错误图片路径
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
return Image.asset(
|
||||
'images/icon_unHaveData.png', // 错误图片路径
|
||||
fit: BoxFit.cover,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
@ -225,8 +224,13 @@ class __DerivedRecordWidgetState extends State<_DerivedRecordWidget> {
|
||||
Future<String> downloadAndSaveFile(String url) async {
|
||||
final http.Response response = await http.get(Uri.parse(url));
|
||||
if (response.statusCode == 200) {
|
||||
// 格式化日期为 yyyyMMdd 格式
|
||||
final String formattedDate =
|
||||
DateFormat('yyyyMMdd').format(DateTime.now());
|
||||
|
||||
final Directory directory = await getApplicationDocumentsDirectory();
|
||||
final File file = File('${directory.path}/record.xlsx');
|
||||
final File file =
|
||||
File('${directory.path}/openLockRecord_${formattedDate}.xlsx');
|
||||
await file.writeAsBytes(response.bodyBytes);
|
||||
return file.path;
|
||||
} else {
|
||||
|
||||
@ -34,7 +34,7 @@ class UdpTalkHangUpHandler extends ScpMessageBaseHandle
|
||||
talkePingOverTimeTimerManager.cancel();
|
||||
talkDataOverTimeTimerManager.cancel();
|
||||
|
||||
EasyLoading.showToast('已挂断'.tr);
|
||||
// EasyLoading.showToast('已挂断'.tr);
|
||||
Get.back();
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ import 'dart:async';
|
||||
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/app_settings/app_settings.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/talk_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/talk_status.dart';
|
||||
import 'package:star_lock/talk/startChart/start_chart_manage.dart';
|
||||
@ -27,7 +28,9 @@ class TalkePingOverTimeTimerManager {
|
||||
|
||||
// 超时处理函数
|
||||
static void _handleTalkePingOverTime() {
|
||||
if (talkStatus.status == TalkStatus.answeredSuccessfully) {
|
||||
// 如果是接听中或者是主动呼叫等待接听状态
|
||||
if (talkStatus.status == TalkStatus.answeredSuccessfully ||
|
||||
talkStatus.status == TalkStatus.proactivelyCallWaitingAnswer) {
|
||||
EasyLoading.showToast('通话异常中断'.tr, duration: 2000.milliseconds);
|
||||
// 停止发送通话保持的命令
|
||||
StartChartManage().stopTalkPingMessageTimer();
|
||||
@ -42,6 +45,7 @@ class TalkePingOverTimeTimerManager {
|
||||
|
||||
// 启动定时器
|
||||
void start() {
|
||||
AppLog.log('启动talkping判断');
|
||||
// 取消之前的定时器
|
||||
_timer?.cancel();
|
||||
_timer = Timer(timeout, onTimeout);
|
||||
|
||||
@ -57,6 +57,7 @@ class ScpMessageBaseHandle {
|
||||
ToPeerId: scpMessage.FromPeerId!,
|
||||
FromPeerId: scpMessage.ToPeerId!,
|
||||
PayloadType: scpMessage.PayloadType!,
|
||||
messageId: scpMessage.MessageId!,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -421,6 +421,9 @@ class StartChartManage {
|
||||
},
|
||||
);
|
||||
talkStatus.setProactivelyCallWaitingAnswer();
|
||||
startTalkPingMessageTimer();
|
||||
// 启动是否收到ping超时判断定时器
|
||||
talkePingOverTimeTimerManager.start();
|
||||
}
|
||||
|
||||
/// 停止持续发送对讲请求
|
||||
@ -597,15 +600,20 @@ class StartChartManage {
|
||||
}
|
||||
|
||||
// 回复成功消息
|
||||
void sendGenericRespSuccessMessage(
|
||||
{required String ToPeerId,
|
||||
required String FromPeerId,
|
||||
required int PayloadType}) async {
|
||||
void sendGenericRespSuccessMessage({
|
||||
required String ToPeerId,
|
||||
required String FromPeerId,
|
||||
required int PayloadType,
|
||||
required int messageId,
|
||||
}) async {
|
||||
if (messageId == null) {
|
||||
messageId = MessageCommand.getNextMessageId(ToPeerId, increment: false);
|
||||
}
|
||||
final message = MessageCommand.genericRespSuccessMessage(
|
||||
ToPeerId: ToPeerId,
|
||||
FromPeerId: FromPeerId,
|
||||
PayloadType: PayloadType,
|
||||
MessageId: MessageCommand.getNextMessageId(ToPeerId, increment: false),
|
||||
MessageId: messageId,
|
||||
);
|
||||
await _sendMessage(message: message);
|
||||
}
|
||||
|
||||
@ -122,15 +122,15 @@ class _XSDropDownWidgetState extends State<XSDropDownWidget> {
|
||||
child: Container(
|
||||
margin:
|
||||
EdgeInsets.only(left: 0.w, right: 0, top: 0, bottom: 0),
|
||||
color: item.itemValue == currentValue
|
||||
? AppColors.mainColor
|
||||
: null, // 设置选中项背景色为蓝色
|
||||
// color: item.itemValue == currentValue
|
||||
// ? AppColors.mainColor
|
||||
// : null, // 设置选中项背景色为蓝色
|
||||
child: Text(
|
||||
item.itemTitle,
|
||||
style: TextStyle(
|
||||
fontSize: 24.sp,
|
||||
color: item.itemValue == currentValue
|
||||
? Colors.white
|
||||
? AppColors.mainColor
|
||||
: Colors.black, // 设置选中项文字颜色为白色
|
||||
),
|
||||
),
|
||||
|
||||
16
pubspec.lock
16
pubspec.lock
@ -1148,6 +1148,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.6"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: nested
|
||||
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
network_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -1388,6 +1396,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "21.1.2"
|
||||
provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: provider
|
||||
sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.2"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user