rtc_prd/airhub_app/lib/pages/profile/profile_page.dart
2026-02-09 18:03:55 +08:00

330 lines
10 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:airhub_app/theme/design_tokens.dart';
import 'package:airhub_app/widgets/feedback_dialog.dart';
import 'package:airhub_app/widgets/animated_gradient_background.dart';
import 'package:airhub_app/pages/profile/profile_info_page.dart';
import 'package:airhub_app/pages/profile/settings_page.dart';
import 'package:airhub_app/pages/profile/agent_manage_page.dart';
import 'package:airhub_app/pages/profile/help_page.dart';
import 'package:airhub_app/pages/product_selection_page.dart';
import 'package:airhub_app/pages/profile/notification_page.dart';
import 'package:airhub_app/widgets/ios_toast.dart';
import 'package:airhub_app/features/user/presentation/controllers/user_controller.dart';
class ProfilePage extends ConsumerWidget {
const ProfilePage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final userAsync = ref.watch(userControllerProvider);
final user = userAsync.value;
return Scaffold(
backgroundColor: Colors.transparent,
body: Stack(
children: [
// 动态渐变背景
const AnimatedGradientBackground(),
// 内容区域
Column(
children: [
_buildHeader(),
Expanded(
child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(
horizontal: AppSpacing.lg,
),
child: Column(
children: [
const SizedBox(height: 20), // Top spacing
const SizedBox(height: 20), // Top spacing
_buildUserCard(context, user),
const SizedBox(height: 20),
_buildMenuList(context),
const SizedBox(height: 140), // Bottom padding for footer
],
),
),
),
],
),
],
),
);
}
Widget _buildHeader() {
return Container(
padding: const EdgeInsets.only(
top: 20, // safe area will be added by SafeArea or MediaQuery
left: AppSpacing.lg,
right: AppSpacing.lg,
bottom: AppSpacing.md,
),
child: SafeArea(
bottom: false,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const SizedBox(width: 44), // Placeholder for balance
Text('我的', style: AppTextStyles.title),
_buildNotificationButton(),
],
),
),
);
}
Widget _buildNotificationButton() {
return Builder(
builder: (context) => GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => const NotificationPage()),
);
},
child: Container(
width: 44,
height: 44,
decoration: BoxDecoration(
color: AppColors.iconBtnBg,
borderRadius: BorderRadius.circular(AppRadius.button),
border: Border.all(color: AppColors.iconBtnBorder),
),
child: Stack(
alignment: Alignment.center,
children: [
Icon(
Icons.notifications_outlined,
color: AppColors.textPrimary,
size: 22,
),
Positioned(
top: 10,
right: 10,
child: Container(
width: 8,
height: 8,
decoration: BoxDecoration(
color: AppColors.notificationDot,
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 2),
),
),
),
],
),
),
),
);
}
Widget _buildUserCard(BuildContext context, dynamic user) {
final nickname = user?.nickname ?? '未设置昵称';
final phone = user?.phone ?? '';
final maskedPhone = phone.length >= 7
? '${phone.substring(0, 3)}****${phone.substring(phone.length - 4)}'
: phone;
final avatarUrl = user?.avatar as String?;
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const ProfileInfoPage()),
);
},
child: Container(
padding: const EdgeInsets.all(AppSpacing.lg),
decoration: BoxDecoration(
color: AppColors.cardSurface,
borderRadius: BorderRadius.circular(AppRadius.card),
boxShadow: const [AppShadows.card],
),
child: Row(
children: [
Container(
width: 64,
height: 64,
decoration: const BoxDecoration(
shape: BoxShape.circle,
gradient: LinearGradient(
colors: AppColors.avatarGradient,
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
child: ClipOval(
child: (avatarUrl != null && avatarUrl.isNotEmpty)
? Image.network(
avatarUrl,
fit: BoxFit.cover,
errorBuilder: (ctx, err, stack) =>
Image.asset('assets/www/Capybara.png', fit: BoxFit.cover),
)
: Image.asset(
'assets/www/Capybara.png',
fit: BoxFit.cover,
errorBuilder: (ctx, err, stack) =>
const Icon(Icons.person, color: Colors.white),
),
),
),
const SizedBox(width: AppSpacing.md),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(nickname, style: AppTextStyles.userName),
const SizedBox(height: 4),
Text('ID: $maskedPhone', style: AppTextStyles.userId),
],
),
),
const Icon(
Icons.chevron_right,
color: AppColors.textHint,
size: 24,
),
],
),
),
);
}
Widget _buildMenuList(BuildContext context) {
return Container(
decoration: BoxDecoration(
boxShadow: const [AppShadows.card],
borderRadius: BorderRadius.circular(AppRadius.card),
),
child: Material(
color: AppColors.cardSurface,
borderRadius: BorderRadius.circular(AppRadius.card),
clipBehavior: Clip.antiAlias,
child: Column(
children: [
_buildMenuItem(
context,
'🧠',
'角色记忆',
showDivider: true,
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const AgentManagePage()),
),
),
_buildMenuItem(
context,
'📦',
'我的设备',
showDivider: true,
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const ProductSelectionPage()),
),
),
_buildMenuItem(
context,
'⚙️',
'设置',
showDivider: true,
badge: 'NEW',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SettingsPage()),
);
},
),
_buildMenuItem(
context,
'💬',
'意见反馈',
showDivider: true,
onTap: () => _showFeedbackDialog(context),
),
_buildMenuItem(
context,
'',
'帮助中心',
showDivider: false,
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const HelpPage()),
),
),
],
),
),
);
}
Widget _buildMenuItem(
BuildContext context,
String iconEmoji,
String text, {
bool showDivider = true,
String? badge,
VoidCallback? onTap,
}) {
return InkWell(
onTap:
onTap ??
() {
AppToast.show(context, '$text 功能开发中');
},
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: AppSpacing.lg,
vertical: 18,
),
decoration: showDivider
? const BoxDecoration(
border: Border(
bottom: BorderSide(
color: Color(0x0D000000),
), // rgba(0,0,0,0.05)
),
)
: null,
child: Row(
children: [
SizedBox(
width: 24,
child: Text(iconEmoji, style: const TextStyle(fontSize: 20)),
),
const SizedBox(width: AppSpacing.md),
Expanded(child: Text(text, style: AppTextStyles.menuText)),
if (badge != null) ...[
Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
decoration: BoxDecoration(
color: AppColors.badgeNew,
borderRadius: BorderRadius.circular(AppRadius.badge),
),
child: Text(badge, style: AppTextStyles.badge),
),
const SizedBox(width: 8),
],
const Icon(
Icons.chevron_right,
color: AppColors.textHint,
size: 20,
),
],
),
),
);
}
void _showFeedbackDialog(BuildContext context) {
showDialog(
context: context,
barrierColor: Colors.black.withOpacity(0.5),
builder: (context) => const FeedbackDialog(),
);
}
}