This is an automated email from the ASF dual-hosted git repository.

shuai pushed a commit to branch feat/1.3.1/ui
in repository https://gitbox.apache.org/repos/asf/incubator-answer.git


The following commit(s) were added to refs/heads/feat/1.3.1/ui by this push:
     new 76c55fcd fix: auto-scroll to the first invalid form field #873
76c55fcd is described below

commit 76c55fcd8e95099b68576e87db220368c9e43766
Author: shuai <[email protected]>
AuthorDate: Thu Apr 25 17:05:57 2024 +0800

    fix: auto-scroll to the first invalid form field #873
---
 ui/src/components/SchemaForm/index.tsx               |  3 +++
 ui/src/pages/Admin/Branding/index.tsx                |  4 +++-
 ui/src/pages/Admin/CssAndHtml/index.tsx              |  4 +++-
 ui/src/pages/Admin/General/index.tsx                 |  4 +++-
 ui/src/pages/Admin/Interface/index.tsx               |  4 +++-
 ui/src/pages/Admin/Legal/index.tsx                   |  4 +++-
 ui/src/pages/Admin/Login/index.tsx                   |  4 +++-
 ui/src/pages/Admin/Privileges/index.tsx              |  8 +++++---
 ui/src/pages/Admin/Seo/index.tsx                     |  4 +++-
 ui/src/pages/Admin/SettingsUsers/index.tsx           |  4 +++-
 ui/src/pages/Admin/Smtp/index.tsx                    |  4 +++-
 ui/src/pages/Admin/Themes/index.tsx                  |  4 +++-
 ui/src/pages/Admin/Write/index.tsx                   |  4 +++-
 ui/src/pages/Install/index.tsx                       |  9 ++++++++-
 ui/src/pages/Questions/Ask/index.tsx                 | 15 +++++++++++++--
 .../pages/Review/components/EditPostModal/index.tsx  | 13 +++++++++++++
 ui/src/pages/Tags/Create/index.tsx                   | 15 ++++++++++++++-
 .../Users/AccountForgot/components/sendEmail.tsx     |  9 ++++++++-
 .../pages/Users/ChangeEmail/components/sendEmail.tsx |  4 +++-
 ui/src/pages/Users/Login/index.tsx                   | 20 ++++++++++++++++++--
 ui/src/pages/Users/OauthBindEmail/index.tsx          |  9 ++++++++-
 ui/src/pages/Users/PasswordReset/index.tsx           | 15 ++++++++++++---
 .../Users/Register/components/SignUpForm/index.tsx   | 11 ++++++++++-
 .../Account/components/ModifyEmail/index.tsx         | 15 ++++++++++++---
 .../Settings/Account/components/ModifyPass/index.tsx | 18 ++++++++++++++----
 ui/src/pages/Users/Settings/Profile/index.tsx        | 17 +++++++++++++----
 26 files changed, 187 insertions(+), 38 deletions(-)

diff --git a/ui/src/components/SchemaForm/index.tsx 
b/ui/src/components/SchemaForm/index.tsx
index d0afb692..51fc4655 100644
--- a/ui/src/components/SchemaForm/index.tsx
+++ b/ui/src/components/SchemaForm/index.tsx
@@ -29,6 +29,7 @@ import { useTranslation } from 'react-i18next';
 import isEmpty from 'lodash/isEmpty';
 import classnames from 'classnames';
 
+import { scrollToElementTop } from '@/utils';
 import type * as Type from '@/common/interface';
 
 import type {
@@ -201,6 +202,7 @@ const SchemaForm: ForwardRefRenderFunction<FormRef, 
FormProps> = (
       if (onChange instanceof Function) {
         onChange({ ...formData });
       }
+      scrollToElementTop(document.getElementById(errors[0]));
       return false;
     }
     const syncErrors = await syncValidator();
@@ -216,6 +218,7 @@ const SchemaForm: ForwardRefRenderFunction<FormRef, 
FormProps> = (
       if (onChange instanceof Function) {
         onChange({ ...formData });
       }
+      scrollToElementTop(document.getElementById(syncErrors[0].key));
       return false;
     }
     return true;
diff --git a/ui/src/pages/Admin/Branding/index.tsx 
b/ui/src/pages/Admin/Branding/index.tsx
index 74c3d40e..bec7fc0f 100644
--- a/ui/src/pages/Admin/Branding/index.tsx
+++ b/ui/src/pages/Admin/Branding/index.tsx
@@ -25,7 +25,7 @@ import { FormDataType } from '@/common/interface';
 import { brandSetting, getBrandSetting } from '@/services';
 import { brandingStore } from '@/stores';
 import { useToast } from '@/hooks';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 
 const uploadType = 'branding';
 const Index: FC = () => {
@@ -145,6 +145,8 @@ const Index: FC = () => {
         if (err.isError) {
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
diff --git a/ui/src/pages/Admin/CssAndHtml/index.tsx 
b/ui/src/pages/Admin/CssAndHtml/index.tsx
index ae64a697..de376ad7 100644
--- a/ui/src/pages/Admin/CssAndHtml/index.tsx
+++ b/ui/src/pages/Admin/CssAndHtml/index.tsx
@@ -24,7 +24,7 @@ import type * as Type from '@/common/interface';
 import { getPageCustom, putPageCustom } from '@/services';
 import { SchemaForm, JSONSchema, initFormData, UISchema } from '@/components';
 import { useToast } from '@/hooks';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 import { customizeStore } from '@/stores';
 
 const Index: FC = () => {
@@ -124,6 +124,8 @@ const Index: FC = () => {
         if (err.isError) {
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
diff --git a/ui/src/pages/Admin/General/index.tsx 
b/ui/src/pages/Admin/General/index.tsx
index 3c6ff51a..6a1b080f 100644
--- a/ui/src/pages/Admin/General/index.tsx
+++ b/ui/src/pages/Admin/General/index.tsx
@@ -26,7 +26,7 @@ import { useToast } from '@/hooks';
 import { siteInfoStore } from '@/stores';
 import { useGeneralSetting, updateGeneralSetting } from '@/services';
 import Pattern from '@/common/pattern';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 
 const General: FC = () => {
   const { t } = useTranslation('translation', {
@@ -157,6 +157,8 @@ const General: FC = () => {
         if (err.isError) {
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
diff --git a/ui/src/pages/Admin/Interface/index.tsx 
b/ui/src/pages/Admin/Interface/index.tsx
index f4808f97..9c622048 100644
--- a/ui/src/pages/Admin/Interface/index.tsx
+++ b/ui/src/pages/Admin/Interface/index.tsx
@@ -39,7 +39,7 @@ import {
   loadLanguageOptions,
   setupAppTimeZone,
 } from '@/utils/localize';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 
 const Interface: FC = () => {
   const { t } = useTranslation('translation', {
@@ -141,6 +141,8 @@ const Interface: FC = () => {
         if (err.isError) {
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
diff --git a/ui/src/pages/Admin/Legal/index.tsx 
b/ui/src/pages/Admin/Legal/index.tsx
index d0dd2e7a..83561566 100644
--- a/ui/src/pages/Admin/Legal/index.tsx
+++ b/ui/src/pages/Admin/Legal/index.tsx
@@ -26,7 +26,7 @@ import type * as Type from '@/common/interface';
 import { SchemaForm, JSONSchema, initFormData, UISchema } from '@/components';
 import { useToast } from '@/hooks';
 import { getLegalSetting, putLegalSetting } from '@/services';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 
 const Legal: FC = () => {
   const { t } = useTranslation('translation', {
@@ -90,6 +90,8 @@ const Legal: FC = () => {
         if (err.isError) {
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
diff --git a/ui/src/pages/Admin/Login/index.tsx 
b/ui/src/pages/Admin/Login/index.tsx
index c58a293b..c43cfcff 100644
--- a/ui/src/pages/Admin/Login/index.tsx
+++ b/ui/src/pages/Admin/Login/index.tsx
@@ -24,7 +24,7 @@ import type * as Type from '@/common/interface';
 import { getLoginSetting, putLoginSetting } from '@/services';
 import { SchemaForm, JSONSchema, initFormData, UISchema } from '@/components';
 import { useToast } from '@/hooks';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 import { loginSettingStore } from '@/stores';
 
 const Index: FC = () => {
@@ -132,6 +132,8 @@ const Index: FC = () => {
         if (err.isError) {
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
diff --git a/ui/src/pages/Admin/Privileges/index.tsx 
b/ui/src/pages/Admin/Privileges/index.tsx
index dbe58f0c..5276912a 100644
--- a/ui/src/pages/Admin/Privileges/index.tsx
+++ b/ui/src/pages/Admin/Privileges/index.tsx
@@ -29,7 +29,7 @@ import {
   AdminSettingsPrivilege,
   AdminSettingsPrivilegeReq,
 } from '@/services';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 import { ADMIN_PRIVILEGE_CUSTOM_LEVEL } from '@/common/constants';
 
 const Index: FC = () => {
@@ -83,10 +83,10 @@ const Index: FC = () => {
           validator: (value: string) => {
             const val = Number(value);
             if (Number.isNaN(val)) {
-              return 'the input should be number';
+              return t('msg.should_be_number');
             }
             if (val < 1) {
-              return 'number should be equal or larger than 1';
+              return t('msg.number_larger_1');
             }
             return true;
           },
@@ -148,6 +148,8 @@ const Index: FC = () => {
         if (err.isError) {
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
diff --git a/ui/src/pages/Admin/Seo/index.tsx b/ui/src/pages/Admin/Seo/index.tsx
index 0424eae8..e539595b 100644
--- a/ui/src/pages/Admin/Seo/index.tsx
+++ b/ui/src/pages/Admin/Seo/index.tsx
@@ -24,7 +24,7 @@ import type * as Type from '@/common/interface';
 import { getSeoSetting, putSeoSetting } from '@/services';
 import { SchemaForm, JSONSchema, initFormData, UISchema } from '@/components';
 import { useToast } from '@/hooks';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 import { seoSettingStore } from '@/stores';
 
 const Index: FC = () => {
@@ -90,6 +90,8 @@ const Index: FC = () => {
         if (err.isError) {
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
diff --git a/ui/src/pages/Admin/SettingsUsers/index.tsx 
b/ui/src/pages/Admin/SettingsUsers/index.tsx
index a83c2e3b..e2714790 100644
--- a/ui/src/pages/Admin/SettingsUsers/index.tsx
+++ b/ui/src/pages/Admin/SettingsUsers/index.tsx
@@ -29,7 +29,7 @@ import {
   putUsersSetting,
   AdminSettingsUsers,
 } from '@/services';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 import * as Type from '@/common/interface';
 import { siteInfoStore } from '@/stores';
 
@@ -168,6 +168,8 @@ const Index: FC = () => {
         if (err.isError) {
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
diff --git a/ui/src/pages/Admin/Smtp/index.tsx 
b/ui/src/pages/Admin/Smtp/index.tsx
index 3103461f..40725c31 100644
--- a/ui/src/pages/Admin/Smtp/index.tsx
+++ b/ui/src/pages/Admin/Smtp/index.tsx
@@ -25,7 +25,7 @@ import { useToast } from '@/hooks';
 import { useSmtpSetting, updateSmtpSetting } from '@/services';
 import pattern from '@/common/pattern';
 import { SchemaForm, JSONSchema, UISchema, initFormData } from '@/components';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 
 const Smtp: FC = () => {
   const { t } = useTranslation('translation', {
@@ -182,6 +182,8 @@ const Smtp: FC = () => {
         if (err.isError) {
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
diff --git a/ui/src/pages/Admin/Themes/index.tsx 
b/ui/src/pages/Admin/Themes/index.tsx
index 346e2e05..0d219816 100644
--- a/ui/src/pages/Admin/Themes/index.tsx
+++ b/ui/src/pages/Admin/Themes/index.tsx
@@ -24,7 +24,7 @@ import type * as Type from '@/common/interface';
 import { getThemeSetting, putThemeSetting } from '@/services';
 import { SchemaForm, JSONSchema, initFormData, UISchema } from '@/components';
 import { useToast } from '@/hooks';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 import { themeSettingStore } from '@/stores';
 import { setupAppTheme } from '@/utils/localize';
 
@@ -135,6 +135,8 @@ const Index: FC = () => {
         if (err.isError) {
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
diff --git a/ui/src/pages/Admin/Write/index.tsx 
b/ui/src/pages/Admin/Write/index.tsx
index 7c837435..42806111 100644
--- a/ui/src/pages/Admin/Write/index.tsx
+++ b/ui/src/pages/Admin/Write/index.tsx
@@ -27,7 +27,7 @@ import {
   getRequireAndReservedTag,
   postRequireAndReservedTag,
 } from '@/services';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 import { writeSettingStore } from '@/stores';
 
 const Index: FC = () => {
@@ -121,6 +121,8 @@ const Index: FC = () => {
         if (err.isError) {
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
diff --git a/ui/src/pages/Install/index.tsx b/ui/src/pages/Install/index.tsx
index 69723d29..14a2b30b 100644
--- a/ui/src/pages/Install/index.tsx
+++ b/ui/src/pages/Install/index.tsx
@@ -29,7 +29,12 @@ import {
   installBaseInfo,
   checkConfigFileExists,
 } from '@/services';
-import { Storage, handleFormError, scrollToDocTop } from '@/utils';
+import {
+  Storage,
+  handleFormError,
+  scrollToDocTop,
+  scrollToElementTop,
+} from '@/utils';
 import { CURRENT_LANG_STORAGE_KEY } from '@/common/constants';
 
 import {
@@ -201,6 +206,8 @@ const Index: FC = () => {
         if (err.isError) {
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         } else {
           handleErr(err);
         }
diff --git a/ui/src/pages/Questions/Ask/index.tsx 
b/ui/src/pages/Questions/Ask/index.tsx
index 68ef0ed6..30939a2e 100644
--- a/ui/src/pages/Questions/Ask/index.tsx
+++ b/ui/src/pages/Questions/Ask/index.tsx
@@ -40,7 +40,12 @@ import {
   getTagsBySlugName,
   saveQuestionWithAnswer,
 } from '@/services';
-import { handleFormError, SaveDraft, storageExpires } from '@/utils';
+import {
+  handleFormError,
+  SaveDraft,
+  storageExpires,
+  scrollToElementTop,
+} from '@/utils';
 import { pathFactory } from '@/router/pathFactory';
 import { useCaptchaPlugin } from '@/utils/pluginKit';
 
@@ -300,6 +305,8 @@ const Ask = () => {
           editCaptcha?.handleCaptchaError(err.list);
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
@@ -321,6 +328,8 @@ const Ask = () => {
           if (!(captchaErr && err.list.length === 1)) {
             const data = handleFormError(err, formData);
             setFormData({ ...data });
+            const ele = document.getElementById(err.list[0].error_field);
+            scrollToElementTop(ele);
           }
         }
       });
@@ -331,6 +340,8 @@ const Ask = () => {
           if (!(captchaErr && err.list.length === 1)) {
             const data = handleFormError(err, formData);
             setFormData({ ...data });
+            const ele = document.getElementById(err.list[0].error_field);
+            scrollToElementTop(ele);
           }
         }
       });
@@ -443,7 +454,7 @@ const Ask = () => {
               </Form.Control.Feedback>
               {bool && <SearchQuestion similarQuestions={similarQuestions} />}
             </Form.Group>
-            <Form.Group controlId="body">
+            <Form.Group controlId="content">
               <Form.Label>{t('form.fields.body.label')}</Form.Label>
               <Form.Control
                 defaultValue={formData.content.value}
diff --git a/ui/src/pages/Review/components/EditPostModal/index.tsx 
b/ui/src/pages/Review/components/EditPostModal/index.tsx
index 4ee80b0a..9e7ae5e9 100644
--- a/ui/src/pages/Review/components/EditPostModal/index.tsx
+++ b/ui/src/pages/Review/components/EditPostModal/index.tsx
@@ -32,6 +32,7 @@ import {
   parseUserInfo,
   handleFormError,
   parseEditMentionUser,
+  scrollToElementTop,
 } from '@/utils';
 import type * as Type from '@/common/interface';
 
@@ -158,6 +159,15 @@ const Index: FC<Props> = ({
     setFormData({
       ...formData,
     });
+
+    if (!bol) {
+      const errObj = Object.keys(formData).filter(
+        (key) => formData[key].isInvalid,
+      );
+      const ele = document.getElementById(errObj[0]);
+      scrollToElementTop(ele);
+    }
+
     return bol;
   };
 
@@ -202,6 +212,9 @@ const Index: FC<Props> = ({
           editCaptcha?.handleCaptchaError(err.list);
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
diff --git a/ui/src/pages/Tags/Create/index.tsx 
b/ui/src/pages/Tags/Create/index.tsx
index 8b3b12bf..b0564f19 100644
--- a/ui/src/pages/Tags/Create/index.tsx
+++ b/ui/src/pages/Tags/Create/index.tsx
@@ -29,7 +29,7 @@ import { Editor, EditorRef } from '@/components';
 import { loggedUserInfoStore } from '@/stores';
 import type * as Type from '@/common/interface';
 import { createTag } from '@/services';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 import { TAG_SLUG_NAME_MAX_LENGTH } from '@/common/constants';
 
 interface FormDataItem {
@@ -107,10 +107,12 @@ const Index = () => {
 
   const checkValidated = (): boolean => {
     let bol = true;
+    let errObjKey = '';
     const { displayName, slugName } = formData;
 
     if (!displayName.value) {
       bol = false;
+      errObjKey = 'display_name';
       formData.displayName = {
         value: '',
         isInvalid: true,
@@ -118,6 +120,7 @@ const Index = () => {
       };
     } else if (displayName.value.length > TAG_SLUG_NAME_MAX_LENGTH) {
       bol = false;
+      errObjKey = 'display_name';
       formData.displayName = {
         value: displayName.value,
         isInvalid: true,
@@ -133,6 +136,7 @@ const Index = () => {
 
     if (!slugName.value) {
       bol = false;
+      errObjKey = 'slug_name';
       formData.slugName = {
         value: '',
         isInvalid: true,
@@ -140,6 +144,7 @@ const Index = () => {
       };
     } else if (slugName.value.length > TAG_SLUG_NAME_MAX_LENGTH) {
       bol = false;
+      errObjKey = 'slug_name';
       formData.slugName = {
         value: slugName.value,
         isInvalid: true,
@@ -156,6 +161,12 @@ const Index = () => {
     setFormData({
       ...formData,
     });
+
+    if (!bol) {
+      const ele = document.getElementById(errObjKey);
+      scrollToElementTop(ele);
+    }
+
     return bol;
   };
 
@@ -187,6 +198,8 @@ const Index = () => {
             { from: 'original_text', to: 'description' },
           ]);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
diff --git a/ui/src/pages/Users/AccountForgot/components/sendEmail.tsx 
b/ui/src/pages/Users/AccountForgot/components/sendEmail.tsx
index 5d7d2c9b..e1a823db 100644
--- a/ui/src/pages/Users/AccountForgot/components/sendEmail.tsx
+++ b/ui/src/pages/Users/AccountForgot/components/sendEmail.tsx
@@ -23,7 +23,7 @@ import { useTranslation } from 'react-i18next';
 
 import type { PasswordResetReq, FormDataType } from '@/common/interface';
 import { resetPassword } from '@/services';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 import { useCaptchaPlugin } from '@/utils/pluginKit';
 
 interface IProps {
@@ -62,6 +62,11 @@ const Index: FC<IProps> = ({ callback }) => {
     setFormData({
       ...formData,
     });
+    if (!bol) {
+      const ele = document.getElementById('email');
+      scrollToElementTop(ele);
+    }
+
     return bol;
   };
 
@@ -89,6 +94,8 @@ const Index: FC<IProps> = ({ callback }) => {
           emailCaptcha?.handleCaptchaError(err.list);
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
diff --git a/ui/src/pages/Users/ChangeEmail/components/sendEmail.tsx 
b/ui/src/pages/Users/ChangeEmail/components/sendEmail.tsx
index 419e226e..eb279ef4 100644
--- a/ui/src/pages/Users/ChangeEmail/components/sendEmail.tsx
+++ b/ui/src/pages/Users/ChangeEmail/components/sendEmail.tsx
@@ -25,7 +25,7 @@ import { useNavigate } from 'react-router-dom';
 import type { PasswordResetReq, FormDataType } from '@/common/interface';
 import { loggedUserInfoStore } from '@/stores';
 import { changeEmail } from '@/services';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 import { useCaptchaPlugin } from '@/utils/pluginKit';
 
 const Index: FC = () => {
@@ -89,6 +89,8 @@ const Index: FC = () => {
           emailCaptcha?.handleCaptchaError(err.list);
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
diff --git a/ui/src/pages/Users/Login/index.tsx 
b/ui/src/pages/Users/Login/index.tsx
index f0435f18..ffaf12f4 100644
--- a/ui/src/pages/Users/Login/index.tsx
+++ b/ui/src/pages/Users/Login/index.tsx
@@ -30,7 +30,13 @@ import {
   loginSettingStore,
   userCenterStore,
 } from '@/stores';
-import { floppyNavigation, guard, handleFormError, userCenter } from '@/utils';
+import {
+  floppyNavigation,
+  guard,
+  handleFormError,
+  userCenter,
+  scrollToElementTop,
+} from '@/utils';
 import { useCaptchaPlugin } from '@/utils/pluginKit';
 import { login, UcAgent } from '@/services';
 import { setupAppTheme } from '@/utils/localize';
@@ -96,6 +102,14 @@ const Index: React.FC = () => {
     setFormData({
       ...formData,
     });
+    if (!bol) {
+      const errObj = Object.keys(formData).filter(
+        (key) => formData[key].isInvalid,
+      );
+      const ele = document.getElementById(errObj[0]);
+      scrollToElementTop(ele);
+    }
+
     return bol;
   };
 
@@ -132,6 +146,8 @@ const Index: React.FC = () => {
           const data = handleFormError(err, formData);
           setFormData({ ...data });
           passwordCaptcha?.handleCaptchaError?.(err.list);
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
@@ -210,7 +226,7 @@ const Index: React.FC = () => {
                   </Form.Control.Feedback>
                 </Form.Group>
 
-                <Form.Group controlId="password" className="mb-3">
+                <Form.Group controlId="pass" className="mb-3">
                   <div className="d-flex justify-content-between">
                     <Form.Label>{t('password.label')}</Form.Label>
                     <Link to="/users/account-recovery" tabIndex={2}>
diff --git a/ui/src/pages/Users/OauthBindEmail/index.tsx 
b/ui/src/pages/Users/OauthBindEmail/index.tsx
index f6a0dc0c..5e3735a0 100644
--- a/ui/src/pages/Users/OauthBindEmail/index.tsx
+++ b/ui/src/pages/Users/OauthBindEmail/index.tsx
@@ -29,7 +29,7 @@ import { loggedUserInfoStore } from '@/stores';
 import { oAuthBindEmail, getLoggedUserInfo } from '@/services';
 import Storage from '@/utils/storage';
 import { LOGGED_TOKEN_STORAGE_KEY } from '@/common/constants';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 
 const Index: FC = () => {
   const { t } = useTranslation('translation', {
@@ -70,6 +70,11 @@ const Index: FC = () => {
     setFormData({
       ...formData,
     });
+    if (!bol) {
+      const ele = document.getElementById('email');
+      scrollToElementTop(ele);
+    }
+
     return bol;
   };
 
@@ -142,6 +147,8 @@ const Index: FC = () => {
           if (err.isError) {
             const data = handleFormError(err, formData);
             setFormData({ ...data });
+            const ele = document.getElementById(err.list[0].error_field);
+            scrollToElementTop(ele);
           }
         });
     }
diff --git a/ui/src/pages/Users/PasswordReset/index.tsx 
b/ui/src/pages/Users/PasswordReset/index.tsx
index 9d04e89a..d43f032f 100644
--- a/ui/src/pages/Users/PasswordReset/index.tsx
+++ b/ui/src/pages/Users/PasswordReset/index.tsx
@@ -26,7 +26,7 @@ import { usePageTags } from '@/hooks';
 import { loggedUserInfoStore } from '@/stores';
 import type { FormDataType } from '@/common/interface';
 import { replacementPassword } from '@/services';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 
 const Index: React.FC = () => {
   const { t } = useTranslation('translation', { keyPrefix: 'password_reset' });
@@ -101,6 +101,13 @@ const Index: React.FC = () => {
     setFormData({
       ...formData,
     });
+    if (!bol) {
+      const errObj = Object.keys(formData).filter(
+        (key) => formData[key].isInvalid,
+      );
+      const ele = document.getElementById(errObj[0]);
+      scrollToElementTop(ele);
+    }
     return bol;
   };
 
@@ -128,6 +135,8 @@ const Index: React.FC = () => {
         if (err.isError) {
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
@@ -140,7 +149,7 @@ const Index: React.FC = () => {
       {step === 1 && (
         <Col className="mx-auto" md={6} lg={4} xl={3}>
           <Form noValidate onSubmit={handleSubmit} autoComplete="off">
-            <Form.Group controlId="email" className="mb-3">
+            <Form.Group controlId="pass" className="mb-3">
               <Form.Label>{t('password.label')}</Form.Label>
               <Form.Control
                 autoComplete="off"
@@ -162,7 +171,7 @@ const Index: React.FC = () => {
               </Form.Control.Feedback>
             </Form.Group>
 
-            <Form.Group controlId="password" className="mb-3">
+            <Form.Group controlId="passSecond" className="mb-3">
               <Form.Label>{t('password_confirm.label')}</Form.Label>
               <Form.Control
                 autoComplete="off"
diff --git a/ui/src/pages/Users/Register/components/SignUpForm/index.tsx 
b/ui/src/pages/Users/Register/components/SignUpForm/index.tsx
index 433f0427..bfa5d23e 100644
--- a/ui/src/pages/Users/Register/components/SignUpForm/index.tsx
+++ b/ui/src/pages/Users/Register/components/SignUpForm/index.tsx
@@ -26,7 +26,7 @@ import { useCaptchaPlugin } from '@/utils/pluginKit';
 import type { FormDataType, RegisterReqParams } from '@/common/interface';
 import { register } from '@/services';
 import userStore from '@/stores/loggedUserInfo';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 import { useLegalClick } from '@/behaviour/useLegalClick';
 
 interface Props {
@@ -84,6 +84,13 @@ const Index: React.FC<Props> = ({ callback }) => {
     setFormData({
       ...formData,
     });
+    if (!bol) {
+      const errObj = Object.keys(formData).filter(
+        (key) => formData[key].isInvalid,
+      );
+      const ele = document.getElementById(errObj[0]);
+      scrollToElementTop(ele);
+    }
     return bol;
   };
 
@@ -116,6 +123,8 @@ const Index: React.FC<Props> = ({ callback }) => {
           emailCaptcha?.handleCaptchaError(err.list);
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
diff --git 
a/ui/src/pages/Users/Settings/Account/components/ModifyEmail/index.tsx 
b/ui/src/pages/Users/Settings/Account/components/ModifyEmail/index.tsx
index 27eda181..17af4b01 100644
--- a/ui/src/pages/Users/Settings/Account/components/ModifyEmail/index.tsx
+++ b/ui/src/pages/Users/Settings/Account/components/ModifyEmail/index.tsx
@@ -25,7 +25,7 @@ import type * as Type from '@/common/interface';
 import { useToast } from '@/hooks';
 import { useCaptchaPlugin } from '@/utils/pluginKit';
 import { getLoggedUserInfo, changeEmail } from '@/services';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 
 const Index: FC = () => {
   const { t } = useTranslation('translation', {
@@ -82,6 +82,13 @@ const Index: FC = () => {
     setFormData({
       ...formData,
     });
+    if (!bol) {
+      const errObj = Object.keys(formData).filter(
+        (key) => formData[key].isInvalid,
+      );
+      const ele = document.getElementById(errObj[0]);
+      scrollToElementTop(ele);
+    }
     return bol;
   };
 
@@ -129,6 +136,8 @@ const Index: FC = () => {
           emailCaptcha?.handleCaptchaError(err.list);
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
@@ -175,7 +184,7 @@ const Index: FC = () => {
       )}
       {step === 2 && (
         <Form noValidate onSubmit={handleSubmit}>
-          <Form.Group controlId="currentPass" className="mb-3">
+          <Form.Group controlId="pass" className="mb-3">
             <Form.Label>{t('pass.label')}</Form.Label>
             <Form.Control
               autoComplete="new-password"
@@ -197,7 +206,7 @@ const Index: FC = () => {
             </Form.Control.Feedback>
           </Form.Group>
 
-          <Form.Group controlId="newEmail" className="mb-3">
+          <Form.Group controlId="e_mail" className="mb-3">
             <Form.Label>{t('new_email.label')}</Form.Label>
             <Form.Control
               autoComplete="off"
diff --git 
a/ui/src/pages/Users/Settings/Account/components/ModifyPass/index.tsx 
b/ui/src/pages/Users/Settings/Account/components/ModifyPass/index.tsx
index bdc84bd7..4f4ec0cb 100644
--- a/ui/src/pages/Users/Settings/Account/components/ModifyPass/index.tsx
+++ b/ui/src/pages/Users/Settings/Account/components/ModifyPass/index.tsx
@@ -27,7 +27,7 @@ import { useToast } from '@/hooks';
 import { useCaptchaPlugin } from '@/utils/pluginKit';
 import type { FormDataType } from '@/common/interface';
 import { modifyPassword } from '@/services';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 import { loggedUserInfoStore } from '@/stores';
 
 const Index: FC = () => {
@@ -123,6 +123,14 @@ const Index: FC = () => {
     setFormData({
       ...formData,
     });
+    if (!bol) {
+      const errObj = Object.keys(formData).filter(
+        (key) => formData[key].isInvalid,
+      );
+      const ele = document.getElementById(errObj[0]);
+      scrollToElementTop(ele);
+    }
+
     return bol;
   };
 
@@ -154,6 +162,8 @@ const Index: FC = () => {
           infoCaptcha?.handleCaptchaError(err.list);
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
@@ -179,7 +189,7 @@ const Index: FC = () => {
       {showForm ? (
         <Form noValidate onSubmit={handleSubmit}>
           <Form.Group
-            controlId="oldPass"
+            controlId="old_pass"
             className={classname('mb-3', user.have_password ? '' : 'd-none')}>
             <Form.Label>{t('current_pass.label')}</Form.Label>
             <Form.Control
@@ -203,7 +213,7 @@ const Index: FC = () => {
             </Form.Control.Feedback>
           </Form.Group>
 
-          <Form.Group controlId="newPass" className="mb-3">
+          <Form.Group controlId="new_pass" className="mb-3">
             <Form.Label>{t('new_pass.label')}</Form.Label>
             <Form.Control
               autoComplete="off"
@@ -225,7 +235,7 @@ const Index: FC = () => {
             </Form.Control.Feedback>
           </Form.Group>
 
-          <Form.Group controlId="newPass2" className="mb-3">
+          <Form.Group controlId="pass2" className="mb-3">
             <Form.Label>{t('pass_confirm.label')}</Form.Label>
             <Form.Control
               autoComplete="off"
diff --git a/ui/src/pages/Users/Settings/Profile/index.tsx 
b/ui/src/pages/Users/Settings/Profile/index.tsx
index 0e935fa7..ab2ee0f1 100644
--- a/ui/src/pages/Users/Settings/Profile/index.tsx
+++ b/ui/src/pages/Users/Settings/Profile/index.tsx
@@ -33,7 +33,7 @@ import {
   getUcSettings,
   UcSettingAgent,
 } from '@/services';
-import { handleFormError } from '@/utils';
+import { handleFormError, scrollToElementTop } from '@/utils';
 
 const Index: React.FC = () => {
   const { t } = useTranslation('translation', {
@@ -209,6 +209,13 @@ const Index: React.FC = () => {
     setFormData({
       ...formData,
     });
+    if (!bol) {
+      const errObj = Object.keys(formData).filter(
+        (key) => formData[key].isInvalid,
+      );
+      const ele = document.getElementById(errObj[0]);
+      scrollToElementTop(ele);
+    }
     return bol;
   };
 
@@ -247,6 +254,8 @@ const Index: React.FC = () => {
         if (err.isError) {
           const data = handleFormError(err, formData);
           setFormData({ ...data });
+          const ele = document.getElementById(err.list[0].error_field);
+          scrollToElementTop(ele);
         }
       });
   };
@@ -295,7 +304,7 @@ const Index: React.FC = () => {
       ) : null}
       {!ucAgent?.enabled || profileAgent?.enabled === false ? (
         <Form noValidate onSubmit={handleSubmit}>
-          <Form.Group controlId="displayName" className="mb-3">
+          <Form.Group controlId="display_name" className="mb-3">
             <Form.Label>{t('display_name.label')}</Form.Label>
             <Form.Control
               required
@@ -318,7 +327,7 @@ const Index: React.FC = () => {
             </Form.Control.Feedback>
           </Form.Group>
 
-          <Form.Group controlId="userName" className="mb-3">
+          <Form.Group controlId="username" className="mb-3">
             <Form.Label>{t('username.label')}</Form.Label>
             <Form.Control
               required
@@ -498,7 +507,7 @@ const Index: React.FC = () => {
             </Form.Control.Feedback>
           </Form.Group>
 
-          <Form.Group controlId="email" className="mb-3">
+          <Form.Group controlId="location" className="mb-3">
             <Form.Label>{`${t('location.label')} ${t('optional', {
               keyPrefix: 'form',
             })}`}</Form.Label>


Reply via email to