// 成就页面 — 徽章收集展示 import 'package:flutter/material.dart'; import 'package:nuanji_app/core/theme/app_colors.dart'; /// 成就数据模型 class Achievement { final String id; final String code; final String name; final String? description; final String icon; final String category; final bool isUnlocked; const Achievement({ required this.id, required this.code, required this.name, this.description, required this.icon, required this.category, this.isUnlocked = false, }); } /// 成就页面 — 徽章收集和展示 class AchievementPage extends StatelessWidget { const AchievementPage({super.key}); static const _achievements = [ Achievement(id: '1', code: 'first_diary', name: '初次落笔', description: '写下第一篇日记', icon: '✏️', category: 'writing', isUnlocked: true), Achievement(id: '2', code: 'streak_7', name: '坚持一周', description: '连续写日记 7 天', icon: '🔥', category: 'writing'), Achievement(id: '3', code: 'streak_30', name: '月度达人', description: '连续写日记 30 天', icon: '💪', category: 'writing'), Achievement(id: '4', code: 'sticker_collector', name: '贴纸收藏家', description: '收集 10 张贴纸', icon: '🎨', category: 'collection'), Achievement(id: '5', code: 'social_butterfly', name: '分享之星', description: '分享 5 篇日记到班级', icon: '🌟', category: 'social'), Achievement(id: '6', code: 'mood_tracker', name: '心情记录员', description: '连续记录心情 14 天', icon: '🌈', category: 'writing'), Achievement(id: '7', code: 'early_bird', name: '早起日记', description: '在早上 7 点前写日记', icon: '🌅', category: 'special'), Achievement(id: '8', code: 'artist', name: '小画家', description: '在日记中画 10 幅涂鸦', icon: '🖌️', category: 'collection'), ]; @override Widget build(BuildContext context) { final theme = Theme.of(context); final colorScheme = theme.colorScheme; final unlocked = _achievements.where((a) => a.isUnlocked).length; return Scaffold( appBar: AppBar( title: const Text('成就'), ), body: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 进度概览 _AchievementProgressCard( unlocked: unlocked, total: _achievements.length, colorScheme: colorScheme, ), const SizedBox(height: 24), Text( '全部成就', style: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(height: 12), GridView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, mainAxisSpacing: 12, crossAxisSpacing: 12, childAspectRatio: 0.75, ), itemCount: _achievements.length, itemBuilder: (context, index) { return _AchievementCard( achievement: _achievements[index], colorScheme: colorScheme, ); }, ), ], ), ), ); } } /// 成就进度卡片 class _AchievementProgressCard extends StatelessWidget { const _AchievementProgressCard({ required this.unlocked, required this.total, required this.colorScheme, }); final int unlocked; final int total; final ColorScheme colorScheme; @override Widget build(BuildContext context) { final theme = Theme.of(context); final progress = total > 0 ? unlocked / total : 0.0; return Card( elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(22), ), color: colorScheme.primaryContainer, child: Padding( padding: const EdgeInsets.all(20), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '收集进度', style: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), ), Text( '$unlocked / $total', style: theme.textTheme.titleMedium?.copyWith( color: colorScheme.primary, fontWeight: FontWeight.bold, ), ), ], ), const SizedBox(height: 12), ClipRRect( borderRadius: BorderRadius.circular(8), child: LinearProgressIndicator( value: progress, minHeight: 10, backgroundColor: colorScheme.primary.withValues(alpha: 0.15), color: colorScheme.primary, ), ), ], ), ), ); } } /// 成就卡片 class _AchievementCard extends StatelessWidget { const _AchievementCard({ required this.achievement, required this.colorScheme, }); final Achievement achievement; final ColorScheme colorScheme; @override Widget build(BuildContext context) { final theme = Theme.of(context); return Card( elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), side: BorderSide( color: achievement.isUnlocked ? AppColors.accent.withValues(alpha: 0.4) : colorScheme.outlineVariant, ), ), child: Padding( padding: const EdgeInsets.all(16), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( width: 56, height: 56, decoration: BoxDecoration( shape: BoxShape.circle, color: achievement.isUnlocked ? AppColors.accent.withValues(alpha: 0.15) : colorScheme.onSurface.withValues(alpha: 0.05), ), alignment: Alignment.center, child: achievement.isUnlocked ? Text(achievement.icon, style: const TextStyle(fontSize: 28)) : Icon( Icons.lock_outline, color: colorScheme.onSurface.withValues(alpha: 0.3), ), ), const SizedBox(height: 8), Text( achievement.name, style: theme.textTheme.titleSmall?.copyWith( fontWeight: FontWeight.w600, color: achievement.isUnlocked ? colorScheme.onSurface : colorScheme.onSurface.withValues(alpha: 0.4), ), ), if (achievement.description != null) ...[ const SizedBox(height: 4), Text( achievement.description!, style: theme.textTheme.bodySmall?.copyWith( color: colorScheme.onSurface.withValues( alpha: achievement.isUnlocked ? 0.6 : 0.3, ), ), textAlign: TextAlign.center, maxLines: 2, overflow: TextOverflow.ellipsis, ), ], ], ), ), ); } }