新增:更新个人中心数据显示
This commit is contained in:
parent
dedc03fc3c
commit
f3a163c958
@ -83,7 +83,7 @@ class _MainScaffold extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
const HomeScreen(),
|
const HomeScreen(),
|
||||||
GalleryScreen(isActive: currentTab == NavTab.gallery),
|
GalleryScreen(isActive: currentTab == NavTab.gallery),
|
||||||
const ProfileScreen(),
|
ProfileScreen(isActive: currentTab == NavTab.profile),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
bottomNavigationBar: BottomNavBar(
|
bottomNavigationBar: BottomNavBar(
|
||||||
|
|||||||
@ -118,6 +118,14 @@ class AuthService {
|
|||||||
UserState.setUserId(uid);
|
UserState.setUserId(uid);
|
||||||
_log('init: 已设置 userId');
|
_log('init: 已设置 userId');
|
||||||
}
|
}
|
||||||
|
final avatarUrl = data?['realm'] as String?;
|
||||||
|
if (avatarUrl != null && avatarUrl.isNotEmpty) {
|
||||||
|
UserState.setAvatar(avatarUrl);
|
||||||
|
}
|
||||||
|
final name = data?['terminal'] as String?;
|
||||||
|
if (name != null && name.isNotEmpty) {
|
||||||
|
UserState.setUserName(name);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
_log('init: 登录失败');
|
_log('init: 登录失败');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,8 @@ class UserState {
|
|||||||
|
|
||||||
static final ValueNotifier<int?> credits = ValueNotifier<int?>(null);
|
static final ValueNotifier<int?> credits = ValueNotifier<int?>(null);
|
||||||
static final ValueNotifier<String?> userId = ValueNotifier<String?>(null);
|
static final ValueNotifier<String?> userId = ValueNotifier<String?>(null);
|
||||||
|
static final ValueNotifier<String?> avatar = ValueNotifier<String?>(null);
|
||||||
|
static final ValueNotifier<String?> userName = ValueNotifier<String?>(null);
|
||||||
|
|
||||||
static void setCredits(int? value) {
|
static void setCredits(int? value) {
|
||||||
credits.value = value;
|
credits.value = value;
|
||||||
@ -15,6 +17,14 @@ class UserState {
|
|||||||
userId.value = value;
|
userId.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setAvatar(String? value) {
|
||||||
|
avatar.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setUserName(String? value) {
|
||||||
|
userName.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
static String formatCredits(int? value) {
|
static String formatCredits(int? value) {
|
||||||
if (value == null) return '--';
|
if (value == null) return '--';
|
||||||
return value.toString().replaceAllMapped(
|
return value.toString().replaceAllMapped(
|
||||||
|
|||||||
@ -1,14 +1,63 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_lucide/flutter_lucide.dart';
|
import 'package:flutter_lucide/flutter_lucide.dart';
|
||||||
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
|
|
||||||
|
import '../../core/api/api_config.dart';
|
||||||
|
import '../../core/api/services/user_api.dart';
|
||||||
|
import '../../core/auth/auth_service.dart';
|
||||||
import '../../core/theme/app_colors.dart';
|
import '../../core/theme/app_colors.dart';
|
||||||
import '../../core/user/user_state.dart';
|
import '../../core/user/user_state.dart';
|
||||||
import '../../core/theme/app_spacing.dart';
|
import '../../core/theme/app_spacing.dart';
|
||||||
import '../../core/theme/app_typography.dart';
|
import '../../core/theme/app_typography.dart';
|
||||||
|
|
||||||
/// Profile screen - matches Pencil KXeow
|
/// Profile screen - matches Pencil KXeow
|
||||||
class ProfileScreen extends StatelessWidget {
|
class ProfileScreen extends StatefulWidget {
|
||||||
const ProfileScreen({super.key});
|
const ProfileScreen({super.key, required this.isActive});
|
||||||
|
|
||||||
|
final bool isActive;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ProfileScreen> createState() => _ProfileScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ProfileScreenState extends State<ProfileScreen> {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
if (widget.isActive) _fetchAccount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(covariant ProfileScreen oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
if (widget.isActive && !oldWidget.isActive) {
|
||||||
|
_fetchAccount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _fetchAccount() async {
|
||||||
|
final uid = UserState.userId.value;
|
||||||
|
if (uid == null || uid.isEmpty) return;
|
||||||
|
try {
|
||||||
|
await AuthService.loginComplete;
|
||||||
|
final res = await UserApi.getAccount(
|
||||||
|
sentinel: ApiConfig.appId,
|
||||||
|
asset: uid,
|
||||||
|
);
|
||||||
|
if (!mounted) return;
|
||||||
|
if (res.isSuccess && res.data != null) {
|
||||||
|
final data = res.data as Map<String, dynamic>?;
|
||||||
|
final credits = data?['reveal'] as int?;
|
||||||
|
if (credits != null) UserState.setCredits(credits);
|
||||||
|
final avatarUrl = data?['realm'] as String?;
|
||||||
|
UserState.setAvatar(
|
||||||
|
avatarUrl != null && avatarUrl.isNotEmpty ? avatarUrl : null);
|
||||||
|
final name = data?['terminal'] as String?;
|
||||||
|
UserState.setUserName(
|
||||||
|
name != null && name.isNotEmpty ? name : null);
|
||||||
|
}
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -23,9 +72,25 @@ class ProfileScreen extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
_ProfileHeader(
|
ValueListenableBuilder<String?>(
|
||||||
userName: 'Alex Johnson',
|
valueListenable: UserState.avatar,
|
||||||
uid: 'UID 84920133',
|
builder: (_, avatarUrl, __) {
|
||||||
|
return ValueListenableBuilder<String?>(
|
||||||
|
valueListenable: UserState.userName,
|
||||||
|
builder: (_, userName, __) {
|
||||||
|
return ValueListenableBuilder<String?>(
|
||||||
|
valueListenable: UserState.userId,
|
||||||
|
builder: (_, userId, __) {
|
||||||
|
return _ProfileHeader(
|
||||||
|
avatarUrl: avatarUrl,
|
||||||
|
userName: userName,
|
||||||
|
uid: userId,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: AppSpacing.xl),
|
const SizedBox(height: AppSpacing.xl),
|
||||||
_BalanceCard(
|
_BalanceCard(
|
||||||
@ -56,12 +121,14 @@ class ProfileScreen extends StatelessWidget {
|
|||||||
|
|
||||||
class _ProfileHeader extends StatelessWidget {
|
class _ProfileHeader extends StatelessWidget {
|
||||||
const _ProfileHeader({
|
const _ProfileHeader({
|
||||||
required this.userName,
|
this.avatarUrl,
|
||||||
required this.uid,
|
this.userName,
|
||||||
|
this.uid,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String userName;
|
final String? avatarUrl;
|
||||||
final String uid;
|
final String? userName;
|
||||||
|
final String? uid;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -82,15 +149,31 @@ class _ProfileHeader extends StatelessWidget {
|
|||||||
width: 2,
|
width: 2,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: const Icon(
|
clipBehavior: Clip.antiAlias,
|
||||||
LucideIcons.user,
|
child: avatarUrl != null && avatarUrl!.isNotEmpty
|
||||||
size: 40,
|
? CachedNetworkImage(
|
||||||
color: AppColors.textSecondary,
|
imageUrl: avatarUrl!,
|
||||||
),
|
fit: BoxFit.cover,
|
||||||
|
placeholder: (_, __) => Icon(
|
||||||
|
LucideIcons.user,
|
||||||
|
size: 40,
|
||||||
|
color: AppColors.textSecondary,
|
||||||
|
),
|
||||||
|
errorWidget: (_, __, ___) => Icon(
|
||||||
|
LucideIcons.user,
|
||||||
|
size: 40,
|
||||||
|
color: AppColors.textSecondary,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Icon(
|
||||||
|
LucideIcons.user,
|
||||||
|
size: 40,
|
||||||
|
color: AppColors.textSecondary,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: AppSpacing.lg),
|
const SizedBox(height: AppSpacing.lg),
|
||||||
Text(
|
Text(
|
||||||
userName,
|
userName ?? 'Guest',
|
||||||
style: AppTypography.bodyLarge.copyWith(
|
style: AppTypography.bodyLarge.copyWith(
|
||||||
color: AppColors.textPrimary,
|
color: AppColors.textPrimary,
|
||||||
),
|
),
|
||||||
@ -107,7 +190,7 @@ class _ProfileHeader extends StatelessWidget {
|
|||||||
border: Border.all(color: AppColors.border),
|
border: Border.all(color: AppColors.border),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
uid,
|
uid != null && uid!.isNotEmpty ? 'UID $uid' : 'UID --',
|
||||||
style: AppTypography.caption.copyWith(
|
style: AppTypography.caption.copyWith(
|
||||||
color: AppColors.textSecondary,
|
color: AppColors.textSecondary,
|
||||||
),
|
),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user