nazuna · NAZUNA 彻夜之歌
为 DeepSeek Harness Web GUI 打造的《彻夜之歌》主题皮肤:深空蓝紫夜色基调、月光紫文字、玻璃质感面板,
七草荠立绘透过毛玻璃透出,随会话阶段柔和转场。
特性
- 全局换肤:覆盖官方
--dsw-* 语义 token(夜城玻璃面板、月光文字、紫罗兰品牌色),亮/暗双主题随系统切换
- 毛玻璃 UI:侧边栏与会话区半透明 + backdrop blur,立绘透过面板透出
- 双立绘布局:左侧 6_2 大立绘 + 右下 5_2 立绘(z-index 0 垫底、玻璃下透出,非浮层贴纸)
- 场景动画:会话 idle → active 时立绘柔和缩放 + 微模糊淡退
- 状态角色卡片:右上角角色卡(头像 + 双语状态 + 光点),跟随会话 phase:
- 待机(紫)· 同步(青脉冲)· 运行(紫脉冲)· 完成(绿)
- 全局视觉改造:统一 14px 圆角、紫罗兰链接/焦点/主按钮、主题化滚动条
- 皮肤管理器集成:设置 → 皮肤管理 提供开关(背景 / 立绘 / 状态卡)
- 完整卸载还原:切换皮肤或卸载时恢复全部 DOM/样式/标题
工程结构
nazuna/
├── package.json # @dsh-external/dsh-client-ui-skin-nazuna
├── cordis.patch.yml # 注入 web 插件表(id: ui-skin-nazuna)
├── skin.json # 皮肤清单(皮肤管理器识别)
├── tsdown.config.ts # 构建入口
├── build/
│ ├── tsdown.client.ts # 自包含 tsdown 构建预设(ModuleLoader 闭包产物 + CSS 内联)
│ └── web-platform.ts # 浏览器平台模块表(externals)
├── src/
│ ├── index.ts # 宿主侧入口(空)
│ └── client/
│ ├── index.ts # 主入口:挂背景/立绘/状态卡,注册清理
│ ├── nazuna.module.css # 皮肤样式(作用域 body[data-dsh-nazuna])
│ └── modules/
│ ├── art.ts # 内嵌立绘 data URI(由 assets/*.webp 生成)
│ ├── scene.ts # 会话阶段 → body[data-nazuna-scene](窄观察)
│ ├── status-character.ts # 右上状态角色卡片
│ └── customization.ts # 皮肤管理器定制协议
├── assets/ # 立绘素材(PNG 原图 + WebP)
├── lib/ # 构建产物(junction 同步到 profile)
└── preview/ # 皮肤管理预览图
安装
方式 A:GitHub 克隆(推荐分发方式)
git clone https://github.com/yangcanbin31-coder/dsh-skin-nazuna.git
cd dsh-skin-nazuna
pnpm install && pnpm build # 生成 lib/client.js
dsh plugin --profile web add <path-to-dsh-skin-nazuna>
方式 B:直接目录(本机开发)
DSH 环境执行(<path> 为工程绝对路径):
dsh plugin --profile web add <path-to-nazuna>
dsh plugin --profile desktop add <path-to-nazuna> # 桌面端如需要
重启 DSH → 设置 → 皮肤管理 → 选择「NAZUNA」。(皮肤互斥,自动停用其他皮肤。)
本机采用 junction 直连开发:profiles/<web|desktop>/node_modules/@dsh-external/dsh-client-ui-skin-nazuna
→ 开发目录,改源码 → pnpm build → 重启 DSH 即完整闭环,无需重新安装。
开发
pnpm install
pnpm build # tsdown → lib/index.js + lib/client.js
换素材 / 布局微调
换立绘图
- 把透明立绘 PNG 放入
assets/,转 WebP:
python gen_art.py(脚本读取 assets/*.webp 重新生成 art.ts)
- 按
art.ts 顶部注释格式确认导出名,改 src/client/index.ts 里的引用
pnpm build → 重启
立绘位置 / 大小
全部集中在 src/client/index.ts 的 apply() 内联样式:
| 元素 | 变量位置 | 说明 |
|---|
| 左侧 6_2 | bigFigure style | left(避开侧栏)、height、opacity |
| 右下 5_2 | rightFigure style | right/bottom、height、opacity |
状态卡片位置
src/client/nazuna.module.css → .statusCard(top/right/z-index)。
改皮肤 id / 名字
必须同步四处:
| 文件 | 字段 |
|---|
package.json | name |
cordis.patch.yml | id: ui-skin-<新id> |
skin.json | id、package、wiring.id、bodyAttr |
src/client/index.ts | body.dataset.dsh<新id> + CSS 的 body[data-dsh-<新id>] |
已知注意事项
- Observe 安全:scene / status 模块只窄观察会话根节点的
data-phase,回调带值守卫与防抖。
不要改回"observe 整个 body subtree 且回调写 textContent"——那会形成自反馈死循环
(曾导致渲染器 CPU 100%、renderer boot failed)。
- CSS Modules 类名:TS 里给元素挂类名必须用
cls('...')(从 nazuna.module.css 导入映射),
不能硬编码原始类名(会被哈希成 SmQiiW_* 导致样式失效)。
- 分层纪律:场景层(backdrop / 立绘 / floorVeil / edgeGlow)一律
z-index: 0,UI 容器 #root
是 z-index: 1,状态卡 z-index: 30。任何场景层都不许高于 #root——floorVeil 曾因写成
z-index: 2 变成一块压在输入框上的深色矩形。若需覆盖 JS 内联样式(如立绘 opacity),
主题/场景规则必须用 !important,且不要给场景切换加 blur 滤镜(会跨主题泄漏模糊)。
许可
MIT(工程原创,仅借鉴社区皮肤的分层思路;不包含第三方角色素材)。
角色形象权利归原作者/版权方;发布含角色形象的作品时请自行确认授权。