修复发布后图片无法看到bug

This commit is contained in:
yml2213
2026-05-23 17:48:56 +08:00
parent 80ae8af375
commit d661a22b8a
4 changed files with 159 additions and 8 deletions
+57 -2
View File
@@ -6,6 +6,7 @@ import (
"strconv"
"hfb_sys/backend/internal/middleware"
filemodule "hfb_sys/backend/internal/modules/file"
"hfb_sys/backend/pkg/response"
"github.com/gin-gonic/gin"
@@ -13,10 +14,11 @@ import (
type Handler struct {
service *Service
storage *filemodule.Storage
}
func NewHandler(service *Service) *Handler {
return &Handler{service: service}
func NewHandler(service *Service, storage *filemodule.Storage) *Handler {
return &Handler{service: service, storage: storage}
}
func (h *Handler) Create(c *gin.Context) {
@@ -215,6 +217,59 @@ func (h *Handler) FindPublic(c *gin.Context) {
response.OK(c, item)
}
func (h *Handler) Cover(c *gin.Context) {
id, ok := parseID(c)
if !ok {
return
}
key, err := h.service.FindPublicCoverKey(id)
if err != nil {
writeListingError(c, err)
return
}
h.writePublicObject(c, key)
}
func (h *Handler) Screenshot(c *gin.Context) {
id, ok := parseID(c)
if !ok {
return
}
index, err := strconv.Atoi(c.Param("index"))
if err != nil || index < 0 {
response.BadRequest(c, "截图序号不正确")
return
}
key, err := h.service.FindPublicScreenshotKey(id, index)
if err != nil {
writeListingError(c, err)
return
}
h.writePublicObject(c, key)
}
func (h *Handler) writePublicObject(c *gin.Context, key string) {
if h.storage == nil {
response.ServiceUnavailable(c, "文件存储未连接")
return
}
object, err := h.storage.Get(c.Request.Context(), key)
if err != nil {
response.Error(c, http.StatusNotFound, "not_found", "图片不存在或暂不可访问")
return
}
defer func() {
_ = object.Reader.Close()
}()
contentType := object.ContentType
if contentType == "" {
contentType = "application/octet-stream"
}
c.Header("Content-Type", contentType)
c.Header("Cache-Control", "public, max-age=300")
c.DataFromReader(http.StatusOK, object.Size, contentType, object.Reader, nil)
}
func (h *Handler) ListMine(c *gin.Context) {
ownerID, ok := currentUserID(c)
if !ok {
+84 -4
View File
@@ -3,6 +3,8 @@ package listing
import (
"encoding/json"
"errors"
"net/url"
"strconv"
"strings"
"time"
@@ -366,7 +368,7 @@ func (r *Repository) ListPublic() ([]ListingDTO, error) {
if err != nil {
return nil, err
}
return rowsToDTO(rows), nil
return publicListings(rowsToDTO(rows)), nil
}
func (r *Repository) ListMine(ownerID uint64) ([]ListingDTO, error) {
@@ -382,7 +384,33 @@ func (r *Repository) ListMine(ownerID uint64) ([]ListingDTO, error) {
}
func (r *Repository) FindPublic(id uint64) (*ListingDTO, error) {
return r.findDTO("l.id = ? AND l.status = ? AND l.review_status = ?", id, "published", "approved")
dto, err := r.findDTO("l.id = ? AND l.status = ? AND l.review_status = ?", id, "published", "approved")
if err != nil {
return nil, err
}
applyPublicListingURLs(dto)
return dto, nil
}
func (r *Repository) FindPublicCoverKey(id uint64) (string, error) {
return r.FindPublicScreenshotKey(id, 0)
}
func (r *Repository) FindPublicScreenshotKey(id uint64, index int) (string, error) {
if index < 0 {
return "", gorm.ErrRecordNotFound
}
dto, err := r.findDTO("l.id = ? AND l.status = ? AND l.review_status = ?", id, "published", "approved")
if err != nil {
return "", err
}
if index >= len(dto.ScreenshotURLS) {
return "", gorm.ErrRecordNotFound
}
if key := extractListingObjectKey(dto.ScreenshotURLS[index]); key != "" {
return key, nil
}
return "", gorm.ErrRecordNotFound
}
func (r *Repository) FindMine(ownerID uint64, id uint64) (*ListingDTO, error) {
@@ -456,6 +484,17 @@ func rowsToDTO(rows []listingRow) []ListingDTO {
return items
}
func publicListings(items []ListingDTO) []ListingDTO {
for index := range items {
applyPublicListingURLs(&items[index])
}
return items
}
func applyPublicListingURLs(item *ListingDTO) {
item.ScreenshotURLS = publicScreenshotURLs(item.ID, item.ScreenshotURLS, item.Status, item.ReviewStatus)
}
func (row listingRow) toDTO() ListingDTO {
assetSummary := decodeAssetSummary(row.AssetSummary)
screenshotURLS := cleanScreenshotURLs(decodeScreenshots(row.ScreenshotURLS))
@@ -474,7 +513,7 @@ func (row listingRow) toDTO() ListingDTO {
HafCoinAmount: row.HafCoinAmount,
AssetSummary: assetSummary,
ScreenshotURLS: screenshotURLS,
CoverURL: firstScreenshotURL(screenshotURLS),
CoverURL: publicCoverURL(row.ID, screenshotURLS, row.Status, row.ReviewStatus),
PriceHourly: row.PriceHourly,
PriceDaily: row.PriceDaily,
PriceWeekly: row.PriceWeekly,
@@ -504,7 +543,7 @@ func toDTO(account model.GameAccount, listing model.RentalListing) *ListingDTO {
HafCoinAmount: account.HafCoinAmount,
AssetSummary: assetSummary,
ScreenshotURLS: screenshotURLS,
CoverURL: firstScreenshotURL(screenshotURLS),
CoverURL: publicCoverURL(listing.ID, screenshotURLS, listing.Status, listing.ReviewStatus),
PriceHourly: listing.PriceHourly,
PriceDaily: listing.PriceDaily,
PriceWeekly: listing.PriceWeekly,
@@ -587,6 +626,47 @@ func firstScreenshotURL(urls []string) string {
return urls[0]
}
func publicCoverURL(listingID uint64, urls []string, status string, reviewStatus string) string {
fallback := firstScreenshotURL(urls)
if status != "published" || reviewStatus != "approved" || extractListingObjectKey(fallback) == "" {
return fallback
}
return "/api/listings/" + strconv.FormatUint(listingID, 10) + "/cover"
}
func publicScreenshotURLs(listingID uint64, urls []string, status string, reviewStatus string) []string {
if status != "published" || reviewStatus != "approved" {
return urls
}
publicURLs := make([]string, 0, len(urls))
for index, fileURL := range urls {
if extractListingObjectKey(fileURL) == "" {
publicURLs = append(publicURLs, fileURL)
continue
}
publicURLs = append(publicURLs, "/api/listings/"+strconv.FormatUint(listingID, 10)+"/screenshots/"+strconv.Itoa(index))
}
return publicURLs
}
func extractListingObjectKey(fileURL string) string {
if fileURL == "" {
return ""
}
parsed, err := url.Parse(fileURL)
if err != nil {
return ""
}
key := parsed.Query().Get("key")
if key == "" {
return ""
}
if !strings.HasPrefix(key, "listing/") || strings.Contains(key, "..") {
return ""
}
return key
}
func appendAuditLog(tx *gorm.DB, actorID uint64, action string, bizType string, bizID uint64, meta AuditMeta, detail map[string]any) error {
raw, err := json.Marshal(detail)
if err != nil {
@@ -179,6 +179,20 @@ func (s *Service) FindPublic(id uint64) (*ListingDTO, error) {
return s.repo.FindPublic(id)
}
func (s *Service) FindPublicCoverKey(id uint64) (string, error) {
if s.repo == nil {
return "", ErrDependencyUnavailable
}
return s.repo.FindPublicCoverKey(id)
}
func (s *Service) FindPublicScreenshotKey(id uint64, index int) (string, error) {
if s.repo == nil {
return "", ErrDependencyUnavailable
}
return s.repo.FindPublicScreenshotKey(id, index)
}
func (s *Service) FindMine(ownerID uint64, id uint64) (*ListingDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable