dsh-endfield-theme

themetested: passnpmMIT

《明日方舟:终末地》主题:炭黑与警戒黄的工业 HUD、在外壳渲染前注入的开屏动画、对话区背景,以及重新配色的 Windows 标题栏。侧栏品牌会改为「终末地工业 / ENDFIELD INDUSTRIES」,可用 URL 参数还原。

下载量 / Downloads
2,751
依赖体积 / node_modules
3.38 MB
测试时间 / Tested
2026-11-06
DSH 版本 / Version
0.2.2-rc.1

Install

dsh plugin --profile web add dsh-endfield-theme

Sandbox test results

StageResult
1 install✓
2 list✓
3 mount✓
4 boot—

Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).

README

终末地主题 for DeepSeek Harness

![npm](https://www.npmjs.com/package/dsh-endfield-theme)

![license](LICENSE)

《明日方舟:终末地》风格的 DSH 客户端主题:炭黑 + 警戒黄工业 HUD、开机开屏动画、可选的对话区底图,

以及把账户余额画成"电力储备"的侧栏读数。设置项统一收在自己的一个分页里。

npm 包名    dsh-endfield-theme
仓库        github.com/Longxiangjunlin/dsh-endfield-theme

它做了什么

  • 开屏动画 —— 每次加载播一次,约 2.9 秒。网格与磁带先亮,徽记以横向擦除展开,BOOT 进度条

与百分比读数同步推进,右下角打出 FACTORY OS 与站名,然后整屏收起。开屏音效有两种可选:

游戏里的系统播报,或一声 1.5 秒的「Arknights」。

  • 对话区底图 —— 内置四档(炭灰原画 / 雪原 / 等高线 / 纯色),也可以放自己的图片。
  • 侧栏电力储备 —— 把账户余额画成电量计,带状态词(NOMINAL / OUTPUT LOW / DEPLETED)、

今日消耗、以及"还能撑几天"的折算。点标题可以折成一行(¥6.06),再点展开,折叠状态会记住;

它停靠在侧栏左下,并会为工作区列表让出底部空间——列表变长时是自己滚动,而不是被面板压住。

  • 余额语音播报 —— 低于阈值或耗尽时播一次,四种播报版本可选。
  • 对话轮次索引 —— 对话左侧的轮次号,从 data-chat-turn 读,没有脚本遍历正文。
  • 屏幕细纹 —— 静态扫描线,不占每帧预算。
  • 设置页 —— 设置对话框里多一个「终末地主题」分页,17 项,含配置导出/导入与一键清除。
  • 品牌位 —— 侧栏左上换成终末地 lockup(可关)。

这是一个 host-only 插件:cordis.patch.yml 里没有 dsh.client facet,因此注册不了官方设置页,

主题自己扩展设置对话框的 DOM;也正因为如此,它不需要数据库、不写入 profile,

除"读取自带底图/清除数据"外不碰磁盘。

安装

从 npm(推荐) —— 走 registry,不需要 Git,国内可直连(npmmirror 已同步):

dsh plugin --profile desktop add dsh-endfield-theme

从 GitHub —— 等价,但需要能连上 github.com:

dsh plugin --profile desktop add github:Longxiangjunlin/dsh-endfield-theme

本地改代码用 link 装,之后改 client/ 下的文件刷新页面即生效:

dsh plugin --profile desktop add link:<本仓库绝对路径>

若提示找不到 dsh:它装在 DSH 安装目录下的 resources\runtime\cli\bin\dsh.cmd,不在 PATH 里;

或者直接用客户端界面「设置 → 插件 → 添加插件」按包名安装。

升级

客户端插件不支持自动更新。两条路:

1. 市场更新:设置 → 插件 → 已安装 → 更新。它会自己从 npm 的 latest 取版本、按具名版本安装,

并带上 --config.minimum-release-age=0,所以能绕过 pnpm 的 24 小时新包冷静期。

2. 先卸再装:按包名重装会受冷静期影响——发布不足 24 小时的版本 pnpm 不会选,它会退回上一个

通过冷静期的版本。

卸载

  • 界面:设置 → 终末地主题 →「清除数据」→ 确认。它会把自己从 profile 的 package.json

(依赖与 bundles)和 cordis.patch.yml 里删掉,清空本地数据,并撤掉页面上的元素;重启客户端后

彻底消失。写配置前会把两个文件备份成 *.ef-uninstall-backup。

  • 命令行:dsh plugin --profile desktop remove dsh-endfield-theme。

屏幕

开屏 · 浅色

![开屏](preview/splash.jpg) · ![浅色](preview/light.jpg)

品牌位(深色) · 品牌位(浅色)

![深色品牌位](preview/brand-dark.png) · ![浅色品牌位](preview/brand-light.png)

设置页

18 项设置,存在 localStorage,改完即时生效。开屏 / 品牌位 / 开屏音效三项例外,

要重启客户端才生效(桌面端没有刷新按钮,所以说明里直接写"重启")。

分组 · 项 · 默认 · 说明

开屏 · 开屏动画 · 开 · 每次加载播一次,约 2.9 s

· 开屏音效 · 开 · 与开屏同步,缺失或不允许播放时静默

· 开屏音效版本 · 经典 · 经典:系统播报;Arknights:短语音

外观 · 替换侧栏品牌位 · 开 · 换成终末地 lockup

· 屏幕细纹 · 开 · 静态扫描线

· 细纹强度 · 22% · 0 = 关闭

· 轮次索引 · 开 · 对话左侧的轮次号

· 对话区背景 · 开 · 有对话内容时显示底图

· 对话区底图 · 原画 · 四档内置 + 自备图片

电力储备 · 侧栏电力储备 · 开 · 关掉则不轮询,播报随之停

· 余额刷新间隔 · 60 s · 最小 15 s

· 余额语音播报 · 开 ·

· 播报版本 · 完整 · 完整 / 简短 / 提示音 / 自定义

· 播报时长 · 2.5 s · 仅「自定义」生效,0.5–10 s

· 播报音量 · 90% · 拖动即试听

· 预警阈值 · ¥5 · 低于它播报一次

· 余额可用天数 · 0(关) · 按最近一周消耗速度折算

· 电量计满量程 · 4× · 阈值 × 这个倍数 = 满格

强关联的项收成一组,起决定作用的当主项,从属项跟着缩进:

开屏动画 ─┬─ 开屏音效 ─── 开屏音效版本
替换侧栏品牌位
屏幕细纹 ─── 细纹强度
轮次索引
对话区背景 ─── 对话区底图
侧栏电力储备 ─┬─ 余额刷新间隔
             ├─ 余额语音播报 ─┬─ 播报版本 ─── 播报时长
             │                └─ 播报音量
             ├─ 预警阈值
             ├─ 余额可用天数
             └─ 电量计满量程

这些是真依赖,不是视觉分组:开屏关掉就没有音效可听;电力储备关掉就不轮询,播报一起停;

阈值为 0 时"满量程 = 阈值 × N"没有意义。判据是主项的值是否为真,唯一的例外是「播报时长」——

它只对"自定义"这一种播报版本有意义,属于等值判断,单独一张表处理。

主项关掉时从属项变灰并且真的 disabled(不是 pointer-events 障眼法,键盘也不该够到一个

没有作用的控件)。变灰而不隐藏,来回切主项时页面不会在手底下跳。

底部还有:试听警告音(两个按钮,走和真实预警同一条播放路径)、配置(重置 / 导出 / 导入;

导入只接受本版本认识的键且类型一致)、清除数据(自卸载)。

面板为什么需要"让位"。 侧栏里唯一能滚的是工作区列表,而电力储备是 position: fixed 的浮层,

停靠左下时会压在列表下沿——列表再长也只是继续往下长,最后几行永远被盖住。所以停靠时把面板高度

再加上一点间距,作为那个列表的 margin-bottom:列表的盒子因此在面板上沿结束,内容超了就是它

自己滚动(实测塞入溢出内容后 scrollHeight 834 > clientHeight 330,滚到底最低一行停在面板上方

30px)。用 margin 而不是 padding 是量出来的——padding 不会移动这个元素的底边(它的 scrollHeight

始终等于 clientHeight),margin 才会真的把弹性盒子的下沿提起来。

折叠是同一件事的另一半:展开时面板 116px,折起来 48px,让出的空间随之从 134px 回到 66px。

折叠不移动面板,只是把"仪表 + 状态词 + 今日消耗"换成标题行里的一个数字——浮层放到窗口中间会显得

没归位,收起来则不会。标题条既是点击目标也是键盘目标(role="button" + Enter/Space),因为折起来

之后它是唯一还看得见的东西。

余额读数

数据来自 DSH 自己的 deepseekAccount.getBalance,经宿主的一条路由转发;插件不碰凭据,

也不假定投影的形状。实际载荷是:

{ "ok": true, "balance": { "status": "ready",
    "value": [ { "currency": "CNY", "balance": "17.22" } ],
    "bonusWallets": [ { "currency": "CNY", "balance": "0" } ] } }

可消费的是 value(一个裸数组),bonusWallets 从不计入——赠金与充值余额是两回事,

算进去会高估可用余额。

电量计:满量程 = 预警阈值 × 倍数(默认 4),预警点因此固定落在四分之一处。

今日变化:账号服务只报一个余额,"今天花了多少"只能自己记基线再相减。跨自然日、

或余额上升(充值)时重置基线,所以刷新不会把测量从错误的数字重新开始。花钱显示 −,

充值显示 +。

余额可用天数:用最近一周的轮询采样算消耗速度,剩余不足设定天数时也触发预警。它与金额阈值

并列,不替代——¥5 对不同消耗速度的人意义不同。速率取窗口两端的差值,而不是逐对平均:

期间充值会让逐对平均失真,而两端相减在充值时直接得到负消耗,于是报"无法估算"而不是"余额很多"。

告警唯一不能答错的方向就是这一边。

两条触发共用同一个边沿:低余额只响一次,回升后重置,下次再跌再响;填 0 关掉天数触发。

播报版本四种:

版本 · 长度 · 做法

完整语音 · 约 9 s · 原样播放

简短 · 约 2.4 s · 同一份素材在播放时截断,末尾 0.3 s 淡出

提示音 · 0.5 s · WebAudio 合成的两声,不占体积

自定义 · 0.5–10 s · 自己填秒数

浅色模式

浅色不是"反色",而是把外壳调色板换成雪原一套(炭黑文字、#6B6A00 一类的强调色),并

把主题自己画的每个部分都重新量过对比度——那些颜色原本是照着炭黑侧栏写的。实测

(rgb(244,246,240) 为底,WCAG 正文要求 4.5):

元素 · 曾经 · 现在

面板标题「电力储备」 · 1.04 · 16.64

余额数字(警戒黄) · 1.12 · 5.23

POWER RESERVE / NOMINAL / 今日 · 1.96 · 5.94

设置页副标题 · 1.22 · 5.49

数值读数 22% / 90% / 4x · 1.22 · 5.69

试听 / 重置 / 导出 等按钮 · 1.22 · 均高于 5.49

输入框占位符 · 2.75 · 4.79

设置页 51 个带文字的节点现在全部达标,最差 5.49。

两处不是"加一条覆盖"能解决的:占位符用的是外壳的 --dsw-alias-label-caption,主题把它设成

了偏浅的灰;开关的填充在 ::after 上,只改外框会留下一块纯黄方块。输入光标同样是警戒黄——

一条 1px 竖线对对比度的要求本来就比正文高,浅色下改为墨黑,深色下提到更亮的黄。

几处非显然的做法

开屏音效有两份,而不是把旧的换掉。 两份音效都随包发:游戏里的系统播报约 9 秒(开屏只有 2.8 秒,

所以它总是被淡出截断),另一份是 1.5 秒的短语音,长度正好落在开屏之内。选择写在 开屏音效版本 里,

受 开屏音效 管;两份都是鹰角的素材,授权同样记在 NOTICE.md。

开屏走 index 注入行,而不是脚本事后搭。 原版没有独立开屏环节,要成为首帧就必须在外壳渲染

之前进 DOM,所以 webserver/index-inject 里加的是一条内联脚本(内联行不可能加载失败;桌

…(truncated)

Rendered from the README published on npm. Formatted only, not edited.

Versions

Published on npm::14,最后更新 2026-11-01

Links

GitHub · Homepage · npm

Same category