import 'package:flutter/material.dart'; import 'package:package_info_plus/package_info_plus.dart'; import '../../../../app/theme/app_colors.dart'; import '../../../../app/router.dart'; import '../../../../app/i18n/app_localizations.dart'; import '../../../../core/updater/update_service.dart'; import '../../../../core/services/issuer_service.dart'; import '../../../../core/services/auth_service.dart'; import '../../../../core/network/api_client.dart'; import '../../../../core/telemetry/telemetry_service.dart'; /// 发行方设置页面(我的) /// /// 企业信息、门店管理、员工管理、专属客服、安全设置 class SettingsPage extends StatefulWidget { const SettingsPage({super.key}); @override State createState() => _SettingsPageState(); } class _SettingsPageState extends State { String _appVersion = ''; bool _isLoadingProfile = true; IssuerProfile? _profile; bool _isLoggingOut = false; final _issuerService = IssuerService(); final _authService = AuthService(); @override void initState() { super.initState(); _loadVersion(); _loadProfile(); } Future _loadVersion() async { final info = await PackageInfo.fromPlatform(); if (mounted) { setState(() => _appVersion = 'v${info.version}+${info.buildNumber}'); } } Future _loadProfile() async { try { final profile = await _issuerService.getProfile(); if (!mounted) return; setState(() { _profile = profile; _isLoadingProfile = false; }); } catch (e) { debugPrint('[SettingsPage] loadProfile error: $e'); if (!mounted) return; setState(() => _isLoadingProfile = false); } } Future _handleLogout() async { final confirmed = await showDialog( context: context, builder: (ctx) => AlertDialog( title: Text(context.t('settings_confirm_logout')), content: Text(context.t('settings_confirm_logout_desc')), actions: [ TextButton(onPressed: () => Navigator.pop(ctx, false), child: Text(context.t('cancel'))), ElevatedButton( onPressed: () => Navigator.pop(ctx, true), style: ElevatedButton.styleFrom(backgroundColor: AppColors.error), child: Text(context.t('confirm')), ), ], ), ); if (confirmed != true) return; setState(() => _isLoggingOut = true); try { await _authService.logout(); } catch (e) { debugPrint('[SettingsPage] logout error: $e'); } // 遥测:退出登录时清除 userId 和 token if (TelemetryService().isInitialized) { TelemetryService().clearUserId(); TelemetryService().clearAccessToken(); } ApiClient.instance.setToken(null); if (!mounted) return; Navigator.pushNamedAndRemoveUntil(context, AppRouter.login, (_) => false); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(context.t('settings_title'))), body: SingleChildScrollView( child: Column( children: [ // Profile Card _buildProfileCard(context), // Tier & Benefits _buildTierCard(context), const SizedBox(height: 8), // Menu Groups _buildMenuGroup(context.t('settings_group_company'), [ _MenuItem(context.t('settings_company_info'), Icons.business_rounded, () { // TODO: Navigate to company info page when available }), _MenuItem(context.t('settings_store_mgmt'), Icons.store_rounded, () { Navigator.pushNamed(context, AppRouter.storeManagement); }), _MenuItem(context.t('settings_employee_mgmt'), Icons.people_rounded, () { Navigator.pushNamed(context, AppRouter.storeManagement); }), _MenuItem(context.t('settings_permissions'), Icons.admin_panel_settings_rounded, () { // TODO: Navigate to permissions page when available }), ]), _buildMenuGroup(context.t('settings_group_support'), [ _MenuItem(context.t('settings_ai_assistant'), Icons.auto_awesome_rounded, () { Navigator.pushNamed(context, AppRouter.aiAgent); }), _MenuItem(context.t('settings_customer_service'), Icons.headset_mic_rounded, () { // TODO: Navigate to customer service page when available }), _MenuItem(context.t('settings_help_center'), Icons.help_outline_rounded, () { // TODO: Navigate to help center page when available }), _MenuItem(context.t('settings_feedback'), Icons.feedback_rounded, () { // TODO: Navigate to feedback page when available }), ]), _buildMenuGroup(context.t('settings_group_security'), [ _MenuItem(context.t('settings_change_password'), Icons.lock_outline_rounded, () { // TODO: Navigate to change password page when available }), _MenuItem(context.t('settings_operation_log'), Icons.history_rounded, () { // TODO: Navigate to operation log page when available }), _MenuItem( '${context.t('settings_about')}${_appVersion.isNotEmpty ? ' $_appVersion' : ''}', Icons.info_outline_rounded, () => UpdateService().manualCheckUpdate(context), ), ]), // Logout Padding( padding: const EdgeInsets.all(20), child: SizedBox( width: double.infinity, child: OutlinedButton( onPressed: _isLoggingOut ? null : _handleLogout, style: OutlinedButton.styleFrom( foregroundColor: AppColors.error, side: const BorderSide(color: AppColors.error), ), child: _isLoggingOut ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2), ) : Text(context.t('settings_logout')), ), ), ), ], ), ), ); } Widget _buildProfileCard(BuildContext context) { return Container( padding: const EdgeInsets.fromLTRB(20, 20, 20, 16), color: AppColors.surface, child: Row( children: [ _profile?.logoUrl != null ? ClipRRect( borderRadius: BorderRadius.circular(14), child: Image.network( _profile!.logoUrl!, width: 56, height: 56, fit: BoxFit.cover, errorBuilder: (_, __, ___) => ClipRRect( borderRadius: BorderRadius.circular(14), child: Image.asset('assets/images/logo_icon.png', width: 56, height: 56), ), ), ) : ClipRRect( borderRadius: BorderRadius.circular(14), child: Image.asset( 'assets/images/logo_icon.png', width: 56, height: 56, ), ), const SizedBox(width: 14), Expanded( child: _isLoadingProfile ? const Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: 120, height: 16, child: LinearProgressIndicator(), ), SizedBox(height: 8), SizedBox( width: 80, height: 12, child: LinearProgressIndicator(), ), ], ) : Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( _profile?.companyName ?? '--', style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w700), ), const SizedBox(height: 4), Text( _profile?.contactEmail != null ? '${context.t('settings_admin')}:${_profile!.contactEmail}' : _profile?.contactPhone != null ? '${context.t('settings_admin')}:${_profile!.contactPhone}' : context.t('settings_admin'), style: const TextStyle(fontSize: 13, color: AppColors.textSecondary), ), ], ), ), const Icon(Icons.chevron_right_rounded, color: AppColors.textTertiary), ], ), ); } Widget _buildTierCard(BuildContext context) { return Container( margin: const EdgeInsets.fromLTRB(20, 12, 20, 0), padding: const EdgeInsets.all(16), decoration: BoxDecoration( gradient: const LinearGradient( colors: [Color(0xFFFFF7E6), Color(0xFFFFECC7)], ), borderRadius: BorderRadius.circular(12), ), child: Row( children: [ const Icon(Icons.star_rounded, color: AppColors.tierGold, size: 28), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( _profile?.creditRating != null ? '${_profile!.creditRating} ${context.t('settings_gold_issuer')}' : context.t('settings_gold_issuer'), style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w700, color: AppColors.tierGold), ), Text(context.t('settings_tier_benefits'), style: const TextStyle(fontSize: 12, color: AppColors.textSecondary)), ], ), ), TextButton( onPressed: () { Navigator.pushNamed(context, AppRouter.credit); }, child: Text(context.t('settings_upgrade'), style: const TextStyle(color: AppColors.tierGold)), ), ], ), ); } Widget _buildMenuGroup(String title, List<_MenuItem> items) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.fromLTRB(20, 20, 20, 8), child: Text(title, style: const TextStyle(fontSize: 13, color: AppColors.textTertiary, fontWeight: FontWeight.w500)), ), Container( color: AppColors.surface, child: Column( children: items.map((item) { return ListTile( leading: Icon(item.icon, color: AppColors.textSecondary, size: 22), title: Text(item.title, style: const TextStyle(fontSize: 15)), trailing: const Icon(Icons.chevron_right_rounded, size: 20, color: AppColors.textTertiary), onTap: item.onTap, ); }).toList(), ), ), ], ); } } class _MenuItem { final String title; final IconData icon; final VoidCallback onTap; const _MenuItem(this.title, this.icon, this.onTap); }