// 贴纸库页面 — 贴纸包浏览 + 分类 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; final _searchController = TextEditingController(); /// 设计规格中的 8 个分类 static const _specCategories = [ '推荐', '可爱', '植物', '手绘', '校园', '节日', '文字', '和纸胶带', ]; @override void initState() { super.initState(); _bloc = StickerBloc(api: context.read()); _bloc.load(); } @override void dispose() { _bloc.dispose(); _searchController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final theme = Theme.of(context); final colorScheme = theme.colorScheme; return Scaffold( body: SafeArea( child: 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('重试'), ), ], ), ); } return Column( children: [ // ---- 自定义顶栏 ---- Padding( padding: const EdgeInsets.fromLTRB(8, 8, 16, 0), child: Row( children: [ IconButton( icon: const Icon(Icons.arrow_back_ios_new, size: 20), onPressed: () => Navigator.of(context).pop(), ), Text('贴纸素材', style: theme.textTheme.titleLarge?.copyWith( fontWeight: FontWeight.w700, )), ], ), ), const SizedBox(height: 8), // ---- 搜索框 ---- Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: TextField( controller: _searchController, decoration: InputDecoration( hintText: '搜索贴纸...', prefixIcon: const Icon(Icons.search, size: 20), filled: true, fillColor: colorScheme.surface, border: OutlineInputBorder( borderRadius: AppRadius.pillBorder, borderSide: BorderSide.none, ), contentPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), isDense: true, ), style: theme.textTheme.bodyMedium, onChanged: (v) { _bloc.search(v); }, ), ), const SizedBox(height: 12), // ---- 分类选择器(设计规格 8 分类) ---- SizedBox( height: 40, child: ListView( scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 16), children: _specCategories.map((cat) { final isSelected = cat == state.selectedCategory || (cat == '推荐' && state.selectedCategory == '全部'); return Padding( padding: const EdgeInsets.only(right: 8), child: FilterChip( selected: isSelected, label: Text(cat), onSelected: (_) { if (cat == '推荐') { _bloc.selectCategory('全部'); } else { _bloc.selectCategory(cat); } }, selectedColor: AppColors.accent.withValues(alpha: 0.15), checkmarkColor: AppColors.accent, labelStyle: TextStyle( color: isSelected ? AppColors.accent : colorScheme.onSurface, fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal, ), ), ); }).toList(), ), ), const SizedBox(height: 12), // ---- 精选贴纸包卡片 ---- if (state.selectedCategory == '全部') Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: const _FeaturedPackCard(), ), if (state.selectedCategory == '全部') const SizedBox(height: 16), // ---- 贴纸包网格 ---- 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 _FeaturedPackCard extends StatelessWidget { const _FeaturedPackCard(); @override Widget build(BuildContext context) { final theme = Theme.of(context); return GestureDetector( onTap: () { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('打开精选贴纸包: 治愈小动物')), ); }, child: Container( width: double.infinity, padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [AppColors.accent, AppColors.tertiary], ), borderRadius: AppRadius.lgBorder, ), child: Row( children: [ // emoji 图标区域 Container( width: 64, height: 64, decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.2), borderRadius: AppRadius.mdBorder, ), alignment: Alignment.center, child: const Text('🧸', style: TextStyle(fontSize: 36)), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('治愈小动物', style: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.w700, color: Colors.white, )), const SizedBox(height: 4), Text('超可爱的手绘小动物贴纸', style: theme.textTheme.bodySmall?.copyWith( color: Colors.white.withValues(alpha: 0.85), )), const SizedBox(height: 8), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), decoration: BoxDecoration( color: AppColors.secondary, borderRadius: AppRadius.pillBorder, ), child: const Text('限时免费', style: TextStyle( fontSize: 11, fontWeight: FontWeight.w600, color: Colors.white, )), ), ], ), ), ], ), ), ); } } /// 贴纸包卡片 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, ), ), ), ], ], ), ], ), ), ), ); } }