diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index 952664e..d5c7e2e 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -63,6 +63,20 @@ func setIfEmpty(adapter *gcfg.AdapterFile, key, envName string) { } } +// needFill 判断某个配置项是否「等于没配」:不存在、为空串、或仍是未被替换的 +// ${PLACEHOLDER}。gf v2.10.2 起不再自动替换占位符,容器里跑的 config.yaml +// 也可能是旧版(没有对应的配置段),这两种情况都必须回填兜底值。 +// +// 注意 adapter.Get 返回的是 any 而不是 *gvar.Var,取值统一走 gconv。 +func needFill(ctx context.Context, adapter *gcfg.AdapterFile, key string) bool { + v, err := adapter.Get(ctx, key) + if err != nil || v == nil { + return true + } + s := gconv.String(v) + return s == "" || gstr.Contains(s, "${") +} + // injectEnv 手动把关键环境变量写入配置系统。 // 注意:gf v2.10.2 起配置不再自动替换 ${ENV} 占位符,需在此显式注入, // 否则 config.dev.yaml 中的 ${DB_DSN}/${JWT_SECRET} 会原样传给数据库与 JWT。 @@ -86,17 +100,20 @@ func injectEnv(ctx context.Context) { _ = adapter.Set("jwt.secret", devDefaultJWTSecret) } } - // 壁纸库路径同理:占位符没被注入时要回填,否则会真的创建一个名为 - // "${WALLPAPER_ROOT}" 的目录,图片全落到那里且难以察觉。 + // 壁纸库路径同理,但要处理**三种**缺失形态:配置项不存在(容器里跑的 + // config.yaml 可能是旧版、压根没有 wallpaper 段)、值为空、以及占位符 + // 没被替换。任何一种漏掉都会掉进 NewStorage 的相对路径兜底 + // (容器内 ./data/wallpaper),表现为「上传成功但 nginx 找不到文件」, + // 而且重启容器就全丢 —— 这种故障极难排查,所以这里必须兜死。 // 生产兜底到 /data/www/wallpaper(由 nginx 直出),开发兜底到仓库内 data/。 - if v, _ := adapter.Get(ctx, "wallpaper.root"); v != nil && gstr.Contains(gconv.String(v), "${") { + if needFill(ctx, adapter, "wallpaper.root") { if isProd { _ = adapter.Set("wallpaper.root", "/data/www/wallpaper") } else { _ = adapter.Set("wallpaper.root", "./data/wallpaper") } } - if v, _ := adapter.Get(ctx, "wallpaper.baseUrl"); v != nil && gstr.Contains(gconv.String(v), "${") { + if needFill(ctx, adapter, "wallpaper.baseUrl") { if isProd { _ = adapter.Set("wallpaper.baseUrl", "https://xpcool.com/wallpaper") } else {