| '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; |
| } |
| // 用户下拉框 |
| 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`, { |
| params: { 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`, { |
| params: { userId, avatar: avatarUrl } |
| }); |
| toast.current?.show({ severity: 'success', summary: 'success', detail: '修改头像成功' }); |
| setShowEditAvatar(false); |
| } 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="/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.url; |
| 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> |
| ); |
| |
| } |