# 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`)。*