Files
x-server-mobile/frontend/src/pages/change-password/index.tsx
T
root 2e5f570b40 feat: 完善鉴权和密码功能,添加飞书通知模块
- 完善Token过期/不存在时跳转登录重新认证
- 实现正常的账号密码登录验证(邮箱/手机号+密码)
- 用户初始化密码设为工号(sn)
- 添加修改密码功能(API+前端页面)
- 修复扫码登录后跳转问题(zustand persist格式)
- 创建飞书通知服务 FeishuNotificationService
- 设置页面添加修改密码入口

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 15:19:37 +08:00

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>
)
}