app-starlock/lib/mine/message/messageList/messageList_page.dart
sky_min e1c1ee0d38 1.设备时区转化
2.消息列表优化
2025-11-05 17:57:56 +08:00

487 lines
20 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_screenutil/flutter_screenutil.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:get/get.dart';
import 'package:star_lock/mine/message/messageList/messageList_state.dart';
import 'package:star_lock/tools/eventBusEventManage.dart';
import 'package:star_lock/tools/noData.dart';
import '../../../appRouters.dart';
import '../../../app_settings/app_colors.dart';
import '../../../tools/EasyRefreshTool.dart';
import '../../../tools/dateTool.dart';
import '../../../tools/showTipView.dart';
import '../../../tools/storage.dart';
import '../../../tools/titleAppBar.dart';
import 'messageList_entity.dart';
import 'messageList_logic.dart';
class MessageListPage extends StatefulWidget {
MessageListPage({Key? key, this.showAppBar = true}) : super(key: key);
bool showAppBar;
@override
State<MessageListPage> createState() => _MessageListPageState();
}
class _MessageListPageState extends State<MessageListPage>
with TickerProviderStateMixin {
final MessageListLogic logic = Get.put(MessageListLogic());
final MessageListState state = Get.find<MessageListLogic>().state;
// 修改 _showCheckboxes 状态变量为可观察状态
final RxBool _showCheckboxes = false.obs;
// 添加选中状态
final RxList<bool> _selectedItems = <bool>[].obs;
// 添加控制通知横幅显示的状态
bool showNotificationBanner = true;
// 添加设置状态变量
final RxBool _pushNotificationEnabled = false.obs;
// 删除方法
void deleteSelectedMessages() {
final List<MessageItemEntity> selectedMessages = [];
for (int i = 0; i < state.itemDataList.value.length; i++) {
if (_selectedItems[i]) {
selectedMessages.add(state.itemDataList.value[i]);
}
}
// 调用删除接口
//logic.deletMessageDataRequest(selectedMessages);
// 清空选中状态
_selectedItems.clear();
_selectedItems.addAll(
List.generate(state.itemDataList.value.length, (index) => false));
_showCheckboxes.value = false;
setState(() {});
}
void getHttpData() {
logic.messageListDataRequest().then((MessageListEntity value) {
setState(() {});
});
}
@override
void initState() {
super.initState();
// 获取当前消息推送设置状态
_loadPushNotificationStatus();
getHttpData();
}
// 加载消息推送状态
void _loadPushNotificationStatus() async {
final bool? enabled = await Storage.getBool('push_notification_enabled');
_pushNotificationEnabled.value = enabled ?? false;
}
//添加以时间分组的方法
Map<String, List<MessageItemEntity>> _groupMessagesByDate() {
Map<String, List<MessageItemEntity>> grouped = {};
state.itemDataList.forEach((item) {
String date = DateTool().dateToYMDString(item.createdAt!.toString());
if (!grouped.containsKey(date)) {
grouped[date] = [];
}
grouped[date]!.add(item);
});
return grouped;
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.mainBackgroundColor,
appBar: widget.showAppBar
? TitleAppBar(
barTitle: '消息'.tr,
haveBack: true,
actionsList: <Widget>[
TextButton(
child: Text(
'清空'.tr,
style: TextStyle(color: Colors.white, fontSize: 24.sp),
),
onPressed: () async {
final bool? isDemoMode =
await Storage.getBool(ifIsDemoModeOrNot);
if (isDemoMode == false) {
ShowTipView().showIosTipWithContentDialog('是否清空?'.tr,
() async {
logic.deletAllMessageDataRequest();
});
} else {
logic.showToast('演示模式'.tr);
}
},
),
],
backgroundColor: AppColors.mainColor)
: null,
body: EasyRefreshTool(onRefresh: () {
logic.pageNo = 1;
getHttpData();
}, onLoad: () {
getHttpData();
}, child: Obx(() {
return state.itemDataList.value.isEmpty
? NoData()
: Stack(
children: [
Positioned(
top: 0,
left: 0,
right: 0,
child: Container(
height: showNotificationBanner ? 100 : 70,
child: Column(children: [
showNotificationBanner
? Container(
padding:
EdgeInsets.only(left: 10, right: 10),
color: AppColors.messageTipsColor,
height: 30,
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text('开启消息通知开关,及时获取通知',
style: TextStyle(
color: Colors.black,
fontSize: 20.sp)),
Row(children: [
!_pushNotificationEnabled.value
? GestureDetector(child: Text('去开启',
style: TextStyle(
color: Colors.blue,
fontSize: 20.sp)),
onTap: (){
Get.toNamed(Routers.mineSetPage);
}) : SizedBox.shrink(),
SizedBox(width: 10),
InkWell(
child: Image.asset(
'images/mine/icon_message_close.png',
width: 24.w,
height: 24.w),
onTap: () {
// 可以通过控制一个状态变量来隐藏整个通知栏
setState(() {
showNotificationBanner =
false;
});
}),
])
]))
: SizedBox.shrink(),
Container(
padding:
EdgeInsets.only(left: 15.w, right: 24.w, top: 20.h),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text('告警',
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 30.sp)),
// 点击多选可以进行删除
// GestureDetector(
// onTap: () {
// // 没有多选删除的 api接口无法使用
// // if (_showCheckboxes.value) {
// // deleteSelectedMessages();
// // } else {
// // setState(() {
// // _showCheckboxes.value =
// // !_showCheckboxes.value;
// // });
// // }
// },
// child: _showCheckboxes.value
// ? Text('删除',
// style: TextStyle(
// fontSize: 24.sp,
// color: Colors.red))
// : Image.asset(
// 'images/mine/icon_message_checbox.png',
// width: 30.w,
// height: 30.h),
// )
]),
)
]))),
Container(
child: Container(
padding: EdgeInsets.only(
top: showNotificationBanner ? 80 : 50),
child: ListView.builder(
itemCount: _buildGroupedListItems().length,
itemBuilder: (BuildContext context, int index) {
var item = _buildGroupedListItems()[index];
if (item is String) {
// 日期标题
return Container(
padding: EdgeInsets.symmetric(
horizontal: 16.w, vertical: 10.h),
color: AppColors.mainBackgroundColor,
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: item.substring(8, 10),
style: TextStyle(
color: Colors.black,
fontSize: 36.sp,
fontWeight: FontWeight.w600,
),
),
TextSpan(
text: ' ',
),
TextSpan(
text: item.substring(5, 7),
style: TextStyle(
color: Colors.grey, fontSize: 20.sp, fontWeight: FontWeight.w400),
),
],
),
),
);
} else if (item is MessageItemEntity) {
// 消息项
return _messageListItem(item, () {
Get.toNamed(Routers.messageDetailPage,
arguments: <String, MessageItemEntity>{
'messageItemEntity': item
});
});
}
return Container();
},
),
),
)
],
);
})),
);
}
// 构建分组列表
List<dynamic> _buildGroupedListItems() {
List<dynamic> items = [];
Map<String, List<MessageItemEntity>> grouped = _groupMessagesByDate();
grouped.forEach((date, messages) {
items.add(date); // 添加日期标题
items.addAll(messages.map((message) => message)); // 添加该日期下的所有消息
});
// 初始化选中状态
if (_selectedItems.length != state.itemDataList.value.length) {
_selectedItems.clear();
_selectedItems.addAll(
List.generate(state.itemDataList.value.length, (index) => false));
}
return items;
}
Widget _messageListItem(
MessageItemEntity messageItemEntity, Function() action) {
final int index = state.itemDataList.value.indexOf(messageItemEntity);
// 查找当前消息在其所属日期分组中的位置
Map<String, List<MessageItemEntity>> grouped = _groupMessagesByDate();
bool isLastInGroupSimple = false;
// 确定当前消息属于哪个日期分组
for (var entry in grouped.entries) {
int messageIndex = entry.value.indexWhere((msg) => msg.id == messageItemEntity.id);
if (messageIndex != -1) {
// 如果是该分组的最后一条消息
isLastInGroupSimple = messageIndex == entry.value.length - 1;
break;
}
}
return GestureDetector(
onTap: () {
// 如果是多选模式,切换选中状态
if (_showCheckboxes.value) {
_selectedItems[index] = !_selectedItems[index];
setState(() {});
} else {
// 否则跳转到详情页
action();
}
},
child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
Container(
padding: EdgeInsets.only(left: 10),
transform: Matrix4.translationValues(0, 20, 0),
child: Column(
children: [
Image.asset(
messageItemEntity.readAt! == 0
? 'images/mine/icon_message_unread.png'
: 'images/mine/icon_message_readed.png',
width: 18.w,
height: 18.h),
// 添加竖线,根据是否是分组最后一条消息来决定是否显示
if (!isLastInGroupSimple)
Container(
width: 0.5,
height: 190.h,
color: AppColors.placeholderTextColor,
)
],
)),
Expanded(
child: Slidable(
key: Key(messageItemEntity.id.toString()), // 为每个item添加唯一key
endActionPane: ActionPane(
motion: const ScrollMotion(),
children: [
SlidableAction(
onPressed: (context) {
// 删除单条消息
logic.deletMessageDataRequest(
messageItemEntity.id!, () {
logic.pageNo = 1;
getHttpData();
});
},
backgroundColor: Colors.red,
foregroundColor: Colors.white,
icon: Icons.delete,
label: '删除',
),
],
), child: Container(
width: 1.sw,
margin: EdgeInsets.all(20.h),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10.w),
),
child: Container(
width: 1.sw,
margin: EdgeInsets.only(left: 20.w, right: 20.w, top: 8.h),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// SizedBox(height: 4.h),
// Row(
// children: <Widget>[
// Flexible(
// child: Text(
// // 调用请求标题
// '远程开门请求',
// maxLines: 1,
// overflow: TextOverflow.ellipsis,
// style: TextStyle(
// fontSize: 22.sp,
// color: messageItemEntity.readAt! == 0
// ? AppColors.blackColor
// : AppColors.placeholderTextColor),
// ),
// ),
// ],
// ),
// SizedBox(height: 4.h),
Wrap(
children: <Widget>[
// if (messageItemEntity.readAt! == 0)
// Container(
// width: 10.w,
// height: 10.w,
// decoration: BoxDecoration(
// color: Colors.red,
// borderRadius: BorderRadius.circular(5.w),
// ),
// )
// else
// Container(),
// if (messageItemEntity.readAt! == 0)
// SizedBox(width: 5.w)
// else
// Container(),
Container(
margin: EdgeInsets.only(top: 4.h),
child: Text(
DateTool().dateToHnString(messageItemEntity.createdAt!.toString()),
style: TextStyle(
fontSize: 20.sp,
color: messageItemEntity.readAt! == 0
? AppColors.blackColor
: AppColors.placeholderTextColor,
),
),
),
Container(
width: 1,
height: 10,
margin: EdgeInsets.only(left: 5.w, right: 5.w, top: 10.h),
color: messageItemEntity.readAt! == 0
? AppColors.blackColor
: AppColors.placeholderTextColor,
),
Container(transform: Matrix4.translationValues(0, -18, 0),
child: Text(' ${messageItemEntity.data!}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 20.sp,
color: messageItemEntity.readAt! == 0
? AppColors.blackColor
: AppColors.placeholderTextColor,
),
)),
Container(transform: Matrix4.translationValues(0, -8, 0), child: GestureDetector(
child: Text('点击查看', style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20.sp, color: AppColors.mainColor),),
),alignment: Alignment.centerRight,)
],
),
// SizedBox(height: 5.h),
// Row(
// mainAxisAlignment: MainAxisAlignment.start,
// children: <Widget>[
// // Image.asset('images/mine/icon_mine_gatewaySignal_strong.png', width: 40.w, height: 40.w,),
// // SizedBox(width: 10.w,),
// Text(
// DateTool().dateToHnString(messageItemEntity
// .createdAt!
// .toString()),
// style: TextStyle(
// fontSize: 18.sp,
// color: messageItemEntity.readAt! == 0
// ? AppColors.blackColor
// : AppColors.placeholderTextColor)),
// ],
// ),
// SizedBox(width: 20.h),
]))))),
// 显示选中状态的复选框
if (_showCheckboxes.value)
Checkbox(
value: _selectedItems[index],
activeColor: Colors.blue,
onChanged: (val) {
_selectedItems[index] = val!;
setState(() {});
},
)
]));
}
}