From 8ef66b2cb1244be2325a4e633c9d8f161bd2bf08 Mon Sep 17 00:00:00 2001
From: hanxuanyu <2252193204@qq.com>
Date: Fri, 30 Jan 2026 15:45:55 +0800
Subject: [PATCH] =?UTF-8?q?=E5=9B=BD=E5=AE=B6=E5=9C=B0=E5=8C=BA=E6=8E=A5?=
=?UTF-8?q?=E5=8F=A3=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
config.example.yaml | 1 +
docs/docs.go | 23 ++++
docs/swagger.json | 23 ++++
docs/swagger.yaml | 15 +++
internal/config/config.go | 8 +-
internal/http/handlers/image.go | 142 ++++++++++++++++++------
internal/http/router.go | 1 +
internal/service/fetcher/fetcher.go | 32 ++++--
internal/service/image/image_service.go | 51 ++++++++-
internal/util/regions.go | 47 +++++---
webapp/src/composables/useImages.ts | 33 ++++++
webapp/src/lib/api-service.ts | 8 ++
webapp/src/lib/api-types.ts | 1 +
webapp/src/lib/mkt-utils.ts | 34 +++---
webapp/src/views/AdminConfig.vue | 35 ++++--
webapp/src/views/Home.vue | 132 +++++++++++++++++++++-
16 files changed, 491 insertions(+), 95 deletions(-)
diff --git a/config.example.yaml b/config.example.yaml
index ba45dd1..ea340ef 100644
--- a/config.example.yaml
+++ b/config.example.yaml
@@ -17,6 +17,7 @@ log:
api:
mode: local # local | redirect
enable_mkt_fallback: true # 当请求的地区不存在时,是否回退到默认地区
+ enable_on_demand_fetch: false # 是否开启按需抓取(当数据库中没有请求的地区图片时,实时从 Bing 抓取)
cron:
enabled: true
diff --git a/docs/docs.go b/docs/docs.go
index ea4ffca..a575e51 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -675,6 +675,29 @@ const docTemplate = `{
}
}
},
+ "/images/global/today": {
+ "get": {
+ "description": "获取配置文件中所有已开启地区的今日必应图片元数据(缩略图)",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "image"
+ ],
+ "summary": "获取所有地区的今日图片列表",
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/handlers.ImageMetaResp"
+ }
+ }
+ }
+ }
+ }
+ },
"/regions": {
"get": {
"description": "返回系统支持的所有必应地区编码及标签。如果配置中指定了抓取地区,这些地区将排在列表最前面(置顶)。",
diff --git a/docs/swagger.json b/docs/swagger.json
index 72ef2d0..a88c272 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -669,6 +669,29 @@
}
}
},
+ "/images/global/today": {
+ "get": {
+ "description": "获取配置文件中所有已开启地区的今日必应图片元数据(缩略图)",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "image"
+ ],
+ "summary": "获取所有地区的今日图片列表",
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/handlers.ImageMetaResp"
+ }
+ }
+ }
+ }
+ }
+ },
"/regions": {
"get": {
"description": "返回系统支持的所有必应地区编码及标签。如果配置中指定了抓取地区,这些地区将排在列表最前面(置顶)。",
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index 14a2d67..214810b 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -700,6 +700,21 @@ paths:
summary: 获取图片列表
tags:
- image
+ /images/global/today:
+ get:
+ description: 获取配置文件中所有已开启地区的今日必应图片元数据(缩略图)
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ items:
+ $ref: '#/definitions/handlers.ImageMetaResp'
+ type: array
+ summary: 获取所有地区的今日图片列表
+ tags:
+ - image
/regions:
get:
description: 返回系统支持的所有必应地区编码及标签。如果配置中指定了抓取地区,这些地区将排在列表最前面(置顶)。
diff --git a/internal/config/config.go b/internal/config/config.go
index a51fbca..38f2b24 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -60,8 +60,9 @@ func (c LogConfig) GetShowDBLog() bool { return c.ShowDBLog }
func (c LogConfig) GetDBLogLevel() string { return c.DBLogLevel }
type APIConfig struct {
- Mode string `mapstructure:"mode" yaml:"mode"` // local | redirect
- EnableMktFallback bool `mapstructure:"enable_mkt_fallback" yaml:"enable_mkt_fallback"` // 当请求的地区不存在时,是否回退到默认地区
+ Mode string `mapstructure:"mode" yaml:"mode"` // local | redirect
+ EnableMktFallback bool `mapstructure:"enable_mkt_fallback" yaml:"enable_mkt_fallback"` // 当请求的地区不存在时,是否回退到默认地区
+ EnableOnDemandFetch bool `mapstructure:"enable_on_demand_fetch" yaml:"enable_on_demand_fetch"` // 是否启用按需抓取
}
type CronConfig struct {
@@ -165,7 +166,8 @@ func Init(configPath string) error {
v.SetDefault("log.show_db_log", false)
v.SetDefault("log.db_log_level", "info")
v.SetDefault("api.mode", "redirect")
- v.SetDefault("api.enable_mkt_fallback", true)
+ v.SetDefault("api.enable_mkt_fallback", false)
+ v.SetDefault("api.enable_on_demand_fetch", false)
v.SetDefault("cron.enabled", true)
v.SetDefault("cron.daily_spec", "20 8-23/4 * * *")
v.SetDefault("retention.days", 0)
diff --git a/internal/http/handlers/image.go b/internal/http/handlers/image.go
index ef3f0a9..5828c8d 100644
--- a/internal/http/handlers/image.go
+++ b/internal/http/handlers/image.go
@@ -5,8 +5,8 @@ import (
"fmt"
"io"
"net/http"
- "sort"
"strconv"
+ "strings"
"BingPaper/internal/config"
"BingPaper/internal/model"
@@ -48,12 +48,13 @@ type ImageMetaResp struct {
// @Param format query string false "格式 (jpg)" default(jpg)
// @Produce image/jpeg
// @Success 200 {file} binary
+// @Failure 404 {object} map[string]string "图片未找到,响应体包含具体原因"
// @Router /image/today [get]
func GetToday(c *gin.Context) {
mkt := c.Query("mkt")
img, err := image.GetTodayImage(mkt)
if err != nil {
- c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
+ sendImageNotFound(c, mkt)
return
}
handleImageResponse(c, img, 7200) // 2小时
@@ -66,12 +67,13 @@ func GetToday(c *gin.Context) {
// @Param mkt query string false "地区编码 (如 zh-CN, en-US)"
// @Produce json
// @Success 200 {object} ImageMetaResp
+// @Failure 404 {object} map[string]string "图片未找到,响应体包含具体原因"
// @Router /image/today/meta [get]
func GetTodayMeta(c *gin.Context) {
mkt := c.Query("mkt")
img, err := image.GetTodayImage(mkt)
if err != nil {
- c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
+ sendImageNotFound(c, mkt)
return
}
c.Header("Cache-Control", "public, max-age=7200") // 2小时
@@ -87,12 +89,13 @@ func GetTodayMeta(c *gin.Context) {
// @Param format query string false "格式" default(jpg)
// @Produce image/jpeg
// @Success 200 {file} binary
+// @Failure 404 {object} map[string]string "图片未找到,响应体包含具体原因"
// @Router /image/random [get]
func GetRandom(c *gin.Context) {
mkt := c.Query("mkt")
img, err := image.GetRandomImage(mkt)
if err != nil {
- c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
+ sendImageNotFound(c, mkt)
return
}
handleImageResponse(c, img, 0) // 禁用缓存
@@ -105,12 +108,13 @@ func GetRandom(c *gin.Context) {
// @Param mkt query string false "地区编码 (如 zh-CN, en-US)"
// @Produce json
// @Success 200 {object} ImageMetaResp
+// @Failure 404 {object} map[string]string "图片未找到,响应体包含具体原因"
// @Router /image/random/meta [get]
func GetRandomMeta(c *gin.Context) {
mkt := c.Query("mkt")
img, err := image.GetRandomImage(mkt)
if err != nil {
- c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
+ sendImageNotFound(c, mkt)
return
}
c.Header("Cache-Control", "no-cache, no-store, must-revalidate")
@@ -127,13 +131,14 @@ func GetRandomMeta(c *gin.Context) {
// @Param format query string false "格式" default(jpg)
// @Produce image/jpeg
// @Success 200 {file} binary
+// @Failure 404 {object} map[string]string "图片未找到,响应体包含具体原因"
// @Router /image/date/{date} [get]
func GetByDate(c *gin.Context) {
date := c.Param("date")
mkt := c.Query("mkt")
img, err := image.GetImageByDate(date, mkt)
if err != nil {
- c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
+ sendImageNotFound(c, mkt)
return
}
handleImageResponse(c, img, 604800) // 7天
@@ -147,13 +152,14 @@ func GetByDate(c *gin.Context) {
// @Param mkt query string false "地区编码 (如 zh-CN, en-US)"
// @Produce json
// @Success 200 {object} ImageMetaResp
+// @Failure 404 {object} map[string]string "图片未找到,响应体包含具体原因"
// @Router /image/date/{date}/meta [get]
func GetByDateMeta(c *gin.Context) {
date := c.Param("date")
mkt := c.Query("mkt")
img, err := image.GetImageByDate(date, mkt)
if err != nil {
- c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
+ sendImageNotFound(c, mkt)
return
}
c.Header("Cache-Control", "public, max-age=604800") // 7天
@@ -223,6 +229,55 @@ func ListImages(c *gin.Context) {
c.JSON(http.StatusOK, result)
}
+// ListGlobalTodayImages 获取所有地区的今日图片列表
+// @Summary 获取所有地区的今日图片列表
+// @Description 获取配置文件中所有已开启地区的今日必应图片元数据(缩略图)
+// @Tags image
+// @Produce json
+// @Success 200 {array} ImageMetaResp
+// @Router /images/global/today [get]
+func ListGlobalTodayImages(c *gin.Context) {
+ images, err := image.GetAllRegionsTodayImages()
+ if err != nil {
+ util.Logger.Error("ListGlobalTodayImages service call failed", zap.Error(err))
+ c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
+ return
+ }
+
+ result := []gin.H{}
+ for _, img := range images {
+ result = append(result, formatMetaSummary(&img))
+ }
+ c.JSON(http.StatusOK, result)
+}
+
+func sendImageNotFound(c *gin.Context, mkt string) {
+ cfg := config.GetConfig().API
+ message := "image not found"
+
+ if mkt != "" {
+ reasons := []string{}
+ if !util.IsValidRegion(mkt) {
+ reasons = append(reasons, fmt.Sprintf("[%s] is not a standard region code", mkt))
+ } else {
+ if !cfg.EnableOnDemandFetch {
+ reasons = append(reasons, "on-demand fetch is disabled")
+ }
+ if !cfg.EnableMktFallback {
+ reasons = append(reasons, "region fallback is disabled")
+ }
+ }
+
+ if len(reasons) > 0 {
+ message = fmt.Sprintf("Image not found for region [%s]. Reasons: %s.", mkt, strings.Join(reasons, ", "))
+ } else {
+ message = fmt.Sprintf("Image not found for region [%s] even after on-demand fetch and fallback attempts.", mkt)
+ }
+ }
+
+ c.JSON(http.StatusNotFound, gin.H{"error": message})
+}
+
func handleImageResponse(c *gin.Context, img *model.Image, maxAge int) {
variant := c.DefaultQuery("variant", "UHD")
format := c.DefaultQuery("format", "jpg")
@@ -387,34 +442,51 @@ func GetRegions(c *gin.Context) {
cfg := config.GetConfig()
pinned := cfg.Fetcher.Regions
- // 创建副本以避免修改原始全局变量
- all := make([]util.Region, len(util.AllRegions))
- copy(all, util.AllRegions)
-
- if len(pinned) > 0 {
- // 创建一个 Map 用于快速查找置顶地区及其顺序
- pinnedMap := make(map[string]int)
- for i, v := range pinned {
- pinnedMap[v] = i
- }
-
- // 对列表进行稳定排序,使置顶地区排在前面
- sort.SliceStable(all, func(i, j int) bool {
- idxI, okI := pinnedMap[all[i].Value]
- idxJ, okJ := pinnedMap[all[j].Value]
-
- if okI && okJ {
- return idxI < idxJ
- }
- if okI {
- return true
- }
- if okJ {
- return false
- }
- return false // 保持非置顶地区的原有相对顺序
- })
+ if len(pinned) == 0 {
+ // 如果没有配置抓取地区,返回所有支持的地区
+ c.JSON(http.StatusOK, util.AllRegions)
+ return
}
- c.JSON(http.StatusOK, all)
+ // 创建一个 Map 用于快速查找配置的地区
+ pinnedMap := make(map[string]bool)
+ for _, v := range pinned {
+ pinnedMap[v] = true
+ }
+
+ // 只返回配置中的地区,并保持配置中的顺序
+ var result []util.Region
+ // 为了保持配置顺序,我们遍历 pinned 而不是 AllRegions
+ for _, pVal := range pinned {
+ for _, r := range util.AllRegions {
+ if r.Value == pVal {
+ result = append(result, r)
+ break
+ }
+ }
+ }
+
+ // 如果配置了一些不在 AllRegions 里的 mkt,上述循环可能漏掉
+ // 但根据之前的逻辑,AllRegions 是已知的 17 个地区。
+ // 如果用户配置了 fr-CA (不在 17 个内),我们也应该返回它吗?
+ // 需求说 "前端页面对地区进行约束",如果配置了,前端就该显示。
+ // 如果不在 AllRegions 里的,我们直接返回原始编码作为 label 或者查找一下。
+
+ if len(result) < len(pinned) {
+ // 补全不在 AllRegions 里的地区
+ for _, pVal := range pinned {
+ found := false
+ for _, r := range result {
+ if r.Value == pVal {
+ found = true
+ break
+ }
+ }
+ if !found {
+ result = append(result, util.Region{Value: pVal, Label: pVal})
+ }
+ }
+ }
+
+ c.JSON(http.StatusOK, result)
}
diff --git a/internal/http/router.go b/internal/http/router.go
index dce749f..d29ddac 100644
--- a/internal/http/router.go
+++ b/internal/http/router.go
@@ -47,6 +47,7 @@ func SetupRouter(webFS embed.FS) *gin.Engine {
img.GET("/date/:date/meta", handlers.GetByDateMeta)
}
api.GET("/images", handlers.ListImages)
+ api.GET("/images/global/today", handlers.ListGlobalTodayImages)
api.GET("/regions", handlers.GetRegions)
// 管理接口
diff --git a/internal/service/fetcher/fetcher.go b/internal/service/fetcher/fetcher.go
index 4029d95..2ac29d6 100644
--- a/internal/service/fetcher/fetcher.go
+++ b/internal/service/fetcher/fetcher.go
@@ -61,15 +61,8 @@ func (f *Fetcher) Fetch(ctx context.Context, n int) error {
}
for _, mkt := range regions {
- util.Logger.Info("Fetching images for region", zap.String("mkt", mkt))
- // 调用两次 API 获取最多两周的数据
- // 第一次 idx=0&n=8 (今天起往回数 8 张)
- if err := f.fetchByMkt(ctx, mkt, 0, 8); err != nil {
- util.Logger.Error("Failed to fetch images", zap.String("mkt", mkt), zap.Int("idx", 0), zap.Error(err))
- }
- // 第二次 idx=7&n=8 (7天前起往回数 8 张,与第一次有重叠,确保不漏)
- if err := f.fetchByMkt(ctx, mkt, 7, 8); err != nil {
- util.Logger.Error("Failed to fetch images", zap.String("mkt", mkt), zap.Int("idx", 7), zap.Error(err))
+ if err := f.FetchRegion(ctx, mkt); err != nil {
+ util.Logger.Error("Failed to fetch region images", zap.String("mkt", mkt), zap.Error(err))
}
}
@@ -77,6 +70,27 @@ func (f *Fetcher) Fetch(ctx context.Context, n int) error {
return nil
}
+// FetchRegion 抓取指定地区的图片
+func (f *Fetcher) FetchRegion(ctx context.Context, mkt string) error {
+ if !util.IsValidRegion(mkt) {
+ util.Logger.Warn("Skipping fetch for invalid region", zap.String("mkt", mkt))
+ return fmt.Errorf("invalid region code: %s", mkt)
+ }
+ util.Logger.Info("Fetching images for region", zap.String("mkt", mkt))
+ // 调用两次 API 获取最多两周的数据
+ // 第一次 idx=0&n=8 (今天起往回数 8 张)
+ if err := f.fetchByMkt(ctx, mkt, 0, 8); err != nil {
+ util.Logger.Error("Failed to fetch images", zap.String("mkt", mkt), zap.Int("idx", 0), zap.Error(err))
+ return err
+ }
+ // 第二次 idx=7&n=8 (7天前起往回数 8 张,与第一次有重叠,确保不漏)
+ if err := f.fetchByMkt(ctx, mkt, 7, 8); err != nil {
+ util.Logger.Error("Failed to fetch images", zap.String("mkt", mkt), zap.Int("idx", 7), zap.Error(err))
+ // 第二次失败不一定返回错误,因为可能第一次已经拿到了
+ }
+ return nil
+}
+
func (f *Fetcher) fetchByMkt(ctx context.Context, mkt string, idx int, n int) error {
url := fmt.Sprintf("%s?format=js&idx=%d&n=%d&uhd=1&mkt=%s", config.BingAPIBase, idx, n, mkt)
util.Logger.Debug("Requesting Bing API", zap.String("url", url))
diff --git a/internal/service/image/image_service.go b/internal/service/image/image_service.go
index 4ed11ce..426ca29 100644
--- a/internal/service/image/image_service.go
+++ b/internal/service/image/image_service.go
@@ -8,6 +8,7 @@ import (
"BingPaper/internal/config"
"BingPaper/internal/model"
"BingPaper/internal/repo"
+ "BingPaper/internal/service/fetcher"
"BingPaper/internal/storage"
"BingPaper/internal/util"
@@ -58,8 +59,19 @@ func GetTodayImage(mkt string) (*model.Image, error) {
tx = tx.Where("mkt = ?", mkt)
}
err := tx.Preload("Variants").First(&img).Error
+ if err != nil && mkt != "" && config.GetConfig().API.EnableOnDemandFetch && util.IsValidRegion(mkt) {
+ // 如果没找到,尝试按需抓取该地区
+ util.Logger.Info("Image not found in DB, attempting on-demand fetch", zap.String("mkt", mkt))
+ f := fetcher.NewFetcher()
+ _ = f.FetchRegion(context.Background(), mkt)
+
+ // 抓取后重新查询
+ tx = repo.DB.Where("date = ?", today).Where("mkt = ?", mkt)
+ err = tx.Preload("Variants").First(&img).Error
+ }
+
if err != nil {
- // 如果今天没有,尝试获取最近的一张
+ // 如果今天还是没有,尝试获取最近的一张
tx = repo.DB.Order("date desc")
if mkt != "" {
tx = tx.Where("mkt = ?", mkt)
@@ -79,6 +91,22 @@ func GetTodayImage(mkt string) (*model.Image, error) {
return &img, err
}
+func GetAllRegionsTodayImages() ([]model.Image, error) {
+ regions := config.GetConfig().Fetcher.Regions
+ if len(regions) == 0 {
+ regions = []string{config.GetConfig().GetDefaultMkt()}
+ }
+
+ var images []model.Image
+ for _, mkt := range regions {
+ img, err := GetTodayImage(mkt)
+ if err == nil {
+ images = append(images, *img)
+ }
+ }
+ return images, nil
+}
+
func GetRandomImage(mkt string) (*model.Image, error) {
var img model.Image
// SQLite 使用 RANDOM(), MySQL/Postgres 使用 RANDOM() 或 RAND()
@@ -89,6 +117,17 @@ func GetRandomImage(mkt string) (*model.Image, error) {
tx = tx.Where("mkt = ?", mkt)
}
tx.Count(&count)
+ if count == 0 && mkt != "" && config.GetConfig().API.EnableOnDemandFetch && util.IsValidRegion(mkt) {
+ // 如果没找到,尝试按需抓取该地区
+ util.Logger.Info("No images found in DB for region, attempting on-demand fetch", zap.String("mkt", mkt))
+ f := fetcher.NewFetcher()
+ _ = f.FetchRegion(context.Background(), mkt)
+
+ // 抓取后重新计数
+ tx = repo.DB.Model(&model.Image{}).Where("mkt = ?", mkt)
+ tx.Count(&count)
+ }
+
if count == 0 {
return nil, fmt.Errorf("no images found")
}
@@ -127,6 +166,16 @@ func GetImageByDate(date string, mkt string) (*model.Image, error) {
tx = tx.Where("mkt = ?", mkt)
}
err := tx.Preload("Variants").First(&img).Error
+ if err != nil && mkt != "" && config.GetConfig().API.EnableOnDemandFetch && util.IsValidRegion(mkt) {
+ // 如果没找到,尝试按需抓取该地区
+ util.Logger.Info("Image not found in DB for date, attempting on-demand fetch", zap.String("mkt", mkt), zap.String("date", date))
+ f := fetcher.NewFetcher()
+ _ = f.FetchRegion(context.Background(), mkt)
+
+ // 抓取后重新查询
+ tx = repo.DB.Where("date = ?", date).Where("mkt = ?", mkt)
+ err = tx.Preload("Variants").First(&img).Error
+ }
// 兜底逻辑
if err != nil && mkt != "" && config.GetConfig().API.EnableMktFallback {
diff --git a/internal/util/regions.go b/internal/util/regions.go
index 75ea1a3..9ae9a74 100644
--- a/internal/util/regions.go
+++ b/internal/util/regions.go
@@ -1,26 +1,37 @@
package util
+import "golang.org/x/text/language"
+
type Region struct {
Value string `json:"value"`
Label string `json:"label"`
}
-var AllRegions = []Region{
- {Value: "zh-CN", Label: "中国 (zh-CN)"},
- {Value: "en-US", Label: "美国 (en-US)"},
- {Value: "ja-JP", Label: "日本 (ja-JP)"},
- {Value: "en-AU", Label: "澳大利亚 (en-AU)"},
- {Value: "en-GB", Label: "英国 (en-GB)"},
- {Value: "de-DE", Label: "德国 (de-DE)"},
- {Value: "en-NZ", Label: "新西兰 (en-NZ)"},
- {Value: "en-CA", Label: "加拿大 (en-CA)"},
- {Value: "fr-FR", Label: "法国 (fr-FR)"},
- {Value: "it-IT", Label: "意大利 (it-IT)"},
- {Value: "es-ES", Label: "西班牙 (es-ES)"},
- {Value: "pt-BR", Label: "巴西 (pt-BR)"},
- {Value: "ko-KR", Label: "韩国 (ko-KR)"},
- {Value: "en-IN", Label: "印度 (en-IN)"},
- {Value: "ru-RU", Label: "俄罗斯 (ru-RU)"},
- {Value: "zh-HK", Label: "中国香港 (zh-HK)"},
- {Value: "zh-TW", Label: "中国台湾 (zh-TW)"},
+// IsValidRegion 校验是否为标准的地区编码 (BCP 47)
+func IsValidRegion(mkt string) bool {
+ if mkt == "" {
+ return false
+ }
+ _, err := language.Parse(mkt)
+ return err == nil
+}
+
+var AllRegions = []Region{
+ {Value: "zh-CN", Label: "中国"},
+ {Value: "en-US", Label: "美国"},
+ {Value: "ja-JP", Label: "日本"},
+ {Value: "en-AU", Label: "澳大利亚"},
+ {Value: "en-GB", Label: "英国"},
+ {Value: "de-DE", Label: "德国"},
+ {Value: "en-NZ", Label: "新西兰"},
+ {Value: "en-CA", Label: "加拿大"},
+ {Value: "fr-FR", Label: "法国"},
+ {Value: "it-IT", Label: "意大利"},
+ {Value: "es-ES", Label: "西班牙"},
+ {Value: "pt-BR", Label: "巴西"},
+ {Value: "ko-KR", Label: "韩国"},
+ {Value: "en-IN", Label: "印度"},
+ {Value: "ru-RU", Label: "俄罗斯"},
+ {Value: "zh-HK", Label: "中国香港"},
+ {Value: "zh-TW", Label: "中国台湾"},
}
diff --git a/webapp/src/composables/useImages.ts b/webapp/src/composables/useImages.ts
index 4a93c22..1468fdb 100644
--- a/webapp/src/composables/useImages.ts
+++ b/webapp/src/composables/useImages.ts
@@ -37,6 +37,39 @@ export function useTodayImage(mkt?: string) {
}
}
+/**
+ * 获取全球今日图片
+ */
+export function useGlobalTodayImages() {
+ const images = ref
+ 如果请求的地区无数据,自动回退到默认地区 +
++ 如果请求的地区无数据,尝试实时从 Bing 抓取 +
+- 如果请求的地区无数据,自动回退到默认地区 -
diff --git a/webapp/src/views/Home.vue b/webapp/src/views/Home.vue index 122b310..5466122 100644 --- a/webapp/src/views/Home.vue +++ b/webapp/src/views/Home.vue @@ -69,6 +69,81 @@