Files
go_blog/models/site_setting.go
T
kevinandClaude Fable 5 d9bb91af00 feat: add navigation links management and user registration
Features:
- Custom navigation links management in admin settings
- Multi-language support for navigation links (Chinese/English)
- Control link behavior (open in new window)
- Sort order and enable/disable toggle for nav links
- User registration system with validation
- Admin can enable/disable user registration
- Registration form with username, display name, email, password
- Link to registration from login page

Navigation Links:
- Admin interface to add/edit/delete custom nav links
- Support for both internal and external URLs
- Display links in header navigation bar
- Respects language preference

User Registration:
- Username validation (3-32 characters, alphanumeric + underscore/dash)
- Password validation (minimum 6 characters)
- Password confirmation matching
- Optional display name and email fields
- Can be toggled on/off by admin in site settings

Templates:
- Added navigation links settings page
- Added user registration page
- Updated login page with registration link
- Updated base layout to render custom nav links

Documentation:
- NAV_LINKS_FEATURE.md - Navigation links feature documentation
- REGISTRATION_FEATURE.md - User registration documentation
- IMPLEMENTATION_SUMMARY.md - Overall implementation summary

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-22 21:01:38 +08:00

124 lines
4.2 KiB
Go

package models
import "time"
// SiteSetting holds the singleton (id=1) global display configuration:
// logo, top-left title, header banner text, and footer text, each with
// zh/en variants that fall back to i18n defaults when empty.
type SiteSetting struct {
ID uint `gorm:"primarykey" json:"id"`
Logo string `gorm:"size:512" json:"logo"` // local filename (served under /uploads/logos) OR a full URL
Favicon string `gorm:"size:512" json:"favicon"` // local filename (served under /uploads/logos) OR a full URL
LogoTextZh string `gorm:"size:255" json:"logo_text_zh"` // top-left title (zh)
LogoTextEn string `gorm:"size:255" json:"logo_text_en"` // top-left title (en)
HeaderTextZh string `gorm:"size:512" json:"header_text_zh"` // header banner text (zh)
HeaderTextEn string `gorm:"size:512" json:"header_text_en"` // header banner text (en)
HomeWelcomeZh string `gorm:"size:255" json:"home_welcome_zh"` // home page welcome heading (zh)
HomeWelcomeEn string `gorm:"size:255" json:"home_welcome_en"` // home page welcome heading (en)
HomeSubtitleZh string `gorm:"size:512" json:"home_subtitle_zh"` // home page subtitle (zh)
HomeSubtitleEn string `gorm:"size:512" json:"home_subtitle_en"` // home page subtitle (en)
FooterTextZh string `gorm:"size:512" json:"footer_text_zh"` // footer text (zh)
FooterTextEn string `gorm:"size:512" json:"footer_text_en"` // footer text (en)
AllowRegistration bool `gorm:"default:false" json:"allow_registration"` // whether users can self-register
UpdatedBy uint `gorm:"index" json:"updated_by"`
UpdatedAt time.Time `json:"updated_at"`
}
// TableName overrides the default GORM table name.
func (SiteSetting) TableName() string {
return "site_settings"
}
// LogoIsURL reports whether the logo value is an external URL rather than a
// local filename.
func (s *SiteSetting) LogoIsURL() bool {
if s == nil || s.Logo == "" {
return false
}
return len(s.Logo) >= 4 && (s.Logo[:4] == "http")
}
// FaviconIsURL reports whether the favicon value is an external URL rather than a
// local filename.
func (s *SiteSetting) FaviconIsURL() bool {
if s == nil || s.Favicon == "" {
return false
}
return len(s.Favicon) >= 4 && (s.Favicon[:4] == "http")
}
// LogoText returns the title for the given language code, falling back to the
// other language when the requested one is empty.
func (s *SiteSetting) LogoText(lang string) string {
if lang == "zh" {
if s.LogoTextZh != "" {
return s.LogoTextZh
}
return s.LogoTextEn
}
if s.LogoTextEn != "" {
return s.LogoTextEn
}
return s.LogoTextZh
}
// HeaderText returns the header banner text for the given language code,
// falling back to the other language when the requested one is empty.
func (s *SiteSetting) HeaderText(lang string) string {
if lang == "zh" {
if s.HeaderTextZh != "" {
return s.HeaderTextZh
}
return s.HeaderTextEn
}
if s.HeaderTextEn != "" {
return s.HeaderTextEn
}
return s.HeaderTextZh
}
// HomeWelcome returns the home page welcome heading for the given language,
// falling back to the other language when the requested one is empty.
func (s *SiteSetting) HomeWelcome(lang string) string {
if lang == "zh" {
if s.HomeWelcomeZh != "" {
return s.HomeWelcomeZh
}
return s.HomeWelcomeEn
}
if s.HomeWelcomeEn != "" {
return s.HomeWelcomeEn
}
return s.HomeWelcomeZh
}
// HomeSubtitle returns the home page subtitle for the given language,
// falling back to the other language when the requested one is empty.
func (s *SiteSetting) HomeSubtitle(lang string) string {
if lang == "zh" {
if s.HomeSubtitleZh != "" {
return s.HomeSubtitleZh
}
return s.HomeSubtitleEn
}
if s.HomeSubtitleEn != "" {
return s.HomeSubtitleEn
}
return s.HomeSubtitleZh
}
// FooterText returns the footer text for the given language code, falling
// back to the other language when the requested one is empty.
func (s *SiteSetting) FooterText(lang string) string {
if lang == "zh" {
if s.FooterTextZh != "" {
return s.FooterTextZh
}
return s.FooterTextEn
}
if s.FooterTextEn != "" {
return s.FooterTextEn
}
return s.FooterTextZh
}