glglove преди 3 седмици
родител
ревизия
7a2b537297
променени са 60 файла, в които са добавени 2577 реда и са изтрити 211 реда
  1. 63 75
      app/lib/main.dart
  2. 1 4
      app/lib/router/component/app_service_provider.dart
  3. 1 1
      melos.yaml
  4. 231 0
      packages/cpt_auth/lib/modules/auth_login/auth_login_page.dart
  5. 70 0
      packages/cpt_auth/lib/modules/auth_login/auth_login_state.dart
  6. 131 0
      packages/cpt_auth/lib/modules/auth_login/auth_login_view_model.dart
  7. 3 3
      packages/cpt_auth/lib/modules/auth_login/vm/auth_login_view_model.g.dart
  8. 0 34
      packages/cpt_auth/lib/modules/auth_login/page/Profile_edit_page.dart
  9. 0 14
      packages/cpt_auth/lib/modules/auth_login/vm/auth_login_view_model.dart
  10. 182 0
      packages/cpt_auth/lib/modules/forgot_input/forgot_input_page.dart
  11. 50 0
      packages/cpt_auth/lib/modules/forgot_input/forgot_input_state.dart
  12. 91 0
      packages/cpt_auth/lib/modules/forgot_input/forgot_input_view_model.dart
  13. 27 0
      packages/cpt_auth/lib/modules/forgot_input/forgot_input_view_model.g.dart
  14. 232 0
      packages/cpt_auth/lib/modules/forgot_verify/forgot_verify_page.dart
  15. 78 0
      packages/cpt_auth/lib/modules/forgot_verify/forgot_verify_state.dart
  16. 155 0
      packages/cpt_auth/lib/modules/forgot_verify/forgot_verify_view_model.dart
  17. 27 0
      packages/cpt_auth/lib/modules/forgot_verify/forgot_verify_view_model.g.dart
  18. 304 0
      packages/cpt_auth/lib/modules/sign_up/sign_up_page.dart
  19. 107 0
      packages/cpt_auth/lib/modules/sign_up/sign_up_state.dart
  20. 199 0
      packages/cpt_auth/lib/modules/sign_up/sign_up_view_model.dart
  21. 26 0
      packages/cpt_auth/lib/modules/sign_up/sign_up_view_model.g.dart
  22. 3 4
      packages/cpt_auth/lib/router/component/auth_component_service.dart
  23. 8 2
      packages/cpt_auth/lib/router/page/auth_page_router.dart
  24. 61 1
      packages/cpt_auth/lib/router/page/auth_page_router.gr.dart
  25. 3 1
      packages/cpt_main/lib/modules/home/page/home_page.dart
  26. 50 0
      packages/cpt_main/lib/modules/main/page/main_page.dart
  27. 2 1
      packages/cpt_main/lib/modules/visitor/page/visitor_page.dart
  28. BIN
      packages/cs_resources/assets/auth/choose_estate_building.webp
  29. BIN
      packages/cs_resources/assets/auth/country_sg.webp
  30. BIN
      packages/cs_resources/assets/auth/forgot_input_email_phone_img.webp
  31. BIN
      packages/cs_resources/assets/auth/forgot_reset_password_img.webp
  32. BIN
      packages/cs_resources/assets/auth/image_add_icon.webp
  33. BIN
      packages/cs_resources/assets/auth/password_hide.webp
  34. BIN
      packages/cs_resources/assets/auth/password_show.webp
  35. BIN
      packages/cs_resources/assets/auth/sign_up_input_img.webp
  36. BIN
      packages/cs_resources/assets/auth/sign_up_success_img.webp
  37. BIN
      packages/cs_resources/assets/auth/sign_up_unit_img.webp
  38. BIN
      packages/cs_resources/assets/auth/sms_verify_img.webp
  39. BIN
      packages/cs_resources/assets/auth/yy_home_success.webp
  40. BIN
      packages/cs_resources/assets/base_service/check_box_checked.webp
  41. BIN
      packages/cs_resources/assets/base_service/check_box_uncheck.webp
  42. BIN
      packages/cs_resources/assets/base_service/triangle_drop_down_icon.webp
  43. BIN
      packages/cs_resources/assets/yy_home_logo.webp
  44. 13 0
      packages/cs_resources/lib/generated/assets.dart
  45. 28 1
      packages/cs_resources/lib/generated/intl/messages_en.dart
  46. 21 1
      packages/cs_resources/lib/generated/intl/messages_zh_CN.dart
  47. 21 1
      packages/cs_resources/lib/generated/intl/messages_zh_HK.dart
  48. 190 0
      packages/cs_resources/lib/generated/l10n.dart
  49. 20 1
      packages/cs_resources/lib/l10n/intl_en.arb
  50. 20 1
      packages/cs_resources/lib/l10n/intl_zh_CN.arb
  51. 20 1
      packages/cs_resources/lib/l10n/intl_zh_HK.arb
  52. 36 5
      packages/cs_resources/lib/theme/app_colors_theme.dart
  53. 14 1
      packages/cs_resources/lib/theme/theme_config.dart
  54. 4 0
      packages/cs_resources/pubspec.yaml
  55. 2 0
      packages/cs_router/lib/path/router_path.dart
  56. 15 11
      packages/cs_widgets/lib/ext/ex_widget.dart
  57. 18 15
      packages/cs_widgets/lib/my_appbar.dart
  58. 40 27
      packages/cs_widgets/lib/my_button.dart
  59. 9 5
      packages/cs_widgets/lib/my_text_field.dart
  60. 1 1
      packages/cs_widgets/lib/shatter/custom_check_box.dart

+ 63 - 75
app/lib/main.dart

@@ -136,17 +136,11 @@ class MyApp extends HookConsumerWidget {
           systemUiOverlayStyle = ThemeConfig.systemUiOverlayStyleDarkTheme;
           break;
         default:
-          Brightness currentBrightness = MediaQuery.of(context).platformBrightness;
-          if (currentBrightness == Brightness.dark) {
-            Log.d("main.dart - 跟随系统模式-暗色模式");
-            systemUiOverlayStyle = ThemeConfig.systemUiOverlayStyleDarkTheme;
-          } else {
-            Log.d("main.dart - 跟随系统模式-亮色模式");
-            systemUiOverlayStyle = ThemeConfig.systemUiOverlayStyleLightThemeBlack;
-          }
+          systemUiOverlayStyle = ThemeConfig.getSystemUiOverlayStyleByTheme(context);
           break;
       }
     }
+
     SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
 
     useEffect(() {
@@ -160,78 +154,72 @@ class MyApp extends HookConsumerWidget {
       };
     }, []);
 
-    //全局入口
-    // return AnnotatedRegion<SystemUiOverlayStyle>(
-    //   value: systemUiOverlayStyle,
-    //   child:
-
-   return   KeyboardVisibilityBuilder(builder: (context, isKeyboardVisible) {
-        return KeyboardDismissOnTap(
-          dismissOnCapturedTaps: false,
-          child: MaterialApp.router(
-            title: 'PropertyManagementSystem',
-            debugShowCheckedModeBanner: true,
+    return KeyboardVisibilityBuilder(builder: (context, isKeyboardVisible) {
+      return KeyboardDismissOnTap(
+        dismissOnCapturedTaps: false,
+        child: MaterialApp.router(
+          title: 'PropertyManagementSystem',
+          debugShowCheckedModeBanner: true,
 
-            //主题配置
-            theme: ThemeData(
-              colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF4161D0)),
-              useMaterial3: false,
-            ).copyWith(extensions: [
-              AppColorsTheme.light(),
-            ]),
-            darkTheme: ThemeData(
-              colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF4161D0), brightness: Brightness.dark),
-              useMaterial3: false,
-            ).copyWith(extensions: [
-              AppColorsTheme.dark(),
-            ]),
-            themeMode: themeMode == ThemeMode.system ? ThemeMode.system : themeMode,
+          //主题配置
+          theme: ThemeData(
+            colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF4161D0)),
+            useMaterial3: false,
+          ).copyWith(extensions: [
+            AppColorsTheme.light(),
+          ]),
+          darkTheme: ThemeData(
+            colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF4161D0), brightness: Brightness.dark),
+            useMaterial3: false,
+          ).copyWith(extensions: [
+            AppColorsTheme.dark(),
+          ]),
+          themeMode: themeMode == ThemeMode.system ? ThemeMode.system : themeMode,
 
-            //国际化配置
-            localizationsDelegates: const [
-              S.delegate,
-              GlobalMaterialLocalizations.delegate,
-              GlobalCupertinoLocalizations.delegate,
-              GlobalWidgetsLocalizations.delegate,
-            ],
-            //国际化英语为首选项
-            supportedLocales: [const Locale('en', ''), ...S.delegate.supportedLocales],
-            localeResolutionCallback: (locale, supportLocales) {
-              // 中文 简繁体处理
-              if (locale?.languageCode == 'zh') {
-                if (locale?.scriptCode == 'Hant') {
-                  return const Locale('zh', 'HK'); //繁体
-                } else {
-                  return const Locale('zh', 'CN'); //简体
-                }
+          //国际化配置
+          localizationsDelegates: const [
+            S.delegate,
+            GlobalMaterialLocalizations.delegate,
+            GlobalCupertinoLocalizations.delegate,
+            GlobalWidgetsLocalizations.delegate,
+          ],
+          //国际化英语为首选项
+          supportedLocales: [const Locale('en', ''), ...S.delegate.supportedLocales],
+          localeResolutionCallback: (locale, supportLocales) {
+            // 中文 简繁体处理
+            if (locale?.languageCode == 'zh') {
+              if (locale?.scriptCode == 'Hant') {
+                return const Locale('zh', 'HK'); //繁体
+              } else {
+                return const Locale('zh', 'CN'); //简体
               }
-              return null;
+            }
+            return null;
+          },
+          //AutoRouter的配置
+          routerConfig: appRouter.config(
+            navigatorObservers: () => [
+              MyNavigatorObserver(),
+            ],
+          ),
+          //SmartDialog初始化默认Loading与Toast
+          builder: FlutterSmartDialog.init(
+            toastBuilder: (String msg) {
+              return CustomToastWidget(msg: msg);
             },
-            //AutoRouter的配置
-            routerConfig: appRouter.config(
-              navigatorObservers: () => [
-                MyNavigatorObserver(),
-              ],
-            ),
-            //SmartDialog初始化默认Loading与Toast
-            builder: FlutterSmartDialog.init(
-              toastBuilder: (String msg) {
-                return CustomToastWidget(msg: msg);
-              },
-              loadingBuilder: (String msg) {
-                return CustomLoadingWidget(msg: msg == 'loading...' ? 'Loading...' : msg);
-              },
-              notifyStyle: FlutterSmartNotifyStyle(
-                successBuilder: (String msg) => CustomSuccessWidget(msg: msg),
-                failureBuilder: (String msg) => CustomFailureWidget(msg: msg),
-                errorBuilder: (String msg) => CustomErrorWidget(msg: msg),
-                alertBuilder: (String msg) => CustomErrorWidget(msg: msg),
-                warningBuilder: (String msg) => CustomErrorWidget(msg: msg),
-              ),
+            loadingBuilder: (String msg) {
+              return CustomLoadingWidget(msg: msg == 'loading...' ? 'Loading...' : msg);
+            },
+            notifyStyle: FlutterSmartNotifyStyle(
+              successBuilder: (String msg) => CustomSuccessWidget(msg: msg),
+              failureBuilder: (String msg) => CustomFailureWidget(msg: msg),
+              errorBuilder: (String msg) => CustomErrorWidget(msg: msg),
+              alertBuilder: (String msg) => CustomErrorWidget(msg: msg),
+              warningBuilder: (String msg) => CustomErrorWidget(msg: msg),
             ),
           ),
-        );
-      });
-    // );
+        ),
+      );
+    });
   }
 }

+ 1 - 4
app/lib/router/component/app_service_provider.dart

@@ -1,15 +1,12 @@
-import 'package:flutter/material.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:router/componentRouter/app_service.dart';
-import 'package:router/componentRouter/main_service.dart';
 
 import 'app_component_service_impl.dart';
 
-
 part 'app_service_provider.g.dart';
 
 @Riverpod(keepAlive: true)
 AppService appService(Ref ref) {
   return AppComponentServiceImpl();
-}
+}

+ 1 - 1
melos.yaml

@@ -44,7 +44,7 @@ scripts:
         - build_runner
 
   build_runner_auth:
-    run: cd "$MELOS_ROOT_PATH/packages/cpt_auth" && dart run build_runner build
+    run: cd "$MELOS_ROOT_PATH/packages/cpt_auth" && dart run build_runner build --delete-conflicting-outputs
     description: Run `dart run build_runner build` in auth module
 
   build_runner_community:

+ 231 - 0
packages/cpt_auth/lib/modules/auth_login/auth_login_page.dart

@@ -0,0 +1,231 @@
+import 'package:cpt_auth/modules/auth_login/auth_login_state.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/gestures.dart';
+import 'package:flutter/material.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_button.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_field.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/shatter/custom_check_box.dart';
+import 'package:widgets/widget_export.dart';
+
+import '../../router/page/auth_page_router.dart';
+import 'auth_login_view_model.dart';
+
+/*
+ * 用户的登录页面
+ */
+@RoutePage()
+class AuthLoginPage extends HookConsumerWidget {
+  const AuthLoginPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.navigate(const AuthLoginPageRoute());
+    } else {
+      appRouter.navigate(const AuthLoginPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(authLoginViewModelProvider.notifier);
+    final state = ref.watch(authLoginViewModelProvider);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(context, "", showBackButton: false),
+      backgroundColor: context.appColors.backgroundDefault,
+      body: SingleChildScrollView(
+        scrollDirection: Axis.vertical,
+        physics: const BouncingScrollPhysics(),
+        child: Container(
+          margin: const EdgeInsets.symmetric(horizontal: 38),
+          width: double.infinity,
+          child: Column(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              //顶部Logo
+              const MyAssetImage(
+                Assets.assetsYyHomeLogo,
+                width: 85.5,
+                height: 85.5,
+              ).marginOnly(top: 45, bottom: 45),
+
+              // 登录表单 - 账号
+              _buildInputLayout(
+                context,
+                state,
+                "account",
+                textInputAction: TextInputAction.next,
+                errorText: state.accountErrorText,
+                onSubmit: (formKey, value) {
+                  state.formData[formKey]!['focusNode'].unfocus();
+                  FocusScope.of(context).requestFocus(state.formData['password']!['focusNode']);
+                },
+              ),
+
+              // 登录表单 - 密码
+              _buildInputLayout(
+                context,
+                state,
+                "password",
+                marginTop: 15,
+                obscureText: !state.pwdVisibility,
+                errorText: state.passwordErrorText,
+                showRightIcon: true,
+                rightWidget: IconButton(
+                  highlightColor: Colors.transparent,
+                  splashColor: Colors.transparent,
+                  icon: state.pwdVisibility
+                      ? const MyAssetImage(
+                          Assets.authPasswordHide,
+                          width: 22.5,
+                          height: 16.5,
+                        )
+                      : const MyAssetImage(
+                          Assets.authPasswordShow,
+                          width: 22.5,
+                          height: 16.5,
+                        ),
+                  onPressed: () {
+                    viewModel.switchPwdVisibility();
+                  },
+                ),
+                onSubmit: (formKey, value) {
+                  state.formData[formKey]!['focusNode'].unfocus();
+                  viewModel.doLogin();
+                },
+              ),
+
+              //登录按钮
+              MyButton(
+                onPressed: viewModel.doLogin,
+                text: S.current.login,
+                isEnabled: state.isLoginBtnEnable,
+                textColor: Colors.white,
+                disabledTextColor: Colors.white,
+                backgroundColor: context.appColors.btnBgDefault,
+                disabledBackgroundColor: context.appColors.btnBgDefault.withOpacity(0.2),
+                fontWeight: FontWeight.w500,
+                type: ClickType.throttle,
+                minHeight: 50,
+                radius: 5,
+              ).marginOnly(top: 20, bottom: 23),
+
+              //忘记密码
+              MyTextView(
+                S.current.forgot_password,
+                isFontMedium: true,
+                fontSize: 16,
+                textColor: context.appColors.textPrimary,
+                onClick: viewModel.gotoForgotPage,
+              ),
+
+              //创建账户-注册
+              MyButton(
+                onPressed: viewModel.gotoSignUpPage,
+                text: S.current.create_new_yy_home_account,
+                textColor: Colors.white,
+                backgroundColor: context.appColors.btnBgDefault,
+                fontWeight: FontWeight.w500,
+                type: ClickType.throttle,
+                minHeight: 50,
+                radius: 5,
+              ).marginOnly(top: 28, bottom: 30),
+
+              //同意协议
+              Row(
+                mainAxisSize: MainAxisSize.min,
+                children: [
+                  MyAssetImage(
+                    state.isAgreeTerms ? Assets.baseServiceCheckBoxChecked : Assets.baseServiceCheckBoxUncheck,
+                    width: 15.5,
+                    height: 15.5,
+                  ).onTap(viewModel.switchAgreeTerms, padding: 10),
+                  RichText(
+                    text: TextSpan(
+                      children: [
+                        TextSpan(
+                          text: S.current.agree_to,
+                          style: TextStyle(color: context.appColors.textDarkGray, fontWeight: FontWeight.w500, fontSize: 15), // 灰色文本
+                        ),
+                        const TextSpan(
+                          text: " ",
+                        ),
+                        TextSpan(
+                          text: S.current.terms_of_service,
+                          style: TextStyle(color: context.appColors.textPrimary, fontWeight: FontWeight.w500, fontSize: 15), // 蓝色文本
+                          recognizer: TapGestureRecognizer()..onTap = viewModel.gotoTermsPage,
+                        ),
+                      ],
+                    ),
+                  ),
+                ],
+              ),
+
+              //结束
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+
+  /// 输入框 账号与密码
+  Widget _buildInputLayout(
+    BuildContext context,
+    LoginState state,
+    String key, {
+    double marginTop = 0,
+    bool? showRightIcon = false, //是否展示右侧的布局
+    Widget? rightWidget, //右侧的布局
+    TextInputType textInputType = TextInputType.text,
+    String? errorText,
+    bool obscureText = false,
+    TextInputAction textInputAction = TextInputAction.done,
+    Function? onSubmit,
+  }) {
+    return IgnoreKeyboardDismiss(
+      child: MyTextField(
+        key,
+        fillBackgroundColor: context.appColors.authFiledBG,
+        state.formData[key]!['value'],
+        hintText: state.formData[key]!['hintText'],
+        hintStyle: TextStyle(
+          color: context.appColors.authFiledHint,
+          fontSize: 16.0,
+          fontWeight: FontWeight.w500,
+        ),
+        controller: state.formData[key]!['controller'],
+        focusNode: state.formData[key]!['focusNode'],
+        margin: EdgeInsets.only(top: marginTop),
+        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 3),
+        showDivider: false,
+        height: 44,
+        style: TextStyle(
+          color: context.appColors.authFiledText,
+          fontSize: 16.0,
+          fontWeight: FontWeight.w500,
+        ),
+        inputType: textInputType,
+        textInputAction: textInputAction,
+        onSubmit: onSubmit,
+        cursorColor: context.appColors.authFiledText,
+        obscureText: obscureText,
+        errorText: errorText,
+        showLeftIcon: true,
+        showRightIcon: showRightIcon,
+        rightWidget: rightWidget,
+      ),
+    );
+  }
+}

+ 70 - 0
packages/cpt_auth/lib/modules/auth_login/auth_login_state.dart

@@ -0,0 +1,70 @@
+/*
+ * 登录的状态类
+ */
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:flutter/material.dart';
+
+class LoginState {
+  //表单的校验与数据
+  final Map<String, Map<String, dynamic>> formData;
+
+  //表单的错误信息展示
+  String? accountErrorText;
+  String? passwordErrorText;
+
+  //是否明文展示密码
+  bool pwdVisibility;
+
+  //登录按钮是否可用
+  bool isLoginBtnEnable;
+
+  bool isAgreeTerms;
+
+  // ===================================  Begin  ↓  ===================================
+
+  LoginState({
+    Map<String, Map<String, dynamic>>? formData,
+    this.accountErrorText,
+    this.passwordErrorText,
+    this.pwdVisibility = false,
+    this.isLoginBtnEnable = false,
+    this.isAgreeTerms = false,
+  }) : formData = formData ??
+            {
+              'account': {
+                'value': '',
+                'controller': TextEditingController(),
+                'hintText': S.current.phone_email,
+                'focusNode': FocusNode(),
+                'obsecure': false,
+              },
+              'password': {
+                'value': '',
+                'controller': TextEditingController(),
+                'hintText': S.current.password,
+                'focusNode': FocusNode(),
+                'obsecure': true,
+              },
+            };
+
+  LoginState copyWith({
+    String? accountErrorText,
+    String? passwordErrorText,
+    String? account,
+    String? password,
+    bool? pwdVisibility,
+    bool? isLoginBtnEnable,
+    bool? isAgreeTerms,
+  }) {
+    return LoginState(
+      formData: this.formData,
+      accountErrorText: accountErrorText,
+      passwordErrorText: passwordErrorText,
+      pwdVisibility: pwdVisibility ?? this.pwdVisibility,
+      isLoginBtnEnable: isLoginBtnEnable ?? this.isLoginBtnEnable,
+      isAgreeTerms: isAgreeTerms ?? this.isLoginBtnEnable,
+    );
+  }
+
+
+}

+ 131 - 0
packages/cpt_auth/lib/modules/auth_login/auth_login_view_model.dart

@@ -0,0 +1,131 @@
+import 'package:cpt_auth/modules/sign_up/sign_up_page.dart';
+import 'package:flutter/material.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/util.dart';
+
+import '../forgot_input/forgot_input_page.dart';
+import 'auth_login_state.dart';
+
+part 'auth_login_view_model.g.dart';
+
+@riverpod
+class AuthLoginViewModel extends _$AuthLoginViewModel {
+  @override
+  LoginState build() {
+    final state = LoginState();
+
+    initListener(state);
+    ref.onDispose(() {
+      onDispose(state);
+    });
+    return state;
+  }
+
+  //切换是否隐藏密码
+  void switchPwdVisibility() {
+    state = state.copyWith(pwdVisibility: !state.pwdVisibility);
+  }
+
+  //执行用户的登录
+  void doLogin() {
+    state = state.copyWith(accountErrorText: null, passwordErrorText: null);
+
+    final FocusNode accountFocusNode = state.formData['account']!['focusNode'];
+    final FocusNode passwordFocusNode = state.formData['password']!['focusNode'];
+    final TextEditingController accountController = state.formData['account']!['controller'];
+    final TextEditingController passwordController = state.formData['password']!['controller'];
+
+    accountFocusNode.unfocus();
+    passwordFocusNode.unfocus();
+
+    final account = accountController.text;
+    final password = passwordController.text;
+
+    Log.d('当前待提交的 账号:${account} password:${password}');
+
+    if (Utils.isEmpty(account)) {
+      state = state.copyWith(accountErrorText: "Phone/Email cannot be empty!");
+      return;
+    }
+
+    if (Utils.isEmpty(password)) {
+      state = state.copyWith(passwordErrorText: "Password cannot be empty!");
+      return;
+    }
+
+    //执行密码登录
+    ToastEngine.show('准备执行请求 账号:${account} password:${password}');
+  }
+
+  //去协议页面
+  void gotoTermsPage() {
+    ToastEngine.show("去协议页面");
+  }
+
+  //去忘记密码页面
+  void gotoForgotPage() {
+    ForgotInputPage.startInstance();
+  }
+
+  //去注册页面
+  void gotoSignUpPage() {
+    SignUpPage.startInstance();
+  }
+
+  //切换同意按钮
+  void switchAgreeTerms(){
+    state = state.copyWith(isAgreeTerms: !state.isAgreeTerms);
+  }
+
+  //初始化监听
+  void initListener(LoginState initState) {
+    final FocusNode accountFocusNode = initState.formData['account']!['focusNode'];
+    final FocusNode passwordFocusNode = initState.formData['password']!['focusNode'];
+    final TextEditingController accountController = initState.formData['account']!['controller'];
+    final TextEditingController passwordController = initState.formData['password']!['controller'];
+
+    accountFocusNode.addListener(() {
+      // 获取焦点的时候清空错误文本
+      if (accountFocusNode.hasFocus) {
+        state = state.copyWith(accountErrorText: null);
+      }
+    });
+
+    passwordFocusNode.addListener(() {
+      // 获取焦点的时候清空错误文本
+      if (passwordFocusNode.hasFocus) {
+        state = state.copyWith(passwordErrorText: null);
+      }
+    });
+
+    //文本框的监听输入
+    accountController.addListener(() {
+      _updateButtonState(accountController, passwordController);
+    });
+
+    passwordController.addListener(() {
+      _updateButtonState(accountController, passwordController);
+    });
+  }
+
+  //当 Account 和 Password 都有值才能按钮可用
+  void _updateButtonState(TextEditingController accountController, TextEditingController passwordController) {
+    state = state.copyWith(isLoginBtnEnable: accountController.text.isNotEmpty && passwordController.text.isNotEmpty);
+  }
+
+  //销毁资源
+  void onDispose(LoginState initState) {
+    final FocusNode accountFocusNode = initState.formData['account']!['focusNode'];
+    final FocusNode passwordFocusNode = initState.formData['password']!['focusNode'];
+    final TextEditingController accountController = initState.formData['account']!['controller'];
+    final TextEditingController passwordController = initState.formData['password']!['controller'];
+    accountFocusNode.dispose();
+    passwordFocusNode.dispose();
+    accountController.dispose();
+    passwordController.dispose();
+    Log.d("LoginViewModel 销毁 onDispose");
+  }
+
+}

+ 3 - 3
packages/cpt_auth/lib/modules/auth_login/vm/auth_login_view_model.g.dart

@@ -7,12 +7,12 @@ part of 'auth_login_view_model.dart';
 // **************************************************************************
 
 String _$authLoginViewModelHash() =>
-    r'10a37f5f6fead251c1df197123d10ce07fe0594c';
+    r'1556a80c857673abab8a1062452673469ca2aa1e';
 
 /// See also [AuthLoginViewModel].
 @ProviderFor(AuthLoginViewModel)
 final authLoginViewModelProvider =
-    AutoDisposeNotifierProvider<AuthLoginViewModel, void>.internal(
+    AutoDisposeNotifierProvider<AuthLoginViewModel, LoginState>.internal(
   AuthLoginViewModel.new,
   name: r'authLoginViewModelProvider',
   debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
@@ -22,6 +22,6 @@ final authLoginViewModelProvider =
   allTransitiveDependencies: null,
 );
 
-typedef _$AuthLoginViewModel = AutoDisposeNotifier<void>;
+typedef _$AuthLoginViewModel = AutoDisposeNotifier<LoginState>;
 // ignore_for_file: type=lint
 // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package

+ 0 - 34
packages/cpt_auth/lib/modules/auth_login/page/Profile_edit_page.dart

@@ -1,34 +0,0 @@
-
-import 'package:flutter/material.dart';
-import 'package:auto_route/auto_route.dart';
-import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:router/ext/auto_router_extensions.dart';
-
-import '../../../router/page/auth_page_router.dart';
-import '../vm/auth_login_view_model.dart';
-
-@RoutePage()
-class AuthLoginPage extends HookConsumerWidget {
-  const AuthLoginPage({Key? key}) : super(key: key);
-
-  //启动当前页面
-  static void startInstance({BuildContext? context}) {
-    if (context != null) {
-      context.router.push(const AuthLoginPageRoute());
-    } else {
-      appRouter.push(const AuthLoginPageRoute());
-    }
-  }
-
-  @override
-  Widget build(BuildContext context, WidgetRef ref) {
-    final _viewModel = ref.read(authLoginViewModelProvider.notifier);
-
-    return Scaffold(
-      appBar: AppBar(title: Text("登录")),
-      body: Center(
-        child: Text("用户登录页面"),
-      ),
-    );
-  }
-}

+ 0 - 14
packages/cpt_auth/lib/modules/auth_login/vm/auth_login_view_model.dart

@@ -1,14 +0,0 @@
-
-import 'package:riverpod_annotation/riverpod_annotation.dart';
-
-part 'auth_login_view_model.g.dart';
-
-@riverpod
-class AuthLoginViewModel extends _$AuthLoginViewModel {
-
-  @override
-  void build(){
-
-  }
-
-}

+ 182 - 0
packages/cpt_auth/lib/modules/forgot_input/forgot_input_page.dart

@@ -0,0 +1,182 @@
+import 'package:cpt_auth/modules/auth_login/auth_login_page.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_button.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_field.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/widget_export.dart';
+
+import '../../router/page/auth_page_router.dart';
+import 'forgot_input_state.dart';
+import 'forgot_input_view_model.dart';
+
+@RoutePage()
+class ForgotInputPage extends HookConsumerWidget {
+  const ForgotInputPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const ForgotInputPageRoute());
+    } else {
+      appRouter.push(const ForgotInputPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(forgotInputViewModelProvider.notifier);
+    final state = ref.watch(forgotInputViewModelProvider);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(context, ""),
+      backgroundColor: context.appColors.backgroundDefault,
+      body: SingleChildScrollView(
+        scrollDirection: Axis.vertical,
+        physics: const BouncingScrollPhysics(),
+        child: Container(
+          margin: const EdgeInsets.symmetric(horizontal: 38),
+          width: double.infinity,
+          child: Column(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              //顶部图片
+              const MyAssetImage(
+                Assets.authForgotInputEmailPhoneImg,
+                width: 260,
+                height: 170,
+              ).marginOnly(top: 25, bottom: 29),
+
+              //提示文本
+              MyTextView(
+                S.current.forgot_text,
+                fontSize: 24,
+                marginBottom: 23,
+                isFontMedium: true,
+                textColor: context.appColors.textBlack,
+              ),
+
+              //邮箱输入框
+              _buildInputLayout(
+                context,
+                state,
+                "email",
+                textInputType: TextInputType.emailAddress,
+                textInputAction: TextInputAction.next,
+                errorText: state.emailErrorText,
+                onSubmit: (formKey, value) {
+                  state.formData[formKey]!['focusNode'].unfocus();
+                  FocusScope.of(context).requestFocus(state.formData['phone']!['focusNode']);
+                },
+              ),
+
+              //电话号码
+              Row(
+                mainAxisSize: MainAxisSize.max,
+                crossAxisAlignment: CrossAxisAlignment.center,
+                children: [
+                  const MyAssetImage(
+                    Assets.authCountrySg,
+                    width: 45,
+                    height: 30,
+                  ),
+                  MyTextView(
+                    "+65",
+                    textColor: context.appColors.textBlack,
+                    fontSize: 20,
+                    marginLeft: 15,
+                    marginRight: 12,
+                    isFontMedium: true,
+                  ),
+                  //电话输入框
+                  _buildInputLayout(
+                    context,
+                    state,
+                    "phone",
+                    textInputType: TextInputType.number,
+                    textInputAction: TextInputAction.done,
+                    errorText: state.phoneErrorText,
+                    onSubmit: (formKey, value) {
+                      state.formData[formKey]!['focusNode'].unfocus();
+                      viewModel.submitInput();
+                    },
+                  ).expanded(),
+                ],
+              ).marginOnly(top: 15),
+
+              MyButton(
+                onPressed: viewModel.submitInput,
+                text: S.current.next,
+                textColor: Colors.white,
+                backgroundColor: context.appColors.btnBgDefault,
+                fontWeight: FontWeight.w500,
+                type: ClickType.throttle,
+                fontSize: 16,
+                minHeight: 50,
+                radius: 5,
+              ).marginOnly(top: 25, bottom: 30),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+
+  /// 输入框
+  Widget _buildInputLayout(
+    BuildContext context,
+    ForgotInputState state,
+    String key, {
+    double marginTop = 0,
+    bool? showRightIcon = false, //是否展示右侧的布局
+    Widget? rightWidget, //右侧的布局
+    TextInputType textInputType = TextInputType.text,
+    String? errorText,
+    bool obscureText = false,
+    TextInputAction textInputAction = TextInputAction.done,
+    Function? onSubmit,
+  }) {
+    return IgnoreKeyboardDismiss(
+      child: MyTextField(
+        key,
+        fillBackgroundColor: context.appColors.authFiledBG,
+        state.formData[key]!['value'],
+        hintText: state.formData[key]!['hintText'],
+        hintStyle: TextStyle(
+          color: context.appColors.authFiledHint,
+          fontSize: 16.0,
+          fontWeight: FontWeight.w500,
+        ),
+        controller: state.formData[key]!['controller'],
+        focusNode: state.formData[key]!['focusNode'],
+        margin: EdgeInsets.only(top: marginTop),
+        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 3),
+        showDivider: false,
+        height: 44,
+        style: TextStyle(
+          color: context.appColors.authFiledText,
+          fontSize: 16.0,
+          fontWeight: FontWeight.w500,
+        ),
+        inputType: textInputType,
+        textInputAction: textInputAction,
+        onSubmit: onSubmit,
+        cursorColor: context.appColors.authFiledText,
+        obscureText: obscureText,
+        errorText: errorText,
+        showLeftIcon: true,
+        showRightIcon: showRightIcon,
+        rightWidget: rightWidget,
+      ),
+    );
+  }
+}

+ 50 - 0
packages/cpt_auth/lib/modules/forgot_input/forgot_input_state.dart

@@ -0,0 +1,50 @@
+/*
+ * 登录的状态类
+ */
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:flutter/material.dart';
+
+class ForgotInputState {
+  //表单的校验与数据
+  final Map<String, Map<String, dynamic>> formData;
+
+  //表单的错误信息展示
+  String? emailErrorText;
+  String? phoneErrorText;
+
+
+  // ===================================  Begin  ↓  ===================================
+
+  ForgotInputState({
+    Map<String, Map<String, dynamic>>? formData,
+    this.emailErrorText,
+    this.phoneErrorText,
+  }) : formData = formData ??
+      {
+        'email': {
+          'value': '',
+          'controller': TextEditingController(),
+          'hintText': S.current.email,
+          'focusNode': FocusNode(),
+          'obsecure': false,
+        },
+        'phone': {
+          'value': '',
+          'controller': TextEditingController(),
+          'hintText': S.current.mobile_phone,
+          'focusNode': FocusNode(),
+          'obsecure': false,
+        },
+      };
+
+  ForgotInputState copyWith({
+    String? emailErrorText,
+    String? phoneErrorText,
+  }) {
+    return ForgotInputState(
+      formData: this.formData,
+      emailErrorText: emailErrorText,
+      phoneErrorText: phoneErrorText,
+    );
+  }
+}

+ 91 - 0
packages/cpt_auth/lib/modules/forgot_input/forgot_input_view_model.dart

@@ -0,0 +1,91 @@
+import 'package:cpt_auth/modules/forgot_verify/forgot_verify_page.dart';
+import 'package:flutter/material.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/util.dart';
+
+import 'forgot_input_state.dart';
+
+part 'forgot_input_view_model.g.dart';
+
+@riverpod
+class ForgotInputViewModel extends _$ForgotInputViewModel {
+  @override
+  ForgotInputState build() {
+    final state = ForgotInputState();
+    initListener(state);
+    ref.onDispose(() {
+      onDispose(state);
+    });
+    return state;
+  }
+
+  //提交忘记密码表单,发送验证码
+  void submitInput() {
+    state = state.copyWith(emailErrorText: null, phoneErrorText: null);
+
+    final FocusNode emailFocusNode = state.formData['email']!['focusNode'];
+    final FocusNode phoneFocusNode = state.formData['phone']!['focusNode'];
+    final TextEditingController emailController = state.formData['email']!['controller'];
+    final TextEditingController phoneController = state.formData['phone']!['controller'];
+
+    emailFocusNode.unfocus();
+    phoneFocusNode.unfocus();
+
+    final email = emailController.text;
+    final phone = phoneController.text;
+
+    Log.d('当前待提交的 邮箱:${email} 电话:${phone}');
+
+    // if (Utils.isEmpty(email)) {
+    //   state = state.copyWith(emailErrorText: "Email cannot be empty!");
+    //   return;
+    // }
+    //
+    // if (Utils.isEmpty(phone)) {
+    //   state = state.copyWith(phoneErrorText: "Phone cannot be empty!");
+    //   return;
+    // }
+
+    //执行密码登录
+    ToastEngine.show('准备执行请求发送验证码 邮箱:${email} 电话:${phone}');
+
+    gotoForgotVerifyPage();
+  }
+
+  //去忘记密码验证页面
+  void gotoForgotVerifyPage() {
+    ForgotVerifyPage.startInstance();
+  }
+
+  //初始化监听
+  void initListener(ForgotInputState initState) {
+    final FocusNode emailFocusNode = initState.formData['email']!['focusNode'];
+    final FocusNode phoneFocusNode = initState.formData['phone']!['focusNode'];
+
+    emailFocusNode.addListener(() {
+      // 获取焦点的时候清空错误文本
+      if (emailFocusNode.hasFocus) {
+        state = state.copyWith(emailErrorText: null);
+      }
+    });
+
+    phoneFocusNode.addListener(() {
+      // 获取焦点的时候清空错误文本
+      if (phoneFocusNode.hasFocus) {
+        state = state.copyWith(phoneErrorText: null);
+      }
+    });
+  }
+
+  //销毁资源
+  void onDispose(ForgotInputState initState) {
+    final FocusNode emailFocusNode = initState.formData['email']!['focusNode'];
+    final FocusNode phoneFocusNode = initState.formData['phone']!['focusNode'];
+    emailFocusNode.dispose();
+    phoneFocusNode.dispose();
+    Log.d("ForgotInputViewModel 销毁 onDispose");
+  }
+
+}

+ 27 - 0
packages/cpt_auth/lib/modules/forgot_input/forgot_input_view_model.g.dart

@@ -0,0 +1,27 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'forgot_input_view_model.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$forgotInputViewModelHash() =>
+    r'5998f4831003ebb7e6ebe822bc002580f13b1962';
+
+/// See also [ForgotInputViewModel].
+@ProviderFor(ForgotInputViewModel)
+final forgotInputViewModelProvider = AutoDisposeNotifierProvider<
+    ForgotInputViewModel, ForgotInputState>.internal(
+  ForgotInputViewModel.new,
+  name: r'forgotInputViewModelProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$forgotInputViewModelHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$ForgotInputViewModel = AutoDisposeNotifier<ForgotInputState>;
+// ignore_for_file: type=lint
+// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package

+ 232 - 0
packages/cpt_auth/lib/modules/forgot_verify/forgot_verify_page.dart

@@ -0,0 +1,232 @@
+import 'package:cpt_auth/modules/forgot_verify/forgot_verify_state.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_button.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_field.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/widget_export.dart';
+
+import '../../router/page/auth_page_router.dart';
+import 'forgot_verify_view_model.dart';
+
+@RoutePage()
+class ForgotVerifyPage extends HookConsumerWidget {
+  const ForgotVerifyPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const ForgotVerifyPageRoute());
+    } else {
+      appRouter.push(const ForgotVerifyPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(forgotVerifyViewModelProvider.notifier);
+    final state = ref.watch(forgotVerifyViewModelProvider);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(context, ""),
+      backgroundColor: context.appColors.backgroundDefault,
+      body: SingleChildScrollView(
+        scrollDirection: Axis.vertical,
+        physics: const BouncingScrollPhysics(),
+        child: Container(
+          margin: const EdgeInsets.symmetric(horizontal: 38),
+          width: double.infinity,
+          child: Column(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              //顶部图片
+              const MyAssetImage(
+                Assets.authForgotResetPasswordImg,
+                width: 260,
+                height: 170,
+              ).marginOnly(top: 25, bottom: 29),
+
+              //提示文本
+              MyTextView(
+                S.current.mobile_phone,
+                fontSize: 15,
+                marginBottom: 23,
+                isFontMedium: true,
+                textColor: context.appColors.textBlack,
+              ),
+
+              MyTextView(
+                "+65 88249621",
+                fontSize: 23,
+                marginBottom: 23,
+                isFontMedium: true,
+                textColor: context.appColors.textBlack,
+              ),
+
+              // 表单 - 验证码
+              _buildInputLayout(
+                context,
+                state,
+                "code",
+                textInputType: TextInputType.number,
+                textInputAction: TextInputAction.next,
+                errorText: state.codeErrorText,
+                showRightIcon: true,
+                rightWidget: MyTextView(
+                  state.isCounting? "${state.countdownTime} s": S.current.get_code,
+                  textAlign: TextAlign.center,
+                  textColor: context.appColors.textPrimary,
+                  fontSize: 15,
+                  paddingRight: 5,
+                  isFontMedium: true,
+                  onClick: state.isCounting ? null : () => viewModel.showVerifyCodedDialog(),
+                ).paddingOnly(top: 15, bottom: 15),
+                onSubmit: (formKey, value) {
+                  state.formData[formKey]!['focusNode'].unfocus();
+                  FocusScope.of(context).requestFocus(state.formData['password']!['focusNode']);
+                },
+              ),
+
+              // 表单 - 重置密码
+              _buildInputLayout(
+                context,
+                state,
+                "password",
+                marginTop: 15,
+                obscureText: !state.pwdVisibility,
+                errorText: state.passwordErrorText,
+                textInputAction: TextInputAction.next,
+                showRightIcon: true,
+                rightWidget: IconButton(
+                  highlightColor: Colors.transparent,
+                  splashColor: Colors.transparent,
+                  icon: state.pwdVisibility
+                      ? const MyAssetImage(
+                          Assets.authPasswordHide,
+                          width: 22.5,
+                          height: 16.5,
+                        )
+                      : const MyAssetImage(
+                          Assets.authPasswordShow,
+                          width: 22.5,
+                          height: 16.5,
+                        ),
+                  onPressed: () {
+                    viewModel.switchPwdVisibility();
+                  },
+                ),
+                onSubmit: (formKey, value) {
+                  state.formData[formKey]!['focusNode'].unfocus();
+                  FocusScope.of(context).requestFocus(state.formData['confirm_password']!['focusNode']);
+                },
+              ),
+
+              // 表单 - 确认密码
+              _buildInputLayout(
+                context,
+                state,
+                "confirm_password",
+                marginTop: 15,
+                obscureText: !state.confirmPwdVisibility,
+                errorText: state.confirmPasswordErrorText,
+                showRightIcon: true,
+                rightWidget: IconButton(
+                  highlightColor: Colors.transparent,
+                  splashColor: Colors.transparent,
+                  icon: state.confirmPwdVisibility
+                      ? const MyAssetImage(
+                          Assets.authPasswordHide,
+                          width: 22.5,
+                          height: 16.5,
+                        )
+                      : const MyAssetImage(
+                          Assets.authPasswordShow,
+                          width: 22.5,
+                          height: 16.5,
+                        ),
+                  onPressed: () {
+                    viewModel.switchConfirmPwdVisibility();
+                  },
+                ),
+                onSubmit: (formKey, value) {
+                  state.formData[formKey]!['focusNode'].unfocus();
+                  viewModel.submitVerify();
+                },
+              ),
+
+              MyButton(
+                onPressed: viewModel.submitVerify,
+                text: S.current.next,
+                textColor: Colors.white,
+                backgroundColor: context.appColors.btnBgDefault,
+                fontWeight: FontWeight.w500,
+                type: ClickType.throttle,
+                fontSize: 16,
+                minHeight: 50,
+                radius: 5,
+              ).marginOnly(top: 25, bottom: 30),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+
+  /// 输入框
+  Widget _buildInputLayout(
+    BuildContext context,
+    ForgotVerifyState state,
+    String key, {
+    double marginTop = 0,
+    bool? showRightIcon = false, //是否展示右侧的布局
+    Widget? rightWidget, //右侧的布局
+    TextInputType textInputType = TextInputType.text,
+    String? errorText,
+    bool obscureText = false,
+    TextInputAction textInputAction = TextInputAction.done,
+    Function? onSubmit,
+  }) {
+    return IgnoreKeyboardDismiss(
+      child: MyTextField(
+        key,
+        fillBackgroundColor: context.appColors.authFiledBG,
+        state.formData[key]!['value'],
+        hintText: state.formData[key]!['hintText'],
+        hintStyle: TextStyle(
+          color: context.appColors.authFiledHint,
+          fontSize: 16.0,
+          fontWeight: FontWeight.w500,
+        ),
+        controller: state.formData[key]!['controller'],
+        focusNode: state.formData[key]!['focusNode'],
+        margin: EdgeInsets.only(top: marginTop),
+        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 3),
+        showDivider: false,
+        height: 44,
+        style: TextStyle(
+          color: context.appColors.authFiledText,
+          fontSize: 16.0,
+          fontWeight: FontWeight.w500,
+        ),
+        inputType: textInputType,
+        textInputAction: textInputAction,
+        onSubmit: onSubmit,
+        cursorColor: context.appColors.authFiledText,
+        obscureText: obscureText,
+        errorText: errorText,
+        showLeftIcon: true,
+        showRightIcon: showRightIcon,
+        rightWidget: rightWidget,
+      ),
+    );
+  }
+}

+ 78 - 0
packages/cpt_auth/lib/modules/forgot_verify/forgot_verify_state.dart

@@ -0,0 +1,78 @@
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:flutter/material.dart';
+
+class ForgotVerifyState {
+  //表单的校验与数据
+  final Map<String, Map<String, dynamic>> formData;
+
+  //表单的错误信息展示
+  String? codeErrorText;
+  String? passwordErrorText;
+  String? confirmPasswordErrorText;
+
+  //是否明文展示密码
+  bool pwdVisibility;
+
+  bool confirmPwdVisibility;
+
+  //获取验证码的倒计时
+  bool isCounting;
+  int countdownTime;
+
+  // ===================================  Begin  ↓  ===================================
+
+  ForgotVerifyState({
+    Map<String, Map<String, dynamic>>? formData,
+    this.pwdVisibility = false,
+    this.confirmPwdVisibility = false,
+    this.isCounting = false,
+    this.countdownTime = 0,
+    this.codeErrorText,
+    this.passwordErrorText,
+    this.confirmPasswordErrorText,
+  }) : formData = formData ??
+            {
+              'code': {
+                'value': '',
+                'controller': TextEditingController(),
+                'hintText': S.current.verification_code,
+                'focusNode': FocusNode(),
+                'obsecure': false,
+              },
+              'password': {
+                'value': '',
+                'controller': TextEditingController(),
+                'hintText': S.current.reset_password,
+                'focusNode': FocusNode(),
+                'obsecure': true,
+              },
+              'confirm_password': {
+                'value': '',
+                'controller': TextEditingController(),
+                'hintText': S.current.confirm_password,
+                'focusNode': FocusNode(),
+                'obsecure': true,
+              },
+            };
+
+  ForgotVerifyState copyWith({
+    String? codeErrorText,
+    String? passwordErrorText,
+    String? confirmPasswordErrorText,
+    bool? pwdVisibility,
+    bool? confirmPwdVisibility,
+    bool? isCounting,
+    int? countdownTime,
+  }) {
+    return ForgotVerifyState(
+      formData: this.formData,
+      pwdVisibility: pwdVisibility ?? this.pwdVisibility,
+      confirmPwdVisibility: confirmPwdVisibility ?? this.confirmPwdVisibility,
+      isCounting: isCounting ?? this.isCounting,
+      countdownTime: countdownTime ?? this.countdownTime,
+      codeErrorText: codeErrorText,
+      passwordErrorText: passwordErrorText,
+      confirmPasswordErrorText: confirmPasswordErrorText,
+    );
+  }
+}

+ 155 - 0
packages/cpt_auth/lib/modules/forgot_verify/forgot_verify_view_model.dart

@@ -0,0 +1,155 @@
+import 'dart:async';
+
+import 'package:flutter/material.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/util.dart';
+
+import '../auth_login/auth_login_page.dart';
+import 'forgot_verify_state.dart';
+
+part 'forgot_verify_view_model.g.dart';
+
+@riverpod
+class ForgotVerifyViewModel extends _$ForgotVerifyViewModel {
+  @override
+  ForgotVerifyState build() {
+    final state = ForgotVerifyState();
+    initListener(state);
+    ref.onDispose(() {
+      onDispose(state);
+    });
+    return state;
+  }
+
+  //提交重置密码的校验
+  void submitVerify() {
+    state = state.copyWith(codeErrorText: null, passwordErrorText: null, confirmPasswordErrorText: null);
+
+    final FocusNode codeFocusNode = state.formData['code']!['focusNode'];
+    final FocusNode passwordFocusNode = state.formData['password']!['focusNode'];
+    final FocusNode confirmPasswordFocusNode = state.formData['confirm_password']!['focusNode'];
+
+    final TextEditingController codeController = state.formData['code']!['controller'];
+    final TextEditingController passwordController = state.formData['password']!['controller'];
+    final TextEditingController confirmPasswordController = state.formData['confirm_password']!['controller'];
+
+    codeFocusNode.unfocus();
+    passwordFocusNode.unfocus();
+    confirmPasswordFocusNode.unfocus();
+
+    final code = codeController.text;
+    final password = passwordController.text;
+    final confirmPassword = confirmPasswordController.text;
+
+    Log.d('当前待提交的 code:$code password:$password confirmPassword:$confirmPassword');
+
+    if (Utils.isEmpty(code)) {
+      state = state.copyWith(codeErrorText: "Verification Code cannot be empty!");
+      return;
+    }
+
+    if (Utils.isEmpty(password)) {
+      state = state.copyWith(passwordErrorText: "Password cannot be empty!");
+      return;
+    }
+
+    if (Utils.isEmpty(confirmPassword)) {
+      state = state.copyWith(confirmPasswordErrorText: "Confirm Password cannot be empty!");
+      return;
+    }
+
+    if (confirmPassword != password) {
+      state = state.copyWith(confirmPasswordErrorText: "Password mismatch, please check password");
+      return;
+    }
+
+    //执行密码登录
+    ToastEngine.show('准备执行请求发送验证码 code:$code password:$password confirmPassword:$confirmPassword');
+
+    gotoLoginPage();
+  }
+
+  //去登录页面
+  void gotoLoginPage() {
+    AuthLoginPage.startInstance();
+  }
+
+  //切换隐藏显示密码
+  void switchPwdVisibility() {
+    state = state.copyWith(pwdVisibility: !state.pwdVisibility);
+  }
+
+  void switchConfirmPwdVisibility() {
+    state = state.copyWith(confirmPwdVisibility: !state.confirmPwdVisibility);
+  }
+
+  // 验证弹窗
+  void showVerifyCodedDialog() {
+    _startCountDown();
+  }
+
+  Timer? countdownTimer;
+
+  /// 开启倒计时
+  void _startCountDown() {
+    //60秒倒计时
+    state = state.copyWith(isCounting: true, countdownTime: 60);
+
+    //每秒的倒计时
+    countdownTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
+      int time = state.countdownTime;
+      Log.d('倒计时-->$time');
+      if (time > 0) {
+        time--;
+        state = state.copyWith(isCounting: true, countdownTime: time);
+      } else {
+        state = state.copyWith(isCounting: false, countdownTime: 0);
+        countdownTimer?.cancel(); // 取消计时器
+      }
+    });
+  }
+
+  //初始化监听
+  void initListener(ForgotVerifyState initState) {
+    final FocusNode codeFocusNode = initState.formData['code']!['focusNode'];
+    final FocusNode passwordFocusNode = initState.formData['password']!['focusNode'];
+    final FocusNode confirmPasswordFocusNode = initState.formData['confirm_password']!['focusNode'];
+
+    codeFocusNode.addListener(() {
+      // 获取焦点的时候清空错误文本
+      if (codeFocusNode.hasFocus) {
+        state = state.copyWith(codeErrorText: null);
+      }
+    });
+
+    passwordFocusNode.addListener(() {
+      // 获取焦点的时候清空错误文本
+      if (passwordFocusNode.hasFocus) {
+        state = state.copyWith(passwordErrorText: null);
+      }
+    });
+
+    confirmPasswordFocusNode.addListener(() {
+      // 获取焦点的时候清空错误文本
+      if (confirmPasswordFocusNode.hasFocus) {
+        state = state.copyWith(confirmPasswordErrorText: null);
+      }
+    });
+  }
+
+  //销毁资源
+  void onDispose(ForgotVerifyState initState) {
+    final FocusNode codeFocusNode = initState.formData['code']!['focusNode'];
+    final FocusNode passwordFocusNode = initState.formData['password']!['focusNode'];
+    final FocusNode confirmPasswordFocusNode = initState.formData['confirm_password']!['focusNode'];
+    codeFocusNode.dispose();
+    passwordFocusNode.dispose();
+    confirmPasswordFocusNode.dispose();
+
+    countdownTimer?.cancel();
+
+    Log.d("ForgotVerifyViewModel 销毁 onDispose");
+  }
+}

+ 27 - 0
packages/cpt_auth/lib/modules/forgot_verify/forgot_verify_view_model.g.dart

@@ -0,0 +1,27 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'forgot_verify_view_model.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$forgotVerifyViewModelHash() =>
+    r'9ca96e6da48e893d90ed8b0dc939ebae4c1fb940';
+
+/// See also [ForgotVerifyViewModel].
+@ProviderFor(ForgotVerifyViewModel)
+final forgotVerifyViewModelProvider = AutoDisposeNotifierProvider<
+    ForgotVerifyViewModel, ForgotVerifyState>.internal(
+  ForgotVerifyViewModel.new,
+  name: r'forgotVerifyViewModelProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$forgotVerifyViewModelHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$ForgotVerifyViewModel = AutoDisposeNotifier<ForgotVerifyState>;
+// ignore_for_file: type=lint
+// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package

+ 304 - 0
packages/cpt_auth/lib/modules/sign_up/sign_up_page.dart

@@ -0,0 +1,304 @@
+
+import 'package:cpt_auth/modules/sign_up/sign_up_state.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/gestures.dart';
+import 'package:flutter/material.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_button.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_field.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/widget_export.dart';
+
+import '../../router/page/auth_page_router.dart';
+import 'sign_up_view_model.dart';
+
+@RoutePage()
+class SignUpPage extends HookConsumerWidget {
+  const SignUpPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const SignUpPageRoute());
+    } else {
+      appRouter.push(const SignUpPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(signUpViewModelProvider.notifier);
+    final state = ref.watch(signUpViewModelProvider);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(context, ""),
+      backgroundColor: context.appColors.backgroundDefault,
+      body: SingleChildScrollView(
+        scrollDirection: Axis.vertical,
+        physics: const BouncingScrollPhysics(),
+        child: Container(
+          margin: const EdgeInsets.symmetric(horizontal: 38),
+          width: double.infinity,
+          child: Column(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              //顶部图片
+              const MyAssetImage(
+                Assets.authSignUpInputImg,
+                width: 260,
+                height: 170,
+              ).marginOnly(top: 22, bottom: 34),
+
+              // 表单 - 名
+              _buildInputLayout(
+                context,
+                state,
+                "first_name",
+                textInputType: TextInputType.text,
+                textInputAction: TextInputAction.next,
+                errorText: state.firstNameErrorText,
+                onSubmit: (formKey, value) {
+                  state.formData[formKey]!['focusNode'].unfocus();
+                  FocusScope.of(context).requestFocus(state.formData['last_name']!['focusNode']);
+                },
+              ),
+
+              // 表单 - 姓
+              _buildInputLayout(
+                context,
+                state,
+                "last_name",
+                marginTop: 15,
+                textInputType: TextInputType.text,
+                textInputAction: TextInputAction.next,
+                errorText: state.lastNameErrorText,
+                onSubmit: (formKey, value) {
+                  state.formData[formKey]!['focusNode'].unfocus();
+                  FocusScope.of(context).requestFocus(state.formData['email']!['focusNode']);
+                },
+              ),
+
+              // 表单 - 邮箱
+              _buildInputLayout(
+                context,
+                state,
+                "email",
+                marginTop: 15,
+                textInputType: TextInputType.emailAddress,
+                textInputAction: TextInputAction.next,
+                errorText: state.emailErrorText,
+                onSubmit: (formKey, value) {
+                  state.formData[formKey]!['focusNode'].unfocus();
+                  FocusScope.of(context).requestFocus(state.formData['phone']!['focusNode']);
+                },
+              ),
+
+              // 表单 - 电话
+              Row(
+                mainAxisSize: MainAxisSize.max,
+                crossAxisAlignment: CrossAxisAlignment.center,
+                children: [
+                  const MyAssetImage(
+                    Assets.authCountrySg,
+                    width: 45,
+                    height: 30,
+                  ),
+                  MyTextView(
+                    "+65",
+                    textColor: context.appColors.textBlack,
+                    fontSize: 20,
+                    marginLeft: 15,
+                    marginRight: 12,
+                    isFontMedium: true,
+                  ),
+                  //电话输入框
+                  _buildInputLayout(
+                    context,
+                    state,
+                    "phone",
+                    marginTop: 15,
+                    textInputType: TextInputType.number,
+                    textInputAction: TextInputAction.next,
+                    errorText: state.phoneErrorText,
+                    onSubmit: (formKey, value) {
+                      state.formData[formKey]!['focusNode'].unfocus();
+                      FocusScope.of(context).requestFocus(state.formData['password']!['focusNode']);
+                    },
+                  ).expanded(),
+                ],
+              ),
+
+              // 表单 - 重置密码
+              _buildInputLayout(
+                context,
+                state,
+                "password",
+                marginTop: 15,
+                obscureText: !state.pwdVisibility,
+                errorText: state.passwordErrorText,
+                textInputAction: TextInputAction.next,
+                showRightIcon: true,
+                rightWidget: IconButton(
+                  highlightColor: Colors.transparent,
+                  splashColor: Colors.transparent,
+                  icon: state.pwdVisibility
+                      ? const MyAssetImage(
+                    Assets.authPasswordHide,
+                    width: 22.5,
+                    height: 16.5,
+                  )
+                      : const MyAssetImage(
+                    Assets.authPasswordShow,
+                    width: 22.5,
+                    height: 16.5,
+                  ),
+                  onPressed: () {
+                    viewModel.switchPwdVisibility();
+                  },
+                ),
+                onSubmit: (formKey, value) {
+                  state.formData[formKey]!['focusNode'].unfocus();
+                  FocusScope.of(context).requestFocus(state.formData['confirm_password']!['focusNode']);
+                },
+              ),
+
+              // 表单 - 确认密码
+              _buildInputLayout(
+                context,
+                state,
+                "confirm_password",
+                marginTop: 15,
+                obscureText: !state.confirmPwdVisibility,
+                errorText: state.confirmPasswordErrorText,
+                showRightIcon: true,
+                rightWidget: IconButton(
+                  highlightColor: Colors.transparent,
+                  splashColor: Colors.transparent,
+                  icon: state.confirmPwdVisibility
+                      ? const MyAssetImage(
+                    Assets.authPasswordHide,
+                    width: 22.5,
+                    height: 16.5,
+                  )
+                      : const MyAssetImage(
+                    Assets.authPasswordShow,
+                    width: 22.5,
+                    height: 16.5,
+                  ),
+                  onPressed: () {
+                    viewModel.switchConfirmPwdVisibility();
+                  },
+                ),
+                onSubmit: (formKey, value) {
+                  state.formData[formKey]!['focusNode'].unfocus();
+                  viewModel.submitSignUp();
+                },
+              ),
+
+              MyButton(
+                onPressed: viewModel.submitSignUp,
+                text: S.current.next,
+                textColor: Colors.white,
+                backgroundColor: context.appColors.btnBgDefault,
+                fontWeight: FontWeight.w500,
+                type: ClickType.throttle,
+                fontSize: 16,
+                minHeight: 50,
+                radius: 5,
+              ).marginOnly(top: 25, bottom: 25),
+
+              //同意协议
+              Row(
+                mainAxisSize: MainAxisSize.min,
+                children: [
+                  MyAssetImage(
+                    state.isAgreeTerms ? Assets.baseServiceCheckBoxChecked : Assets.baseServiceCheckBoxUncheck,
+                    width: 15.5,
+                    height: 15.5,
+                  ).onTap(viewModel.switchAgreeTerms, padding: 10),
+                  RichText(
+                    text: TextSpan(
+                      children: [
+                        TextSpan(
+                          text: S.current.agree_to,
+                          style: TextStyle(color: context.appColors.textDarkGray, fontWeight: FontWeight.w500, fontSize: 15), // 灰色文本
+                        ),
+                        const TextSpan(
+                          text: " ",
+                        ),
+                        TextSpan(
+                          text: S.current.terms_of_service,
+                          style: TextStyle(color: context.appColors.textPrimary, fontWeight: FontWeight.w500, fontSize: 15), // 蓝色文本
+                          recognizer: TapGestureRecognizer()..onTap = viewModel.gotoTermsPage,
+                        ),
+                      ],
+                    ),
+                  ),
+                ],
+              ).marginOnly(bottom: 35),
+
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+
+  /// 输入框
+  Widget _buildInputLayout(
+      BuildContext context,
+      SignUpState state,
+      String key, {
+        double marginTop = 0,
+        bool? showRightIcon = false, //是否展示右侧的布局
+        Widget? rightWidget, //右侧的布局
+        TextInputType textInputType = TextInputType.text,
+        String? errorText,
+        bool obscureText = false,
+        TextInputAction textInputAction = TextInputAction.done,
+        Function? onSubmit,
+      }) {
+    return IgnoreKeyboardDismiss(
+      child: MyTextField(
+        key,
+        fillBackgroundColor: context.appColors.authFiledBG,
+        state.formData[key]!['value'],
+        hintText: state.formData[key]!['hintText'],
+        hintStyle: TextStyle(
+          color: context.appColors.authFiledHint,
+          fontSize: 16.0,
+          fontWeight: FontWeight.w500,
+        ),
+        controller: state.formData[key]!['controller'],
+        focusNode: state.formData[key]!['focusNode'],
+        margin: EdgeInsets.only(top: marginTop),
+        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 3),
+        showDivider: false,
+        height: 44,
+        style: TextStyle(
+          color: context.appColors.authFiledText,
+          fontSize: 16.0,
+          fontWeight: FontWeight.w500,
+        ),
+        inputType: textInputType,
+        textInputAction: textInputAction,
+        onSubmit: onSubmit,
+        cursorColor: context.appColors.authFiledText,
+        obscureText: obscureText,
+        errorText: errorText,
+        showLeftIcon: true,
+        showRightIcon: showRightIcon,
+        rightWidget: rightWidget,
+      ),
+    );
+  }
+
+}

+ 107 - 0
packages/cpt_auth/lib/modules/sign_up/sign_up_state.dart

@@ -0,0 +1,107 @@
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:flutter/material.dart';
+
+class SignUpState {
+  //表单的校验与数据
+  final Map<String, Map<String, dynamic>> formData;
+
+  //表单的错误信息展示
+  String? firstNameErrorText;
+  String? lastNameErrorText;
+  String? emailErrorText;
+  String? phoneErrorText;
+  String? passwordErrorText;
+  String? confirmPasswordErrorText;
+
+  //是否明文展示密码
+  bool pwdVisibility;
+
+  bool confirmPwdVisibility;
+
+  bool isAgreeTerms;
+
+  // ===================================  Begin  ↓  ===================================
+
+  SignUpState({
+    Map<String, Map<String, dynamic>>? formData,
+    this.pwdVisibility = false,
+    this.confirmPwdVisibility = false,
+    this.isAgreeTerms = false,
+    this.firstNameErrorText,
+    this.lastNameErrorText,
+    this.emailErrorText,
+    this.phoneErrorText,
+    this.passwordErrorText,
+    this.confirmPasswordErrorText,
+  }) : formData = formData ??
+            {
+              'first_name': {
+                'value': '',
+                'controller': TextEditingController(),
+                'hintText': S.current.first_name,
+                'focusNode': FocusNode(),
+                'obsecure': false,
+              },
+              'last_name': {
+                'value': '',
+                'controller': TextEditingController(),
+                'hintText': S.current.last_name,
+                'focusNode': FocusNode(),
+                'obsecure': false,
+              },
+              'email': {
+                'value': '',
+                'controller': TextEditingController(),
+                'hintText': S.current.email,
+                'focusNode': FocusNode(),
+                'obsecure': false,
+              },
+              'phone': {
+                'value': '',
+                'controller': TextEditingController(),
+                'hintText': S.current.mobile_phone,
+                'focusNode': FocusNode(),
+                'obsecure': false,
+              },
+              'password': {
+                'value': '',
+                'controller': TextEditingController(),
+                'hintText': S.current.password,
+                'focusNode': FocusNode(),
+                'obsecure': true,
+              },
+              'confirm_password': {
+                'value': '',
+                'controller': TextEditingController(),
+                'hintText': S.current.confirm_password,
+                'focusNode': FocusNode(),
+                'obsecure': true,
+              },
+            };
+
+  SignUpState copyWith({
+    String? firstNameErrorText,
+    String? lastNameErrorText,
+    String? emailErrorText,
+    String? phoneErrorText,
+    String? passwordErrorText,
+    String? confirmPasswordErrorText,
+    bool? pwdVisibility,
+    bool? confirmPwdVisibility,
+    bool? isAgreeTerms,
+  }) {
+    return SignUpState(
+      formData: this.formData,
+      isAgreeTerms: isAgreeTerms ?? this.isAgreeTerms,
+      pwdVisibility: pwdVisibility ?? this.pwdVisibility,
+      confirmPwdVisibility: confirmPwdVisibility ?? this.confirmPwdVisibility,
+      firstNameErrorText: firstNameErrorText,
+      lastNameErrorText: lastNameErrorText,
+      emailErrorText: emailErrorText,
+      phoneErrorText: phoneErrorText,
+      passwordErrorText: passwordErrorText,
+      confirmPasswordErrorText: confirmPasswordErrorText,
+    );
+  }
+
+}

+ 199 - 0
packages/cpt_auth/lib/modules/sign_up/sign_up_view_model.dart

@@ -0,0 +1,199 @@
+import 'package:flutter/material.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/util.dart';
+
+import 'sign_up_state.dart';
+
+part 'sign_up_view_model.g.dart';
+
+@riverpod
+class SignUpViewModel extends _$SignUpViewModel {
+  @override
+  SignUpState build() {
+    final state = SignUpState();
+    initListener(state);
+    ref.onDispose(() {
+      onDispose(state);
+    });
+    return state;
+  }
+
+  //提交注册表单
+  void submitSignUp() {
+    state = state.copyWith(
+      firstNameErrorText: null,
+      lastNameErrorText: null,
+      emailErrorText: null,
+      phoneErrorText: null,
+      passwordErrorText: null,
+      confirmPasswordErrorText: null,
+    );
+
+    final FocusNode firstNameFocusNode = state.formData['first_name']!['focusNode'];
+    final FocusNode lastNameFocusNode = state.formData['last_name']!['focusNode'];
+    final FocusNode emailFocusNode = state.formData['email']!['focusNode'];
+    final FocusNode phoneFocusNode = state.formData['phone']!['focusNode'];
+    final FocusNode passwordFocusNode = state.formData['password']!['focusNode'];
+    final FocusNode confirmPasswordFocusNode = state.formData['confirm_password']!['focusNode'];
+
+    firstNameFocusNode.unfocus();
+    lastNameFocusNode.unfocus();
+    emailFocusNode.unfocus();
+    phoneFocusNode.unfocus();
+    passwordFocusNode.unfocus();
+    confirmPasswordFocusNode.unfocus();
+
+    final TextEditingController firstNameController = state.formData['first_name']!['controller'];
+    final TextEditingController lastNameController = state.formData['last_name']!['controller'];
+    final TextEditingController emailController = state.formData['email']!['controller'];
+    final TextEditingController phoneController = state.formData['phone']!['controller'];
+    final TextEditingController passwordController = state.formData['password']!['controller'];
+    final TextEditingController confirmPasswordController = state.formData['confirm_password']!['controller'];
+
+    final firstName = firstNameController.text;
+    final lastName = lastNameController.text;
+    final email = emailController.text;
+    final phone = phoneController.text;
+    final password = passwordController.text;
+    final confirmPassword = confirmPasswordController.text;
+
+    Log.d('当前待提交的 firstName:$firstName lastName:$lastName email:$email phone:$phone password:$password confirmPassword:$confirmPassword');
+
+    if (Utils.isEmpty(firstName)) {
+      state = state.copyWith(firstNameErrorText: "First Name cannot be empty!");
+      return;
+    }
+
+    if (Utils.isEmpty(lastName)) {
+      state = state.copyWith(lastNameErrorText: "Last Name cannot be empty!");
+      return;
+    }
+
+    if (Utils.isEmpty(email)) {
+      state = state.copyWith(emailErrorText: "Email cannot be empty!");
+      return;
+    }
+
+    if (Utils.isEmpty(phone)) {
+      state = state.copyWith(phoneErrorText: "Email cannot be empty!");
+      return;
+    }
+
+    if (Utils.isEmpty(password)) {
+      state = state.copyWith(passwordErrorText: "Password cannot be empty!");
+      return;
+    }
+
+    if (Utils.isEmpty(confirmPassword)) {
+      state = state.copyWith(confirmPasswordErrorText: "Confirm Password cannot be empty!");
+      return;
+    }
+
+    if (confirmPassword != password) {
+      state = state.copyWith(confirmPasswordErrorText: "Password mismatch, please check password");
+      return;
+    }
+
+    //执行密码登录
+    ToastEngine.show('准备执行请求发送验证码 firstName:$firstName lastName:$lastName email:$email phone:$phone password:$password confirmPassword:$confirmPassword');
+
+    gotoSignUpVerifyPage();
+
+  }
+
+  //去注册的短信校验页面
+  void gotoSignUpVerifyPage() {
+
+  }
+
+  //切换隐藏显示密码
+  void switchPwdVisibility() {
+    state = state.copyWith(pwdVisibility: !state.pwdVisibility);
+  }
+
+  void switchConfirmPwdVisibility() {
+    state = state.copyWith(confirmPwdVisibility: !state.confirmPwdVisibility);
+  }
+
+  //切换同意按钮
+  void switchAgreeTerms() {
+    state = state.copyWith(isAgreeTerms: !state.isAgreeTerms);
+  }
+
+  void gotoTermsPage() {
+    ToastEngine.show("去协议页面");
+  }
+
+  //初始化监听
+  void initListener(SignUpState initState) {
+    final FocusNode firstNameFocusNode = initState.formData['first_name']!['focusNode'];
+    final FocusNode lastNameFocusNode = initState.formData['last_name']!['focusNode'];
+    final FocusNode emailFocusNode = initState.formData['email']!['focusNode'];
+    final FocusNode phoneFocusNode = initState.formData['phone']!['focusNode'];
+    final FocusNode passwordFocusNode = initState.formData['password']!['focusNode'];
+    final FocusNode confirmPasswordFocusNode = initState.formData['confirm_password']!['focusNode'];
+
+    firstNameFocusNode.addListener(() {
+      // 获取焦点的时候清空错误文本
+      if (firstNameFocusNode.hasFocus) {
+        state = state.copyWith(firstNameErrorText: null);
+      }
+    });
+
+    lastNameFocusNode.addListener(() {
+      // 获取焦点的时候清空错误文本
+      if (lastNameFocusNode.hasFocus) {
+        state = state.copyWith(lastNameErrorText: null);
+      }
+    });
+
+    emailFocusNode.addListener(() {
+      // 获取焦点的时候清空错误文本
+      if (emailFocusNode.hasFocus) {
+        state = state.copyWith(emailErrorText: null);
+      }
+    });
+
+    phoneFocusNode.addListener(() {
+      // 获取焦点的时候清空错误文本
+      if (phoneFocusNode.hasFocus) {
+        state = state.copyWith(phoneErrorText: null);
+      }
+    });
+
+    passwordFocusNode.addListener(() {
+      // 获取焦点的时候清空错误文本
+      if (passwordFocusNode.hasFocus) {
+        state = state.copyWith(passwordErrorText: null);
+      }
+    });
+
+    confirmPasswordFocusNode.addListener(() {
+      // 获取焦点的时候清空错误文本
+      if (confirmPasswordFocusNode.hasFocus) {
+        state = state.copyWith(confirmPasswordErrorText: null);
+      }
+    });
+  }
+
+  //销毁资源
+  void onDispose(SignUpState initState) {
+    final FocusNode firstNameFocusNode = initState.formData['first_name']!['focusNode'];
+    final FocusNode lastNameFocusNode = initState.formData['last_name']!['focusNode'];
+    final FocusNode emailFocusNode = initState.formData['email']!['focusNode'];
+    final FocusNode phoneFocusNode = initState.formData['phone']!['focusNode'];
+    final FocusNode passwordFocusNode = initState.formData['password']!['focusNode'];
+    final FocusNode confirmPasswordFocusNode = initState.formData['confirm_password']!['focusNode'];
+    firstNameFocusNode.dispose();
+    lastNameFocusNode.dispose();
+    emailFocusNode.dispose();
+    phoneFocusNode.dispose();
+    passwordFocusNode.dispose();
+    confirmPasswordFocusNode.dispose();
+
+    Log.d("SignUpViewModel 销毁 onDispose");
+  }
+
+}

+ 26 - 0
packages/cpt_auth/lib/modules/sign_up/sign_up_view_model.g.dart

@@ -0,0 +1,26 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'sign_up_view_model.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$signUpViewModelHash() => r'b85704f97138aebd2e6e6abc9ef7efb2c6cbfb2d';
+
+/// See also [SignUpViewModel].
+@ProviderFor(SignUpViewModel)
+final signUpViewModelProvider =
+    AutoDisposeNotifierProvider<SignUpViewModel, SignUpState>.internal(
+  SignUpViewModel.new,
+  name: r'signUpViewModelProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$signUpViewModelHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$SignUpViewModel = AutoDisposeNotifier<SignUpState>;
+// ignore_for_file: type=lint
+// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package

+ 3 - 4
packages/cpt_auth/lib/router/component/auth_component_service.dart

@@ -1,13 +1,14 @@
 /*
  * Auth 组件的组件路由
  */
+import 'package:cpt_auth/modules/forgot_input/forgot_input_page.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:router/componentRouter/auth_service.dart';
 import 'package:flutter/material.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 
-import '../../modules/auth_login/page/Profile_edit_page.dart';
+import '../../modules/auth_login/auth_login_page.dart';
 
 part 'auth_component_service.g.dart';
 
@@ -17,7 +18,6 @@ AuthService authService(Ref ref) {
 }
 
 class AuthComponentService extends AuthService {
-
   @override
   void startLoginPage() {
     AuthLoginPage.startInstance();
@@ -25,7 +25,6 @@ class AuthComponentService extends AuthService {
 
   @override
   void startResetPasswordPage() {
-
+    ForgotInputPage.startInstance();
   }
-
 }

+ 8 - 2
packages/cpt_auth/lib/router/page/auth_page_router.dart

@@ -3,7 +3,11 @@ import 'package:flutter/material.dart';
 import 'package:router/ext/auto_router_extensions.dart';
 import 'package:router/path/router_path.dart';
 
-import '../../modules/auth_login/page/Profile_edit_page.dart';
+import '../../modules/auth_login/auth_login_page.dart';
+import '../../modules/forgot_input/forgot_input_page.dart';
+import '../../modules/forgot_verify/forgot_verify_page.dart';
+import '../../modules/sign_up/sign_up_page.dart';
+
 
 
 part 'auth_page_router.gr.dart';
@@ -15,7 +19,9 @@ part 'auth_page_router.gr.dart';
 class AuthPageRouter extends _$AuthPageRouter {
   @override
   List<AutoRoute> get routes => [
-
     CustomRoute(page: AuthLoginPageRoute.page, path: RouterPath.authLogin, transitionsBuilder: applySlideTransition),
+    CustomRoute(page: ForgotInputPageRoute.page, path: RouterPath.authForgotInput, transitionsBuilder: applySlideTransition),
+    CustomRoute(page: ForgotVerifyPageRoute.page, path: RouterPath.authForgotVerify, transitionsBuilder: applySlideTransition),
+    CustomRoute(page: SignUpPageRoute.page, path: RouterPath.authSignUp, transitionsBuilder: applySlideTransition),
   ];
 }

+ 61 - 1
packages/cpt_auth/lib/router/page/auth_page_router.gr.dart

@@ -20,7 +20,25 @@ abstract class _$AuthPageRouter extends RootStackRouter {
         routeData: routeData,
         child: const AuthLoginPage(),
       );
-    }
+    },
+    ForgotInputPageRoute.name: (routeData) {
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: const ForgotInputPage(),
+      );
+    },
+    ForgotVerifyPageRoute.name: (routeData) {
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: const ForgotVerifyPage(),
+      );
+    },
+    SignUpPageRoute.name: (routeData) {
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: const SignUpPage(),
+      );
+    },
   };
 }
 
@@ -37,3 +55,45 @@ class AuthLoginPageRoute extends PageRouteInfo<void> {
 
   static const PageInfo<void> page = PageInfo<void>(name);
 }
+
+/// generated route for
+/// [ForgotInputPage]
+class ForgotInputPageRoute extends PageRouteInfo<void> {
+  const ForgotInputPageRoute({List<PageRouteInfo>? children})
+      : super(
+          ForgotInputPageRoute.name,
+          initialChildren: children,
+        );
+
+  static const String name = 'ForgotInputPageRoute';
+
+  static const PageInfo<void> page = PageInfo<void>(name);
+}
+
+/// generated route for
+/// [ForgotVerifyPage]
+class ForgotVerifyPageRoute extends PageRouteInfo<void> {
+  const ForgotVerifyPageRoute({List<PageRouteInfo>? children})
+      : super(
+          ForgotVerifyPageRoute.name,
+          initialChildren: children,
+        );
+
+  static const String name = 'ForgotVerifyPageRoute';
+
+  static const PageInfo<void> page = PageInfo<void>(name);
+}
+
+/// generated route for
+/// [SignUpPage]
+class SignUpPageRoute extends PageRouteInfo<void> {
+  const SignUpPageRoute({List<PageRouteInfo>? children})
+      : super(
+          SignUpPageRoute.name,
+          initialChildren: children,
+        );
+
+  static const String name = 'SignUpPageRoute';
+
+  static const PageInfo<void> page = PageInfo<void>(name);
+}

+ 3 - 1
packages/cpt_main/lib/modules/home/page/home_page.dart

@@ -95,7 +95,9 @@ class HomePage extends HookConsumerWidget {
                   child: Text('Login'),
                 ),
                 ElevatedButton(
-                  onPressed: () {},
+                  onPressed: () {
+                    ComponentServiceManager().authService.startResetPasswordPage();
+                  },
                   child: Text('Forgot'),
                 ),
                 ElevatedButton(

+ 50 - 0
packages/cpt_main/lib/modules/main/page/main_page.dart

@@ -1,3 +1,5 @@
+import 'package:cs_resources/theme/theme_config.dart';
+import 'package:flutter/services.dart';
 import 'package:flutter/src/widgets/framework.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:auto_route/auto_route.dart';
@@ -23,6 +25,54 @@ class MainPage extends HookConsumerWidget {
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
+    // return AutoTabsRouter(
+    //   routes: const [
+    //     HomePageRoute(),
+    //     VisitorPageRoute(),
+    //     FeedbackPageRoute(),
+    //     MePageRoute(),
+    //   ],
+    //   transitionBuilder: (context, child, animation) => FadeTransition(
+    //     opacity: animation,
+    //     child: child,
+    //   ),
+    //   builder: (context, child) {
+    //     final tabsRouter = AutoTabsRouter.of(context);
+    //     return AnnotatedRegion<SystemUiOverlayStyle>(
+    //         value: ThemeConfig.getSystemUiOverlayStyleByTheme(context),
+    //         child: Scaffold(
+    //           body: child,
+    //           bottomNavigationBar: BottomNavigationBar(
+    //             backgroundColor: context.theme.primaryColor,
+    //             selectedItemColor: context.theme.colorScheme.secondary,
+    //             unselectedItemColor: Colors.grey[500],
+    //             elevation: 20,
+    //             type: BottomNavigationBarType.fixed,
+    //             items: const <BottomNavigationBarItem>[
+    //               BottomNavigationBarItem(
+    //                 icon: Icon(Icons.home),
+    //                 label: 'Home',
+    //               ),
+    //               BottomNavigationBarItem(
+    //                 icon: Icon(Icons.card_giftcard),
+    //                 label: 'Visitor',
+    //               ),
+    //               BottomNavigationBarItem(
+    //                 icon: Icon(Icons.feed),
+    //                 label: 'Feedback',
+    //               ),
+    //               BottomNavigationBarItem(
+    //                 icon: Icon(Icons.person),
+    //                 label: 'Me',
+    //               ),
+    //             ],
+    //             onTap: tabsRouter.setActiveIndex,
+    //             currentIndex: tabsRouter.activeIndex,
+    //           ),
+    //         ));
+    //   },
+    // );
+
     return AutoTabsScaffold(
       routes: const [
         HomePageRoute(),

+ 2 - 1
packages/cpt_main/lib/modules/visitor/page/visitor_page.dart

@@ -1,5 +1,6 @@
 import 'package:cpt_main/modules/visitor/vm/visitor_view_model.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:cs_resources/theme/theme_config.dart';
 import 'package:cs_resources/theme/theme_notifier.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
@@ -35,7 +36,7 @@ class VisitorPage extends HookConsumerWidget {
     Log.d("VisitorPage - build 了");
 
     return Scaffold(
-      appBar: AppBar(title: Text("Visitor")),
+      appBar: AppBar(title: Text("Visitor"),systemOverlayStyle: ThemeConfig.getSystemUiOverlayStyleByTheme(context)),
       backgroundColor: context.appColors.backgroundDefault,
       body: Center(
         child: Column(

BIN
packages/cs_resources/assets/auth/choose_estate_building.webp


BIN
packages/cs_resources/assets/auth/country_sg.webp


BIN
packages/cs_resources/assets/auth/forgot_input_email_phone_img.webp


BIN
packages/cs_resources/assets/auth/forgot_reset_password_img.webp


BIN
packages/cs_resources/assets/auth/image_add_icon.webp


BIN
packages/cs_resources/assets/auth/password_hide.webp


BIN
packages/cs_resources/assets/auth/password_show.webp


BIN
packages/cs_resources/assets/auth/sign_up_input_img.webp


BIN
packages/cs_resources/assets/auth/sign_up_success_img.webp


BIN
packages/cs_resources/assets/auth/sign_up_unit_img.webp


BIN
packages/cs_resources/assets/auth/sms_verify_img.webp


BIN
packages/cs_resources/assets/auth/yy_home_success.webp


BIN
packages/cs_resources/assets/base_service/check_box_checked.webp


BIN
packages/cs_resources/assets/base_service/check_box_uncheck.webp


BIN
packages/cs_resources/assets/base_service/triangle_drop_down_icon.webp


BIN
packages/cs_resources/assets/yy_home_logo.webp


+ 13 - 0
packages/cs_resources/lib/generated/assets.dart

@@ -3,6 +3,19 @@ class Assets {
   Assets._();
 
   static const String assetsYyBusinessTopLogo = 'assets/yy_business_top_logo.webp';
+  static const String assetsYyHomeLogo = 'assets/yy_home_logo.webp';
+  static const String authChooseEstateBuilding = 'assets/auth/choose_estate_building.webp';
+  static const String authCountrySg = 'assets/auth/country_sg.webp';
+  static const String authForgotInputEmailPhoneImg = 'assets/auth/forgot_input_email_phone_img.webp';
+  static const String authForgotResetPasswordImg = 'assets/auth/forgot_reset_password_img.webp';
+  static const String authImageAddIcon = 'assets/auth/image_add_icon.webp';
+  static const String authPasswordHide = 'assets/auth/password_hide.webp';
+  static const String authPasswordShow = 'assets/auth/password_show.webp';
+  static const String authSignUpInputImg = 'assets/auth/sign_up_input_img.webp';
+  static const String authSignUpSuccessImg = 'assets/auth/sign_up_success_img.webp';
+  static const String authSignUpUnitImg = 'assets/auth/sign_up_unit_img.webp';
+  static const String authSmsVerifyImg = 'assets/auth/sms_verify_img.webp';
+  static const String authYyHomeSuccess = 'assets/auth/yy_home_success.webp';
   static const String baseLibBlackBack = 'assets/base_lib/black_back.webp';
   static const String baseLibDialogBlueDeleteIcon = 'assets/base_lib/dialog_blue_delete_icon.webp';
   static const String baseLibDialogDeleteIcon = 'assets/base_lib/dialog_delete_icon.webp';

+ 28 - 1
packages/cs_resources/lib/generated/intl/messages_en.dart

@@ -22,11 +22,38 @@ class MessageLookup extends MessageLookupByLibrary {
 
   final messages = _notInlinedMessages(_notInlinedMessages);
   static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
+        "agree_to": MessageLookupByLibrary.simpleMessage("Agree to"),
+        "confirm_password":
+            MessageLookupByLibrary.simpleMessage("Confirm Password"),
+        "create_new_yy_home_account":
+            MessageLookupByLibrary.simpleMessage("Create New YY Home Account"),
+        "email": MessageLookupByLibrary.simpleMessage("Email"),
         "facility": MessageLookupByLibrary.simpleMessage("Facility"),
+        "first_name": MessageLookupByLibrary.simpleMessage("First Name"),
+        "forgot_password":
+            MessageLookupByLibrary.simpleMessage("Forgot Password?"),
+        "forgot_text": MessageLookupByLibrary.simpleMessage(
+            "Enter your email and mobile phone number"),
         "form": MessageLookupByLibrary.simpleMessage("Form"),
+        "get_code": MessageLookupByLibrary.simpleMessage("Get Code"),
+        "last_name": MessageLookupByLibrary.simpleMessage("Last Name"),
+        "login": MessageLookupByLibrary.simpleMessage("Log In"),
+        "mobile_phone": MessageLookupByLibrary.simpleMessage("Mobile Phone"),
+        "next": MessageLookupByLibrary.simpleMessage("Next"),
         "notice_board": MessageLookupByLibrary.simpleMessage("Notice Board"),
         "notification": MessageLookupByLibrary.simpleMessage("Notification"),
+        "other": MessageLookupByLibrary.simpleMessage("Other"),
+        "password": MessageLookupByLibrary.simpleMessage("Password"),
+        "password_format":
+            MessageLookupByLibrary.simpleMessage("8 Digits Alphanumeric"),
         "payment": MessageLookupByLibrary.simpleMessage("Payment"),
-        "rewards": MessageLookupByLibrary.simpleMessage("Rewards")
+        "phone_email": MessageLookupByLibrary.simpleMessage("Phone/Email"),
+        "reset_password":
+            MessageLookupByLibrary.simpleMessage("Reset Password"),
+        "rewards": MessageLookupByLibrary.simpleMessage("Rewards"),
+        "terms_of_service":
+            MessageLookupByLibrary.simpleMessage("Terms of Service"),
+        "verification_code":
+            MessageLookupByLibrary.simpleMessage("Verification Code")
       };
 }

+ 21 - 1
packages/cs_resources/lib/generated/intl/messages_zh_CN.dart

@@ -22,11 +22,31 @@ class MessageLookup extends MessageLookupByLibrary {
 
   final messages = _notInlinedMessages(_notInlinedMessages);
   static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
+        "agree_to": MessageLookupByLibrary.simpleMessage("同意"),
+        "confirm_password": MessageLookupByLibrary.simpleMessage("确认密码"),
+        "create_new_yy_home_account":
+            MessageLookupByLibrary.simpleMessage("创建新的 YY Home 账户"),
+        "email": MessageLookupByLibrary.simpleMessage("邮箱"),
         "facility": MessageLookupByLibrary.simpleMessage("设施"),
+        "first_name": MessageLookupByLibrary.simpleMessage("名"),
+        "forgot_password": MessageLookupByLibrary.simpleMessage("忘记密码?"),
+        "forgot_text": MessageLookupByLibrary.simpleMessage("请输入您的邮箱和手机号码"),
         "form": MessageLookupByLibrary.simpleMessage("表单"),
+        "get_code": MessageLookupByLibrary.simpleMessage("获取验证码"),
+        "last_name": MessageLookupByLibrary.simpleMessage("姓"),
+        "login": MessageLookupByLibrary.simpleMessage("登录"),
+        "mobile_phone": MessageLookupByLibrary.simpleMessage("手机号码"),
+        "next": MessageLookupByLibrary.simpleMessage("下一步"),
         "notice_board": MessageLookupByLibrary.simpleMessage("消息板"),
         "notification": MessageLookupByLibrary.simpleMessage("通知"),
+        "other": MessageLookupByLibrary.simpleMessage("其他"),
+        "password": MessageLookupByLibrary.simpleMessage("密码"),
+        "password_format": MessageLookupByLibrary.simpleMessage("8位数字或字母"),
         "payment": MessageLookupByLibrary.simpleMessage("支付"),
-        "rewards": MessageLookupByLibrary.simpleMessage("奖励")
+        "phone_email": MessageLookupByLibrary.simpleMessage("电话或邮箱"),
+        "reset_password": MessageLookupByLibrary.simpleMessage("重置密码"),
+        "rewards": MessageLookupByLibrary.simpleMessage("奖励"),
+        "terms_of_service": MessageLookupByLibrary.simpleMessage("服务条款"),
+        "verification_code": MessageLookupByLibrary.simpleMessage("验证码")
       };
 }

+ 21 - 1
packages/cs_resources/lib/generated/intl/messages_zh_HK.dart

@@ -22,11 +22,31 @@ class MessageLookup extends MessageLookupByLibrary {
 
   final messages = _notInlinedMessages(_notInlinedMessages);
   static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
+        "agree_to": MessageLookupByLibrary.simpleMessage("同意"),
+        "confirm_password": MessageLookupByLibrary.simpleMessage("确认密码"),
+        "create_new_yy_home_account":
+            MessageLookupByLibrary.simpleMessage("创建新的 YY Home 账户"),
+        "email": MessageLookupByLibrary.simpleMessage("邮箱"),
         "facility": MessageLookupByLibrary.simpleMessage("設施"),
+        "first_name": MessageLookupByLibrary.simpleMessage("名"),
+        "forgot_password": MessageLookupByLibrary.simpleMessage("忘记密码?"),
+        "forgot_text": MessageLookupByLibrary.simpleMessage("请输入您的邮箱和手机号码"),
         "form": MessageLookupByLibrary.simpleMessage("表單"),
+        "get_code": MessageLookupByLibrary.simpleMessage("获取验证码"),
+        "last_name": MessageLookupByLibrary.simpleMessage("姓"),
+        "login": MessageLookupByLibrary.simpleMessage("登录"),
+        "mobile_phone": MessageLookupByLibrary.simpleMessage("手机号码"),
+        "next": MessageLookupByLibrary.simpleMessage("下一步"),
         "notice_board": MessageLookupByLibrary.simpleMessage("通知板"),
         "notification": MessageLookupByLibrary.simpleMessage("通知"),
+        "other": MessageLookupByLibrary.simpleMessage("其他"),
+        "password": MessageLookupByLibrary.simpleMessage("密码"),
+        "password_format": MessageLookupByLibrary.simpleMessage("8位数字或字母"),
         "payment": MessageLookupByLibrary.simpleMessage("支付"),
-        "rewards": MessageLookupByLibrary.simpleMessage("獎勵")
+        "phone_email": MessageLookupByLibrary.simpleMessage("电话或邮箱"),
+        "reset_password": MessageLookupByLibrary.simpleMessage("重置密码"),
+        "rewards": MessageLookupByLibrary.simpleMessage("獎勵"),
+        "terms_of_service": MessageLookupByLibrary.simpleMessage("服务条款"),
+        "verification_code": MessageLookupByLibrary.simpleMessage("验证码")
       };
 }

+ 190 - 0
packages/cs_resources/lib/generated/l10n.dart

@@ -109,6 +109,196 @@ class S {
       args: [],
     );
   }
+
+  /// `Phone/Email`
+  String get phone_email {
+    return Intl.message(
+      'Phone/Email',
+      name: 'phone_email',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Password`
+  String get password {
+    return Intl.message(
+      'Password',
+      name: 'password',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Log In`
+  String get login {
+    return Intl.message(
+      'Log In',
+      name: 'login',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Forgot Password?`
+  String get forgot_password {
+    return Intl.message(
+      'Forgot Password?',
+      name: 'forgot_password',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Create New YY Home Account`
+  String get create_new_yy_home_account {
+    return Intl.message(
+      'Create New YY Home Account',
+      name: 'create_new_yy_home_account',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Agree to`
+  String get agree_to {
+    return Intl.message(
+      'Agree to',
+      name: 'agree_to',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Terms of Service`
+  String get terms_of_service {
+    return Intl.message(
+      'Terms of Service',
+      name: 'terms_of_service',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Enter your email and mobile phone number`
+  String get forgot_text {
+    return Intl.message(
+      'Enter your email and mobile phone number',
+      name: 'forgot_text',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Email`
+  String get email {
+    return Intl.message(
+      'Email',
+      name: 'email',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Mobile Phone`
+  String get mobile_phone {
+    return Intl.message(
+      'Mobile Phone',
+      name: 'mobile_phone',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Next`
+  String get next {
+    return Intl.message(
+      'Next',
+      name: 'next',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Verification Code`
+  String get verification_code {
+    return Intl.message(
+      'Verification Code',
+      name: 'verification_code',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Reset Password`
+  String get reset_password {
+    return Intl.message(
+      'Reset Password',
+      name: 'reset_password',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Confirm Password`
+  String get confirm_password {
+    return Intl.message(
+      'Confirm Password',
+      name: 'confirm_password',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `8 Digits Alphanumeric`
+  String get password_format {
+    return Intl.message(
+      '8 Digits Alphanumeric',
+      name: 'password_format',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Get Code`
+  String get get_code {
+    return Intl.message(
+      'Get Code',
+      name: 'get_code',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `First Name`
+  String get first_name {
+    return Intl.message(
+      'First Name',
+      name: 'first_name',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Last Name`
+  String get last_name {
+    return Intl.message(
+      'Last Name',
+      name: 'last_name',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Other`
+  String get other {
+    return Intl.message(
+      'Other',
+      name: 'other',
+      desc: '',
+      args: [],
+    );
+  }
 }
 
 class AppLocalizationDelegate extends LocalizationsDelegate<S> {

+ 20 - 1
packages/cs_resources/lib/l10n/intl_en.arb

@@ -4,5 +4,24 @@
   "notification": "Notification",
   "facility": "Facility",
   "form": "Form",
-  "notice_board": "Notice Board"
+  "notice_board": "Notice Board",
+  "phone_email": "Phone/Email",
+  "password": "Password",
+  "login": "Log In",
+  "forgot_password": "Forgot Password?",
+  "create_new_yy_home_account": "Create New YY Home Account",
+  "agree_to": "Agree to",
+  "terms_of_service": "Terms of Service",
+  "forgot_text": "Enter your email and mobile phone number",
+  "email": "Email",
+  "mobile_phone": "Mobile Phone",
+  "next": "Next",
+  "verification_code": "Verification Code",
+  "reset_password": "Reset Password",
+  "confirm_password": "Confirm Password",
+  "password_format": "8 Digits Alphanumeric",
+  "get_code": "Get Code",
+  "first_name": "First Name",
+  "last_name": "Last Name",
+  "other": "Other"
 }

+ 20 - 1
packages/cs_resources/lib/l10n/intl_zh_CN.arb

@@ -4,5 +4,24 @@
   "notification": "通知",
   "facility": "设施",
   "form": "表单",
-  "notice_board": "消息板"
+  "notice_board": "消息板",
+  "phone_email": "电话或邮箱",
+  "password": "密码",
+  "login": "登录",
+  "forgot_password": "忘记密码?",
+  "create_new_yy_home_account": "创建新的 YY Home 账户",
+  "agree_to": "同意",
+  "terms_of_service": "服务条款",
+  "forgot_text": "请输入您的邮箱和手机号码",
+  "email": "邮箱",
+  "mobile_phone": "手机号码",
+  "next": "下一步",
+  "verification_code": "验证码",
+  "reset_password": "重置密码",
+  "confirm_password": "确认密码",
+  "password_format": "8位数字或字母",
+  "get_code": "获取验证码",
+  "first_name": "名",
+  "last_name": "姓",
+  "other": "其他"
 }

+ 20 - 1
packages/cs_resources/lib/l10n/intl_zh_HK.arb

@@ -4,5 +4,24 @@
   "notification": "通知",
   "facility": "設施",
   "form": "表單",
-  "notice_board": "通知板"
+  "notice_board": "通知板",
+  "phone_email": "电话或邮箱",
+  "password": "密码",
+  "login": "登录",
+  "forgot_password": "忘记密码?",
+  "create_new_yy_home_account": "创建新的 YY Home 账户",
+  "agree_to": "同意",
+  "terms_of_service": "服务条款",
+  "forgot_text": "请输入您的邮箱和手机号码",
+  "email": "邮箱",
+  "mobile_phone": "手机号码",
+  "next": "下一步",
+  "verification_code": "验证码",
+  "reset_password": "重置密码",
+  "confirm_password": "确认密码",
+  "password_format": "8位数字或字母",
+  "get_code": "获取验证码",
+  "first_name": "名",
+  "last_name": "姓",
+  "other": "其他"
 }

+ 36 - 5
packages/cs_resources/lib/theme/app_colors_theme.dart

@@ -12,10 +12,12 @@ extension AppColorsThemeExtensions on BuildContext {
 class AppColorsTheme extends ThemeExtension<AppColorsTheme> {
   //亮色主题的自定义颜色值
   static const _colorPrimary = Color(0xFF4161D0); //主题色
-  static const _colorB0B0B0 = Color(0xFFB0B0B0);
+  static const _colorFCFCFC = Color(0xFFFCFCFC);
   static const _color6C6C6C = Color(0xFF6C6C6C);
-  static const _colorF9F9F9 = Color(0xffF9F9F9);
+  static const _color666666 = Color(0xFF666666);
   static const _colorD7DBE7 = Color(0xffD7DBE7);
+  static const _colorBDBDBD = Color(0xFFBDBDBD);
+  static const _colorF2F2F2 = Color(0xFFF2F2F2);
 
   //暗色主题的一些自定义颜色值
   static const _darkBlackBg = Color(0xFF0F0F0F);
@@ -26,23 +28,40 @@ class AppColorsTheme extends ThemeExtension<AppColorsTheme> {
 
   // 页面中真正使用到的颜色名称
   final Color backgroundDefault; //页面背景颜色
-  final Color btnBgDefault;
+  final Color btnBgDefault;  //按钮背景颜色
   final Color searchFiledBorder; //搜索框的边框颜色
-
+  final Color authFiledHint; //输入框默认的提示文本颜色
+  final Color authFiledText; //输入框默认的文本颜色
+  final Color authFiledBG; //输入框默认的背景颜色
+  final Color textPrimary; //主题色文本
+  final Color textBlack; //黑色文本
+  final Color textDarkGray; //深灰色 666 文本
 
   // 私有的构造函数
   const AppColorsTheme._internal({
     required this.backgroundDefault,
     required this.btnBgDefault,
     required this.searchFiledBorder,
+    required this.authFiledHint,
+    required this.authFiledText,
+    required this.authFiledBG,
+    required this.textPrimary,
+    required this.textBlack,
+    required this.textDarkGray,
   });
 
   // 浅色主题工厂方法
   factory AppColorsTheme.light() {
     return const AppColorsTheme._internal(
-      backgroundDefault: _colorF9F9F9,
+      backgroundDefault: _colorFCFCFC,
       btnBgDefault: _colorPrimary,
       searchFiledBorder: _colorD7DBE7,
+      authFiledHint: _colorBDBDBD,
+      authFiledText: Colors.black,
+      authFiledBG: _colorF2F2F2,
+      textPrimary: _colorPrimary,
+      textBlack: Colors.black,
+      textDarkGray: _color666666,
     );
   }
 
@@ -52,6 +71,12 @@ class AppColorsTheme extends ThemeExtension<AppColorsTheme> {
       backgroundDefault: _darkBlackBg,
       btnBgDefault: _darkBlackItem,
       searchFiledBorder: _darkBlackItem,
+      authFiledHint: _colorD7DBE7,
+      authFiledText: Colors.white,
+      authFiledBG: _darkBlackItem,
+      textPrimary: Colors.white,
+      textBlack: Colors.white,
+      textDarkGray: Colors.white,
     );
   }
 
@@ -70,6 +95,12 @@ class AppColorsTheme extends ThemeExtension<AppColorsTheme> {
       backgroundDefault: Color.lerp(backgroundDefault, other.backgroundDefault, t)!,
       btnBgDefault: Color.lerp(btnBgDefault, other.btnBgDefault, t)!,
       searchFiledBorder: Color.lerp(searchFiledBorder, other.searchFiledBorder, t)!,
+      authFiledHint: Color.lerp(authFiledHint, other.authFiledHint, t)!,
+      authFiledText: Color.lerp(authFiledText, other.authFiledText, t)!,
+      authFiledBG: Color.lerp(authFiledBG, other.authFiledBG, t)!,
+      textPrimary: Color.lerp(textPrimary, other.textPrimary, t)!,
+      textBlack: Color.lerp(textBlack, other.textBlack, t)!,
+      textDarkGray: Color.lerp(textDarkGray, other.textDarkGray, t)!,
     );
   }
 }

+ 14 - 1
packages/cs_resources/lib/theme/theme_config.dart

@@ -3,7 +3,6 @@ import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 
 class ThemeConfig {
-
   //亮色模式模式下的状态栏与导航栏设置 (默认黑色状态栏文本,白色导航栏)
   static SystemUiOverlayStyle get systemUiOverlayStyleLightThemeBlack {
     return SystemUiOverlayStyle.light.copyWith(
@@ -42,4 +41,18 @@ class ThemeConfig {
     );
   }
 
+  //根据上下文的亮色模式和暗色模式返回对应的 SystemUiOverlay 配置
+  static SystemUiOverlayStyle getSystemUiOverlayStyleByTheme(BuildContext context) {
+    late SystemUiOverlayStyle systemUiOverlayStyle;
+
+    Brightness currentBrightness = MediaQuery.of(context).platformBrightness;
+    if (currentBrightness == Brightness.dark) {
+      systemUiOverlayStyle = systemUiOverlayStyleDarkTheme;
+    } else {
+      systemUiOverlayStyle = systemUiOverlayStyleLightThemeBlack;
+    }
+
+    return systemUiOverlayStyle;
+  }
+
 }

+ 4 - 0
packages/cs_resources/pubspec.yaml

@@ -27,7 +27,11 @@ flutter:
     - assets/
     - assets/base_lib/
     - assets/base_service/
+<<<<<<< HEAD
     - assets/property/
+=======
+    - assets/auth/
+>>>>>>> 5aa4bec8cb4b6dcf57ae73e59b3f8b7688c4ed35
 
 
 flutter_intl:

+ 2 - 0
packages/cs_router/lib/path/router_path.dart

@@ -6,6 +6,8 @@ class RouterPath {
 
   //用户
   static const authLogin = '/auth/login'; //用户登录注册
+  static const authForgotInput = '/auth/forgot/input'; //忘记密码
+  static const authForgotVerify = '/auth/forgot/verify'; //忘记密码校验
   static const authSignUp = '/auth/signup'; //注册
   static const authResetPassword = '/auth/rest_psd'; //重置密码
 

+ 15 - 11
packages/cs_widgets/lib/ext/ex_widget.dart

@@ -491,25 +491,29 @@ extension ExWidget on Widget {
 
   /// 手势
   Widget onTap(
-    GestureTapCallback onTap, {
-    Key? key,
-    HitTestBehavior? behavior,
-    ClickType type = ClickType.none, //默认没有点击类型
-    int milliseconds = 500, //点击类型的时间戳(毫秒)
-    bool excludeFromSemantics = false,
-    DragStartBehavior dragStartBehavior = DragStartBehavior.start,
-  }) =>
+      GestureTapCallback onTap, {
+        Key? key,
+        HitTestBehavior? behavior,
+        ClickType type = ClickType.none,
+        int milliseconds = 500,
+        bool excludeFromSemantics = false,
+        DragStartBehavior dragStartBehavior = DragStartBehavior.start,
+        double padding = 0,  // 通过 padding 参数控制点击范围的扩展
+      }) =>
       GestureDetector(
         key: key,
         onTap: type == ClickType.debounce
             ? onTap.debounce(milliseconds)
             : type == ClickType.throttle
-                ? onTap.throttle(milliseconds)
-                : onTap,
+            ? onTap.throttle(milliseconds)
+            : onTap,
         behavior: behavior ?? HitTestBehavior.opaque,
         excludeFromSemantics: excludeFromSemantics,
         dragStartBehavior: dragStartBehavior,
-        child: this,
+        child: Padding(
+          padding: EdgeInsets.all(padding),  // 通过 Padding 扩大点击区域
+          child: this,
+        ),
       );
 
   /// 长按手势

+ 18 - 15
packages/cs_widgets/lib/my_appbar.dart

@@ -1,3 +1,4 @@
+import 'package:cs_resources/theme/theme_config.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
@@ -20,26 +21,28 @@ class MyAppBar {
       Color backgroundColor = Colors.transparent,
       SystemUiOverlayStyle? systemUiOverlayStyle,
       bool showBottomDivider = false,
+      bool showBackButton = true, //是否展示返回按钮
       List<Widget>? actions}) {
     // 检查当前主题是亮色还是暗色
     final bool isDarkMode = Theme.of(context).brightness == Brightness.dark;
 
     return AppBar(
-      //设置变色与背景颜色一致,避免滚动的时候AppBar变色
       backgroundColor: backgroundColor,
       surfaceTintColor: backgroundColor,
-      systemOverlayStyle: systemUiOverlayStyle,
-      // 如果没有自带的返回按钮,直接使用系统自带的返回图标
-      leading: backIconPath != null
-          ? IconButton(
-              icon: MyAssetImage(
-                backIconPath,
-                width: backIconWidth ?? 11,
-                height: backIconHeight ?? 18,
-              ),
-              onPressed: backCallback,
-            )
-          : null,
+      systemOverlayStyle: systemUiOverlayStyle ?? ThemeConfig.getSystemUiOverlayStyleByTheme(context),
+      // 根据 showBackButton 参数决定是否显示返回按钮
+      leading: showBackButton
+          ? (backIconPath != null
+              ? IconButton(
+                  icon: MyAssetImage(
+                    backIconPath,
+                    width: backIconWidth ?? 11,
+                    height: backIconHeight ?? 18,
+                  ),
+                  onPressed: backCallback,
+                )
+              : null) // 使用系统默认返回按钮
+          : const SizedBox.shrink(),
       iconTheme: IconThemeData(color: isDarkMode ? Colors.white : Theme.of(context).colorScheme.primary),
       centerTitle: true,
       title: subTitle == null
@@ -64,7 +67,7 @@ class MyAppBar {
             ),
       actions: actions,
       elevation: 0.0,
-      bottom: showBottomDivider // 根据变量控制 bottom 的显示
+      bottom: showBottomDivider
           ? const PreferredSize(
               preferredSize: Size.fromHeight(0.5),
               child: Divider(
@@ -98,7 +101,7 @@ class MyAppBar {
     return AppBar(
       backgroundColor: backgroundColor,
       surfaceTintColor: backgroundColor,
-      systemOverlayStyle: systemUiOverlayStyle,
+      systemOverlayStyle: systemUiOverlayStyle ?? ThemeConfig.getSystemUiOverlayStyleByTheme(context),
       // 标题与其他控件的间隔
       titleSpacing: 0,
       // 如果没有自带的返回按钮,直接使用系统自带的返回图标

+ 40 - 27
packages/cs_widgets/lib/my_button.dart

@@ -22,24 +22,25 @@ import 'package:shared/utils/ext_dart.dart';
 class MyButton extends StatelessWidget {
   const MyButton({
     Key? key,
-    required this.onPressed, //必选,点击回调
+    required this.onPressed,
     this.text = '',
     this.fontSize = 16,
     this.textColor,
     this.disabledTextColor,
     this.backgroundColor,
     this.disabledBackgroundColor,
-    this.minHeight = 43.0, //最高高度,默认43
-    this.minWidth = double.infinity, //最小宽度,默认充满控件
-    this.padding = const EdgeInsets.symmetric(horizontal: 16.0), //内间距,默认是横向内间距
-    this.radius = 5.0, //圆角
-    this.enableOverlay = true, //是否支持水波纹效果,不过这个效果对比InkWell比较克制,推荐开启
-    this.elevation = 0.0, //是否支持阴影,设置Z轴高度
-    this.shadowColor = Colors.black, //阴影的颜色
-    this.side = BorderSide.none, //边框的设置
+    this.minHeight = 43.0,
+    this.minWidth = double.infinity,
+    this.padding = const EdgeInsets.symmetric(horizontal: 16.0),
+    this.radius = 5.0,
+    this.enableOverlay = true,
+    this.elevation = 0.0,
+    this.shadowColor = Colors.black,
+    this.side = BorderSide.none,
     this.fontWeight,
     this.type = ClickType.none,
     this.milliseconds = 500,
+    this.isEnabled = true, // 控制按钮是否可用
   }) : super(key: key);
 
   final String text;
@@ -58,42 +59,49 @@ class MyButton extends StatelessWidget {
   final double elevation;
   final Color? shadowColor;
   final FontWeight? fontWeight;
-  final ClickType type; //默认没有点击类型
-  final int milliseconds; //点击类型的时间戳(毫秒)
+  final ClickType type;
+  final int milliseconds;
+  final bool isEnabled; // 控制按钮是否可用
 
   @override
   Widget build(BuildContext context) {
     return TextButton(
-        onPressed: type == ClickType.debounce
+        onPressed: isEnabled
+            ? (type == ClickType.debounce
             ? onPressed?.debounce(milliseconds)
             : type == ClickType.throttle
-                ? onPressed?.throttle(milliseconds)
-                : onPressed,
+            ? onPressed?.throttle(milliseconds)
+            : onPressed)
+            : null, // 如果按钮不可用,则 onPressed 设为 null
         style: ButtonStyle(
-          // 文字颜色
-          //               MaterialStateProperty.all            //各种状态都是这个颜色
           foregroundColor: MaterialStateProperty.resolveWith(
-            //根据不同的状态展示不同的颜色
-            (states) {
+                (states) {
               if (states.contains(MaterialState.disabled)) {
-                return DarkThemeUtil.multiColors(context,disabledTextColor ?? Colors.grey, darkColor: Colors.grey);
+                return DarkThemeUtil.multiColors(
+                    context, disabledTextColor ?? Colors.grey,
+                    darkColor: Colors.grey);
               }
-              return DarkThemeUtil.multiColors(context,textColor ?? Colors.white, darkColor: Colors.white);
+              return DarkThemeUtil.multiColors(
+                  context, textColor ?? Colors.white,
+                  darkColor: Colors.white);
             },
           ),
-          // 背景颜色
           backgroundColor: MaterialStateProperty.resolveWith((states) {
             if (states.contains(MaterialState.disabled)) {
               return disabledBackgroundColor;
             }
             return backgroundColor;
           }),
-          // 水波纹
           overlayColor: MaterialStateProperty.resolveWith((states) {
-            return enableOverlay ? DarkThemeUtil.multiColors(context,textColor ?? Colors.white)?.withOpacity(0.12) : Colors.transparent;
+            return enableOverlay
+                ? DarkThemeUtil.multiColors(context, textColor ?? Colors.white)
+                ?.withOpacity(0.12)
+                : Colors.transparent;
           }),
-          // 按钮最小大小
-          minimumSize: (minWidth == null || minHeight == null) ? null : MaterialStateProperty.all<Size>(Size(minWidth!, minHeight!)),
+          minimumSize: (minWidth == null || minHeight == null)
+              ? null
+              : MaterialStateProperty.all<Size>(
+              Size(minWidth!, minHeight!)),
           padding: MaterialStateProperty.all<EdgeInsetsGeometry>(padding),
           shape: MaterialStateProperty.all<OutlinedBorder>(
             RoundedRectangleBorder(
@@ -102,11 +110,16 @@ class MyButton extends StatelessWidget {
           ),
           side: MaterialStateProperty.all<BorderSide>(side),
           elevation: MaterialStateProperty.all<double>(elevation),
-          shadowColor: MaterialStateProperty.all<Color>(DarkThemeUtil.multiColors(context,shadowColor ?? Colors.black, darkColor: Colors.white)!),
+          shadowColor: MaterialStateProperty.all<Color>(
+              DarkThemeUtil.multiColors(
+                  context, shadowColor ?? Colors.black,
+                  darkColor: Colors.white)!),
         ),
         child: Text(
           text,
-          style: TextStyle(fontSize: fontSize, fontWeight: fontWeight ?? FontWeight.w400),
+          style: TextStyle(
+              fontSize: fontSize, fontWeight: fontWeight ?? FontWeight.w400),
         ));
   }
 }
+

+ 9 - 5
packages/cs_widgets/lib/my_text_field.dart

@@ -24,6 +24,8 @@ class MyTextField extends StatelessWidget {
   String? hintText;
   TextStyle? hintStyle;
   TextStyle? style;
+  final String? subHintText; //提示附文本
+  final TextStyle? subHintStyle;
   bool? autofocus;
   int? maxLines = 1;
   InputBorder? border;
@@ -65,6 +67,8 @@ class MyTextField extends StatelessWidget {
     this.cursorColor, // 光标颜色
     this.hintText, //提示文本
     this.hintStyle, //提示文本样式
+    this.subHintText, // 新的子提示文本
+    this.subHintStyle, // 新的子提示文本样式
     this.style, //默认的文本样式
     this.autofocus = false, // 自动聚焦
     this.maxLines = 1, //最多行数,高度与行数同步
@@ -79,7 +83,7 @@ class MyTextField extends StatelessWidget {
     this.obscureText = false, //是否隐藏文本,即显示密码类型
     this.height = 50.0,
     this.fillBackgroundColor, //整体的背景颜色
-    this.fillCornerRadius, //整体的背景颜色圆角
+    this.fillCornerRadius = 5.0, //整体的背景颜色圆角
     this.padding = EdgeInsets.zero, //整体布局的Padding
     this.margin = EdgeInsets.zero, //整体布局的Margin
     this.decoration, //自定义装饰
@@ -127,7 +131,7 @@ class MyTextField extends StatelessWidget {
               focusNode: focusNode,
               obscureText: obscureText,
               cursorWidth: cursorWidth,
-              cursorColor: DarkThemeUtil.multiColors(context,cursorColor, darkColor: Colors.white),
+              cursorColor: DarkThemeUtil.multiColors(context, cursorColor, darkColor: Colors.white),
               autofocus: autofocus!,
               controller: controller,
               inputFormatters: inputFormatters,
@@ -140,9 +144,9 @@ class MyTextField extends StatelessWidget {
                     suffixIcon: showRightIcon == true ? rightWidget : null,
                     labelText: labelText,
                     errorText: errorText,
-                    errorStyle: TextStyle(color: hexToColor("#7BABC8"), fontSize: 11.5),
-                    errorBorder: OutlineInputBorder(
-                      borderSide: BorderSide(color: hexToColor("#7BABC8")),
+                    errorStyle: const TextStyle(color: Colors.redAccent, fontSize: 11.5, height: 0.5),
+                    errorBorder: const OutlineInputBorder(
+                      borderSide: BorderSide(color: Colors.redAccent),
                     ),
                   ),
               onChanged: changeActionType == ClickType.debounce

+ 1 - 1
packages/cs_widgets/lib/shatter/custom_check_box.dart

@@ -103,7 +103,7 @@ class _CustomCheckBoxState extends State<CustomCheckBox> {
     return Row(
       mainAxisSize: MainAxisSize.min,
       children: <Widget>[
-        MyAssetImage(path, width: 20.5, height: 20.5),
+        MyAssetImage(path, width: 15.5, height: 15.5),
         const SizedBox(width: 10),
         MyTextView(
           text,