# dsh-ui-web

> 一个 npm 包内置 9 款 DSH Web GUI 主题皮肤与皮肤中心卡片，支持在线试穿、一键切换，无需重启。

## Metadata

- Author: [@CAPTAIN1275](https://github.com/CAPTAIN1275)
- Repo: <https://github.com/CAPTAIN1275/dsh-ui-web.git>
- GitHub: [CAPTAIN1275/dsh-ui-web](https://github.com/CAPTAIN1275/dsh-ui-web)
- Stars: 34
- Language: TypeScript
- License: [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html)
- Topics: `dsh-plugin`, `dsh-plugin-market`, `dsh-plugins`
- Forks: 2
- Open Issues: 0
- Last push: 2026-08-16T18:08:27.000Z
- Added: 2026-08-20T00:00:00.000Z

## Install

```bash
dsh plugin --profile web add github:CAPTAIN1275/dsh-ui-web/packages/dsh-skins
```

## Wiki

## 一句话定位
DSH Web GUI 的皮肤全家桶聚合包：装上它就在「插件配置 → Web UI 插件」组里多出一张「皮肤中心」卡片，列出 9 款内置主题皮肤（同花顺、Windows XP、蓝色幻想、龙的传人、Minecraft、初音未来、交易终端、鲸吟、极光），支持在线试穿和一键切换。

## 核心能力
- 在「插件配置 → Web UI 插件」里插入一张皮肤中心卡片，列出官方默认与所有已装皮肤的名称、tagline、强调色，当前激活带 Active 标记
- 在线试穿任意一款皮肤（不持久化）：即时看效果、亮/暗主题切换、退出完整还原当前皮肤状态
- 一键应用皮肤：宿主 `/api/skin-center/apply` 走进程内的 `dsh-skin use` ESM 端口，写 `~/.dsh/cordis.patch.yml` 的 managed 区段，配置监听器秒级热加载，无需重启
- 皮肤之间互斥：同一时刻只激活一款，由 patch 文件的 `dsh-skin managed` 区段强制
- 一个 npm 包内置全部 9 款皮肤资产（每个皮肤是一组 `skin.json` + `lib/client.js` + `lib/index.js` + `cordis.patch.yml`），无需为每款皮肤单独占用 npm 包名
- 试穿走按需加载：皮肤 bundle（~700KB base64 美术资源）只在点「Try on」时才通过同源 script 路由取，不嵌入冷启动

## 技术实现
- **语言**: TypeScript（皮肤中心 host/client）+ Node.js（聚合包 build 脚本为 ESM `.mjs`）
- **关键依赖**: `@deepseek-ai/dsh-host-webserver`（host 端路由服务）、`@deepseek-ai/dsh-settings`（背景遮挡配置 schema）、`@deepseek-ai/dsh-client-runtime` / `@deepseek-ai/dsh-client-ui-theme` / `@deepseek-ai/dsh-client-locale`（client 端运行时/主题/i18n）、`schemastery`（schema 校验）、`react ^18.2.0`（皮肤中心卡片 UI）
- **架构模式**: Cordis 插件 host + client 双半区；host 半区在 `ctx.effect` 里挂载原生 HTTP 路由 `/api/skin-center/*`，通过 `dsh-client-runtime` 注入；切换皮肤的 `use` 命令由进程内 `src/skin-switch.ts`（`dsh-skin` CLI 的 1:1 ESM 端口）直接写 patch 文件 + 管理 profile node_modules 符号链接，无需外部 CLI 二进制
- **入口文件**: 聚合入口 `packages/dsh-skins/build.mjs`（从源 `packages/skins/<id>` 同步资产到 `packages/dsh-skins/skins/<id>`）；皮肤中心 host 入口 `packages/skins/skin-center/src/index.ts`；皮肤中心 client 入口 `packages/skins/skin-center/src/client/index.ts`

## 适用场景
希望给 DSH Web 聊天界面换个风格、又不想折腾命令行的普通用户：装一个包就拿到 9 款主题，从同花顺炒股风格、Windows XP Luna 怀旧、Minecraft 方块世界到当下流行的初音未来、鲸吟都有，皮肤中心卡片里就能试穿 / 一键切换。
喜欢自定义皮肤的开发者也能用：聚合包把每款皮肤的 `skin.json` + `lib/client.js` 完整内置，照着 `packages/skins/aurora` 模板加一款自己的皮肤，跑一次 `pnpm --filter @captain1275/dsh-skins build` 即可出现在皮肤中心里。

## 前置依赖与兼容性
| 依赖 | 最低版本 | 说明 |
|---|---|---|
| DSH | 0.1.0-rc.6+ | 皮肤中心 devDependencies 中 `@deepseek-ai/dsh-host-webserver`、`@deepseek-ai/dsh-client-runtime` 等均为 `^0.1.0-rc.6`（packages/skins/skin-center/package.json:38-46） |
| Node | 未声明 | 仓库根与本包 package.json 均未声明 engines 字段 |
| 平台 | Web / macOS / Windows / Linux | bundle 声明 `dsh.client.platform: "web"`（packages/skins/skin-center/package.json:23）；host 半区在 Windows 上自动回退到目录联结（junction），不依赖开发者模式（packages/skins/skin-center/src/skin-switch.ts:433、487-502） |
| 原生模块 | 无 | 仅使用 Node 内置 fs/os/path，无第三方原生模块；Windows 符号链接失败时回退到目录联结 |

## 安装方式
```bash
dsh plugin --profile web add github:CAPTAIN1275/dsh-ui-web/packages/dsh-skins
```

## 配置项
| 配置 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| `backgroundOpacity` | 数字（0-100，步长 5） | 主界面背景遮挡透明度，数值越大背景图被遮得越深；仅对内置背景图的皮肤（如 blue-fantasy / whale-song）可见效果（packages/skins/skin-center/src/index.ts:34-47） | 0 |

## 常见问题

**Q: 装上这个包之后能在 DSH Web 界面里看到什么？**

A: 在「设置 → 插件配置 → Web UI 插件」组里多出一张「皮肤中心」卡片，列出「官方默认」加上当前安装的所有内置皮肤（同花顺 ths、Windows XP luna、蓝色幻想 blue-fantasy、龙的传人 dragon-heir、Minecraft minecraft、初音未来 miku、交易终端 trading、鲸吟 whale-song、极光 aurora），当前激活的皮肤带 Active 标记。

**Q: 切换皮肤需要重启 `dsh web` 服务吗？**

A: 不需要。点击「Apply / 恢复默认」后皮肤中心会通过进程内 `dsh-skin use` 把变更写入 `~/.dsh/cordis.patch.yml` 的 `dsh-skin managed` 区段，宿主配置监听器在数秒内热加载，浏览器刷新即可看到新皮肤。

**Q: 能不能同时启用两款皮肤？**

A: 不能。皮肤中心通过 patch 文件的 `dsh-skin managed` 区段强制只有一个激活，其它皮肤被写为 `disabled: true`。

**Q: "在线试穿"（Try on）会不会修改我的当前设置？**

A: 不会。试穿只在当前页面临时挂载该皮肤的视觉（真实走模块加载器、不用 eval），退出时按配方完整还原当前皮肤的 body 属性、背景内联样式、chrome 子节点、xp footer taskbar 等，不会写入任何文件。

**Q: 装完之后皮肤列表是空的，或者少了几款怎么办？**

A: 检查 `packages/dsh-skins/skins/<id>` 目录里是否同时存在 `skin.json`、`lib/client.js`、`lib/index.js`、`cordis.patch.yml`，缺一会被 `build.mjs` 跳过；正常 npm 安装会自动完成构建。

**Q: Windows 上切换时报"权限不足"怎么办？**

A: 切换逻辑在符号链接失败时会自动回退到目录联结（junction），不需要开发者模式；如果仍失败请以管理员身份运行 dsh，或手动把皮肤包放进 profile 的 node_modules。

**Q: 怎么加一款自己的皮肤？**

A: 在 `packages/skins/<your-id>/` 下放 `skin.json`（含 id、name、tagline、bodyAttr、wiring.id、package 字段）+ 构建后的 `lib/client.js` / `lib/index.js` / `cordis.patch.yml`，然后跑 `pnpm --filter @captain1275/dsh-skins build` 重新打包，重装聚合包即可在皮肤中心看到。

**Q: 怎么卸掉某款皮肤换回官方默认？**

A: 皮肤中心卡片里有「官方默认」入口，点击即可一键应用；想完全卸载插件则用 `dsh plugin --profile web remove @captain1275/dsh-skins`。

## 上手难度
入门 — 装上即可在 Web 端插件配置里直接看到皮肤中心卡片，无需任何额外配置；想新增或调整皮肤时才需要看 `build.mjs` 和 `skin.json` 字段。

## 已知问题与限制
- 皮肤中心只读取每个 `skin.json` 里 `wiring.bundleWired` 静态字段，未实现基于 profile 实际加载情况的运行时检测（`packages/skins/skin-center/src/skin-switch.ts:245-248` 标注 TODO）
- Windows 上创建 profile 符号链接可能失败（无开发者模式 / 权限不足），需自动回退到目录联结（junction）才能完成切换（`packages/skins/skin-center/src/skin-switch.ts:433、487-502`）
- bundle 仅面向 DSH Web GUI（`dsh.client.platform: "web"`），CLI 模式（headless profile）下浏览器半区不会加载
- 皮肤只改浏览器 DOM（CSS、标题栏、状态栏、背景图等），不触及任何模型请求

---

This document is auto-generated by [deepseek-plugin.org](https://deepseek-plugin.org). HTML page: [dsh-ui-web](https://deepseek-plugin.org/plugins/CAPTAIN1275/dsh-ui-web/packages/dsh-skins)
Wiki generated by AI (model: `MiniMax-M3`)
