dsh-skin-alphacoders
v0.4.3
Published
DSH skin plugin: Alphacoders popular wallpapers as the DeepSeek Harness Web GUI background (gallery, search, local upload, per-theme wallpapers, favorites, auto-change, history, glass blur)
Maintainers
Readme
dsh-skin-alphacoders
English | 中文
DSH 皮肤插件:把 Alphacoders 热门壁纸 设为 DeepSeek Harness Web GUI 的背景,并支持 MoeWalls / Pexels 动态壁纸(视频背景)。符合 DSH 插件包规范的双半(Host + Client)Cordis 插件。


功能
静态壁纸(Alphacoders)
- 壁纸库:设置面板新增「壁纸」分区,浏览 Alphacoders 热门壁纸(每页 15 张、可翻页、懒加载)。
- 搜索:按关键词搜索壁纸(走 Alphacoders 官方搜索页,单页最多 30 条);清除搜索恢复热门列表。
- 一键应用:点击缩略图即应用为背景;只有页面骨架(应用框架、对话区、侧边栏)经主题 token 半透明化透出壁纸;所有凸起表面保持不透明(
--dsw-alias-bg-layer-1/2/3沿用产品原生值)——卡片、输入框、菜单、弹窗与「修改文件」悬浮预览的文字对比度与默认界面一致,不会与壁纸混在一起。
动态壁纸(视频背景,v3)
- MoeWalls / DesktopHut 双源:动态壁纸 tab 内可切换两个视频源;分类/搜索/分页浏览缩略图。
- 下载制(v3.4):点击缩略图跳转原站(moewalls.com / desktophut.com)下载视频文件,再通过「上传本地图片/视频」设为动态壁纸——插件不做在线流式播放,避免被原站限流拖慢。
- 本地上传视频(v3.4):支持 PNG/JPEG/WebP/GIF 图片与 WebM/MP4 视频;视频作为动态壁纸循环播放,文件存于
$DSH_HOME/storages/skin-alphacoders/,重启后恢复;上限 200MB。 - 无缝循环(v3.3):双
<video>接力 + 瞬时切换(无交叉淡化),循环无停顿、无暗亮闪,效果接近 Wallpaper Engine;毛玻璃/遮罩/淡入同样作用于视频层。
视觉与显示
- 毛玻璃(v3):0~30px 背景模糊,只作用于壁纸层——界面与文字在其上层保持清晰。
- Ken Burns 微动效(v3.1):静态壁纸缓慢缩放平移,背景不再死板。
- 渐变分层遮罩(v3.1):边缘压暗 + 中间半透 + 柔光暗角 + 品牌光晕,由单一遮罩滑条驱动;浅色主题白雾、深色主题黑雾,跟随 DSH 主题(
light/dark/system)。 - 换壁纸淡入(v3.1):新壁纸 0.8s 淡入,滑条/主题切换不会闪屏。
- 显示控制:四种填充方式(铺满/完整/居中/拉伸)与 0~90% 遮罩强度。
其他(v2)
- 浅深双主题壁纸:浅色与深色主题各保存一张壁纸,切换明暗自动跟随。
- 收藏:画廊卡片右上角 ☆ 一键收藏,持久化于
user-data.json,点击收藏卡即应用。 - 自动更换:定时自动换壁纸——
随机(远程新鲜壁纸)/顺序(按收藏顺序轮换)/仅收藏(收藏中随机),另有「立即换一张」按钮;间隔 1~168 小时可调。 - 历史记录(v3.1):应用过的壁纸自动记录(最多 5 条,重复应用自动去重移顶),一键恢复旧壁纸。
- 持久化:偏好存于插件自有文档
$DSH_HOME/storages/skin-alphacoders/settings.json(DSH 0.2 移除了 0.4.2 所用的插件 settings 服务),原子写入;收藏与历史存于同目录user-data.json。从 ≤0.4.2 升级不会迁移旧的settings.yaml分节,升级后重新选一次壁纸即可。 - 性能:背景默认使用 1920px 变体(
thumb-1920-<id>),不下载 5K/8K 原图;列表/搜索/动态壁纸均有内存 TTL 缓存。 - 干净卸载:移除插件行后 route、调度器、样式全部消失,GUI 恢复默认外观。
安装
方式一:npm 安装(推荐)
# 安装到 web profile(含构建产物,无需本地构建)
dsh plugin --profile web add dsh-skin-alphacoders方式二:从源码构建安装
# 1. 构建本包(生成 lib/ 产物)
pnpm install && pnpm build # 或 npm install && npm run build
# 2. 安装进 web profile(从本包所在目录的上级执行)
dsh plugin --profile web add "file:<本包绝对路径>"两种方式都需在 $DSH_HOME/profiles/web/cordis.patch.yml 中登记插件行:
# $DSH_HOME/profiles/web/cordis.patch.yml
- insert:
- id: skin-alphacoders
name: 'dsh-skin-alphacoders'
config:
cacheTtlMs: 3600000 # 可选:列表缓存 TTL(毫秒)
requestTimeoutMs: 20000 # 可选:抓取超时(毫秒)
localMaxBytes: 209715200 # 可选:本地上传上限(字节,默认 200MB)重启 dsh web 生效;设置面板 → 「壁纸」分区即可使用。
提示:开发迭代时,可用目录联接把 profile 的
node_modules/dsh-skin-alphacoders指向源码目录(pnpm 的file:依赖默认硬链接复制,修改源码后需要重建联接或重新 add)。
架构
┌─ Host 半(node)─────────────────────────────────────────────┐
│ alphacoders:fetch + 解析 popular-wallpapers?page=N │
│ (服务端渲染的 schema.org ImageObject,15 条/页) │
│ moewalls(v3):REST 列表/分类 → Chrome 抓取降级 → HTML 页 │
│ 详情按页面 URL 解析;视频经本地代理 + 磁盘缓存(LRU 10) │
│ desktophut(v3.5):Node 直抓首页/分类/搜索页, │
│ wallpaper-card 卡片解析(缩略图兼容 /images 与 /img, │
│ 首页解析为空时回退 /popular-live-wallpapers);视频走 │
│ 原站下载制(播放需本地上传) │
│ 内存 TTL 缓存(列表 6h、详情 6h、分类 24h) │
│ settings.json 自有文档(原子写 + 串行写队列) │
│ user-data.json(收藏 ≤200、历史 ≤5,原子写入) │
│ 自动更换调度器(setTimeout 链,按模式选池) │
│ HTTP route(经 ctx.webServer): │
│ GET /skin-alphacoders/wallpapers?page=N | ?query=Q │
│ GET /skin-alphacoders/moewalls/{categories,list,detail,video} │
│ GET /skin-alphacoders/desktophut/list │
│ GET /skin-alphacoders/settings | POST(字段白名单 patch)│
│ GET /skin-alphacoders/user-data │
│ POST /skin-alphacoders/favorites(+ /favorites/remove) │
│ POST /skin-alphacoders/history/remove │
│ POST /skin-alphacoders/theme / auto-change/now │
│ POST /skin-alphacoders/local(图片/视频上传) │
│ GET /skin-alphacoders/health │
└──────────────────────────────────────────────────────────────┘
同源 fetch(无 CORS 面)
┌─ Client 半(浏览器)─────────────────────────────────────────┐
│ skin-store:GET/POST settings route 的本地快照 + 订阅 │
│ user-data store:收藏/历史快照 │
│ 双主题镜像:theme/change 时把当前主题槽同步到扁平字段 │
│ (带 fromTheme 标记,不产生历史记录) │
│ background:body::before 壁纸层 + ::after 渐变遮罩层 │
│ + 视频接力层(双 <video> 瞬时切换,无暗亮闪) │
│ + ctx.theme.overrideTokens 表面半透明 │
│ (签名去重防 theme/change 重入风暴) │
│ settings.section「壁纸」:静态库 + 动态库 + 上传 + 收藏 │
│ + 历史 + 自动换 + 主题 tab │
└──────────────────────────────────────────────────────────────┘为什么由插件自己持有设置文档
api-proxy 的 settings 协议是 Host 白名单(locale、ui-theme 等),仓库外插件注册的 namespace 只会得到 settings-not-exposed;DSH 0.2 又进一步移除了插件侧的 settings 服务(ctx.settings.register / SettingsScope 已不存在)。因此 Host 侧改为自持一份普通文档 $DSH_HOME/storages/skin-alphacoders/settings.json(promise 队列串行 + 临时文件原子替换),浏览器侧仍只经插件自己的 HTTP route 读写。0.4.2 写在 $DSH_HOME/settings.yaml 的 ui-skin 分节不会迁移。
配置
| 字段 | 默认 | 说明 |
|---|---|---|
| cacheTtlMs | 3600000 | 壁纸列表页内存缓存时长(毫秒) |
| requestTimeoutMs | 20000 | 抓取远程站点的超时(毫秒) |
| localMaxBytes | 209715200 | 本地上传(图片/视频)大小上限(字节) |
版权与合规
- 壁纸版权归原作者与 Alphacoders / MoeWalls / DesktopHut 所有;本插件仅供个人使用,不批量下载或再分发壁纸。
- 请在网络策略允许访问上述站点与其图片/视频 CDN 的环境中使用。
验证
e2e/verify.mjs 是 Puppeteer(连接本机 Chrome)端到端验证:需先按上述步骤装好插件并启动 dsh --profile web --port 3090(测试实例可用 E2E_URL 环境变量覆盖端口),再执行:
node e2e/verify.mjs覆盖(70 项断言):画廊渲染、收藏往返、双主题独立壁纸、明暗联动、刷新持久化、历史恢复(含去重)、自动更换、毛玻璃/滤镜增强/Ken Burns/渐变遮罩、搜索、动态壁纸列表/分页/跳转原站、本地上传(图片与视频)、动态壁纸无缝接力、本地壁纸清理、收藏/历史持久化、无页面错误。
另有三个数据源脚本:e2e/bench-desktophut.mjs(抓取层,直打真实站点)、e2e/verify-live-sources-ui.mjs(UI 层,覆盖静态壁纸 / MoeWalls / DesktopHut 三个源,需 E2E_PAGE_URL 指向带 token 的实例)、e2e/net-probe-alt-sites.mjs(源站连通性)。
DesktopHut 壁纸数为 0 的排查顺序
DesktopHut 的列表来自服务端渲染的 HTML,站点改版会让解析静默失败——不报错,只是列表为空。按抓取层 → Host 路由层 → UI 层依次排查:
# 1) 抓取层(直接打真实站点,不需要启动实例;失败时退出码为 1)
node e2e/bench-desktophut.mjs
# 期望:ALL PASS,其中 “all (cat="") p1” 的 items ≥ 3
# 2) Host 路由层(PowerShell;items 不能是空数组)
Invoke-RestMethod "http://127.0.0.1:3080/skin-alphacoders/desktophut/list?page=1" | ConvertTo-Json -Depth 3
Invoke-RestMethod "http://127.0.0.1:3080/skin-alphacoders/desktophut/list?cat=anime-live-wallpapers&page=1" | ConvertTo-Json -Depth 3
# 3) 分类 slug 是否还有效(失效 slug 返回 404 → 该分类为空)
Invoke-WebRequest "https://www.desktophut.com/category/<slug>/" -Method Head -UseBasicParsing | Select-Object StatusCode
# 4) UI 层(需要带 token 的实例地址;断言三个源网格非空、缩略图无需滚动即全部加载,并截图)
$env:E2E_PAGE_URL='http://127.0.0.1:3090/?token=<token>'
node e2e/verify-live-sources-ui.mjs排查要点:
- 默认「全部」页签走的是站点首页
https://www.desktophut.com。站点会不定时改版(2026-09-25 就把首页缩略图从/images/…换成了/img/<W>x<H>/…),解析规则已同时兼容两种路径;若首页再次改版导致解析为空,会自动回退到/popular-live-wallpapers。 - 分类 slug 会被站点改名且不做跳转。当前表在
src/fetch-desktophut.ts的DESKTOPHUT_CATEGORIES(Host 校验与 UI 下拉共用同一份)。要重新同步,从https://www.desktophut.com/show/all-categories里读取/category/<slug>链接,并用上面的bench脚本逐个验证非空。 - 空结果不再进缓存:列表在内存里有 1 小时 TTL 缓存(
cacheTtlMs),但从 v3.5.1 起空页不写缓存,所以「本页没有壁纸」时点一次重试就会真正重新抓取。改了 Host 代码后仍需重启 Host;重启后浏览器再硬刷新一次(client 半也更新了)。 - 切换到动态源几乎是瞬时的:进入「壁纸」分区时,插件会并行预热 MoeWalls 与 DesktopHut 的第一页(Host 端按页缓存并合并并发请求),因此首次切换不再付冷抓成本;预热失败不影响任何源的正常加载。
