blob: abc1b6625664da2662c37bb18064f09bff8541d5 [file] [log] [blame]
"use client";
import { useRef, useState } from "react";
import { Avatar } from "primereact/avatar";
import { Button } from "primereact/button";
// 弹窗
import { Dialog } from "primereact/dialog";
// 头像下拉框
import { OverlayPanel } from "primereact/overlaypanel";
// 输入框
import { FloatLabel } from "primereact/floatlabel";
import { InputText } from "primereact/inputtext";
// 页面跳转
import Link from "next/link";
// 文件上传
import { FileUpload } from "primereact/fileupload";
// 通知
import { Toast } from "primereact/toast";
// 接口传输
import axios from "axios";
import { useLocalStorage } from "../../hook/useLocalStorage";
// 样式
import "./user-avatar.scss";
interface User {
Id: number;
Avatar: string,
}
// 用户下拉框
export default function UserAvatar() {
const user = useLocalStorage<User>("user");
const userId: number = user?.Id ?? -1;
// 功能选项
const op = useRef<OverlayPanel>(null);
let hoverTimeout: NodeJS.Timeout;
// 通知
const toast = useRef<Toast>(null);
// 控制三个弹窗可见性
const [showEditSignature, setShowEditSignature] = useState(false);
const [showEditAvatar, setShowEditAvatar] = useState(false);
const [showEditPassword, setShowEditPassword] = useState(false);
// 头像URL
const [avatarUrl, setAvatar] = useState<string>("");
// 签名
const [signValue, setSignValue] = useState<string>("");
// 新密码
const [passwardValue, setPasswardValue] = useState<string>("");
const [newPasswardValue, setNewPasswardValue] = useState<string>("");
// 老密码
const [oldPasswardValue, setOldPasswardValue] = useState<string>("");
const handleMouseEnter = (event: React.MouseEvent) => {
clearTimeout(hoverTimeout);
op.current?.show(event, event.currentTarget);
};
const handleMouseLeave = () => {
hoverTimeout = setTimeout(() => {
op.current?.hide();
}, 300);
};
// 修改密码接口
const editPassward = async () => {
try {
await axios.put(process.env.PUBLIC_URL + `/user/password`, {
body: {
userId,
password: oldPasswardValue,
newPassword: passwardValue,
},
});
toast.current?.show({
severity: "success",
summary: "success",
detail: "修改密码成功",
});
setShowEditPassword(false);
} catch (err) {
console.error("修改密码失败", err);
toast.current?.show({
severity: "error",
summary: "error",
detail: "修改密码失败",
});
}
};
// 修改签名接口
const editSign = async () => {
try {
await axios.put(process.env.PUBLIC_URL + `/user/signature`, {
params: { userId, signature: signValue },
});
toast.current?.show({
severity: "success",
summary: "success",
detail: "修改签名成功",
});
setShowEditSignature(false);
} catch (err) {
console.error("修改签名失败", err);
toast.current?.show({
severity: "error",
summary: "error",
detail: "修改签名失败",
});
}
};
// 修改头像接口
const editAvatar = async () => {
try {
await axios.put(process.env.PUBLIC_URL + `/user/avatar`, {
userId,
avatar: avatarUrl,
});
toast.current?.show({
severity: "success",
summary: "success",
detail: "修改头像成功",
});
setAvatar(avatarUrl);
setShowEditAvatar(false);
localStorage.setItem("user", JSON.stringify({...user, Avatar: avatarUrl}))
} catch (err) {
console.error("修改头像失败", err);
toast.current?.show({
severity: "error",
summary: "error",
detail: "修改头像失败",
});
}
};
return (
<div
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
className="user-avatar-wrapper"
>
<Toast ref={toast}></Toast>
<Link href="/user" className="no-underline">
<Avatar
image={useLocalStorage<User>("user")?.Avatar}
size="large"
shape="circle"
className="user-avatar-link"
/>
</Link>
<OverlayPanel ref={op} dismissable={false}>
<div
onMouseEnter={() => clearTimeout(hoverTimeout)}
onMouseLeave={handleMouseLeave}
className="user-overlay-panel"
>
<Toast ref={toast}></Toast>
<Link href="/user" className="no-underline">
<Avatar
image="/images/avatar/asiyajavayant.png"
size="large"
shape="circle"
className="user-avatar-link"
/>
</Link>
<OverlayPanel ref={op} dismissable={false}>
<div
onMouseEnter={() => clearTimeout(hoverTimeout)}
onMouseLeave={handleMouseLeave}
className="user-overlay-panel"
>
<Button
text
icon="pi pi-pencil"
label="修改签名"
onClick={() => setShowEditSignature(true)}
/>
<Button
text
icon="pi pi-image"
label="修改头像"
onClick={() => setShowEditAvatar(true)}
/>
<Button
text
icon="pi pi-unlock"
label="修改密码"
onClick={() => setShowEditPassword(true)}
/>
</div>
</OverlayPanel>
{/* 修改签名弹窗 */}
<Dialog
header="修改签名"
visible={showEditSignature}
style={{ width: '30vw' }}
onHide={() => {
setSignValue('');
setShowEditSignature(false);
}}
modal
>
<div className="dialog-container">
<div className="dialog-input-group">
<FloatLabel>
<InputText id="username" value={signValue} onChange={(e) => setSignValue(e.target.value)} />
<label htmlFor="username">个性签名</label>
</FloatLabel>
</div>
<div className="dialog-button-group">
<Button label="确定" className="p-button-sm" onClick={() => editSign()} />
<Button
label="取消"
className="p-button-secondary p-button-sm"
onClick={() => {
setSignValue('');
setShowEditSignature(false);
}}
/>
</div>
</div>
</Dialog>
{/* 修改头像弹窗 */}
<Dialog
header="修改头像"
visible={showEditAvatar}
style={{ display: 'flex', flexDirection: 'column', width: '30vw' }}
onHide={() => {
setAvatar('');
setShowEditAvatar(false);
}}
modal
>
<div className="dialog-container">
<FileUpload
mode="advanced"
name="file"
customUpload
uploadHandler={async (e) => {
const formData = new FormData();
formData.append("file", e.files[0]);
try {
const res = await axios.post(`${process.env.PUBLIC_URL}/file`, formData);
const fileUrl = res.data;
console.log(fileUrl);
setAvatar(fileUrl);
toast.current?.show({ severity: 'success', summary: '上传成功' });
} catch (error) {
console.log(error);
toast.current?.show({ severity: 'error', summary: '上传失败' });
}
}}
auto
accept="image/*"
chooseLabel="上传头像"
/>
<div className="dialog-button-group">
<Button label="确定" className="p-button-sm" onClick={() => editAvatar()} />
<Button
label="取消"
className="p-button-secondary p-button-sm"
onClick={() => setShowEditAvatar(false)}
/>
</div>
</div>
</Dialog>
{/* 修改密码弹窗 */}
<Dialog
header="修改密码"
visible={showEditPassword}
style={{ width: '30vw' }}
onHide={() => {
setOldPasswardValue('');
setPasswardValue('');
setNewPasswardValue('');
setShowEditPassword(false);
}}
modal
>
<div className="dialog-container">
<div className="dialog-input-group">
<FloatLabel>
<InputText id="username" value={oldPasswardValue} onChange={(e) => setOldPasswardValue(e.target.value)} />
<label htmlFor="username">输入旧密码</label>
</FloatLabel>
</div>
<div className="dialog-input-group">
<FloatLabel>
<InputText id="username" value={passwardValue} onChange={(e) => setPasswardValue(e.target.value)} />
<label htmlFor="username">更新密码</label>
</FloatLabel>
</div>
<div className="dialog-input-group">
<FloatLabel>
<InputText id="username" value={newPasswardValue} onChange={(e) => setNewPasswardValue(e.target.value)} />
<label htmlFor="username">确认密码</label>
</FloatLabel>
</div>
<div className="dialog-button-group">
<Button label="确定" className="p-button-sm" onClick={() => {
if (passwardValue !== newPasswardValue) {
toast.current?.show({
severity: 'warn',
summary: '两次密码不一致',
detail: '请确保新密码和确认密码一致',
});
return;
} else {
editPassward();
}
}} />
<Button
label="取消"
className="p-button-secondary p-button-sm"
onClick={() => {
setOldPasswardValue('');
setPasswardValue('');
setNewPasswardValue('');
setShowEditPassword(false);
}}
/>
</div>
</div>
</Dialog>
</div>
</OverlayPanel>
{/* 修改签名弹窗 */}
<Dialog
header="修改签名"
visible={showEditSignature}
style={{ width: "30vw" }}
onHide={() => {
setSignValue("");
setShowEditSignature(false);
}}
modal
>
<div className="dialog-container">
<div className="dialog-input-group">
<FloatLabel>
<InputText
id="username"
value={signValue}
onChange={(e) => setSignValue(e.target.value)}
/>
<label htmlFor="username">个性签名</label>
</FloatLabel>
</div>
<div className="dialog-button-group">
<Button
label="确定"
className="p-button-sm"
onClick={() => editSign()}
/>
<Button
label="取消"
className="p-button-secondary p-button-sm"
onClick={() => {
setSignValue("");
setShowEditSignature(false);
}}
/>
</div>
</div>
</Dialog>
{/* 修改头像弹窗 */}
<Dialog
header="修改头像"
visible={showEditAvatar}
style={{ display: "flex", flexDirection: "column", width: "30vw" }}
onHide={() => {
setAvatar("");
setShowEditAvatar(false);
}}
modal
>
<div className="dialog-container">
<FileUpload
mode="advanced"
name="file"
customUpload
uploadHandler={async (e) => {
const formData = new FormData();
formData.append("file", e.files[0]);
try {
const res = await axios.post(
`${process.env.PUBLIC_URL}/file`,
formData
);
const fileUrl = res.data;
console.log(fileUrl);
setAvatar(fileUrl);
toast.current?.show({
severity: "success",
summary: "上传成功",
});
} catch (error) {
console.log(error);
toast.current?.show({ severity: "error", summary: "上传失败" });
}
}}
auto
accept="image/*"
chooseLabel="上传头像"
/>
<div className="dialog-button-group">
<Button
label="确定"
className="p-button-sm"
onClick={() => editAvatar()}
/>
<Button
label="取消"
className="p-button-secondary p-button-sm"
onClick={() => setShowEditAvatar(false)}
/>
</div>
</div>
</Dialog>
{/* 修改密码弹窗 */}
<Dialog
header="修改密码"
visible={showEditPassword}
style={{ width: "30vw" }}
onHide={() => {
setOldPasswardValue("");
setPasswardValue("");
setNewPasswardValue("");
setShowEditPassword(false);
}}
modal
>
<div className="dialog-container">
<div className="dialog-input-group">
<FloatLabel>
<InputText
id="username"
value={oldPasswardValue}
onChange={(e) => setOldPasswardValue(e.target.value)}
/>
<label htmlFor="username">输入旧密码</label>
</FloatLabel>
</div>
<div className="dialog-input-group">
<FloatLabel>
<InputText
id="username"
value={passwardValue}
onChange={(e) => setPasswardValue(e.target.value)}
/>
<label htmlFor="username">更新密码</label>
</FloatLabel>
</div>
<div className="dialog-input-group">
<FloatLabel>
<InputText
id="username"
value={newPasswardValue}
onChange={(e) => setNewPasswardValue(e.target.value)}
/>
<label htmlFor="username">确认密码</label>
</FloatLabel>
</div>
<div className="dialog-button-group">
<Button
label="确定"
className="p-button-sm"
onClick={() => {
if (passwardValue !== newPasswardValue) {
toast.current?.show({
severity: "warn",
summary: "两次密码不一致",
detail: "请确保新密码和确认密码一致",
});
return;
} else {
editPassward();
}
}}
/>
<Button
label="取消"
className="p-button-secondary p-button-sm"
onClick={() => {
setOldPasswardValue("");
setPasswardValue("");
setNewPasswardValue("");
setShowEditPassword(false);
}}
/>
</div>
</div>
</Dialog>
</div>
);
}