2e5f570b40
- 完善Token过期/不存在时跳转登录重新认证 - 实现正常的账号密码登录验证(邮箱/手机号+密码) - 用户初始化密码设为工号(sn) - 添加修改密码功能(API+前端页面) - 修复扫码登录后跳转问题(zustand persist格式) - 创建飞书通知服务 FeishuNotificationService - 设置页面添加修改密码入口 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
115 lines
3.4 KiB
TypeScript
115 lines
3.4 KiB
TypeScript
import { useState } from 'react'
|
|
import { useNavigate } from 'react-router-dom'
|
|
import { Input, Button, Toast } from 'antd-mobile'
|
|
import { useTranslation } from 'react-i18next'
|
|
import { userApi } from '@/services/api'
|
|
import styles from './change-password.module.css'
|
|
|
|
export default function ChangePassword() {
|
|
const navigate = useNavigate()
|
|
const { t } = useTranslation()
|
|
const [formData, setFormData] = useState({
|
|
oldPassword: '',
|
|
newPassword: '',
|
|
confirmPassword: '',
|
|
})
|
|
const [loading, setLoading] = useState(false)
|
|
|
|
const handleChange = (field: string, value: string) => {
|
|
setFormData((prev) => ({ ...prev, [field]: value }))
|
|
}
|
|
|
|
const validateForm = (): string | null => {
|
|
if (!formData.oldPassword || !formData.newPassword || !formData.confirmPassword) {
|
|
return t('changePassword.fillAllFields')
|
|
}
|
|
if (formData.newPassword.length < 6) {
|
|
return t('changePassword.passwordTooShort')
|
|
}
|
|
if (formData.newPassword !== formData.confirmPassword) {
|
|
return t('changePassword.passwordMismatch')
|
|
}
|
|
return null
|
|
}
|
|
|
|
const handleSubmit = async () => {
|
|
const error = validateForm()
|
|
if (error) {
|
|
Toast.show(error)
|
|
return
|
|
}
|
|
|
|
setLoading(true)
|
|
try {
|
|
await userApi.changePassword({
|
|
old_password: formData.oldPassword,
|
|
new_password: formData.newPassword,
|
|
confirm_password: formData.confirmPassword,
|
|
})
|
|
Toast.show(t('changePassword.success'))
|
|
setTimeout(() => {
|
|
navigate(-1)
|
|
}, 1500)
|
|
} catch (error: any) {
|
|
const message = error.message || t('error.unknownError')
|
|
Toast.show(message)
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className={styles.page}>
|
|
<div className={styles.container}>
|
|
<h1 className={styles.title}>{t('changePassword.title')}</h1>
|
|
|
|
<div className={styles.form}>
|
|
<div className={styles.field}>
|
|
<label className={styles.label}>{t('changePassword.oldPassword')}</label>
|
|
<Input
|
|
type="password"
|
|
placeholder={t('changePassword.oldPasswordPlaceholder')}
|
|
value={formData.oldPassword}
|
|
onChange={(value) => handleChange('oldPassword', value)}
|
|
clearable
|
|
/>
|
|
</div>
|
|
|
|
<div className={styles.field}>
|
|
<label className={styles.label}>{t('changePassword.newPassword')}</label>
|
|
<Input
|
|
type="password"
|
|
placeholder={t('changePassword.newPasswordPlaceholder')}
|
|
value={formData.newPassword}
|
|
onChange={(value) => handleChange('newPassword', value)}
|
|
clearable
|
|
/>
|
|
</div>
|
|
|
|
<div className={styles.field}>
|
|
<label className={styles.label}>{t('changePassword.confirmPassword')}</label>
|
|
<Input
|
|
type="password"
|
|
placeholder={t('changePassword.confirmPasswordPlaceholder')}
|
|
value={formData.confirmPassword}
|
|
onChange={(value) => handleChange('confirmPassword', value)}
|
|
clearable
|
|
/>
|
|
</div>
|
|
|
|
<Button
|
|
block
|
|
color="primary"
|
|
size="large"
|
|
loading={loading}
|
|
onClick={handleSubmit}
|
|
className={styles.submitBtn}
|
|
>
|
|
{t('changePassword.submit')}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|