chengc 1 день назад
Родитель
Сommit
9936433697
2 измененных файлов с 208 добавлено и 0 удалено
  1. 1 0
      .gitignore
  2. 207 0
      lib/features/profile/profile_page.dart

+ 1 - 0
.gitignore

@@ -12,6 +12,7 @@ migrate_working_dir/
 
 *.swp
 profile
+!lib/features/profile/
 
 DerivedData/
 

+ 207 - 0
lib/features/profile/profile_page.dart

@@ -0,0 +1,207 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:go_router/go_router.dart';
+import 'package:tdesign_flutter/tdesign_flutter.dart';
+import '../../core/i18n/app_localizations.dart';
+import '../../core/i18n/locale_provider.dart';
+import '../../core/theme/app_colors.dart';
+import '../../shared/widgets/profile_menu_item.dart';
+import '../shell/nav_bar_config.dart';
+
+class ProfilePage extends ConsumerWidget {
+  const ProfilePage({super.key});
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final l10n = AppLocalizations.of(context);
+    final location = GoRouterState.of(context).uri.toString();
+    final currentLocale = ref.watch(localeProvider);
+
+    if (location.startsWith('/profile')) {
+      ref
+          .read(navBarConfigProvider.notifier)
+          .update(
+            NavBarConfig(
+              title: l10n.get('tabProfile'),
+              showBack: true,
+              leadingIcon: Icons.close,
+            ),
+          );
+    }
+    return SingleChildScrollView(
+      physics: const AlwaysScrollableScrollPhysics(),
+      child: Column(
+        children: [
+          const SizedBox(height: 16),
+          // 用户信息头部
+          _buildUserInfoCard(context, l10n),
+          const SizedBox(height: 16),
+          // 菜单列表
+          Padding(
+            padding: const EdgeInsets.symmetric(horizontal: 16),
+            child: Column(
+              children: [
+                ProfileMenuItem(
+                  icon: Icons.checklist,
+                  label: l10n.get('myApprovals'),
+                  onTap: () => context.push('/expense/list'),
+                ),
+                const SizedBox(height: 8),
+                ProfileMenuItem(
+                  icon: Icons.description,
+                  label: l10n.get('myApplications'),
+                  onTap: () => context.push('/expense-apply/list'),
+                ),
+                const SizedBox(height: 8),
+                ProfileMenuItem(
+                  icon: Icons.receipt_long,
+                  label: l10n.get('myExpenses'),
+                  onTap: () => context.push('/expense/list'),
+                ),
+                const SizedBox(height: 8),
+                ProfileMenuItem(
+                  icon: Icons.edit_note,
+                  label: l10n.get('outingLog'),
+                  onTap: () => context.push('/outing-log/list'),
+                ),
+                const SizedBox(height: 8),
+                ProfileMenuItem(
+                  icon: Icons.campaign,
+                  label: l10n.get('announcements'),
+                  onTap: () => context.push('/announcement/list'),
+                ),
+                const SizedBox(height: 8),
+                ProfileMenuItem(
+                  icon: Icons.settings,
+                  label: l10n.get('settings'),
+                ),
+                const SizedBox(height: 8),
+                ProfileMenuItem(
+                  icon: Icons.language,
+                  label: l10n.get('language'),
+                  trailing: _localeName(currentLocale),
+                  onTap: () => _showLanguageSheet(context, ref, currentLocale),
+                ),
+                const SizedBox(height: 8),
+                ProfileMenuItem(
+                  icon: Icons.info_outline,
+                  label: l10n.get('about'),
+                ),
+              ],
+            ),
+          ),
+          const SizedBox(height: 8),
+          TDFooter(TDFooterType.text, text: l10n.get('version')),
+        ],
+      ),
+    );
+  }
+
+  Widget _buildUserInfoCard(BuildContext context, AppLocalizations l10n) {
+    return Container(
+      margin: const EdgeInsets.symmetric(horizontal: 16),
+      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
+      decoration: BoxDecoration(
+        color: AppColors.bgCard,
+        borderRadius: BorderRadius.circular(12),
+      ),
+      child: Row(
+        children: [
+          // 头像
+          Container(
+            width: 64,
+            height: 64,
+            decoration: const BoxDecoration(
+              color: AppColors.primaryLight,
+              shape: BoxShape.circle,
+            ),
+            child: Center(
+              child: Text(
+                '张',
+                style: const TextStyle(
+                  fontSize: 28,
+                  fontWeight: FontWeight.w700,
+                  color: AppColors.primary,
+                ),
+              ),
+            ),
+          ),
+          const SizedBox(width: 16),
+          // 用户信息
+          Expanded(
+            child: Column(
+              crossAxisAlignment: CrossAxisAlignment.start,
+              children: [
+                Text(
+                  l10n.get('userName'),
+                  style: const TextStyle(
+                    fontSize: AppFontSizes.title,
+                    fontWeight: FontWeight.w600,
+                    color: AppColors.textPrimary,
+                  ),
+                ),
+                const SizedBox(height: AppSpacing.xs),
+                Text(
+                  l10n.get('salesDepartment'),
+                  style: const TextStyle(
+                    fontSize: AppFontSizes.body,
+                    color: AppColors.textSecondary,
+                  ),
+                ),
+              ],
+            ),
+          ),
+          // 箭头
+          const Icon(
+            Icons.chevron_right,
+            size: 16,
+            color: AppColors.textPlaceholder,
+          ),
+        ],
+      ),
+    );
+  }
+
+  String _localeName(Locale locale) {
+    if (locale.languageCode == 'zh' && locale.countryCode == 'TW') {
+      return '繁體中文';
+    }
+    if (locale.languageCode == 'en') {
+      return 'English';
+    }
+    return '简体中文';
+  }
+
+  void _showLanguageSheet(
+    BuildContext context,
+    WidgetRef ref,
+    Locale currentLocale,
+  ) {
+    final languages = [
+      (label: '简体中文', locale: const Locale('zh', 'CN')),
+      (label: 'English', locale: const Locale('en')),
+      (label: '繁體中文', locale: const Locale('zh', 'TW')),
+    ];
+
+    TDActionSheet.showListActionSheet(
+      Navigator.of(context, rootNavigator: true).context,
+      showCancel: false,
+      useSafeArea: false,
+      items: languages.map((lang) {
+        final isSelected =
+            lang.locale.languageCode == currentLocale.languageCode &&
+            lang.locale.countryCode == currentLocale.countryCode;
+        return TDActionSheetItem(
+          label: isSelected ? '${lang.label}  ✓' : lang.label,
+          textStyle: TextStyle(
+            color: isSelected ? AppColors.primary : AppColors.textPrimary,
+            fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
+          ),
+        );
+      }).toList(),
+      onSelected: (item, index) {
+        ref.read(localeProvider.notifier).setLocale(languages[index].locale);
+      },
+    );
+  }
+}