import 'dart:async'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../core/theme/app_colors.dart'; import '../shell/nav_bar_config.dart'; import '../../core/utils/date_utils.dart' as du; import '../../core/i18n/app_localizations.dart'; import 'announcement_list_controller.dart'; import 'announcement_model.dart'; class AnnouncementDetailPage extends ConsumerStatefulWidget { final String id; const AnnouncementDetailPage({super.key, required this.id}); @override ConsumerState createState() => _AnnouncementDetailPageState(); } class _AnnouncementDetailPageState extends ConsumerState { late AnnouncementModel _item; final bool _isAdmin = true; @override void initState() { super.initState(); _item = mockAnnouncements.firstWhere( (e) => e.id == widget.id, orElse: () => mockAnnouncements.first, ); // 停留 ≥2s 自动标记已读 Timer(const Duration(seconds: 2), () { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('已标记为已读'), duration: Duration(seconds: 1), ), ); } }); } @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context); ref .read(navBarConfigProvider.notifier) .update( NavBarConfig( title: l10n.get('announcementDetail'), showBack: true, onBack: () => context.pop(), ), ); _item = mockAnnouncements.firstWhere( (e) => e.id == widget.id, orElse: () => mockAnnouncements.first, ); return SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 已过期红色横幅 if (_item.isExpired) Container( width: double.infinity, padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 10), color: AppColors.danger, child: Text( '该公告已于 ${du.DateUtils.formatDateTime(_item.expiryDate!)} 过期', style: const TextStyle( fontSize: 13, color: Colors.white), textAlign: TextAlign.center, ), ), // 红头文件样式标题区 Container( width: double.infinity, padding: const EdgeInsets.all(24), color: AppColors.bgCard, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 红色上划线(红头文件风格) Container( width: 60, height: 4, color: AppColors.danger, ), const SizedBox(height: 16), Text( _item.title, style: const TextStyle( fontSize: 20, fontWeight: FontWeight.w700, color: AppColors.textPrimary, height: 1.4, ), ), const SizedBox(height: 12), Row( children: [ _buildTypeTag(_item.typeLabel), const SizedBox(width: 12), Text(_item.publisherName, style: const TextStyle( fontSize: 13, color: AppColors.textSecondary)), const SizedBox(width: 12), Text( du.DateUtils.formatDateTime(_item.publishTime), style: const TextStyle( fontSize: 13, color: AppColors.textPlaceholder)), ], ), ], ), ), Container( width: double.infinity, height: 2, color: AppColors.danger), // 正文内容 Padding( padding: const EdgeInsets.all(16), child: Container( width: double.infinity, padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: AppColors.bgCard, borderRadius: BorderRadius.circular(8), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('各部门、各位同事:', style: TextStyle( fontSize: 14, color: AppColors.textPrimary, height: 1.7)), const SizedBox(height: 12), Text( _item.content, style: const TextStyle( fontSize: 14, color: AppColors.textSecondary, height: 1.7), ), ], ), ), ), // 附件列表 if (_item.attachments.isNotEmpty) Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('附件下载', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: AppColors.textPrimary)), const SizedBox(height: 8), ..._item.attachments.map( (att) => GestureDetector( onTap: () { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('模拟下载:$att')), ); }, child: Container( width: double.infinity, margin: const EdgeInsets.only(bottom: 8), padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: AppColors.bgCard, borderRadius: BorderRadius.circular(8), ), child: Row( children: [ const Icon(Icons.description_outlined, size: 20, color: AppColors.primary), const SizedBox(width: 8), Expanded( child: Text(att, style: const TextStyle( fontSize: 14, color: AppColors.textPrimary)), ), Text('${(att.length * 100) ~/ 1000}KB', style: const TextStyle( fontSize: 12, color: AppColors.textPlaceholder)), const SizedBox(width: 8), const Icon(Icons.download_outlined, size: 16, color: AppColors.textPlaceholder), ], ), ), ), ), ], ), ), // 管理员增量:已读/未读统计 + DING if (_isAdmin) Padding( padding: const EdgeInsets.all(16), child: Container( width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColors.bgCard, borderRadius: BorderRadius.circular(8), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('全员触达率', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: AppColors.textPrimary)), const SizedBox(height: 12), Row( children: [ GestureDetector( onTap: () { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('模拟:展开已读员工列表')), ); }, child: Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 6), decoration: BoxDecoration( color: AppColors.successBg, borderRadius: BorderRadius.circular(16), ), child: Text( '已读 ${_item.readCount} 人', style: const TextStyle( fontSize: 12, color: AppColors.success), ), ), ), const SizedBox(width: 12), GestureDetector( onTap: () { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('模拟:展开未读员工列表')), ); }, child: Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 6), decoration: BoxDecoration( color: AppColors.bgPage, borderRadius: BorderRadius.circular(16), ), child: Text( '未读 ${_item.unreadCount} 人', style: const TextStyle( fontSize: 12, color: AppColors.statusGray), ), ), ), ], ), const SizedBox(height: 12), GestureDetector( onTap: () { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( '已向 ${_item.unreadCount} 名未读员工发送催办通知'), ), ); }, child: Container( width: double.infinity, padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 12), decoration: BoxDecoration( color: AppColors.danger, borderRadius: BorderRadius.circular(20), ), child: const Text( 'DING 催办', textAlign: TextAlign.center, style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Colors.white), ), ), ), ], ), ), ), const SizedBox(height: 24), ], ), ); } Widget _buildTypeTag(String type) { Color bgColor; Color textColor; switch (type) { case '人事与制度': bgColor = AppColors.successBg; textColor = AppColors.success; break; case '放假与活动': bgColor = AppColors.warningBg; textColor = AppColors.warning; break; default: bgColor = AppColors.primaryLight; textColor = AppColors.primary; } return Container( padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), decoration: BoxDecoration( color: bgColor, borderRadius: BorderRadius.circular(3), ), child: Text(type, style: TextStyle(fontSize: 11, color: textColor)), ); } }