diff --git a/assets/icon-apps/read_message.png b/assets/icon-apps/read_message.png new file mode 100644 index 0000000..aaa902a Binary files /dev/null and b/assets/icon-apps/read_message.png differ diff --git a/assets/icon-apps/unread_message.png b/assets/icon-apps/unread_message.png new file mode 100644 index 0000000..9687551 Binary files /dev/null and b/assets/icon-apps/unread_message.png differ diff --git a/lib/http/modules/notif_api.dart b/lib/http/modules/notif_api.dart new file mode 100644 index 0000000..69193ce --- /dev/null +++ b/lib/http/modules/notif_api.dart @@ -0,0 +1,69 @@ +import 'package:dio/dio.dart'; +import 'package:qhd_prevention/http/ApiService.dart'; +import 'package:qhd_prevention/http/HttpManager.dart'; + +class NotifApi { + + /// 通知列表 + static Future> getNoticeList(Map data) { + return HttpManager().request( + '${ApiService.basePath}/appmenu', + '/noticeReadRecord/list', + method: Method.post, + data: { + ...data , + }, + ); + } + + /// 通知详情 + static Future> getNoticeDetail(String noticeId) { + return HttpManager().request( + '${ApiService.basePath}/appmenu', + '/notice/noticeContentInfo/$noticeId', + method: Method.get, + data: { + // ...data , + }, + ); + } + + /// 已阅 + static Future> saveReadNoticeDetail(String noticeId) { + return HttpManager().request( + '${ApiService.basePath}/appmenu', + '/noticeReadRecord/save', + method: Method.post, + data: { + "noticeId": noticeId, + }, + ); + } + + /// 回复 + static Future> replyContent(String noticeReadId,String replyContent) { + return HttpManager().request( + '${ApiService.basePath}/appmenu', + '/noticeReadRecord/reply', + method: Method.put, + data: { + "noticeReadId": noticeReadId, + "replyContent": replyContent, + }, + ); + } + + /// 通知数量 + static Future> getNotifRedPoint() { + return HttpManager().request( + '${ApiService.basePath}/appmenu', + '/notice/unreadCount', + method: Method.get, + data: { + // ...data , + }, + ); + } + + +} \ No newline at end of file diff --git a/lib/pages/badge_manager.dart b/lib/pages/badge_manager.dart new file mode 100644 index 0000000..3ba68d5 --- /dev/null +++ b/lib/pages/badge_manager.dart @@ -0,0 +1,129 @@ +import 'dart:async'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_new_badger/flutter_new_badger.dart'; +import 'package:qhd_prevention/common/route_service.dart'; +import 'package:qhd_prevention/http/ApiService.dart'; +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/http/modules/notif_api.dart'; + + +/// 优化版 BadgeManager:每个接口超时保护、增量更新、notify 合并、原生角标 debounce +class BadgeManager extends ChangeNotifier { + BadgeManager._internal(); + static final BadgeManager _instance = BadgeManager._internal(); + factory BadgeManager() => _instance; +// 添加完整的工作数据存储 + Map _workData = {}; + Map get workData => _workData; + // 各模块未读 + int _notifCount = 0; + + + // 读取接口值的公开 getter + int get count => _notifCount ; + int get notifCount => _notifCount; + + + + // 通知合并控制(短时间内多次更新只触发一次 notify) + Timer? _notifyTimer; + Duration _notifyDelay = const Duration(milliseconds: 180); + void _scheduleNotify() { + // 如果已有计划,不需要再立即计划(合并) + _notifyTimer?.cancel(); + _notifyTimer = Timer(_notifyDelay, () { + try { + notifyListeners(); + } catch (e) { + debugPrint('BadgeManager.notifyListeners error: $e'); + } + _notifyTimer = null; + }); + } + + // 原生角标同步 debounce(防止短时间内频繁调用) + Timer? _syncTimer; + Duration _syncDelay = const Duration(milliseconds: 250); + void _syncNativeDebounced() { + _syncTimer?.cancel(); + _syncTimer = Timer(_syncDelay, () { + try { + final total = count; + if (total > 0) { + FlutterNewBadger.setBadge(total); + } else { + FlutterNewBadger.removeBadge(); + } + } catch (e) { + debugPrint('BadgeManager._syncNativeDebounced error: $e'); + } + _syncTimer = null; + }); + } + + // safe wrapper: 给单个 future 加超时与兜底返回 + Future _safe(Future future, T fallback, {Duration timeout = const Duration(seconds: 5)}) async { + try { + return await future.timeout(timeout); + } catch (e, st) { + // 报错不抛出到外层,记录并返回 fallback + debugPrint('BadgeManager._safe error: $e\n$st'); + return fallback; + } + } + + /// 初始化所有模块(并行发起,但每个接口独立 timeout & 提交结果) + Future initAllModules() async { + // 不 await 整个 Future.wait,使调用方不会因为单个慢接口阻塞 + try { + // 每个请求都通过 _safe 包裹,设置超时与兜底 + final fNotif = _safe>( + NotifApi.getNotifRedPoint().then((r) => r as Map), + {}, + timeout: const Duration(seconds: 4), + ); + + + fNotif.then((notifJson) { + try { + _notifCount = ((notifJson['data'] as int?) ?? 0); + } catch (e, st) { + debugPrint('BadgeManager.parse notifJson error: $e\n$st'); + } + _scheduleNotify(); + _syncNativeDebounced(); + }); + + + } catch (e, st) { + debugPrint('BadgeManager.initAllModules unexpected error: $e\n$st'); + } + } + + // 下面的 updateX 方法也做了超时保护并使用 _onModuleChanged 合并通知 + + void updateNotifCount() async { + try { + final notifJson = await _safe>( + NotifApi.getNotifRedPoint().then((r) => r as Map), + {}, + timeout: const Duration(seconds: 4), + ); + _notifCount = (notifJson['data'] as int?) ?? 0; + _onModuleChanged(); + } catch (e) { + debugPrint('updateNotifCount error: $e'); + } + } + + + void clearAll() { + _syncNativeDebounced(); + _scheduleNotify(); + } + + void _onModuleChanged() { + _syncNativeDebounced(); + _scheduleNotify(); + } +} diff --git a/lib/pages/main_tab.dart b/lib/pages/main_tab.dart index 121197c..319d891 100644 --- a/lib/pages/main_tab.dart +++ b/lib/pages/main_tab.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:qhd_prevention/pages/badge_manager.dart'; import 'package:qhd_prevention/pages/home/home_page.dart'; import 'package:qhd_prevention/pages/mine/mine_page.dart'; import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/pages/notif/notif_page.dart'; import 'package:qhd_prevention/services/heartbeat_service.dart'; /// 用于向子树公布当前 tab 索引 @@ -35,21 +37,33 @@ class MainPage extends StatefulWidget { class _MainPageState extends State with WidgetsBindingObserver { int _currentIndex = 0; final GlobalKey _homeKey = GlobalKey(); - + final GlobalKey _notifKey = GlobalKey(); // final GlobalKey _appKey = GlobalKey(); final GlobalKey _mineKey = GlobalKey(); late List _pages; late List _tabVisibility; // 存储每个Tab的显示状态 + // 添加 BadgeManager 实例 + late final BadgeManager _badgeManager; + @override void initState() { super.initState(); + + // 初始化 BadgeManager + _badgeManager = BadgeManager(); + _badgeManager.initAllModules(); + + // 监听 BadgeManager 的变化 + _badgeManager.addListener(_onBadgeChanged); + // 注册生命周期监听 WidgetsBinding.instance.addObserver(this); // 初始化所有Tab _tabVisibility = [true, true, true]; _pages = [ HomePage(key: _homeKey, isChooseFirm: widget.isChooseFirm), + NotifPage(key: _notifKey), MinePage(key: _mineKey, isChooseFirm: widget.isChooseFirm), ]; // 启动心跳服务 @@ -58,7 +72,7 @@ class _MainPageState extends State with WidgetsBindingObserver { @override void dispose() { - // BadgeManager().removeListener(_onBadgeChanged); + _badgeManager.removeListener(_onBadgeChanged); // 移除生命周期监听 WidgetsBinding.instance.removeObserver(this); @@ -122,7 +136,7 @@ class _MainPageState extends State with WidgetsBindingObserver { @override Widget build(BuildContext context) { - // final bm = BadgeManager(); + final bm = _badgeManager; // 构建可见的底部导航项 final List visibleItems = []; @@ -150,6 +164,20 @@ class _MainPageState extends State with WidgetsBindingObserver { visiblePages.add(_pages[i]); break; case 1: + visibleItems.add(BottomNavigationBarItem( + icon: _buildIconWithBadge( + icon: Image.asset('assets/tabbar/works.png', width: 24, height: 24), + badgeCount: bm.notifCount, + ), + activeIcon: _buildIconWithBadge( + icon: Image.asset('assets/tabbar/works_cur.png', width: 24, height: 24), + badgeCount: bm.notifCount, + ), + label: '通知', + )); + visiblePages.add(_pages[i]); + break; + case 2: visibleItems.add( BottomNavigationBarItem( icon: Image.asset( @@ -167,7 +195,6 @@ class _MainPageState extends State with WidgetsBindingObserver { ); visiblePages.add(_pages[i]); break; - break; } } } @@ -218,4 +245,16 @@ class _MainPageState extends State with WidgetsBindingObserver { ), ); } + + + void _onBadgeChanged() { + // 当角标数据变化时,只更新需要重建的部分 + // 但这里我们只需要触发 build 来更新底部导航栏的角标 + if (mounted) { + setState(() { + // 只触发重建,不改变数据 + }); + } + } + } diff --git a/lib/pages/notif/notif_detail_page.dart b/lib/pages/notif/notif_detail_page.dart new file mode 100644 index 0000000..2aea4c5 --- /dev/null +++ b/lib/pages/notif/notif_detail_page.dart @@ -0,0 +1,189 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_html/flutter_html.dart'; +import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart'; +import 'package:qhd_prevention/customWidget/custom_button.dart'; +import 'package:qhd_prevention/customWidget/toast_util.dart'; +import 'package:qhd_prevention/http/modules/notif_api.dart'; +import 'package:qhd_prevention/pages/mine/webViewPage.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/tools/h_colors.dart'; +import 'package:qhd_prevention/tools/tools.dart'; +import 'package:webview_flutter/webview_flutter.dart'; + +import '../../http/ApiService.dart'; + + +class NotifDetailPage extends StatefulWidget { + const NotifDetailPage(this.item, this.selectedTab, {super.key,required this.onClose}); + + final Function(String) onClose; // 回调函数 + final dynamic item; + final int selectedTab; + + @override + State createState() => _NotifDetailPageState(item,selectedTab,onClose); +} + +class _NotifDetailPageState extends State { + _NotifDetailPageState(this.item, this.selectedTab,this.onClose); + + final Function(String) onClose; // 回调函数 + final dynamic item; + final int selectedTab; + String title=""; + String time=""; + String text=""; + bool isShowReply=false; + String replyText=""; + String noticeReadId=''; + + @override + void initState() { + super.initState(); + if(0==selectedTab){ + _getNotifDetail(); + }else{ + _getNotifEnterpriseDetail(); + } + + } + + Future _getNotifDetail() async { + // LoadingDialogHelper.show(); + try { + final result = await NotifApi.getNoticeDetail(item['noticeId']); + if (result['success']) { + final dynamic newList = result['data'] ; + setState(() { + title= newList['title']??''; + time= newList['publishTime']??''; + text= newList['content']??''; + isShowReply=newList['requireReply']==1?true:false; + noticeReadId=newList['noticeReadId']??''; + replyText=newList['replyContent']??''; + }); + if(newList['readStatus']!='1'){ + final resultTwo = await NotifApi.saveReadNoticeDetail(item['noticeId']); + if (result['success']) { + noticeReadId = resultTwo['data'] ?? ''; + } + } + } + } catch (e) { + print('加载出错: $e'); + } + } + + Future _getNotifEnterpriseDetail() async { + // LoadingDialogHelper.show(); + try { + // final result = await HiddenDangerApi.getNotifEnterpriseDetail(item['NOTICECORPUSERID_ID']); + // if (result['result'] == 'success') { + // final dynamic newList = result['pd'] ; + // setState(() { + // title= newList['SYNOPSIS']; + // time= newList['CREATTIME']; + // text= newList['CONTENT']; + // }); + // } + } catch (e) { + print('加载出错: $e'); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: MyAppbar(title: "通知详情"), + body: SafeArea( + child: Container( + // color: Colors.white, + child: Padding( + padding: EdgeInsets.all(10), + child: Card( + child: Container( + width: double.infinity, // 铺满父容器 + color: Colors.white, + padding: const EdgeInsets.all(15), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, // 左对齐 + children: [ + Padding( + padding: EdgeInsets.only(left: 10,right: 10), + child: Text(title,style: TextStyle(color: Colors.black,fontSize: 16,fontWeight: FontWeight.bold),), + ), + + SizedBox(height: 8), + Padding( + padding: EdgeInsets.only(left: 10,right: 10), + child: Text(time,), + ), + SizedBox(height: 8), + Html( + data: text, + ), + + SizedBox(height: 8), + if(isShowReply&&replyText.isEmpty) + CustomButton( + height: 35, + margin: EdgeInsets.only(right: 10), + onPressed: () async { + final confirmed = await CustomAlertDialog.showInput( + context, + title: "回复", + hintText: '输入内容', + cancelText: '关闭', + confirmText: '确定', + ); + if (confirmed != null&&confirmed.isNotEmpty) { + //确定回复 + // ToastUtil.showNormal(context, confirmed); + _replyContent(confirmed); + } + }, + backgroundColor: h_AppBarColor(), + textStyle: const TextStyle(color: Colors.white), + buttonStyle: ButtonStyleType.primary, + text: '回复', + ), + ], + ), + ), + + ), + ), + + ), + ), + ), + ); + } + + @override + void dispose() { + // TODO: implement dispose + super.dispose(); + onClose('关闭详情'); // 触发回调 + } + + + Future _replyContent(String content) async { + try { + LoadingDialogHelper.show(); + final result = await NotifApi.replyContent(noticeReadId,content); + LoadingDialogHelper.hide(); + if (result['success']) { + ToastUtil.showNormal(context, '回复成功'); + Navigator.pop(context); + // onClose('关闭详情'); // 触发回调 + } + } catch (e) { + print('加载出错: $e'); + } + } + + +} diff --git a/lib/pages/notif/notif_page.dart b/lib/pages/notif/notif_page.dart new file mode 100644 index 0000000..3eecd37 --- /dev/null +++ b/lib/pages/notif/notif_page.dart @@ -0,0 +1,497 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:qhd_prevention/common/route_aware_state.dart'; +import 'package:qhd_prevention/common/route_service.dart'; +import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart'; +import 'package:qhd_prevention/customWidget/search_bar_widget.dart'; +import 'package:qhd_prevention/customWidget/toast_util.dart'; +import 'package:qhd_prevention/http/modules/notif_api.dart'; +import 'package:qhd_prevention/pages/badge_manager.dart'; +import 'package:qhd_prevention/pages/main_tab.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; + +import 'package:qhd_prevention/pages/notif/notif_detail_page.dart'; +import 'package:qhd_prevention/tools/tools.dart'; +import '../../http/ApiService.dart'; + +class NotifPage extends StatefulWidget { + const NotifPage({Key? key}) : super(key: key); + + @override + NotifPageState createState() => NotifPageState(); +} + +class NotifPageState extends RouteAwareState + with TickerProviderStateMixin, WidgetsBindingObserver { + final TextEditingController searchController = TextEditingController(); + + late List _list = []; + + + late TabController _tabController; + late TabController _tabControllerTwo; + int _selectedTab = 0; + int _selectedTabTwo = 0; + int pageNum = 1; + int _totalPage=1; + String keyWord = ""; + + // 控制Tab显示状态 + bool _showPlatformAnnouncement = true; + bool _showEnterpriseAnnouncement = true; + + // 标记是否已初始化 + bool _isInitialized = false; + bool _isLoading = false; + bool _hasMore = true; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addObserver(this); + + // 初始化显示状态 + _initializeVisibility(); + + // 初始化TabController + _initializeTabControllers(); + + _getListData(false); + + _isInitialized = true; + } + + void _initializeVisibility() { + _showPlatformAnnouncement = true; + _showEnterpriseAnnouncement = true; + } + + void _initializeTabControllers() { + final visibleTabsCount = + (_showPlatformAnnouncement ? 1 : 0) + + (_showEnterpriseAnnouncement ? 1 : 0); + + _tabController = TabController(length: visibleTabsCount, vsync: this); + _tabController.addListener(() { + if (_tabController.indexIsChanging) { + setState(() => _selectedTab = _tabController.index); + print('切换到标签:${_tabController.index}'); + searchController.text = ""; + keyWord = ""; + reRefreshData(); + } + }); + + _tabControllerTwo = TabController(length: 2, vsync: this); + _tabControllerTwo.addListener(() { + if (_tabControllerTwo.indexIsChanging) { + setState(() => _selectedTabTwo = _tabControllerTwo.index); + print('切换到标签:${_tabControllerTwo.index}'); + + searchController.text = ""; + keyWord = ""; + reRefreshData(); + } + }); + } + + void _updateNotifVisibility() { + final routeService = RouteService(); + final notifRoutes = + routeService.mainTabs.isNotEmpty + ? routeService.getRoutesForTab(routeService.mainTabs[2]) + : []; + + bool newPlatformAnnouncement = false; + bool newEnterpriseAnnouncement = false; + + // 根据路由标题匹配并设置显示状态 + for (final route in notifRoutes) { + final routeTitle = route.title; + + switch (routeTitle) { + case '公告': + newPlatformAnnouncement = route.hasMenu; + break; + case '通知': + newEnterpriseAnnouncement = route.hasMenu; + break; + } + } + + // 只有当显示状态确实发生变化时才更新 + if (newPlatformAnnouncement != _showPlatformAnnouncement || + newEnterpriseAnnouncement != _showEnterpriseAnnouncement) { + setState(() { + _showPlatformAnnouncement = newPlatformAnnouncement; + _showEnterpriseAnnouncement = newEnterpriseAnnouncement; + + // 重新初始化TabController + _disposeTabControllers(); + _initializeTabControllers(); + + // 重置选中状态 + _selectedTab = 0; + _selectedTabTwo = 0; + }); + } + } + + void _disposeTabControllers() { + _tabController.dispose(); + _tabControllerTwo.dispose(); + } + + void onRouteConfigLoaded() { + if (mounted && _isInitialized) { + _updateNotifVisibility(); + } + } + + void reRefreshData() { + pageNum = 1; + _list.clear(); + _getListData(false); + // if (0 == _selectedTab) { + // + // _getNotifList(); + // } else { + // _getNotifEnterprise(); + // } + } + + @override + Future onVisible() async { + final current = CurrentTabNotifier.of(context)?.currentIndex ?? 0; + const myIndex = 2; + if (current != myIndex) { + return; + } + // BadgeManager().updateNotifCount(); + } + + Future _getListData(bool loadMore) async { + try { + if (_isLoading) return; + _isLoading = true; + + LoadingDialogHelper.show(); + + final Map result; + + final data = { + "pageSize": 20, + "pageIndex": pageNum, + }; + + if(_selectedTab==0){ + result = await NotifApi.getNoticeList(data); + }else{ + result = await NotifApi.getNoticeList(data); + } + BadgeManager().updateNotifCount(); + LoadingDialogHelper.hide(); + if(_selectedTab==0){ + if (result['success']) { + _totalPage =result['totalPages'] ?? 1; + final List newList = result['data'] ?? []; + // setState(() { + // _list.addAll(newList); + // }); + + setState(() { + if (loadMore) { + _list.addAll(newList); + } else { + _list = newList; + } + _hasMore = pageNum < _totalPage; + // if (_hasMore) _page++; + }); + + }else{ + ToastUtil.showNormal(context, "加载数据失败"); + // _showMessage('加载数据失败'); + } + } + + + } catch (e) { + LoadingDialogHelper.hide(); + // 出错时可以 Toast 或者在页面上显示错误状态 + print('加载数据失败:$e'); + } finally { + // if (!loadMore) LoadingDialogHelper.hide(); + _isLoading = false; + } + } + + + + @override + void dispose() { + WidgetsBinding.instance.removeObserver(this); + _disposeTabControllers(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + // 构建可见的Tab列表 + final List visibleTabs = []; + if (_showPlatformAnnouncement) { + visibleTabs.add(const Tab(text: '公告')); + } + if (_showEnterpriseAnnouncement) { + visibleTabs.add(const Tab(text: '通知')); + } + + // 如果没有可见的Tab,显示空页面 + if (visibleTabs.isEmpty) { + return Scaffold( + appBar: MyAppbar(title: '通知', isBack: false), + body: Center( + child: Text( + '暂无通知权限', + style: TextStyle(fontSize: 16, color: Colors.grey), + ), + ), + ); + } + + return Scaffold( + appBar: MyAppbar(title: '通知', isBack: false), + body: GestureDetector( + onTap: () { + FocusScope.of(context).unfocus(); + }, + behavior: HitTestBehavior.opaque, + child: Scaffold( + body: SafeArea( + child: Column( + children: [ + // Tab bar + Container( + color: Colors.white, + child: TabBar( + controller: _tabController, + labelStyle: const TextStyle(fontSize: 16), + indicator: const UnderlineTabIndicator( + borderSide: BorderSide( + width: 4.0, + color: const Color(0xFF1C61FF), + ), + insets: EdgeInsets.symmetric(horizontal: 35.0), + ), + labelColor: const Color(0xFF1C61FF), + unselectedLabelColor: Colors.grey, + tabs: visibleTabs, + ), + ), + + NotificationListener( + onNotification: _onScroll, + child: // List + Expanded( + child: + _list.isEmpty + ? NoDataWidget.show() + : ListView.builder( + itemCount: _list.length, + itemBuilder: (context, index) { + return _itemCellTwo(_list[index]); + }, + ), + ), + ), + + + ], + ), + ), + ), + ), + ); + } + + bool _onScroll(ScrollNotification n) { + if (n.metrics.pixels > n.metrics.maxScrollExtent - 100 && + _hasMore && + !_isLoading) { + pageNum++; + _getListData(true); + } + return false; + } + + Widget _itemCellTwo(final item) { + return GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: + (context) => NotifDetailPage( + item, + _selectedTab, + onClose: (result) { + print('详情页面已关闭,返回结果: $result'); + reRefreshData(); + }, + ), + ), + ); + }, + child: Card( + margin: EdgeInsets.all(8.0), + color: Colors.white, + elevation: 2.0, + child: Padding( + padding: EdgeInsets.all(16.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 标题 + Text( + item['title']??'', + style: TextStyle( + fontSize: 18.0, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + + SizedBox(height: 8.0), + + Text( + '发布时间:${item['publishTime']??''}', + style: TextStyle(fontSize: 14.0, color: Colors.grey[500]), + ), + ], + ), + ), + + SizedBox(height: 8.0), + + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + item['readStatus']=='1'?'已阅':'待阅', + style: TextStyle( + fontSize: 16.0, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ), + const SizedBox(width: 6.0), + Image.asset( + item['readStatus']=='1'?'assets/icon-apps/read_message.png':'assets/icon-apps/unread_message.png', + width: 25, + height: 25, + ), + const SizedBox(width: 6.0), + ], + ), + ], + ), + ), + ), + ); + } + + + + + + + Widget _itemCell(final item) { + return Column( + children: [ + ListTile( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: + (context) => NotifDetailPage( + item, + _selectedTab, + onClose: (result) { + print('详情页面已关闭,返回结果: $result'); + reRefreshData(); + }, + ), + ), + ); + }, + contentPadding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), + title: Padding( + padding: const EdgeInsets.only(bottom: 20), + child: Text(item['SYNOPSIS'], style: const TextStyle(fontSize: 14)), + ), + subtitle: Text( + item['CREATTIME'], + style: const TextStyle(fontSize: 13), + ), + trailing: Container( + constraints: const BoxConstraints(minHeight: 100), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + if (0 != _selectedTab) + Text( + item['TYPE'] == 1 ? '已读' : '未读', + style: TextStyle( + fontSize: 12, + color: item['TYPE'] == 1 ? Colors.grey : Colors.red, + ), + ), + const SizedBox(height: 15), + if (0 != _selectedTab && item['TYPE'] == 1) + SizedBox( + height: 24, + child: TextButton( + onPressed: () async { + final ok = await CustomAlertDialog.showConfirm( + context, + title: '确认删除', + content: '确定要删除这条通知吗?', + cancelText: '取消', + ); + // if (ok) { + // _deleteNotif(item['NOTICECORPUSERID_ID']); + // } + }, + style: TextButton.styleFrom( + padding: const EdgeInsets.symmetric(horizontal: 12), + backgroundColor: Colors.red, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), + child: const Text( + '删除', + style: TextStyle(fontSize: 13, color: Colors.white), + ), + ), + ), + ], + ), + ), + ), + const Divider(height: 1, color: Colors.black12), + ], + ); + } +}