release: prepare v0.1.140
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / test (push) Has been cancelled
CI / frontend (push) Has been cancelled
CI / golangci-lint (push) Has been cancelled
Security Scan / backend-security (push) Has been cancelled
Security Scan / frontend-security (push) Has been cancelled

This commit is contained in:
kone
2026-06-03 23:52:28 +08:00
parent d1b574bcad
commit 6f4a680156
17 changed files with 767 additions and 127 deletions
@@ -1151,6 +1151,14 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
response.BadRequest(c, "Custom menu item placement must be 'sidebar', 'home_header' or 'both'")
return
}
switch item.LinkOpenMode {
case "", "internal":
items[i].LinkOpenMode = "internal"
case "external":
default:
response.BadRequest(c, "Custom menu item link open mode must be 'internal' or 'external'")
return
}
if len(item.IconSVG) > maxMenuItemIconSVGLen {
response.BadRequest(c, "Custom menu item icon SVG is too large (max 10KB)")
return
+21 -8
View File
@@ -7,14 +7,15 @@ import (
// CustomMenuItem represents a user-configured custom menu entry.
type CustomMenuItem struct {
ID string `json:"id"`
Label string `json:"label"`
IconSVG string `json:"icon_svg"`
URL string `json:"url"`
PageSlug string `json:"page_slug,omitempty"`
Visibility string `json:"visibility"` // "user" or "admin"
Placement string `json:"placement,omitempty"`
SortOrder int `json:"sort_order"`
ID string `json:"id"`
Label string `json:"label"`
IconSVG string `json:"icon_svg"`
URL string `json:"url"`
PageSlug string `json:"page_slug,omitempty"`
Visibility string `json:"visibility"` // "user" or "admin"
Placement string `json:"placement,omitempty"`
LinkOpenMode string `json:"link_open_mode,omitempty"`
SortOrder int `json:"sort_order"`
}
// CustomEndpoint represents an admin-configured API endpoint for quick copy.
@@ -371,6 +372,7 @@ func ParseCustomMenuItems(raw string) []CustomMenuItem {
}
for i := range items {
items[i].Placement = normalizeCustomMenuPlacement(items[i].Placement)
items[i].LinkOpenMode = normalizeCustomMenuLinkOpenMode(items[i].LinkOpenMode)
}
return items
}
@@ -388,6 +390,17 @@ func normalizeCustomMenuPlacement(raw string) string {
}
}
func normalizeCustomMenuLinkOpenMode(raw string) string {
switch strings.TrimSpace(raw) {
case "", "internal":
return "internal"
case "external":
return "external"
default:
return "internal"
}
}
// ParseUserVisibleMenuItems parses custom menu items and filters out admin-only entries.
func ParseUserVisibleMenuItems(raw string) []CustomMenuItem {
items := ParseCustomMenuItems(raw)
@@ -1218,6 +1218,14 @@ func normalizeCustomMenuItemsRaw(raw string) json.RawMessage {
default:
item["placement"] = "sidebar"
}
linkOpenMode, _ := item["link_open_mode"].(string)
switch strings.TrimSpace(linkOpenMode) {
case "", "internal":
item["link_open_mode"] = "internal"
case "external":
default:
item["link_open_mode"] = "internal"
}
}
normalized, err := json.Marshal(items)
if err != nil {