login_page.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  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: Row(
  87. mainAxisSize: MainAxisSize.min,
  88. crossAxisAlignment: CrossAxisAlignment.center,
  89. children: [
  90. MyTextView(
  91. "Vietnam".tr,
  92. textColor: ColorConstants.white,
  93. isFontMedium: true,
  94. marginRight: 5,
  95. fontSize: 15,
  96. ),
  97. MyAssetImage(
  98. Assets.baseServiceTriangleDropDown,
  99. width: 8,
  100. height: 5,
  101. ),
  102. ],
  103. ).onTap(() => controller.gotoSelectCountryPage()).marginOnly(right: 20, top: ScreenUtil.getStatusBarH(context) + 20),
  104. ),
  105. // 底部滚动的布局
  106. SingleChildScrollView(
  107. scrollDirection: Axis.vertical,
  108. physics: const BouncingScrollPhysics(),
  109. child: Column(
  110. mainAxisSize: MainAxisSize.max,
  111. crossAxisAlignment: CrossAxisAlignment.center,
  112. children: [
  113. MyTextView(
  114. "Casual Labour System",
  115. textColor: ColorConstants.white,
  116. isFontBold: true,
  117. fontSize: 35,
  118. marginTop: 20,
  119. fontStyle: FontStyle.italic,
  120. textAlign: TextAlign.center,
  121. marginLeft: 50,
  122. marginRight: 50,
  123. ),
  124. //中间的输入框布局
  125. Container(
  126. width: double.infinity,
  127. margin: EdgeInsets.symmetric(vertical: 45, horizontal: 15),
  128. padding: EdgeInsets.symmetric(vertical: 33, horizontal: 20),
  129. decoration: BoxDecoration(
  130. color: Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
  131. borderRadius: BorderRadius.circular(5.0), // 设置圆角
  132. ),
  133. child: Center(
  134. child: Column(
  135. crossAxisAlignment: CrossAxisAlignment.start,
  136. children: [
  137. //登录文本
  138. MyTextView(
  139. "Email".tr,
  140. isFontMedium: true,
  141. fontSize: 17,
  142. textColor: ColorConstants.white,
  143. ),
  144. // 登录表单 - 账号
  145. _buildInputLayout(
  146. "code",
  147. textInputAction: TextInputAction.next,
  148. errorText: state.codeErrorText,
  149. onSubmit: (formKey, value) {
  150. state.formData[formKey]!['focusNode'].unfocus();
  151. FocusScope.of(context).requestFocus(state.formData['password']!['focusNode']);
  152. },
  153. ),
  154. //密码文本
  155. MyTextView(
  156. "Password".tr,
  157. isFontMedium: true,
  158. fontSize: 17,
  159. textColor: ColorConstants.white,
  160. marginTop: 18,
  161. ),
  162. // 登录表单 - 密码
  163. _buildInputLayout(
  164. "password",
  165. obscureText: !state.pwdVisibility,
  166. errorText: state.passwordErrorText,
  167. showRightIcon: true,
  168. rightWidget: IconButton(
  169. highlightColor: Colors.transparent,
  170. splashColor: Colors.transparent,
  171. icon: state.pwdVisibility
  172. ? const MyAssetImage(
  173. Assets.cptAuthPasswordShowIcon,
  174. width: 21,
  175. height: 21,
  176. color: ColorConstants.white,
  177. )
  178. : const MyAssetImage(
  179. Assets.cptAuthPasswordHideIcon,
  180. width: 21,
  181. height: 21,
  182. color: ColorConstants.white,
  183. ),
  184. onPressed: () {
  185. controller.switchPwdVisibility();
  186. },
  187. ),
  188. onSubmit: (formKey, value) {
  189. state.formData[formKey]!['focusNode'].unfocus();
  190. controller.doInputLogin();
  191. },
  192. ),
  193. //选择签到功能还是全功能
  194. CustomRadioCheck(
  195. options: state.loginOption,
  196. onOptionSelected: (index, text) {
  197. state.loginOptionPosition = index;
  198. },
  199. ).marginSymmetric(vertical: 20),
  200. //登录按钮
  201. MyButton(
  202. type: ClickType.throttle,
  203. milliseconds: 500,
  204. onPressed: () {
  205. FocusScope.of(context).unfocus();
  206. controller.doInputLogin();
  207. },
  208. text: "Log in".tr,
  209. textColor: ColorConstants.white,
  210. fontSize: 16,
  211. radius: 22.5,
  212. backgroundColor: hexToColor("#FFBB1B"),
  213. fontWeight: FontWeight.w500,
  214. ),
  215. //注册入口
  216. Visibility(
  217. visible: !DeviceUtils.isAndroid,
  218. child: _buildRichText(),
  219. ),
  220. ],
  221. ),
  222. ), // 传递子部件
  223. ),
  224. ],
  225. )).expanded(),
  226. ],
  227. ),
  228. ),
  229. );
  230. },
  231. );
  232. }
  233. //底部的注册文本
  234. Widget _buildRichText() {
  235. return Align(
  236. alignment: Alignment.center,
  237. child: RichText(
  238. text: TextSpan(
  239. style: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, color: ColorConstants.textGrayAECAE5),
  240. children: <TextSpan>[
  241. TextSpan(
  242. text: "Don’t have an account?".tr,
  243. style: TextStyle(color: ColorConstants.textGrayAECAE5),
  244. ),
  245. TextSpan(
  246. text: "Sign up".tr,
  247. style: TextStyle(color: ColorConstants.textYellowFFBB1B),
  248. recognizer: TapGestureRecognizer()
  249. ..onTap = () {
  250. //去登录页面
  251. controller.gotoSignUpPage();
  252. },
  253. ),
  254. ],
  255. ),
  256. ),
  257. ).marginOnly(top: 23);
  258. }
  259. /// 输入框 账号与密码
  260. Widget _buildInputLayout(
  261. String key, {
  262. double marginTop = 0,
  263. bool? showRightIcon = false, //是否展示右侧的布局
  264. Widget? rightWidget, //右侧的布局
  265. TextInputType textInputType = TextInputType.text,
  266. String? errorText,
  267. bool obscureText = false,
  268. TextInputAction textInputAction = TextInputAction.done,
  269. Function? onSubmit,
  270. }) {
  271. return IgnoreKeyboardDismiss(
  272. child: MyTextField(
  273. key,
  274. state.formData[key]!['value'],
  275. hintText: state.formData[key]!['hintText'],
  276. hintStyle: TextStyle(
  277. color: hexToColor("#AECAE5"),
  278. fontSize: 15.0,
  279. fontWeight: FontWeight.w500,
  280. ),
  281. controller: state.formData[key]!['controller'],
  282. focusNode: state.formData[key]!['focusNode'],
  283. margin: EdgeInsets.only(top: marginTop),
  284. showDivider: true,
  285. dividerColor: hexToColor("#7BABC8"),
  286. style: TextStyle(
  287. color: ColorConstants.white,
  288. fontSize: 15.0,
  289. fontWeight: FontWeight.w500,
  290. ),
  291. inputType: textInputType,
  292. height: 35,
  293. textInputAction: textInputAction,
  294. onSubmit: onSubmit,
  295. cursorColor: ColorConstants.white,
  296. obscureText: obscureText,
  297. errorText: errorText,
  298. showLeftIcon: true,
  299. showRightIcon: showRightIcon,
  300. rightWidget: rightWidget,
  301. ),
  302. );
  303. }
  304. }