From 47b45cfa2310c2e2f9859fad5db9a1fcdd713c4a Mon Sep 17 00:00:00 2001 From: laoyang Date: Mon, 28 Sep 2026 19:28:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8E=E5=8F=B0=E6=96=B0=E5=A2=9E=E3=80=8C?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E4=B8=8E=E9=93=BE=E6=8E=A5=E7=9A=84=E6=89=93?= =?UTF-8?q?=E5=BC=80=E6=96=B9=E5=BC=8F=E3=80=8D=EF=BC=8C=E5=B9=B6=E8=AE=A9?= =?UTF-8?q?=E7=AB=99=E7=82=B9=E9=93=BE=E6=8E=A5=E8=B7=9F=E9=9A=8F=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原先的设置项只作用于顶部搜索框,文案也写作「搜索结果新窗口打开」;而站点格 与合集里的链接 target 是写死的 _blank —— 于是切到「当前页面打开」时会出现 半生效:搜索留在本页,点网站却仍然弹新标签。 - index.php:把打开方式收敛成一个 open_target(),搜索框与所有站点格共用同一 来源,任何一处都不再写死 target;页面输出 data-open="blank|self" 便于断言与排查。 - admin/index.php:后台由含义含糊的复选框改为明确的二选一(新标签页 / 当前页面), 并补一段说明它管哪两处、不影响后台管理界面。 - admin/actions.php:保存走白名单回退 —— '0' 之外(含字段缺失、被篡改成怪值) 一律回到 '1'(新标签页)。默认值与改造前的旧行为一致,老库不受影响。 - 当前页面模式下不再输出无意义的 rel="noopener"。 验证:php -l 4 个文件通过;e2e 113/113(新增 20 项,并做了反向验证——把链接 改回写死 _blank 后,相关断言精确失败 4 条);线上部署 0 FAIL(双版本语法检查、 62 条静态断言、38 文件哈希逐字节一致、HTTP 冒烟、真机上切换两种模式并已复原)。 --- admin/actions.php | 5 ++++- admin/index.php | 14 +++++++++++++- db.php | 2 ++ index.php | 19 ++++++++++++++++--- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/admin/actions.php b/admin/actions.php index 0994313..5863dfc 100644 --- a/admin/actions.php +++ b/admin/actions.php @@ -213,12 +213,15 @@ try { $src = in_array($srcRaw, ['auto', 'baidu', 'bing', 'so360'], true) ? $srcRaw : 'baidu'; // 合集区显示方式:flat = 全部平铺;其余一律回到 tabs(标签页折叠) $coll = (string)($_POST['collections_layout'] ?? 'tabs') === 'flat' ? 'flat' : 'tabs'; + // 打开方式:'0' = 当前页面;其余(含字段缺失、被篡改成怪值)一律回到 '1'(新标签页) + // ——默认必须等于改造前的旧行为,这样老库里已有的值上线后不会突然变样。 + $open = (string)($_POST['open_blank'] ?? '1') === '0' ? '0' : '1'; $map = [ 'site_name' => trim((string)($_POST['site_name'] ?? '')), 'subtitle' => trim((string)($_POST['subtitle'] ?? '')), 'default_engine' => preg_replace('/[^a-z0-9\-_]/i', '', (string)($_POST['default_engine'] ?? '')), 'primary_color' => preg_match('/^#[0-9a-fA-F]{3,8}$/', (string)($_POST['primary_color'] ?? '')) ? $_POST['primary_color'] : '#2F6BF7', - 'open_blank' => isset($_POST['open_blank']) ? '1' : '0', + 'open_blank' => $open, 'icon_services' => isset($_POST['icon_services']) ? '1' : '0', 'suggest_source' => $src, 'collections_layout' => $coll, diff --git a/admin/index.php b/admin/index.php index 0161127..a3b3f7e 100644 --- a/admin/index.php +++ b/admin/index.php @@ -335,7 +335,19 @@ else: // settings ?> 某个板块是进「合集」还是做成普通网格板块,由「板块 → 展示方式」决定。
- + ++ 同时管两处:顶部搜索(提交后到哪儿看结果)和所有网站格 / 合集链接。 + 「新标签页打开」(默认):点完当前导航页还在,方便连着开好几个; + 「当前页面打开」:在同一个标签里跳走,适合把本站当浏览器起始页、不想堆一堆标签的场景。 + 不影响后台管理界面里的链接。 +
勾上后,当站点自身没有提供高清图标时,会依次尝试 icon.horse、Yandex 图标服务;关掉则只用站点自己声明的图标。
diff --git a/db.php b/db.php index 4e832b1..1a19d7c 100644 --- a/db.php +++ b/db.php @@ -104,6 +104,8 @@ function seed_settings(PDO $pdo): void 'subtitle' => '个人网站导航', 'default_engine' => 'bing', 'primary_color' => '#2F6BF7', + // '1' = 顶部搜索框与所有站点/合集链接都在**新标签页**打开;'0' = 都在**当前页面**打开。 + // 默认 '1' 与引入该设置前的旧行为一致;老库若已有这一行不会被覆盖(INSERT OR IGNORE)。 'open_blank' => '1', ]; $stmt = $pdo->prepare('INSERT OR IGNORE INTO settings (k, v) VALUES (?, ?)'); diff --git a/index.php b/index.php index 6f770ee..1a642db 100644 --- a/index.php +++ b/index.php @@ -21,6 +21,17 @@ $engines = $pdo->query("SELECT * FROM engines WHERE is_active=1 ORDER BY sort // flat = 全部平铺 —— 每个合集各占一块,一眼看全、不用点 $collLayout = setting('collections_layout', 'tabs') === 'flat' ? 'flat' : 'tabs'; +/** 站点链接与顶部搜索框的打开方式(后台「设置 → 打开方式」) + * 返回 `_blank`(新标签页,默认,等同改造前的旧行为)或 `_self`(当前页面)。 + * ⚠️ 搜索框与站点格必须共用这一个来源,不要在任何一处写死 target。 */ +function open_target(): string +{ + return setting('open_blank', '1') === '1' ? '_blank' : '_self'; +} + +$openTarget = open_target(); +$openMode = $openTarget === '_blank' ? 'blank' : 'self'; + // 默认引擎 $defSlug = setting('default_engine', 'bing'); $default = null; @@ -48,9 +59,11 @@ function site_tile(array $s): void { $label = site_label($s); $src = icon_src($s['icon']); + // 打开方式与顶部搜索框同源(见 open_target()):新标签页 or 当前页面 + $tgt = open_target(); ?>