flutter_integrated_whb/lib/pages/login_page.dart

287 lines
9.7 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// ignore_for_file: use_build_context_synchronously
import 'package:flutter/material.dart';
import 'main_tab.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '登录页面',
theme: ThemeData(
primarySwatch: Colors.blue,
inputDecorationTheme: const InputDecorationTheme(
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(horizontal: 8),
),
),
home: const LoginPage(),
debugShowCheckedModeBanner: false,
);
}
}
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
@override
// ignore: library_private_types_in_public_api
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final TextEditingController _phoneController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
String _errorMessage = '';
bool _isLoading = false;
bool _obscurePassword = true;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Column(
children: [
_buildHeader(),
Transform.translate(
offset: const Offset(0, -20),
child: Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
),
child: Padding(
padding: const EdgeInsets.only(top: 30),
child: Column(
children: [
// 手机号
_buildInputSection(
label: "手机号码",
controller: _phoneController,
hintText: "请输入手机号...",
keyboardType: TextInputType.phone,
validator: (value) {
if (value == null || value.isEmpty) {
return '请输入手机号';
}
if (!RegExp(r'^1[3-9]\d{9}$').hasMatch(value)) {
return '请输入有效的手机号';
}
return null;
},
),
Padding(padding: const EdgeInsets.symmetric(horizontal: 25),
child: const Divider(height: 1, thickness: 1),
),
// 密码
_buildInputSection(
label: "密码",
controller: _passwordController,
hintText: "请输入密码...",
obscureText: _obscurePassword,
suffixIcon: IconButton(
icon: Icon(
_obscurePassword
? Icons.visibility
: Icons.visibility_off,
color: Colors.grey,
),
onPressed: () {
setState(() {
_obscurePassword = !_obscurePassword;
});
},
),
validator: (value) {
if (value == null || value.isEmpty) {
return '请输入密码';
}
if (value.length < 6) {
return '密码长度至少6位';
}
return null;
},
),
Padding(padding: const EdgeInsets.symmetric(horizontal: 25),
child: const Divider(height: 1, thickness: 1),
),
// 登录按钮
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 25, vertical: 24),
child: SizedBox(
width: double.infinity,
height: 48,
child: ElevatedButton(
onPressed: _isLoading ? null : _handleLogin,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: _isLoading
? const CircularProgressIndicator(
color: Colors.white,
)
: const Text(
'登录',
style: TextStyle(
fontSize: 18,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
),
Padding(padding: const EdgeInsets.only(left: 30, right: 30),
child:Text(" 本平台为互联网非涉密平台,严禁处理、传输国家秘密和工作秘密",
style: TextStyle(color: Colors.red))
)
],
),
),
),
),
],
),
),
);
}
// 顶部图片和文字
Widget _buildHeader() {
return Stack(
alignment: Alignment.center,
children: [
Image.asset(
'assets/images/login-bg.png',
width: double.infinity,
fit: BoxFit.fitWidth,
),
Positioned(
bottom: 40,
left: 30,
child: Column(
children: [
const Text(
'欢迎登录',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Colors.white,
shadows: [
Shadow(
blurRadius: 10,
color: Colors.black45,
offset: Offset(2, 2),
),
],
),
),
const SizedBox(height: 8),
Text(
'秦皇岛市应急管局\n数智应急管理平台',
style: TextStyle(fontSize: 18, color: Colors.white),
),
],
),
),
],
);
}
// 输入区域组件
Widget _buildInputSection({
required String label,
required TextEditingController controller,
required String hintText,
bool obscureText = false,
TextInputType keyboardType = TextInputType.text,
Widget? suffixIcon,
String? Function(String?)? validator,
}) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
color: Colors.black87,
),
),
const SizedBox(height: 15),
TextFormField(
controller: controller,
obscureText: obscureText,
keyboardType: keyboardType,
validator: validator,
// 关键属性:让文字在行内垂直居中
textAlignVertical: TextAlignVertical.center,
decoration: InputDecoration(
hintText: hintText,
suffixIcon: suffixIcon,
// 去掉默认的上下/左右 padding让文字贴紧外层的 25 左边距
isDense: true,
contentPadding: EdgeInsets.zero,
),
),
],
),
);
}
// 登录处理
void _handleLogin() {
// 清除之前的错误信息
setState(() => _errorMessage = '');
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => const MainPage()),
);
// if (_formKey.currentState?.validate() ?? false) {
// setState(() => _isLoading = true);
//
// // 模拟登录请求
// Future.delayed(const Duration(seconds: 2), () {
// setState(() => _isLoading = false);
// // 登录成功,跳转到主页
// // Navigator.pushReplacement(
// // context,
// // MaterialPageRoute(builder: (context) => const MainPage()),
// // );
// // 模拟登录逻辑
// if (_phoneController.text == "13800138000" &&
// _passwordController.text == "123456") {
// // 登录成功,跳转到主页
// Navigator.pushReplacement(
// context,
// MaterialPageRoute(builder: (context) => const MainPage()),
// );
// } else {
// // 登录失败,显示错误信息
// setState(() {
// _errorMessage = '手机号或密码错误,请重试';
// });
// }
// });
// }
}
}