498 lines
14 KiB
Dart
498 lines
14 KiB
Dart
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<NotifPage>
|
||
with TickerProviderStateMixin, WidgetsBindingObserver {
|
||
final TextEditingController searchController = TextEditingController();
|
||
|
||
late List<dynamic> _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<void> onVisible() async {
|
||
final current = CurrentTabNotifier.of(context)?.currentIndex ?? 0;
|
||
const myIndex = 2;
|
||
if (current != myIndex) {
|
||
return;
|
||
}
|
||
// BadgeManager().updateNotifCount();
|
||
}
|
||
|
||
Future<void> _getListData(bool loadMore) async {
|
||
try {
|
||
if (_isLoading) return;
|
||
_isLoading = true;
|
||
|
||
LoadingDialogHelper.show();
|
||
|
||
final Map<String, dynamic> 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<dynamic> 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<Widget> 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<ScrollNotification>(
|
||
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),
|
||
],
|
||
);
|
||
}
|
||
}
|