login_page.dart 14 KB

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