dsh-skin:给 DeepSeek Harness 界面铺一层壁纸

前言

DSH 的工作台是长驻窗口,一打开就是几小时。纯色背景看久了容易疲劳,但给界面加背景这件事,多数皮肤插件只做到「换一套配色」,真正把壁纸放进去的很少。已有的做法通常是自己抓一张图塞进 CSS,端口一变、文件路径一变就失效,而且图片缓存没有着落。

下面介绍的 dsh-skin(架上包名 dsh-skin-bg)就是为了这件事:把图床直链、本地图片、Wallpaper Engine 库里的素材铺到 DSH 界面背后,再配上透明度、模糊、轮播和快捷键。插件由 Avan0203 维护,在社区目录里归在「趣味换装」分类下,许可证为 MIT。

这是什么

一句话:这是一个 DSH 界面皮肤插件,把壁纸渲染在应用框架之下,用同源 HTTP 路由读取本地媒体,用设置页集中管理来源与外观。

它解决三个问题:

  1. Web UI 跑在 http://127.0.0.1:<port> 上,浏览器读不了 file:// 路径,而 localStorage 又会因为端口变化失效——所以配置和媒体都放在 Host 半边。
  2. 壁纸来源不止一种(图床、本地、Wallpaper Engine),来源之间要能互斥切换,切换后立刻重建播放列表。
  3. 换壁纸不能影响操作:弹窗要保持实心、快捷键要能改、其他皮肤插件同时开启时不要互相覆盖颜色。

核心能力

三种壁纸来源

三选一,切换后立即重新加载并重建播放列表。

  • 图床链接:每行一个 https://… 直链,最多 100 条。支持 png jpg jpeg jfif webp gif avif bmp svg,也接受 mp4 webm ogv mov m4v 视频。每次切换都会带 fresh=1 重新取图并按地址存档,旧图留在「已加载图片」里,重启后仍在。
  • 本地图片:填单个文件或整个目录,最多分别为 200 条和 50 条;也可以在设置里点「选择文件夹」导入(导入的是副本,原文件不动)。
  • Wallpaper Engine:指向创意工坊 431960 目录或任意已下载壁纸目录,自动扫描图片和视频,视频静音循环播放。

外观与播放

三个滑杆控制层级:壁纸透明度(0–100)、界面不透明度(0–100,越低壁纸越明显)、高斯模糊(0–80 px)。界面层的半透明是通过改写 --dsw-alias-bg-base、--dsw-specific-sidebar-fill、--dsw-alias-bg-layer-1/2、--dsw-alias-bg-overlay 的 alpha 实现的,读取的是当前令牌值,所以别的皮肤换的配色照样会透出壁纸;弹窗用同一令牌的不透明副本兜住,[role="dialog"]、[aria-modal="true"] 始终实心。

轮播方面:间隔 3 秒~24 小时、随机顺序、0–5 秒交叉淡入淡出;视频可以「播完自动切」或循环,默认静音(被浏览器拦截自动播放时自动回退静音)。

快捷键与持久化

两条命令 dsh-skin-bg.next 和 dsh-skin-bg.previous 对应下一张 / 上一张,默认 Ctrl+Alt+←/→,macOS 为 ⌘+⌥+Shift,可以在 设置 → 通用 → 快捷键 里改键。注册失败会在面板里说明,不会静默忽略。

配置存在 $DSH_HOME/data/dsh-skin/config.json;媒体路由支持 Range,视频可以拖动播放。界面语言中英双语,跟随 DSH 语言设置。

安装与启用

插件只在 Web UI 上渲染,前提是 DSH(桌面版或 dsh web)带有 webServer 服务。DSH 的插件是装在 profile 里的普通 npm 包,没有统一的 dsh plugin add 命令,需要自己进 profile 目录执行。

方式一,从 GitHub 安装(README 推荐的做法):

cd "$HOME/.dsh/profiles/desktop"
pnpm add github:Avan0203/dsh-skin

Windows 下 profile 默认在 %USERPROFILE%\.dsh\profiles\desktop。然后编辑同目录的 package.json,把包名加进 dsh.profile.bundles:

{
  "dsh": {
    "profile": {
      "bundles": [
        "@deepseek-ai/dsh-base",
        "@deepseek-ai/dsh-web-app",
        "dsh-skin-bg"
      ]
    }
  }
}

重启 DSH,打开 设置 → 背景壁纸。注意一个容易踩的坑:仓库名是 dsh-skin,但架上包名是 dsh-skin-bg——dsh-skin 这个名字在 npm 和插件市场索引里已被同名插件占用,bundles 里要写的是 dsh-skin-bg。

方式二,用 Release 里的压缩包:

cd "$HOME/.dsh/profiles/desktop"
pnpm add ./dsh-skin-bg-1.0.3.tgz

从 Releases 下载 dsh-skin-bg-<版本>.tgz(若该版本没附带压缩包,用方式一或 GitHub 自动生成的 Source code 压缩包),同样把 "dsh-skin-bg" 加进 dsh.profile.bundles 并重启。

方式三,本地开发 link,适合改代码时用:

git clone https://github.com/Avan0203/dsh-skin.git
cd "$HOME/.dsh/profiles/desktop"
pnpm add link:/绝对路径/dsh-skin

之后改 client.js 刷新页面即可生效,改 index.js(Host 半边)需要重启 DSH。

1.0.x 升级时的包名变更

包名从 dsh-skin 改成了 dsh-skin-bg。升级步骤:

  1. profile 的 package.json 里把 dsh-skin 换成 dsh-skin-bg(依赖与 dsh.profile.bundles 两处);
  2. pnpm install,重启 DSH。

设置和已存档的壁纸不会动:数据目录仍是 $DSH_HOME/data/dsh-skin/,HTTP 路由前缀仍是 /plugin-skin。唯一会变的是快捷键 id(dsh-skin.next → dsh-skin-bg.next),自定义过按键的话要在 设置 → 通用 → 快捷键 里重设一次。

配置项

设置保存在 $DSH_HOME/data/dsh-skin/config.json,也可以直接改这个文件,改完重启 DSH 或打开设置页保存一次。常用字段如下:

字段 默认值 范围 / 取值 说明
enabled true 布尔 关闭后立即移除壁纸层。
source "urls" urls / local / wallpaper 当前使用的来源。
urls [] 最多 100 条 图床直链。
folders [] 最多 50 条 本地图片 / 视频目录。
files [] 最多 200 条 本地单个媒体文件。
cacheUrls true 布尔 开启后每次切到图床图都重新下载并另存;关闭后直接请求图床、不落盘(历史存档仍会列出)。
cacheDir "" 路径 留空用 $DSH_HOME/data/dsh-skin/library。
wallpaperDir "" 路径 Wallpaper Engine 创意工坊目录。
opacity 100 0–100 壁纸本身的透明度。
surfaceOpacity 62 0–100 主界面面板的不透明度。
blur 0 0–80 壁纸的高斯模糊(像素)。
intervalSec 30 3–86400 轮播间隔(秒)。
random false 布尔 随机播放。
advanceOnEnd true 布尔 视频播完自动切下一张。
videoMuted true 布尔 视频默认静音。
fadeSec 1.2 0–5 两张壁纸交叉淡入淡出时长(秒)。

典型用法

装好之后,打开 设置 → 背景壁纸,按下面的顺序配:

  1. 在「图床链接 / 本地图片 / Wallpaper Engine」里选一个来源,切换后立即重新加载。
  2. 填来源:粘贴图床直链、添加本地文件或目录、或填 Wallpaper Engine 目录后点「重新扫描」。
  3. 调外观:先把「界面不透明度」调到 40~70,壁纸和控件都能看清;想让壁纸更干净就把模糊加到 10~20 px。
  4. 设播放:轮播间隔按自己的节奏定,需要背景图常变就把间隔设小;视频不想要声音就保持默认静音。
  5. 用快捷键切图:Ctrl+Alt+←/→。想让壁纸只在不用 DSH 时出现,比起改快捷键,更直接的是用 enabled 开关或调低 opacity。

图床来源的图会按地址分文件夹缓存,列表最多展示最近 5000 张。「已加载图片」里点缩略图立即切回,悬停点 × 删单张;右上的「清空」只清掉当前来源的地址列表,不删缓存文件。

实现与安全边界

插件分成两半。index.js 是 Host 半边,负责持久化配置并以同源 HTTP 路由提供媒体文件;client.js 是浏览器半边,负责壁纸层、轮播、设置页和快捷键;另有 cordis.patch.yml 往 profile 里 insert 这个 bundle,locale/{zh,en}.json 提供双语文案。

Host 需要一个 HTTP 路由前缀,挂在 /plugin-skin 下:

方法 路径 用途
GET /plugin-skin/state 读配置 + 当前播放列表,?refresh=1 强制重扫目录。
POST /plugin-skin/config 保存整份配置(JSON)。
GET/HEAD /plugin-skin/media?path=… 流式读取本地媒体文件。
GET/HEAD /plugin-skin/remote?url=… 代理并缓存图床图片,&fresh=1 取一张新的并另存。
GET /plugin-skin/cache 列出已缓存的图床图片。
POST /plugin-skin/upload?name=… 「选择文件夹」导入时把文件写入缓存目录。

安全边界写得比较明确:

  • media 路由只放行当前配置里声明过的目录 / 文件(由 source 决定白名单),其余路径 403;
  • 只放行白名单内的图片 / 视频扩展名,其余 415;
  • 目录扫描最多 4 层、4000 个条目,远程下载 64 MB 上限、20 秒超时;
  • 除你主动添加的图床地址外不发起任何外部请求,不上传、不统计,本地媒体只经 127.0.0.1 同源路由。

适用场景与注意

适合这几类人:想把 DSH 工作台换成自己熟悉的壁纸、已经有 Wallpaper Engine 素材库、或者需要给截图和录屏换一个干净背景的开发者。只要用的是带 webServer 的 DSH 构建,桌面版和 dsh web 都可以。

几点要注意。

  • 插件以当前 DSH 进程的权限运行,并会注册同源 HTTP 路由、读写 $DSH_HOME/data/ 下的目录和 profile 里的 package.json。安装前先读一遍源码与许可证(本仓库为 MIT)再决定是否引入。
  • 已知边界:图床来源的随机播放不生效,图床按地址顺序轮播;视频播完自动切时,轮播间隔对该视频不生效,切换时机由视频时长决定;壁纸层固定在 z-index:-1,只做背景,不替换任何官方控件。
  • 与其他皮肤插件同时开启不会打架:界面不透明度监听 theme/change,每次用当时的令牌值重算 alpha。
  • 改动提醒:改 index.js 必须重启 DSH,改 client.js 只需刷新页面。

结尾

dsh-skin 做的事情很窄——把壁纸铺到 DSH 界面底下,不碰控件、不做主题系统。真正值得借鉴的是它的工程取舍:配置放 Host 侧、本地媒体走同源路由、内存之外再留一份按地址分文件夹的存档,因此重启不丢东西,快捷键和播放状态也有兜底。

如果只是想换个背景、又不想自己维护一堆 CSS,这个插件可以直接用;想更进一步,/plugin-skin 的路由表和 cordis.patch.yml 就是全部实现入口。

  • 社区目录:https://www.skillhub.cn/plugins/Avan0203/dsh-skin
  • 仓库:https://github.com/Avan0203/dsh-skin
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜