后台上传站点图标:首页品牌图 + favicon + PWA 图标一起换
需求:后台新增设置,允许管理员上传自己的图标;上传后首页品牌图标与浏览器 标签页 favicon(以及「添加到手机主屏」图标)一起换成它。 要点: - 一张上传图服务端居中裁剪成正方形,生成 16/32/48/64/180/192/512 + maskable 192/512 整套尺寸,并手工拼装多帧 favicon.ico。 - 单一来源 site_icon_url() 统一取址;site_icon_head() 被首页/登录页/后台 三处共用;PWA manifest 改由 manifest.php 动态输出、maskable 也跟随 —— 三处防线共同杜绝「首页换了、标签页还是旧的」这类半生效。 - 目录可写则落静态文件(最快);不可写的保守环境整套压进设置、由 site-icon.php 按需输出,功能不因权限限制整块不可用。 - 与「网站列表里每个网站自己的图标」是两个维度:目录与设置键都分开, 清理时互不误伤。 顺手修掉两个真问题: - login.php / admin/_auth.php 各留了一行写死的 favicon,与新的 site_icon_head() 并存 → head 里两条 rel="icon",是「上传了却没换」的 温床。已删掉写死那两行。 - 自定义 favicon.ico 原先只塞 16+32 两帧,而内置是 16/32/48/64 四帧 —— 换图标反而退步。已补齐 icon-64 并统一为 4 帧。 - setting() 的请求内缓存导致「同请求写后再读」拿到旧值(真实坑): settings_cache() 支持强制重载 + settings_reload(),写入后立即失效。 验证:单测 44/44(含只读目录动态回退)、HTTP 56/56、e2e 174/0、 反向验证 5 变体全部被抓住(含「写死残留」与「ico 只塞两帧」两个新哨兵)、 真机几何 360/390/768/1440 无溢出、线上直连桌面+移动端几何全绿、 线上诊断页走通「上传→前台全换→复原」。
This commit is contained in:
+35
-3
@@ -18,6 +18,17 @@ define('ICON_PATH', APP_PATH . '/uploads/icons'); // 抓取的网站图标(可
|
||||
define('ICON_URL', 'uploads/icons'); // 相对站点根
|
||||
define('ICON_STORE', 128); // 图标统一存成 128×128(高清屏下 45~64px 显示仍锐利)
|
||||
|
||||
/**
|
||||
* 「站点整体图标」(浏览器标签页 favicon + 首页品牌图标)—— 用户上传后自动生成的一整套尺寸。
|
||||
*
|
||||
* ⚠️ 与上面的 ICON_PATH 是**两件事**,目录也刻意分开:
|
||||
* ICON_PATH = 导航格子里**某个网站**自己的小图标,一个网站一份(键 = icon_key(网址));
|
||||
* SITE_ICON_PATH = **本站自己**的图标,全局唯一(键 = 随机 16 位 hex)。
|
||||
* 混在一起的话,清理图标目录时两边会互相误伤。
|
||||
*/
|
||||
define('SITE_ICON_PATH', APP_PATH . '/uploads/site');
|
||||
define('SITE_ICON_URL', 'uploads/site');
|
||||
|
||||
/**
|
||||
* 是否「由 PHP 再发一颗」绕开服务器侧页面缓存的标记 cookie。
|
||||
*
|
||||
@@ -60,11 +71,19 @@ function site_name(): string
|
||||
return setting('site_name', APP_NAME);
|
||||
}
|
||||
|
||||
/** 读取设置项 */
|
||||
function setting(string $key, string $default = ''): string
|
||||
/**
|
||||
* 设置表缓存(可失效)。
|
||||
*
|
||||
* ⚠️ 为什么必须能失效:这个缓存只在**首次读取**时查库,之后整进程复用。
|
||||
* 后台「保存设置 → 重定向」是两次请求,所以以前没暴露问题;但只要有**同一次请求里
|
||||
* 先写设置、再读回来**的路径(上传站点图标就是:写完马上要用新键拼 URL),
|
||||
* 就会读到写之前的旧值 —— 表现为「上传成功但图标没变」。
|
||||
* 任何写入设置的地方,写完都要调 settings_reload()。
|
||||
*/
|
||||
function settings_cache(bool $reload = false): array
|
||||
{
|
||||
static $cache = null;
|
||||
if ($cache === null) {
|
||||
if ($cache === null || $reload) {
|
||||
$cache = [];
|
||||
try {
|
||||
foreach (db()->query('SELECT k, v FROM settings') as $row) {
|
||||
@@ -74,5 +93,18 @@ function setting(string $key, string $default = ''): string
|
||||
$cache = [];
|
||||
}
|
||||
}
|
||||
return $cache;
|
||||
}
|
||||
|
||||
/** 写入设置后调用,让本次请求后续的 setting() 读到新值 */
|
||||
function settings_reload(): void
|
||||
{
|
||||
settings_cache(true);
|
||||
}
|
||||
|
||||
/** 读取设置项 */
|
||||
function setting(string $key, string $default = ''): string
|
||||
{
|
||||
$cache = settings_cache();
|
||||
return array_key_exists($key, $cache) && $cache[$key] !== '' ? $cache[$key] : $default;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user