feat(app): 多页面动态化 — 搜索/资料/教师/贴纸库/模板/日历
- SearchPage: 热搜词从日记标签频率动态生成 + 模板搜索网格 - ProfilePage: 成就徽章从 AchievementBloc 动态加载 + 头像首字母 - TeacherPage: 班级码改为对话框展示 (班级名+码+人数) - StickerLibraryPage: 分类从 API 动态合并 + 精选包卡片动态化 - TemplateGalleryPage: 适配动态数据 - ClassPage: 微调 - HomePage: 路由适配 - CalendarBloc: 新增测试 - AppRouter: 路由更新
This commit is contained in:
@@ -10,6 +10,8 @@ import 'package:nuanji_app/features/auth/bloc/auth_bloc.dart';
|
||||
import 'package:nuanji_app/features/profile/bloc/settings_bloc.dart';
|
||||
import 'package:nuanji_app/data/models/user.dart';
|
||||
import 'package:nuanji_app/data/repositories/journal_repository.dart';
|
||||
import 'package:nuanji_app/features/achievement/bloc/achievement_bloc.dart';
|
||||
import 'package:nuanji_app/data/remote/api_client.dart';
|
||||
|
||||
/// 个人中心页面
|
||||
class ProfilePage extends StatelessWidget {
|
||||
@@ -60,7 +62,10 @@ class ProfilePage extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: const Text('😊', style: TextStyle(fontSize: 36)),
|
||||
child: Text(
|
||||
displayName.isNotEmpty ? displayName[0] : '😊',
|
||||
style: const TextStyle(fontSize: 36, color: Colors.white),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
// 用户名
|
||||
@@ -91,7 +96,7 @@ class ProfilePage extends StatelessWidget {
|
||||
_LiveStatsBar(borderSoft: borderSoft, colorScheme: colorScheme),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
// ---- 成就徽章 ----
|
||||
// ---- 成就徽章(动态加载) ----
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text('成就徽章', style: theme.textTheme.titleMedium?.copyWith(
|
||||
@@ -101,21 +106,11 @@ class ProfilePage extends StatelessWidget {
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(
|
||||
height: 100,
|
||||
child: ListView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
children: [
|
||||
_BadgeItem(emoji: '📝', name: '初出茅庐', bgColor: accentSoft, locked: false),
|
||||
const SizedBox(width: 12),
|
||||
_BadgeItem(emoji: '🔥', name: '七日连续', bgColor: tertiarySoft, locked: false),
|
||||
const SizedBox(width: 12),
|
||||
_BadgeItem(emoji: '🎨', name: '装饰达人', bgColor: roseSoft, locked: false),
|
||||
const SizedBox(width: 12),
|
||||
_BadgeItem(emoji: '🌟', name: '人气之星', bgColor: secondarySoft, locked: true),
|
||||
const SizedBox(width: 12),
|
||||
_BadgeItem(emoji: '🏆', name: '写作高手', bgColor: accentSoft, locked: true),
|
||||
const SizedBox(width: 12),
|
||||
_BadgeItem(emoji: '💎', name: '全能王', bgColor: tertiarySoft, locked: true),
|
||||
],
|
||||
child: _AchievementBadges(
|
||||
accentSoft: accentSoft,
|
||||
tertiarySoft: tertiarySoft,
|
||||
roseSoft: roseSoft,
|
||||
secondarySoft: secondarySoft,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
@@ -430,9 +425,79 @@ class _LiveStatsBarState extends State<_LiveStatsBar> {
|
||||
VerticalDivider(width: 1, indent: 4, endIndent: 4, color: widget.borderSoft),
|
||||
_StatItem(label: '本月日记', value: '$_monthCount', valueColor: widget.colorScheme.onSurface),
|
||||
VerticalDivider(width: 1, indent: 4, endIndent: 4, color: widget.borderSoft),
|
||||
_StatItem(label: '贴纸数', value: '--', valueColor: widget.colorScheme.onSurface),
|
||||
_StatItem(label: '贴纸数', value: _totalCount > 0 ? '$_totalCount' : '0', valueColor: widget.colorScheme.onSurface),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 成就徽章动态组件 — 从 AchievementBloc 加载真实数据
|
||||
class _AchievementBadges extends StatefulWidget {
|
||||
const _AchievementBadges({
|
||||
required this.accentSoft,
|
||||
required this.tertiarySoft,
|
||||
required this.roseSoft,
|
||||
required this.secondarySoft,
|
||||
});
|
||||
|
||||
final Color accentSoft;
|
||||
final Color tertiarySoft;
|
||||
final Color roseSoft;
|
||||
final Color secondarySoft;
|
||||
|
||||
@override
|
||||
State<_AchievementBadges> createState() => _AchievementBadgesState();
|
||||
}
|
||||
|
||||
class _AchievementBadgesState extends State<_AchievementBadges> {
|
||||
late final AchievementBloc _bloc;
|
||||
List<Achievement> _achievements = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_bloc = AchievementBloc(api: context.read<ApiClient>());
|
||||
_bloc.load();
|
||||
_bloc.addListener(_onUpdate);
|
||||
}
|
||||
|
||||
void _onUpdate() {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_achievements = _bloc.state.achievements;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_bloc.removeListener(_onUpdate);
|
||||
_bloc.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_achievements.isEmpty) {
|
||||
return const Center(child: Text('暂无成就', style: TextStyle(fontSize: 13)));
|
||||
}
|
||||
|
||||
final bgColors = [widget.accentSoft, widget.tertiarySoft, widget.roseSoft, widget.secondarySoft];
|
||||
|
||||
return ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: _achievements.length,
|
||||
separatorBuilder: (_, __) => const SizedBox(width: 12),
|
||||
itemBuilder: (context, index) {
|
||||
final a = _achievements[index];
|
||||
return _BadgeItem(
|
||||
emoji: a.icon ?? '🏆',
|
||||
name: a.name,
|
||||
bgColor: bgColors[index % bgColors.length],
|
||||
locked: !a.isUnlocked,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user