feat: 接入旧站管理端并完整迁移后台能力

This commit is contained in:
yml
2026-11-12 22:03:01 +08:00
parent e5f923706b
commit a4441bba9a
509 changed files with 140714 additions and 1068 deletions
+25 -10
View File
@@ -94,15 +94,7 @@ func (h *Handler) writeObject(c *gin.Context, publicOnly bool) {
response.BadRequest(c, "文件 key 不正确")
return
}
if publicOnly &&
!strings.HasPrefix(key, "home-banner/") &&
!strings.HasPrefix(key, "avatar/") &&
!strings.HasPrefix(key, "announcement/") &&
!strings.HasPrefix(key, "mohong/") &&
!strings.HasPrefix(key, "crash/") &&
!strings.HasPrefix(key, "aw-recycle/") &&
!strings.HasPrefix(key, "cooperation-feedback/") &&
!strings.HasPrefix(key, "support-qrcode/") {
if publicOnly && !isPublicObjectKey(key) {
response.Error(c, http.StatusNotFound, "not_found", "文件不存在或暂不可访问")
return
}
@@ -142,10 +134,33 @@ func (h *Handler) writeObject(c *gin.Context, publicOnly bool) {
contentType = "application/octet-stream"
}
c.Header("Content-Type", contentType)
c.Header("Cache-Control", "private, max-age=300")
if publicOnly {
c.Header("Cache-Control", "public, max-age=86400")
} else {
c.Header("Cache-Control", "private, max-age=300")
}
c.DataFromReader(http.StatusOK, object.Size, contentType, object.Reader, nil)
}
func isPublicObjectKey(key string) bool {
for _, prefix := range []string{
"home-banner/",
"avatar/",
"announcement/",
"mohong/",
"crash/",
"aw-recycle/",
"cooperation-feedback/",
"support-qrcode/",
"points-mall/",
} {
if strings.HasPrefix(key, prefix) {
return true
}
}
return false
}
func writeFileError(c *gin.Context, err error) {
response.RecordError(c, err)
switch {
+4 -2
View File
@@ -109,7 +109,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 == "announcement" || scene == "mohong" || scene == "crash" || scene == "aw-recycle" || scene == "cooperation-feedback" || scene == "support-qrcode" {
if scene == "home-banner" || scene == "avatar" || scene == "announcement" || scene == "mohong" || scene == "crash" || scene == "aw-recycle" || scene == "cooperation-feedback" || scene == "support-qrcode" || scene == "points-mall" {
fileURL = "/api/public/files/object?key=" + url.QueryEscape(key)
}
return fileURL
@@ -118,12 +118,14 @@ 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", "support-qrcode", "mohong", "crash", "aw-recycle", "cooperation-feedback", "manual-disbursement", "operating-expense":
case "listing", "handoff", "dispute", "realname", "avatar", "home-banner", "chat", "payment-cert", "announcement", "qrcode", "support-qrcode", "mohong", "crash", "aw-recycle", "cooperation-feedback", "manual-disbursement", "operating-expense", "points-mall":
return scene
case "listing_screenshot", "listing-screenshot":
return "listing"
case "operating_expense":
return "operating-expense"
case "points_mall":
return "points-mall"
default:
return "misc"
}
@@ -87,6 +87,19 @@ func TestSupportQrcodeSceneUsesPublicFileURL(t *testing.T) {
}
}
func TestPointsMallSceneUsesPublicFileURL(t *testing.T) {
if got := normalizeScene("points_mall"); got != "points-mall" {
t.Fatalf("normalize points_mall scene = %q, want points-mall", got)
}
got := fileURLForScene("points-mall", "points-mall/2026/11/04/example.webp")
if !strings.HasPrefix(got, "/api/public/files/object?") {
t.Fatalf("points-mall file url = %q, want public file endpoint", got)
}
if !isPublicObjectKey("points-mall/2026/11/04/example.webp") {
t.Fatal("points-mall object should be publicly readable")
}
}
func TestNormalizeSceneListingScreenshotAndOperatingExpense(t *testing.T) {
if got := normalizeScene("listing_screenshot"); got != "listing" {
t.Fatalf("normalize listing_screenshot scene = %q, want listing", got)