From 8a850ca0e5ced3a8349ea4e1af131822d895acdf Mon Sep 17 00:00:00 2001 From: laoyang Date: Tue, 3 Nov 2026 07:21:04 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=E5=85=A8=E7=AB=99?= =?UTF-8?q?=E5=9B=BE=E7=89=87=20503=20=E2=80=94=E2=80=94=20oss.enabled=20?= =?UTF-8?q?=E6=B4=BE=E7=94=9F=E5=86=99=E5=85=A5=E8=A2=AB=20has()=20?= =?UTF-8?q?=E5=AE=88=E5=8D=AB=E6=8B=A6=E6=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题:attachment.storage 存成 oss,但 oss.enabled 一直停在 0。 media.php 判 fb_oss_enabled() 为 false,直接 503「对象存储未配置」, 所有 OSS 附件(历史 + 新增)全部打不开。 根因有两层: 1. oss.enabled 是派生字段,表单里没有对应 input,上一个提交加的 $save() 统一守卫用 $has() 判断「没提交」就 return,把它挡掉了; 2. 更根本的是两份状态描述同一件事 —— storage 和 enabled 迟早漂移。 修法: - 派生写入改用 $saveForce(),并整段包进 if ($has(attachment.storage)), 避免反向问题(没提交存储方式时被默认值改成 off); - fb_oss_enabled() 改为只看 attachment.storage 作单一事实来源, oss.enabled 仅在 storage 完全没配过的老库上作为回落。 --- admin.php | 22 +++++++++++++++++----- lib/oss.php | 19 ++++++++++++++++++- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/admin.php b/admin.php index 0477bdd..f21134e 100644 --- a/admin.php +++ b/admin.php @@ -453,11 +453,23 @@ function fb_admin_save_settings() { $save($k, (int)round($mb * 1048576)); } - $storage = (string)$post('attachment.storage', 'off'); - if (!in_array($storage, ['off', 'local', 'oss'], true)) { $storage = 'off'; } - $save('attachment.storage', $storage); - // OSS 模式下 oss.enabled 必须跟着开;其它模式关掉,避免误判 - $save('oss.enabled', $storage === 'oss' ? 1 : 0); + // 附件存储方式:只有表单真的带了这个字段才处理。 + // 没有它(比如只提交了 site_name 的局部表单)就整段跳过 —— + // 否则下面 $post(..., 'off') 的默认值会把存储方式误改成「关闭」。 + if ($has('attachment.storage')) { + $storage = (string)$post('attachment.storage', 'off'); + if (!in_array($storage, ['off', 'local', 'oss'], true)) { $storage = 'off'; } + $save('attachment.storage', $storage); + + // OSS 模式下 oss.enabled 必须跟着开;其它模式关掉,避免误判。 + // 🔴 这里必须用 $saveForce,不能用 $save: + // oss.enabled 是【派生字段】—— 表单里根本没有名为 oss_enabled 的 input, + // $save 的 $has() 守卫会判定"没提交"而直接 return,于是 storage 存成了 oss、 + // enabled 却永远停在旧值 0。media.php 因此报「对象存储未配置」,全站图片 503。 + // (2026-11-03 图片全挂的直接原因:守卫修好了跨 tab 清空,却把派生写入也挡掉了。) + // 又因为它处在 $has('attachment.storage') 分支内,不会出现「没提交却强制写 0」的反向问题。 + $saveForce('oss.enabled', $storage === 'oss' ? 1 : 0); + } $texts = ['oss.endpoint', 'oss.bucket', 'oss.instance_role', 'oss.domain', 'oss.prefix', 'moderation.close_mail_subject']; foreach ($texts as $k) { diff --git a/lib/oss.php b/lib/oss.php index bcfe8ed..67f3136 100644 --- a/lib/oss.php +++ b/lib/oss.php @@ -34,7 +34,24 @@ function fb_oss_cfg($k = null, $d = null) { */ function fb_oss_enabled() { $c = fb_oss_cfg(); - if (empty($c['enabled'])) { return false; } + + /* 🔴 启用判据只看 attachment.storage(单一事实来源)。 + * + * 原先这里只看 oss.enabled —— 而 oss.enabled 是个【派生字段】: + * 后台表单里没有对应的 input,只能由保存逻辑“顺手”写一次。 + * 两份状态描述同一件事,就必然有漂移的一天,实际也真的漂了: + * 2026-11-03 attachment.storage=oss 而 oss.enabled=0, + * 结果上传/读取全被判成「对象存储未配置」,全站图片 503。 + * + * 现在只有 storage 完全没配过(老库、安装向导中途)才回落到 oss.enabled。 + */ + $storage = strtolower(trim((string)fb_cfg('attachment.storage', ''))); + if ($storage !== '') { + if ($storage !== 'oss') { return false; } // local / off → OSS 一律不启用 + } elseif (empty($c['enabled'])) { + return false; + } + foreach (['bucket', 'endpoint'] as $k) { if (trim((string)(isset($c[$k]) ? $c[$k] : '')) === '') { return false; } }