添加了修改头像功能,顺便重新设计了用户组件

此提交包含在:
2021-09-28 00:28:59 +08:00
父節點 1b0e9d3042
當前提交 2967009dfb
共有 12 個檔案被更改,包括 374 行新增72 行删除

查看文件

@@ -0,0 +1,122 @@
.user-avatar {
width: 40px;
height: 40px;
position: relative;
}
.user-avatar > img {
border-radius: 50%;
width: 100%;
height: 100%;
cursor: pointer;
}
.user-avatar-edit {
border-radius: 8px;
background-color: #f7f7f7;
border: 1px solid #e5e5e5;
width: 160px;
height: 26px;
position: absolute;
margin-top: 10px;
left: -60px;
filter: opacity(0);
transition-property: width, height, filter;
transition-duration: .3s;
transition-timing-function: ease-out;
}
.user-avatar-edit > .pointer {
position: absolute;
width: 20px;
height: 10px;
top: -10px;
left: 70px;
}
.user-avatar-edit > .pointer > svg {
position: absolute;
}
.user-avatar-edit-tip {
width: 160px;
height: 26px;
line-height: 26px;
padding-left: 5px;
box-sizing: border-box;
z-index: 1;
}
.user-avatar-edit.expand {
width: 160px;
height: 160px;
}
.user-avatar-edit-tip,
.avatar-upload > * {
position: absolute;
filter: opacity(0);
transition: filter .3s ease-out;
}
.user-avatar-edit-tip.show,
.avatar-upload > .show,
.user-avatar-edit.show {
filter: opacity(1);
}
.user-avatar-edit-content {
overflow: hidden;
height: 100%;
}
.avatar-upload {
display: flex;
justify-content: center;
align-items: center;
height: 160px;
}
.avatar-upload .upload-unit-progress.show {
z-index: 2;
}
.avatar-upload .upload-unit-progress > .progress-detail {
color: black;
}
.upload-unit-progress > .icon {
width: 40px;
height: 40px;
}
.avatar-preview {
width: 160px;
height: 160px;
display: flex;
flex-direction: column;
align-items: center;
background-size: cover;
background-position: center;
}
.avatar-preview.show {
z-index: 1;
}
.avatar-preview > .upload-btns {
margin: 0;
bottom: 10px;
position: absolute;
}
.btn-close {
position: absolute;
right: 3px;
top: 3px;
z-index: 2;
width: 20px;
height: 20px;
display: flex;
justify-content: center;
align-items: center;
background-color: #e5e5e5bb;
border-radius: 4px;
backdrop-filter: blur(10px);
}
.btn-close > svg {
width: 16px;
height: 16px;
}

查看文件

@@ -0,0 +1,135 @@
import { useState, useCallback, useRef } from "react";
import Spinner from '../Spinner/Spinner';
import './AvatarUnit.css';
import { multiFormPost } from '../../helper/axios';
import { alert } from '../../helper/alert';
import { apis } from "../../helper/apis";
export default function AvatarUnit({ avatar, onChangeAvatar, showTip }) {
const [showBubble, setShowBubble] = useState(showTip);
const [showUpload, setShowUpload] = useState(false);
const [loading, setLoading] = useState(false);
const [loaded, setLoaded] = useState(false);
const [uploading, setUploading] = useState(false);
const [uploaded, setUploaded] = useState(false);
const [dataURL, setDataURL] = useState(null);
const [file, setFile] = useState(null);
const inputRef = useRef(null);
// useEffect(() => {
// setShowBubble(!localStorage.getItem("avatarTipShown"));
// localStorage.setItem("avatarTipShown", true);
// }, []);
const handleClose = () => {
setShowBubble(false);
setShowUpload(false);
setLoading(false);
setLoaded(false);
setUploading(false);
setUploaded(false);
setFile(null);
};
const handleFileChange = useCallback(file => {
if (file) {
if (!["image/jpeg", "image/png", "image/gif"].includes(file.type)) {
alert('请不要上传jpg、png、gif格式以外的文件!');
return;
}
setLoading(true);
setFile(file);
const reader = new FileReader();
reader.onload = () => {
setDataURL(reader.result);
if (inputRef.current) {
inputRef.current.value = "";
}
setLoaded(true);
setLoading(false);
};
reader.readAsDataURL(file);
}
}, []);
const handleCancel = useCallback(() => {
setLoaded(false);
setFile(null);
}, []);
const handleUpload = useCallback(() => {
if (file) {
setUploading(true);
const formData = new FormData();
formData.append("image", file);
multiFormPost(apis.uploadAvatar, formData).then(data => {
if (data.networkStatus === 200 && data.status) {
setUploaded(true);
setUploading(false);
setTimeout(() => {
handleClose();
onChangeAvatar(data.data);
}, 800);
}
else {
alert(data.data);
setUploading(false);
}
});
}
}, [file, onChangeAvatar]);
return (
<div className="user-avatar">
<img src={avatar} alt="user avatar" onClick={() => {
setShowBubble(true);
setShowUpload(true);
}} />
<div className={"user-avatar-edit" + (showUpload ? ' expand' : '') + (showBubble ? ' show' : '')}>
<div className="pointer">
<svg viewBox="0 0 20 10">
<path stroke="#e5e5e5" d="M0.112042+10.4465C1.43209+10.4306+4.24584+9.35904+5.0218+8.01502L6.77358+4.98086L8.52535+1.94671C9.30131+0.602693+10.5594+0.602693+11.3354+1.94671L13.0871+4.98086L14.8389+8.01502C15.6149+9.35904+18.4986+10.4864+20.0163+10.4757" fill="#f7f7f7"/>
</svg>
</div>
<button className="btn btn-close" onClick={handleClose}>
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M597.333333 512l284.444445 284.444444c2.929778 3.328 2.929778 22.357333 0 28.444445l-56.888889 56.888889c-6.087111 2.929778-25.116444 2.929778-28.444445 0L512 597.333333 227.555556 881.777778c-3.328 2.929778-22.328889 2.929778-28.444445 0l-56.888889-56.888889c-2.929778-6.087111-2.929778-25.116444 0-28.444445l284.444445-284.444444L142.222222 227.555556c-2.929778-3.328-2.929778-22.328889 0-28.444445l56.888889-56.888889c6.115556-2.929778 25.116444-2.929778 28.444445 0l284.444444 284.444445L796.444444 142.222222c3.328-2.929778 22.357333-2.929778 28.444445 0l56.888889 56.888889c2.929778 6.115556 2.929778 25.116444 0 28.444445L597.333333 512z" fill="#4a4a4a"></path></svg>
</button>
<div className="user-avatar-edit-content">
<span className={'user-avatar-edit-tip' + (showBubble && !showUpload ? ' show' : '')}>点击图标修改头像</span>
<div className="avatar-upload">
<div className={"upload-unit-progress" + (uploaded ? ' show' : '')}>
<div className="icon">
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M939.717 106.665l-304.049 324.529-78.769 85.071-225.28 240.246-123.668-115.003-129.182-121.305-78.769 84.283 129.969 121.305 33.083 31.508 129.969 121.305 44.111 40.96 304.049-324.529 78.769-85.071 304.049-324.529-84.283-78.769z" fill="#47c74c"></path></svg>
</div>
<div className="progress-detail">
上传成功
</div>
</div>
<div className={"upload-unit-progress" + (loading || uploading ? ' show' : '')}>
<Spinner isGray />
<div className="progress-detail">
{loading ? '加载中' : uploading ? '上传中' : ''}
</div>
</div>
<div className={"avatar-preview" + (loaded && !uploading && !uploaded ? ' show' : '')} style={{ backgroundImage: `url(${dataURL})` }}>
<div className="upload-btns">
<button className="btn btn-circle btn-ok" onClick={handleUpload}>
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M939.717 106.665l-304.049 324.529-78.769 85.071-225.28 240.246-123.668-115.003-129.182-121.305-78.769 84.283 129.969 121.305 33.083 31.508 129.969 121.305 44.111 40.96 304.049-324.529 78.769-85.071 304.049-324.529-84.283-78.769z" fill="#ffffff"></path></svg>
</button>
<button className="btn btn-circle btn-gray" onClick={handleCancel}>
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M597.333333 512l284.444445 284.444444c2.929778 3.328 2.929778 22.357333 0 28.444445l-56.888889 56.888889c-6.087111 2.929778-25.116444 2.929778-28.444445 0L512 597.333333 227.555556 881.777778c-3.328 2.929778-22.328889 2.929778-28.444445 0l-56.888889-56.888889c-2.929778-6.087111-2.929778-25.116444 0-28.444445l284.444445-284.444444L142.222222 227.555556c-2.929778-3.328-2.929778-22.328889 0-28.444445l56.888889-56.888889c6.115556-2.929778 25.116444-2.929778 28.444445 0l284.444444 284.444445L796.444444 142.222222c3.328-2.929778 22.357333-2.929778 28.444445 0l56.888889 56.888889c2.929778 6.115556 2.929778 25.116444 0 28.444445L597.333333 512z" fill="#4a4a4a"></path></svg>
</button>
</div>
</div>
<div className={"upload-image-btn" + (showUpload && !file ? ' show' : '')}>
<input type="file" accept="image/*" multiple={false} onChange={e => handleFileChange(e.target.files[0])} ref={inputRef} />
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 54"><path d="M60.342,102.091l5.331-8a2.249,2.249,0,0,1,1.872-1h18a2.246,2.246,0,0,1,1.872,1l5.332,8h7.094a6.72,6.72,0,0,1,6.7,6.7v31.6a6.722,6.722,0,0,1-6.7,6.7h-46.6a6.722,6.722,0,0,1-6.7-6.7v-31.6a6.72,6.72,0,0,1,6.7-6.7h7.094Zm5.407,0H87.341l-3-4.5H68.751l-3,4.5Zm10.8,35.25a12.75,12.75,0,1,0-12.75-12.75A12.764,12.764,0,0,0,76.545,137.341Zm0-21a8.25,8.25,0,1,1-8.25,8.25A8.261,8.261,0,0,1,76.545,116.341Z" transform="translate(-46.546 -93.091)" fill="#8A8A8A"/></svg>
<div className="upload-image-btn-text">添加图片</div>
</div>
</div>
</div>
</div>
</div>
);
}