diff --git a/handlers/backend/auth.go b/handlers/backend/auth.go index 1515fc4..919db2a 100644 --- a/handlers/backend/auth.go +++ b/handlers/backend/auth.go @@ -180,21 +180,19 @@ func UpdateUser(c *gin.Context) { return } - updates := map[string]interface{}{} - if req.Nickname != "" { - updates["nickname"] = req.Nickname - } - if req.Email != "" { - updates["email"] = req.Email - } - if req.Avatar != "" { - updates["avatar"] = req.Avatar + updates := map[string]interface{}{ + "nickname": req.Nickname, + "email": req.Email, + "avatar": req.Avatar, } if err := database.DB.Model(&user).Updates(updates).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "更新失败"}) return } + user.Nickname = req.Nickname + user.Email = req.Email + user.Avatar = req.Avatar c.JSON(http.StatusOK, gin.H{"data": user}) } diff --git a/routers/router.go b/routers/router.go index 6394adb..6eeb235 100644 --- a/routers/router.go +++ b/routers/router.go @@ -65,9 +65,7 @@ func setupAuthenticatedAPIRoutes(api *gin.RouterGroup) { auth.GET("/dashboard/stats", backend.GetDashboardStats) // 当前用户信息 auth.GET("/auth/me", backend.GetCurrentUser) - //TODO: 修改用户信息接口,在admin/index.html中添加修改用户信息表单 auth.PUT("/auth/me", backend.UpdateUser) - //TODO: 修改密码接口,在admin/index.html中添加修改密码表单 auth.PUT("/auth/password", backend.ChangePassword) auth.POST("/auth/logout", backend.Logout) diff --git a/static/css/adminstyle.css b/static/css/adminstyle.css index 73be5f2..df23478 100644 --- a/static/css/adminstyle.css +++ b/static/css/adminstyle.css @@ -33,6 +33,45 @@ body { .admin-header #username { margin-left: auto; } +.user-menu-wrapper { + position: relative; + margin-left: auto; +} +.user-menu-wrapper #username { + margin-left: 0; +} +.user-menu { + position: absolute; + top: calc(100% + 4px); + right: 0; + z-index: 1100; + display: none; + min-width: 140px; + padding: 4px 0; + background: #fff; + border: 1px solid #e8e8e8; + border-radius: 4px; + box-shadow: 0 3px 12px rgba(0,0,0,0.16); +} +.user-menu-wrapper:hover .user-menu, +.user-menu-wrapper:focus-within .user-menu { + display: block; +} +.user-menu button { + display: block; + width: 100%; + padding: 9px 14px; + border: 0; + background: transparent; + color: #333; + text-align: left; + cursor: pointer; + font-size: 13px; +} +.user-menu button:hover { + background: #f5f5f5; + color: #1890ff; +} .admin-header span { background: transparent; padding: 5px 12px; diff --git a/static/js/admin.js b/static/js/admin.js index 9940448..7d841e6 100644 --- a/static/js/admin.js +++ b/static/js/admin.js @@ -108,6 +108,8 @@ document.addEventListener('DOMContentLoaded', () => { bindForm('modal-form', handleModalSubmit); bindForm('user-form', handleUserSubmit); bindForm('settings-form', handleSettingsSubmit); + bindForm('profile-form', handleProfileSubmit); + bindForm('password-form', handlePasswordSubmit); // 封面图上传 const coverFileInput = document.getElementById('post-cover-file'); @@ -122,6 +124,86 @@ document.addEventListener('DOMContentLoaded', () => { } }); +// 显示个人信息弹窗 +function showProfileModal() { + document.getElementById('profile-nickname').value = currentUser?.nickname || ''; + document.getElementById('profile-email').value = currentUser?.email || ''; + document.getElementById('profile-avatar').value = currentUser?.avatar || ''; + document.getElementById('profile-modal').classList.remove('hidden'); +} + +function hideProfileModal() { + document.getElementById('profile-modal').classList.add('hidden'); +} + +// 保存个人信息 +async function handleProfileSubmit(e) { + e.preventDefault(); + const body = { + nickname: document.getElementById('profile-nickname').value.trim(), + email: document.getElementById('profile-email').value.trim(), + avatar: document.getElementById('profile-avatar').value.trim() + }; + + try { + const res = await fetch(`${API_BASE}/auth/me`, { + method: 'PUT', + headers: getHeaders(), + body: JSON.stringify(body) + }); + const data = await res.json().catch(() => ({})); + if (!res.ok) { + alert(data.error || '保存失败'); + return; + } + currentUser = Object.assign({}, currentUser, body, data.data || {}); + document.getElementById('username').textContent = currentUser.nickname || currentUser.username; + hideProfileModal(); + alert('个人信息已保存'); + } catch (err) { + alert('保存失败: ' + err.message); + } +} + +// 显示修改密码弹窗 +function showPasswordModal() { + document.getElementById('password-form').reset(); + document.getElementById('password-modal').classList.remove('hidden'); +} + +function hidePasswordModal() { + document.getElementById('password-modal').classList.add('hidden'); +} + +// 修改密码 +async function handlePasswordSubmit(e) { + e.preventDefault(); + const oldPassword = document.getElementById('old-password').value; + const newPassword = document.getElementById('new-password').value; + const confirmPassword = document.getElementById('confirm-password').value; + if (newPassword !== confirmPassword) { + alert('两次输入的新密码不一致'); + return; + } + + try { + const res = await fetch(`${API_BASE}/auth/password`, { + method: 'PUT', + headers: getHeaders(), + body: JSON.stringify({ old_password: oldPassword, new_password: newPassword }) + }); + const data = await res.json().catch(() => ({})); + if (!res.ok) { + alert(data.error || '修改密码失败'); + return; + } + hidePasswordModal(); + alert(data.message || '密码修改成功'); + } catch (err) { + alert('修改密码失败: ' + err.message); + } +} + // 安全绑定表单提交(元素不存在时忽略) function bindForm(formId, handler) { const form = document.getElementById(formId); diff --git a/templates/admin/index.html b/templates/admin/index.html index 476c156..9f5f84a 100644 --- a/templates/admin/index.html +++ b/templates/admin/index.html @@ -10,7 +10,13 @@

GoBlog

- {{.DisplayName}} +
+ {{.DisplayName}} + +
退出
@@ -48,6 +54,8 @@ {{if or (index .PageSet "categories") (index .PageSet "tags") (index .PageSet "pages")}}{{template "admin_modal_common" .}}{{end}} {{if index .PageSet "users"}}{{template "admin_modal_user" .}}{{end}} {{if index .PageSet "themes"}}{{template "admin_modal_theme" .}}{{end}} + {{template "admin_modal_profile" .}} + {{template "admin_modal_password" .}} @@ -55,6 +63,58 @@ {{end}} +{{define "admin_modal_profile"}} + +{{end}} + +{{define "admin_modal_password"}} + +{{end}} + {{define "admin_page_dashboard"}}