starwork_flutter/lib/views/messages/messages_view.dart

426 lines
13 KiB
Dart
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/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:starwork_flutter/base/app_permission.dart';
import 'messages_controller.dart';
import 'messages_model.dart';
class MessagesView extends GetView<MessagesController> {
const MessagesView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFF6F7FB),
body: SafeArea(
child: Container(
width: 1.sw,
padding: EdgeInsets.symmetric(horizontal: 15.w, vertical: 4.h),
child: Column(
children: [
// 固定的上半部分
_buildPageHead(context),
_buildSystemNotificationPermissionRow(),
Obx(
() => Visibility(
visible: controller
.homeController.isOpenNotificationPermission.value,
child: SizedBox(
height: 10.h,
),
),
),
// 消息列表
Expanded(
child: _buildRefreshableMessageList(),
),
],
),
),
),
);
}
_buildPageHead(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// 左侧标题区域
Expanded(
child: GestureDetector(
onTap: () {
controller.mainController.scaffoldKey.currentState?.openDrawer();
},
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: Text(
'19104656的互12312联',
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w600,
color: Colors.black87,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
),
Icon(
Icons.arrow_right_rounded,
size: 22.sp,
),
],
),
),
),
// 右侧功能按钮区域
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.min,
children: [
// 清除未读按钮
Flexible(
child: GestureDetector(
onTap: () {
// 处理清除未读点击事件
controller.clearAllUnread();
print('清除未读被点击');
},
child: Container(
padding: EdgeInsets.symmetric(
horizontal: 6.w, // 减小内边距
vertical: 3.h,
),
decoration: BoxDecoration(
color: const Color(0xFFF0F0F0),
borderRadius: BorderRadius.circular(12.r),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: Text(
'清除未读',
style: TextStyle(
fontSize: 12.sp, // 减小字体
color: Colors.black54,
fontWeight: FontWeight.w400,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
),
],
),
),
),
),
// 分隔线
Container(
height: 16.h, // 减小高度
width: 1.w,
color: Colors.grey.withOpacity(0.3),
),
// 通知设置按钮
Flexible(
child: GestureDetector(
onTap: () {
// 处理通知设置点击事件
print('通知设置被点击');
},
child: Text(
'通知设置',
style: TextStyle(
fontSize: 14.sp, // 减小字体
color: Colors.black,
fontWeight: FontWeight.w400,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
),
),
],
),
),
],
);
}
_buildSystemNotificationPermissionRow() {
return Obx(
() => Visibility(
visible: !controller.homeController.isOpenNotificationPermission.value,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 4.h),
decoration: BoxDecoration(
color: const Color(0xFFFEF2E5),
borderRadius: BorderRadius.all(
Radius.circular(8.r),
),
),
margin: EdgeInsets.symmetric(vertical: 8.h),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'系统通知未开启,报警消息无法通知'.tr,
style: TextStyle(
color: const Color(0xFFEE9846),
fontSize: 12.sp,
),
),
const Spacer(),
GestureDetector(
onTap: () async {
controller.homeController.isOpenNotificationPermission.value =
await AppPermission.requestNotificationPermission();
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 6.w, vertical: 4.h),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(4.r),
),
),
child: Text(
'去开启'.tr,
style: TextStyle(
color: const Color(0xFFEE9846),
fontSize: 12.sp,
),
),
),
),
SizedBox(
width: 14.w,
),
GestureDetector(
onTap: () {
controller.homeController.isOpenNotificationPermission.value =
true;
},
child: Icon(
Icons.cancel,
color: const Color(0xFFEE9846),
size: 18.sp,
),
)
],
),
),
),
);
}
_buildRefreshableMessageList() {
return RefreshIndicator(
onRefresh: _onRefresh,
// 基础样式配置
color: const Color(0xFF4A90E2),
// 刷新指示器颜色
backgroundColor: Colors.white,
// 背景颜色
// 控制下拉触发距离的关键属性
displacement: 60.0,
// 刷新指示器距离顶部的距离默认40.0
edgeOffset: 0.0,
// 边缘偏移量默认0.0
// 控制下拉幅度的关键属性
triggerMode: RefreshIndicatorTriggerMode.onEdge,
// 触发模式
// RefreshIndicatorTriggerMode.onEdge: 在边缘触发(默认)
// RefreshIndicatorTriggerMode.anywhere: 在任何位置都可以触发
// 描边宽度
strokeWidth: 2.5,
// 刷新指示器的描边宽度默认2.0
// 语义标签(用于无障碍功能)
semanticsLabel: '下拉刷新消息列表',
semanticsValue: '刷新中...',
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(
// 控制滚动物理特性
parent: BouncingScrollPhysics(), // 添加弹性滚动效果
),
child: Column(
children: [
_buildMessageList(),
SizedBox(height: 16.h),
_buildMessageTip(),
],
),
),
);
}
Future<void> _onRefresh() async {
// 调用controller的刷新方法
await controller.refreshMessages();
}
_buildMessageList() {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8.r),
),
child: Obx(
() => Column(
children: [
// 动态生成消息列表项
...controller.messageList.asMap().entries.map((entry) {
int index = entry.key;
MessageItem message = entry.value;
return Column(
children: [
_buildMessageItem(
message: message,
onTap: () => _onMessageTap(index, message),
),
// 如果不是最后一项,显示分隔线
if (index < controller.messageList.length - 1)
_buildDivider(),
],
);
}).toList(),
],
),
),
);
}
_buildMessageTip() {
return Container(
padding: EdgeInsets.symmetric(vertical: 10.h),
child: Text(
'只展示最近7天的消息',
style: TextStyle(
fontSize: 12.sp,
color: Colors.grey[500],
fontWeight: FontWeight.w400,
),
),
);
}
_buildMessageItem({
required MessageItem message,
VoidCallback? onTap,
}) {
return GestureDetector(
onTap: onTap ??
() {
// 默认点击事件
print('${message.title} 被点击');
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 10.h),
child: Row(
children: [
// 左侧图标
Stack(
children: [
Container(
width: 40.w,
height: 40.w,
decoration: BoxDecoration(
color: message.iconBgColor,
borderRadius: BorderRadius.circular(8.r),
),
child: Icon(
message.icon,
color: message.iconColor,
size: 20.sp,
),
),
if (message.hasRedDot)
Positioned(
top: 0,
right: 0,
child: Container(
width: 8.w,
height: 8.w,
decoration: const BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
),
),
],
),
SizedBox(width: 12.w),
// 中间内容
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
message.title,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: Colors.black87,
),
),
SizedBox(height: 4.h),
Text(
message.subtitle,
style: TextStyle(
fontSize: 14.sp,
color: Colors.grey[600],
fontWeight: FontWeight.w400,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
),
// 右侧时间
if (message.time.isNotEmpty)
Text(
message.time,
style: TextStyle(
fontSize: 12.sp,
color: Colors.grey[400],
fontWeight: FontWeight.w400,
),
),
],
),
),
);
}
// 处理消息项点击事件
void _onMessageTap(int index, MessageItem message) {
print('${message.title} 被点击,索引: $index');
// 这里可以添加具体的业务逻辑,比如跳转到详情页面
// 如果有未读标记,可以标记为已读
if (message.hasRedDot) {
// 可以在这里调用controller的方法标记为已读
}
}
_buildDivider() {
return Container(
margin: EdgeInsets.symmetric(horizontal: 16.w),
height: 1.h,
color: Colors.grey[200],
);
}
}