Files
blackbird/docs/dnfs_custom_themes.md
T

246 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# dnfs 自定义主题说明
树状笔记(dnfs)支持通过**特殊节点**自定义整个界面的样式:无需改代码、无需重新部署,发布一个节点即可换肤或深度改造界面,随时一键还原。
两类样式节点:
| 类型 | 表单选项 | 能力 | 适用场景 |
|---|---|---|---|
| `theme` | 主题变量 | 仅覆盖 CSS 变量(`:root` 换肤) | 改配色、圆角、阴影,最稳妥 |
| `style` | 界面样式 | 注入任意 CSS | 改布局、加特效、深度定制 |
---
## 1. 快速上手
### 发布步骤
1. 登录后打开「树状笔记」,进入自己的目标节点(样式节点发布在**谁拥有**的节点下,权限见下)
2. 在「节点操作」表单中,将**节点类型**选为 `主题变量` 或 `界面样式`
3. 在「节点内容」中填写变量或 CSS(格式见后文)
4. 可选:勾选「离开本节点后仍保持生效」(`persist`)
5. 提交——内容经 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 质感):
```css
/* 全局等宽字体 */
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,隐藏干扰元素)
```css
/* 隐藏统计与页脚,加宽版心,放大正文字号 */
.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`)。*