diff --git a/internal/common/helper.go b/internal/common/helper.go index 8be8312..654f2e6 100644 --- a/internal/common/helper.go +++ b/internal/common/helper.go @@ -86,6 +86,9 @@ func BuildPageData(c *gin.Context, extra gin.H) gin.H { data["IsLoggedIn"] = true data["Username"] = username } + if avatar, exists := c.Get("avatar"); exists { + data["Avatar"] = avatar + } // 注入 CSRF token(由 CSRF 中间件设置到上下文中) if token, exists := c.Get("csrf_token"); exists { data["CSRFToken"] = token diff --git a/internal/middleware/auth.go b/internal/middleware/auth.go index e7b3247..650beef 100644 --- a/internal/middleware/auth.go +++ b/internal/middleware/auth.go @@ -77,6 +77,7 @@ func injectSessionContext(c *gin.Context, s *session.Session) { c.Set("uid", s.UserID) c.Set("email", s.Email) c.Set("username", s.Username) + c.Set("avatar", s.Avatar) c.Set("role", s.Role) c.Set("sid", s.ID) } diff --git a/internal/repository/user_repo.go b/internal/repository/user_repo.go index 4f0af6c..5d2dd42 100644 --- a/internal/repository/user_repo.go +++ b/internal/repository/user_repo.go @@ -74,11 +74,10 @@ func (r *UserRepo) ExistsByEmailExclude(email string, excludeUID uint) (bool, er return count > 0, err } -// FindByIDForAuth 认证专用查询:返回 uid/email/username/role/status -// 比 FindByID 轻量(不查 avatar、bio 等无用字段),避免全量 SELECT * +// FindByIDForAuth 认证专用查询:返回 uid/email/username/avatar/role/status func (r *UserRepo) FindByIDForAuth(userID uint) (*model.User, error) { var user model.User - err := r.db.Select("uid", "email", "username", "role", "status"). + err := r.db.Select("uid", "email", "username", "avatar", "role", "status"). First(&user, userID).Error if err != nil { return nil, err diff --git a/internal/session/manager.go b/internal/session/manager.go index 11332fc..3123a50 100644 --- a/internal/session/manager.go +++ b/internal/session/manager.go @@ -37,6 +37,7 @@ func (m *Manager) Create(user *model.User, rememberMe bool, ip, userAgent string UserID: user.ID, Email: user.Email, Username: user.Username, + Avatar: user.Avatar, Role: user.Role, RememberMe: rememberMe, IP: ip, diff --git a/internal/session/session.go b/internal/session/session.go index 0088742..878dbc0 100644 --- a/internal/session/session.go +++ b/internal/session/session.go @@ -12,6 +12,7 @@ type Session struct { UserID uint // 用户 ID Email string // 邮箱 Username string // 用户名 + Avatar string // 头像 URL Role string // 角色 RememberMe bool // 是否持久化(决定 cookie maxAge) IP string // 登录 IP diff --git a/internal/theme/loader.go b/internal/theme/loader.go index e678148..a9ccc0e 100644 --- a/internal/theme/loader.go +++ b/internal/theme/loader.go @@ -24,6 +24,17 @@ func LoadTemplates(roots ...TemplateRoot) (*template.Template, error) { "subtract": func(a, b int) int { return a - b }, "formatTTL": formatTTL, "assetV": common.AssetV, + "substr": func(s string, start, length int) string { + runes := []rune(s) + if start >= len(runes) { + return "" + } + end := start + length + if end > len(runes) { + end = len(runes) + } + return string(runes[start:end]) + }, // derefUint 安全解引用 *uint 指针。 // Go 1.26 的模板引擎在将 *uint 传给 printf/print 时不会自动解引用, // 导致打印指针地址而非值。通过此函数显式解引用后传给 printf。 diff --git a/templates/MetaLab-2026/html/layout/nav.html b/templates/MetaLab-2026/html/layout/nav.html index c7d9c4f..d4650b6 100644 --- a/templates/MetaLab-2026/html/layout/nav.html +++ b/templates/MetaLab-2026/html/layout/nav.html @@ -6,21 +6,31 @@