8.7 KiB
8.7 KiB
dnfs 自定义主题说明
树状笔记(dnfs)支持通过特殊节点自定义整个界面的样式:无需改代码、无需重新部署,发布一个节点即可换肤或深度改造界面,随时一键还原。
两类样式节点:
| 类型 | 表单选项 | 能力 | 适用场景 |
|---|---|---|---|
theme |
主题变量 | 仅覆盖 CSS 变量(:root 换肤) |
改配色、圆角、阴影,最稳妥 |
style |
界面样式 | 注入任意 CSS | 改布局、加特效、深度定制 |
1. 快速上手
发布步骤
- 登录后打开「树状笔记」,进入自己的目标节点(样式节点发布在谁拥有的节点下,权限见下)
- 在「节点操作」表单中,将节点类型选为
主题变量或界面样式 - 在「节点内容」中填写变量或 CSS(格式见后文)
- 可选:勾选「离开本节点后仍保持生效」(
persist) - 提交——内容经 AI 审核通过后即时生效
发布权限
- 节点拥有者或管理员可发布样式节点(后端强制,前端面板仅做展示切换)
- 在他人节点下提交样式节点会被拒绝(HTTP 403)
- 根层(pid=0)无拥有者,仅管理员可在根层发布
- 所有样式节点内容都会经过 AI 内容审核
生命周期
| 模式 | 生效范围 | 移除时机 |
|---|---|---|
| 默认(节点作用域) | 进入该节点所在层时生效 | 切换/返回节点时自动还原 |
persist(勾选保持) |
一旦访问即全局保持,跨节点生效 | 用户面板点「还原界面样式」,或停用对应节点 |
- 每个样式节点卡片上有「停用样式/启用样式」与「审计源码」按钮,可逐个控制
- 用户面板的「还原界面样式」一键清除全部注入样式(含 persist),本会话内 persist 样式不再自动注入(刷新页面恢复)
2. theme 节点(主题变量)
格式
「节点内容」中每行一个变量,分号可选:
--accent: #e8853a
--bg: #0a0f0a;
规则(后端强制)
- 变量名:必须以
--开头,仅含字母/数字/-/_,长度 ≤ 64 - 变量值:非空,长度 ≤ 256,不得包含
{}<>(防止逃逸:root上下文注入任意规则) - 条数:1 ~ 64 条
- 未列出的变量保持站点默认值,可只覆盖关心的几项
可覆盖变量清单
默认值(亮色 / 系统暗色模式):
| 变量 | 亮色默认 | 暗色默认 | 作用 |
|---|---|---|---|
--bg |
#fdf6ee |
#1e1712 |
页面背景 |
--fg |
#4a3728 |
#f0e4d8 |
主文字 |
--fg-secondary |
#8c7260 |
#a08c78 |
次要文字 |
--card |
#ffffff |
#2a2119 |
卡片背景 |
--card-hover |
#fff7ef |
#342a20 |
卡片悬停背景 |
--border |
#f0e0cc |
#3e3228 |
边框 |
--border-light |
#f7ecdd |
#342a20 |
浅边框 |
--muted |
#b89b7a |
#8c7a66 |
弱化元素 |
--accent |
#e8853a |
#e8934a |
品牌强调色 |
--accent-dark |
#cf6b1f |
#f0a060 |
强调色深阶 |
--accent-soft |
rgba(232,133,58,.10) |
rgba(232,147,74,.12) |
强调色底衬 |
--accent-glow |
rgba(232,133,58,.25) |
rgba(232,147,74,.20) |
强调色辉光 |
--error / --error-bg |
#d94f3d / #fef0ee |
#e8685a / #3a2220 |
错误 |
--success |
#5a9e6f |
#6fb87f |
成功 |
--warning |
#d4922a |
#e0a84a |
警告 |
--shadow-sm / --shadow-md |
浅棕阴影 | 深黑阴影 | 投影 |
--radius-sm / --radius-md / --radius-lg |
10px / 14px / 20px |
同左 | 圆角 |
站点会随系统
prefers-color-scheme切换亮/暗两套默认值;theme 节点注入的变量对两种模式同时生效(注入的:root规则优先级高于媒体查询默认值)。
3. style 节点(任意 CSS)
格式
「节点内容」直接填写 CSS 文本,上限 256KB。
安全边界
- CSS 无法执行脚本,风险面仅为界面外观;滥用可随时一键还原
- js 特效节点仍运行在 iframe 沙箱中,与样式节点互不影响
常用选择器参考
| 选择器 | 对应元素 |
|---|---|
.box |
页面主容器(宽 90%,max-width 720px) |
.card |
节点卡片(含 :hover) |
.card h3 |
卡片标题(点击进入子节点) |
.card-owner / .owner-avatar / .owner-name |
发帖人头像与昵称 |
.card-stats / .stat-item |
观看/点赞/分享统计 |
.card-actions / .act-btn(.act-edit .act-move .act-del) |
卡片操作按钮 |
.searchbox / .searchbox-input / .searchbox-btn |
顶部搜索框 |
.userpanel / .minimap / .movebar |
用户面板 / 右侧导航 / 底部移动条 |
.tag |
导航标签 |
.node-form |
底部节点编辑卡 |
.sp-code / .sp-actions / .sp-note |
特殊节点卡片内元素 |
.footer |
页脚 |
body::before / body::after |
点阵底纹 / 顶部暖光(可被覆盖改背景效果) |
编写注意事项
- 层叠上下文:全屏覆盖层建议
z-index ≤ 9998(9999被 js 特效 iframe 占用) - 不拦截交互:覆盖层务必加
pointer-events: none - 避免动画
transform作用于卡片祖先:会使position: fixed后代(如 minimap、特效)定位异常 - 修改
--accent-glow等含rgba()的值在 theme 节点中是允许的(不含禁字符)
4. 示例
4.1 极客终端风
先发 theme 节点(磷光绿配色):
--bg: #0a0f0a
--fg: #33ff66
--fg-secondary: #1f9944
--card: #0d140d
--card-hover: #111a11
--border: #1a331f
--border-light: #142614
--muted: #2a6b3a
--accent: #33ff66
--accent-dark: #00cc44
--accent-soft: rgba(51, 255, 102, 0.08)
--accent-glow: rgba(51, 255, 102, 0.25)
--error: #ff4444
--error-bg: #2a0d0d
--success: #33ff66
--warning: #ffaa00
再发 style 节点(CRT 质感):
/* 全局等宽字体 */
body, .card, input, textarea, button, select {
font-family: "JetBrains Mono", "Fira Code", Consolas, Menlo, monospace !important;
}
/* 磷光辉光 */
.card h3, .tag, .searchbox-input {
text-shadow: 0 0 6px var(--accent-glow), 0 0 2px currentColor;
}
/* 卡片终端窗口化:左侧亮条 + 内发光 */
.card {
border-left: 3px solid var(--accent);
box-shadow: 0 0 18px rgba(51, 255, 102, 0.08),
inset 0 0 40px rgba(51, 255, 102, 0.03);
}
/* 标题加 >_ 提示符 */
.card h3::before {
content: ">_ ";
color: var(--accent);
}
/* CRT 扫描线(不拦截点击,z-index 低于特效层 9999) */
body::after {
content: "";
position: fixed;
inset: 0;
z-index: 9998;
pointer-events: none;
background: repeating-linear-gradient(
0deg,
rgba(0, 0, 0, 0.18) 0px, rgba(0, 0, 0, 0.18) 1px,
transparent 1px, transparent 3px
);
}
/* 链接呼吸辉光 */
a { transition: text-shadow 0.2s; }
a:hover { text-shadow: 0 0 8px var(--accent); }
/* 滚动条终端化 */
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--accent); }
4.2 暗夜蓝(仅 theme,最小改动)
--bg: #0d1117
--fg: #c9d1d9
--fg-secondary: #8b949e
--card: #161b22
--card-hover: #1c2129
--border: #30363d
--border-light: #21262d
--muted: #6e7681
--accent: #58a6ff
--accent-dark: #1f6feb
--accent-soft: rgba(88, 166, 255, 0.10)
--accent-glow: rgba(88, 166, 255, 0.25)
4.3 阅读优化(仅 style,隐藏干扰元素)
/* 隐藏统计与页脚,加宽版心,放大正文字号 */
.card-stats, .footer { display: none; }
.box { max-width: 860px; }
.card p { font-size: 1.05rem; line-height: 1.9; }
/* 卡片去边框,纯排版 */
.card { border: none; box-shadow: none; border-bottom: 1px solid var(--border-light); border-radius: 0; }
5. 常见问题
发布了但没生效? 样式节点经 AI 审核,审核未通过会提示「内容审核不通过」;通过后刷新页面生效。非节点拥有者在他人节点下发布会被 403 拒绝。
界面被改乱了怎么办? 左上角用户面板 →「还原界面样式」,立即恢复默认。或在对应卡片上点「停用样式」。
想让全站访客都看到主题? 发布时勾选「离开本节点后仍保持生效」(persist),并建议放在高层级节点中提高被访问到的概率。
样式节点之间冲突? 多个样式节点同时生效时按 DOM 注入顺序叠加,同特异性后者优先;可用卡片上的启停按钮逐个排查。
存量 image 节点显示异常?
image 类型已移除,旧图片节点按原始文本显示,拥有者可编辑为 file 类型或删除。
相关源码:后端校验 dnfs2/src/dnfs2.cpp(validate_sp),前端渲染 fsys/public/js/dnfs.js(renderSpCss)。