111
This commit is contained in:
@@ -49,13 +49,13 @@ class _LoginPageState extends State<LoginPage> {
|
||||
key: formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
// 顶部品牌区域
|
||||
// 頂部品牌區域
|
||||
_buildBrandSection(),
|
||||
const SizedBox(height: AppSpacing.xxl),
|
||||
// 表单区域
|
||||
// 表單區域
|
||||
_buildFormSection(),
|
||||
const SizedBox(height: AppSpacing.xl),
|
||||
// 底部注册链接
|
||||
// 底部註冊鏈接
|
||||
_buildRegisterRow(),
|
||||
],
|
||||
),
|
||||
@@ -66,13 +66,13 @@ class _LoginPageState extends State<LoginPage> {
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 品牌区域 - Logo + 品牌名 + 标语
|
||||
// 品牌區域 - Logo + 品牌名 + 標語
|
||||
// ============================================
|
||||
|
||||
Widget _buildBrandSection() {
|
||||
return Column(
|
||||
children: [
|
||||
// Logo 圆形:渐变 #1F2937 → #374151,内含 "M"
|
||||
// Logo 圓形:漸變 #1F2937 → #374151,內含 "M"
|
||||
Container(
|
||||
width: _logoCircleSize,
|
||||
height: _logoCircleSize,
|
||||
@@ -105,9 +105,9 @@ class _LoginPageState extends State<LoginPage> {
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: AppSpacing.md),
|
||||
// 标语
|
||||
// 標語
|
||||
Text(
|
||||
'虚拟货币模拟交易平台',
|
||||
'虛擬貨幣模擬交易平臺',
|
||||
style: AppTextStyles.bodyLarge(context).copyWith(
|
||||
color: context.colors.onSurfaceVariant,
|
||||
),
|
||||
@@ -118,7 +118,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 表单区域 - 用户名 + 密码 + 登录按钮
|
||||
// 表單區域 - 用戶名 + 密碼 + 登錄按鈕
|
||||
// ============================================
|
||||
|
||||
Widget _buildFormSection() {
|
||||
@@ -139,7 +139,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
height: _inputHeight,
|
||||
child: ShadInputFormField(
|
||||
id: 'username',
|
||||
placeholder: const Text('请输入用户名'),
|
||||
placeholder: const Text('請輸入用戶名'),
|
||||
leading: Padding(
|
||||
padding: const EdgeInsets.only(right: AppSpacing.sm),
|
||||
child: Icon(LucideIcons.user, size: 18, color: context.appColors.onSurfaceMuted),
|
||||
@@ -166,7 +166,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
height: _inputHeight,
|
||||
child: ShadInputFormField(
|
||||
id: 'password',
|
||||
placeholder: const Text('请输入密码'),
|
||||
placeholder: const Text('請輸入密碼'),
|
||||
obscureText: _obscurePassword,
|
||||
leading: Padding(
|
||||
padding: const EdgeInsets.only(right: AppSpacing.sm),
|
||||
@@ -196,7 +196,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
}
|
||||
|
||||
Widget _buildLoginButton() {
|
||||
// 设计稿: accent-primary = light:#1F2937 / dark:#D4AF37
|
||||
// 設計稿: accent-primary = light:#1F2937 / dark:#D4AF37
|
||||
final buttonColor = context.appColors.accentPrimary;
|
||||
final textColor = context.colors.onPrimary;
|
||||
|
||||
@@ -222,7 +222,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
'登录',
|
||||
'登錄',
|
||||
style: AppTextStyles.headlineLarge(context).copyWith(
|
||||
fontWeight: FontWeight.w700,
|
||||
color: textColor,
|
||||
@@ -235,7 +235,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 底部注册链接
|
||||
// 底部註冊鏈接
|
||||
// ============================================
|
||||
|
||||
Widget _buildRegisterRow() {
|
||||
@@ -249,7 +249,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'还没有账户?',
|
||||
'還沒有賬戶?',
|
||||
style: AppTextStyles.bodyLarge(context).copyWith(
|
||||
color: secondaryTextColor,
|
||||
),
|
||||
@@ -258,7 +258,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
GestureDetector(
|
||||
onTap: _navigateToRegister,
|
||||
child: Text(
|
||||
'立即注册',
|
||||
'立即註冊',
|
||||
style: AppTextStyles.bodyLarge(context).copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: goldColor,
|
||||
@@ -276,20 +276,20 @@ class _LoginPageState extends State<LoginPage> {
|
||||
|
||||
String? _validateUsername(String? value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return '请输入用户名';
|
||||
return '請輸入用戶名';
|
||||
}
|
||||
if (value.length < 3) {
|
||||
return '用户名至少 3 个字符';
|
||||
return '用戶名至少 3 個字符';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String? _validatePassword(String? value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return '请输入密码';
|
||||
return '請輸入密碼';
|
||||
}
|
||||
if (value.length < 6) {
|
||||
return '密码至少 6 个字符';
|
||||
return '密碼至少 6 個字符';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -312,7 +312,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
if (response.success) {
|
||||
_navigateToMainPage();
|
||||
} else {
|
||||
_showErrorDialog(response.message ?? '用户名或密码错误');
|
||||
_showErrorDialog(response.message ?? '用戶名或密碼錯誤');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,11 +334,11 @@ class _LoginPageState extends State<LoginPage> {
|
||||
showShadDialog(
|
||||
context: context,
|
||||
builder: (context) => ShadDialog.alert(
|
||||
title: const Text('登录失败'),
|
||||
title: const Text('登錄失敗'),
|
||||
description: Text(message),
|
||||
actions: [
|
||||
ShadButton(
|
||||
child: const Text('确定'),
|
||||
child: const Text('確定'),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -11,7 +11,7 @@ import '../../components/glass_panel.dart';
|
||||
import '../../components/neon_glow.dart';
|
||||
import '../main/main_page.dart';
|
||||
|
||||
/// 注册页面(两步注册:账号信息 + 身份证上传)
|
||||
/// 註冊頁面(兩步註冊:賬號信息 + 身份證上傳)
|
||||
class RegisterPage extends StatefulWidget {
|
||||
const RegisterPage({super.key});
|
||||
|
||||
@@ -20,7 +20,7 @@ class RegisterPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _RegisterPageState extends State<RegisterPage> {
|
||||
int _currentStep = 0; // 0: 账号信息, 1: 身份证上传
|
||||
int _currentStep = 0; // 0: 賬號信息, 1: 身份證上傳
|
||||
|
||||
// 第一步
|
||||
final _usernameController = TextEditingController();
|
||||
@@ -96,11 +96,11 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
// 步骤指示器
|
||||
// 步驟指示器
|
||||
_buildStepIndicator(colorScheme),
|
||||
SizedBox(height: AppSpacing.xl),
|
||||
|
||||
// 内容区
|
||||
// 內容區
|
||||
_currentStep == 0 ? _buildStep1(colorScheme) : _buildStep2(colorScheme),
|
||||
],
|
||||
),
|
||||
@@ -114,7 +114,7 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
children: [
|
||||
_buildStepCircle(
|
||||
number: '1',
|
||||
label: '账号信息',
|
||||
label: '賬號信息',
|
||||
isActive: true,
|
||||
isComplete: _currentStep > 0,
|
||||
colorScheme: colorScheme,
|
||||
@@ -129,7 +129,7 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
),
|
||||
_buildStepCircle(
|
||||
number: '2',
|
||||
label: '身份验证',
|
||||
label: '身份驗證',
|
||||
isActive: _currentStep >= 1,
|
||||
isComplete: false,
|
||||
colorScheme: colorScheme,
|
||||
@@ -191,17 +191,17 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
);
|
||||
}
|
||||
|
||||
/// 第一步:账号信息
|
||||
/// 第一步:賬號信息
|
||||
Widget _buildStep1(ColorScheme colorScheme) {
|
||||
return Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
// 标题
|
||||
// 標題
|
||||
Center(
|
||||
child: Text(
|
||||
'创建账号',
|
||||
'創建賬號',
|
||||
style: AppTextStyles.displaySmall(context).copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: colorScheme.onSurface,
|
||||
@@ -210,30 +210,30 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
),
|
||||
SizedBox(height: AppSpacing.xxl),
|
||||
|
||||
// 用户名
|
||||
// 用戶名
|
||||
TextFormField(
|
||||
controller: _usernameController,
|
||||
style: TextStyle(color: colorScheme.onSurface),
|
||||
decoration: InputDecoration(
|
||||
hintText: '请输入账号(4-20位字母数字)',
|
||||
hintText: '請輸入賬號(4-20位字母數字)',
|
||||
prefixIcon: Icon(Icons.person_outline, color: colorScheme.onSurfaceVariant),
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) return '请输入账号';
|
||||
if (value.length < 4) return '账号至少4位';
|
||||
if (value.length > 20) return '账号最多20位';
|
||||
if (value == null || value.isEmpty) return '請輸入賬號';
|
||||
if (value.length < 4) return '賬號至少4位';
|
||||
if (value.length > 20) return '賬號最多20位';
|
||||
return null;
|
||||
},
|
||||
),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
|
||||
// 密码
|
||||
// 密碼
|
||||
TextFormField(
|
||||
controller: _passwordController,
|
||||
obscureText: _obscurePassword,
|
||||
style: TextStyle(color: colorScheme.onSurface),
|
||||
decoration: InputDecoration(
|
||||
hintText: '请输入密码(至少6位)',
|
||||
hintText: '請輸入密碼(至少6位)',
|
||||
prefixIcon: Icon(Icons.lock_outline, color: colorScheme.onSurfaceVariant),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(
|
||||
@@ -244,20 +244,20 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
),
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) return '请输入密码';
|
||||
if (value.length < 6) return '密码至少6位';
|
||||
if (value == null || value.isEmpty) return '請輸入密碼';
|
||||
if (value.length < 6) return '密碼至少6位';
|
||||
return null;
|
||||
},
|
||||
),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
|
||||
// 确认密码
|
||||
// 確認密碼
|
||||
TextFormField(
|
||||
controller: _confirmPasswordController,
|
||||
obscureText: _obscureConfirmPassword,
|
||||
style: TextStyle(color: colorScheme.onSurface),
|
||||
decoration: InputDecoration(
|
||||
hintText: '请再次输入密码',
|
||||
hintText: '請再次輸入密碼',
|
||||
prefixIcon: Icon(Icons.lock_outline, color: colorScheme.onSurfaceVariant),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(
|
||||
@@ -268,25 +268,25 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
),
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) return '请再次输入密码';
|
||||
if (value != _passwordController.text) return '两次密码不一致';
|
||||
if (value == null || value.isEmpty) return '請再次輸入密碼';
|
||||
if (value != _passwordController.text) return '兩次密碼不一致';
|
||||
return null;
|
||||
},
|
||||
),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
|
||||
// 推广码(可选)
|
||||
// 推廣碼(可選)
|
||||
TextFormField(
|
||||
controller: _referralCodeController,
|
||||
style: TextStyle(color: colorScheme.onSurface),
|
||||
decoration: InputDecoration(
|
||||
hintText: '推广码(选填)',
|
||||
hintText: '推廣碼(選填)',
|
||||
prefixIcon: Icon(Icons.card_giftcard, color: colorScheme.onSurfaceVariant),
|
||||
),
|
||||
),
|
||||
SizedBox(height: AppSpacing.xl),
|
||||
|
||||
// 下一步按钮
|
||||
// 下一步按鈕
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: NeonButton(
|
||||
@@ -303,11 +303,11 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
|
||||
// 登录链接
|
||||
// 登錄鏈接
|
||||
Center(
|
||||
child: TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text('已有账号?立即登录', style: AppTextStyles.headlineMedium(context)),
|
||||
child: Text('已有賬號?立即登錄', style: AppTextStyles.headlineMedium(context)),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -315,12 +315,12 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
);
|
||||
}
|
||||
|
||||
/// 第二步:身份证上传
|
||||
/// 第二步:身份證上傳
|
||||
Widget _buildStep2(ColorScheme colorScheme) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
// 标题区
|
||||
// 標題區
|
||||
GlassPanel(
|
||||
padding: EdgeInsets.all(AppSpacing.lg),
|
||||
child: Column(
|
||||
@@ -345,7 +345,7 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'身份验证',
|
||||
'身份驗證',
|
||||
style: AppTextStyles.headlineLarge(context).copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: colorScheme.onSurface,
|
||||
@@ -353,7 +353,7 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
),
|
||||
SizedBox(height: AppSpacing.xs),
|
||||
Text(
|
||||
'上传身份证正反面完成注册',
|
||||
'上傳身份證正反面完成註冊',
|
||||
style: AppTextStyles.bodyMedium(context).copyWith(
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
@@ -364,9 +364,9 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
),
|
||||
SizedBox(height: AppSpacing.xl),
|
||||
|
||||
// 身份证正面
|
||||
// 身份證正面
|
||||
Text(
|
||||
'身份证正面(人像面)',
|
||||
'身份證正面(人像面)',
|
||||
style: AppTextStyles.bodyLarge(context).copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: colorScheme.onSurface,
|
||||
@@ -382,9 +382,9 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
),
|
||||
SizedBox(height: AppSpacing.lg),
|
||||
|
||||
// 身份证反面
|
||||
// 身份證反面
|
||||
Text(
|
||||
'身份证反面(国徽面)',
|
||||
'身份證反面(國徽面)',
|
||||
style: AppTextStyles.bodyLarge(context).copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: colorScheme.onSurface,
|
||||
@@ -394,19 +394,19 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
_buildUploadZone(
|
||||
imageFile: _backFile,
|
||||
imageBytes: _backBytes,
|
||||
label: '国徽面',
|
||||
label: '國徽面',
|
||||
onTap: () => _pickImage(false),
|
||||
colorScheme: colorScheme,
|
||||
),
|
||||
SizedBox(height: AppSpacing.xl),
|
||||
|
||||
// 注册按钮
|
||||
// 註冊按鈕
|
||||
Consumer<AuthProvider>(
|
||||
builder: (context, auth, _) {
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
child: NeonButton(
|
||||
text: _isLoading ? '注册中...' : '完成注册',
|
||||
text: _isLoading ? '註冊中...' : '完成註冊',
|
||||
type: NeonButtonType.primary,
|
||||
onPressed: _canSubmit && !auth.isLoading ? _handleRegister : null,
|
||||
height: 48,
|
||||
@@ -434,7 +434,7 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
SizedBox(width: AppSpacing.sm),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'您的身份信息将被加密存储,仅用于身份验证',
|
||||
'您的身份信息將被加密存儲,僅用於身份驗證',
|
||||
style: AppTextStyles.bodySmall(context).copyWith(
|
||||
color: AppColorScheme.up.withValues(alpha: 0.8),
|
||||
),
|
||||
@@ -502,7 +502,7 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'$label已选择',
|
||||
'$label已選擇',
|
||||
style: AppTextStyles.bodyMedium(context).copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColorScheme.darkOnPrimary,
|
||||
@@ -551,7 +551,7 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
Text(
|
||||
'点击上传$label',
|
||||
'點擊上傳$label',
|
||||
style: AppTextStyles.bodyLarge(context).copyWith(
|
||||
color: colorScheme.onSurfaceVariant.withValues(alpha: 0.6),
|
||||
),
|
||||
@@ -597,11 +597,11 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
showShadDialog(
|
||||
context: context,
|
||||
builder: (ctx) => ShadDialog.alert(
|
||||
title: const Text('注册失败'),
|
||||
description: Text(response.message ?? '请稍后重试'),
|
||||
title: const Text('註冊失敗'),
|
||||
description: Text(response.message ?? '請稍後重試'),
|
||||
actions: [
|
||||
ShadButton(
|
||||
child: const Text('确定'),
|
||||
child: const Text('確定'),
|
||||
onPressed: () => Navigator.of(ctx).pop(),
|
||||
),
|
||||
],
|
||||
@@ -613,11 +613,11 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
showShadDialog(
|
||||
context: context,
|
||||
builder: (ctx) => ShadDialog.alert(
|
||||
title: const Text('注册失败'),
|
||||
title: const Text('註冊失敗'),
|
||||
description: Text(e.toString()),
|
||||
actions: [
|
||||
ShadButton(
|
||||
child: const Text('确定'),
|
||||
child: const Text('確定'),
|
||||
onPressed: () => Navigator.of(ctx).pop(),
|
||||
),
|
||||
],
|
||||
@@ -630,7 +630,7 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 虚线边框画笔
|
||||
/// 虛線邊框畫筆
|
||||
class _DashedBorderPainter extends CustomPainter {
|
||||
final Color color;
|
||||
final double borderRadius;
|
||||
|
||||
Reference in New Issue
Block a user