renjie2026/dsh-theme-gallery

dsh-theme-gallery

DeepSeek Harness 桌面版主题皮肤画廊插件 —— 一个插件管全部皮肤(JSON 数据驱动,内置 山青婷彩 / 梦海游鱼),npm/tarball 安装零构建授权 | A community theme gallery plugin for DeepSeek Harness: JSON-defined skins with full-screen coverage

Uncategorizeddeepseekdeepseek-harnessdsh

给 DeepSeek Harness 的主题画廊:一个插件 + 一堆 JSON 皮肤。装一次,拿到全部主题;加皮肤不用改代码、不用重启、不用重新装包。

你想要怎么做
直接用别人做好的皮肤装上插件,在设置里点选
自己做皮肤(或让 AI 做)在 lib/themes/ 加 JSON 后重跑 npm run embed-themes,或装 dsh-theme-skin-author 技能让 AI 生成
贡献一个皮肤给所有人在 lib/themes/ 放一个 JSON,提 PR

已随 0.8.3 发布 12 套皮肤:六套复刻自蜂链商城电商新零售系统管理后台 (renjie2026/fenglianshop-open 的 admin-modular/src/utils/themes.js),两套是本插件原创的宠物主题(同一套造色方法,色相取自中国传统色库), 一套是**「纯色/拼色」配色选择器卡片(15 个可点色值,见下), 还有三套深色主题**——大鲸鱼娘(社区同人立绘 · 深海夜航,见 出处与致谢)与 **青玉凤剑 / 青玉凤剑(带壁纸)**两套全屏武器主题(原创,同一套双剑素材 + 气焰特效的两个独立主题位,后者带国风背景壁纸)。

id名称主色强调色
shan-qing-ting-cai山青婷彩#2F7D5E 青山绿#E88BB0 蜻蜓粉
meng-hai-you-yu梦海游鱼#177CB0 靛青#FFD166 琥珀金
jiang-pan-dong-yun江畔冬云#3A556B 冬云青灰(按钮/边框族)#F2C879 冬云暖金
ying-mu-cai-yun营慕彩云#2D5A3D 林间深绿#FFB347 琥珀
pei-an-jie-xin佩安杰心#7A5C3E 暖檀褐#B4653A 赭陶
xu-shan-jun-yue徐山军月(复刻)#2C3B2E 夜山松绿(按钮/边框族)#D4B266 军月金
hu-po-mao-mi琥珀猫咪(原创)#9C5F24 琥珀深焙(按钮/边框族)#CA6924 琥珀(中国传统色)
hu-zi-a-huang虎子阿黄(原创)#896C39 秋色(按钮/边框族)#F0C239 缃色(中国传统色)
shi-liu-jin纯色/拼色(配色选择器)#F20C00 石榴红(默认那套「石榴金」)#9D2933 胭脂(按钮族)
da-jing-yu-niang大鲸鱼娘(社区同人立绘)#061320 深海夜蓝(半透明壁纸底)#5FD9F5 鲸鳍水青
longyan-baojian青玉凤剑(原创·全屏武器)#0E1822 深夜青碧(半透明渐变底)#E8C25A 金凤金
longyan-baojian-2青玉凤剑(带壁纸)(原创·全屏武器)#0E1822 深夜青碧(国风壁纸衬底)#E8C25A 金凤金

面板里另有两张内置外观卡(浅色 / 深色)、一张宠物挂件卡(宠物挂件 · 七只小伙伴)、 一张心情问候卡(心情问候)和一张菜单折叠卡(菜单折叠):它们都不是皮肤, 所以不计入上面这 12 套。 内置卡把配色切回官方的浅色 / 深色(与「设置 → 通用 → 外观」同一套),我们在官方浅色/深色上加了一点小惊喜 —— 见 效果预览 最后一行。官方外观里的「跟随系统」不出卡:它就是浅色/深色二选一, 再占一张卡只是重复。宠物挂件卡则完全不碰主题:点头像换宠物、点卡身开关挂件, 与任何皮肤都能同时开启(见 宠物挂件)。 心情问候卡同样不碰主题:它控制标题栏上一条滚动的问候语,默认开启、35 分钟换一条, 可调速度 / 方向 / 位置区域(见 心情问候语)。 菜单折叠卡也不碰主题:开启后侧栏不再显示入口,设置页里留一个轻量一键入口 (打开面板 / 恢复侧栏),默认关闭(见 菜单折叠)。

工作区里另有四套皮肤仍在打磨,尚未发布:光彩凤晨 guang-cai-feng-chen(复刻); 取意古风歌曲《白羽行》的两套原创——流星白羽 liu-xing-bai-yu、姑苏繁花 gu-su-fan-hua; 以及青冥飞剑 qing-ming-fei-jian(原创,全屏三剑编队入场 + 悬停自旋 + 聊天区宝剑壁纸,已实机验收)。

⚠️ 深色皮肤有 大鲸鱼娘 与 青玉凤剑 两套(2026-10-01 起青玉凤剑同为 colorScheme dark、 102 token 深色形态):外壳里「规划卡片 / 交付物 / 变更 / JSON 树 / 思考区」几处用的是 只在外观偏好为深色时才切深色底的组件级常量(--plan-card-fill = --dsw-static-neutral-50 #f9fafb, 声明在卡片元素自身,皮肤令牌层盖不到)。把「设置 → 通用 → 外观」设为深色,这些面板才是深色卡片 (实测:浅色偏好下正文压在那张 #f9fafb 卡片上只有 1.08:1;深色偏好下走 #2c2c2e → 12.37:1)。 🐋 大鲸鱼娘的入场特效:选中这套皮肤时,她会从窗口右上角的画面之外俯冲进来、 向左下横扫过整个工作区,再在主区绕一个完整的大圈(经过收口处的闭合环), 最后落到她那个站位上(约 1.8 秒,落点带一点过冲再回弹; 身后拖一串水泡、落地时一圈很淡的水花), 停在最前方——正文之上——约 1.2 秒(她完全清晰);约 3 秒时交叉淡入淡出(约 0.45 秒) 转成背景壁纸:立绘搬到 body 级、独立层上,一张伴生样式表(与壁纸层同生共死) 把应用表面变成半透明,于是正文压在她上面(左侧压暗、右下留亮)。 ⚠️ 这一层用层序而不是负 z-index 实现(2026-09-30 实测修正):壁纸层 z-index:0、 应用内容 #root 抬到 1、装饰层维持 60 —— 负 z-index 会被压在画布底色之下, 实机现象就是"3 秒后完全看不见她"(且没有任何异常)。 切到别的皮肤再切回来会整套重播;系统开启「减少动效」时跳过飞入与交叉、直接呈现壁纸态 (不等待,人物照常显示);config: { ambient: false } 急停时立绘层、伴生样式表与标记类一起撤掉。 (发布前自检会核对这份清单:README 里的每个 id 都要真实存在, lib/themes 里的每套皮肤也必须在这里被提到。)

每个皮肤 67 个 token,覆盖整屏。

效果预览

青玉凤剑 longyan-baojian(原创)青玉凤剑(带壁纸) longyan-baojian-2(原创)
青玉凤剑:深夜青碧的工作区,青玉凤纹与银鎏金双剑悬空交叠、青焰金火缭绕,侧栏火屑升腾青玉凤剑(带壁纸):白龙与唐装执剑少女的国风壁纸衬底,整剑悬于其上、金凤青焰沿剑身直达剑尖
大鲸鱼娘 da-jing-yu-niang(社区同人立绘)
大鲸鱼娘:深海夜航的整屏深蓝,鲸鱼娘落定在右上角的「深海小窗」里,气泡自侧栏升起
山青婷彩 shan-qing-ting-cai梦海游鱼 meng-hai-you-yu
山青婷彩:青山两层、云雾、蜻蜓与落花,侧栏水塘收底梦海游鱼:左上柔光辉、上浮气泡与光点、蓝色小鱼、水草与水底渐变
营慕彩云 ying-mu-cai-yun佩安杰心 pei-an-jie-xin
营慕彩云:暮色暖光、三层彩云与前后两层漂移云海,两只热气球往返漫游佩安杰心:雾山远衬、禅意圆相与坐禅人影、香炉两缕青烟与浮尘,底部禅语
琥珀猫咪 hu-po-mao-mi(原创)虎子阿黄 hu-zi-a-huang(原创)
琥珀猫咪:暖阳光晕与晒暖窗台,坐姿虎斑猫摆尾抖耳,蜷卧酣睡猫呼吸起伏并冒小 z,阳光浮尘虎子阿黄:金色光晕与田埂干草丛,中黄田园犬镰刀尾摇摆、歪头、挂着铃铛项圈,缃色皮球与蒲公英绒毛

江畔冬云 jiang-pan-dong-yun(0.7.0 新增)的实机截图下次更新补上:冬云低垂、江畔泛舟, 侧栏是灰蓝江天与层叠冬云。它自 0.7.0 起已在包里,装最新版即可直接用。

内置浅色 / 深色 + 皮肤素材 —— 那个小惊喜

内置「浅色」+ 山青婷彩的侧栏素材内置「深色」+ 营慕彩云的侧栏素材
内置浅色外观:调色回到官方浅色,而侧栏仍留着山青婷彩的山峦、水塘与蜻蜓内置深色外观:调色回到官方深色,而侧栏仍留着营慕彩云的彩云与热气球

「纯色/拼色」卡片 —— 同一张卡、两套配色(点色格即时换色;卡片名旁边的「已应用」标出当前那套)

石榴金配色(默认)换点「松柏绿」那一格之后
纯色/拼色卡片 + 石榴金配色:侧栏与主区都是石榴红/赤金/翡翠那套暖调同一张卡片换成松柏绿配色:整屏转为松柏叶的墨绿调

玩法:先点一套皮肤,再点「浅色」或「深色」 —— 调色回到官方外观,而侧栏素材留在原处 (切到另一套皮肤时素材会正常替换;重启应用后不会有残留,因为那时的页面上本来就没有"上一套"可留)。

截图取自桌面版 0.1.7-rc.2 实机。图片用绝对地址引用而不是相对路径,是为了让同一份 README 在 GitHub、npm 与社区市场三处都能显示(npm 不会把相对路径解析到仓库)。原图在 screenshots/ 下,不在 npm 包内(package.json 的 files 白名单只含运行必需文件)。

侧栏装饰还可以先看后装:仓库内的 tools/theme-bench/ambient-preview.html 以宽窄两种侧栏宽度 并排渲染全部皮肤(该页把 CSS 与场景标记直接读自 lib/client.js,不会与出货版本漂移); tools/theme-bench/panel-preview.html 则渲染面板本身的卡片顺序与文案 —— 顺序表、内置卡文案、页面样式同样直接读自 lib/client.js。


为什么是「一个插件 + 数据」,而不是「一个皮肤一个插件」

这是本项目唯一重要的架构决定,结论是前者:

维度一个插件 + N 个皮肤数据每个皮肤一个插件
用户装一个皮肤不用动,设置里直接就出现要再装一个包
设置里的选择器一行列出全部每个插件各自注册一行,UI 抢位
作者加皮肤改一个 JSON新建仓库 + 发 npm + 绑版本
加载开销一个插件一行N 个插件 N 行
升级一个包对一个 DSH 版本N 个包各自绑版本,升级全炸

判断准则:有运行时逻辑 / 服务 / Hook → 独立插件;只是数据 / 配色 → 数据文件。

皮肤是纯数据,所以走后者。这也正是官方 ctx.theme 的设计意图——官方 README 原话:"registering one means overriding same-named alias variables"。


为什么官方「设置 → 通用 → 外观」看不到这些皮肤

官方那一行的选项是写死的常量数组:

// 官方源码 packages/client/ui-theme/src/client/AppearanceRow.tsx
const CUBES = [light, dark, system]

它渲染 CUBES.map(...),从不读取主题注册表。官方 README 也说得很直白:"Third-party themes are an extension point, not a product"。

所以本插件自带入口。


入口在哪:左侧菜单区【插件】图标的下方,不是设置

位置官方插槽形态
本插件用这个sidebar.panellist + main(keyed,同一个 id)左栏一个图标 → 主区一整页主题卡片
备选(未用)sidebar.footer.action齿轮旁的小图标 + 弹出气泡
备选(未用)settings.general.item设置里一行按钮

选第一个的理由不只是位置好:它正是这个应用的"插件"机制——一个插件 = 侧栏一个入口 + 主区一个页面,和 Plugins 页同级。

而且侧栏入口是 list 插槽,一个插件最多占一个座位:这从机制上就否定了"每个皮肤一个插件"。

sidebar.footer.action 同样是 list,一个插件也只有一个座位,且气泡里放不下预览。设置行则额外需要 settings 域——见下面的踩坑记录。

打开方式:在左侧菜单区,【插件】图标的下方点 主题皮肤(它与「插件」同为面板入口,就在其下一行), 主区显示全部可选主题,点卡片切换,选中态会记入设置。


安装

三种安装方式

① 用包名安装(推荐) —— 包已发布到 npm:https://www.npmjs.com/package/dsh-theme-gallery

  1. 设置 → 插件 → 添加插件 → 填 dsh-theme-gallery
  2. 重启应用
  3. 左侧菜单区【插件】图标的下方出现 主题皮肤 入口(不在「设置 → 通用 → 外观」里, 原因见下文),面板里是 12 套皮肤 + 内置浅色/深色两张卡(清单见页面顶部表格)

Web / CLI profile 用官方 CLI 装同一个包:

dsh plugin --profile web add dsh-theme-gallery

桌面版的 profile 由 Electron 独占,dsh plugin --profile desktop … 会被拒绝 —— 桌面用户请走上面的界面。

⚠️ 刚发版就想装最新版? DSH 桌面版内置的 pnpm 11 默认带「新版本约 24 小时冷却」的供应链保护: 发布后一天内按包名安装或重装,会静默装到上一版(不报错,不是发版失败,与安装源无关)。 想立即装到刚发布的新版,把包名连版本号一起填(例如新发布的是 0.9.0,就填 dsh-theme-gallery@0.9.0,实测可行), 或等约 24 小时后正常安装。

② 下载构建产物(不经过 npm 的等价方式,零构建授权)

  1. 到 Releases 下载 dsh-theme-gallery-<版本>.tgz
  2. 设置 → 插件 → 添加插件 → 粘贴该文件的完整路径
  3. 重启应用

③ 用仓库地址安装(github:renjie2026/dsh-theme-gallery,拉的是源码,不推荐)

只在你想跟源码时用它。本包没有构建步骤,所以不会出现"缺 lib/ 目录"那类失败; 它的代价是 pnpm 可能要求你为构建脚本授权(allowBuilds)。

更新到新版本

先说清楚:DSH 桌面版本身不会提示第三方插件有更新,所以「发现新版」和「执行更新」这两件事得靠下面的渠道。

怎么知道有新版本?

渠道说明
插件市场装 DSH-Plugins-Marketplace 后,卡片会显示 「已装 v0.2.0 → v0.3.0」 并给更新按钮 —— 目前最省事的路径
GitHub Releases在本仓库点 Watch → Custom → Releases only,有新版本会收到邮件
对照版本号插件面板右上角显示你装的版本(如 v0.3.0),与 npm 页面 上的版本号直接对照

怎么更新?

  1. 设置 → 插件 → 添加插件 → 再填一次 dsh-theme-gallery → 重启(装上 ^x.y.z 范围内的最新版)
  2. 想要强制拿最新(含 0.2.x → 0.3.0 这类次版本号变更):先移除、再添加
  3. 装了市场的:点卡片上的更新按钮
  4. Web / CLI profile:dsh plugin --profile web add dsh-theme-gallery

版本范围语义:安装时会记录成 ^0.2.0,即 >=0.2.0 <0.3.0 —— 0.2.1 这类补丁会在重装时自动带上;0.3.0 不会(npm 对 0.x 的惯例是 把次版本号变更视为可能破坏性),那种情况按第 2 条显式重装即可。

⚠️ 从 Release 的 .tgz 安装的用户没有更新机制(tgz 是一次性快照,只能重新下载)—— 想长期跟更新,建议用包名安装。

兼容性与权限

项说明
平台DeepSeek Harness 桌面版 0.1.7-rc.2(实测通过);同为 web 客户端的 Web / CLI profile 理论可用,但本项目只实测过桌面版
网络不联网 —— 插件半侧不发起任何请求
文件包内只有 lib/、schema/、cordis.patch.yml(见 package.json 的 files),不读写用户文件
界面改动只新增左侧菜单区一个面板入口(在【插件】图标下方);官方「设置 → 通用 → 外观」那一行保持原样——面板里的浅色/深色卡只是调用官方偏好接口,不会往那一行塞任何东西
本地状态皮肤选择存在 localStorage;主题偏好只写 light/dark/system

装不上或想手动装

桌面 profile 由 Electron 独占,CLI 会被拒绝:

error: profile "desktop" is managed exclusively by the Electron application

那就手动改 profile 清单(这是官方 profile 的既定机制,不是 hack):

// <DSH_HOME>/profiles/desktop/package.json
//   "dependencies":        { "dsh-theme-gallery": "^0.3.0" }
//   "dsh.profile.bundles": [ ..., "dsh-theme-gallery" ]
cd <DSH_HOME>/profiles/desktop && pnpm install

Windows 上 <DSH_HOME> 默认是 C:\Users\<你>\.dsh。

然后重启。


卸载与回滚

主题插件最坏的情况是界面进不去。以下四招按"由轻到重"排列,都不需要重装应用。

① 只停装饰与自动恢复,保留插件(最轻)

插件的两个活动层可以用一个配置开关整体停掉,不必卸载。编辑 profile 自己的 cordis.patch.yml(位置:<DSH_HOME>/profiles/desktop/cordis.patch.yml),加:

- id: theme-gallery
  name: dsh-theme-gallery
  config:
    ambient: false      # 停掉氛围装饰层与皮肤恢复层

为什么需要这一招:dsh.profile.bundles 不是手写清单 —— 每次插件安装 / 启用 / 优化后,应用都会按 dependencies 里声明了 dsh.bundle.patch 的包自动推导重建它。 所以把一个包从 bundles 里删掉不能持久,会被写回来。上面的开关是插件侧的刹车。

② 从应用里卸载

设置 → 插件 里移除本插件,然后重启。这是最干净的做法。

③ 手动从 profile 卸掉

// <DSH_HOME>/profiles/desktop/package.json
//   删掉 dependencies 里的 "dsh-theme-gallery"
//   删掉 dsh.profile.bundles 里的 "dsh-theme-gallery"
cd <DSH_HOME>/profiles/desktop && pnpm install

重启。

④ 界面完全起不来时:把偏好改回内置值

这是最可能的"起不来"原因,而且它完全是你自己写的配置造成的。

皮肤 id 绝不能写进主题偏好。ui-theme.config.preference 只接受 light / dark / system:

# <DSH_HOME>/profiles/desktop/cordis.patch.yml
ui-theme:
  config:
    preference: light      # 只能是 light | dark | system

写成皮肤 id(如 shan-qing-ting-cai)时,buildSnapshot() 会抛 theme registry lost 并拒绝启动 —— 因为偏好指向一个(当时)还没注册的主题。

皮肤的当前选择存在 localStorage 里,不在 preference 里。 这是刻意设计: 偏好是启动期读取的,而皮肤要等插件加载后才注册,两者天然有先后。

还有一招:拿一份干净的 profile 快照

<DSH_HOME>/profiles/desktop/ 整个目录可以先复制一份再改。出问题时把 package.json 与 cordis.patch.yml 换回去即可。改之前备份是最省事的保险。


疑难排障

应用弹「无法使用」并给出「禁用第三方插件」出口

DSH 有启动保护。先用它进去,再按上面的「卸载与回滚」处理。

启动挂起、日志里什么都没有

怀疑 fiber pending,去查 inject 与循环等待;不要去看模型或网络配置。

crash-*-web-boot.log(%APPDATA%\@deepseek-ai\dsh-desktop\logs\)里 一条记录都没有,而应用卡在 "Loading plugins..." —— 这就是 pending fiber 的指纹。

历史上撞过三次,都源自 inject:

版本错误结果
第一版把 settingsScope 写成硬依赖dsh-theme-gallery: pending (waiting for service: settingsScope)
第二版以为 immediately: true 能解决无效,是错的根因判断
第三版声明的模块没在 dsh.client.inject 里完全没有任何日志

Cordis 的 inject 有两种形态:

inject: ['a', 'b']            // 数组 —— 每一项都是【必需】
inject: { a: cfg, b: null }   // 映射 —— null 标记该项可选

用数组形态时,拿不到的服务会让 fiber 永远停在 pending,而未激活的 entry 会让整个 web boot 失败。

教训:把自己无法控制的服务写成硬依赖,等于给了它一票否决应用启动的权力。

当前状态:exports.inject = ['slots', 'locale', 'theme'] —— 三者都由静态编入的 UI 包提供,保证存在。另外 package.json 的 dsh.client.inject 声明了提供主题服务的 模块,用来固定加载顺序(漏掉它时不产生任何日志,最难查)。

回归测试锁住了这件事(tests/smoke-host.mjs、tests/check-boot-safety.mjs)。

启动保护弹窗(比手改更快)

DSH 有启动保护,弹窗给两个出口:

  1. 「禁用第三方插件、备份 profile patch 并重启」 —— 先用这个进去。 注意它会重置 profile 的 cordis.patch.yml,所以恢复后要检查 <DSH_HOME>/profiles/desktop/cordis.patch.yml 是否需要补回偏好设置。
  2. 退出 / 重启

崩溃详情在:

%APPDATA%\@deepseek-ai\dsh-desktop\logs\crash-*-web-boot.log

日志会逐条列出 pending 的 entry 和它等待的服务名——排查启动问题最快的信息源。

但注意:本插件遇到过一种完全不写日志的启动失败(dsh.client.inject 漏声明), 所以"日志是空的"不能排除插件问题。详见上一节。

⚠️ 桌面版不读 $DSH_HOME/settings.yaml

这一点与官方文档的默认值相反,值得单独记住:dsh-base 与 dsh-web-app 两个 bundle 都把设置文件 provider 配成了内存模式——

- name: '@deepseek-ai/dsh-settings-file'
  path: ':memory:'

所以桌面版里手写 settings.yaml 不生效;应用启动时会把这类文件归档成 settings.yaml.imported,然后继续使用内存状态。控制皮肤选择的权威位置是组合层——profile 的 cordis.patch.yml:

- id: ui-theme
  name: "@deepseek-ai/dsh-client-ui-theme"
  config:
    preference: shan-qing-ting-cai

或者,等插件加载成功后直接用设置界面点选。

(theme-gallery 段仍可写在 settings.yaml 里,但需要 profile 换成文件型 provider;桌面版目前走内存,所以加自定义皮肤请改 lib/themes/*.json 后重跑 npm run embed-themes。)

首次启动的顺序注意

首次启动前,cordis.patch.yml 里的偏好先留内置值(dark / light / system)。因为 ui-theme 的 buildSnapshot 在偏好指向未注册 id 时会抛错(官方源码里是明确的 throw,不在 try/catch 内):

if (active === void 0) throw new Error(`theme registry lost "${resolvedId}"`)

而 shan-qing-ting-cai 要等本插件的浏览器半侧注册完才存在。确认插件加载成功后,再把偏好改成皮肤 id。


两种状态:整屏铺满 / 阅读时变浅

皮肤的价值是整屏覆盖;而整屏覆盖正是长对话难读的原因。所以界面被分成两种状态:

侧栏素材与激活标记(region 1 复刻)

皮肤不只是配色,还把原系统左侧菜单区的元素素材复刻了过来,并给"正在使用"的状态加了标记色。

侧栏氛围装饰 ambient

皮肤素材
山青婷彩 kind: "shan"青山两层 + 山间云雾 + 山脚水面与点水涟漪 + 两只悬停蜻蜓 + 花瓣飘落
梦海游鱼 kind: "dream"左上柔光辉 + 两道弥散光洗 + 上浮气泡 + 五叶水草摇摆
营慕彩云 kind: "caiyun"暮色暖光 + 暖金光点 + 三层模糊彩云 + 前后两层漂移云海 + 两只往返漫游的热气球
佩安杰心 kind: "jiexin"雾山远衬 + 禅意圆相与坐禅人影 + 香炉两缕青烟 + 浮尘光点 + 禅语「自在 · 安顿」
琥珀猫咪 kind: "humao"(原创)暖阳光晕 + 晒暖窗台 + 坐姿虎斑猫(摆尾 / 抖耳)+ 蜷卧酣睡猫(呼吸起伏 + 小 z)+ 阳光浮尘
虎子阿黄 kind: "ahuang"(原创)金色光晕 + 田埂 + 中黄田园犬(镰刀尾摇摆 / 歪头 / 铃铛项圈)+ 干草丛 + 缃色皮球 + 蒲公英绒毛
大鲸鱼娘 kind: "jingyu"(社区同人立绘)入场特效——自窗口右上角画面外俯冲进来、向左下横扫整个工作区、绕一个完整的大圈后落定(身后拖一串水泡、落点一圈很淡的水花),约 3 秒时交叉淡入淡出转成背景壁纸态(右上「深海小窗」立绘 + 半透明应用表面);侧栏另有上浮气泡(7 枚)与两只幼鲸
流星白羽 kind: "liuxing"(原创,尚未发布)弦月金辉 + 白羽流星低频掠过 + 雁阵缓渡 + 蒹葭摇曳 + 白露霜星 + 远山淡影
姑苏繁花 kind: "fanhua"(原创,尚未发布)垂柳丝绦 + 桃花枝 + 落英缤纷 + 春水涟漪 + 飞燕横渡 + 罨画远山
青冥飞剑 kind: "feijian"(原创,尚未发布)悬停剑落定后绕剑柄—剑尖轴缓缓自旋(呼吸荧光晕 + 世界坐标剑穗 + 荧光微尘);另有全屏部分——三剑编队沿用户红笔图的双环轨迹入场(主剑 + 两把伴飞小剑,尾翼=青白主痕/樱粉副痕/残影箭羽/迸散火花,挂在 .dsh-amb-control 全视口层、场景盒之外)+ 四周剑光角饰框;聊天文字区另有宝剑壁纸(body 级 z-index:-2 独立层里的横放古剑,飞剑落定后淡入,正文压在剑上)
青玉凤剑 kind: "longyan"(原创;显示名 2026-10-01 由龙焰宝剑改来)全屏双剑悬空(青玉凤纹系 + 银鎏金流光系两柄透明底古剑,交叠摆位各自缓浮)+ 四重气焰——呼吸辉光、剑刃焰舌、升腾火屑、扫刃辉光;素材带另有青焰辉光 + 能量丝 + 火屑。青焰 #3FE0BB × 鎏金 #E8C25A 的暗色新调色盘(102 token 深色形态);背景壁纸另立独立主题位
龙焰宝剑(显示名青玉凤剑(带壁纸))kind: "longyan2"(原创)青玉凤剑·整剑版 + 背景壁纸:同一套气焰与入场,A 剑为像素级合成的整剑(断剑延长,凤尾与青焰顺势向剑尖延伸),悬停露柄侧半截;聊天区背景壁纸 = 国风图(白龙+唐装执剑少女+金焰),显示管线照青冥壁纸(body 级背景层 + 可读性幕布 + 水印保底 + 双路半透明地面令牌);卡片序 76(2026-10-01 用户指定:77 与 75 之间)

素材逐像素复刻自源系统对应的主题动画组件(ShanQingTingCaiAnimation.vue、 DreamOceanAmbient.vue、YingMuCaiYunAnimation.vue、PeiAnJieXinAnimation.vue);humao / ahuang 两套为本插件原创绘制(同一条造色十步法,色相取自中国传统色库)。与原系统有意偏离两处:

  1. 尺寸改为百分比 / em。原系统写死 223px 侧栏宽;DSH 侧栏可拖拽,固定像素在窄侧栏会截断。
  2. pointer-events:none 且置于导航之下。原系统文档记有一条 bug:不透明山形贴在侧栏底部会遮挡最下方菜单项。

kind 是数据键而非素材路径——插件只为它真正画得出的场景提供键,写错会在构建期失败,而不是运行时静默不画。

装饰挂在 document.body 上的全屏 .dsh-amb-control 图层里,场景盒再按侧栏几何绝对定位在图层内部——图层与场景盒必须拆成两层,这是本项目花了二十多轮才找到的结论(压在一个元素上时两种形态都不绘制)。这是本插件唯一直接操作外壳 DOM 的地方(侧栏没有装饰插槽,插槽组件会成为列的兄弟而非其背后的图层),因此单独隔离、整体 try/catch:装饰是修饰,绝不能成为故障原因。侧栏定位用三级回退,因为外壳类名是 CSS-module 哈希、不是稳定契约。

先看效果再装:npm run preview:ambient 生成的预览页把 CSS 直接读自 lib/client.js,因此不会与出货版本漂移;两种侧栏宽度并排。

激活标记 accent

侧栏条目与选中对话行在 DSH 里共同读取 --dsw-alias-button-ghost-active-fill/-border/-hover,所以 accent 叠加到这三个 token 上,两者同时变成标记色。

取值遵循来源项目《主题皮肤设计规范(第二区域)》第 123 / 118 行:强调色取本皮肤第一区域的特征色,且禁止引入第一区域不存在的色相。所以

皮肤强调色出处
山青婷彩#E88BB0蜻蜓粉
梦海游鱼#FFD166夕照金
营慕彩云#FFB347云霞琥珀
佩安杰心#B4653A赭陶
琥珀猫咪(原创)#CA6924中国传统色「琥珀」
虎子阿黄(原创)#F0C239中国传统色「缃色」
流星白羽(原创,尚未发布)#F2BE45中国传统色「赤金」(弦月金辉——冷夜场景里唯一的暖色)
姑苏繁花(原创,尚未发布)#F47983中国传统色「桃红」(桃花正繁——暖忆场景里的花色即accent)
青冥飞剑(原创,尚未发布)#25C6D0剑光青(靛青 #177CB0 的荧光化提亮,自调——荧光感是这套皮肤的身份)
江畔冬云#F2C879冬云暖金
徐山军月#D4B266军月金
大鲸鱼娘(社区同人立绘)#5FD9F5鲸鳍水青(深海夜航里唯一的亮青,自调)
青玉凤剑 / 青玉凤剑(带壁纸)(原创)#E8C25A金凤金(鎏金凤纹——同一套双剑素材共用的强调色)

不是所有主题一律粉——那样恰好违反来源项目自己的规范。两条约束由代码强制:叠加只对活跃主题生效、切走即撤除;不动 brand-primary(否则链接、主按钮、状态徽标会被一起改掉)。

状态判定视觉
空对话态会话里还没有消息整屏铺满主题:左侧栏渐变 + Windows 顶部标题栏渐变 + 中间留白也是主题色
有对话态出现消息后正文套一层提亮卡片(默认 62% 不透明度 / 3px 模糊 / 640px 限宽),四周仍透出主题渐变;左侧栏与顶部保持主题强度,一眼可辨是哪个皮肤

配色选择器 card(纯色/拼色 一类)

到 0.3.0 为止,每张卡片都是一条 6px 色带,取色由代码从皮肤的 3 个 token 里挑 (brand-primary / label-secondary / state-business-primary),所以任何皮肤都不用额外写卡片信息。 一条色带只能表达"一套配色长什么样",而这一类卡片要表达的是**"这里有多少套配色,点哪个换哪个"**。

所以新增了可选字段 card.rows(不写它就还是那条色带,九套场景皮肤一个字都没改): 卡片上排 15 个可点的色值按钮,5 + 5 + 5:上两排是 10 个纯色方案,最后一排是 5 个拼色方案。

"card": {
  "rows": [
    { "kind": "solid", "schemes": ["p-xiang-se", "p-ju-huang", "p-tao-hong", "p-hai-tang-hong", "p-jiang-zi"] },
    { "kind": "solid", "schemes": ["p-song-bai-lu", "p-zhu-qing", "p-cang-qing", "p-dai-zi", "p-xuan-qing"] },
    { "kind": "clash", "schemes": ["p-shi-liu-jin", "p-bao-lan-jin", "p-qing-lian-jin", "p-song-hua-tao", "p-wu-jin"] }
  ]
}

15 套配色不是 15 个主题。 它们住在 lib/palette-schemes.json,由建期 内联进包里,但不注册进主题服务:所以官方「设置 → 通用 → 外观」的主题列表里不会多出 15 项, 面板头部的"N 款皮肤"也仍然是皮肤数。点一个按钮 = 把该方案的 token 层叠到整屏上, 所选方案记在 localStorage(theme-gallery:palette),绝不写进 ui-theme.preference。

规则为什么
2 或 3 排,最后一排必须是拼色拼色排在最下方才读得出层级;放别处只会像画错了
一排 1–5 个按钮,等宽5 个是卡片最小宽度(200px)下仍能读出 5 种颜色的上限,第 6 个只剩约 28px,会读成条纹
每个按钮按宽度分带:纯色格一条带占满;拼色格主色占 2 份、每个次色各占 1 份一眼看出"这一套谁占大头、旁边配了哪些色"。比值由数据算出来(一主一次 = 2/1、一主两次 = 2/1/1、一主四次 = 2/1/1/1/1),不是写死的;画法和点下去的效果取自同一张表,不可能对不上
每个次色相对主色的对比度 ≥ 2.5:1次色带在最窄的卡片上只有几像素宽,明度接近时整条糊进主色里,没有异常也没有日志。实测反面样本:碧色 #1BD1A5 上的红点 1.14:1、海棠红 #DB5A6B 上的竹青 1.07:1
深色正文压在方案底色上 ≥ 7:115 套方案只写三四个色,其余 60 多个 token 由 schemeTokens() 派生;底色与正文的对比度是整屏的阅读下限
按钮填充色按对比度选(本色 + 深色字 / 本色 + 白字 / 压深后用白字)缃色、橘黄、桃红这类亮色做填充时白字只有 1.7–3.7:1,读不清。规则逐个候选试,尽量让按钮留在色库那个名字色上;石榴金显式指定用「胭脂」#9D2933(白字 7.50:1)
15 套全部出自中国传统色库zerosoul/chinese-colors 的 src/assets/colors.json,每套都写明「组 + id」出处(见 source 字段)

15 套色值一览(主色 = 纯色格那一整条带 / 拼色格的第 1 条带;次色 = 拼色格其余各条带。 表由 lib/palette-schemes.json 直接生成,不手抄):

位置方案主色次色色库出处
纯色 1缃色#F0C239—黄 1-9 缃色(浅黄色)
纯色 2橘黄#FF8936—黄 1-5 橘黄(柑橘的黄色)
纯色 3桃红#F47983—红 0-3 桃红(桃花的颜色)
纯色 4海棠红#DB5A6B—红 0-4 海棠红(淡紫红色、较桃红色深一些)
纯色 5绛紫#8C4356—红 0-9 绛紫(紫中略带红的颜色)
纯色 6松柏绿#057748—绿 2-30 松花绿(松柏叶的墨绿)
纯色 7竹青#789262—绿 2-3 竹青(竹子的绿色)
纯色 8苍青#7397AB—苍 4-3 苍青
纯色 9黛紫#574266—蓝 3-12 黛紫(深紫色)
纯色 10玄青#3D3B4F—黑 7-1 玄青(深黑色)
拼色 1石榴金#F20C00#FFFFFF #D6ECF0 #EACD76 #3DE1AD红 0-5 石榴红 + 金银 8-0 赤金 + 绿 2-14 翡翠色;按钮族用红 0-11 胭脂(白字 7.50:1,而压在石榴红上只有 4.35:1)
拼色 2宝蓝·赤金#4B5CC4#F2BE45 #EACD76 #D9B611 #FFFFFF蓝 3-5 宝蓝(多和小面积纯黄色(金色)配合使用)+ 金银 8-0 赤金
拼色 3青莲·金玉#801DAE#F2BE45 #FFF143 #3DE1AD #FFFFFF蓝 3-19 青莲(偏蓝的紫色)+ 黄 1-0 鹅黄 + 绿 2-14 翡翠色
拼色 4松花·桃粉#BCE672#C93756 #057748绿 2-31 松花色(嫩黄绿)+ 红 0-1 樱桃色 + 绿 2-30 松花绿
拼色 5藏青·鹅黄#2E4E7E#F2BE45 #FFFFFF #FFB3A7 #3DE1AD蓝 8-2 藏青(深蓝)+ 金银 8-0 赤金 + 精白 + 红 0-0 粉红 + 绿 2-14 翡翠色

两处按用户反馈改过色(2026-09-26):① 原「松花·桃粉」的主色是松花绿 #057748, 与纯色「松柏绿」撞脸(两张卡看着是同一个绿),于是那个墨绿归给松柏绿这一格, 「松花·桃粉」改用松花色 #BCE672 当主色、只配两个次色(画出来正是 2/1/1); ② 原「乌金·翡翠」是拿玄色 #622A1D 当"乌"用,观感发闷,整条换成「藏青·鹅黄」。 色库里的「乌金」其实是 #A78E44 这个金褐色 —— 名字与用途对不上也是换掉它的原因之一。

出处与致谢

  • 纯色/拼色卡片上的 15 个色值,全部取自「中国传统色库」项目(chinese-colors): https://github.com/zerosoul/chinese-colors —— 作者 tristan(GitHub @zerosoul), 在线手册 https://colors.ichuantong.cn,许可 ISC。 该项目把 170 个中国传统色的名字与色值整理成 src/assets/colors.json, 本插件只做取色与派生(每套方案只挑三四个名字色,其余 token 由同一条造色规则算出来); 取色数据在 lib/palette-schemes.json,每套都带 source 记着它在色库里的「组 + id」。色名与色值是作者整理的开源成果, 在此感谢作者 tristan 的整理与开源。
  • 七套复刻皮肤的场景与配色复刻自蜂链商城电商新零售系统管理后台的主题: https://github.com/renjie2026/fenglianshop-open(该项目的开发者就是本插件的作者)。
  • 两套宠物主题(琥珀猫咪、虎子阿黄)、内置浅色/深色与**宠物挂件家族(七只小宠物)**的美术、台词与实现是本插件原创。
  • 大鲸鱼娘 da-jing-yu-niang 的工作区壁纸人物,用的是社区项目「Deepseek Whale-chan」的现成角色素材 (副标题 A Little Deeper, A Kinder World):https://github.com/Neko3000/deepseek-whalechan —— 取该仓库 skills/whalechan-image-character/assets/reference-images/standard/01_gentle_wave.webp (标准体型正面立姿,1024×1024)。角色 IP 属于原作者:鲸鱼娘形象原案 @上善无形(Bilibili https://space.bilibili.com/4456176)、女仆装设计 @ZipZipPipe(Bilibili https://space.bilibili.com/4168597)、角色卡 mamemily2050 (用户提供的角色设定图作者)。该项目的角色设定与素材以 CC BY-NC-SA 4.0 授权、禁止商用, 商用需另行取得原作者书面许可;本插件是非商用同人作品,不做任何商业使用。 本插件对素材只做了两件事:① 把平涂米色底抠成透明、裁到人物外接框、透明区做去边渗色 (一次性加工脚本 tools/art/whale-maid-from-whalechan.py, 它读取的原图 tools/art/whalechan-01_gentle_wave.webp 与产物 lib/assets/whale-maid.png 都在仓库里,重跑脚本会逐字节复现同一张图; 这两件都不进发布包);② 在 AMBIENT_CSS 里 加一层呼吸微动、身后光晕/上浮气泡,以及入场飞入 → 停留 → 转背景壁纸那套动画与层级 (飞入的水泡尾迹、落地水花、可读性遮罩都是 CSS;半透明「地面」由与壁纸层同生共死的 一张伴生样式表提供,皮肤 JSON 始终是 hex 形状)。人物形象本身未作改绘。 在此感谢 Neko3000 的素材整理,以及 @上善无形、@ZipZipPipe、mamemily2050 的创作。 若原作者对上述用法有异议,请提 issue,我们会立即撤下该素材(可回退到本插件自绘版本)。
  • 宠物挂件的「活性」设计(宠物对工作状态的反应、闲聊的节奏控制)受社区插件 @linxin666/dsh-pet(作者 @linxin666 及其上游资产作者)启发, 一期挂件的位置持久化也借鉴了它的思路,在此感谢。本插件的实现是独立的: 不注入任何额外服务,「模型生成中」的检测走的是 composer 按钮的无哈希 aria-label(DOM 信号)。

如果你是要转载或再分发本插件:色值本身请按上面那条一并保留出处与致谢; 复刻皮肤的场景素材请遵循蜂链商城仓库的许可; 大鲸鱼娘的人物素材(lib/assets/whale-maid.png)请遵循 CC BY-NC-SA 4.0 —— 署名(@上善无形 / @ZipZipPipe / mamemily2050 与 Neko3000/deepseek-whalechan)、 非商用、相同方式共享,三条缺一不可。

这一类卡片不印 description:15 个按钮已经占满卡面,文字会把卡片挤爆。description 仍然必须非空 —— 它照 Schema 的定义只作 tooltip(title