fix: 修复登录表单验证错误显示重叠问题

- 重构登录表单结构,使用 fieldWrapper 包裹输入框和错误信息
- 修复验证错误消息与输入框重叠的布局问题
- 更新依赖版本

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
hailin 2025-11-26 02:19:58 -08:00
parent ef5e9aec3f
commit 1296bd607c
4 changed files with 52 additions and 48 deletions

View File

@ -29,7 +29,7 @@
"eslint-config-next": "^15.1.6", "eslint-config-next": "^15.1.6",
"prettier": "^3.4.2", "prettier": "^3.4.2",
"sass": "^1.83.4", "sass": "^1.83.4",
"typescript": "^5.7.3" "typescript": "5.9.3"
} }
}, },
"node_modules/@babel/runtime": { "node_modules/@babel/runtime": {

View File

@ -35,6 +35,6 @@
"eslint-config-next": "^15.1.6", "eslint-config-next": "^15.1.6",
"prettier": "^3.4.2", "prettier": "^3.4.2",
"sass": "^1.83.4", "sass": "^1.83.4",
"typescript": "^5.7.3" "typescript": "5.9.3"
} }
} }

View File

@ -92,33 +92,31 @@
&__inputGroup { &__inputGroup {
align-self: stretch; align-self: stretch;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
border-radius: 6px;
background-color: transparent;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
gap: 16px;
}
&__fieldWrapper {
align-self: stretch;
display: flex;
flex-direction: column;
gap: 4px;
} }
&__inputWrapper { &__inputWrapper {
align-self: stretch; align-self: stretch;
background-color: $white; background-color: $white;
border: 1px solid #cbd5e1; border: 1px solid #cbd5e1;
border-radius: 6px;
overflow: hidden; overflow: hidden;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
justify-content: center; justify-content: center;
padding: 12px; padding: 12px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
&:first-child {
border-radius: 6px 6px 0 0;
border-bottom: none;
}
&:last-child {
border-radius: 0 0 6px 6px;
}
&--error { &--error {
border-color: $error-color; border-color: $error-color;

View File

@ -125,43 +125,49 @@ export default function LoginPage() {
<form className={styles.login__form} onSubmit={handleSubmit}> <form className={styles.login__form} onSubmit={handleSubmit}>
{/* 输入框组 */} {/* 输入框组 */}
<div className={styles.login__inputGroup}> <div className={styles.login__inputGroup}>
<div {/* 邮箱输入字段 */}
className={`${styles.login__inputWrapper} ${ <div className={styles.login__fieldWrapper}>
errors.email ? styles['login__inputWrapper--error'] : '' <div
}`} className={`${styles.login__inputWrapper} ${
> errors.email ? styles['login__inputWrapper--error'] : ''
<input }`}
className={styles.login__input} >
placeholder="电子邮件" <input
type="email" className={styles.login__input}
value={formData.email} placeholder="电子邮件"
onChange={handleInputChange('email')} type="email"
aria-label="电子邮件" value={formData.email}
autoComplete="email" onChange={handleInputChange('email')}
/> aria-label="电子邮件"
autoComplete="email"
/>
</div>
{errors.email && (
<span className={styles.login__error}>{errors.email}</span>
)}
</div> </div>
{errors.email && (
<span className={styles.login__error}>{errors.email}</span>
)}
<div {/* 密码输入字段 */}
className={`${styles.login__inputWrapper} ${ <div className={styles.login__fieldWrapper}>
errors.password ? styles['login__inputWrapper--error'] : '' <div
}`} className={`${styles.login__inputWrapper} ${
> errors.password ? styles['login__inputWrapper--error'] : ''
<input }`}
className={styles.login__input} >
placeholder="密码" <input
type="password" className={styles.login__input}
value={formData.password} placeholder="密码"
onChange={handleInputChange('password')} type="password"
aria-label="密码" value={formData.password}
autoComplete="current-password" onChange={handleInputChange('password')}
/> aria-label="密码"
autoComplete="current-password"
/>
</div>
{errors.password && (
<span className={styles.login__error}>{errors.password}</span>
)}
</div> </div>
{errors.password && (
<span className={styles.login__error}>{errors.password}</span>
)}
</div> </div>
{/* 忘记密码链接 */} {/* 忘记密码链接 */}