Files
tuiche/lib/pages/main_bottom/message_page.dart
2026-04-07 14:49:31 +08:00

373 lines
17 KiB
Dart
Raw Permalink 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 'dart:async';
import 'package:ef/ef.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:vbvs_app/common/color/appConstants.dart';
import 'package:vbvs_app/common/color/app_uri_status.dart';
import 'package:vbvs_app/common/util/EventBus.dart';
import 'package:vbvs_app/common/util/FitTool.dart';
import 'package:vbvs_app/common/util/eventType.dart';
import 'package:vbvs_app/component/NullDataComponentWidget.dart';
import 'package:vbvs_app/component/tool/ClickableContainer.dart';
import 'package:vbvs_app/component/tool/TopSlideNotification.dart';
import 'package:vbvs_app/controller/message/message_controller.dart';
import 'package:vbvs_app/controller/theme_controller/ThemeController.dart';
import 'package:vbvs_app/pages/main_bottom/component/MessageWidgetWidget.dart';
class MessagePage extends StatefulWidget {
const MessagePage({super.key});
@override
State<MessagePage> createState() => _MessagePageState();
}
class _MessagePageState extends State<MessagePage> {
ThemeController themeController = Get.find();
MessageController messageController = Get.find();
late PageController _pageController;
@override
void initState() {
super.initState();
_pageController =
PageController(initialPage: messageController.model.type == 1 ? 0 : 1);
messageController.getMessageStatus();
late StreamSubscription<SwitchLanguageEvent> subscription;
// 监听切换语言
subscription = EventBus().on<SwitchLanguageEvent>().listen((event) {
ef.log("切换语言事件通知:${event.language}");
_fetchMessageData();
});
_fetchMessageData();
}
void _fetchMessageData() {
String type = messageController.model.type == 1 ? "app_vsm" : "app_system";
messageController.updateMessageStatus(type: type);
messageController.getMessageList().then((response) {
if (response.code != HttpStatusCodes.ok) {
TopSlideNotification.show(
Get.context!,
text: response.msg ?? "失败".tr,
textColor: themeController.currentColor.sc9,
);
}
});
}
void _onTabChanged(int index) {
int currentIndex = messageController.model.type == 1 ? 0 : 1;
// 只有当切换到不同tab时才重置加载状态
if (currentIndex != index) {
messageController.isLoadingMore = false;
messageController.bodyPage = 1;
messageController.systemPage = 1;
}
messageController.model.type = index == 0 ? 1 : 2;
messageController.updateAll();
_fetchMessageData();
_pageController.animateToPage(index,
duration: const Duration(milliseconds: 300), curve: Curves.easeInOut);
}
void _onPageChanged(int index) {
int newType = index == 0 ? 1 : 2;
if (messageController.model.type != newType) {
messageController.model.type = newType;
messageController.updateAll();
_fetchMessageData();
}
}
@override
void dispose() {
_pageController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.light,
));
return LayoutBuilder(
builder: (context, boxConstraints) => GestureDetector(
// onTap: () => FocusScope.of(context).unfocus(),,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(getBackgroundImageNoImage()),
fit: BoxFit.fill,
),
),
child: Scaffold(
appBar: AppBar(
systemOverlayStyle: SystemUiOverlayStyle(
statusBarColor: Colors.transparent, // 状态栏背景色
statusBarIconBrightness: Brightness.light, // 图标颜色Android
statusBarBrightness: Brightness.light, // 图标颜色iOS
),
// backgroundColor: themeController.currentColor.sc17,
backgroundColor: Colors.transparent,
automaticallyImplyLeading: false,
iconTheme: IconThemeData(color: themeController.currentColor.sc3),
// toolbarHeight: 140.rpx,
titleSpacing: 0,
title: Padding(
padding: EdgeInsetsDirectional.fromSTEB(0.rpx, 0, 0.rpx, 0),
child: Container(
width: double.infinity,
height: 140.rpx,
child: Column(
children: [
SizedBox(height: 40.rpx),
Expanded(
child: Stack(
alignment: Alignment.bottomLeft,
children: [
Row(
children: [
// 第一个容器,宽度占屏幕一半
if (!AppConstants.is_test_account)
Obx(() {
return Expanded(
child: ClickableContainer(
padding: EdgeInsets.all(0),
backgroundColor: Colors.transparent,
highlightColor:
themeController.currentColor.sc21,
borderRadius: 8.rpx,
onTap: () => _onTabChanged(0),
child: Container(
alignment: Alignment.center,
child: Stack(
alignment: Alignment.center,
clipBehavior: Clip.none,
children: [
Text(
'体征消息'.tr,
style: TextStyle(
fontFamily: 'Inter',
fontSize: AppConstants()
.title_text_fontSize,
color:
messageController
.model.type ==
2
? themeController
.currentColor.sc3
: themeController
.currentColor.sc2,
),
),
Obx(() {
return messageController.model
.body_message_read ==
1
? Positioned(
top: -4,
right: -14,
child: Container(
width: 8,
height: 8,
decoration:
const BoxDecoration(
color: Colors.red,
shape:
BoxShape.circle,
),
),
)
: const SizedBox.shrink();
}),
],
),
),
),
);
}),
SizedBox(width: 10.rpx),
// 第二个容器,宽度占屏幕一半
Obx(() {
return Expanded(
child: ClickableContainer(
padding: EdgeInsets.all(0),
backgroundColor: Colors.transparent,
highlightColor:
themeController.currentColor.sc21,
borderRadius: 8.rpx,
onTap: () => _onTabChanged(1),
child: Container(
alignment: Alignment.center,
child: Stack(
alignment: Alignment.center,
clipBehavior: Clip.none,
children: [
Text(
'系统消息'.tr,
style: TextStyle(
fontFamily: 'Inter',
fontSize: AppConstants()
.title_text_fontSize,
color:
messageController
.model.type ==
1
? themeController
.currentColor.sc3
: themeController
.currentColor.sc2,
),
),
Obx(() {
return messageController.model
.system_message_read ==
1
? Positioned(
top: -4,
right: -14,
child: Container(
width: 8,
height: 8,
decoration:
const BoxDecoration(
color: Colors.red,
shape:
BoxShape.circle,
),
),
)
: const SizedBox.shrink();
}),
],
),
),
),
);
}),
],
),
// 动画线
if (!AppConstants.is_test_account)
Obx(() {
double lineWidth =
MediaQuery.sizeOf(context).width * 0.5 -
20.rpx; // 每个容器占宽度的一半
return AnimatedPositioned(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
bottom: 0,
left: messageController.model.type == 1
? 0
: MediaQuery.sizeOf(context).width * 0.5 +
10.rpx, // 动态设置左侧位置
child: Container(
width: lineWidth,
height: 5.rpx,
decoration: BoxDecoration(
color: themeController.currentColor.sc2,
borderRadius:
BorderRadius.circular(2.rpx),
),
),
);
}),
if (AppConstants.is_test_account)
Obx(() {
double lineWidth = MediaQuery.sizeOf(context)
.width; // 每个容器占宽度的一半
messageController.model.type == 2;
return AnimatedPositioned(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
bottom: 0,
left: 0, // 动态设置左侧位置
child: Container(
width: lineWidth,
height: 4.rpx,
decoration: BoxDecoration(
color: themeController.currentColor.sc2,
borderRadius:
BorderRadius.circular(2.rpx),
),
),
);
}),
],
),
),
SizedBox(height: 17.rpx),
],
),
),
),
actions: const [],
centerTitle: false,
),
backgroundColor: Colors.transparent,
body: SafeArea(
top: true,
child: Scrollbar(
child: PageView(
controller: _pageController,
onPageChanged: _onPageChanged,
children: [
Obx(() {
final list = messageController.messageList.value;
return list.isEmpty
? const NullDataWidget()
: _buildMessageListView(list, "app_vsm");
}),
Obx(() {
final list = messageController.messageList.value;
return list.isEmpty
? const NullDataWidget()
: _buildMessageListView(list, "app_system");
}),
],
),
)),
),
),
),
);
}
Widget _buildMessageListView(List dataList, String type) {
return NotificationListener<ScrollNotification>(
onNotification: (scrollInfo) {
// 检查是否滚动到底部,并且没有正在加载
if (scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent &&
!messageController.isLoadingMore) {
messageController.isLoadingMore = true;
// 滑到底部,加载下一页
messageController.loadMore(type).then((_) {
// 加载完成后重置标志位
messageController.isLoadingMore = false;
}).catchError((_) {
messageController.isLoadingMore = false;
});
}
return true;
},
child: ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 30.rpx, vertical: 30.rpx),
itemCount: dataList.length,
itemBuilder: (context, index) {
return Padding(
padding: EdgeInsets.only(bottom: 30.rpx),
child: MessageWidgetWidget(data: dataList[index]),
);
},
),
);
}
}