diff --git a/assets/images/bg copy.jpg b/assets/images/bg copy.jpg new file mode 100644 index 0000000..58b49fb Binary files /dev/null and b/assets/images/bg copy.jpg differ diff --git a/assets/images/bg.jpg b/assets/images/bg.jpg new file mode 100644 index 0000000..e7cde1e Binary files /dev/null and b/assets/images/bg.jpg differ diff --git a/assets/images/company_logo.png b/assets/images/company_logo.png new file mode 100644 index 0000000..dd546b1 Binary files /dev/null and b/assets/images/company_logo.png differ diff --git a/assets/images/company_logo1.png b/assets/images/company_logo1.png new file mode 100644 index 0000000..893733d Binary files /dev/null and b/assets/images/company_logo1.png differ diff --git a/lib/app_theme.dart b/lib/app_theme.dart index 5db6784..697b0be 100644 --- a/lib/app_theme.dart +++ b/lib/app_theme.dart @@ -1,40 +1,38 @@ import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:sk_base_mobile/util/screen_adaper_util.dart'; class AppTheme { AppTheme._(); - static const Color primaryColor = Color(0xFFB0F320); - static const Color primaryColorDark = Color(0xFFABEE1C); - static const Color nearlyWhite = Color(0xFFFEFEFE); + static const Color primaryColor = Color(0xFFC89607); + static Color primaryColorLight = primaryColor.withOpacity(0.7); + static Color primaryColorDark = Color.fromRGBO( + primaryColor.red, + primaryColor.green, + primaryColor.blue, + 1 - primaryColor.computeLuminance(), + ); static const Color white = Color(0xFFFFFFFF); + static const Color nearlyWhite = Color(0xFFFEFEFE); + static const Color black = Color(0xFF000000); static const Color nearlyBlack = Color(0xFF213333); static const Color grey = Color(0xFF3A5160); - static const Color dark_grey = Color(0xFF313A44); static const Color snackbarErrorBackgroudColor = Colors.red; static const Color snackbarSuccessBackgroudColor = Colors.green; static const Color snackbarWarningBackgroudColor = Colors.orange; - static const Color roleIconBackgroudColor = Color(0xff002f5f); - static const Color fixturePublishStatusColor = Color(0xFF5B8C00); - static const Color fixtureNotPublishStatusColor = Color(0xFFD7616E); - static const Color darkText = Color(0xFF253840); - static const Color darkerText = Color(0xFF17262A); - static const Color lightText = Color(0xFF4A6572); static const Color dismissibleBackground = Color(0xFF364A54); static const String fontName = 'NotoSans'; } final theme = ThemeData( fontFamily: AppTheme.fontName, - // primarySwatch:MaterialColor() AppTheme.primaryColor, visualDensity: VisualDensity.adaptivePlatformDensity, primaryColor: AppTheme.primaryColor, primaryColorDark: AppTheme.primaryColorDark, progressIndicatorTheme: - ProgressIndicatorThemeData(color: AppTheme.primaryColor), - dividerColor: Color(0xFFDBDBDA), - cardColor: Colors.white, - scaffoldBackgroundColor: Color(0xFFF8F8F8), + const ProgressIndicatorThemeData(color: AppTheme.primaryColor), + dividerColor: AppTheme.grey, + cardColor: AppTheme.white, + scaffoldBackgroundColor: AppTheme.nearlyWhite, tabBarTheme: TabBarTheme( indicator: BoxDecoration( border: @@ -42,11 +40,27 @@ final theme = ThemeData( )), appBarTheme: AppBarTheme( centerTitle: true, - iconTheme: IconThemeData(color: Colors.black), + iconTheme: const IconThemeData(color: Colors.black), backgroundColor: AppTheme.primaryColor, titleTextStyle: TextStyle( color: Colors.black, fontSize: ScreenAdaper.sp(20), fontWeight: FontWeight.bold), ), + inputDecorationTheme: InputDecorationTheme( + floatingLabelStyle: TextStyle( + color: AppTheme.primaryColor, + fontSize: ScreenAdaper.sp(30), + ), + labelStyle: TextStyle( + fontSize: ScreenAdaper.sp(25), + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(ScreenAdaper.sp(15))), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(ScreenAdaper.sp(15)), + borderSide: BorderSide( + color: AppTheme.primaryColorLight, width: 2), // 选中时的边框颜色和宽度 + ), + ), ); diff --git a/lib/global.dart b/lib/global.dart index 7af266c..21b0f5a 100644 --- a/lib/global.dart +++ b/lib/global.dart @@ -14,7 +14,10 @@ class Global { WidgetsFlutterBinding.ensureInitialized(); /// 设置初始化竖屏 - await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); + // await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); + + /// 设置跟随系统屏幕旋转 + await SystemChrome.setPreferredOrientations(DeviceOrientation.values); /// 设置系统UI 因用户反馈可能存在bug先隐藏功能 setSystemUi(); diff --git a/lib/index.dart b/lib/index.dart index d48df4d..a677565 100644 --- a/lib/index.dart +++ b/lib/index.dart @@ -16,9 +16,13 @@ class IndexPage extends StatelessWidget { const IndexPage({super.key}); @override Widget build(BuildContext context) { + final isLandscape = + MediaQuery.of(context).orientation == Orientation.landscape; return ScreenUtilInit( minTextAdapt: true, - designSize: const Size(932, 1490), // 2800 * 1800p 309ppi + designSize: isLandscape + ? const Size(1490, 932) + : const Size(932, 1490), // 2800 * 1800p 309ppi builder: (buildContext, child) => RefreshConfiguration( headerBuilder: () => RefreshHeader(), footerBuilder: () => const RefreshFooter(), @@ -33,20 +37,13 @@ class IndexPage extends StatelessWidget { initialRoute: getInitialRoute(), // initialRoute: RouteConfig.onboarding, debugShowCheckedModeBanner: false, - builder: (_, widget) => Obx(() => MediaQuery( - //设置文字大小不随系统设置改变 - data: MediaQuery.of(context).copyWith( - textScaleFactor: AppInfoService.to.scale.value), - child: GestureDetector( - onTap: () { - FocusScopeNode currentFocus = FocusScope.of(context); - if (!currentFocus.hasPrimaryFocus && - currentFocus.focusedChild != null) { - FocusManager.instance.primaryFocus?.unfocus(); - } - }, - child: widget!, - )))))); + builder: (_, widget) { + return Obx(() => MediaQuery( + //设置文字大小不随系统设置改变 + data: MediaQuery.of(context).copyWith( + textScaleFactor: AppInfoService.to.scale.value), + child: widget!)); + }))); } String getInitialRoute() { diff --git a/lib/main.dart b/lib/main.dart index 4c29cdd..4ce092f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:sk_base_mobile/global.dart'; import 'package:sk_base_mobile/index.dart'; import 'package:sk_base_mobile/util/logger_util.dart'; @@ -9,6 +10,5 @@ Future main() async { } catch (e) { LoggerUtil().error('Init failed, please try again.${e}'); } - runApp(const IndexPage()); } diff --git a/lib/screens/login/login copy.dart b/lib/screens/login/login copy.dart new file mode 100644 index 0000000..563cc01 --- /dev/null +++ b/lib/screens/login/login copy.dart @@ -0,0 +1,194 @@ +import 'package:date_format/date_format.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:sk_base_mobile/app_theme.dart'; +import 'package:sk_base_mobile/screens/login/login.controller.dart'; +import 'package:sk_base_mobile/util/screen_adaper_util.dart'; + +class LoginScreen extends StatelessWidget { + LoginScreen({super.key}); + final _controller = Get.put(LoginController()); + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/bg.jpg'), + fit: BoxFit.cover, + ), + ), + child: buildBody())); + + // return Scaffold( + + // body: SafeArea(child: buildBody())); + } + + buildBody() { + return Center( + child: SingleChildScrollView( + child: GestureDetector( + behavior: HitTestBehavior.translucent, + onTap: () { + // 点击空白处时收起键盘 + FocusScope.of(Get.context!).unfocus(); + }, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image( + height: ScreenAdaper.width(150), + image: const AssetImage( + 'assets/images/company_logo.png', + )), + SizedBox( + width: ScreenAdaper.width(10), + ), + Text( + '山矿通', + style: TextStyle( + fontWeight: FontWeight.w700, + color: AppTheme.nearlyWhite, + letterSpacing: ScreenAdaper.sp(5), + fontSize: ScreenAdaper.sp(70)), + ) + ], + ), + // Row( + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // Text( + // '山矿通', + // style: TextStyle( + // letterSpacing: ScreenAdaper.sp(10), + // fontSize: ScreenAdaper.sp(70)), + // ) + // ], + // ), + SizedBox(height: ScreenAdaper.height(50)), + buildForm(), + SizedBox(height: ScreenAdaper.height(50)), + ], + ), + ), + )); + } + + Widget buildForm() { + final children = [ + buildUserNameInput(), + SizedBox( + height: ScreenAdaper.height(20), + ), + buildPasswordInput(), + SizedBox( + height: ScreenAdaper.height(20), + ), + buildForgotPassword(), + SizedBox( + height: ScreenAdaper.height(20), + ), + buildSubmitButton(), + ]; + + final child = Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: children, + ); + + return Form( + key: _controller.formKey, + child: Container( + alignment: Alignment.center, + width: ScreenAdaper.width(800), + padding: EdgeInsets.symmetric( + vertical: 0, horizontal: ScreenAdaper.width(50)), + child: child, + )); + } + + Widget buildSubmitButton() { + final button = ElevatedButton( + style: ElevatedButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(ScreenAdaper.sp(30))), + padding: EdgeInsets.symmetric( + horizontal: ScreenAdaper.height(25), + vertical: ScreenAdaper.height(20)), + foregroundColor: AppTheme.nearlyWhite, + textStyle: TextStyle( + letterSpacing: 5, + fontWeight: FontWeight.bold, + fontSize: ScreenAdaper.sp(25)), + backgroundColor: AppTheme.primaryColor), + onPressed: _controller.doLogin, + child: const Text('登录'), + ); + final child = Expanded( + child: button, + ); + return Row( + children: [child], + ); + } + + Widget buildUserNameInput() { + return TextFormField( + decoration: const InputDecoration( + labelText: '用户名', + ), + onFieldSubmitted: (value) { + _controller.passwordFocusNode.requestFocus(); + }, + style: TextStyle(fontSize: ScreenAdaper.sp(25)), + onChanged: (value) {}, + validator: (String? value) { + if (value == null || value == '') { + return '用户名必填'; + } else { + return null; + } + }, + ); + } + + Widget buildPasswordInput() { + return TextFormField( + decoration: const InputDecoration( + labelText: '密码', + ), + obscureText: true, + focusNode: _controller.passwordFocusNode, + onFieldSubmitted: (value) { + _controller.doLogin(); + }, + style: TextStyle(fontSize: ScreenAdaper.sp(25)), + onChanged: (value) {}, + validator: (String? value) { + return (value ?? '').length >= 6 ? null : '密码长度至少6位'; + }, + ); + } + + Widget buildForgotPassword() { + return GestureDetector( + onTap: () {}, + child: Container( + alignment: Alignment.centerRight, + child: Text( + '忘记密码?', + style: TextStyle( + color: Colors.grey, + fontSize: ScreenAdaper.sp(20), + decoration: TextDecoration.underline, + ), + )), + ); + } +} diff --git a/lib/screens/login/login.controller.dart b/lib/screens/login/login.controller.dart index 37a03f2..8fd0a65 100644 --- a/lib/screens/login/login.controller.dart +++ b/lib/screens/login/login.controller.dart @@ -7,31 +7,12 @@ import '../../util/util.dart'; class LoginController extends GetxController { final isAgreeTerm = RxBool(false); - - Future fastLogin() async { - await confirmAgreement().then((value) async { - if (value != null) { - await AuthStore.to.login(LoginEnum.fastLogin); - } - }); - } - - Future confirmAgreement() async { - // if (!isAgreeTerm.value) { - // return Get.defaultDialog( - // title: '', - // content: ConfirmAgreement(), - // titlePadding: const EdgeInsets.all(0)); - // } else { - // return Future(() => true); - // } - } - - Future onPrivacyPolicyTap() async { - // launchUrl(Uri.parse(GloablConfig.PRIVACY_POLICY)); - } - - Future onTermTap() async { - // launchUrl(Uri.parse(GloablConfig.TERM_OF_USER)); + final formKey = GlobalKey(); + final passwordFocusNode = FocusNode(); + bool loading = false; + Future doLogin() async { + if (!formKey.currentState!.validate()) { + return; + } } } diff --git a/lib/screens/login/login.dart b/lib/screens/login/login.dart index 796bd60..ddbf4af 100644 --- a/lib/screens/login/login.dart +++ b/lib/screens/login/login.dart @@ -1,195 +1,204 @@ +import 'package:date_format/date_format.dart'; import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import 'package:sk_base_mobile/app_theme.dart'; +import 'package:sk_base_mobile/screens/login/login.controller.dart'; import 'package:sk_base_mobile/util/screen_adaper_util.dart'; class LoginScreen extends StatelessWidget { LoginScreen({super.key}); - final formKey = GlobalKey(); - late BuildContext theContext; - bool loading = false; - String? username; - String? password; + final _controller = Get.put(LoginController()); + double formWidth = 700; @override Widget build(BuildContext context) { - return Scaffold(body: SafeArea(child: buildBody())); + return Scaffold( + body: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/bg.jpg'), + fit: BoxFit.cover, + ), + ), + child: buildBody())); } - buildBody() { + Widget buildBody() { return GestureDetector( behavior: HitTestBehavior.translucent, onTap: () { - // 触摸收起键盘 + // 点击空白处时收起键盘 + FocusScope.of(Get.context!).unfocus(); }, - child: Padding( - padding: EdgeInsets.fromLTRB(0, 0, 10, 30), - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - // Logo(size: 120), - SizedBox(height: 30), - buildForm(), - SizedBox(height: 30), - ], + child: Center( + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image( + height: ScreenAdaper.width(150), + image: const AssetImage( + 'assets/images/company_logo.png', + )), + SizedBox( + width: ScreenAdaper.width(10), ), - ), - buildGoRegister(), - buildNotice(), - ], - ), - ))); - } - - Widget buildNotice() { - return Padding( - padding: EdgeInsets.fromLTRB(50, 5, 50, 5), - child: Text( - 'If you have registered as a PLAYER, COACH, MANAGER or REFEREE, please use your login details provided.', - textAlign: TextAlign.center, - style: TextStyle(fontWeight: FontWeight.bold))); + Text( + '山矿通', + style: TextStyle( + fontWeight: FontWeight.w700, + color: AppTheme.nearlyWhite, + letterSpacing: ScreenAdaper.sp(5), + fontSize: ScreenAdaper.sp(70)), + ) + ], + ), + SizedBox(height: ScreenAdaper.height(50)), + buildForm(), + SizedBox(height: ScreenAdaper.height(50)), + buildSubmitButton(), + SizedBox(height: ScreenAdaper.height(50)), + ], + ), + ), + )); } Widget buildForm() { final children = [ buildUserNameInput(), - SizedBox( - height: 15, + Divider( + thickness: ScreenAdaper.height(2), ), buildPasswordInput(), - SizedBox( - height: 12, - ), - buildForgotPassword(), - SizedBox( - height: 12, - ), - buildSubmitButton(), - - /* SizedBox( - height: 12, - ), - buildRegistry() */ ]; final child = Column( - mainAxisAlignment: MainAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, children: children, ); return Form( - key: formKey, - child: Padding( - padding: EdgeInsets.symmetric(vertical: 0, horizontal: 50), + key: _controller.formKey, + child: Container( + padding: EdgeInsets.symmetric(vertical: ScreenAdaper.height(10)), + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: AppTheme.black.withOpacity(0.3), + spreadRadius: ScreenAdaper.sp(10), + blurRadius: ScreenAdaper.sp(10), + offset: Offset( + 0, ScreenAdaper.height(2)), // changes position of shadow + ), + ], + border: Border.all(width: 0), + borderRadius: BorderRadius.circular(ScreenAdaper.sp(30)), + color: AppTheme.nearlyWhite.withOpacity(0.9), + ), + alignment: Alignment.center, + width: ScreenAdaper.width(formWidth), child: child, )); } - Widget buildGoRegister() => Container( - child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ - Text('Don\'t have an account?'), - SizedBox(width: 5), - GestureDetector( - onTap: () {}, - child: Text('Create', - style: TextStyle( - color: AppTheme.primaryColor, - decoration: TextDecoration.underline, - ))), - ]), - ); - Widget buildSubmitButton() { - final color = AppTheme.primaryColor; - - // final button = RaisedButton( - // shape: StadiumBorder(), - // child: loading - // ? SizedBox( - // child: CircularProgressIndicator( - // color: AppTheme.primaryColorDark, - // ), - // height: 18, - // width: 18, - // ) - // : Text('Sign In'), - // onPressed: () { - // _submit(); - // }, - // color: color, - // /* elevation: 20, */ - // padding: EdgeInsets.all(12), - // ); - - // final child = Expanded( - // child: button, - // ); - - return Row( - children: [], + final button = ElevatedButton( + style: ElevatedButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(ScreenAdaper.sp(30))), + padding: EdgeInsets.symmetric( + horizontal: ScreenAdaper.height(25), + vertical: ScreenAdaper.height(20)), + foregroundColor: AppTheme.nearlyWhite, + textStyle: TextStyle( + letterSpacing: 5, + fontWeight: FontWeight.bold, + fontSize: ScreenAdaper.sp(25)), + backgroundColor: AppTheme.primaryColor), + onPressed: _controller.doLogin, + child: const Text('登录'), + ); + final child = Expanded( + child: button, + ); + return Container( + decoration: BoxDecoration( + border: Border.all(width: 0), + borderRadius: BorderRadius.circular(ScreenAdaper.sp(30)), + boxShadow: [ + BoxShadow( + color: AppTheme.black.withOpacity(0.3), + spreadRadius: ScreenAdaper.sp(10), + blurRadius: ScreenAdaper.sp(10), + offset: + Offset(0, ScreenAdaper.height(5)), // changes position of shadow + ), + ], + ), + alignment: Alignment.center, + width: ScreenAdaper.width(formWidth), + child: Row( + children: [child], + ), ); } Widget buildUserNameInput() { return TextFormField( - initialValue: username, decoration: InputDecoration( - labelText: 'Email / Reg ID', - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(ScreenAdaper.sp(10))), - fillColor: Color(0xFFF8F8F8), - ), - onChanged: (value) { - this.username = value; - }, - validator: (String? value) { - if (value == null || value == '') { - return 'Email / Reg ID is required'; - } else { - return null; - } + prefixIcon: Icon( + Icons.person_2_outlined, + size: ScreenAdaper.sp(40), + ), + hintText: '用户名', + border: InputBorder.none, + focusedBorder: InputBorder.none), + onFieldSubmitted: (value) { + _controller.passwordFocusNode.requestFocus(); }, + style: TextStyle(fontSize: ScreenAdaper.sp(25)), + onChanged: (value) {}, ); } Widget buildPasswordInput() { return TextFormField( - initialValue: password, decoration: InputDecoration( - labelText: 'Password', - /* border: OutlineInputBorder(), */ - fillColor: Color(0xFFF8F8F8), - ), + prefixIcon: Icon( + Icons.lock_outlined, + size: ScreenAdaper.sp(40), + ), + hintText: '密码', + border: InputBorder.none, + focusedBorder: InputBorder.none), obscureText: true, - onChanged: (value) { - this.password = value; - }, - validator: (String? value) { - return (value ?? '').length >= 6 ? null : 'Invalid password'; + focusNode: _controller.passwordFocusNode, + onFieldSubmitted: (value) { + _controller.doLogin(); }, + style: TextStyle(fontSize: ScreenAdaper.sp(25)), + onChanged: (value) {}, + // validator: (String? value) { + // return (value ?? '').length >= 6 ? null : '密码长度至少6位'; + // }, ); } - Future _submit() async { - if (!formKey.currentState!.validate()) { - return; - } - - return; - } - Widget buildForgotPassword() { return GestureDetector( onTap: () {}, child: Container( alignment: Alignment.centerRight, child: Text( - 'Forgot Password?', + '忘记密码?', style: TextStyle( color: Colors.grey, + fontSize: ScreenAdaper.sp(20), decoration: TextDecoration.underline, ), )), diff --git a/lib/util/screen_adaper_util.dart b/lib/util/screen_adaper_util.dart index e93f534..aa35e2a 100644 --- a/lib/util/screen_adaper_util.dart +++ b/lib/util/screen_adaper_util.dart @@ -1,3 +1,4 @@ +import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; @@ -45,6 +46,6 @@ class ScreenAdaper { } static isLandspace() { - return Get.width > Get.height; + return Get.context?.orientation == Orientation.landscape; } }