nex_docus/frontend/src/pages/Profile/ProfilePage.jsx

243 lines
7.2 KiB
React
Raw Normal View History

2025-12-20 11:18:59 +00:00
import { useState, useEffect } from 'react'
import { Card, Tabs, Form, Input, Button, Avatar, Upload, message } from 'antd'
import { UserOutlined, LockOutlined, UploadOutlined } from '@ant-design/icons'
import { getCurrentUser, updateProfile, changePassword } from '@/api/auth'
import useUserStore from '@/stores/userStore'
import MainLayout from '@/components/MainLayout/MainLayout'
import Toast from '@/components/Toast/Toast'
import './ProfilePage.css'
function ProfilePage() {
const [loading, setLoading] = useState(false)
const [userInfo, setUserInfo] = useState(null)
const [profileForm] = Form.useForm()
const [passwordForm] = Form.useForm()
const { user, setUser } = useUserStore()
useEffect(() => {
loadUserInfo()
}, [])
// 加载用户信息
const loadUserInfo = async () => {
try {
const res = await getCurrentUser()
setUserInfo(res.data)
profileForm.setFieldsValue({
username: res.data.username,
nickname: res.data.nickname,
email: res.data.email,
phone: res.data.phone,
})
} catch (error) {
console.error('Load user info error:', error)
message.error('加载用户信息失败')
}
}
// 更新资料
const handleUpdateProfile = async (values) => {
setLoading(true)
try {
const res = await updateProfile({
nickname: values.nickname,
email: values.email,
phone: values.phone,
})
setUserInfo(res.data)
setUser(res.data) // 更新全局用户信息
Toast.success('更新成功', '个人资料已更新')
} catch (error) {
console.error('Update profile error:', error)
message.error(error.response?.data?.detail || '更新失败')
} finally {
setLoading(false)
}
}
// 修改密码
const handleChangePassword = async (values) => {
setLoading(true)
try {
await changePassword({
old_password: values.old_password,
new_password: values.new_password,
})
Toast.success('修改成功', '密码已修改,请重新登录')
passwordForm.resetFields()
// 2秒后跳转到登录页
setTimeout(() => {
window.location.href = '/login'
}, 2000)
} catch (error) {
console.error('Change password error:', error)
message.error(error.response?.data?.detail || '修改密码失败')
} finally {
setLoading(false)
}
}
const tabItems = [
{
key: 'profile',
label: (
<span>
<UserOutlined />
个人资料
</span>
),
children: (
<div className="profile-tab-content">
<div className="avatar-section">
<Avatar size={100} icon={<UserOutlined />} />
<Upload showUploadList={false}>
<Button icon={<UploadOutlined />} style={{ marginTop: 16 }}>
更换头像
</Button>
</Upload>
<p className="avatar-tip">支持 JPGPNG 格式文件小于 2MB</p>
</div>
<Form
form={profileForm}
layout="vertical"
onFinish={handleUpdateProfile}
className="profile-form"
>
<Form.Item label="用户名" name="username">
<Input disabled />
</Form.Item>
<Form.Item
label="昵称"
name="nickname"
rules={[{ max: 50, message: '昵称最多50个字符' }]}
>
<Input placeholder="请输入昵称" />
</Form.Item>
<Form.Item
label="邮箱"
name="email"
rules={[
{ type: 'email', message: '请输入有效的邮箱地址' },
]}
>
<Input placeholder="请输入邮箱" />
</Form.Item>
<Form.Item
label="手机号"
name="phone"
rules={[
{ pattern: /^1[3-9]\d{9}$/, message: '请输入有效的手机号' },
]}
>
<Input placeholder="请输入手机号" />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" loading={loading}>
保存修改
</Button>
</Form.Item>
</Form>
</div>
),
},
{
key: 'password',
label: (
<span>
<LockOutlined />
修改密码
</span>
),
children: (
<div className="password-tab-content">
<Form
form={passwordForm}
layout="vertical"
onFinish={handleChangePassword}
className="password-form"
>
<Form.Item
label="当前密码"
name="old_password"
rules={[{ required: true, message: '请输入当前密码' }]}
>
<Input.Password placeholder="请输入当前密码" />
</Form.Item>
<Form.Item
label="新密码"
name="new_password"
rules={[
{ required: true, message: '请输入新密码' },
{ min: 6, message: '密码至少6个字符' },
{ max: 50, message: '密码最多50个字符' },
]}
>
<Input.Password placeholder="请输入新密码至少6个字符" />
</Form.Item>
<Form.Item
label="确认新密码"
name="confirm_password"
dependencies={['new_password']}
rules={[
{ required: true, message: '请确认新密码' },
({ getFieldValue }) => ({
validator(_, value) {
if (!value || getFieldValue('new_password') === value) {
return Promise.resolve()
}
return Promise.reject(new Error('两次输入的密码不一致'))
},
}),
]}
>
<Input.Password placeholder="请再次输入新密码" />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" loading={loading}>
修改密码
</Button>
<Button
style={{ marginLeft: 8 }}
onClick={() => passwordForm.resetFields()}
>
重置
</Button>
</Form.Item>
<div className="password-tips">
<h4>密码安全建议</h4>
<ul>
<li>密码长度至少6个字符</li>
<li>包含字母数字和特殊字符的组合更安全</li>
<li>不要使用过于简单的密码"123456"</li>
<li>定期更换密码提高账户安全性</li>
</ul>
</div>
</Form>
</div>
),
},
]
return (
<MainLayout>
<div className="profile-page">
<Card className="profile-card">
<h2 className="profile-title">个人中心</h2>
<Tabs items={tabItems} defaultActiveKey="profile" />
</Card>
</div>
</MainLayout>
)
}
export default ProfilePage