login_page.dart 12 KB

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