Files
flutterApp/lib/features/v2/my/presentation/pages/my_page.dart

292 lines
11 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter/services.dart';
import 'package:get_it/get_it.dart';
import 'package:go_router/go_router.dart';
import 'package:maibu_satabot_v2/core/app/app_user_cubit.dart';
import 'package:maibu_satabot_v2/core/localization/app_localizations.dart';
import 'package:maibu_satabot_v2/core/router/route_paths.dart';
import 'package:maibu_satabot_v2/core/storage/user_storage.dart';
import 'package:maibu_satabot_v2/core/theme/AppTheme.dart';
import 'package:maibu_satabot_v2/core/theme/theme_cubit.dart';
import 'package:maibu_satabot_v2/features/auth/presentation/bloc/auth_cubit.dart';
import 'package:maibu_satabot_v2/features/v2/my/presentation/cubit/my_cubit.dart';
import 'package:maibu_satabot_v2/features/v2/my/presentation/states/my_state.dart';
import 'package:maibu_satabot_v2/features/v2/my/di/my_di.dart';
import 'package:maibu_satabot_v2/features/v2/my/presentation/constants/my_constants.dart';
import 'package:maibu_satabot_v2/features/v2/my/presentation/widgets/user_profile_card.dart';
import 'package:maibu_satabot_v2/features/v2/my/presentation/widgets/quick_action_card.dart';
import 'package:maibu_satabot_v2/features/v2/my/presentation/widgets/menu_item_card.dart';
import 'package:maibu_satabot_v2/features/v2/my/presentation/pages/system_settings_page.dart';
import 'package:maibu_satabot_v2/features/v2/my/presentation/pages/profile_detail_page.dart';
/// 我的页面(100% 还原设计稿)
class MyPage extends StatelessWidget {
const MyPage({super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => MyDependencyInjector.createMyCubit()..loadData(),
child: _MyPageContent(),
);
}
}
class _MyPageContent extends StatelessWidget {
const _MyPageContent();
@override
Widget build(BuildContext context) {
return AnnotatedRegion<SystemUiOverlayStyle>(
value: const SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.light,
),
child: Scaffold(
extendBodyBehindAppBar: true,
backgroundColor: context.appColors.pageBackground,
body: BlocConsumer<MyCubit, MyState>(
listener: (context, state) {
if (state is MyError) {
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text(state.message)));
}
},
builder: (context, state) {
if (state is MyLoading) {
return const Center(
child: CircularProgressIndicator(color: MyColors.primary),
);
}
if (state is MyLoaded) {
final cubit = context.read<MyCubit>();
final appUserState = context.watch<AppUserCubit>().state;
final user = appUserState.user;
// 🔥 监听全局主题状态,夜间模式开关的真实值以 ThemeCubit 为准
final isDarkMode = context.watch<ThemeCubit>().isDarkMode;
// 获取用户信息(优先使用昵称,其次用户名)
final userName = user?.nickname ?? user?.username ?? '未知用户';
final userRole = user?.email ?? user?.phone ?? '未设置';
return Column(
children: [
// 用户信息卡片(延伸到状态栏)
UserProfileCard(
name: userName,
role: userRole,
avatar: user?.avatar,
onTap: () {
// 跳转到个人信息详情页
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const ProfileDetailPage(),
),
);
},
),
// 快捷入口卡片(负margin向上重叠)
Transform.translate(
offset: const Offset(0, -15),
child: QuickActionCard(
onMessageTap: () {
debugPrint('我的消息');
},
onFavoriteTap: () {
debugPrint('我的收藏');
},
onWorkOrderTap: () {
debugPrint('我的工单');
},
),
),
// 菜单列表(白色卡片)
Container(
margin: const EdgeInsets.only(
top: 15,
left: 16,
right: 16,
bottom: 16,
),
decoration: BoxDecoration(
color: context.appColors.cardBackground,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: context.appColors.cardShadow,
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.5,
),
child: ListView.builder(
shrinkWrap: true,
padding: EdgeInsets.zero,
// 末尾追加退出登录,占据“关于我们”原来的位置
itemCount: state.menuItems.length + 1,
itemBuilder: (context, index) {
// 退出登录(列表最后一项,在可滚动区域内避免底部溢出)
if (index == state.menuItems.length) {
return _buildLogoutButton(context);
}
final item = state.menuItems[index];
// 🔥 夜间模式开关值以全局 ThemeCubit 状态为准
final displayItem = item.id == 'night_mode'
? item.copyWith(switchValue: isDarkMode)
: item;
return MenuItemCard(
item: displayItem,
onTap: () => _handleMenuItemTap(context, cubit, item),
onSwitchChanged: item.hasSwitch
? (value) {
// 更新菜单 UI 状态
cubit.toggleNightMode(value);
// 🔥 真正切换全局主题
context
.read<ThemeCubit>()
.toggleDarkMode(value);
}
: null,
);
},
),
),
],
);
}
return const SizedBox.shrink();
},
),
),
);
}
/// 处理菜单项点击
void _handleMenuItemTap(BuildContext context, MyCubit cubit, dynamic item) {
debugPrint('🔍 点击菜单项 ID: ${item.id}, 标题: ${item.title}');
switch (item.id) {
case 'personal_info':
debugPrint('✅ 准备跳转到个人信息详情页');
// 跳转到个人信息详情页
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const ProfileDetailPage()),
);
debugPrint('✅ 已调用 Navigator.push');
break;
case 'offline_cache':
_showClearCacheDialog(context, cubit);
break;
case 'night_mode':
// 由 Switch 处理
break;
case 'system_settings':
// 跳转到系统设置页面
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SystemSettingsPage()),
);
break;
default:
debugPrint('点击菜单: ${item.title}');
// TODO: 根据 ID 跳转到对应页面
}
}
/// 显示清除缓存对话框
void _showClearCacheDialog(BuildContext context, MyCubit cubit) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(
AppLocalizations.of(context).translate('my_v2.clear_cache'),
),
content: Text(
AppLocalizations.of(context).translate('my_v2.confirm_clear_cache'),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text(AppLocalizations.of(context).translate('my_v2.cancel')),
),
TextButton(
onPressed: () {
Navigator.pop(context);
cubit.clearCache();
},
child: Text(
AppLocalizations.of(context).translate('my_v2.confirm'),
),
),
],
),
);
}
/// 退出登录(作为菜单列表最后一项,占据“关于我们”原来的位置)
Widget _buildLogoutButton(BuildContext context) {
return GestureDetector(
onTap: () {
_showLogoutDialog(context);
},
behavior: HitTestBehavior.opaque,
child: SizedBox(
height: 56,
child: Center(
child: Text(
AppLocalizations.of(context).translate('login.logout'),
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
color: Color(0xFFF53F3F),
),
),
),
),
);
}
/// 显示退出登录确认对话框
void _showLogoutDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(AppLocalizations.of(context).translate('login.logout')),
content: Text(
AppLocalizations.of(context).translate('login.confirm_logout'),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text(AppLocalizations.of(context).translate('my_v2.cancel')),
),
TextButton(
onPressed: () async {
Navigator.pop(context);
// 执行退出登录逻辑
await GetIt.I<UserStorage>().deleteUser();
GetIt.I<AuthCubit>().logout();
context.go(RoutePaths.login);
},
style: TextButton.styleFrom(
foregroundColor: const Color(0xFFF53F3F),
),
child: Text(
AppLocalizations.of(context).translate('my_v2.confirm'),
),
),
],
),
);
}
}