blob: 4ed94d7d7c4708bf6916e8e98fc094244e033574 [file] [log] [blame]
LaoeGaoci656ab002025-06-05 17:48:28 +08001'use client';
2
3import { useRef, useState } from 'react';
4import { Avatar } from 'primereact/avatar';
5import { Button } from 'primereact/button';
6// 弹窗
7import { Dialog } from 'primereact/dialog';
8// 头像下拉框
9import { OverlayPanel } from 'primereact/overlaypanel';
10// 输入框
11import { FloatLabel } from "primereact/floatlabel";
12import { InputText } from 'primereact/inputtext';
13// 页面跳转
14import Link from 'next/link';
15// 文件上传
16import { FileUpload } from 'primereact/fileupload';
17// 通知
18import { Toast } from 'primereact/toast';
19// 接口传输
20import axios from 'axios';
21// 样式
22import './user-avatar.scss';
23
24// 用户下拉框
25export default function UserAvatar() {
26 // 功能选项
27 const op = useRef<OverlayPanel>(null);
28 let hoverTimeout: NodeJS.Timeout;
29 // 通知
30 const toast = useRef<Toast>(null);
31 // 控制三个弹窗可见性
32 const [showEditSignature, setShowEditSignature] = useState(false);
33 const [showEditAvatar, setShowEditAvatar] = useState(false);
34 const [showEditPassword, setShowEditPassword] = useState(false);
35 // 头像URL
36 const [avatarUrl, setAvatar] = useState<string>('');
37 // 签名
38 const [signValue, setSignValue] = useState<string>('');
39 // 新密码
40 const [passwardValue, setPasswardValue] = useState<string>('');
41 const [newPasswardValue, setNewPasswardValue] = useState<string>('');
42 // 老密码
43 const [oldPasswardValue, setOldPasswardValue] = useState<string>('');
44
45
46 const handleMouseEnter = (event: React.MouseEvent) => {
47 clearTimeout(hoverTimeout);
48 op.current?.show(event, event.currentTarget);
49 };
50
51 const handleMouseLeave = () => {
52 hoverTimeout = setTimeout(() => {
53 op.current?.hide();
54 }, 300);
55 };
56
57
58 // 修改密码接口
59 const editPassward = async () => {
60 try {
61 await axios.put(process.env.PUBLIC_URL + `/user/password`, {
62 params: { userId: 22301145, password: oldPasswardValue, newPassword: passwardValue }
63 });
64 toast.current?.show({ severity: 'success', summary: 'success', detail: '修改密码成功' });
65 setShowEditPassword(false);
66 } catch (err) {
67 console.error('修改密码失败', err);
68 toast.current?.show({ severity: 'error', summary: 'error', detail: '修改密码失败' });
69 }
70 }
71 // 修改签名接口
72 const editSign = async () => {
73 try {
74 await axios.put(process.env.PUBLIC_URL + `/user/signature`, {
75 params: { userId: 22301145, signature: signValue }
76 });
77 toast.current?.show({ severity: 'success', summary: 'success', detail: '修改签名成功' });
78 setShowEditSignature(false);
79 } catch (err) {
80 console.error('修改签名失败', err);
81 toast.current?.show({ severity: 'error', summary: 'error', detail: '修改签名失败' });
82 }
83 }
84
85 // 修改头像接口
86 const editAvatar = async () => {
87 try {
88 await axios.put(process.env.PUBLIC_URL + `/user/avatar`, {
89 params: { userId: 22301145, avatar: avatarUrl }
90 });
91 toast.current?.show({ severity: 'success', summary: 'success', detail: '修改头像成功' });
92 setShowEditAvatar(false);
93 } catch (err) {
94 console.error('修改头像失败', err);
95 toast.current?.show({ severity: 'error', summary: 'error', detail: '修改头像失败' });
96 }
97 }
98 return (
99 <div
100 onMouseEnter={handleMouseEnter}
101 onMouseLeave={handleMouseLeave}
102 className="user-avatar-wrapper"
103 >
104 <Toast ref={toast}></Toast>
105 <Link href="/user" className="no-underline">
106 <Avatar
107 image="/images/avatar/asiyajavayant.png"
108 size="large"
109 shape="circle"
110 className="user-avatar-link"
111 />
112 </Link>
113
114 <OverlayPanel ref={op} dismissable={false}>
115 <div
116 onMouseEnter={() => clearTimeout(hoverTimeout)}
117 onMouseLeave={handleMouseLeave}
118 className="user-overlay-panel"
119 >
120 <Button
121 text
122 icon="pi pi-pencil"
123 label="修改签名"
124 onClick={() => setShowEditSignature(true)}
125 />
126 <Button
127 text
128 icon="pi pi-image"
129 label="修改头像"
130 onClick={() => setShowEditAvatar(true)}
131 />
132 <Button
133 text
134 icon="pi pi-unlock"
135 label="修改密码"
136 onClick={() => setShowEditPassword(true)}
137 />
138 </div>
139 </OverlayPanel>
140
141 {/* 修改签名弹窗 */}
142 <Dialog
143 header="修改签名"
144 visible={showEditSignature}
145 style={{ width: '30vw' }}
146 onHide={() => {
147 setSignValue('');
148 setShowEditSignature(false);
149 }}
150 modal
151 >
152 <div className="dialog-container">
153 <div className="dialog-input-group">
154 <FloatLabel>
155 <InputText id="username" value={signValue} onChange={(e) => setSignValue(e.target.value)} />
156 <label htmlFor="username">个性签名</label>
157 </FloatLabel>
158 </div>
159 <div className="dialog-button-group">
160 <Button label="确定" className="p-button-sm" onClick={() => editSign()} />
161 <Button
162 label="取消"
163 className="p-button-secondary p-button-sm"
164 onClick={() => {
165 setSignValue('');
166 setShowEditSignature(false);
167 }}
168 />
169 </div>
170 </div>
171 </Dialog>
172
173 {/* 修改头像弹窗 */}
174 <Dialog
175 header="修改头像"
176 visible={showEditAvatar}
177 style={{ display: 'flex', flexDirection: 'column', width: '30vw' }}
178 onHide={() => {
179 setAvatar('');
180 setShowEditAvatar(false);
181 }}
182 modal
183 >
184 <div className="dialog-container">
185 <FileUpload
186 mode="advanced"
187 name="file"
188 customUpload
189 uploadHandler={async (e) => {
190 const formData = new FormData();
191 formData.append("file", e.files[0]);
192
193 try {
194 const res = await axios.post(`${process.env.PUBLIC_URL}/file/avatar`, formData);
195
196 const fileUrl = res.data.url;
197 console.log(fileUrl);
198 setAvatar(fileUrl);
199 toast.current?.show({ severity: 'success', summary: '上传成功' });
200 } catch (error) {
201 console.log(error);
202 toast.current?.show({ severity: 'error', summary: '上传失败' });
203 }
204 }}
205 auto
206 accept="image/*"
207 chooseLabel="上传头像"
208 />
209
210 <div className="dialog-button-group">
211 <Button label="确定" className="p-button-sm" onClick={() => editAvatar()} />
212 <Button
213 label="取消"
214 className="p-button-secondary p-button-sm"
215 onClick={() => setShowEditAvatar(false)}
216 />
217 </div>
218 </div>
219 </Dialog>
220
221 {/* 修改密码弹窗 */}
222 <Dialog
223 header="修改密码"
224 visible={showEditPassword}
225 style={{ width: '30vw' }}
226 onHide={() => {
227 setOldPasswardValue('');
228 setPasswardValue('');
229 setNewPasswardValue('');
230 setShowEditPassword(false);
231 }}
232 modal
233 >
234 <div className="dialog-container">
235 <div className="dialog-input-group">
236 <FloatLabel>
237 <InputText id="username" value={oldPasswardValue} onChange={(e) => setOldPasswardValue(e.target.value)} />
238 <label htmlFor="username">输入旧密码</label>
239 </FloatLabel>
240 </div>
241 <div className="dialog-input-group">
242 <FloatLabel>
243 <InputText id="username" value={passwardValue} onChange={(e) => setPasswardValue(e.target.value)} />
244 <label htmlFor="username">更新密码</label>
245 </FloatLabel>
246 </div>
247 <div className="dialog-input-group">
248 <FloatLabel>
249 <InputText id="username" value={newPasswardValue} onChange={(e) => setNewPasswardValue(e.target.value)} />
250 <label htmlFor="username">确认密码</label>
251 </FloatLabel>
252 </div>
253 <div className="dialog-button-group">
254 <Button label="确定" className="p-button-sm" onClick={() => {
255 if (passwardValue !== newPasswardValue) {
256 toast.current?.show({
257 severity: 'warn',
258 summary: '两次密码不一致',
259 detail: '请确保新密码和确认密码一致',
260 });
261 return;
262 } else {
263 editPassward();
264 }
265 }} />
266 <Button
267 label="取消"
268 className="p-button-secondary p-button-sm"
269 onClick={() => {
270 setOldPasswardValue('');
271 setPasswardValue('');
272 setNewPasswardValue('');
273 setShowEditPassword(false);
274 }}
275 />
276 </div>
277 </div>
278 </Dialog>
279 </div>
280 );
281
282}