add
This commit is contained in:
@@ -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(), // 初始显示登录页
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user