service.xpcool.com/internal/controller/wallpaper/open.go
夏犀麟 d0a084b80e
Some checks failed
Build and Deploy (service.xpcool.com) / build-and-deploy (push) Failing after 28s
feat(wallpaper): 平台配置脱敏回显 + 图库元字段补齐
后台做完界面才发现的两个接口缺口:

1) 平台配置不回显 → 用户只改一个开关,defaultQuery / purity / baseUrl
   会被一起清空(SaveSource 只对 apiKey/apiSecret 做了"留空即保留")。
   现在 Sources() 返回脱敏后的 config(凭据一律置空,是否已设置由
   HasApiKey 表达),前台接口不下发该字段 —— toAPISource 加 withConfig
   开关,公开接口没必要泄露自建反代地址等内部信息。

2) Item 缺 enabled / sort / remark → 后台列表无法显示启用状态,
   编辑抽屉也拿不到当前值。补齐字段并在 library.toItem 中填充,
   开源平台条目保持默认值(这三个字段对前台无意义)。

另抽出 sanitizeSourceConfig 统一处理凭据抹除,避免以后再加配置项时漏抹。
2026-09-14 01:48:23 +08:00

89 lines
3.4 KiB
Go

package wallpaper
import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
wallpaperv1 "service.xpcool.com/api/wallpaper"
"service.xpcool.com/internal/model/dto"
wallpapersvc "service.xpcool.com/internal/service/wallpaper"
)
// OpenController 前台读取接口(免鉴权,供 xpcool.com 调用)。
type OpenController struct{}
// NewOpen 构造前台控制器。
func NewOpen() *OpenController { return &OpenController{} }
// Sources 返回全部来源清单。
//
// 除开源平台外还带回自建图库的启用数量:前台据此决定要不要显示
// 「我的图库」这个入口 —— 一张图都没有时显示它只会让人点进去看空白。
func (c *OpenController) Sources(ctx context.Context, req *wallpaperv1.OpenSourceListReq) (res *wallpaperv1.OpenSourceListRes, err error) {
svc := wallpapersvc.Wallpaper()
list, err := svc.Sources(ctx)
if err != nil {
return nil, err
}
// 图库计数失败不影响平台列表:把 0 当成「没有自建图」,入口不显示即可,
// 没必要因为一个计数把整个来源接口拖垮。
mineCount, err := svc.MineCount(ctx)
if err != nil {
g.Log().Warningf(ctx, "统计自建图库数量失败: %v", err)
mineCount = 0
}
out := make([]*wallpaperv1.SourceInfo, 0, len(list))
for i := range list {
// 前台不带平台配置:公开接口没必要下发 baseUrl 等内部信息。
out = append(out, toAPISource(&list[i], false))
}
return &wallpaperv1.OpenSourceListRes{List: out, MineCount: mineCount}, nil
}
// List 按来源分页取图。
func (c *OpenController) List(ctx context.Context, req *wallpaperv1.OpenListReq) (res *wallpaperv1.OpenListRes, err error) {
q := dto.WallpaperQuery{
Source: req.Source,
Query: req.Query,
Orientation: req.Orientation,
Tag: req.Tag,
Page: req.Page,
Size: req.Size,
}
items, total, err := wallpapersvc.Wallpaper().List(ctx, q)
if err != nil {
// 前台是公开接口,平台侧的原始错误(含 URL、Key 片段)不应直接抛给浏览器
g.Log().Warningf(ctx, "壁纸列表获取失败 source=%s: %v", req.Source, err)
return nil, gerror.New("该来源暂时不可用,请换一个来源试试")
}
return &wallpaperv1.OpenListRes{
List: toAPIItems(items),
Total: total,
Page: q.Page,
Size: q.Size,
}, nil
}
// Random 跨来源随机取一张。
func (c *OpenController) Random(ctx context.Context, req *wallpaperv1.OpenRandomReq) (res *wallpaperv1.OpenRandomRes, err error) {
item, err := wallpapersvc.Wallpaper().Random(ctx, req.Sources, req.Orientation)
if err != nil {
g.Log().Warningf(ctx, "随机取壁纸失败 sources=%v: %v", req.Sources, err)
return nil, gerror.New("暂时取不到壁纸,请稍后再试")
}
return &wallpaperv1.OpenRandomRes{Item: toAPIItem(item)}, nil
}
// TrackDownload 下载回调(目前仅 Unsplash 需要)。
// 刻意做成「永远返回成功」:这是统计性质的回调,不能因为它失败而挡住用户下载。
func (c *OpenController) TrackDownload(ctx context.Context, req *wallpaperv1.OpenTrackDownloadReq) (res *wallpaperv1.OpenTrackDownloadRes, err error) {
if err = wallpapersvc.Wallpaper().TrackDownload(ctx, req.Source, req.Id); err != nil {
g.Log().Warningf(ctx, "下载回调失败 source=%s id=%s: %v", req.Source, req.Id, err)
}
return &wallpaperv1.OpenTrackDownloadRes{Message: "ok"}, nil
}