|
@@ -1,142 +1,30 @@
|
|
|
-import { postForm } from '@/request';
|
|
|
|
|
-import * as api from '@/services/login';
|
|
|
|
|
-import { message } from '@/utils/antdAppInstance';
|
|
|
|
|
-import { userKey } from '@/utils/authUtils';
|
|
|
|
|
-import { secureLocalStorage as ls } from '@/utils/localUtils';
|
|
|
|
|
-import {
|
|
|
|
|
- CloseOutlined,
|
|
|
|
|
- EditOutlined,
|
|
|
|
|
- LoadingOutlined,
|
|
|
|
|
- PlusOutlined,
|
|
|
|
|
- SaveOutlined,
|
|
|
|
|
-} from '@ant-design/icons';
|
|
|
|
|
|
|
+import { CloseOutlined, EditOutlined, SaveOutlined } from '@ant-design/icons';
|
|
|
import { ProFormText } from '@ant-design/pro-components';
|
|
import { ProFormText } from '@ant-design/pro-components';
|
|
|
-import { useModel } from '@umijs/max';
|
|
|
|
|
-import { Avatar, Button, Card, Col, Form, Row, Space, Upload } from 'antd';
|
|
|
|
|
-import React, { useEffect, useState } from 'react';
|
|
|
|
|
|
|
+import { Button, Card, Col, Form, Row, Space } from 'antd';
|
|
|
|
|
|
|
|
-const UserInfo: React.FC = () => {
|
|
|
|
|
- const { initialState, setInitialState } = useModel('@@initialState');
|
|
|
|
|
- const [form] = Form.useForm();
|
|
|
|
|
- const [isEditing, setIsEditing] = useState(false);
|
|
|
|
|
- const [loading, setLoading] = useState(false);
|
|
|
|
|
- const [uploading, setUploading] = useState(false);
|
|
|
|
|
- const [userInfo, setUserInfo] = useState<API.UserInfo | null>(null);
|
|
|
|
|
|
|
+import { AvatarUpload } from './components/AvatarUpload';
|
|
|
|
|
+import { useUserInfo } from './hooks/useUserInfo';
|
|
|
|
|
|
|
|
- useEffect(() => {
|
|
|
|
|
- if (initialState?.currentUser) {
|
|
|
|
|
- setUserInfo(initialState.currentUser);
|
|
|
|
|
- form.setFieldsValue({
|
|
|
|
|
- username: initialState.currentUser.username,
|
|
|
|
|
- nickname: initialState.currentUser.nickname,
|
|
|
|
|
- avatar: initialState.currentUser.avatar,
|
|
|
|
|
- email: initialState.currentUser.email,
|
|
|
|
|
- phone: initialState.currentUser.phone,
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
- }, [initialState?.currentUser, form]);
|
|
|
|
|
-
|
|
|
|
|
- const handleEdit = () => {
|
|
|
|
|
- setIsEditing(true);
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- const handleCancel = () => {
|
|
|
|
|
- setIsEditing(false);
|
|
|
|
|
- if (userInfo) {
|
|
|
|
|
- form.setFieldsValue({
|
|
|
|
|
- username: userInfo.username,
|
|
|
|
|
- nickname: userInfo.nickname,
|
|
|
|
|
- avatar: userInfo.avatar,
|
|
|
|
|
- email: userInfo.email,
|
|
|
|
|
- phone: userInfo.phone,
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- const handleSave = async () => {
|
|
|
|
|
- try {
|
|
|
|
|
- const values = await form.validateFields();
|
|
|
|
|
- setLoading(true);
|
|
|
|
|
-
|
|
|
|
|
- const result = await api.fetchUserUpdateInfo({
|
|
|
|
|
- username: values.username,
|
|
|
|
|
- nickname: values.nickname,
|
|
|
|
|
- avatar: values.avatar,
|
|
|
|
|
- email: values.email,
|
|
|
|
|
- phone: values.phone,
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- if (result.success) {
|
|
|
|
|
- message.success('修改成功');
|
|
|
|
|
- setIsEditing(false);
|
|
|
|
|
-
|
|
|
|
|
- setInitialState((prev) => ({
|
|
|
|
|
- ...prev,
|
|
|
|
|
- currentUser: {
|
|
|
|
|
- ...prev?.currentUser,
|
|
|
|
|
- ...values,
|
|
|
|
|
- },
|
|
|
|
|
- }));
|
|
|
|
|
-
|
|
|
|
|
- const localUserInfo = ls.getLocal<API.UserInfo>(userKey);
|
|
|
|
|
- const newUserInfo = {
|
|
|
|
|
- ...localUserInfo,
|
|
|
|
|
- ...values,
|
|
|
|
|
- };
|
|
|
|
|
- ls.setLocal<API.UserInfo>(userKey, newUserInfo);
|
|
|
|
|
- setUserInfo(newUserInfo);
|
|
|
|
|
- } else {
|
|
|
|
|
- message.error(result.errorMessage || '修改失败');
|
|
|
|
|
- }
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- message.error('修改失败');
|
|
|
|
|
- } finally {
|
|
|
|
|
- setLoading(false);
|
|
|
|
|
- }
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- const handleAvatarUpload = async (options: any) => {
|
|
|
|
|
- const { file } = options;
|
|
|
|
|
- const isImage = file.type.startsWith('image/');
|
|
|
|
|
- if (!isImage) {
|
|
|
|
|
- message.error('只能上传图片文件!');
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if (file.size / 1024 / 1024 > 1) {
|
|
|
|
|
- message.error('头像大小不能超过1MB');
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- setUploading(true);
|
|
|
|
|
- try {
|
|
|
|
|
- const formData = new FormData();
|
|
|
|
|
- formData.append('file', file);
|
|
|
|
|
- formData.append('fileType', 'avatar');
|
|
|
|
|
- const res = await postForm<API.Result<{ url: string; path: string }>>(
|
|
|
|
|
- '/minio/upload',
|
|
|
|
|
- formData,
|
|
|
|
|
- );
|
|
|
|
|
- if (res.success && res.data) {
|
|
|
|
|
- form.setFieldValue('avatar', res.data.path);
|
|
|
|
|
- setUserInfo((prev) => (prev ? { ...prev, avatar: res.data!.url } : prev));
|
|
|
|
|
- message.success('上传成功');
|
|
|
|
|
- } else {
|
|
|
|
|
- message.error(res.errorMessage || '上传失败');
|
|
|
|
|
- }
|
|
|
|
|
- } catch {
|
|
|
|
|
- message.error('上传失败');
|
|
|
|
|
- } finally {
|
|
|
|
|
- setUploading(false);
|
|
|
|
|
- }
|
|
|
|
|
- };
|
|
|
|
|
|
|
+const UserInfo = () => {
|
|
|
|
|
+ const {
|
|
|
|
|
+ form,
|
|
|
|
|
+ isEditing,
|
|
|
|
|
+ loading,
|
|
|
|
|
+ uploading,
|
|
|
|
|
+ userInfo,
|
|
|
|
|
+ handleEdit,
|
|
|
|
|
+ handleCancel,
|
|
|
|
|
+ handleSave,
|
|
|
|
|
+ handleAvatarUpload,
|
|
|
|
|
+ } = useUserInfo();
|
|
|
|
|
|
|
|
if (!userInfo) {
|
|
if (!userInfo) {
|
|
|
return <div>加载中...</div>;
|
|
return <div>加载中...</div>;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
- <div style={{ padding: '24px' }}>
|
|
|
|
|
- <Card title="用户信息" style={{ maxWidth: 800, margin: '0 auto' }}>
|
|
|
|
|
|
|
+ <div className="p-6">
|
|
|
|
|
+ <Card title="用户信息" className="max-w-200 mx-auto">
|
|
|
<Form form={form} layout="vertical">
|
|
<Form form={form} layout="vertical">
|
|
|
<Row gutter={24}>
|
|
<Row gutter={24}>
|
|
|
<Col span={12}>
|
|
<Col span={12}>
|
|
@@ -174,30 +62,16 @@ const UserInfo: React.FC = () => {
|
|
|
</Col>
|
|
</Col>
|
|
|
<Col span={12}>
|
|
<Col span={12}>
|
|
|
<Form.Item name="avatar" hidden />
|
|
<Form.Item name="avatar" hidden />
|
|
|
- <div style={{ textAlign: 'center' }}>
|
|
|
|
|
- <div style={{ marginBottom: 16 }}>
|
|
|
|
|
- <Avatar
|
|
|
|
|
- size={120}
|
|
|
|
|
- src={userInfo.avatar}
|
|
|
|
|
- style={{ border: '2px solid #f0f0f0' }}
|
|
|
|
|
- />
|
|
|
|
|
- </div>
|
|
|
|
|
- {isEditing && (
|
|
|
|
|
- <Upload
|
|
|
|
|
- showUploadList={false}
|
|
|
|
|
- customRequest={handleAvatarUpload}
|
|
|
|
|
- accept="image/*"
|
|
|
|
|
- >
|
|
|
|
|
- <Button icon={uploading ? <LoadingOutlined /> : <PlusOutlined />}>
|
|
|
|
|
- 上传头像
|
|
|
|
|
- </Button>
|
|
|
|
|
- </Upload>
|
|
|
|
|
- )}
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ <AvatarUpload
|
|
|
|
|
+ avatar={userInfo.avatar}
|
|
|
|
|
+ isEditing={isEditing}
|
|
|
|
|
+ uploading={uploading}
|
|
|
|
|
+ onUpload={handleAvatarUpload}
|
|
|
|
|
+ />
|
|
|
</Col>
|
|
</Col>
|
|
|
</Row>
|
|
</Row>
|
|
|
</Form>
|
|
</Form>
|
|
|
- <div style={{ textAlign: 'center', marginTop: 24 }}>
|
|
|
|
|
|
|
+ <div className="text-center mt-6">
|
|
|
{!isEditing ? (
|
|
{!isEditing ? (
|
|
|
<Button type="primary" icon={<EditOutlined />} onClick={handleEdit}>
|
|
<Button type="primary" icon={<EditOutlined />} onClick={handleEdit}>
|
|
|
修改信息
|
|
修改信息
|