diff --git a/frontend/asset_assistant/lib/main.dart b/frontend/asset_assistant/lib/main.dart index 3882381..b339250 100644 --- a/frontend/asset_assistant/lib/main.dart +++ b/frontend/asset_assistant/lib/main.dart @@ -1,101 +1,82 @@ +import 'package:asset_assistant/pages/home_page.dart'; import 'package:asset_assistant/pages/login_page.dart'; import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; -void main() { - runApp(const MyApp()); +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + final prefs = await SharedPreferences.getInstance(); + final userId = prefs.getString('user_id'); + debugPrint('初始化路由,用户ID: $userId'); + runApp(MyApp(initialRoute: userId != null ? '/home' : '/login')); } class MyApp extends StatelessWidget { - const MyApp({super.key}); + final String initialRoute; + const MyApp({super.key, required this.initialRoute}); @override Widget build(BuildContext context) { - // 金融风格暗夜主题 - final darkTheme = ThemeData( - brightness: Brightness.dark, - primaryColor: const Color(0xFF0F3460), // 主色调:深蓝色 - colorScheme: ColorScheme.dark( - primary: const Color(0xFF0F3460), - secondary: const Color(0xFFD4AF37), - surface: const Color(0xFF121212), // 页面主背景 - surfaceContainerHighest: const Color(0xFF1E1E1E), // 卡片背景(分层色) - onPrimary: Colors.white, - onSecondary: Colors.black, - onSurface: Colors.white70, // 所有表面的默认文本色 - ), - // 文本样式(继承 onSurface 颜色,增强可读性) - textTheme: TextTheme( - bodyLarge: TextStyle(color: Colors.white70, fontSize: 16, height: 1.5), - bodyMedium: TextStyle(color: Colors.white60, fontSize: 14, height: 1.5), - headlineLarge: TextStyle( - color: Colors.white, - fontSize: 24, - fontWeight: FontWeight.w600, - ), - headlineMedium: TextStyle( - color: Colors.white, - fontSize: 20, - fontWeight: FontWeight.w600, - ), - ), - // 输入框样式 - inputDecorationTheme: InputDecorationTheme( - border: OutlineInputBorder( - borderSide: const BorderSide(color: Color(0xFF333333)), - borderRadius: BorderRadius.circular(8), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide(color: Color(0xFF333333)), - borderRadius: BorderRadius.circular(8), - ), - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide(color: Color(0xFFD4AF37), width: 2), - borderRadius: BorderRadius.circular(8), - ), - labelStyle: const TextStyle(color: Colors.white60), - prefixIconColor: Colors.white60, - hintStyle: const TextStyle(color: Colors.white38), - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 14, - ), - ), - // 按钮样式 - elevatedButtonTheme: ElevatedButtonThemeData( - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0F3460), - foregroundColor: Colors.white, - padding: const EdgeInsets.symmetric(vertical: 16), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - textStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500), - elevation: 2, - shadowColor: Colors.black54, - ), - ), - // 文本按钮样式(忘记密码) - textButtonTheme: TextButtonThemeData( - style: TextButton.styleFrom( - foregroundColor: const Color(0xFFD4AF37), // 金色文本,符合辅助色 - textStyle: const TextStyle(fontSize: 14), - ), - ), - // 卡片样式 - cardTheme: CardThemeData( - color: const Color(0xFF1E1E1E), - elevation: 4, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - side: const BorderSide(color: Color(0xFF333333)), - ), - ), - // 去除页面默认边距 - scaffoldBackgroundColor: const Color(0xFF121212), - ); - return MaterialApp( title: '资产助手', - theme: darkTheme, - home: const LoginPage(), + debugShowCheckedModeBanner: false, // 移除 debug 标签 + initialRoute: initialRoute, + routes: { + '/login': (context) => const LoginPage(), + '/home': (context) => const HomePage(), + }, + theme: ThemeData( + // 金融暗夜风格主题配置 + brightness: Brightness.dark, + colorScheme: ColorScheme.dark( + primary: const Color(0xFF0070F3), // 主色调:深蓝色 + secondary: const Color(0xFF64FFDA), // 辅助色:亮青色 + // 将 background 替换为 surface + surface: const Color(0xFF0F172A), // 背景色:深灰蓝 + // 使用 surfaceContainerHighest 替代 deprecated 的 surfaceVariant + surfaceContainerHighest: const Color(0xFF1E293B), // 表面色:中灰蓝 + onPrimary: Colors.white, + onSecondary: Colors.black87, + // 将 onBackground 替换为 onSurface + onSurface: Colors.white, + onSurfaceVariant: Colors.white70, + ), + inputDecorationTheme: InputDecorationTheme( + filled: true, + fillColor: const Color(0xFF1E293B), + border: OutlineInputBorder( + borderSide: const BorderSide(color: Color(0xFF334155)), + borderRadius: BorderRadius.circular(8), + ), + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide(color: Color(0xFF0070F3), width: 2), + borderRadius: BorderRadius.circular(8), + ), + hintStyle: const TextStyle(color: Color(0xFF94A3B8)), + labelStyle: const TextStyle(color: Color(0xFFCBD5E1)), + ), + elevatedButtonTheme: ElevatedButtonThemeData( + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFF0070F3), + foregroundColor: Colors.white, + padding: const EdgeInsets.symmetric(vertical: 16), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + textStyle: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), + ), + textButtonTheme: TextButtonThemeData( + style: TextButton.styleFrom( + foregroundColor: const Color(0xFF94A3B8), + textStyle: const TextStyle(fontSize: 16), + ), + ), + ), + home: const LoginPage(), // 初始显示登录页 ); } } diff --git a/frontend/asset_assistant/lib/pages/login_page.dart b/frontend/asset_assistant/lib/pages/login_page.dart index 4171988..27d8890 100644 --- a/frontend/asset_assistant/lib/pages/login_page.dart +++ b/frontend/asset_assistant/lib/pages/login_page.dart @@ -1,8 +1,6 @@ import 'package:asset_assistant/pages/home_page.dart'; -import 'package:asset_assistant/utils/host_manager.dart'; import 'package:flutter/material.dart'; -import 'package:http/http.dart' as http; -import 'dart:convert'; +import 'package:dio/dio.dart'; import 'package:shared_preferences/shared_preferences.dart'; // 登录页面 @@ -39,30 +37,36 @@ class _LoginPageState extends State { try { // 构建请求URL - final url = HostManager().getUriHostByPath("/user/login"); - debugPrint('url is: $url'); + const baseUrl = 'https://api.fishestlife.com'; + const path = '/user/login'; + final url = '$baseUrl$path'; + debugPrint('请求URL: $url'); + + // 初始化Dio实例 + final dio = Dio(); // 发送POST请求 - final response = await http.post( + final response = await dio.post( url, - headers: {'Content-Type': 'application/json'}, - body: json.encode({'account': account, 'password': password}), + data: {'account': account, 'password': password}, + options: Options( + headers: {'Content-Type': 'application/json'}, + responseType: ResponseType.json, + ), ); // 解析响应 if (response.statusCode == 200) { - final result = json.decode(response.body); + final result = response.data; // 打印后端返回的完整数据,确认code和状态 debugPrint('登录响应:$result'); + if (result['success'] == true) { debugPrint('登录成功,准备跳转'); // 保存token和用户信息到本地存储 final prefs = await SharedPreferences.getInstance(); - await prefs.setString( - 'user_id', - result['data']['user_id'], - ); // 保存用户ID。 + await prefs.setString('user_id', result['data']['user_id']); // 保存用户ID debugPrint('保存的用户ID: ${result['data']['user_id']}'); // 延迟后再检查上下文是否仍有效 @@ -80,8 +84,27 @@ class _LoginPageState extends State { _showDialog('错误', '服务器响应异常: ${response.statusCode}'); debugPrint('服务器响应异常: ${response.statusCode}'); } + } on DioException catch (e) { + // 处理Dio异常 + String errorMessage = '网络请求失败'; + if (e.response != null) { + errorMessage = + '请求失败: ${e.response?.statusCode} - ${e.response?.statusMessage}'; + debugPrint('响应数据: ${e.response?.data}'); + } else if (e.type == DioExceptionType.connectionTimeout) { + errorMessage = '连接超时,请检查网络'; + } else if (e.type == DioExceptionType.receiveTimeout) { + errorMessage = '接收数据超时'; + } else if (e.type == DioExceptionType.sendTimeout) { + errorMessage = '发送数据超时'; + } else if (e.type == DioExceptionType.connectionError) { + errorMessage = '网络连接错误,请检查网络设置'; + } + + _showDialog('错误', errorMessage); + debugPrint('详细错误信息: ${e.toString()}'); } catch (e) { - _showDialog('错误', '网络请求失败: $e'); + _showDialog('错误', '发生未知错误: $e'); debugPrint('详细错误信息: ${e.toString()}'); } finally { if (mounted) { diff --git a/frontend/asset_assistant/lib/utils/host_manager.dart b/frontend/asset_assistant/lib/utils/host_manager.dart deleted file mode 100644 index 0e1ef0e..0000000 --- a/frontend/asset_assistant/lib/utils/host_manager.dart +++ /dev/null @@ -1,41 +0,0 @@ -import 'package:flutter/material.dart'; - -class HostManager { - // 单例实例 - static final HostManager _instance = HostManager._internal(); - - // 工厂构造函数,确保保证只有一个实例 - factory HostManager() => _instance; - - // 私有构造函数 - HostManager._internal(); - - // 判断是否为开发环境 - bool get isDebug => const bool.fromEnvironment('dart.vm.product') == false; - - Uri getUriHostByPath(String path) { - final host = HostManager().getHostByPath(path); - final url = Uri.parse(host); - return url; - } - - // 根据传入的path返回对应的host - // 可根据实际需求扩展path与host的映射关系 - String getHostByPath(String path) { - debugPrint('path is:$path'); - String host = ""; - if (!isDebug) { - debugPrint('release model'); - host = "https://api.fishestlife.com"; - } else { - debugPrint('debug model'); - if (path.startsWith('/user')) { - host = "https://api.fishestlife.com"; - } else { - host = ""; - } - } - debugPrint('url is:$host$path'); - return host + path; - } -} diff --git a/frontend/asset_assistant/test/widget_test.dart b/frontend/asset_assistant/test/widget_test.dart index 4bd1263..fcc4edc 100644 --- a/frontend/asset_assistant/test/widget_test.dart +++ b/frontend/asset_assistant/test/widget_test.dart @@ -13,7 +13,7 @@ import 'package:asset_assistant/main.dart'; void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); + await tester.pumpWidget(const MyApp(initialRoute: '')); // Verify that our counter starts at 0. expect(find.text('0'), findsOneWidget);