DSH HUB
首页插件商店插件包社区排行榜资源发布指南
插件源码
返回插件目录

ymh0000123 /

dsh-theme-endfield

已验证

终末地官网风格的 DSH Web 主题:奶油纸底、墨黑文字、信号黄强调、全直角工业编辑风。

★ 2 Stars0 Forks0 IssuesN/A 社区评分0 已确认安装
查看 GitHub
README来源: main@48ad1292

dsh-theme-endfield

Edge Intelligence Theme — 参考《明日方舟:终末地》(Arknights: Endfield)官网视觉风格制作的 DSH(DeepSeek Harness)Web 主题插件(动态 Cordis 插件,Client 半部)。

参考:https://endfield.hypergryph.com(国际版 https://endfield.gryphline.com)

设计语言

还原终末地官网的「工业编辑风」:

  • 色板:奶油纸底 #f6f6f3 / 墨黑文字 #101110 / 信号黄强调 #fff500(暗色:纸底 #101110、面板 #181a18、文字 #f5f5f0)
  • 字体:Arial / Helvetica Neue / PingFang SC / Microsoft YaHei,开启 tnum 等宽数字
  • 直角化:按钮、输入框、卡片、菜单、标签、气泡全部 border-radius: 0(状态圆点/头像/加载圈保留圆形)
  • 信号黄交互:悬停反色、焦点环、输入光标、滚动条、表格行、按钮、激活项、Markdown 标记

实现方式

client.js 通过三种机制作用于 DSH Web 界面:

  1. theme.overrideTokens — 覆盖 13 个主题令牌(亮/暗双色),映射终末地官网色板;
  2. styles.insert — 注入全局样式:字体栈、直角化、信号黄强调、中和 DSH 内部 DeepSeek 品牌蓝、hover 反色、表格/按钮/徽章/头部动作黄化等;
  3. 设置页开关 — 「终末地主题设置」提供背景水印、水印保持显示、启动加载动画、主题总开关、圆角模式五个开关,均由 localStorage 持久化。

启动加载动画(默认关闭)

参考终末地官方主视觉:整屏黑底,左边缘 10px 信号黄进度轨自上而下填充。刻度 + 百分比 + 状态行跟随进度轨的填充端一起下移(参考图中读数就贴在黄条前端下方),并做了下边界钳制,接近 100% 时不会滑出屏幕。

播放时序(开启后每次刷新页面播放一次):

  1. 进度(约 1.75s,easeOutCubic 缓出)——黄条自上而下填充,读数随之下移;
  2. 黄色向右铺满(520ms)——到 100% 后,进度轨从 10px 横向展开成整屏黄色,覆盖品牌块与读数;
  3. 整屏淡出(620ms)——黄色连同整块遮罩淡至透明,节点随即从 DOM 移除。

设置行提供「预览」按钮,可不刷新页面直接重播一次。

海报式排版

版式取自主视觉(参考图 1184×685 实测)。要点:品牌块内部左对齐(各行共用同一条左侧节奏线),但整体摆在画面右侧——这个组合才是参考图的观感;若改成右对齐(左边缘参差)则完全变味。

  • END / FIELD 上下两行紧排堆叠,不含中文字标(参考图字标为纯拉丁);
  • 小字冒头 DEEPSEEK HARNESS 在字标之上,双 V 形黄色箭标外突到左侧留白;
  • 说明行、方块指示条、底部标语依次收束在同一节奏线上。

定位改为「锚右边距」而非「锚左百分比」。 早前用 --edge-rail: 73% 定左边缘,实测暴露两个问题:左百分比只决定文字从哪开始,其宽度自由地向右伸展,于是「离右边缘多远」——也就是肉眼真正读到的那段留白——从来不是被控制的量;且纯 vh 取值在宽而矮的窗口里会把字标缩小。现在改为 right: var(--edge-gap),把右侧留白变成显式声明值,节奏线由最宽的一行自然决定。

实测对照(参考图为逐像素扫描;实现为 1440×900 渲染实测):

项目 参考图 修改前 修改后
字标 cap(占画面高) 4.23% 3.01%(偏小) 3.72%
右侧留白 7.4% 10.5%(且不受控) 12%(显式声明)
行距 / cap 1.10 1.10 1.10
右侧溢出 — 无 无

字标尺寸为 --edge-word: clamp(26px, min(5.2vh, 4.8vw), 64px):

  • min(5.2vh, 4.8vw) 取较小轴,因此无论窗口「矮」还是「窄」,品牌块都不会挤进左侧进度轨;
  • 26px 下限保证辅助小字在极小画面下仍可读;
  • 64px 上限是实测结论——不加它时,2560×1440 下 cap 占比会掉到 2.69%(大屏上字标反而变小),加上后稳定在 3.2% 以上。

跨视口验证:520×900 到 2560×1440 共 13 种视口逐一实测(用精确尺寸的 iframe,vh/vw 与媒体查询按真实视口解析),全部无任何方向溢出,cap 占比维持 3.1–3.9%,与进度轨/读数的水平间距 ≥150px。字标仍刻意略小于参考图:参考图是整幅出血海报,而这里是一闪而过、盖在应用之上的遮罩。整块尺寸只由 --edge-word 一个变量控制(各行均为其比例)。

三处易错细节:

  1. 字标行 margin-left: -0.055em 抵消 Arial 左侧字身空隙,让字形墨边(而非字盒)落在节奏线上;
  2. line-height 取 0.80 而非 1.10——参考图的 1.10 是墨边间距,而 line-height 覆盖整个 em 盒(Arial-900 约为 cap 的 1.38 倍),直接写 1.10 会渲染成松散的 1.52;
  3. 品牌块不能加 max-width:各行均为 nowrap,宽度上限只会裁字而不换行;应改为移动 --edge-gap。

两个实测踩坑,都是「只看代码看不出来、只有量像素才发现」的:

  • 小字号必须有 px 下限。 各辅助行原先只写 em 比例,缩小整块后实测只剩 3px 高、峰值亮度 94 的灰糊——肉眼是一道模糊而非文字。现在统一改为 max(8~10px, …em);实测每行笔画分组数 16~37(模糊时仅个位数),确认为可读字形。
  • 标语用 Arial Narrow 压缩字体。 早前判断「Arial 下标语无法满足参考比例」只对了一半:探测渲染器后发现 Arial Narrow 确实可用(同一探测串 245px vs Arial 299px);在缺少该字体的机器上会回退到 Arial,因尺寸是比例值而非固定 px,仍然不会溢出。

进度轨几何同样为实测值:轨宽 10px、刻度 4×16px、数字 cap-height 28px、状态行 #666。

工程要点:

  • 进度由墙钟时间推导(非逐帧累加),不会漂移;
  • 双时钟驱动:requestAnimationFrame 负责跟随刷新率的平滑更新,setInterval 作为兜底——实测 rAF 在后台/被遮挡标签页与无头渲染器中会在首帧后停摆,仅靠 rAF 会让全屏遮罩永久留在屏幕上;
  • 收尾动画同样由 JS 驱动,不用 CSS transition。 这是实测结论而非偏好:最初「铺满 + 淡出」写成 transition: width …,在验证渲染器里完全不执行——transitionrun/transitionstart/transitionend 一个都不触发,width 过了时长仍停在 10px。做过对照实验(transition 写在状态选择器里 / 预先写在基础规则里,两种写法都不动),确认是渲染器不跑 transition,与写法无关。若照此发布,用户会看到左边一条 10px 黄条僵在原地。改为 JS 按墙钟时间逐帧写 width/opacity 后,实测同一渲染器下取到 17 个不同宽度、10px → 500px,并在真实速度截图中抓到中途帧(1184 宽画面上黄色已铺到 895px,整屏无缝隙、品牌块被完全覆盖);
  • 硬性保险丝:一个独立 setTimeout 终点(时长长于 进度 + 铺满 + 淡出),即使所有时钟停摆也必定移除遮罩,应用不会被永久遮住;该定时器不随 clearLoaderTimers() 清除,因为收尾阶段本身要调用它来停掉进度时钟;
  • prefers-reduced-motion:直接跳过铺满与淡出,立即移除遮罩;
  • pointer-events: none:即使动画进行中也不拦截点击,下层应用始终可用;
  • 全部字形由 CSS content 绘制(整块无任何 DOM 文本节点)+ translate="no"/notranslate/aria-hidden,防浏览器翻译改写品牌名;
  • 插件停止/卸载时,rAF、interval、timeout 与 DOM 节点全部随 ctx.effect 拆除(含动画播放中途卸载);
  • CSS 注释必须成对:一次误把 */ 提前收束,导致后续几行说明文字直接落进样式表,--edge-word 未定义、整个品牌块塌回左上角——node --check 查不出这类问题(文件照样能解析),故校验脚本专门检查「顶层是否漏进散文」;同理,CSS 模板字符串里不能出现反引号(写在注释里也会提前闭合模板串),校验脚本亦已覆盖。

回合状态标签「Deep diving...」

该标签由 @deepseek-ai/dsh-client-ui-conversation(类名 Md3f7G_turnStatus)绘制,是渐变文字而非普通着色文字:上游画了一层 linear-gradient 背景,再用 -webkit-text-fill-color: transparent + background-clip: text 把字「镂空」,并以 background-position 做流光动画。由此有两个结论:

  1. 写 color: 完全无效——透明文字填充优先,字仍由渐变决定;改色必须改渐变本身。
  2. 不能去动 --dsw-static-deepseek-500/200 这两个共享令牌。它们同时支撑 --dsw-alias-button-info-fill、--dsw-alias-state-business-primary 与 --dsw-specific-bubble-highlight(已在 dsh-client-ui-theme/styles/design-platform.css 中核对),本主题刻意把它们映射成墨/纸色。因此只覆盖 background-image,上游的 background-size、background-position 与流光动画保持不变。

配色是量出来的,不是挑出来的。 每个渐变色标都必须对该模式下两种可能底色(bg-base 与 bg-layer-1)都达到 WCAG AA 4.5:1——因为中间亮带会扫过字形,而在 prefers-reduced-motion 下上游把 background-size 钉成 100%,那条亮带会永久留在字里。实测:

颜色 亮色底 #e8e8e2 / #f2f2ec 暗色底 #101110 / #181a18
#fff500(直觉上的「改成黄色」) 1.02:1——完全不可见 15.26:1 ✓
#8f7c00 3.38 ✗ 4.21 ✗
#7d6c00 4.25 ✗ —
#6b5d00 5.35 ✓(亮色下第一个达标的金) —
#a08a00 — 5.11 ✓
#3f3600 9.82 ✓ —

因此流光在两种模式下都向暗处下沉,而非向亮处提亮:亮色底上没有比 #6b5d00 更亮的金能达标,而暗色底上「提亮」的浅色带会褪成近白、彻底失去黄意。亮色模式用深金而非信号黄,与水印/进度轨同理——在米色纸底上,#fff500 不是一种配色选择,而是一次抹除。

一个方法论提醒:视觉模型的文字描述不能作为颜色结论的依据。 期间它曾断言某候选在亮色面板下「金色更亮」,而两个候选的亮色值完全相同;靠逐像素取色才纠正。同样,第一版取色脚本误测到灰色的计时数字而非标签本身(计时器有自己的不透明颜色,在亮底上比浅黄更「显眼」),改为量「无计时器」状态才得到正确数据。

背景水印与「水印保持显示」

水印默认只在新建会话页(hero)显示,居中跟随标题。开启「水印保持显示」后,对话页等非新建会话页面也会显示水印:

  • 水印挂载在会话列内部,以 z-index: -1 位于正文之下(该列在水印挂载期间获得 isolation: isolate 与 position: relative,卸载后自动还原为 static / auto);
  • pointer-events: none,不拦截点击与文本选择;
  • 非 hero 页透明度为 0.16(hero 页 0.13)。该值经真实页面实测标定:0.07 在深色下合成为 #202120(对 #101110 仅 16/255,约 1.17:1)几乎不可见;0.22 虽清晰但大字母边缘会与正文视觉打架;0.16 约为深色 1.54:1 / 浅色 1.40:1。

该开关需先开启「背景水印」;未开启时按钮为禁用态。

提问卡片:「推荐」徽标与选项编号

提问卡片(@deepseek-ai/dsh-client-ui-user-questions)里有两处「字和自己的底色同色」,都是实测量像素才发现的:

  • 「推荐」徽标在亮/暗两种模式下都完全不可见。 上游把 --dsw-alias-button-info-fill 当前景色用(color),底色用 --dsw-specific-sidebar-nav-item-active-accent;而本主题为了中和残留蓝色,把这两个令牌映射成了同一个值(亮 #101110 / 暗 #fff500),于是标签把自己画在自己的底色上。实测「有文字 / 无文字」两版渲染逐像素差为 0——DOM 里有字,画面上一个像素都没有。修复不去动这两个令牌(它们在别处确实被当作背景填充使用),而是只在选项行内把这对前景/背景显式钉死。
  • 选项编号在暗色选中行上是黑底黑字。 既有的暗色选中行反色规则只把后代文字改黑,改不到后代自己的背景,所以编号仍保留 --dsw-alias-bg-overlay(#1c1e1c)的底色,实测对比度 1.25:1,编号消失。改为给编号加一层半透明墨色淡底(而非填死),让数字落在黄底上仍读得出,同时保留「小方块」的形态。

实测对照(逐像素,差异像素数 为「有文字」与「无文字」两版渲染之差,0 即完全不可见):

用例 修复前 修复后
「推荐」徽标 · 暗色 · 普通行 0 px(不可见) 1275 px,16.50:1
「推荐」徽标 · 亮色 · 普通行 0 px(不可见) 1275 px,16.50:1
「推荐」徽标 · 暗色 · 选中行 1274 px,18.31:1 1296 px,16.50:1(反色保边)
选项编号 · 暗色 · 选中行 207 px,1.25:1 225 px,11.69:1
选项编号 · 暗色 · 普通行 — 230 px,4.98:1(未回归)
选项编号 · 亮色 · 选中行 — 230 px,7.73:1(未回归)

两个验证方法上的坑,记下来免得重犯:

  • 不能靠「猜矩形 + 取色」判断可见性。 必须渲染「有文字 / 无文字」两版再做差:类名、层叠、几何完全相同,唯一变量是文字内容,差异像素数即字形本身。
  • 给徽标做差时必须保留一个零宽空格(\200B)。 inline-block 里没有任何在流内容时高度会塌成 0(line-height 只作用于由内容产生的行盒),空文字那版会连背景都不画,差出来的是背景而不是字形——第一次就是这样量出「假可见」的。
  • :hover 用同权重的类替换来验证。 截图无法触发 :hover,而主题里已有一条 [class*='badge' i]:hover{color:#000};把 :hover 换成 .HOVERPROBE(类与伪类特异度同为 0,1,0,层叠结果不变)后实测:暗色选中行悬停时徽标为 #fff500 on #101110(16.50:1),没有被旧规则改成黑底黑字。

防浏览器误翻译

水印是品牌名,不应被 Chrome/Edge「翻译此页」、Google 翻译挂件或翻译插件改写。采取结构性 + 声明式双重防护:

  • 结构性(主要手段):字形由 CSS content(::before)绘制,元素本身没有任何 DOM 文本节点(实测 textContent.length === 0、childNodes === 0),逐文本节点遍历的翻译器根本看不到它;
  • 声明式:translate="no"(HTML5 标准 opt-out,Chrome/Edge 遵循)、class="notranslate"(Google 翻译自有钩子)、lang="en"(避免被判定为中文正文);
  • aria-hidden="true":纯装饰元素不进入无障碍树。

实测:模拟翻译器改写会话列内 781 个文本节点后,水印内被改写的节点数为 0,字形仍为 ENDFIELD。

安装

作为 DSH 插件(推荐)

dsh plugin --profile web add github:ymh0000123/dsh-theme-endfield

dsh plugin 会转发给 profile 目录的 pnpm 完成安装,并根据包内的 cordis.patch.yml(dsh.bundle.patch)自动把插件行挂进 bundle 栈,同时把 exports["./client"](client.js)登记为浏览器端 client bundle。安装后重启(或重新加载)web profile 即生效。

本主题是纯 Client 半部插件:Host 半部(index.js)为空实现,全部效果由浏览器端的 token 覆盖 + 样式注入完成。

作为动态 Cordis 插件(临时试用)

  1. 打开 client.js,复制 apply(ctx) { ... } 函数体;
  2. 在 DSH 会话中用 cordis_define 新建插件,将函数体粘贴为 Client 代码(return { apply(ctx) { ... } }), 在 cordis_run 中激活该 Package;
  3. 刷新页面即生效;在 Run 卡片上停止插件即可完全卸载(token 层与样式层自动拆除)。

提示:client.js 依赖 DSH Client 运行时提供的 theme 服务、styles 内建与 ctx.effect,仅在 DSH Web 环境中可用,不能直接在普通浏览器中运行。

卸载

dsh plugin --profile web rm dsh-theme-endfield

使用

以动态 Cordis 插件的 Client 代码加载 client.js 的内容(apply 返回 Cordis Plugin),激活后刷新页面即生效;停止插件会自动拆除全部样式副作用。

特性清单

  • 终末地官网色板(亮/暗)
  • 信号黄 ::selection、光标、焦点环
  • 全局直角化
  • 中和残留蓝色(状态点、气泡、信息按钮、侧栏激活项、偏蓝文字)
  • 新建会话页背景光晕改信号黄(应用原本是 SVG 属性写死的 #6187D8,不走 token;亮 8% / 暗 5% 按亮度实测对齐原光晕强度)
  • hover 文字反色
  • 表格行悬停实心黄底黑字
  • 新建会话按钮黄底黑字
  • Cordis 操作按钮(run/stop/approve)黄化
  • 会话头部动作(agent preset 徽标 / 子代理 / 任务)黄化
  • 背景 ENDFIELD 水印(hero 页跟随标题居中)
  • 水印保持显示开关(非新建会话页面亦显示,置于正文之下)
  • Cordis 审批按钮图标与自身底色对比(黄底黑勾 / 红底白叉)
  • 提问卡片(ask_user_question)「推荐」徽标与选项编号可见(见下)
  • 启动加载动画(左侧黄色进度轨 + 百分比 + ENDFIELD 字标,默认关闭,可预览)
  • 加载屏海报式排版(END/FIELD 双行堆叠 + 品牌块居右 + 统一左侧节奏线)
  • 读数跟随进度轨填充端下移(含下边界钳制,接近 100% 不出屏)
  • 收尾动画:黄色向右铺满整屏 → 整体淡出移除(JS 驱动,不依赖 CSS transition)
  • 回合状态标签「Deep diving...」改信号黄/深金(渐变文字,每个色标均实测达 AA,见上)

校验脚本

样式表是一整个 JavaScript 模板字符串,因此有几类改动会在「文件仍能解析」的情况下悄悄破坏效果。这些不变量已固化为脚本,而非依赖人工小心:

node check.js      # 检查 client.js 的样式表不变量
node selftest.js   # 反过来验证 check.js 真的能抓到那些 bug

check.js 检查项:

  • 模板字符串内无反引号(写在 CSS 注释里也会提前闭合,导致整个 client bundle 解析失败);
  • 无 ${...}(在模板字符串里那是插值,不是 CSS);
  • CSS 注释成对、花括号配平(花括号在剥离注释后再统计);
  • 顶层没有漏进散文——这是抓「注释提前闭合」的那一项:注释提前闭合后注释本身仍是配平的,真正的破坏是残留文字落到顶层、与下一条选择器黏在一起,从而整条规则被丢弃;
  • --edge-word / --edge-gap 在实际生效的 CSS 里有定义(注释里提到不算);
  • client.js 能编译(用 vm.Script 在进程内解析、不执行;避免 node --check 子进程在沙箱下的 stdio 限制);
  • 回合状态标签仍通过 background-image 改色(写成 color: 对渐变文字无效,属于「改了但没生效」的静默失败)。

selftest.js 会把上述每个真实 bug 注入 client.js 的副本并断言 check.js 确实失败——包括断言注入本身生效,避免「测试其实什么都没改」的空跑。一个从未被观察到失败过的校验,不能算证据。

顺带一个实测教训:「顶层漏进散文」的第一版实现用「含逗号或英文单词」做判据,在合法选择器上产生了 33 个误报(:is([role='tab'], …)、input, textarea、tbody tr:hover)。可靠信号窄得多:CSS 选择器里不会出现跟在字母后的句点+空格,而散文会。

许可证

MIT

—/ 5

暂无评分

已验证 DSH bundle

Commit 48ad12921bd6

社区评论

还没有评论,来写第一条。

DSH HUB

社区维护的 DSH 插件索引。不是 GitHub 或 DeepSeek AI 的官方产品。

社区资源API关于