feat: 媒体库 blob 去重存储与品牌/注册等前端调整

新增:
- blob_store 二进制去重存储 + blob_dedup 测试

其它:
- 后端 settings/auth/media_library/upload/operations 服务与 handler 调整
- 前端品牌(BrandLockup/BrandCropModal/BrandSeoPanel)、注册、媒体库、分析详情页、Header/SiteChrome 等更新
This commit is contained in:
2026-10-03 02:38:11 +08:00
parent 8cfdfcbbf0
commit 46e0cdc0b3
32 changed files with 1242 additions and 228 deletions

View File

@@ -9,16 +9,17 @@ import (
// 站点品牌与页脚(公开设置,缺省为空)
const (
SettingKeySiteWordmark = "site_wordmark"
SettingKeySiteSlogan = "site_slogan"
SettingKeySiteKeywords = "site_keywords"
SettingKeyLogoLightURL = "logo_light_url"
SettingKeyLogoDarkURL = "logo_dark_url"
SettingKeyFaviconURL = "favicon_url"
SettingKeyFooterLinks = "footer_links"
SettingKeyBrandMark = "brand_mark"
SettingKeyBrandLogoSize = "brand_logo_size"
SettingKeyBrandLogoFit = "brand_logo_fit"
SettingKeySiteWordmark = "site_wordmark"
SettingKeySiteSlogan = "site_slogan"
SettingKeySiteKeywords = "site_keywords"
SettingKeyLogoLightURL = "logo_light_url"
SettingKeyLogoDarkURL = "logo_dark_url"
SettingKeyFaviconURL = "favicon_url"
SettingKeyFooterLinks = "footer_links"
SettingKeyBrandMark = "brand_mark"
SettingKeyBrandLogoSize = "brand_logo_size"
SettingKeyBrandLogoFit = "brand_logo_fit"
SettingKeyBrandSloganVisible = "brand_slogan_visible"
BrandSlotLight = "logo_light"
BrandSlotDark = "logo_dark"
@@ -43,6 +44,8 @@ const (
BrandLogoSize3x1 = "3x1"
BrandLogoSize4x1 = "4x1"
BrandLogoSize169 = "16x9"
// BrandLogoSizeAuto 原图比例:自由裁剪,页眉图槽按图片原始比例自适应宽度
BrandLogoSizeAuto = "auto"
BrandLogoFitCover = "cover"
BrandLogoFitContain = "contain"
@@ -114,7 +117,7 @@ func NormalizeBrandLogoSize(raw string) (string, bool) {
switch strings.TrimSpace(raw) {
case "", BrandLogoSizeSQ:
return BrandLogoSizeSQ, true
case BrandLogoSize2x1, BrandLogoSize3x1, BrandLogoSize4x1, BrandLogoSize169:
case BrandLogoSize2x1, BrandLogoSize3x1, BrandLogoSize4x1, BrandLogoSize169, BrandLogoSizeAuto:
return strings.TrimSpace(raw), true
default:
return "", false
@@ -367,6 +370,15 @@ func (s *SettingService) fillBrand(out *PublicSiteSettings) error {
out.BrandLogoFit = f
}
}
sv, found, err := s.getValue(SettingKeyBrandSloganVisible)
if err != nil {
return err
}
if found {
out.BrandSloganVisible = sv == "true"
} else {
out.BrandSloganVisible = true
}
rawLinks, found, err := s.getValue(SettingKeyFooterLinks)
if err != nil {
return err
@@ -483,6 +495,14 @@ func (s *SettingService) SetBrandLogoFit(raw string) error {
return s.putValue(SettingKeyBrandLogoFit, v)
}
// SetBrandSloganVisible 控制标语是否在页眉显示;true 为缺省值,存库时删 key 以保持精简。
func (s *SettingService) SetBrandSloganVisible(visible bool) error {
if visible {
return s.deleteKey(SettingKeyBrandSloganVisible)
}
return s.putValue(SettingKeyBrandSloganVisible, "false")
}
func (s *SettingService) setBrandURL(key, slot, url string) error {
u, ok := NormalizeBrandURL(slot, url)
if !ok {