集中管理深浅色皮肤预设,一键切换背景与立绘
30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/9 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add Firefly-Star/dsh-mini-skin该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · ui
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 26 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件发起外部网络请求
查看扫描证据(共 16 处,展示前 15 条)
- 读取本地文件lib/index.js:67
const names = (await readdir(dir)).filter((name) => name.toLowerCase().endsWith(".json")); - 读取本地文件lib/index.js:70
const pack = JSON.parse(await readFile(join(dir, name), "utf8")); - 写入本地文件lib/index.js:76
await writeFile(join(dir, OFFICIAL_FILE), JSON.stringify(OFFICIAL_PACK, null, 1), "utf8"); - 读取本地文件lib/index.js:117
const info = await stat(join(dir, file)); - 读取本地文件lib/index.js:118
const text = await readFile(join(dir, file), "utf8"); - 读取本地文件lib/index.js:148
send(res, 200, await readFile(join(dir, file), "utf8")); - 写入本地文件lib/index.js:154
await mkdir(dir, { recursive: true }); - 读取本地文件lib/index.js:162
const names = (await readdir(dir)).filter((name) => name.toLowerCase().endsWith(".json")).sort(); - 写入本地文件lib/index.js:175
await mkdir(dir, { recursive: true }); - 写入本地文件lib/index.js:181
await writeFile(join(dir, file), JSON.stringify(pack, null, 1), "utf8"); - 删除本地文件lib/index.js:191
await rm(join(dir, file), { force: true }); - 发起网络请求lib/client.js:1050
const dataUrlToBlob = async (dataUrl) => (await fetch(dataUrl)).blob(); - 发起网络请求lib/client.js:1200
const response = await fetch(LIBRARY_ROUTE, { credentials: "same-origin" }); - 发起网络请求lib/client.js:1207
const response = await fetch(`${LIBRARY_ROUTE}?file=${encodeURIComponent(file)}`, { credentials: "same-origin" }); - 发起网络请求lib/client.js:1213
const response = await fetch(LIBRARY_ROUTE, {
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 管理深浅色皮肤预设
- 一键切换背景与立绘
- 导入导出皮肤
DSH 皮肤插件:只用样式表换主题,自带皮肤库(深色/浅色按模式预设、导入导出、一个设置分区)
README
由 DeepSeek 最新模型翻译生成dsh-mini-skin
一个只注入样式表的 DSH 皮肤插件,带一个自包含的皮肤库。所有开关集中在 设置 → 自定义皮肤 一个分区里。
运行时成本刻意压到最低:0 个 MutationObserver、1 个一次性监听(DOMContentLoaded)、只依赖宿主的稳定钩子(data-slot=)。图片数据一律留在样式表里,切换素材只改一个 body 属性;行内变量只存极小值(rgba 颜色、字体栈、px 偏移、blob URL)。
安装
GitHub(推荐:一行装,不需要 npm 账号)
dsh plugin --profile web add 'github:Firefly-Star/dsh-mini-skin'
本地目录(link:改文件即时生效,开发用)
dsh plugin --profile web add '<绝对路径>\mini-skin'
tarball(复制安装,工作区目录不再是运行依赖)
npm pack --pack-destination .
dsh plugin --profile web add '<绝对路径>\dsh-mini-skin-0.1.0.tgz'
本插件未发布到 npm(npm 上没有 dsh-mini-skin):请用上面的 GitHub 或 tarball 方式安装。
展开完整文档(README 剩余 1 节)
dsh-mini-skin
一个只注入样式表的 DSH 皮肤插件,带一个自包含的皮肤库。所有开关集中在 设置 → 自定义皮肤 一个分区里。
运行时成本刻意压到最低:0 个 MutationObserver、1 个一次性监听(DOMContentLoaded)、只依赖宿主的稳定钩子(data-slot=)。图片数据一律留在样式表里,切换素材只改一个 body 属性;行内变量只存极小值(rgba 颜色、字体栈、px 偏移、blob URL)。
安装
GitHub(推荐:一行装,不需要 npm 账号)
dsh plugin --profile web add 'github:Firefly-Star/dsh-mini-skin'
本地目录(link:改文件即时生效,开发用)
dsh plugin --profile web add '<绝对路径>\mini-skin'
tarball(复制安装,工作区目录不再是运行依赖)
npm pack --pack-destination .
dsh plugin --profile web add '<绝对路径>\dsh-mini-skin-0.1.0.tgz'
本插件未发布到 npm(npm 上没有 dsh-mini-skin):请用上面的 GitHub 或 tarball 方式安装。从 GitHub/tarball 安装是复制安装——本地源码的改动不会再影响已装版本。
重启语义:客户端半边(lib/client.js)热更新即可;节点半边(lib/index.js)改动必须重启 DSH。皮肤库路由只在重启后存在。
功能
四种皮肤状态
| 状态 | 含义 |
| 官方皮肤 | 宿主原样:本插件的样式表、body 属性、行内变量全部撤下(插件本体仍在,设置分区照旧可用) |
| 内置皮肤 | 出厂那套:深色→暗色场景、浅色→亮色场景、侧栏→maid-atelier 立绘 |
| 皮肤库里的皮肤 | 插件自带目录中的 .json 包,名字取自包内 name |
| 自定义 | 当前设置的指纹与应用皮肤时记下的指纹不符(即你改过任何一项) |
四套预设:主题 × 状态
主内容背景图 / 不透明度、侧栏背景图 / 不透明度 / 水平 / 垂直位置 按四个组合各存一份:dark:idle / dark:work / light:idle / light:work。
生效组合 = 当前主题 × 当前状态(是否正在工作);主题事件与状态变化都会重放设置。
工作状态怎么检测:宿主只在 DOM 上暴露状态(没有服务、没有事件),所以每 0.4 秒读一次 [data-state=running] 与 [data-composer-input][data-phase]。原皮肤为此挂了整个 body 的 MutationObserver;本插件改用一个定时器(每轮一两次 querySelector)—— 代价是切换最多延迟 0.4 秒,收益是保住 0 观察器。
面板顶部的「正在编辑」是四选一:切换它会调用宿主的 theme.setTheme() 把界面主题真的切过去、并临时把预览状态切到空闲或工作,所以你改什么就能立刻看到什么;关掉面板后交还给自动检测。在某一套里改任何值也会先确保该套生效。
背景图(勾选式)
主内容 [x] 有背景图
|-- 背景图 本地文件… / (禁用项)内置素材:亮色场景(来自皮肤)
| 已选择本地文件:xxx.webp <- 勾了没选时显示「尚未选择图片。」
| 不透明度 ----o---- [52] %
[ ] 有背景图 -> 素材 / 不透明度 / 位置全部隐藏,该模式素材设为「无」侧栏 同一套(含水平 / 垂直位置)
- 勾选 = 该模式素材为 file;取消 = none。存储与皮肤包格式与选择无关。
- 素材只支持本地图片(系统文件选择器,图片本体存 IndexedDB)。不支持远程 URL:custom 分支仅作为旧设置的兼容兜底保留。
- 内置素材(场景 / 立绘)不能在这里挑选——它们属于"皮肤"这一层;下拉里只以禁用项出现,告诉你"现在是什么、来自哪"。
其它
- 方形契约(可关):按钮、输入框、卡片、弹窗圆角归零
- 字体:界面字体(覆盖宿主的 --dsw-font-family)+ 侧栏字体(只作用于侧栏列)
- 品牌字标:DSH 方框字标 / 宿主原样
- LINK ACTIVE 标签开关
皮肤库(插件自己的目录)
节点半边把 <DSH_HOME>/mini-skins/ 通过一条同源路由暴露给浏览器半边:
GET -> { dir, skins: [{ file, name, savedAt, bytes, ok, error }] }
GET ?file=<名字> -> 该包的完整 JSON
POST { pack } -> 写进库(重名自动加时间戳后缀)
DELETE ?file=<名字> -> 删除
- 只处理目录里直接的 .json;请求只能点名文件,不能给路径(basename + 白名单正则双重校验)。
- 解析不了的文件不隐藏,在下拉里标灰并给出原因(JSON 解析失败 / format 不符 / 读取失败:)。
- 导出 = 两件事都做:下载 <名称>-<日期>.json 并且存入皮肤库(状态行分别报告两边结果)。
- 导入:系统文件选择器读一个 .json,图片写回本机存储后立即套用。
包格式(自包含)
{
"format": "dsh-mini-skin-pack",
"version": 2,
"name": "我的皮肤", "savedAt": "2026-...",
"shared": { "square": true, "brandMark": "dsh", "linkChip": true, "uiFont": "system", "sidebarFont": "inherit", "packName": "我的皮肤" },
"modes": {json
"dark": { "canvasImage": "dark-hero", "canvasOpacity": 52, "sidebarImage": "maid-left", "sidebarOpacity": 100, "sidebarOffsetX": 0, "sidebarOffsetY": 0 },
"light": { "canvasImage": "light-hero", "canvasOpacity": 52, "sidebarImage": "maid-left", "sidebarOpacity": 100, "sidebarOffsetX": 0, "sidebarOffsetY": 0 }
},
"images": { "sidebar:dark": "data:image/webp;base64,..." }
}
- 内置素材按名字引用(dark-hero / light-hero / maid-left ...),不重复打包 -> 纯内置配置的包只有几 KB。
- 本地图片的字节内嵌进 images(键为 区域:模式)-> 换台机器导入即用,不需要原文件。
- activeSkin(皮肤库身份)不进包:由导入方在导入后决定。
- 因此「自包含」是结构上的保证:只涉及本地图片,没有跨域 / 失效链接的可能。
数据与存储
| 位置 | 内容 |
| localStorage['dsh-mini-skin:settings:v1'] | 设置 v2:{ version, dark{10 项}, light{10 项}, square, brandMark, linkChip, uiFont, sidebarFont, packName, activeSkin } |
| IndexedDB['dsh-mini-skin'].images | 本地图片本体,键为 canvas:dark / canvas:light / sidebar:dark / sidebar:light |
| <DSH_HOME>/mini-skins/.json | 皮肤库 |
迁移:v1(扁平、无模式概念)会同时写进两套预设;更早的 dsh-mini-skin:art-opacity 单键也会被读取(先判键存在——Number(null) 是 0,曾经因此让全新安装的默认不透明度变成 0)。
文件
| 路径 | 说明 |
| lib/index.js | 节点半边:皮肤库目录 + /api/dsh/mini-skins 路由(ctx.inject(["webServer"], ...) + server.register) |
| lib/client.js | 浏览器半边(提交型产物,460 KB,含 5 张内嵌图):样式表、生命周期、设置分区、皮肤库客户端 |
| package.json | dsh.bundle.patch / dsh.client / exports(含 ./locale/.json)/ files 白名单 |
| cordis.patch.yml | bundle patch:插入插件行 |
| locale/{zh,en}.json | 插件菜单的本地化名称与简介 |
| assets/plugin-icon.svg | 插件图标(自绘,无第三方美术) |
| artwork/ | 署名与许可 |
| skins/ | 烘焙好的动图与可直接放进皮肤库的示例皮肤包 |
| dev/anim/ | 动画管线:状态图集切片、质心对齐、皮肤包生成、接缝校验 |
开发
工厂源码在 dev/new-factory.txt,assemble.mjs 把它拼到 lib/client.js 的图片前缀之后。不要手改 lib/client.js 里那段工厂:它每次都会被覆盖。
powershell
node dev/assemble.mjs # 拼接(保留 412 KB 图片前缀 + 内嵌 5 张图)
node --check mini-skin/lib/client.js # 语法
验证(探针)
验证脚本通过 CDP 驱动一个隔离的无头 Chrome,对着一个探针 DSH 实例跑真实交互: powershell
1) 探针实例(写 ~/.dsh,需要更宽权限)
dsh --profile web --no-open --port 0
2) 隔离 Chrome(需要命名管道权限)
chrome --headless=new --no-sandbox --remote-debugging-port=9335 --user-data-dir=<工作区>\_probe-chrome
3) 跑脚本
$env:DSH_PROBE_APP='http://127.0.0.1:<端口>/?token=<令牌>'; $env:DSH_PROBE_CDP='http://127.0.0.1:9335'
node dev/verify-chain4.mjs
脚本要点(踩过的坑都在里面):设置弹窗必须用真实鼠标事件(Input.dispatchMouseEvent)点击,.click() 无效;点击前要 scrollIntoView(面板会超出视口);用 的 value + change 合成事件驱动不了 React。
探针的硬限制:探针实例切不动宿主主题(「外观」那三个方块点了不生效),所以「切主题 -> 换预设」这条路必须由人在真实界面里验。
已验证 / 未验证(如实)
已在探针里实测通过:插件装载(样式表 + body 属性)、画布与侧栏背景层真实绘制、侧栏定位 0px 0px, 50% 100%、面板渲染(7 下拉 / 4 滑块 / 4 数字框 / 11 按钮)、按模式取预设一致(含侧栏垂直偏移)、导出包生成(格式 / 命名 / 入库)、控制台无异常。
已用无头 Chrome 实测(软件渲染):侧栏 268x268 下「无背景 / 静态图 / 空闲动图(6帧1.12s) / 工作动图(8帧0.66s) / 工作动图全屏」五档,帧距中位数均为 8.3ms(120Hz)、p95 8.4-8.5ms、最大不超过 18ms,Task% 差异全在 ±0.5% 噪声内(基线反而最高),Layout/Recalc 均为 0.00 —— 即动图代价在噪声之下。无头是软件渲染,真机 GPU 表现建议用 DevTools → Rendering → Frame Rendering Stats 复核。
只有静态核查:勾选式 UI、皮肤库路由的运行时行为、导入流程、v3 四套预设的迁移路径。
探针 / 实测抓出并修掉的真 bug(留存记录):
1. 行内样式写几百 KB 的 data URI -> 图不显示、换图无效(图片数据必须留在样式表)
2. 蒙版 rgba() 当作 background-image 图层 -> 整条声明失效(必须是 linear-gradient())
3. 缺失的旧键 Number(null) === 0 -> 全新安装默认不透明度为 0
4. 外层脚本 const IMAGES 在 HMR 重复求值时抛 already been declared -> 整份插件失效(改为可重复求值的 window.__dshMiniSkinArt 赋值)
5. 受控 的当前值不在选项里 -> 显示第一项("不要背景图"),再选它因"值没变"不触发
6. 面板用 inject 捕获的对象快照初始化 -> 重新挂载后显示旧值(改为向插件取当前值)
许可
本仓库的代码与美术分开许可,两套条款各自独立:
| 范围 | 许可 | 文件 |
| 代码:lib/index.js、lib/client.js 里的代码、package.json、cordis.patch.yml、locale/、assets/、构建工具 | MIT | LICENSE |
| 美术:artwork/ 下的图片资源,以及 lib/client.js 内嵌的图片数据 | CC BY-NC-SA 4.0 | artwork/LICENSE-ARTWORK |
署名链(必须随资源一起保留):
- 场景图:orca-link —— 上善 -> Small-tailqwq,见 artwork/NOTICE
- 立绘:maid-atelier —— 上善 -> ZipZipPipe -> Small-tailqwq,见 artwork/NOTICE-maid-atelier
注意事项:
- 美术是非商业许可:不得用于以商业优势或金钱报酬为主要目的的用途。
- 立绘经降采样与重编码后随包分发,属改编作品,按相同方式共享条款继续以 CC BY-NC-SA 4.0 分发。
- 复制本插件的图片资源时,署名与许可必须一起带走。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
Firefly-Star/dsh-mini-skin
集中管理深浅色皮肤预设,一键切换背景与立绘
相关插件 · UI / 主题
破甲增强版JeffKeeping/dsh-purge-plus
dsh-purge 的非官方分支fork:适配 DeepSeek Harness 0.2.1-rc.2、破甲内核…
★ 387已汉化DeepSeek 客户端
71.9
无代码业务系统平台nocobase/nocobase
NocoBase 是什么
★ 24,804已汉化DSH
71.8
1Panel 服务器面板1Panel-dev/1Panel
全球 250 万+ 自托管用户共同喜爱。
★ 37,350已汉化DSH
71.5
工作状态行动态ccch1mneyyy/working-activity
作者:chimney@ccch1mneyyy。社区项目,非 DeepSeek 官方项目。
★ 664已汉化DSH
71.2
多模型配置管家farion1231/cc-switch
跨平台桌面一体化助手,支持 Claude Code、Codex、OpenCode、DeepSeek Harness 等工具,唯一官网 ccswitch.io
★ 151,506已汉化DSH
71.1
AI 矢量设计工具ZSeven-W/openpencil
全球首个 AI 原生开源矢量设计工具。
★ 7,027已汉化DSH
71.1
这是你的仓库?认领条目