消息中心,待测试

This commit is contained in:
2026-01-08 15:33:40 +08:00
parent 7d9c879a4e
commit baee5dba83
5 changed files with 145 additions and 57 deletions

View File

@@ -5,6 +5,7 @@ import 'package:getx_scaffold/getx_scaffold.dart';
import 'package:ln_jq_app/common/model/base_model.dart'; import 'package:ln_jq_app/common/model/base_model.dart';
import 'package:ln_jq_app/common/token_interceptor.dart'; import 'package:ln_jq_app/common/token_interceptor.dart';
import 'package:ln_jq_app/storage_service.dart'; import 'package:ln_jq_app/storage_service.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'common/styles/theme.dart'; import 'common/styles/theme.dart';
import 'pages/home/view.dart'; import 'pages/home/view.dart';
@@ -47,6 +48,8 @@ void main() async {
fallbackLocale: Locale('zh', 'CN'), fallbackLocale: Locale('zh', 'CN'),
supportedLocales: [Locale('zh', 'CN')], supportedLocales: [Locale('zh', 'CN')],
localizationsDelegates: const [ localizationsDelegates: const [
//pull_to_refresh
RefreshLocalizations.delegate,
GlobalMaterialLocalizations.delegate, GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate, GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate, GlobalCupertinoLocalizations.delegate,

View File

@@ -1,15 +1,16 @@
import 'package:get/get.dart';
import 'package:getx_scaffold/getx_scaffold.dart'; import 'package:getx_scaffold/getx_scaffold.dart';
import 'package:ln_jq_app/common/model/base_model.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'model.dart'; import 'model.dart';
class MessageController extends GetxController { class MessageController extends GetxController {
final RefreshController refreshController = RefreshController(initialRefresh: false); final RefreshController refreshController = RefreshController(initialRefresh: false);
final RxList<MessageModel> messageList = <MessageModel>[].obs; final RxList<MessageModel> messageList = <MessageModel>[].obs;
int _pageNum = 1; int _pageNum = 1;
final int _pageSize = 10; final int _pageSize = 20;
// 模拟所有已读状态,实际应根据接口判断 // 是否所有已读状态
final RxBool allRead = false.obs; final RxBool allRead = false.obs;
@override @override
@@ -19,45 +20,58 @@ class MessageController extends GetxController {
} }
Future<void> _loadData({bool isRefresh = false}) async { Future<void> _loadData({bool isRefresh = false}) async {
if (isRefresh) { final int targetPage = isRefresh ? 1 : _pageNum + 1;
_pageNum = 1;
} else {
_pageNum++;
}
try { try {
// 模拟请求延迟 final Map<String, dynamic> requestData = {
await Future.delayed(const Duration(milliseconds: 500)); 'appFlag': 1,
'pageNum': targetPage,
'pageSize': _pageSize,
};
// 模拟数据 (请替换为实际接口请求) final response = await HttpService.to.get(
// var response = await HttpService.to.post('message/list', data: {'pageNum': _pageNum, 'pageSize': _pageSize}); 'appointment/unread_notice/page',
params: requestData,
);
List<MessageModel> newData = List.generate(10, (index) { if (response == null) {
int id = (_pageNum - 1) * _pageSize + index; throw Exception("Response is null");
}
final result = BaseModel.fromJson(response.data);
if (result.code != 0) {
throw Exception(result.message ?? "Business error");
}
final recordsList = result.data?["records"] as List? ?? [];
final List<MessageModel> newData = recordsList.map((e) {
return MessageModel( return MessageModel(
id: id.toString(), id: e['id']?.toString() ?? '',
title: '加氢预约失败通知', title: e['noticeTitle'] ?? '',
content: '1月6日14时30分-1月6日15时30分北京朝阳加氢站加氢预约失败。原因设备维护', content: e['noticeContent'] ?? '',
createTime: '刚刚', createTime: e['createTime'] ?? '',
isRead: index % 3 == 0 ? 1 : 0, isRead: int.tryParse(e['isRead']?.toString() ?? '0') ?? 0,
); );
}); }).toList();
if (isRefresh) { if (isRefresh) {
messageList.assignAll(newData); messageList.assignAll(newData);
refreshController.refreshCompleted(); _pageNum = 1; // 只有成功了才重置页码
} else { } else {
if (newData.isEmpty) { messageList.addAll(newData);
refreshController.loadNoData(); if (newData.isNotEmpty) {
} else { _pageNum++; // 只有成功且有数据才+1
messageList.addAll(newData);
refreshController.loadComplete();
} }
} }
_checkAllRead(); _updateRefreshState(isRefresh, newData.length);
// 检查是否全部已读
_checkAllRead();
} catch (e) { } catch (e) {
Logger.d("加载失败: $e"); // 建议加上日志
if (isRefresh) { if (isRefresh) {
refreshController.refreshFailed(); refreshController.refreshFailed();
} else { } else {
@@ -66,24 +80,48 @@ class MessageController extends GetxController {
} }
} }
/// 处理 RefreshController 状态
void _updateRefreshState(bool isRefresh, int count) {
if (isRefresh) {
refreshController.refreshCompleted();
// 如果刷新后的数据量小于 pageSize说明没有更多数据了
if (count < _pageSize) {
refreshController.loadNoData();
} else {
// 必须重置 footer 状态,否则之前如果是 NoData 状态无法再加载
refreshController.resetNoData();
}
} else {
if (count == 0) {
refreshController.loadNoData();
} else {
refreshController.loadComplete();
}
}
}
void onRefresh() => _loadData(isRefresh: true); void onRefresh() => _loadData(isRefresh: true);
void onLoading() => _loadData(isRefresh: false); void onLoading() => _loadData(isRefresh: false);
// 标记全部已读 // 标记全部已读
void markAllRead() async { void markAllRead() async {
showLoading('正在标记...'); showLoading('正在标记...');
try { try {
// await HttpService.to.post('message/readAll'); final response = await HttpService.to.post('appointment/unread_notice/read/all');
await Future.delayed(const Duration(milliseconds: 500)); if (response != null) {
final result = BaseModel.fromJson(response.data);
if (result.code == 0) {
for (var msg in messageList) {
msg.isRead = 0;
}
messageList.refresh();
allRead.value = true;
for (var msg in messageList) { dismissLoading();
msg.isRead = 1; showSuccessToast('全部已读');
}
} }
messageList.refresh();
allRead.value = true;
dismissLoading();
showSuccessToast('全部已读');
} catch (e) { } catch (e) {
dismissLoading(); dismissLoading();
showErrorToast('操作失败'); showErrorToast('操作失败');
@@ -92,15 +130,22 @@ class MessageController extends GetxController {
// 标记单条已读(弹窗显示时调用) // 标记单条已读(弹窗显示时调用)
void markRead(MessageModel message) async { void markRead(MessageModel message) async {
if (message.isRead == 1) return; if (message.isRead == 0) return;
// await HttpService.to.post('message/read', data: {'id': message.id}); final response = await HttpService.to.post(
message.isRead = 1; '/appointment/unread_notice/read/${message.id}',
messageList.refresh(); );
_checkAllRead(); if (response != null) {
final result = BaseModel.fromJson(response.data);
if (result.code == 0) {
message.isRead = 0;
messageList.refresh();
_checkAllRead();
}
}
} }
void _checkAllRead() { void _checkAllRead() {
allRead.value = messageList.every((msg) => msg.isRead == 1); allRead.value = messageList.every((msg) => msg.isRead == 0);
} }
} }

View File

@@ -3,7 +3,7 @@ class MessageModel {
final String title; final String title;
final String content; final String content;
final String createTime; final String createTime;
int isRead; // 0: 读, 1: int isRead; // 0: 读, 1:
MessageModel({ MessageModel({
required this.id, required this.id,

View File

@@ -31,6 +31,7 @@ class MineController extends GetxController with BaseControllerMixin {
} }
String rate = ""; String rate = "";
String rating = "";
String accident = ""; String accident = "";
String historyBreakRules = ""; String historyBreakRules = "";
String vin = ""; String vin = "";
@@ -38,6 +39,7 @@ class MineController extends GetxController with BaseControllerMixin {
String violationTotal = "0"; String violationTotal = "0";
String violationScore = "0"; String violationScore = "0";
String violationDispose = "0"; String violationDispose = "0";
bool isNotice = false;
void renderData() async { void renderData() async {
if (StorageService.to.hasVehicleInfo) { if (StorageService.to.hasVehicleInfo) {
@@ -56,6 +58,8 @@ class MineController extends GetxController with BaseControllerMixin {
_fetchCompletionRate(), // 请求1完成率 _fetchCompletionRate(), // 请求1完成率
_fetchAccidentCount(), // 请求2事故数 _fetchAccidentCount(), // 请求2事故数
_fetchBreakRulesCount(), // 请求3违章数 _fetchBreakRulesCount(), // 请求3违章数
_rating(), // 司机评分
_msgNotice(), // 红点消息
]); ]);
} catch (e, stackTrace) { } catch (e, stackTrace) {
showErrorToast("加载数据失败,请稍后重试 $e"); showErrorToast("加载数据失败,请稍后重试 $e");
@@ -65,6 +69,37 @@ class MineController extends GetxController with BaseControllerMixin {
} }
} }
Future<void> _msgNotice() async {
final Map<String, dynamic> requestData = {
'appFlag': 1,
'isRead': 1,
'pageNum': 1,
'pageSize': 5,
};
final response = await HttpService.to.get(
'appointment/unread_notice/page',
params: requestData,
);
if (response != null) {
final result = BaseModel.fromJson(response.data);
if (result.code == 0 && result.data != null) {
int total = result.data["total"] ?? 0;
isNotice = total > 0;
}
}
}
Future<void> _rating() async {
final response = await HttpService.to.get('appointment/rating/driver');
if (response != null) {
final result = BaseModel.fromJson(response.data);
if (result.code == 0 && result.data != null) {
rating = result.data.toString();
}
}
}
Future<void> _fetchCompletionRate() async { Future<void> _fetchCompletionRate() async {
final response = await HttpService.to.get( final response = await HttpService.to.get(
'appointment/orderAddHyd/driverAppointmentCompletionRate?phone=${StorageService.to.phone}', 'appointment/orderAddHyd/driverAppointmentCompletionRate?phone=${StorageService.to.phone}',

View File

@@ -91,17 +91,19 @@ class MinePage extends GetView<MineController> {
backgroundColor: Colors.grey[100], backgroundColor: Colors.grey[100],
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
), ),
icon: const Badge( icon: Badge(
// label: Text('3'), // 如果你想显示数字,就加 label // label: Text('3'), // 如果你想显示数字,就加 label
smallSize: 8, // 红点的大小 smallSize: 8,
backgroundColor: Colors.red, // 红点颜色 // 红点的大小
backgroundColor: controller.isNotice ? Colors.red : Colors.white,
// 红点颜色
child: Icon( child: Icon(
Icons.notifications_outlined, Icons.notifications_outlined,
color: Colors.black87, color: Colors.black87,
size: 25, size: 25,
), ),
), ),
) ),
], ],
), ),
), ),
@@ -157,14 +159,14 @@ class MinePage extends GetView<MineController> {
fit: StackFit.expand, fit: StackFit.expand,
children: [ children: [
CircularProgressIndicator( CircularProgressIndicator(
value: 10, // 假设得分80% value: (double.tryParse(controller.rating) ?? 0) / 10,
strokeWidth: 8, strokeWidth: 8,
backgroundColor: Colors.grey[200], backgroundColor: Colors.grey[200],
valueColor: AlwaysStoppedAnimation<Color>(Colors.blue), valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
), ),
Center( Center(
child: Text( child: Text(
'10', controller.rating,
style: TextStyle( style: TextStyle(
fontSize: 32, fontSize: 32,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -329,7 +331,10 @@ class MinePage extends GetView<MineController> {
// 如果加载完成且有数据 // 如果加载完成且有数据
if (snapshot.hasData) { if (snapshot.hasData) {
return TextX.labelSmall("当前版本: ${snapshot.data}",color: Colors.black54,); return TextX.labelSmall(
"当前版本: ${snapshot.data}",
color: Colors.black54,
);
} }
// 错误处理 // 错误处理
@@ -338,7 +343,7 @@ class MinePage extends GetView<MineController> {
), ),
), ),
], ],
) ),
], ],
), ),
), ),