「网页版,导航,增加导航地址的时候,怎么没有自定义图标功能啊,修改也没有。」
「我的网址」里新增站点、编辑已有站点两个表单,都只有四个可填项:
网址 · 所属板块 · 显示名 · 简称
网址
所属板块
显示名
简称
没有任何可以指定图标的地方。图标只能靠两种被动方式得到:
NavFetch::fetchIcon
一旦抓错了(抓到的是默认图标、或者是站点小 logo 糊成一团),或者站点根本没有 favicon, 用户没有任何办法换掉它 —— 列表里就一直是一个灰字母块。
nav_sites.icon
icon_custom
Nav::ICON_DIR = uploads/nav-icons
nav_icon.php?f=<文件名>
32位hex.扩展名
iconUrl()
deleteIconFile()
copyIconFile()
icon_custom = 1
也就是说这是纯 UI 缺口,不是要新造一套图标机制。
在 网址 / 所属板块 / 显示名 / 简称 之后,加一项自定义图标:
网址 / 所属板块 / 显示名 / 简称
同样能上传 / 替换 / 清除自定义图标。上传后立刻生效,不需要先删了站点重建。
用户上传的图标 ⇒ icon_custom = 1 ⇒ 之后点「全部更新」不会被抓取覆盖。 这是 SimpleNav 既定的语义,也是用户「设置好以后就固定了」的原话。
清除自定义图标 ⇒ icon_custom = 0 ⇒ 允许下次「全部更新」重新抓。
icon_custom = 0
Nav::ICON_DIR
nav_icon.php
sandbox
deleteIconFile
ff818a3(已 push)。6 个文件。
ff818a3
导航站点的新增/编辑表单里,现在有「自定义图标」:左边 40px 预览,右边「选择图片」+ 文件名,已经设过图的还能勾「清除自定义图标」。
选完文件立刻能看到预览(本地预览,不用等上传)。上限 1MB,按文件内容判类型而不是看扩展名。
三态语义 —— 这里最容易出 bug,所以特意做死:
self::
从 SimpleNav 搬过来时,自由函数改成了 NavFetch 的静态方法,但类内部的调用点没跟着改。
NavFetch
PHP 报的是:
Error: Call to undefined function App\http_get() in app/NavFetch.php:171
整条抓取链路 —— http_get / attr_value / absolutize / third_party_icon_urls / default_icon_candidates / meta_content / parse_icon_links / manifest_icons / is_third_party_icon / looks_generated_tile / grab_icon / ensure_utf8 —— 一处都没跑起来过。
http_get
attr_value
absolutize
third_party_icon_urls
default_icon_candidates
meta_content
parse_icon_links
manifest_icons
is_third_party_icon
looks_generated_tile
grab_icon
ensure_utf8
这既是「全部更新」按钮 500 的根因,也是图标一直抓不到的原因。
修后实测:
NavFetch::meta('https://www.baidu.com') → name = [百度一下,你就知道] → icons = 3 → 图标落盘 3818 字节
ICON_STORE
NavFetch.php 第 667 / 739 行在用,但 define('ICON_STORE', 128) 搬迁时整段漏了。PHP 8 直接 Error: Undefined constant "ICON_STORE",走到 GD 位图分支就 500。
NavFetch.php
define('ICON_STORE', 128)
Error: Undefined constant "ICON_STORE"
为什么一直没暴露:saveUploaded() 一直是死代码(有定义、无调用点)。这次接上调用才炸出来。已补进 app/bootstrap.php(带 if (!defined) 保护)。
saveUploaded()
app/bootstrap.php
if (!defined)
md5(icon_key($url))
Nav::iconFileInUse()
php -l
_b34_nav_icon_e2e.py
_b34_icon_custom_semantics.py
端到端覆盖:真实上传 PNG → 列表出图标 → nav_icon.php 返 200 + PNG 头 → 编辑换图 → 清除 → 只改简称图不丢 → 清理。
语义验收一开始是假绿:按钮没找到的时候它照样判「图标未变 ✅」—— 因为什么都没发生也叫"未变"。改成用「服务端回报了 N 条站点」当证据才站得住。
线上 6 个文件 md5 与仓库逐一比对,全部一致。
本轮造的 7 条测试站点(自定义图u… / 默认图u…,全指向 example.com)和 7 个专属图标文件都删了。站点数 101 → 94,最大 id 回到 125(真实数据最后一条是「学堂在线」)。
自定义图u…
默认图u…
uploads/nav-icons/ 现 66 个文件 / 65 个被引用,唯一孤儿是 9 月 28 日的 ea75fea4…png,不是本轮产物,没动。
uploads/nav-icons/
ea75fea4…png
已实现并部署。站点表单新增自定义图标上传:40px 预览、选图即时预览、可换图可清除,三态语义保证只改名不丢图。
连带修复两个真 bug:NavFetch 里 22 处裸函数调用缺 self::(「全部更新」500 与图标抓不到的根因)、ICON_STORE 常量从未定义。整条抓取链路从全程失败恢复可用。
端到端 21/0,线上 6 文件 md5 与仓库一致,测试数据已清理。commit ff818a3。
No dependencies set.
The note is not visible to the blocked user.
现象(用户反馈)
「我的网址」里新增站点、编辑已有站点两个表单,都只有四个可填项:
网址·所属板块·显示名·简称没有任何可以指定图标的地方。图标只能靠两种被动方式得到:
NavFetch::fetchIcon);一旦抓错了(抓到的是默认图标、或者是站点小 logo 糊成一团),或者站点根本没有 favicon,
用户没有任何办法换掉它 —— 列表里就一直是一个灰字母块。
现状:底层其实都齐了,只差 UI
nav_sites.icon/icon_customNav::ICON_DIR = uploads/nav-iconsnav_icon.php?f=<文件名>32位hex.扩展名)iconUrl()/deleteIconFile()/copyIconFile()icon_custom = 1不覆盖也就是说这是纯 UI 缺口,不是要新造一套图标机制。
期望
新增站点时
在
网址 / 所属板块 / 显示名 / 简称之后,加一项自定义图标:编辑已有站点时
同样能上传 / 替换 / 清除自定义图标。上传后立刻生效,不需要先删了站点重建。
语义(必须与现有
icon_custom一致)用户上传的图标 ⇒
icon_custom = 1⇒ 之后点「全部更新」不会被抓取覆盖。这是 SimpleNav 既定的语义,也是用户「设置好以后就固定了」的原话。
清除自定义图标 ⇒
icon_custom = 0⇒ 允许下次「全部更新」重新抓。验收标准
icon_custom = 1,点「全部更新」之后仍然是用户那张(不被覆盖)。icon_custom = 0,字母块 / 抓取图标恢复可用。Nav::ICON_DIR,且符合nav_icon.php的白名单(32位hex.扩展名);nav_icon.php已有的 CSP 处理(该文件已对 SVG 加sandbox);deleteIconFile已有此能力,注意别删别人复用在用的)。做完了,已上线
ff818a3(已 push)。6 个文件。你要的功能
导航站点的新增/编辑表单里,现在有「自定义图标」:左边 40px 预览,右边「选择图片」+ 文件名,已经设过图的还能勾「清除自定义图标」。
选完文件立刻能看到预览(本地预览,不用等上传)。上限 1MB,按文件内容判类型而不是看扩展名。
三态语义 —— 这里最容易出 bug,所以特意做死:
顺带挖出两个真 bug,这才是「图标一直抓不到」的真相
1. 22 处裸函数调用缺
self::从 SimpleNav 搬过来时,自由函数改成了
NavFetch的静态方法,但类内部的调用点没跟着改。PHP 报的是:
整条抓取链路 ——
http_get/attr_value/absolutize/third_party_icon_urls/default_icon_candidates/meta_content/parse_icon_links/manifest_icons/is_third_party_icon/looks_generated_tile/grab_icon/ensure_utf8—— 一处都没跑起来过。这既是「全部更新」按钮 500 的根因,也是图标一直抓不到的原因。
修后实测:
2.
ICON_STORE常量从来没定义过NavFetch.php第 667 / 739 行在用,但define('ICON_STORE', 128)搬迁时整段漏了。PHP 8 直接Error: Undefined constant "ICON_STORE",走到 GD 位图分支就 500。为什么一直没暴露:
saveUploaded()一直是死代码(有定义、无调用点)。这次接上调用才炸出来。已补进app/bootstrap.php(带if (!defined)保护)。顺手加固的两处
saveUploaded()原来按md5(icon_key($url))命名 —— 单用户系统看不出问题,多用户会互相覆盖同一个 URL 的图。改成随机文件名。Nav::iconFileInUse(),别把别人还在用的删了。验证
php -l5 个文件_b34_nav_icon_e2e.py_b34_icon_custom_semantics.py端到端覆盖:真实上传 PNG → 列表出图标 →
nav_icon.php返 200 + PNG 头 → 编辑换图 → 清除 → 只改简称图不丢 → 清理。语义验收一开始是假绿:按钮没找到的时候它照样判「图标未变 ✅」—— 因为什么都没发生也叫"未变"。改成用「服务端回报了 N 条站点」当证据才站得住。
线上 6 个文件 md5 与仓库逐一比对,全部一致。
测试数据已清理
本轮造的 7 条测试站点(
自定义图u…/默认图u…,全指向 example.com)和 7 个专属图标文件都删了。站点数 101 → 94,最大 id 回到 125(真实数据最后一条是「学堂在线」)。uploads/nav-icons/现 66 个文件 / 65 个被引用,唯一孤儿是 9 月 28 日的ea75fea4…png,不是本轮产物,没动。已实现并部署。站点表单新增自定义图标上传:40px 预览、选图即时预览、可换图可清除,三态语义保证只改名不丢图。
连带修复两个真 bug:
NavFetch里 22 处裸函数调用缺self::(「全部更新」500 与图标抓不到的根因)、ICON_STORE常量从未定义。整条抓取链路从全程失败恢复可用。端到端 21/0,线上 6 文件 md5 与仓库一致,测试数据已清理。commit
ff818a3。