223 lines
5.8 KiB
Dart
223 lines
5.8 KiB
Dart
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
|
|
import '../models/notification_model.dart';
|
|||
|
|
import '../services/notification_service.dart';
|
|||
|
|
|
|||
|
|
/// 通知状态
|
|||
|
|
class NotificationState {
|
|||
|
|
final List<NotificationModel> notifications;
|
|||
|
|
final int total;
|
|||
|
|
final int unreadCount;
|
|||
|
|
final bool isLoading;
|
|||
|
|
final String? error;
|
|||
|
|
|
|||
|
|
NotificationState({
|
|||
|
|
this.notifications = const [],
|
|||
|
|
this.total = 0,
|
|||
|
|
this.unreadCount = 0,
|
|||
|
|
this.isLoading = false,
|
|||
|
|
this.error,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
NotificationState copyWith({
|
|||
|
|
List<NotificationModel>? notifications,
|
|||
|
|
int? total,
|
|||
|
|
int? unreadCount,
|
|||
|
|
bool? isLoading,
|
|||
|
|
String? error,
|
|||
|
|
}) {
|
|||
|
|
return NotificationState(
|
|||
|
|
notifications: notifications ?? this.notifications,
|
|||
|
|
total: total ?? this.total,
|
|||
|
|
unreadCount: unreadCount ?? this.unreadCount,
|
|||
|
|
isLoading: isLoading ?? this.isLoading,
|
|||
|
|
error: error,
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 通知Notifier
|
|||
|
|
class NotificationNotifier extends StateNotifier<NotificationState> {
|
|||
|
|
final NotificationService _service = NotificationService();
|
|||
|
|
|
|||
|
|
NotificationNotifier() : super(NotificationState());
|
|||
|
|
|
|||
|
|
/// 加载通知列表
|
|||
|
|
Future<void> loadNotifications({
|
|||
|
|
int page = 1,
|
|||
|
|
int limit = 10,
|
|||
|
|
bool onlyUnread = false,
|
|||
|
|
}) async {
|
|||
|
|
state = state.copyWith(isLoading: true, error: null);
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
final response = await _service.getNotifications(
|
|||
|
|
page: page,
|
|||
|
|
limit: limit,
|
|||
|
|
onlyUnread: onlyUnread,
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
if (response.success && response.data != null) {
|
|||
|
|
state = state.copyWith(
|
|||
|
|
notifications: response.data!['notifications'] as List<NotificationModel>,
|
|||
|
|
total: response.data!['total'] as int,
|
|||
|
|
isLoading: false,
|
|||
|
|
);
|
|||
|
|
} else {
|
|||
|
|
state = state.copyWith(
|
|||
|
|
isLoading: false,
|
|||
|
|
error: response.message,
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
state = state.copyWith(
|
|||
|
|
isLoading: false,
|
|||
|
|
error: '加载通知列表失败: $e',
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 加载未读通知数量
|
|||
|
|
Future<void> loadUnreadCount() async {
|
|||
|
|
try {
|
|||
|
|
final response = await _service.getUnreadCount();
|
|||
|
|
|
|||
|
|
if (response.success && response.data != null) {
|
|||
|
|
state = state.copyWith(
|
|||
|
|
unreadCount: response.data!,
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
print('加载未读通知数量失败: $e');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 标记通知为已读
|
|||
|
|
Future<bool> markAsRead(int notificationId) async {
|
|||
|
|
try {
|
|||
|
|
final response = await _service.markAsRead(notificationId);
|
|||
|
|
|
|||
|
|
if (response.success) {
|
|||
|
|
// 更新本地状态
|
|||
|
|
final updatedNotifications = state.notifications.map((n) {
|
|||
|
|
if (n.id == notificationId) {
|
|||
|
|
return NotificationModel(
|
|||
|
|
id: n.id,
|
|||
|
|
userId: n.userId,
|
|||
|
|
type: n.type,
|
|||
|
|
title: n.title,
|
|||
|
|
content: n.content,
|
|||
|
|
link: n.link,
|
|||
|
|
isRead: true,
|
|||
|
|
priority: n.priority,
|
|||
|
|
createdAt: n.createdAt,
|
|||
|
|
readAt: DateTime.now(),
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
return n;
|
|||
|
|
}).toList();
|
|||
|
|
|
|||
|
|
state = state.copyWith(
|
|||
|
|
notifications: updatedNotifications,
|
|||
|
|
unreadCount: state.unreadCount > 0 ? state.unreadCount - 1 : 0,
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
} catch (e) {
|
|||
|
|
print('标记通知已读失败: $e');
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 标记所有通知为已读
|
|||
|
|
Future<bool> markAllAsRead() async {
|
|||
|
|
try {
|
|||
|
|
final response = await _service.markAllAsRead();
|
|||
|
|
|
|||
|
|
if (response.success) {
|
|||
|
|
// 更新本地状态
|
|||
|
|
final updatedNotifications = state.notifications.map((n) {
|
|||
|
|
return NotificationModel(
|
|||
|
|
id: n.id,
|
|||
|
|
userId: n.userId,
|
|||
|
|
type: n.type,
|
|||
|
|
title: n.title,
|
|||
|
|
content: n.content,
|
|||
|
|
link: n.link,
|
|||
|
|
isRead: true,
|
|||
|
|
priority: n.priority,
|
|||
|
|
createdAt: n.createdAt,
|
|||
|
|
readAt: DateTime.now(),
|
|||
|
|
);
|
|||
|
|
}).toList();
|
|||
|
|
|
|||
|
|
state = state.copyWith(
|
|||
|
|
notifications: updatedNotifications,
|
|||
|
|
unreadCount: 0,
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
} catch (e) {
|
|||
|
|
print('标记所有通知已读失败: $e');
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 删除通知
|
|||
|
|
Future<bool> deleteNotification(int notificationId) async {
|
|||
|
|
try {
|
|||
|
|
final response = await _service.deleteNotification(notificationId);
|
|||
|
|
|
|||
|
|
if (response.success) {
|
|||
|
|
// 从本地状态中移除
|
|||
|
|
final updatedNotifications =
|
|||
|
|
state.notifications.where((n) => n.id != notificationId).toList();
|
|||
|
|
|
|||
|
|
// 如果删除的是未读通知,更新未读数量
|
|||
|
|
final deletedNotification =
|
|||
|
|
state.notifications.firstWhere((n) => n.id == notificationId);
|
|||
|
|
final newUnreadCount = deletedNotification.isRead
|
|||
|
|
? state.unreadCount
|
|||
|
|
: (state.unreadCount > 0 ? state.unreadCount - 1 : 0);
|
|||
|
|
|
|||
|
|
state = state.copyWith(
|
|||
|
|
notifications: updatedNotifications,
|
|||
|
|
total: state.total - 1,
|
|||
|
|
unreadCount: newUnreadCount,
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
} catch (e) {
|
|||
|
|
print('删除通知失败: $e');
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 刷新通知列表
|
|||
|
|
Future<void> refresh() async {
|
|||
|
|
await loadNotifications();
|
|||
|
|
await loadUnreadCount();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 通知Provider
|
|||
|
|
final notificationProvider =
|
|||
|
|
StateNotifierProvider<NotificationNotifier, NotificationState>(
|
|||
|
|
(ref) => NotificationNotifier(),
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
/// 未读通知数量Provider(便捷访问)
|
|||
|
|
final unreadCountProvider = Provider<int>((ref) {
|
|||
|
|
return ref.watch(notificationProvider).unreadCount;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
/// 通知列表Provider(便捷访问)
|
|||
|
|
final notificationListProvider = Provider<List<NotificationModel>>((ref) {
|
|||
|
|
return ref.watch(notificationProvider).notifications;
|
|||
|
|
});
|