This commit is contained in:
vipg
2025-11-13 17:19:29 +08:00
parent 5e4d7509fd
commit b177f0647d
2 changed files with 254 additions and 108 deletions

View File

@@ -13,6 +13,7 @@ class _LoginPageState extends State<LoginPage> {
final _usernameController = TextEditingController();
final _passwordController = TextEditingController();
bool _isLoading = false;
bool _obscurePassword = true;
final _dio = Dio();
Future<void> _submitForm() async {
@@ -32,11 +33,13 @@ class _LoginPageState extends State<LoginPage> {
// 登录成功处理
if (response.statusCode == 200) {
// 这里根据实际返回的数据结构处理
if (mounted) {
ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text('登录成功')));
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('登录成功'),
backgroundColor: Color(0xFF2E7D32), // 成功绿色
),
);
// 导航到主页或其他页面
// Navigator.pushReplacement(...);
}
@@ -44,9 +47,12 @@ class _LoginPageState extends State<LoginPage> {
} catch (e) {
// 错误处理
if (mounted) {
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('登录失败: ${e.toString()}')));
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('登录失败: ${e.toString()}'),
backgroundColor: Color(0xFFC62828), // 错误红色
),
);
}
} finally {
if (mounted) {
@@ -61,57 +67,165 @@ class _LoginPageState extends State<LoginPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('登录')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
controller: _usernameController,
decoration: const InputDecoration(
labelText: '用户名',
prefixIcon: Icon(Icons.person),
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return '请输入用户名';
}
return null;
},
enabled: !_isLoading,
),
const SizedBox(height: 16),
TextFormField(
controller: _passwordController,
decoration: const InputDecoration(
labelText: '密码',
prefixIcon: Icon(Icons.lock),
border: OutlineInputBorder(),
),
obscureText: true,
validator: (value) {
if (value == null || value.isEmpty) {
return '请输入密码';
}
return null;
},
enabled: !_isLoading,
),
const SizedBox(height: 24),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: _isLoading ? null : _submitForm,
child: _isLoading
? const CircularProgressIndicator()
: const Text('登录'),
// 增加顶部阴影效果
appBar: AppBar(
title: const Text('账户登录'),
backgroundColor: Theme.of(context).colorScheme.primary,
elevation: 4,
shadowColor: Colors.black54,
),
// 主体内容使用卡片包裹增加层次感
body: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0xFF121212), Color(0xFF1A1A2E)],
),
),
child: Center(
child: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Card(
margin: const EdgeInsets.symmetric(horizontal: 16),
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// 金融风格Logo位置可替换为实际Logo
const Icon(
Icons.account_balance,
size: 64,
color: Color(0xFFD4AF37),
),
const SizedBox(height: 24),
const Text(
'资产助手',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Color(0xFFD4AF37),
),
),
const SizedBox(height: 32),
TextFormField(
controller: _usernameController,
decoration: InputDecoration(
labelText: '用户名',
prefixIcon: const Icon(Icons.person),
border: const OutlineInputBorder(),
// 增加焦点效果
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: Color(0xFFD4AF37),
width: 2,
),
borderRadius: BorderRadius.circular(8),
),
),
validator: (value) {
if (value == null || value.isEmpty) {
return '请输入用户名';
}
return null;
},
enabled: !_isLoading,
),
const SizedBox(height: 16),
TextFormField(
controller: _passwordController,
decoration: InputDecoration(
labelText: '密码',
prefixIcon: const Icon(Icons.lock),
border: const OutlineInputBorder(),
suffixIcon: IconButton(
icon: Icon(
_obscurePassword
? Icons.visibility_off
: Icons.visibility,
color: Colors.white60,
),
onPressed: () {
setState(() {
_obscurePassword = !_obscurePassword;
});
},
),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: Color(0xFFD4AF37),
width: 2,
),
borderRadius: BorderRadius.circular(8),
),
),
obscureText: _obscurePassword,
validator: (value) {
if (value == null || value.isEmpty) {
return '请输入密码';
}
return null;
},
enabled: !_isLoading,
),
const SizedBox(height: 8),
// 忘记密码链接
Align(
alignment: Alignment.centerRight,
child: TextButton(
onPressed: _isLoading
? null
: () {
// 忘记密码逻辑
},
child: const Text(
'忘记密码?',
style: TextStyle(
color: Color(0xFFD4AF37),
fontSize: 14,
),
),
),
),
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: _isLoading ? null : _submitForm,
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF0F3460),
padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: _isLoading
? const CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
Colors.white,
),
)
: const Text(
'安全登录',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
),
),
],
),
),
),
],
),
),
),
),

View File

@@ -10,60 +10,92 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
// 金融风格暗夜主题
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, // 所有表面的默认文本色
),
// 将home改为LoginPage
// 文本样式(继承 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(),
);
}
}
// 以下MyHomePage代码可以保留或删除根据实际需求决定
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('You have pushed the button this many times:'),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}