diff --git a/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart b/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart index 0a136aa8..c0500019 100755 --- a/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart +++ b/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart @@ -82,8 +82,7 @@ class _DoorLockLogPageState extends State with RouteAware { backgroundColor: AppColors.mainColor, actionsList: [ Visibility( - visible: CommonDataManage().currentKeyInfo.isLockOwner == 1 || - CommonDataManage().currentKeyInfo.keyRight == 1, + visible: CommonDataManage().currentKeyInfo.isLockOwner == 1 || CommonDataManage().currentKeyInfo.keyRight == 1, child: GestureDetector( child: Image.asset( 'images/icon_tips_Q.png', @@ -92,27 +91,20 @@ class _DoorLockLogPageState extends State with RouteAware { color: Colors.white, ), onTap: () { - ShowTipView().showSureAlertDialog( - '1.锁没有联网,密码、IC卡、指纹等开门记录无法实时上传,可以点击右上角按钮,然后读取记录。'.tr + - '\n' + - '2.如果您需要保留历史记录,可以点击右上角按钮,然后导出记录'.tr, - tipTitle: '看不到操作记录,可能原因有'.tr, - sureStr: '我知道了'.tr); + ShowTipView().showSureAlertDialog('1.锁没有联网,密码、IC卡、指纹等开门记录无法实时上传,可以点击右上角按钮,然后读取记录。'.tr + '\n' + '2.如果您需要保留历史记录,可以点击右上角按钮,然后导出记录'.tr, + tipTitle: '看不到操作记录,可能原因有'.tr, sureStr: '我知道了'.tr); }, )), Visibility( - visible: CommonDataManage().currentKeyInfo.isLockOwner == 1 || - CommonDataManage().currentKeyInfo.keyRight == 1, + visible: CommonDataManage().currentKeyInfo.isLockOwner == 1 || CommonDataManage().currentKeyInfo.keyRight == 1, child: PopupMenuButton( onSelected: _onMenuItemSelected, color: Colors.black, itemBuilder: (BuildContext context) { return >[ _buildCustomPopupMenuItem('读取记录'.tr), - if (CommonDataManage().currentKeyInfo.isLockOwner == 1) - const PopupMenuDivider(), - if (CommonDataManage().currentKeyInfo.isLockOwner == 1) - _buildCustomPopupMenuItem('清空记录'.tr), + if (CommonDataManage().currentKeyInfo.isLockOwner == 1) const PopupMenuDivider(), + if (CommonDataManage().currentKeyInfo.isLockOwner == 1) _buildCustomPopupMenuItem('清空记录'.tr), const PopupMenuDivider(), _buildCustomPopupMenuItem('导出记录'.tr), ]; @@ -130,11 +122,7 @@ class _DoorLockLogPageState extends State with RouteAware { body: Column( mainAxisSize: MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.start, - children: [ - topAdvancedCalendarWidget(), - eventDropDownWidget(), - Expanded(child: timeLineView()) - ], + children: [topAdvancedCalendarWidget(), eventDropDownWidget(), Expanded(child: timeLineView())], ), floatingActionButton: Visibility( visible: _isAtBottom, @@ -193,8 +181,7 @@ class _DoorLockLogPageState extends State with RouteAware { builder: (BuildContext context) { return ExportRecordDialog( onExport: (String filePath) { - Get.toNamed(Routers.exportSuccessPage, - arguments: {'filePath': filePath}); + Get.toNamed(Routers.exportSuccessPage, arguments: {'filePath': filePath}); }, ); }, @@ -271,8 +258,7 @@ class _DoorLockLogPageState extends State with RouteAware { String formatTimestampToDateTimeYYYYMMDD(int timestampMs) { DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(timestampMs); - DateFormat formatter = - DateFormat('MM${'月'.tr}dd${'日'.tr}'); // 格式:2025-08-18 14:30 + DateFormat formatter = DateFormat('MM${'月'.tr}dd${'日'.tr}'); // 格式:2025-08-18 14:30 return formatter.format(dateTime); } @@ -300,103 +286,71 @@ class _DoorLockLogPageState extends State with RouteAware { final recordType = item.recordType; switch (recordType) { case 10: - if (item.username != null && item.username != '') { - return '${formatTimestampToHHmm(item.operateDate!)} ' + - '指纹'.tr + - '开锁'.tr + - '(ID:${item.username})'; - } else { - return item.recordStr ?? ''; - } + return '${formatTimestampToHHmm(item.operateDate!)} ' + '指纹'.tr + '开锁'.tr + '(${_formatUserNameOrId(item)})'; case 20: return '${formatTimestampToHHmm(item.operateDate!)} ' + '密码'.tr + '开锁'.tr + - '(${'昵称'.tr}:${item.username})' + + '(${_formatUserNameOrId(item)})' + '(${'密码'.tr}:${item.keyboardPwd})'; case 30: - return '${formatTimestampToHHmm(item.operateDate!)} ' + - '卡'.tr + - '开锁'.tr + - '(${'昵称'.tr}:${item.username})'; + return '${formatTimestampToHHmm(item.operateDate!)} ' + '卡'.tr + '开锁'.tr + '(${_formatUserNameOrId(item)})'; case 40: if (item.username != null && item.username != '') { - return '${formatTimestampToHHmm(item.operateDate!)} ' + - '蓝牙'.tr + - '开锁'.tr + - '(' + - '${'昵称'.tr}'.tr + - ':${item.username})'; + return '${formatTimestampToHHmm(item.operateDate!)} ' + '蓝牙'.tr + '开锁'.tr + '(${_formatUserNameOrId(item)})'; } else { - return '${formatTimestampToHHmm(item.operateDate!)} ' + - '蓝牙'.tr + - '开锁'.tr + - '(' + - 'ID'.tr + - ':${item.userid})'; + return '${formatTimestampToHHmm(item.operateDate!)} ' + '蓝牙'.tr + '开锁'.tr + '(' + 'ID'.tr + ':${item.userid})'; } - case 50: - return '${formatTimestampToHHmm(item.operateDate!)} ' + - '组合模式'.tr + - '开锁'.tr + - '(${'昵称'.tr}:${item.username})'; + return '${formatTimestampToHHmm(item.operateDate!)} ' + '组合模式'.tr + '开锁'.tr + '(${_formatUserNameOrId(item)})'; case 60: - return '${formatTimestampToHHmm(item.operateDate!)} ' + - '添加'.tr + - '指纹'.tr + - '(${'昵称'.tr}:${item.username})'; + return '${formatTimestampToHHmm(item.operateDate!)} ' + '添加'.tr + '指纹'.tr + '(${_formatUserNameOrId(item)})'; case 70: - return '${formatTimestampToHHmm(item.operateDate!)} ' + - '添加'.tr + - '密码'.tr + - '(${'昵称'.tr}:${item.username})'; + return '${formatTimestampToHHmm(item.operateDate!)} ' + '添加'.tr + '密码'.tr + '(${_formatUserNameOrId(item)})'; case 80: - return '${formatTimestampToHHmm(item.operateDate!)} ' + - '添加'.tr + - '卡'.tr + - '(${'昵称'.tr}:${item.username})'; + return '${formatTimestampToHHmm(item.operateDate!)} ' + '添加'.tr + '卡'.tr + '(${_formatUserNameOrId(item)})'; case 90: - return '${formatTimestampToHHmm(item.operateDate!)} ' + - '删除'.tr + - '指纹'.tr + - '(${'昵称'.tr}:${item.username})'; + return '${formatTimestampToHHmm(item.operateDate!)} ' + '删除'.tr + '指纹'.tr + '(${_formatUserNameOrId(item)})'; case 100: - return '${formatTimestampToHHmm(item.operateDate!)} ' + - '删除'.tr + - '密码'.tr + - '(${'昵称'.tr}:${item.username})'; + return '${formatTimestampToHHmm(item.operateDate!)} ' + '删除'.tr + '密码'.tr + '(${_formatUserNameOrId(item)})'; case 110: - return '${formatTimestampToHHmm(item.operateDate!)} ' + - '删除'.tr + - '卡'.tr + - '(${'昵称'.tr}:${item.username})'; + return '${formatTimestampToHHmm(item.operateDate!)} ' + '删除'.tr + '卡'.tr + '(${_formatUserNameOrId(item)})'; case 160: - return '${formatTimestampToHHmm(item.operateDate!)} ' + - '人脸'.tr + - '开锁'.tr + - '(${'昵称'.tr}:${item.username})'; + return '${formatTimestampToHHmm(item.operateDate!)} ' + '人脸'.tr + '开锁'.tr + '(${_formatUserNameOrId(item)})'; case 190: - return '${formatTimestampToHHmm(item.operateDate!)} ' + - '胁迫指纹'.tr + - '开锁'.tr + - '(${'昵称'.tr}:${item.username})'; + return '${formatTimestampToHHmm(item.operateDate!)} ' + '胁迫指纹'.tr + '开锁'.tr + '(${_formatUserNameOrId(item)})'; case 200: - return '${formatTimestampToHHmm(item.operateDate!)} ' + - '胁迫密码'.tr + - '开锁'.tr + - '(${'昵称'.tr}:${item.username})'; + return '${formatTimestampToHHmm(item.operateDate!)} ' + '胁迫密码'.tr + '开锁'.tr + '(${_formatUserNameOrId(item)})'; case 210: - return '${formatTimestampToHHmm(item.operateDate!)} ' + - '胁迫卡片'.tr + - '开锁'.tr + - '(${'昵称'.tr}:${item.username})'; + return '${formatTimestampToHHmm(item.operateDate!)} ' + '胁迫卡片'.tr + '开锁'.tr + '(${_formatUserNameOrId(item)})'; default: return item.recordStr ?? ''; } } + // 提取为私有方法,更清晰 + String _formatUserNameOrId(DoorLockLogDataItem item) { + final recordStr = item.recordStr; + final idMatch = RegExp(r'ID[::](\w+)').firstMatch(recordStr ?? ''); + final idValue = idMatch?.group(1) ?? ''; + + final name = item.username ?? ''; + + // 如果用户名不为空,并且是以 ID: 或 ID: 开头的格式,则直接返回 ID:xxx + if (name.isNotEmpty) { + final idInNameMatch = RegExp(r'^ID[::].+').hasMatch(name); + if (idInNameMatch) { + return name; // 直接返回,例如 "ID:123" + } else { + return '${'昵称'.tr}:$name'; // 正常用户昵称,加前缀 + } + } + + // 如果用户名为空,使用 recordStr 中提取的 ID + return 'ID:$idValue'; + } + Color _buildTextColorByType(DoorLockLogDataItem item) { final recordType = item.recordType; switch (recordType) { @@ -420,12 +374,9 @@ class _DoorLockLogPageState extends State with RouteAware { contentsBuilder: (BuildContext context, int index) { final DoorLockLogDataItem timelineData = state.lockLogItemList[index]; // 👇 提前计算第一个有 videoUrl 的索引(可以在 build 外层计算一次,避免重复) - int? firstVideoIndex = state.lockLogItemList - .indexWhere((item) => _checkIsVideoOrImagesType(item)); + int? firstVideoIndex = state.lockLogItemList.indexWhere((item) => _checkIsVideoOrImagesType(item)); bool isInvalid = _checkIsVideoOrImagesType(timelineData) && - ((timelineData.imagesUrl == null && - timelineData.videoUrl == null) || - (timelineData.videoUrl == '' && timelineData.imagesUrl == '')); + ((timelineData.imagesUrl == null && timelineData.videoUrl == null) || (timelineData.videoUrl == '' && timelineData.imagesUrl == '')); String typeText = ''; if (timelineData.recordType == 130) { @@ -446,8 +397,7 @@ class _DoorLockLogPageState extends State with RouteAware { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - '${formatTimestampToDateTimeYYYYMMDD(timelineData.operateDate!)}', + Text('${formatTimestampToDateTimeYYYYMMDD(timelineData.operateDate!)}', style: TextStyle( fontSize: 20.sp, )), @@ -464,12 +414,7 @@ class _DoorLockLogPageState extends State with RouteAware { ), children: [ TextSpan( - text: _buildIDByType(timelineData) + - (isInvalid - ? '(${typeText}' + - '已失效'.tr + - ')' - : ''), + text: _buildIDByType(timelineData) + (isInvalid ? '(${typeText}' + '已失效'.tr + ')' : ''), ), WidgetSpan( alignment: PlaceholderAlignment.middle, @@ -504,8 +449,7 @@ class _DoorLockLogPageState extends State with RouteAware { height: 12.h, ), Visibility( - visible: _checkIsVideoOrImagesType(timelineData) && - index == firstVideoIndex, + visible: _checkIsVideoOrImagesType(timelineData) && index == firstVideoIndex, child: GestureDetector( onTap: () async { await logic.getWebPlayUrl(); @@ -580,9 +524,7 @@ class _DoorLockLogPageState extends State with RouteAware { if (recordData.videoUrl != null && recordData.videoUrl!.isNotEmpty) { final lockLogItemList = state.lockLogItemList.value; final list = lockLogItemList - .where((e) => - (e.videoUrl != null && e.videoUrl!.isNotEmpty) || - (e.imagesUrl != null && e.imagesUrl!.isNotEmpty)) + .where((e) => (e.videoUrl != null && e.videoUrl!.isNotEmpty) || (e.imagesUrl != null && e.imagesUrl!.isNotEmpty)) .map( (e) => RecordListData( videoUrl: e.videoUrl, @@ -593,16 +535,13 @@ class _DoorLockLogPageState extends State with RouteAware { ), ) .toList(); - final selectDateString = - DateTool().dateToYMDString(state.startDate.value.toString()); - final cloudStorageData = - CloudStorageData(date: selectDateString, recordList: list); + final selectDateString = DateTool().dateToYMDString(state.startDate.value.toString()); + final cloudStorageData = CloudStorageData(date: selectDateString, recordList: list); Get.toNamed(Routers.videoLogDetailPage, arguments: { 'recordData': recordData, 'videoDataList': [cloudStorageData] }); - } else if (recordData.imagesUrl != null && - recordData.imagesUrl!.isNotEmpty) { + } else if (recordData.imagesUrl != null && recordData.imagesUrl!.isNotEmpty) { Navigator.push( context, MaterialPageRoute( @@ -613,8 +552,7 @@ class _DoorLockLogPageState extends State with RouteAware { ); } }, - child: ((recordData.imagesUrl != null && recordData.imagesUrl != '') || - (recordData.videoUrl != null && recordData.videoUrl != '')) + child: ((recordData.imagesUrl != null && recordData.imagesUrl != '') || (recordData.videoUrl != null && recordData.videoUrl != '')) ? Container( width: 260.w, height: 260.h, @@ -632,8 +570,7 @@ class _DoorLockLogPageState extends State with RouteAware { _buildImageOrVideoItem(RecordListData recordData) { if (recordData.videoUrl != null && recordData.videoUrl!.isNotEmpty) { return _buildVideoItem(recordData); - } else if (recordData.imagesUrl != null && - recordData.imagesUrl!.isNotEmpty) { + } else if (recordData.imagesUrl != null && recordData.imagesUrl!.isNotEmpty) { return _buildImageItem(recordData); } else { return SizedBox.shrink(); @@ -650,8 +587,7 @@ class _DoorLockLogPageState extends State with RouteAware { child: Image.network( recordData.imagesUrl!, fit: BoxFit.cover, - errorBuilder: - (BuildContext context, Object error, StackTrace? stackTrace) { + errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) { // 图片加载失败时显示错误图片 return Image.asset( 'images/icon_unHaveData.png', // 错误图片路径 @@ -749,11 +685,8 @@ class _DoorLockLogPageState extends State with RouteAware { print('外部收到选中: $date'); state.operateDate = date.millisecondsSinceEpoch; - state.startDate.value = - DateTime(date.year, date.month, date.day).millisecondsSinceEpoch; - state.endDate.value = - DateTime(date.year, date.month, date.day, 23, 59, 59, 999) - .millisecondsSinceEpoch; + state.startDate.value = DateTime(date.year, date.month, date.day).millisecondsSinceEpoch; + state.endDate.value = DateTime(date.year, date.month, date.day, 23, 59, 59, 999).millisecondsSinceEpoch; await logic.mockNetworkDataRequest(isRefresh: true); }, onWeekChanged: (DateTime start, DateTime end) {