refactor: 重写导航栏布局与交互
- 导航项重新排序:首页、投稿、信封图标、头像下拉菜单 - 铃铛图标替换为信封图标 - 用户名/设置/退出移入头像 hover 下拉菜单 - 设置改名为个人中心,退出改名为退出登录 - 头像点击跳转 /space,hover 展开下拉菜单 - 无头像时显示用户名首字彩色圆形占位 - Avatar 数据链路打通:Session→Middleware→BuildPageData→模板 - FindByIDForAuth 查询增加 avatar 列 - 新增 substr 模板函数
This commit is contained in:
@ -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
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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。
|
||||
|
||||
Reference in New Issue
Block a user