This commit is contained in:
vipg
2025-11-13 17:37:49 +08:00
parent 3cd8527a7d
commit cc33c46ef3
4 changed files with 106 additions and 143 deletions

View File

@@ -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(), // 初始显示登录页
);
}
}

View File

@@ -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<LoginPage> {
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<LoginPage> {
_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) {

View File

@@ -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;
}
}

View File

@@ -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);