login_page.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. import 'package:cs_resources/constants/color_constants.dart';
  2. import 'package:cs_resources/generated/assets.dart';
  3. import 'package:flutter/cupertino.dart';
  4. import 'package:flutter/gestures.dart';
  5. import 'package:flutter/material.dart';
  6. import 'package:flutter/widgets.dart';
  7. import 'package:get/get.dart';
  8. import 'package:plugin_basic/base/base_stateful_page.dart';
  9. import 'package:plugin_basic/base/base_state.dart';
  10. import 'package:plugin_basic/base/mixin_state_lifecycle.dart';
  11. import 'package:plugin_basic/utils/ext_get_nav.dart';
  12. import 'package:router/path/router_path.dart';
  13. import 'package:shared/utils/device_utils.dart';
  14. import 'package:shared/utils/log_utils.dart';
  15. import 'package:shared/utils/screen_util.dart';
  16. import 'package:widgets/custom_radio_check.dart';
  17. import 'package:widgets/ext/ex_widget.dart';
  18. import 'package:widgets/my_button.dart';
  19. import 'package:widgets/my_load_image.dart';
  20. import 'package:widgets/my_text_field.dart';
  21. import 'package:widgets/my_text_view.dart';
  22. import 'package:widgets/widget_export.dart';
  23. import 'login_controller.dart';
  24. import 'login_state.dart';
  25. /*
  26. App 登录页面
  27. */
  28. class LoginPage extends BaseStatefulPage<LoginController> {
  29. LoginPage({super.key});
  30. //启动当前页面
  31. static void startInstance() {
  32. return Get.start(RouterPath.AUTH_LOGIN, launchModel: LaunchModel.standard);
  33. }
  34. static void startWithPopAll() {
  35. Get.offAllNamed(RouterPath.AUTH_LOGIN);
  36. }
  37. @override
  38. State<LoginPage> createState() => _MainPageState();
  39. @override
  40. LoginController createRawController() {
  41. return LoginController();
  42. }
  43. }
  44. /**
  45. * 页面
  46. */
  47. class _MainPageState extends BaseState<LoginPage, LoginController> with StateLifecycle {
  48. late LoginState state;
  49. @override
  50. void initState() {
  51. super.initState();
  52. state = controller.state;
  53. }
  54. @override
  55. void dispose() {
  56. Get.delete<LoginController>();
  57. super.dispose();
  58. }
  59. @override
  60. Widget build(BuildContext context) {
  61. Log.d("LoginPage Lifecycle - build走了一遍");
  62. return autoCtlGetBuilder(
  63. builder: (controller) {
  64. return Scaffold(
  65. body: Container(
  66. width: double.infinity,
  67. height: double.infinity,
  68. decoration: const BoxDecoration(
  69. gradient: LinearGradient(
  70. colors: [
  71. Color(0xFF091D44),
  72. Color(0xFF245A8A),
  73. Color(0xFF7F7CEC),
  74. ],
  75. begin: Alignment.topCenter,
  76. end: Alignment.bottomCenter,
  77. ),
  78. ),
  79. child: Column(
  80. mainAxisSize: MainAxisSize.max,
  81. crossAxisAlignment: CrossAxisAlignment.center,
  82. children: [
  83. //当前选择的国家,这个不跟随滚动
  84. Align(
  85. alignment: Alignment.topRight,
  86. child: MyTextView(
  87. "Vietnam".tr,
  88. textColor: ColorConstants.white,
  89. isFontMedium: true,
  90. fontSize: 15,
  91. marginTop: ScreenUtil.getStatusBarH(context) + 20,
  92. marginRight: 20,
  93. ),
  94. ),
  95. // 底部滚动的布局
  96. SingleChildScrollView(
  97. scrollDirection: Axis.vertical,
  98. physics: const BouncingScrollPhysics(),
  99. child: Column(
  100. mainAxisSize: MainAxisSize.max,
  101. crossAxisAlignment: CrossAxisAlignment.center,
  102. children: [
  103. MyTextView(
  104. "Casual Labour System",
  105. textColor: ColorConstants.white,
  106. isFontBold: true,
  107. fontSize: 35,
  108. marginTop: 20,
  109. fontStyle: FontStyle.italic,
  110. textAlign: TextAlign.center,
  111. marginLeft: 50,
  112. marginRight: 50,
  113. ),
  114. //中间的输入框布局
  115. Container(
  116. width: double.infinity,
  117. margin: EdgeInsets.symmetric(vertical: 45, horizontal: 15),
  118. padding: EdgeInsets.symmetric(vertical: 33, horizontal: 20),
  119. decoration: BoxDecoration(
  120. color: Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
  121. borderRadius: BorderRadius.circular(5.0), // 设置圆角
  122. ),
  123. child: Center(
  124. child: Column(
  125. crossAxisAlignment: CrossAxisAlignment.start,
  126. children: [
  127. //登录文本
  128. MyTextView(
  129. "Email".tr,
  130. isFontMedium: true,
  131. fontSize: 17,
  132. textColor: ColorConstants.white,
  133. ),
  134. // 登录表单 - 账号
  135. _buildInputLayout(
  136. "code",
  137. textInputAction: TextInputAction.next,
  138. errorText: state.codeErrorText,
  139. onSubmit: (formKey, value) {
  140. state.formData[formKey]!['focusNode'].unfocus();
  141. FocusScope.of(context).requestFocus(state.formData['password']!['focusNode']);
  142. },
  143. ),
  144. //密码文本
  145. MyTextView(
  146. "Password".tr,
  147. isFontMedium: true,
  148. fontSize: 17,
  149. textColor: ColorConstants.white,
  150. marginTop: 18,
  151. ),
  152. // 登录表单 - 密码
  153. _buildInputLayout(
  154. "password",
  155. obscureText: !state.pwdVisibility,
  156. errorText: state.passwordErrorText,
  157. showRightIcon: true,
  158. rightWidget: IconButton(
  159. highlightColor: Colors.transparent,
  160. splashColor: Colors.transparent,
  161. icon: state.pwdVisibility
  162. ? const MyAssetImage(
  163. Assets.cptAuthPasswordShowIcon,
  164. width: 21,
  165. height: 21,
  166. color: ColorConstants.white,
  167. )
  168. : const MyAssetImage(
  169. Assets.cptAuthPasswordHideIcon,
  170. width: 21,
  171. height: 21,
  172. color: ColorConstants.white,
  173. ),
  174. onPressed: () {
  175. controller.switchPwdVisibility();
  176. },
  177. ),
  178. onSubmit: (formKey, value) {
  179. state.formData[formKey]!['focusNode'].unfocus();
  180. controller.doInputLogin();
  181. },
  182. ),
  183. //选择签到功能还是全功能
  184. CustomRadioCheck(
  185. options: state.loginOption,
  186. onOptionSelected: (index, text) {
  187. state.loginOptionPosition = index;
  188. },
  189. ).marginSymmetric(vertical: 20),
  190. //登录按钮
  191. MyButton(
  192. type: ClickType.throttle,
  193. milliseconds: 500,
  194. onPressed: () {
  195. FocusScope.of(context).unfocus();
  196. controller.doInputLogin();
  197. },
  198. text: "Log in".tr,
  199. textColor: ColorConstants.white,
  200. fontSize: 16,
  201. radius: 22.5,
  202. backgroundColor: hexToColor("#FFBB1B"),
  203. fontWeight: FontWeight.w500,
  204. ),
  205. //注册入口
  206. Visibility(
  207. visible: !DeviceUtils.isAndroid,
  208. child: _buildRichText(),
  209. ),
  210. ],
  211. ),
  212. ), // 传递子部件
  213. ),
  214. ],
  215. )).expanded(),
  216. ],
  217. ),
  218. ),
  219. );
  220. },
  221. );
  222. }
  223. //底部的注册文本
  224. Widget _buildRichText() {
  225. return Align(
  226. alignment: Alignment.center,
  227. child: RichText(
  228. text: TextSpan(
  229. style: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, color: ColorConstants.textGrayAECAE5),
  230. children: <TextSpan>[
  231. TextSpan(
  232. text: "Don’t have an account?".tr,
  233. style: TextStyle(color: ColorConstants.textGrayAECAE5),
  234. ),
  235. TextSpan(
  236. text: "Sign up".tr,
  237. style: TextStyle(color: ColorConstants.textYellowFFBB1B),
  238. recognizer: TapGestureRecognizer()
  239. ..onTap = () {
  240. //去登录页面
  241. controller.gotoSignUpPage();
  242. },
  243. ),
  244. ],
  245. ),
  246. ),
  247. ).marginOnly(top: 23);
  248. }
  249. /// 输入框 账号与密码
  250. Widget _buildInputLayout(
  251. String key, {
  252. double marginTop = 0,
  253. bool? showRightIcon = false, //是否展示右侧的布局
  254. Widget? rightWidget, //右侧的布局
  255. TextInputType textInputType = TextInputType.text,
  256. String? errorText,
  257. bool obscureText = false,
  258. TextInputAction textInputAction = TextInputAction.done,
  259. Function? onSubmit,
  260. }) {
  261. return IgnoreKeyboardDismiss(
  262. child: MyTextField(
  263. key,
  264. state.formData[key]!['value'],
  265. hintText: state.formData[key]!['hintText'],
  266. hintStyle: TextStyle(
  267. color: hexToColor("#AECAE5"),
  268. fontSize: 15.0,
  269. fontWeight: FontWeight.w500,
  270. ),
  271. controller: state.formData[key]!['controller'],
  272. focusNode: state.formData[key]!['focusNode'],
  273. margin: EdgeInsets.only(top: marginTop),
  274. showDivider: true,
  275. dividerColor: hexToColor("#7BABC8"),
  276. style: TextStyle(
  277. color: ColorConstants.white,
  278. fontSize: 15.0,
  279. fontWeight: FontWeight.w500,
  280. ),
  281. inputType: textInputType,
  282. height: 35,
  283. textInputAction: textInputAction,
  284. onSubmit: onSubmit,
  285. cursorColor: ColorConstants.white,
  286. obscureText: obscureText,
  287. errorText: errorText,
  288. showLeftIcon: true,
  289. showRightIcon: showRightIcon,
  290. rightWidget: rightWidget,
  291. ),
  292. );
  293. }
  294. }