dsh-wallpaper
给 DSH 网页端加一张照片当背景,并把画布、侧边栏变成半透明,让图透出来。所有参数都能在 设置 → 壁纸 里实时调,改完自动保存。
An adjustable photo wallpaper for the DSH web GUI: a fixed backdrop layer plus translucent canvas/sidebar, tuned live from a Settings page.

功能
- 真实背景图:
background-size: cover的固定图层,窗口缩放、滚动都不跑位。 - 半透明而不是换皮:只覆盖
--dsw-alias-bg-base(画布)和--dsw-specific-sidebar-fill(侧边栏)两个语义色,组件自身的卡片、按钮、文字配色完全不动,深浅色主题各自保留原色相。 - 五个可调参数:画布透明、侧边栏透明、薄纱(整体压暗/提亮的一层膜)、亮度、柔化(模糊)。拖动即时生效,防抖后写入 Host。
- 换图:点「选择图片…」或直接把图片拖进面板,支持
webp / png / jpg / jpeg / gif / avif / bmp,单张上限 24 MB,按扩展名给出正确的Content-Type。 - 一键恢复:清空当前图片,回到仓库内置图。
- 出问题也不会拖垮启动:Host 半边零静态 import、逐条路由 try/catch;浏览器半边声明了
inject: ['slots'],任何一步失败只会让设置页或背景消失,插件条目照常激活。
安装
前置:DSH 0.2.1 及以上(桌面版或 dsh web 都一样,插件跑在网页端)。
git clone https://github.com/dingzhen-114514/dsh-wallpaper.git
cd dsh-wallpaper
node scripts/install.mjs # 默认装进 desktop 配置
# node scripts/install.mjs --profile work # 或者指定另一个 profile
脚本只做三件事:
- 在
~/.dsh/profiles/desktop/node_modules/@local/dsh-wallpaper建一个指向本仓库的目录链接(不复制文件,改代码立即生效); - 给 profile 的
package.json加上"@local/dsh-wallpaper": "link:<本仓库路径>"; - 把包名加进
dsh.profile.bundles—— 包内自带的cordis.patch.yml会在启动时插入加载行。
然后重启 DSH。 配置里的 bundle 列表只在启动时读取、不监听变化;重启后打开「设置 → 壁纸」。
包名带
@local/作用域,是因为它通过link:装进 profile、不发布到 npm。clone 到哪里都行,脚本会写入实际路径。
卸载
node scripts/install.mjs --remove # 移出 bundles、删掉依赖与链接
重启 DSH 即恢复原样。个人设置仍在 ~/.dsh/wallpaper/,想彻底清掉连这个目录一起删。
用法
打开 设置 → 壁纸:
| 控件 | 默认 | 作用 |
|---|---|---|
| 启用背景 | 开 | 总开关,关掉就退回不透明的原生外观 |
| 画布透明 | 60% | 主内容区底色透明度,越低越透 |
| 侧边栏透明 | 72% | 左侧栏底色透明度,通常比画布更透一点更耐看 |
| 薄纱 | 18% | 盖在图上的一层膜:浅色主题提亮、深色主题压暗,用来压住花哨照片、保证文字对比度 |
| 亮度 | 100% | 图片亮度,50%–150% |
| 柔化 | 1px | 高斯模糊,0–12px,适合把细节多的照片化开 |
「图片」卡片里可以预览当前图、选择新图(或拖放)、恢复内置图。底部状态行会显示「已保存」「已恢复内置图」这类结果。
换成自己的图
三种方式,任选:
- 设置页里点「选择图片…」或拖放 —— 存到
~/.dsh/wallpaper/wallpaper-<时间戳>.<扩展名>; - 把图直接存成仓库根目录的
wallpaper.webp(已被.gitignore忽略,不会误提交别人的图); - 不想要内置图时什么都不用做:仓库自带的
assets/placeholder.webp自动兜底。
原理
┌──────────────────────────────┐
│ .dsh-wallpaper 固定图层 z=0 │ ← 照片 + 薄纱 ::after + brightness/blur 滤镜
├──────────────────────────────┤
│ #root z=1 │ ← 应用本体
│ body 背景透明 │
│ 画布/侧边栏 = 语义色的半透明 │ ← 只改这两个 token,组件其余部分不动
└──────────────────────────────┘
- 浏览器半边把设置写成
documentElement上的 CSS 变量(--dw-canvas-a、--dw-sidebar-a、--dw-veil-a、--dw-brightness、--dw-blur、--dw-image),样式表用这些变量合成rgb(255 255 255 / var(--dw-canvas-a))(浅色)和rgb(21 21 23 / var(--dw-canvas-a))(深色,由body[data-ds-dark-theme]区分)。 - 因为只改语义别名,任何依赖
--dsw-alias-*的组件都会自动得到正确的对比度,不需要逐个打补丁。 - 图片 URL 带
?rev=<mtime>-<size>,换图后浏览器不会拿旧缓存。
数据与接口
设置文件 ~/.dsh/wallpaper/state.json($DSH_HOME 优先),诊断日志 ~/.dsh/wallpaper/boot.log。
| 路由 | 方法 | 说明 |
|---|---|---|
/wallpaper/state |
GET |
返回 { state, image },image.url 带版本号 |
/wallpaper/state |
POST |
局部更新,数值非法时被夹到合法范围 |
/wallpaper/image.webp |
GET |
当前生效的图片字节(Content-Type 随实际文件扩展名) |
/wallpaper/upload |
POST |
{ name, dataUrl },落盘后自动切换 |
state.json 字段:enabled、image(绝对路径或 null)、canvas、sidebar、veil(0–100)、brightness(50–150)、blur(0–12)。
开发
npm test # = node tests/smoke.mjs,60 项离线检查
测试不启动应用:Host 半边在临时 DSH_HOME 里跑真实路由(默认值、夹取、持久化、坏 JSON、405、上传往返、非法扩展名、恢复);浏览器半边用 DOM/React/fetch 桩执行真实的 client.js,驱动设置面板并断言样式变量与保存请求。
两条硬约束(写 DSH 客户端插件请记住)
- 浏览器半边必须在自己导出的插件对象上写
inject: ['slots']。 Cordis 的 context 是代理,读未声明的服务属性会直接抛cannot get property "slots" without inject;这个异常会让整个客户端条目激活失败,桌面壳把它报成web boot: 1 entry did not activate,页面起不来,只能禁用插件。 - Host 半边不要写静态 import,路由逐条 try/catch。 这样某条路由注册失败时插件仍然激活,错误落在
boot.log,不会把一个装饰性插件变成启动阻断。
排错入口:~/.dsh/wallpaper/boot.log(Host 激活与每条路由的结果)、%APPDATA%\@deepseek-ai\dsh-desktop\logs\crash-*-web-boot.log(桌面壳的网页端启动崩溃报告)。
兼容性
- 在 Windows + DSH 桌面版
0.2.1-rc.5(Electron 44 / Node 24)上验证;Host 半边只用ctx.webServer.register与node:fs,路径全部走DSH_HOME,dsh web与桌面版通用。 - 安装脚本在非 Windows 上退化为普通符号链接(
junction类型仅在 Windows 生效)。 - 只影响画布与侧边栏两处语义色。如果同时装了别的改主题插件,两边都写
--dsw-alias-bg-base,最终效果取决于加载顺序。
许可
MIT。仓库自带的 assets/placeholder.webp 是程序生成的渐变图,可直接使用;wallpaper.webp 故意不进版本库,请只提交你拥有权利的图片。
No comments yet. Be the first to write one.