新增首页 AW炫彩回收入口,支持后台配置展示图

首页第三入口点击查看回收说明图;配置项 mobile.aw_recycle 可配标题/图片;aw-recycle 走公开文件链路,首页鉴权预览兼容旧私有地址。
This commit is contained in:
yml2213
2026-07-19 22:50:16 +08:00
parent dabcec45cb
commit 9b1ee445b7
14 changed files with 533 additions and 18 deletions
+3 -1
View File
@@ -70,7 +70,9 @@ func (h *Handler) writeObject(c *gin.Context, publicOnly bool) {
!strings.HasPrefix(key, "avatar/") &&
!strings.HasPrefix(key, "payment-cert/") &&
!strings.HasPrefix(key, "announcement/") &&
!strings.HasPrefix(key, "mohong/") && !strings.HasPrefix(key, "crash/") {
!strings.HasPrefix(key, "mohong/") &&
!strings.HasPrefix(key, "crash/") &&
!strings.HasPrefix(key, "aw-recycle/") {
response.Error(c, http.StatusNotFound, "not_found", "文件不存在或暂不可访问")
return
}
+2 -2
View File
@@ -106,7 +106,7 @@ func normalizeContentType(contentType string, data []byte) string {
func fileURLForScene(scene string, key string) string {
fileURL := "/api/files/object?key=" + url.QueryEscape(key)
if scene == "home-banner" || scene == "avatar" || scene == "payment-cert" || scene == "announcement" || scene == "mohong" || scene == "crash" {
if scene == "home-banner" || scene == "avatar" || scene == "payment-cert" || scene == "announcement" || scene == "mohong" || scene == "crash" || scene == "aw-recycle" {
fileURL = "/api/public/files/object?key=" + url.QueryEscape(key)
}
return fileURL
@@ -115,7 +115,7 @@ func fileURLForScene(scene string, key string) string {
func normalizeScene(scene string) string {
scene = strings.TrimSpace(strings.ToLower(scene))
switch scene {
case "listing", "handoff", "dispute", "realname", "avatar", "home-banner", "chat", "payment-cert", "announcement", "qrcode", "mohong", "crash":
case "listing", "handoff", "dispute", "realname", "avatar", "home-banner", "chat", "payment-cert", "announcement", "qrcode", "mohong", "crash", "aw-recycle":
return scene
default:
return "misc"
@@ -29,3 +29,14 @@ func TestNormalizeSceneAllowsAnnouncement(t *testing.T) {
t.Fatalf("normalize announcement scene = %q", got)
}
}
func TestAWRecycleSceneUsesPublicFileURL(t *testing.T) {
if got := normalizeScene("aw-recycle"); got != "aw-recycle" {
t.Fatalf("normalize aw-recycle scene = %q", got)
}
key := "aw-recycle/2026/07/19/example.webp"
got := fileURLForScene("aw-recycle", key)
if !strings.HasPrefix(got, "/api/public/files/object?") {
t.Fatalf("aw-recycle file url = %q, want public file endpoint", got)
}
}
@@ -0,0 +1,43 @@
package systemconfig
import (
"encoding/json"
"strings"
)
const awRecycleConfigKey = "mobile.aw_recycle"
func defaultAWRecycle() AWRecycleConfig {
return AWRecycleConfig{
Title: "AW炫彩回收",
Subtitle: "点击查看回收说明",
ImageURL: "",
Enabled: true,
}
}
func defaultAWRecycleConfigValue() string {
raw, err := json.Marshal(defaultAWRecycle())
if err != nil {
return `{"title":"AW炫彩回收","subtitle":"点击查看回收说明","image_url":"","enabled":true}`
}
return string(raw)
}
func normalizeAWRecycle(item AWRecycleConfig) AWRecycleConfig {
def := defaultAWRecycle()
title := strings.TrimSpace(item.Title)
if title == "" {
title = def.Title
}
subtitle := strings.TrimSpace(item.Subtitle)
if subtitle == "" {
subtitle = def.Subtitle
}
return AWRecycleConfig{
Title: title,
Subtitle: subtitle,
ImageURL: strings.TrimSpace(item.ImageURL),
Enabled: item.Enabled,
}
}
@@ -25,6 +25,15 @@ type HomeConfigDTO struct {
Announcements []string `json:"announcements"`
Banners []HomeBannerItem `json:"banners"`
PublishOptions PublishOptionsDTO `json:"publish_options"`
AWRecycle AWRecycleConfig `json:"aw_recycle"`
}
// AWRecycleConfig 首页「AW炫彩回收」入口:点击展示可配置图片。
type AWRecycleConfig struct {
Title string `json:"title"`
Subtitle string `json:"subtitle"`
ImageURL string `json:"image_url"`
Enabled bool `json:"enabled"`
}
type OrderAgreementsDTO struct {
@@ -45,6 +45,7 @@ var defaultConfigs = []defaultConfig{
{Key: "integration.paddle_ocr_model", Value: "PaddleOCR-VL-1.6", Description: "PaddleOCR 识别模型"},
{Key: homeAnnouncementsConfigKey, Value: defaultHomeAnnouncementsConfigValue(), Description: "移动端首页公告 JSON 数组"},
{Key: homeBannersConfigKey, Value: defaultHomeBannersConfigValue(), Description: "移动端首页轮播图 JSON 数组"},
{Key: awRecycleConfigKey, Value: defaultAWRecycleConfigValue(), Description: "首页 AW炫彩回收入口配置 JSON(标题/副标题/展示图片)"},
{Key: publishOptionsConfigKey, Value: defaultPublishOptionsConfigValue(), Description: "发布页选项配置 JSON"},
{Key: salePriceConfigKey, Value: defaultSalePriceConfigValue(), Description: "内部出售定价规则 JSON"},
}
@@ -67,6 +68,7 @@ var adminVisibleConfigKeys = []string{
"listing.sale_price_config",
"mobile.home_announcements",
"mobile.home_banners",
"mobile.aw_recycle",
"order.agreements",
"order.pending_payment_timeout_minutes",
"order.return_overdue_grace_minutes",
@@ -28,6 +28,10 @@ func (s *Service) HomeConfig(ctx context.Context) (*HomeConfigDTO, error) {
if err != nil {
return nil, err
}
awRecycle, err := s.awRecycle(ctx)
if err != nil {
return nil, err
}
publishOptions, err := s.publishOptions(ctx)
if err != nil {
return nil, err
@@ -36,6 +40,7 @@ func (s *Service) HomeConfig(ctx context.Context) (*HomeConfigDTO, error) {
Announcements: announcements,
Banners: banners,
PublishOptions: publishOptions,
AWRecycle: awRecycle,
}, nil
}
@@ -62,3 +67,15 @@ func (s *Service) homeBanners(ctx context.Context) ([]HomeBannerItem, error) {
}
return normalizeHomeBanners(items), nil
}
func (s *Service) awRecycle(ctx context.Context) (AWRecycleConfig, error) {
value, err := s.repo.FindValue(ctx, awRecycleConfigKey)
if err != nil {
return defaultAWRecycle(), err
}
item := defaultAWRecycle()
if err := json.Unmarshal([]byte(value), &item); err != nil {
item = defaultAWRecycle()
}
return normalizeAWRecycle(item), nil
}