/// In-site notification fetched from the notification-service backend. class InSiteNotification { final String id; final String title; final String content; final String type; // SYSTEM | MAINTENANCE | FEATURE | ANNOUNCEMENT | BILLING | SECURITY final String priority; // LOW | NORMAL | HIGH | URGENT final String? imageUrl; final String? linkUrl; final bool requiresForceRead; final DateTime? publishedAt; final bool isRead; const InSiteNotification({ required this.id, required this.title, required this.content, required this.type, required this.priority, this.imageUrl, this.linkUrl, required this.requiresForceRead, this.publishedAt, required this.isRead, }); factory InSiteNotification.fromJson(Map json) { return InSiteNotification( id: json['id'] as String, title: json['title'] as String? ?? '', content: json['content'] as String? ?? '', type: json['type'] as String? ?? 'ANNOUNCEMENT', priority: json['priority'] as String? ?? 'NORMAL', imageUrl: json['imageUrl'] as String?, linkUrl: json['linkUrl'] as String?, requiresForceRead: json['requiresForceRead'] as bool? ?? false, publishedAt: json['publishedAt'] != null ? DateTime.tryParse(json['publishedAt'] as String) : null, isRead: json['isRead'] as bool? ?? false, ); } InSiteNotification copyWith({bool? isRead}) => InSiteNotification( id: id, title: title, content: content, type: type, priority: priority, imageUrl: imageUrl, linkUrl: linkUrl, requiresForceRead: requiresForceRead, publishedAt: publishedAt, isRead: isRead ?? this.isRead, ); String get typeLabel { const labels = { 'SYSTEM': '系统通知', 'MAINTENANCE': '维护通知', 'FEATURE': '新功能', 'ANNOUNCEMENT': '公告', 'BILLING': '账单通知', 'SECURITY': '安全通知', }; return labels[type] ?? type; } String get typeEmoji { const emojis = { 'SYSTEM': '⚙️', 'MAINTENANCE': '🔧', 'FEATURE': '✨', 'ANNOUNCEMENT': '📢', 'BILLING': '💳', 'SECURITY': '🔒', }; return emojis[type] ?? '📩'; } String get relativeTime { final ref = publishedAt ?? DateTime.now(); final diff = DateTime.now().difference(ref); if (diff.inMinutes < 1) return '刚刚'; if (diff.inHours < 1) return '${diff.inMinutes}分钟前'; if (diff.inDays < 1) return '${diff.inHours}小时前'; if (diff.inDays < 30) return '${diff.inDays}天前'; return '${ref.year}-${ref.month.toString().padLeft(2, '0')}-${ref.day.toString().padLeft(2, '0')}'; } }