// 贴纸库页面 — 贴纸包浏览 + 分类 Tab import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:nuanji_app/core/theme/app_colors.dart'; import 'package:nuanji_app/core/theme/app_radius.dart'; import 'package:nuanji_app/data/remote/api_client.dart'; import '../bloc/sticker_bloc.dart'; /// 贴纸库页面 — 分类浏览贴纸包 class StickerLibraryPage extends StatefulWidget { const StickerLibraryPage({super.key}); @override State createState() => _StickerLibraryPageState(); } class _StickerLibraryPageState extends State { late final StickerBloc _bloc; @override void initState() { super.initState(); _bloc = StickerBloc(api: context.read()); _bloc.load(); } @override void dispose() { _bloc.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; return Scaffold( appBar: AppBar(title: const Text('贴纸库')), body: ListenableBuilder( listenable: _bloc, builder: (context, _) { final state = _bloc.state; if (state.isLoading) { return const Center(child: CircularProgressIndicator()); } if (state.errorMessage != null) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.error_outline, size: 48, color: colorScheme.error), const SizedBox(height: 16), FilledButton.tonal( onPressed: _bloc.load, child: const Text('重试'), ), ], ), ); } final categories = state.categories; return Column( children: [ // 分类选择器(横向滚动 Chips) SizedBox( height: 48, child: ListView( scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 16), children: categories.map((cat) { final isSelected = cat == state.selectedCategory; return Padding( padding: const EdgeInsets.only(right: 8), child: FilterChip( selected: isSelected, label: Text(cat), onSelected: (_) => _bloc.selectCategory(cat), selectedColor: colorScheme.primaryContainer, checkmarkColor: colorScheme.primary, ), ); }).toList(), ), ), const SizedBox(height: 8), // 贴纸包网格 Expanded( child: state.filteredPacks.isEmpty ? const Center(child: Text('暂无贴纸包')) : GridView.builder( padding: const EdgeInsets.all(16), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, mainAxisSpacing: 12, crossAxisSpacing: 12, childAspectRatio: 0.85, ), itemCount: state.filteredPacks.length, itemBuilder: (context, index) { return _StickerPackCard( pack: state.filteredPacks[index], colorScheme: colorScheme, ); }, ), ), ], ); }, ), ); } } /// 贴纸包卡片 class _StickerPackCard extends StatelessWidget { const _StickerPackCard({ required this.pack, required this.colorScheme, }); final StickerPack pack; final ColorScheme colorScheme; @override Widget build(BuildContext context) { final theme = Theme.of(context); return Card( elevation: 0, shape: RoundedRectangleBorder( borderRadius: AppRadius.mdBorder, side: BorderSide(color: colorScheme.outlineVariant), ), child: InkWell( onTap: () { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('打开贴纸包: ${pack.name}')), ); }, borderRadius: AppRadius.mdBorder, child: Padding( padding: const EdgeInsets.all(16), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // 贴纸包封面图标 Container( width: 64, height: 64, decoration: BoxDecoration( color: colorScheme.primaryContainer.withValues(alpha: 0.3), borderRadius: AppRadius.mdBorder, ), alignment: Alignment.center, child: Text( pack.coverImageUrl != null ? '🎨' : pack.displayCover, style: const TextStyle(fontSize: 32), ), ), const SizedBox(height: 12), // 名称 Text( pack.name, style: theme.textTheme.titleSmall?.copyWith( fontWeight: FontWeight.w600, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), const SizedBox(height: 4), // 数量和价格标签 Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( '${pack.stickerCount} 张', style: theme.textTheme.bodySmall?.copyWith( color: colorScheme.onSurface.withValues(alpha: 0.5), ), ), if (!pack.isFree) ...[ const SizedBox(width: 8), Container( padding: const EdgeInsets.symmetric( horizontal: 6, vertical: 2), decoration: BoxDecoration( color: AppColors.accent.withValues(alpha: 0.15), borderRadius: BorderRadius.circular(6), ), child: Text( '积分', style: theme.textTheme.labelSmall?.copyWith( color: AppColors.accent, ), ), ), ], ], ), ], ), ), ), ); } }