Palette Nav 上网导航
独立运行的 Halo 2.x 上网导航插件。
- 前台独立页面:
/nav - 控制台管理页:
/console/palette-nav - 不依赖 Halo 官方「链接管理」插件
功能
- 分类、链接、搜索引擎、快捷导航的完整管理
- 6 种配色与夜间模式
- 时钟、日期、问候语、随机一言(本地文本)
- 多搜索引擎跳转、百度搜索建议(可关闭)
- 分类筛选、背景图片/视频切换、快捷导航菜单
- 响应式布局(8 / 6 / 4 / 3 列)
- 控制台仪表盘:链接数量、今日/累计浏览量、近 7 天 PV/UV 走势(服务端采集,可在设置中关闭)
- 内置默认导航数据:在没有任何导航数据的新实例上首次启用时自动导入分组、链接、搜索引擎与快捷导航;之后用户的修改和删除不会被恢复。默认数据不含访问统计
截图
六种主题色
| 紫色 | 蓝色 | 绿色 |
|---|---|---|
![]() |
![]() |
![]() |
| 粉色 | 橙色 | 青色 |
|---|---|---|
![]() |
![]() |
![]() |
背景图片与搜索引擎切换
| 背景图片(紫色) | 背景图片(蓝色) |
|---|---|
![]() |
![]() |
夜间模式
| 紫色 | 蓝色 |
|---|---|
![]() |
![]() |
环境要求
- Halo >= 2.27.0
- JDK 21
- Node.js >= 22.12、pnpm 10
开发与构建
# 前端依赖
pnpm -C ui install
# 构建插件 JAR
./gradlew build
产物:build/libs/palette-nav-<version>.jar,可直接在 Halo 控制台「插件 → 安装」上传。
本地 8095 调试(无 Docker)
-
复制
halo.jar到.tools/halo/(本机可从相邻项目复制 Halo 2.27.2)。 -
复制
scripts/application.example.yaml到.tools/halo/application.yaml,把其中D:/path/to/...改成当前项目绝对路径。配置已固定端口8095、H2 文件库与开发模式。 -
准备运行时资源:
./gradlew classes -
启动 Halo:
./scripts/dev.sh脚本会校验 JDK 21(可用
HALO_JAVA_HOME=/path/to/jdk-21指定),并在 Halo 就绪后通过本地 basic auth 自动启用palette-nav插件。若当前JAVA_HOME不是 21,请设置HALO_JAVA_HOME。Windows 也可用scripts\dev.bat(该脚本不会自动启用插件)。 -
首次访问
http://localhost:8095/system/setup完成初始化(本地示例:admin/admin123)。 -
使用
scripts/dev.sh时插件会自动启用;用dev.bat或其他方式启动时,登录控制台在「插件」中启用Palette Nav 上网导航,然后访问/nav。 -
进入
/console/palette-nav,添加分类、链接、搜索引擎与快捷导航。
halo { port = 8095 } 同时写入 build.gradle,有 Docker 环境时可直接使用 ./gradlew haloServer。
插件设置
设置已合并到控制台 /console/palette-nav 的「设置」页签。插件不声明 Halo Setting,因此插件详情页没有设置入口,插件列表的「重置配置」也不会出现。没有保存过设置的新实例会使用内置默认值(站点名称、描述、关键词、品牌文字、紫色主题等)。共五组设置:
- 基本设置:标题、描述、关键词、LOGO(支持上传 / 附件库 / 链接)、品牌文字、版权、ICP、公安备案
- 访问统计:访问统计开关(
enableVisitStats)与可信反向代理地址(trustedProxyIps)。关闭后不再记录新的访问,历史数据仍会展示;只有来自本机回环地址或trustedProxyIps的X-Forwarded-For/X-Real-IP才会被采信,留空表示只信任本机代理。多级代理(CDN → nginx → Halo)需要逐一填写每一跳代理地址才能取到真实访客 IP - 外观设置:默认主题色、默认明暗模式、时钟、一言、背景媒体(图片或视频,支持上传 / 附件库 / 链接)
- 附件存储:新增/编辑链接点击「获取」时,网站图标会先转存到 Halo 附件再引用;控制台通过「上传」添加的图标、LOGO 与背景也会存入这里指定的存储策略与附件分组。留空时使用上传界面中优先级最高的存储策略、不分组
- 搜索设置:百度搜索建议开关(默认开启)
图标字段支持控制台内直接上传图片/SVG 文件、从 Halo 附件库选择、填写图片地址或粘贴 SVG 代码,底层兼容三种存储形式:
- SVG 雪碧图引用(
<svg><use xlink:href="#pn-x"></use></svg>,可用图标见palette-icons.js;分类默认使用彩色pn-cat-*logo,链接使用pn-*线条图标;旧版 6 个默认分类 id 会映射到对应分类 logo,其余lyicon-*/icon-*引用显示为通用链接图标) - 完整 SVG 代码(渲染时转为 base64 data URL 图片,脚本不会执行)
http(s)://或站内/...图片地址(上传的文件会写入附件库)
新增/编辑链接时点击网址右侧的「获取」,会自动读取网页名称与图标;图标会下载并转存为 Halo 附件,表单保存的是附件地址,不再直接热链接目标站点。转存失败(例如目标站点拒绝访问或图标格式不受存储策略支持)时回退为原图标地址。目标网页无法读取时接口仍返回 200 并带 fetched=false,名称与图标按域名回退;该操作会写入附件,因此接口使用 POST。
安装、升级与卸载
- 安装:控制台「插件 → 安装」,上传
palette-nav-<version>.jar后启用。首次启用且四类导航数据都为空时,会导入一次内置默认数据;之后即使清空数据也不会再次导入(除非手动删除palette-nav-defaults-stateConfigMap)。 - 升级:在插件列表使用「升级」上传新版本 JAR。已创建的导航数据、访问统计与
palette-nav-config设置都会保留。Windows 下如果在线升级提示文件被占用(运行中的 JVM 锁住了旧 JAR),请先停用插件或停止 Halo,替换工作目录plugins/palette-nav-*.jar后重新启动。 - 卸载:在插件列表卸载。Halo 不会删除插件创建的自定义资源;设置保存在独立的
palette-nav-configConfigMap 中,插件未把它声明为spec.configMapName,因此即使勾选「卸载并删除配置」也不会删除这些业务设置。重新安装同版本插件后分类、链接、搜索引擎、快捷导航、访问统计和设置都会恢复;如需彻底清理,请在卸载前删除业务数据,或直接清理palette-nav.halo.run命名空间下的资源与palette-nav-config、palette-nav-defaults-state。
权限
插件只申请完成自身功能所需的权限,不读写其他插件或系统配置:
plugin:palette-nav:manage:访问/console/palette-nav,管理四类导航数据、拖拽排序、分类级联删除、读取仪表盘,以及读写本插件设置(configmaps的get/update通过resourceNames限定为palette-nav-config,没有创建任意 ConfigMap 的权限)。- 附件相关:上传图标/背景文件并读取 Halo 附件库(
attachments读取与上传、存储策略/分组读取)。 /nav是公开页面,不需要登录或额外权限。
隐私与第三方服务
- 访问统计(默认开启,可在设置中关闭):
/nav每次成功渲染会增加一次浏览量(PV)。独立访客(UV)按「当天随机盐 + 客户端 IP + User-Agent」的截断 SHA-256 哈希按天去重,不保存原始 IP 或 User-Agent;盐每天更换,不同日期无法关联同一访客。每位访客的NavVisitVisitor记录保留当天与前一天(用于覆盖跨零点请求和轻微时钟漂移),更早的记录会在下次清理时删除;每日聚合的 PV/UV 计数(NavVisitStat)会长期保留以展示仪表盘。关闭统计后不再记录新访问,历史数据仍会展示。 - 反向代理与真实 IP:只有来自本机回环地址或设置中
trustedProxyIps的X-Forwarded-For/X-Real-IP会被采信,其余请求一律使用 TCP 对端地址,避免访客伪造 IP 刷高 UV。多级代理(CDN → nginx → Halo)需要列出每一跳代理地址。 - 百度搜索建议(默认开启,可在设置中关闭):开启时,搜索框在输入过程中会把当前关键词发送到
suggestion.baidu.com以获取联想词;关闭后不再发起该请求。 - 目标网页抓取:「获取」按钮只在管理员点击时访问目标网页,用于读取标题与图标;访客访问
/nav不会触发对目标站点的抓取。转存的图标会写入 Halo 附件。 - 除上述情况外,插件不向第三方发送遥测数据。导航卡片与快捷导航指向的站点由管理员配置,访客点击后会跳转到相应站点,其隐私政策由该站点负责。
安全说明
- 链接与图片地址只接受
http/https或站内/路径;javascript:、data:、协议相对 URL 会被拒绝,图片/背景不接受页内锚点#。 - 图标在服务端经过白名单过滤后再输出,控制台预览使用同一套规则。
- 从目标网页抓取的图标只接受 PNG/JPEG/GIF/WebP/ICO/BMP/AVIF 的魔数校验结果;SVG 不会转存为附件(Halo 内联展示附件时可能执行其中的脚本),而是保留原地址并通过
<img>引用。 /nav为公开页面;排序与分类级联删除接口仅对拥有plugin:palette-nav:manage权限的角色开放。- 「获取」使用插件内置的出站客户端:先解析并校验目标地址,再连接已校验的 IP(防 DNS rebinding),逐跳校验重定向,限制响应大小与超时,并按文件魔数识别图片。为了固定连接地址,它不经过 Halo/系统的 HTTP 代理与自定义 CA 配置;若部署环境必须经代理访问外网,需要额外改造。
- 出站目标默认拒绝 loopback、link-local、multicast、RFC1918 私有网段、CGNAT 与文档/保留网段,不提供内网白名单。内网站点仍可手动填写名称与图标,只是「获取」不会抓取内网页面。
- 版权信息在服务端经过 jsoup 白名单净化后再输出到
/nav:仅保留链接、加粗、斜体等文本级 HTML,script、事件属性、style、iframe等会被移除;「自定义页脚代码」字段已移除。拥有plugin:palette-nav:manage的角色无法通过设置页向公开页面注入脚本。
目录
src/main/java/cn/litx/palettenav/ 后端
src/main/resources/templates/ 前台 Thymeleaf 模板
src/main/resources/static/nav/ 前台静态资源
ui/ 控制台 ESM 前端
tools/ 开发期数据转换与测试脚本
src/main/resources/data/ 内置默认导航数据(nav-defaults.json)
docs/screenshots/ README 截图
支持与反馈
- 问题反馈:https://github.com/litxiaoxi/halo-plugin-palette-nav/issues
- 源码与更新日志:https://github.com/litxiaoxi/halo-plugin-palette-nav
License
MIT。
插件内的图标、默认导航数据、背景图与 LOGO 均为本项目自制或已取得授权;不再随包分发第三方图标集。默认导航数据中的品牌名称与网址仅用于指向对应服务,相关商标归各权利人所有。详见 THIRD-PARTY-NOTICES.md。
















