diff --git a/frontend/mining-app/lib/presentation/pages/asset/asset_page.dart b/frontend/mining-app/lib/presentation/pages/asset/asset_page.dart index 58656d64..7f21a4fc 100644 --- a/frontend/mining-app/lib/presentation/pages/asset/asset_page.dart +++ b/frontend/mining-app/lib/presentation/pages/asset/asset_page.dart @@ -30,11 +30,13 @@ class AssetPage extends ConsumerWidget { return Scaffold( backgroundColor: Colors.white, body: SafeArea( + bottom: false, child: RefreshIndicator( onRefresh: () async { ref.invalidate(shareAccountProvider(accountSequence)); }, child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), child: Column( children: [ // 顶部导航栏 diff --git a/frontend/mining-app/lib/presentation/pages/auth/login_page.dart b/frontend/mining-app/lib/presentation/pages/auth/login_page.dart index 7a19b7e6..3a72aa37 100644 --- a/frontend/mining-app/lib/presentation/pages/auth/login_page.dart +++ b/frontend/mining-app/lib/presentation/pages/auth/login_page.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../../core/router/routes.dart'; -import '../../../core/constants/app_colors.dart'; import '../../providers/user_providers.dart'; class LoginPage extends ConsumerStatefulWidget { @@ -13,6 +12,14 @@ class LoginPage extends ConsumerStatefulWidget { } class _LoginPageState extends ConsumerState { + // 设计色彩 - 与导航页面统一 + static const Color _orange = Color(0xFFFF6B00); + static const Color _darkText = Color(0xFF1F2937); + static const Color _grayText = Color(0xFF6B7280); + static const Color _lightGray = Color(0xFF9CA3AF); + static const Color _bgGray = Color(0xFFF3F4F6); + static const Color _borderGray = Color(0xFFE5E7EB); + final _formKey = GlobalKey(); final _phoneController = TextEditingController(); final _passwordController = TextEditingController(); @@ -113,17 +120,19 @@ class _LoginPageState extends ConsumerState { const SizedBox(height: 60), // Logo - Container( - width: 80, - height: 80, - decoration: BoxDecoration( - color: AppColors.primary.withOpacity(0.1), - borderRadius: BorderRadius.circular(20), - ), - child: const Icon( - Icons.eco, - size: 48, - color: AppColors.primary, + Center( + child: Container( + width: 80, + height: 80, + decoration: BoxDecoration( + color: _orange.withOpacity(0.1), + borderRadius: BorderRadius.circular(20), + ), + child: const Icon( + Icons.eco, + size: 48, + color: _orange, + ), ), ), @@ -134,17 +143,18 @@ class _LoginPageState extends ConsumerState { style: TextStyle( fontSize: 28, fontWeight: FontWeight.bold, + color: _darkText, ), textAlign: TextAlign.center, ), const SizedBox(height: 8), - Text( - '登录您的榴莲挖矿账户', + const Text( + '登录您的榴莲生态账户', style: TextStyle( fontSize: 16, - color: Colors.grey[600], + color: _grayText, ), textAlign: TextAlign.center, ), @@ -152,59 +162,66 @@ class _LoginPageState extends ConsumerState { const SizedBox(height: 48), // 登录方式切换 - Row( - children: [ - Expanded( - child: GestureDetector( - onTap: () => setState(() => _isPasswordLogin = true), - child: Container( - padding: const EdgeInsets.symmetric(vertical: 12), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: _isPasswordLogin ? AppColors.primary : Colors.transparent, - width: 2, + Container( + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide(color: _borderGray, width: 1), + ), + ), + child: Row( + children: [ + Expanded( + child: GestureDetector( + onTap: () => setState(() => _isPasswordLogin = true), + child: Container( + padding: const EdgeInsets.symmetric(vertical: 12), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: _isPasswordLogin ? _orange : Colors.transparent, + width: 2, + ), ), ), - ), - child: Text( - '密码登录', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - fontWeight: _isPasswordLogin ? FontWeight.bold : FontWeight.normal, - color: _isPasswordLogin ? AppColors.primary : Colors.grey, + child: Text( + '密码登录', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontWeight: _isPasswordLogin ? FontWeight.bold : FontWeight.normal, + color: _isPasswordLogin ? _orange : _lightGray, + ), ), ), ), ), - ), - Expanded( - child: GestureDetector( - onTap: () => setState(() => _isPasswordLogin = false), - child: Container( - padding: const EdgeInsets.symmetric(vertical: 12), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: !_isPasswordLogin ? AppColors.primary : Colors.transparent, - width: 2, + Expanded( + child: GestureDetector( + onTap: () => setState(() => _isPasswordLogin = false), + child: Container( + padding: const EdgeInsets.symmetric(vertical: 12), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: !_isPasswordLogin ? _orange : Colors.transparent, + width: 2, + ), ), ), - ), - child: Text( - '验证码登录', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - fontWeight: !_isPasswordLogin ? FontWeight.bold : FontWeight.normal, - color: !_isPasswordLogin ? AppColors.primary : Colors.grey, + child: Text( + '验证码登录', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontWeight: !_isPasswordLogin ? FontWeight.bold : FontWeight.normal, + color: !_isPasswordLogin ? _orange : _lightGray, + ), ), ), ), ), - ), - ], + ], + ), ), const SizedBox(height: 24), @@ -213,12 +230,25 @@ class _LoginPageState extends ConsumerState { TextFormField( controller: _phoneController, keyboardType: TextInputType.phone, + style: const TextStyle(color: _darkText), decoration: InputDecoration( labelText: '手机号', - prefixIcon: const Icon(Icons.phone), + labelStyle: const TextStyle(color: _grayText), + prefixIcon: const Icon(Icons.phone_outlined, color: _grayText), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _borderGray), ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _borderGray), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _orange, width: 2), + ), + filled: true, + fillColor: Colors.white, ), validator: (value) { if (value == null || value.isEmpty) { @@ -238,18 +268,32 @@ class _LoginPageState extends ConsumerState { TextFormField( controller: _passwordController, obscureText: _obscurePassword, + style: const TextStyle(color: _darkText), decoration: InputDecoration( labelText: '密码', - prefixIcon: const Icon(Icons.lock), + labelStyle: const TextStyle(color: _grayText), + prefixIcon: const Icon(Icons.lock_outline, color: _grayText), suffixIcon: IconButton( icon: Icon( - _obscurePassword ? Icons.visibility_off : Icons.visibility, + _obscurePassword ? Icons.visibility_off_outlined : Icons.visibility_outlined, + color: _grayText, ), onPressed: () => setState(() => _obscurePassword = !_obscurePassword), ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _borderGray), ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _borderGray), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _orange, width: 2), + ), + filled: true, + fillColor: Colors.white, ), validator: (value) { if (value == null || value.isEmpty) { @@ -266,13 +310,26 @@ class _LoginPageState extends ConsumerState { controller: _smsCodeController, keyboardType: TextInputType.number, maxLength: 6, + style: const TextStyle(color: _darkText), decoration: InputDecoration( labelText: '验证码', - prefixIcon: const Icon(Icons.sms), + labelStyle: const TextStyle(color: _grayText), + prefixIcon: const Icon(Icons.sms_outlined, color: _grayText), counterText: '', border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _borderGray), ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _borderGray), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _orange, width: 2), + ), + filled: true, + fillColor: Colors.white, ), validator: (value) { if (value == null || value.isEmpty) { @@ -292,13 +349,16 @@ class _LoginPageState extends ConsumerState { child: ElevatedButton( onPressed: _countDown > 0 ? null : _sendSmsCode, style: ElevatedButton.styleFrom( + backgroundColor: _countDown > 0 ? _bgGray : _orange.withOpacity(0.1), + foregroundColor: _countDown > 0 ? _lightGray : _orange, + elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: Text( _countDown > 0 ? '${_countDown}s' : '获取验证码', - style: const TextStyle(fontSize: 14), + style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), ), ), ), @@ -313,7 +373,9 @@ class _LoginPageState extends ConsumerState { child: ElevatedButton( onPressed: userState.isLoading ? null : _login, style: ElevatedButton.styleFrom( - backgroundColor: AppColors.primary, + backgroundColor: _orange, + disabledBackgroundColor: _orange.withOpacity(0.5), + elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), @@ -346,9 +408,9 @@ class _LoginPageState extends ConsumerState { alignment: Alignment.centerRight, child: TextButton( onPressed: () => context.push(Routes.forgotPassword), - child: Text( + child: const Text( '忘记密码?', - style: TextStyle(color: Colors.grey[600]), + style: TextStyle(color: _grayText), ), ), ), @@ -359,13 +421,19 @@ class _LoginPageState extends ConsumerState { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text( + const Text( '还没有账号?', - style: TextStyle(color: Colors.grey[600]), + style: TextStyle(color: _grayText), ), TextButton( onPressed: () => context.push(Routes.register), - child: const Text('立即注册'), + child: const Text( + '立即注册', + style: TextStyle( + color: _orange, + fontWeight: FontWeight.w600, + ), + ), ), ], ), diff --git a/frontend/mining-app/lib/presentation/pages/auth/register_page.dart b/frontend/mining-app/lib/presentation/pages/auth/register_page.dart index c386eef1..038d3f48 100644 --- a/frontend/mining-app/lib/presentation/pages/auth/register_page.dart +++ b/frontend/mining-app/lib/presentation/pages/auth/register_page.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../../core/router/routes.dart'; -import '../../../core/constants/app_colors.dart'; import '../../providers/user_providers.dart'; class RegisterPage extends ConsumerStatefulWidget { @@ -13,6 +12,14 @@ class RegisterPage extends ConsumerStatefulWidget { } class _RegisterPageState extends ConsumerState { + // 设计色彩 - 与导航页面统一 + static const Color _orange = Color(0xFFFF6B00); + static const Color _darkText = Color(0xFF1F2937); + static const Color _grayText = Color(0xFF6B7280); + static const Color _lightGray = Color(0xFF9CA3AF); + static const Color _bgGray = Color(0xFFF3F4F6); + static const Color _borderGray = Color(0xFFE5E7EB); + final _formKey = GlobalKey(); final _phoneController = TextEditingController(); final _passwordController = TextEditingController(); @@ -100,7 +107,7 @@ class _RegisterPageState extends ConsumerState { backgroundColor: Colors.transparent, elevation: 0, leading: IconButton( - icon: const Icon(Icons.arrow_back, color: Colors.black), + icon: const Icon(Icons.arrow_back_ios, color: _darkText), onPressed: () => context.pop(), ), ), @@ -117,16 +124,17 @@ class _RegisterPageState extends ConsumerState { style: TextStyle( fontSize: 28, fontWeight: FontWeight.bold, + color: _darkText, ), ), const SizedBox(height: 8), - Text( - '加入榴莲挖矿,开启绿色财富之旅', + const Text( + '加入榴莲生态,开启绿色财富之旅', style: TextStyle( fontSize: 16, - color: Colors.grey[600], + color: _grayText, ), ), @@ -136,12 +144,25 @@ class _RegisterPageState extends ConsumerState { TextFormField( controller: _phoneController, keyboardType: TextInputType.phone, + style: const TextStyle(color: _darkText), decoration: InputDecoration( labelText: '手机号', - prefixIcon: const Icon(Icons.phone), + labelStyle: const TextStyle(color: _grayText), + prefixIcon: const Icon(Icons.phone_outlined, color: _grayText), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _borderGray), ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _borderGray), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _orange, width: 2), + ), + filled: true, + fillColor: Colors.white, ), validator: (value) { if (value == null || value.isEmpty) { @@ -164,13 +185,26 @@ class _RegisterPageState extends ConsumerState { controller: _smsCodeController, keyboardType: TextInputType.number, maxLength: 6, + style: const TextStyle(color: _darkText), decoration: InputDecoration( labelText: '验证码', - prefixIcon: const Icon(Icons.sms), + labelStyle: const TextStyle(color: _grayText), + prefixIcon: const Icon(Icons.sms_outlined, color: _grayText), counterText: '', border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _borderGray), ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _borderGray), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _orange, width: 2), + ), + filled: true, + fillColor: Colors.white, ), validator: (value) { if (value == null || value.isEmpty) { @@ -190,13 +224,16 @@ class _RegisterPageState extends ConsumerState { child: ElevatedButton( onPressed: _countDown > 0 ? null : _sendSmsCode, style: ElevatedButton.styleFrom( + backgroundColor: _countDown > 0 ? _bgGray : _orange.withOpacity(0.1), + foregroundColor: _countDown > 0 ? _lightGray : _orange, + elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: Text( _countDown > 0 ? '${_countDown}s' : '获取验证码', - style: const TextStyle(fontSize: 14), + style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), ), ), ), @@ -209,18 +246,32 @@ class _RegisterPageState extends ConsumerState { TextFormField( controller: _passwordController, obscureText: _obscurePassword, + style: const TextStyle(color: _darkText), decoration: InputDecoration( labelText: '密码', - prefixIcon: const Icon(Icons.lock), + labelStyle: const TextStyle(color: _grayText), + prefixIcon: const Icon(Icons.lock_outline, color: _grayText), suffixIcon: IconButton( icon: Icon( - _obscurePassword ? Icons.visibility_off : Icons.visibility, + _obscurePassword ? Icons.visibility_off_outlined : Icons.visibility_outlined, + color: _grayText, ), onPressed: () => setState(() => _obscurePassword = !_obscurePassword), ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _borderGray), ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _borderGray), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _orange, width: 2), + ), + filled: true, + fillColor: Colors.white, ), validator: (value) { if (value == null || value.isEmpty) { @@ -239,18 +290,32 @@ class _RegisterPageState extends ConsumerState { TextFormField( controller: _confirmPasswordController, obscureText: _obscureConfirmPassword, + style: const TextStyle(color: _darkText), decoration: InputDecoration( labelText: '确认密码', - prefixIcon: const Icon(Icons.lock_outline), + labelStyle: const TextStyle(color: _grayText), + prefixIcon: const Icon(Icons.lock_outline, color: _grayText), suffixIcon: IconButton( icon: Icon( - _obscureConfirmPassword ? Icons.visibility_off : Icons.visibility, + _obscureConfirmPassword ? Icons.visibility_off_outlined : Icons.visibility_outlined, + color: _grayText, ), onPressed: () => setState(() => _obscureConfirmPassword = !_obscureConfirmPassword), ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _borderGray), ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _borderGray), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: _orange, width: 2), + ), + filled: true, + fillColor: Colors.white, ), validator: (value) { if (value == null || value.isEmpty) { @@ -271,7 +336,9 @@ class _RegisterPageState extends ConsumerState { child: ElevatedButton( onPressed: userState.isLoading ? null : _register, style: ElevatedButton.styleFrom( - backgroundColor: AppColors.primary, + backgroundColor: _orange, + disabledBackgroundColor: _orange.withOpacity(0.5), + elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), @@ -302,13 +369,19 @@ class _RegisterPageState extends ConsumerState { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text( + const Text( '已有账号?', - style: TextStyle(color: Colors.grey[600]), + style: TextStyle(color: _grayText), ), TextButton( onPressed: () => context.pop(), - child: const Text('立即登录'), + child: const Text( + '立即登录', + style: TextStyle( + color: _orange, + fontWeight: FontWeight.w600, + ), + ), ), ], ), diff --git a/frontend/mining-app/lib/presentation/pages/contribution/contribution_page.dart b/frontend/mining-app/lib/presentation/pages/contribution/contribution_page.dart index 9df1d4f9..535214bf 100644 --- a/frontend/mining-app/lib/presentation/pages/contribution/contribution_page.dart +++ b/frontend/mining-app/lib/presentation/pages/contribution/contribution_page.dart @@ -34,6 +34,7 @@ class ContributionPage extends ConsumerWidget { return Scaffold( backgroundColor: const Color(0xFFF5F5F5), body: SafeArea( + bottom: false, child: RefreshIndicator( onRefresh: () async { ref.invalidate(contributionProvider(accountSequence)); @@ -67,7 +68,7 @@ class ContributionPage extends ConsumerWidget { const SizedBox(height: 16), // 贡献值失效倒计时 _buildExpirationCard(contribution, recordsAsync), - const SizedBox(height: 24), + const SizedBox(height: 100), ]), ), ), diff --git a/frontend/mining-app/lib/presentation/pages/profile/profile_page.dart b/frontend/mining-app/lib/presentation/pages/profile/profile_page.dart index 6c58aa6f..f3660a64 100644 --- a/frontend/mining-app/lib/presentation/pages/profile/profile_page.dart +++ b/frontend/mining-app/lib/presentation/pages/profile/profile_page.dart @@ -24,6 +24,7 @@ class ProfilePage extends ConsumerWidget { return Scaffold( backgroundColor: _bgGray, body: SafeArea( + bottom: false, child: SingleChildScrollView( child: Column( children: [ @@ -76,7 +77,7 @@ class ProfilePage extends ConsumerWidget { ), ), - const SizedBox(height: 32), + const SizedBox(height: 100), ], ), ), diff --git a/frontend/mining-app/lib/presentation/pages/trading/trading_page.dart b/frontend/mining-app/lib/presentation/pages/trading/trading_page.dart index 8ef1ad2d..f138d068 100644 --- a/frontend/mining-app/lib/presentation/pages/trading/trading_page.dart +++ b/frontend/mining-app/lib/presentation/pages/trading/trading_page.dart @@ -46,6 +46,7 @@ class _TradingPageState extends ConsumerState { return Scaffold( backgroundColor: const Color(0xFFF5F5F5), body: SafeArea( + bottom: false, child: Column( children: [ // 顶部导航栏 @@ -73,7 +74,7 @@ class _TradingPageState extends ConsumerState { _buildTradingPanel(accountSequence), // 我的挂单 _buildMyOrdersCard(), - const SizedBox(height: 24), + const SizedBox(height: 100), ], ), ),