mirror of
https://git.fightbot.fun/hxuanyu/BingPaper.git
synced 2026-02-15 13:19:33 +08:00
优化图片处理逻辑:优先使用最小变体以节省流量,并新增 normalizeImageUrl 函数处理相对路径问题
This commit is contained in:
@@ -218,7 +218,7 @@ func ListImages(c *gin.Context) {
|
|||||||
|
|
||||||
result := []gin.H{}
|
result := []gin.H{}
|
||||||
for _, img := range images {
|
for _, img := range images {
|
||||||
result = append(result, formatMeta(&img))
|
result = append(result, formatMetaSummary(&img))
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, result)
|
c.JSON(http.StatusOK, result)
|
||||||
}
|
}
|
||||||
@@ -300,6 +300,49 @@ func serveLocal(c *gin.Context, key string, etag string, maxAge int) {
|
|||||||
io.Copy(c.Writer, reader)
|
io.Copy(c.Writer, reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func formatMetaSummary(img *model.Image) gin.H {
|
||||||
|
cfg := config.GetConfig()
|
||||||
|
|
||||||
|
// 找到最小的变体(Size 最小)
|
||||||
|
var smallest *model.ImageVariant
|
||||||
|
for i := range img.Variants {
|
||||||
|
v := &img.Variants[i]
|
||||||
|
if smallest == nil || v.Size < smallest.Size {
|
||||||
|
smallest = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variants := []gin.H{}
|
||||||
|
if smallest != nil {
|
||||||
|
url := smallest.PublicURL
|
||||||
|
if url == "" && cfg.API.Mode == "redirect" && img.URLBase != "" {
|
||||||
|
url = fmt.Sprintf("https://www.bing.com%s_%s.jpg", img.URLBase, smallest.Variant)
|
||||||
|
} else if cfg.API.Mode == "local" || url == "" {
|
||||||
|
url = fmt.Sprintf("%s/api/v1/image/date/%s?variant=%s&format=%s&mkt=%s", cfg.Server.BaseURL, img.Date, smallest.Variant, smallest.Format, img.Mkt)
|
||||||
|
}
|
||||||
|
variants = append(variants, gin.H{
|
||||||
|
"variant": smallest.Variant,
|
||||||
|
"format": smallest.Format,
|
||||||
|
"size": smallest.Size,
|
||||||
|
"url": url,
|
||||||
|
"storage_key": smallest.StorageKey,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return gin.H{
|
||||||
|
"date": img.Date,
|
||||||
|
"mkt": img.Mkt,
|
||||||
|
"title": img.Title,
|
||||||
|
"copyright": img.Copyright,
|
||||||
|
"copyrightlink": img.CopyrightLink,
|
||||||
|
"quiz": img.Quiz,
|
||||||
|
"startdate": img.StartDate,
|
||||||
|
"fullstartdate": img.FullStartDate,
|
||||||
|
"hsh": img.HSH,
|
||||||
|
"variants": variants,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func formatMeta(img *model.Image) gin.H {
|
func formatMeta(img *model.Image) gin.H {
|
||||||
cfg := config.GetConfig()
|
cfg := config.GetConfig()
|
||||||
variants := []gin.H{}
|
variants := []gin.H{}
|
||||||
|
|||||||
@@ -66,6 +66,21 @@ func TestHandleImageResponseRedirect(t *testing.T) {
|
|||||||
assert.Contains(t, variants[0]["url"].(string), "myserver.com")
|
assert.Contains(t, variants[0]["url"].(string), "myserver.com")
|
||||||
assert.Contains(t, variants[0]["url"].(string), "/api/v1/image/date/")
|
assert.Contains(t, variants[0]["url"].(string), "/api/v1/image/date/")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("FormatMetaSummary should only return the smallest variant", func(t *testing.T) {
|
||||||
|
imgWithMultipleVariants := &model.Image{
|
||||||
|
Date: "2026-01-26",
|
||||||
|
Variants: []model.ImageVariant{
|
||||||
|
{Variant: "UHD", Size: 1000, Format: "jpg"},
|
||||||
|
{Variant: "640x480", Size: 200, Format: "jpg"},
|
||||||
|
{Variant: "1920x1080", Size: 500, Format: "jpg"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
meta := formatMetaSummary(imgWithMultipleVariants)
|
||||||
|
variants := meta["variants"].([]gin.H)
|
||||||
|
assert.Equal(t, 1, len(variants))
|
||||||
|
assert.Equal(t, "640x480", variants[0]["variant"])
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetRegions(t *testing.T) {
|
func TestGetRegions(t *testing.T) {
|
||||||
|
|||||||
@@ -35,6 +35,26 @@ export const buildApiUrl = (endpoint: string): string => {
|
|||||||
return `${API_BASE_URL}${normalizedEndpoint}`
|
return `${API_BASE_URL}${normalizedEndpoint}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标准化图片 URL
|
||||||
|
* 当后端返回相对路径且配置了绝对 API 基础地址时,自动拼接完整域名
|
||||||
|
*/
|
||||||
|
export const normalizeImageUrl = (url: string | undefined): string => {
|
||||||
|
if (!url) return ''
|
||||||
|
if (url.startsWith('http')) return url
|
||||||
|
|
||||||
|
// 处理相对路径问题:如果配置了绝对 API 基础地址,则拼接 Origin
|
||||||
|
if (API_BASE_URL.startsWith('http')) {
|
||||||
|
try {
|
||||||
|
const origin = new URL(API_BASE_URL).origin
|
||||||
|
return url.startsWith('/') ? origin + url : origin + '/' + url
|
||||||
|
} catch (e) {
|
||||||
|
// 解析失败则返回原样
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP 状态码枚举
|
* HTTP 状态码枚举
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -156,7 +156,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 图片网格 -->
|
<!-- 图片网格 -->
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-6">
|
||||||
<div
|
<div
|
||||||
v-for="(image, index) in images"
|
v-for="(image, index) in images"
|
||||||
:key="image.date || index"
|
:key="image.date || index"
|
||||||
@@ -264,6 +264,7 @@
|
|||||||
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
|
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
|
||||||
import { useImageList } from '@/composables/useImages'
|
import { useImageList } from '@/composables/useImages'
|
||||||
import { bingPaperApi } from '@/lib/api-service'
|
import { bingPaperApi } from '@/lib/api-service'
|
||||||
|
import { normalizeImageUrl } from '@/lib/api-config'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { getDefaultMkt, setSavedMkt, SUPPORTED_REGIONS, setSupportedRegions } from '@/lib/mkt-utils'
|
import { getDefaultMkt, setSavedMkt, SUPPORTED_REGIONS, setSupportedRegions } from '@/lib/mkt-utils'
|
||||||
import {
|
import {
|
||||||
@@ -570,8 +571,11 @@ const getLatestImageUrl = () => {
|
|||||||
return bingPaperApi.getImageUrlByDate(latestImage.value.date, 'UHD', 'jpg', latestImage.value.mkt)
|
return bingPaperApi.getImageUrlByDate(latestImage.value.date, 'UHD', 'jpg', latestImage.value.mkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取图片 URL(缩略图 - 使用较小分辨率节省流量)
|
// 获取图片 URL(缩略图 - 优先使用后端返回的最小变体以节省流量)
|
||||||
const getImageUrl = (image: any) => {
|
const getImageUrl = (image: any) => {
|
||||||
|
if (image.variants && image.variants.length > 0) {
|
||||||
|
return normalizeImageUrl(image.variants[0].url)
|
||||||
|
}
|
||||||
return bingPaperApi.getImageUrlByDate(image.date!, '640x480', 'jpg', image.mkt)
|
return bingPaperApi.getImageUrlByDate(image.date!, '640x480', 'jpg', image.mkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user