import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'controller.dart'; import 'model.dart'; class MessagePage extends GetView { const MessagePage({super.key}); @override Widget build(BuildContext context) { Get.put(MessageController()); return Scaffold( backgroundColor: const Color(0xFFF7F9FB), appBar: AppBar( title: const Text('消息通知'), centerTitle: true, backgroundColor: Colors.white, foregroundColor: Colors.black, elevation: 0, leading: IconButton( icon: const Icon(Icons.arrow_back_ios, size: 20), onPressed: () => Get.back(), ), ), body: Stack( children: [ Obx(() => SmartRefresher( controller: controller.refreshController, enablePullUp: true, onRefresh: controller.onRefresh, onLoading: controller.onLoading, child: ListView.builder( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), itemCount: controller.messageList.length, itemBuilder: (context, index) { return _buildMessageItem(context, controller.messageList[index]); }, ), )), Obx(() => !controller.allRead.value ? Positioned( right: 20, bottom: 50, child: GestureDetector( onTap: controller.markAllRead, child: Container( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 14), decoration: BoxDecoration( color: const Color(0xFF007A45), borderRadius: BorderRadius.circular(30), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: const Text( '全部已读', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 14, ), ), ), ), ) : const SizedBox.shrink()), ], ), ); } Widget _buildMessageItem(BuildContext context, MessageModel item) { return IntrinsicHeight( child: Row( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // 左侧时间轴线条和圆点 SizedBox( width: 40, child: Stack( alignment: Alignment.topCenter, children: [ Container( width: 1.5, color: const Color(0xFFD8E2EE), ), Positioned( top: 25, child: Container( width: 12, height: 12, decoration: BoxDecoration( color: item.isRead == 1 ? const Color(0xFFAAB6C3) : const Color(0xFF4CAF50), shape: BoxShape.circle, border: Border.all(color: Colors.white, width: 2), ), ), ), ], ), ), // 右侧内容卡片 Expanded( child: GestureDetector( onTap: () { controller.markRead(item); _showMessageDialog(context, item); }, child: Container( margin: const EdgeInsets.only(bottom: 16), padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(24), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.02), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( item.title, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Color(0xFF333333), ), ), const SizedBox(height: 10), Text( item.content, style: const TextStyle( fontSize: 14, color: Color(0xFF666666), height: 1.4, ), ), const SizedBox(height: 12), Text( item.createTime, style: const TextStyle( fontSize: 12, color: Color(0xFFCCCCCC), ), ), ], ), ), ), ), ], ), ); } void _showMessageDialog(BuildContext context, MessageModel item) { showDialog( context: context, barrierDismissible: true, builder: (context) { return Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Container( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( item.title, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 16), Text( item.content, style: const TextStyle( fontSize: 15, height: 1.5, color: Color(0xFF333333)), ), const SizedBox(height: 24), Align( alignment: Alignment.centerRight, child: TextButton( onPressed: () => Navigator.pop(context), style: TextButton.styleFrom( foregroundColor: const Color(0xFF007A45), ), child: const Text('确认', style: TextStyle(fontWeight: FontWeight.bold)), ), ), ], ), ), ); }, ); } }