Files
Scoring-System/frontend/src/components/ProfileModal.jsx

125 lines
3.5 KiB
JavaScript

import React, { useState, useEffect } from 'react';
import { Modal, Form, Input, Upload, Button, message, Avatar } from 'antd';
import { UserOutlined, UploadOutlined, LoadingOutlined } from '@ant-design/icons';
import { useAuth } from '../context/AuthContext';
import { updateUserInfo, uploadUserAvatar } from '../api';
const ProfileModal = ({ visible, onClose }) => {
const { user, updateUser } = useAuth();
const [form] = Form.useForm();
const [loading, setLoading] = useState(false);
const [uploading, setUploading] = useState(false);
const [avatarUrl, setAvatarUrl] = useState('');
useEffect(() => {
if (visible && user) {
form.setFieldsValue({
nickname: user.nickname,
});
setAvatarUrl(user.avatar_url);
}
}, [visible, user, form]);
const handleUpload = async (file) => {
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
if (!isJpgOrPng) {
message.error('You can only upload JPG/PNG file!');
return Upload.LIST_IGNORE;
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
message.error('Image must smaller than 2MB!');
return Upload.LIST_IGNORE;
}
const formData = new FormData();
formData.append('file', file);
setUploading(true);
try {
const res = await uploadUserAvatar(formData);
if (res.data.success) {
setAvatarUrl(res.data.file_url);
message.success('头像上传成功');
} else {
message.error('头像上传失败: ' + (res.data.message || '未知错误'));
}
} catch (error) {
console.error('Upload failed:', error);
message.error('头像上传失败');
} finally {
setUploading(false);
}
return false; // Prevent default auto upload
};
const handleOk = async () => {
try {
const values = await form.validateFields();
setLoading(true);
const updateData = {
nickname: values.nickname,
avatar_url: avatarUrl
};
const res = await updateUserInfo(updateData);
updateUser(res.data);
message.success('个人信息更新成功');
onClose();
} catch (error) {
console.error('Update failed:', error);
message.error('更新失败');
} finally {
setLoading(false);
}
};
return (
<Modal
title="个人设置"
open={visible}
onOk={handleOk}
onCancel={onClose}
confirmLoading={loading}
centered
>
<Form
form={form}
layout="vertical"
style={{ marginTop: 20 }}
>
<Form.Item label="头像" style={{ textAlign: 'center' }}>
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 15 }}>
<Avatar
size={100}
src={avatarUrl}
icon={<UserOutlined />}
/>
<Upload
name="avatar"
showUploadList={false}
beforeUpload={handleUpload}
accept="image/*"
>
<Button icon={uploading ? <LoadingOutlined /> : <UploadOutlined />} loading={uploading}>
{uploading ? '上传中...' : '更换头像'}
</Button>
</Upload>
</div>
</Form.Item>
<Form.Item
name="nickname"
label="昵称"
rules={[{ required: true, message: '请输入昵称' }]}
>
<Input placeholder="请输入昵称" maxLength={20} />
</Form.Item>
</Form>
</Modal>
);
};
export default ProfileModal;