dsh-background-by-model 0.7.3 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +190 -171
- package/CHANGELOG.zh.md +191 -170
- package/LICENSE +21 -21
- package/README.md +294 -300
- package/README.zh.md +294 -300
- package/cordis.patch.yml +8 -8
- package/lib/client.js +261 -49
- package/lib/client.js.map +1 -1
- package/lib/index.js +46 -14
- package/package.json +4 -2
package/README.zh.md
CHANGED
|
@@ -1,300 +1,294 @@
|
|
|
1
|
-
# dsh-background-by-model
|
|
2
|
-
|
|
3
|
-
<p align="center">
|
|
4
|
-
<a href="https://github.com/HarmlessFunny/dsh-background-by-model"><img src="https://img.shields.io/github/stars/HarmlessFunny/dsh-background-by-model?style=social" alt="GitHub stars"></a>
|
|
5
|
-
<a href="https://www.npmjs.com/package/dsh-background-by-model"><img src="https://img.shields.io/npm/v/dsh-background-by-model" alt="npm version"></a>
|
|
6
|
-
</p>
|
|
7
|
-
|
|
8
|
-
[English](README.md) | 中文
|
|
9
|
-
|
|
10
|
-
> 派生自 [`Tkingxiao/dsh-any-background`](https://github.com/Tkingxiao/dsh-any-background),并重命名为 `dsh-background-by-model`。
|
|
11
|
-
|
|
12
|
-
一个 **DeepSeek Harness**
|
|
13
|
-
|
|
14
|
-
> **v0.3.0 是破坏性更新**:视频背景、生成式背景与全局主题色均已被移除。详见 [CHANGELOG.zh.md 的 v0.3.0 条目](./CHANGELOG.zh.md#v030)。
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## 模型规则如何工作
|
|
19
|
-
|
|
20
|
-
一条规则 = 一个**匹配串** + **一整套背景外观**。切换模型时,插件读取当前会话的模型名,自上而下扫描列表,使用**第一条**“匹配串出现在模型名里”的规则(忽略大小写)。如果一条都没命中,就使用**第 1 条**——规则 1 同时兼任兜底。
|
|
21
|
-
|
|
22
|
-
示例列表:
|
|
23
|
-
|
|
24
|
-
| # | 匹配串 | 背景图 |
|
|
25
|
-
| --- | --- | --- |
|
|
26
|
-
| 1 | `deepseek` | 图 1 |
|
|
27
|
-
| 2 | `flash` | 图 2 |
|
|
28
|
-
| 3 | `glm` | 图 3 |
|
|
29
|
-
|
|
30
|
-
| 当前模型 | 结果 | 原因 |
|
|
31
|
-
| --- | --- | --- |
|
|
32
|
-
| `DeepSeek-Flash` | 规则 1 → 图 1 | `deepseek` 先命中 |
|
|
33
|
-
| `GLM-Flash` | 规则 2 → 图 2 | `flash` 比 `glm` 更靠前 |
|
|
34
|
-
| `Qwen-Flash` | 规则 2 → 图 2 | `flash` 命中 |
|
|
35
|
-
| `GLM-Turbo` | 规则 3 → 图 3 | 只有 `glm` 命中 |
|
|
36
|
-
| `Kimi-K3` | 兜底 → 规则 1 → 图 1 | 都没有命中 |
|
|
37
|
-
|
|
38
|
-
说明:
|
|
39
|
-
|
|
40
|
-
- **顺序即优先级。** 先命中者胜,而不是最精确者胜——需要时拖动规则调整顺序。
|
|
41
|
-
- **匹配串留空**表示该规则不参与匹配、只作为兜底。因此单规则 + 空匹配串就是“一张图到处用”。
|
|
42
|
-
- 匹配串会同时比对 **provider、模型 id 与模型显示名**三者拼接出的字符串,三者任一都能用来选中规则。
|
|
43
|
-
- 当前模型取自**本会话的持久化模型选择**(`modelSelection` 投影,和输入框上的模型选择器读的是同一份值),因此会话内切换模型会立即生效。「模型背景」页顶部会显示当前读到的是哪个模型;如果只读到宿主全局默认模型(不是本会话的选择),会额外标注 **宿主默认**。
|
|
44
|
-
|
|
45
|
-
> 提醒:上面这张示例表里**没有 `kimi`**,所以切到 Kimi 会走到兜底 = 规则 1 = 图 1,看起来像“没反应”。想给 Kimi 单独配图,就加一条匹配串为 `kimi` 的规则。
|
|
46
|
-
|
|
47
|
-
## 截图
|
|
48
|
-
|
|
49
|
-
同一套界面、同一份配置,只因为当前模型不同:
|
|
50
|
-
|
|
51
|
-
<p align="center">
|
|
52
|
-
<img src="example_img/wallpaper-deepseek.webp" alt="DeepSeek 下的外观" width="880">
|
|
53
|
-
<br/>
|
|
54
|
-
<em>DeepSeek V4.1 Flash · 命中匹配串含 <code>deepseek</code> 的规则:浅色壁纸 + 与图相配的主题色</em>
|
|
55
|
-
</p>
|
|
56
|
-
|
|
57
|
-
<p align="center">
|
|
58
|
-
<img src="example_img/wallpaper-kimi.webp" alt="Kimi 下的外观" width="880">
|
|
59
|
-
<br/>
|
|
60
|
-
<em>Kimi K2.7 Code · 命中匹配串含 <code>kimi</code> 的规则:深色壁纸 + 深色主题,整个界面跟着换肤</em>
|
|
61
|
-
</p>
|
|
62
|
-
|
|
63
|
-
<p align="center">
|
|
64
|
-
<img src="example_img/rule-editor.webp" alt="单条规则的编辑器" width="660">
|
|
65
|
-
<br/>
|
|
66
|
-
<em>「模型背景」页的单条规则 ·
|
|
67
|
-
</p>
|
|
68
|
-
|
|
69
|
-
<p align="center">
|
|
70
|
-
<sub>示例壁纸素材来源于 bilibili <a href="https://space.bilibili.com/4168597">ZipZipPipe</a></sub>
|
|
71
|
-
</p>
|
|
72
|
-
|
|
73
|
-
## 功能特性
|
|
74
|
-
|
|
75
|
-
### 模型规则
|
|
76
|
-
|
|
77
|
-
- **有序规则列表** — 可新增、删除、拖动排序并命名规则;每条规则用自己的匹配串参与匹配,先命中者生效,规则 1 兼任兜底。
|
|
78
|
-
- **实时状态提示** — 「模型背景」页顶部会显示当前状态,例如「当前模型 deepseek-flash → 命中 · 规则 1」,方便当场验证规则写对没有;检测不到当前模型时会给出提示。
|
|
79
|
-
-
|
|
80
|
-
- **一条规则多张图** — 每条规则持有一组有序图片,用胶片条展示:可一次加多张(多选文件、拖放,或一行一个网址批量粘贴)、排序、把某张设为第一张、**原地替换某一张**(替换会保住它在轮换里的位置)、逐张删除。不轮换时规则画的就是**第一张**。删掉最后一张只是让这条规则变空,而空不等于失效:只要它还留着自己的主题色,它就照旧参与匹配与兜底、只给界面配色而不铺壁纸;连主题色也没有(比如刚新增的规则)才会被匹配跳过。空规则是一个看得见、退得回的状态,而不是卡住出不来的死胡同。一张图都没有时胶片条会隐藏、上方那块大预览**就是**上传按钮,所以添加图片的地方只有一个、也很显眼。
|
|
81
|
-
- **导入 / 导出** — 一键把**每一条规则连同它的全部图片**导出为 `dsh-background-by-model-theme.json`(版本 6,图片以 base64
|
|
82
|
-
- **文件持久化** — 所有设置与图片保存到文件系统 `~/.dsh/.dsh-background-by-model-data/`,不依赖 `localStorage`。
|
|
83
|
-
- **自动迁移** —
|
|
84
|
-
- **中英双语** — 完整的中英文界面,自动跟随语言设置。
|
|
85
|
-
- **主题守护** — 宿主重置主题后自动重新激活自定义主题。
|
|
86
|
-
|
|
87
|
-
### 多图轮换
|
|
88
|
-
|
|
89
|
-
按规则开关,且**默认关闭** —— 轮换是真要花流量、内存和电的,不该由默认值替你决定。
|
|
90
|
-
|
|
91
|
-
- **按规则开启** — 开关就在规则卡片里,规则至少有两张图之后才能打开。
|
|
92
|
-
- **每张停留** — 10 秒 / 30 秒 / 1 分钟 / 5 分钟 / 30 分钟 / 1 小时,也可以自己填秒数(限制在 5 秒 – 24 小时)。
|
|
93
|
-
- **换图顺序** — 「按顺序」自上而下走完一圈再回到第一张;「随机」会在**除当前这张之外**的所有图里等概率挑一张,因为抽到同一张看起来就跟这一次没生效一模一样。
|
|
94
|
-
- **切换模型时也换一张** — 可选的第二种触发方式:每次切换模型落到这条规则上就往前走一张。对「每次都想看到不一样」的规则来说,这就是全部功能,而且不用挂任何定时器。
|
|
95
|
-
- **只有正在生效的规则会轮换** — 全插件只有一个定时器,始终对准当前模型解析出的那条规则。标签页不可见时它会停下、回来时重新计时;只有一张图的规则(以及所有[节日](#节日特殊背景))从不排期。
|
|
96
|
-
- **下一张** — 立刻换一张,方便当场检查这组图。
|
|
97
|
-
-
|
|
98
|
-
-
|
|
99
|
-
- **只加载用得到的图** — 启动时只读每条规则的**第一张**,其余的在展开卡片时、或者在轮换即将用到它时再读。所以「五条规则各十张图」不等于首帧之前先传五十张壁纸。
|
|
100
|
-
|
|
101
|
-
### 切换效果(全局)
|
|
102
|
-
|
|
103
|
-
壁纸**发生变化**时长什么样。它放在 **「配置」** 页,对所有规则是同一个(规则本身没有「切换效果」这个概念),并且覆盖壁纸变化的所有来源:切模型、[轮换](#多图轮换)换图、手动「下一张」,以及[节日](#节日特殊背景)接管。
|
|
104
|
-
|
|
105
|
-
- **四种效果** — **淡入淡出**(此前每个版本都在用的混合方式,因此是默认)、**直接切换**(硬切)、**缩放淡入**(新图从大 6% 收拢到位)、**平移推入**(新图从侧向推入)。缩放与平移动的是 `transform`,壁纸层此前从未用过它,所以两者都不增加一个字节的传输。
|
|
106
|
-
- **缓动** — 标准 / 匀速 / 先快后慢 / 两端慢。效果为**「直接切换」**时这一行不渲染:硬切没有曲线可调,而一个什么都不做的控件比没有这个控件更糟。
|
|
107
|
-
- **所有切换共用一个时长** — `0`–`3000 ms`,而 `0` 就是硬切,不会被当成「没设置」。它取代了每条规则的 `rotate.fadeMs`:那个字段从 0.7.0 起就**没有任何界面能改**(只能手改配置),所以手改过的值会在旧配置第一次被读取时折进这里(等于出厂 320ms 的值会被忽略,普通配置照旧拿默认值)。
|
|
108
|
-
- **「直接切换」和 0 秒是同一种硬切** — 同一个诉求的两种说法,所以两者都照做,而不是把其中一个读成「没设置」。
|
|
109
|
-
- **「减少动态效果」是否决而不是缩短动画** — 系统处于 `prefers-reduced-motion: reduce` 时完全不做动画,并且卡片会直说,而不是预览一个界面根本不会执行的效果。
|
|
110
|
-
- **有一个预览块,因为壁纸淡入到它自己身上是看不见的** — 拿已经在屏上的壁纸回放效果,什么都看不到,而这正是本插件一直在设计上规避的「我改了但什么都没发生」。预览块用**此刻真实切换会用的时长**回放所选效果,换一个效果也会立刻重放一次。
|
|
111
|
-
- **界面配色走同一个时钟** — 一次主题色变化就是一次 token 块重写,以前它会让所有表面在一帧里跳完,而壁纸却在淡入。现在这些 alias token 被注册成颜色、按本设置的时长与缓动插值,包括那些不继承而是自己重声明这些 token 的面,以及插件内联绘制的那两处。有一个刻意的例外:**浅↔深互切立即切换**——那是换了一整套调色板而不是同一套的色调变化,在两者之间插值会让界面经过一段两个方向的字色都读不清的中间态。壁纸不受影响,照旧有动画。
|
|
112
|
-
- **它不是滑块** — 只有调色板真的变了才武装渐变。拖动滑块会在每一帧重写同一个 token 块,那里若挂着过渡,表面就会滞后于指针。
|
|
113
|
-
|
|
114
|
-
### 节日特殊背景
|
|
115
|
-
|
|
116
|
-
小小一个,不是一整块设置:**「配置」页上一个开关,别的什么都没有**。它默认就是开的;到了日子背景自己换,第二天早上自己换回。
|
|
117
|
-
|
|
118
|
-
- **行为** — 中秋与国庆当天,壁纸换成那个节日自己的图片,并配上该节日固定的主题色(中秋 `#384A77`、国庆 `#FFF6EB`);第二天交还给模型规则。这份配色同时写在节日条目和它的图片上——主题色现在住在图片里——所以以后节日也能多图轮换、每张带自己的配色。
|
|
119
|
-
- **中秋节** — 农历八月十五当天。它在公历上逐年移动(2024-09-17、2025-10-06、2026-09-25、2027-09-15……),所以是运行时按农历换算的,时区钉在 **Asia/Shanghai** —— 农历日期在北京时间午夜翻页,不是你那边的午夜。
|
|
120
|
-
- **国庆节** — 公历 10 月 1–7 日。
|
|
121
|
-
- **两者重叠时中秋优先** — 它们确实会撞(2025-10-06 就是同一天),一个精确的单日比七天窗口里的某一天更值得采信。
|
|
122
|
-
- **没有图的节日会回落到模型规则**,而不是把背景刷空。
|
|
123
|
-
- **内置壁纸** — 两个节日都自带一张压缩过的壁纸(原生分辨率下 228 KB 与 500 KB,原图共 8.37 MB)。只会去取**今天真能生效**的那一张,所以不在节日的配置一点都不会传。
|
|
124
|
-
- **图片和配色都不可替换,这是刻意的** — 一个要求用户去配置的彩蛋就不是彩蛋了。节日槽位是只读的:往 `modelbg-h-midautumn` / `modelbg-h-nationalday` 里放文件不会被任何一次读取采用,插件也拒绝写入、抓取和删除这两个槽位。主题色是节日定义里的常量、每次读取都强制覆盖——**节日条目和它的图片两处都覆盖**,所以手改 `theme-config.json` 里的 `color`
|
|
125
|
-
- **不想要它** — 关掉「配置」页那个开关,或者在同一个文件里写 `"holidays": { "enabled": false }`。
|
|
126
|
-
|
|
127
|
-
###
|
|
128
|
-
|
|
129
|
-
- **背景图片** — 一条规则可以放一张或多张图,每张图是独立文件。胶片条决定你正在编辑哪一张;不轮换时规则画的是**第一张**。规则也可以是**一张图都没有**的:这时它不再铺壁纸,但只要它有自己的主题色就照旧参与匹配与兜底(只是把界面按那个颜色配色),连主题色也没有才会被匹配跳过,直到你给它一点内容。
|
|
130
|
-
- **主题色** — HSL 色轮 + 数值输入 + 灵感色板,外加「从本图提取」和吸管「从图片取色」。**颜色属于图片**:这些控件编辑的是胶片条里选中的那张,胶片条上会标出哪些图已经各自有颜色,而没有自己颜色的图**跟随系统主题**、不会去继承规则的颜色。**一张图都没有**的规则只剩它自己的主题色可编辑——那正是这种规则唯一能画的东西。实时生成整套 CSS 设计令牌。跟随系统主题时,界面配色交还宿主,而壁纸与「界面」页的透明度、模糊照旧生效——表面颜色是从宿主自己的令牌读出来后套上你的透明度的,所以壁纸不会被一块不透明底板盖住。
|
|
131
|
-
- **布局模式** — 适应 / 填充 / 拉伸 / 平铺 /
|
|
132
|
-
- **取景** — 在视口比例的编辑器中拖动平移、滚轮缩放;**仅「适应」模式下可编辑**,提交的构图在窗口缩放、跨屏移动后保持一致。按图分别保存。
|
|
133
|
-
- **背景透明度** — `0–100%`,作用于该规则的壁纸层。
|
|
134
|
-
- **背景模糊** — `0–60 px`,作用于壁纸层。
|
|
135
|
-
|
|
136
|
-
### 全局设置(「界面」页)
|
|
137
|
-
|
|
138
|
-
- **分部位界面透明度** — 主背景、左侧栏、右侧栏、卡片面板(含对话框周围的选项框/菜单)、输入框与控件(发送框、Cordis 插件面板)、设置面板与对话文本框各自独立滑块。与主题色无关:某条规则没有主题色时这些滑块同样生效。
|
|
139
|
-
- **分部位界面模糊度** — 每个界面部位可独立调整毛玻璃 `backdrop-filter` 模糊(`0–60 px`),并通过宿主的稳定选择器为发送框与 Cordis 面板提供真实背景模糊。
|
|
140
|
-
- **对话与轨迹页** — 消息列表自动包裹为半透明卡片,轨迹页可整页调节透明度与模糊,让壁纸从内容后方透出来。
|
|
141
|
-
- **右侧栏** — 点开文件后从右侧滑出的那一栏有了自己的卡片:透明度默认跟随「主背景」(拖动后本卡片接管),模糊则在主背景模糊之上再叠加;关闭时不占位置、无副作用。
|
|
142
|
-
|
|
143
|
-
## 设置界面
|
|
144
|
-
|
|
145
|
-
设置的 **「主题」** 分类下现在有三个选项卡:
|
|
146
|
-
|
|
147
|
-
| 选项卡 | 作用范围 | 内容 |
|
|
148
|
-
| --- | --- | --- |
|
|
149
|
-
| **界面** | 全局,所有模型共用 | 主背景、左侧栏、右侧栏、卡片面板、输入框与控件、设置面板、对话文本框、轨迹页的透明度与模糊度 |
|
|
150
|
-
| **模型背景** |
|
|
151
|
-
| **配置** | — | 全局[切换效果](#切换效果全局)、导入 / 导出整套规则(`dsh-background-by-model-theme.json`),外加[节日特殊背景](#节日特殊背景)那一个开关 |
|
|
152
|
-
|
|
153
|
-
原先的 **「色彩」** 选项卡已删除——主题色改为每条规则自己的属性;原 **「背景」** 选项卡已改造成 **「模型背景」**。
|
|
154
|
-
|
|
155
|
-
## 存储位置
|
|
156
|
-
|
|
157
|
-
数据目录:`~/.dsh/.dsh-background-by-model-data/`(Windows:`C:\Users\<你>\.dsh\.dsh-background-by-model-data\`)
|
|
158
|
-
|
|
159
|
-
| 文件 | 内容 |
|
|
160
|
-
| --- | --- |
|
|
161
|
-
| `theme-config.json` | 规则列表(每条规则含图片列表与轮换设置)+ 全局「界面」设置 + 全局切换效果 + 节日覆盖配置 |
|
|
162
|
-
| `modelbg-<slot>` | 一张图片,保存为原始字节,无扩展名 —— 一张图一个文件,所以一条有三张图的规则占三个槽位 |
|
|
163
|
-
| `modelbg-h-midautumn` / `modelbg-h-nationalday` | 不使用:两张节日壁纸都随包发布,直接从包内送出 |
|
|
164
|
-
|
|
165
|
-
## 安装
|
|
166
|
-
|
|
167
|
-
### 方式一:npm 安装(推荐)
|
|
168
|
-
|
|
169
|
-
```sh
|
|
170
|
-
dsh plugin --profile web add dsh-background-by-model
|
|
171
|
-
# 或者直接从仓库安装:
|
|
172
|
-
dsh plugin --profile web add github:HarmlessFunny/dsh-background-by-model
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
装完需要重启 `dsh web`。
|
|
176
|
-
|
|
177
|
-
插件会出现在设置面板的 **“主题”** 分类中。
|
|
178
|
-
|
|
179
|
-
### 方式二:npx(无需全局安装)
|
|
180
|
-
|
|
181
|
-
```sh
|
|
182
|
-
npx @deepseek-ai/dsh plugin --profile web add github:HarmlessFunny/dsh-background-by-model
|
|
183
|
-
npx @deepseek-ai/dsh web
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
### 方式三:本地构建(开发)
|
|
187
|
-
|
|
188
|
-
`lib/` 目录已提交,安装后无需构建。修改 `src/` 后重新构建:
|
|
189
|
-
|
|
190
|
-
```sh
|
|
191
|
-
git clone https://github.com/HarmlessFunny/dsh-background-by-model.git
|
|
192
|
-
cd dsh-background-by-model
|
|
193
|
-
pnpm install
|
|
194
|
-
pnpm run bundle # 产物在 lib/
|
|
195
|
-
pnpm run typecheck
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
本地开发挂载方式:在 profile 的 `package.json` 里加 `link:` 依赖并把它加进 `dsh.profile.bundles`:
|
|
199
|
-
|
|
200
|
-
```jsonc
|
|
201
|
-
{
|
|
202
|
-
"dependencies": {
|
|
203
|
-
"dsh-background-by-model": "link:E:/DeepSeek/dsh-background-by-model"
|
|
204
|
-
},
|
|
205
|
-
"dsh": {
|
|
206
|
-
"profile": {
|
|
207
|
-
"bundles": ["dsh-background-by-model"]
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
改完 `src/` 必须重新执行 `pnpm run bundle` 才会生效——挂载的 profile 加载的是 `lib/`。
|
|
214
|
-
|
|
215
|
-
`pnpm test` 会构建、类型检查并跑六道校验(`tsdown && tsc -p tsconfig.json && node scripts/holiday-check.ts && node scripts/rotation-check.ts && node scripts/transition-check.ts && node scripts/repaint-check.ts && node scripts/ui-strings-check.ts && node scripts/node-half-check.mjs`)。六道都不需要依赖、不需要转译器、也不需要浏览器,也可以单独跑:`pnpm check:holiday` / `pnpm check:rotation` / `pnpm check:transition` / `pnpm check:repaint` / `pnpm check:ui` / `pnpm check:node`。
|
|
216
|
-
|
|
217
|
-
- **`check:holiday`** — 两个节日窗口对照已知日期、北京时间的跨日边界(23:59 与 00:01)、1900–2100 年间的闰八月,以及 `pickHoliday` 允许节日接管背景之前必须通过的四道闸门。
|
|
218
|
-
- **`check:rotation`** — 轮换的判定(`nextIndex` / `isRotating`):不会走越界、随机不会重复当前这张(在整个随机取值范围内穷举)、也不会把只有一张图的规则报成「正在轮换」。
|
|
219
|
-
- **`check:transition`** — 切换效果的判定(`resolveFadeMs` / `transitionPlan`),代码在 `src/client/transition.ts`,正是那些不报错、只是「看起来没生效」的部分:出厂默认仍然必须产出**与旧版本逐字符相同**的过渡串(`opacity 320ms ease`,且只动 opacity——没有变化的属性不能被写进过渡列表);`直接切换`、时长为 `0`、统一时长为 `0`、以及时长不是数字,四者都必须等于硬切;「减少动态效果」是否决而不是缩短;每个效果的起点都必须与终点不同(也就是「换了新效果却什么都没发生」);每个效果结束时都必须完全可见且**没有残留缩放**——一次没有复位的 zoom 会让之后每一张壁纸都被放大裁掉一圈。
|
|
220
|
-
- **`check:repaint`** — 「这次编辑要不要重画界面」的判定(`shouldRepaint`),其中就包含实际踩过的那个坑:**这次编辑本身**制造出了生效规则(某条规则的第一张图、第一个颜色或自动提取出的颜色)时,即使被编辑的规则此刻还不是生效规则,也必须立刻重画。它同时还会在 `src/client/index.tsx` 里任何一条写入路径不再询问这个判定时报错——也就是说,把老的 `id === activeRuleId` 判断写回去,会是构建校验失败,而不是你下一次上传时界面不动;轮换步骤不再重发调色板(主题色属于图片,换图就是换配色)同样会被它拦下。
|
|
221
|
-
- **`check:ui`** — 每个 `t('…')` 键在中英两本字典里都存在、两本字典键集完全一致、每个 `dab-…` 类在样式表里都有规则,且没有字典条目变成没人引用的死键。
|
|
222
|
-
- **`check:node`** — 把构建好的 node 半边通过它真实的 RPC 处理器跑一遍,`DSH_HOME` 指向临时目录:节日配置块穿过共享的 sanitizer、内置壁纸从空槽位被送出(且不会因此写进数据目录)、节日槽位拒绝写入 / 删除 / 抓取而丢进去的文件被忽略、普通规则槽位照常写入和删除,以及手改过的配置无法把节日指向别的规则的图片。它还覆盖逐图主题色这套形状:读取时抬升的两个方向(缺键继承规则色、显式 `null` 不继承)、颜色经过文件往返后各自独立,以及 `null` 是写出键而不是省略。切换效果同样在覆盖范围内:旧配置拿到的出厂默认、选定的效果 / 缓动 / 统一时长能原样穿过文件往返、非法值回退而夸张时长被夹紧、时长为 `0` 被保留而不是回退成默认,以及 `transition` 内部的字段漂移会被上报而不是悄悄丢掉。
|
|
223
|
-
|
|
224
|
-
## 常见问题
|
|
225
|
-
|
|
226
|
-
**所有模型看起来都一样,为什么?**
|
|
227
|
-
多半是第 1 条规则的匹配串是空的,它成了纯兜底、把整个列表兜住了。给规则 1 填一个匹配串,或把更具体的规则加到兜底规则**上面**。
|
|
228
|
-
|
|
229
|
-
**`GLM-Flash` 命中了不是我想用的规则。**
|
|
230
|
-
匹配是先命中者胜,而不是最精确者胜。把更具体的规则往上拖,或调整顺序让你想要的规则排在前面。
|
|
231
|
-
|
|
232
|
-
**图片存在哪?**
|
|
233
|
-
在 `~/.dsh/.dsh-background-by-model-data/`:每张图一个 `modelbg-<slot>` 文件,外加 `theme-config.json`。
|
|
234
|
-
|
|
235
|
-
**我开了轮换,背景却一直没变。**
|
|
236
|
-
有三件事会拦住它:规则至少要有两张图;标签页必须可见(隐藏的标签页什么都不画,轮换跟着一起停);只有当前模型解析出的那条规则在轮换——没生效的规则,「下一张」按钮就是灰的,正是这个原因。
|
|
237
|
-
|
|
238
|
-
**轮换有代价吗?**
|
|
239
|
-
有,所以默认关闭。每张图都按原始保真度保存(不做重编码),所以一条放了十张 8 MB 壁纸的规则就是十份 8 MB;每次换图还会重画整个界面。建议一组控制在两到五张、节奏也别太密。启动时只读每条规则的第一张,轮换也会提前预热它下一张要用的图,所以代价落在内存和磁盘上,而不是启动时间上。
|
|
240
|
-
|
|
241
|
-
**删掉规则里的图片之后,主题色为什么不起作用了?**
|
|
242
|
-
这是已经修掉的旧行为,根因是「有没有图」被当成了「这条规则是否可用」:图片删光的规则不再参与匹配,效果自然也就无从谈起,而它原本负责的模型还会被交给下一条规则。现在只要规则**有图、或者有自己的主题色**就仍然生效:不铺壁纸,只按这个颜色给界面配色(面板上会写明当前属于哪种状态)。连主题色也没有、也就是一点内容都没有的规则才会被跳过——「这条规则还没有图片,也没有自己的主题色:没有可显示的内容,匹配和兜底都会跳过它」。
|
|
243
|
-
|
|
244
|
-
**我更新了插件,面板说我的改动没有保存。**
|
|
245
|
-
浏览器半边和宿主半边是分开加载的:刷新页面后新客户端可能已经生效,而 DSH 主进程还在跑上一个版本的插件——它读不懂新的配置格式(`SCHEMA_VERSION` 比它低就知道),下一次写入就可能把规则丢掉。客户端检测到这种情况会**扣住所有配置写入**并提示你:重启 DSH 之后,多图配置、轮换设置等一切都会正常保存。
|
|
246
|
-
|
|
247
|
-
**我给一张图设了颜色,其它图片却没跟着变。**
|
|
248
|
-
这是设计如此:从 0.7.1 起主题色属于**图片**而不是规则,所以一组图可以依次是不同调性(绿的、红的、以及跟随系统主题的)。调色控件作用于胶片条里选中的那一张,控件上方的提示会写明是哪一张。唯一例外是**一张图都没有**的规则:那时控件编辑的是规则自己的主题色——那正是这种规则能画的东西,而且它刻意不作为该规则图片的默认值。
|
|
249
|
-
|
|
250
|
-
**更新之前我设的主题色去哪了?**
|
|
251
|
-
哪儿也没去:在「逐图主题色」之前写下的图片条目**根本没有** `color` 这个键,而这正是加载时用来区分「从来没有自己的颜色」和「被主动清空过」的依据——前者会把规则的颜色抬升到每一张这样的图上。所以带主题色的规则升级后观感完全一致,此后每张图就可以各自改色了。
|
|
252
|
-
|
|
253
|
-
**能分享整套配置吗?**
|
|
254
|
-
可以,在 **「配置」** 页导出即可;导出的 JSON 会把每条规则的图片内联进去。
|
|
255
|
-
|
|
256
|
-
**支持视频或生成式背景吗?**
|
|
257
|
-
不支持。两者都在 0.3.0 中移除,每条规则使用一张静态图片。
|
|
258
|
-
|
|
259
|
-
**把主题色切回「系统主题」后,界面和设置弹窗为什么不是一套配色?**
|
|
260
|
-
这是已经修掉的旧行为:清空主题色时插件只撤掉了 `body` 上那套令牌,设置弹窗里那三个**没有宿主回退**的重定向(`--dsw-alias-bg-layer-*` → 插件私有变量)以及轨迹页、三栏的内联背景都还留着上一次的颜色,于是出现「深色界面 + 浅色弹窗、白底白字」。现在这些表面统一由一个调色板来源驱动:有主题色时用规则自己的令牌,没有时**读取宿主当前令牌**再套上你的透明度重发,切换时一并交还宿主。
|
|
261
|
-
|
|
262
|
-
**切回「系统主题」后一开始还是浅色,拖一下滑块才变深,为什么?**
|
|
263
|
-
同一个洞的另一半:插件在持有主题色时会**强改** `body[data-ds-dark-theme]`(深色调色板写标记、浅色调色板直接删掉),而宿主只在**主题快照变化时**才重写这个标记(它不监听属性)。于是浅色皮肤留下的「标记被删」会一直生效,插件在切回系统主题那一刻读到的就是宿主的浅色调色板,并且之后没有任何事件再去重读——直到你碰了某个滑块。现在:切换时同步交还标记(宿主深色就写成宿主的布尔形式),并把宿主解析出的配色方案(`ctx.theme` 的 `active.colorScheme`,过期则回退到 `html[data-ds-theme-source]` + `prefers-color-scheme`)推给渲染层;每秒的守护定时器在「无主题色」状态下也会重读一次宿主调色板,变了就重画。
|
|
264
|
-
|
|
265
|
-
**为什么「自定义颜色」点下去就有颜色了?**
|
|
266
|
-
因为按下它就等于离开「跟随系统主题」,必须给出一个起始色。它先跑一次「从本图提取」(和「从本图提取」按钮同一条链路),取不到鲜明颜色时才退回默认色,所以不会再出现「点一下就从浅色跳成一块跟壁纸无关的深蓝」。
|
|
267
|
-
|
|
268
|
-
**我换了新的切换效果,壁纸还是直接跳过去。**
|
|
269
|
-
有两件事会拦住它,而且两件都在那张卡上:效果是**「直接切换」**;或者时长是 `0`(效果和时长是同一个硬切的两种说法,而效果优先)。第三件不在插件里:系统开了**「减少动态效果」**时完全不做动画,卡片也会直说。
|
|
270
|
-
|
|
271
|
-
## 近期优化
|
|
272
|
-
|
|
273
|
-
> 这里只列最近两个版本;更早的版本(v0.7.
|
|
274
|
-
|
|
275
|
-
### v0.7.
|
|
276
|
-
|
|
277
|
-
-
|
|
278
|
-
-
|
|
279
|
-
-
|
|
280
|
-
-
|
|
281
|
-
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
[](https://www.star-history.com/?repos=HarmlessFunny%2Fdsh-background-by-model&type=timeline&legend=bottom-right)
|
|
297
|
-
|
|
298
|
-
## 许可
|
|
299
|
-
|
|
300
|
-
MIT
|
|
1
|
+
# dsh-background-by-model
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://github.com/HarmlessFunny/dsh-background-by-model"><img src="https://img.shields.io/github/stars/HarmlessFunny/dsh-background-by-model?style=social" alt="GitHub stars"></a>
|
|
5
|
+
<a href="https://www.npmjs.com/package/dsh-background-by-model"><img src="https://img.shields.io/npm/v/dsh-background-by-model" alt="npm version"></a>
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
[English](README.md) | 中文
|
|
9
|
+
|
|
10
|
+
> 派生自 [`Tkingxiao/dsh-any-background`](https://github.com/Tkingxiao/dsh-any-background),并重命名为 `dsh-background-by-model`。
|
|
11
|
+
|
|
12
|
+
一个 **DeepSeek Harness** 外观插件,核心是一份**有序的模型规则列表**:每条规则自带壁纸(可多张)、透明度与模糊度,**每张图各有自己的布局模式、取景与主题色**,切换模型即切换背景,切换过程走你在「配置」页选定的全局[切换效果](#切换效果全局)。
|
|
13
|
+
|
|
14
|
+
> **v0.3.0 是破坏性更新**:视频背景、生成式背景与全局主题色均已被移除。详见 [CHANGELOG.zh.md 的 v0.3.0 条目](./CHANGELOG.zh.md#v030)。
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 模型规则如何工作
|
|
19
|
+
|
|
20
|
+
一条规则 = 一个**匹配串** + **一整套背景外观**。切换模型时,插件读取当前会话的模型名,自上而下扫描列表,使用**第一条**“匹配串出现在模型名里”的规则(忽略大小写)。如果一条都没命中,就使用**第 1 条**——规则 1 同时兼任兜底。
|
|
21
|
+
|
|
22
|
+
示例列表:
|
|
23
|
+
|
|
24
|
+
| # | 匹配串 | 背景图 |
|
|
25
|
+
| --- | --- | --- |
|
|
26
|
+
| 1 | `deepseek` | 图 1 |
|
|
27
|
+
| 2 | `flash` | 图 2 |
|
|
28
|
+
| 3 | `glm` | 图 3 |
|
|
29
|
+
|
|
30
|
+
| 当前模型 | 结果 | 原因 |
|
|
31
|
+
| --- | --- | --- |
|
|
32
|
+
| `DeepSeek-Flash` | 规则 1 → 图 1 | `deepseek` 先命中 |
|
|
33
|
+
| `GLM-Flash` | 规则 2 → 图 2 | `flash` 比 `glm` 更靠前 |
|
|
34
|
+
| `Qwen-Flash` | 规则 2 → 图 2 | `flash` 命中 |
|
|
35
|
+
| `GLM-Turbo` | 规则 3 → 图 3 | 只有 `glm` 命中 |
|
|
36
|
+
| `Kimi-K3` | 兜底 → 规则 1 → 图 1 | 都没有命中 |
|
|
37
|
+
|
|
38
|
+
说明:
|
|
39
|
+
|
|
40
|
+
- **顺序即优先级。** 先命中者胜,而不是最精确者胜——需要时拖动规则调整顺序。
|
|
41
|
+
- **匹配串留空**表示该规则不参与匹配、只作为兜底。因此单规则 + 空匹配串就是“一张图到处用”。
|
|
42
|
+
- 匹配串会同时比对 **provider、模型 id 与模型显示名**三者拼接出的字符串,三者任一都能用来选中规则。
|
|
43
|
+
- 当前模型取自**本会话的持久化模型选择**(`modelSelection` 投影,和输入框上的模型选择器读的是同一份值),因此会话内切换模型会立即生效。「模型背景」页顶部会显示当前读到的是哪个模型;如果只读到宿主全局默认模型(不是本会话的选择),会额外标注 **宿主默认**。
|
|
44
|
+
|
|
45
|
+
> 提醒:上面这张示例表里**没有 `kimi`**,所以切到 Kimi 会走到兜底 = 规则 1 = 图 1,看起来像“没反应”。想给 Kimi 单独配图,就加一条匹配串为 `kimi` 的规则。
|
|
46
|
+
|
|
47
|
+
## 截图
|
|
48
|
+
|
|
49
|
+
同一套界面、同一份配置,只因为当前模型不同:
|
|
50
|
+
|
|
51
|
+
<p align="center">
|
|
52
|
+
<img src="example_img/wallpaper-deepseek.webp" alt="DeepSeek 下的外观" width="880">
|
|
53
|
+
<br/>
|
|
54
|
+
<em>DeepSeek V4.1 Flash · 命中匹配串含 <code>deepseek</code> 的规则:浅色壁纸 + 与图相配的主题色</em>
|
|
55
|
+
</p>
|
|
56
|
+
|
|
57
|
+
<p align="center">
|
|
58
|
+
<img src="example_img/wallpaper-kimi.webp" alt="Kimi 下的外观" width="880">
|
|
59
|
+
<br/>
|
|
60
|
+
<em>Kimi K2.7 Code · 命中匹配串含 <code>kimi</code> 的规则:深色壁纸 + 深色主题,整个界面跟着换肤</em>
|
|
61
|
+
</p>
|
|
62
|
+
|
|
63
|
+
<p align="center">
|
|
64
|
+
<img src="example_img/rule-editor.webp" alt="单条规则的编辑器" width="660">
|
|
65
|
+
<br/>
|
|
66
|
+
<em>「模型背景」页的单条规则 · 壁纸、透明度与模糊度属于这条规则;布局模式、取景与主题色(色轮 / HSL / RGB / 从本图提取 / 从图片取色)属于它正在编辑的那张图</em>
|
|
67
|
+
</p>
|
|
68
|
+
|
|
69
|
+
<p align="center">
|
|
70
|
+
<sub>示例壁纸素材来源于 bilibili <a href="https://space.bilibili.com/4168597">ZipZipPipe</a></sub>
|
|
71
|
+
</p>
|
|
72
|
+
|
|
73
|
+
## 功能特性
|
|
74
|
+
|
|
75
|
+
### 模型规则
|
|
76
|
+
|
|
77
|
+
- **有序规则列表** — 可新增、删除、拖动排序并命名规则;每条规则用自己的匹配串参与匹配,先命中者生效,规则 1 兼任兜底。
|
|
78
|
+
- **实时状态提示** — 「模型背景」页顶部会显示当前状态,例如「当前模型 deepseek-flash → 命中 · 规则 1」,方便当场验证规则写对没有;检测不到当前模型时会给出提示。
|
|
79
|
+
- **外观随规则走,逐图的三项随图走** — 壁纸(多张)、透明度与模糊度是每条规则自己的属性;**布局模式、取景和主题色则是每张图片自己的**。除「界面」页外没有任何全局外观项。
|
|
80
|
+
- **一条规则多张图** — 每条规则持有一组有序图片,用胶片条展示:可一次加多张(多选文件、拖放,或一行一个网址批量粘贴)、排序、把某张设为第一张、**原地替换某一张**(替换会保住它在轮换里的位置)、逐张删除。不轮换时规则画的就是**第一张**。删掉最后一张只是让这条规则变空,而空不等于失效:只要它还留着自己的主题色,它就照旧参与匹配与兜底、只给界面配色而不铺壁纸;连主题色也没有(比如刚新增的规则)才会被匹配跳过。空规则是一个看得见、退得回的状态,而不是卡住出不来的死胡同。一张图都没有时胶片条会隐藏、上方那块大预览**就是**上传按钮,所以添加图片的地方只有一个、也很显眼。
|
|
81
|
+
- **导入 / 导出** — 一键把**每一条规则连同它的全部图片**导出为 `dsh-background-by-model-theme.json`(版本 6,图片以 base64 内联),可随时导入还原。更早版本导出的文件同样能导入:规则唯一的那张图会被还原成它的图片列表,在「主题色属于图片」之前写下的颜色会被抬升到每一张还没有自己颜色的图上,在布局模式下放到规则上时写下的值会被抬升到它的每一张图上,而在[切换效果](#切换效果全局)之前写下的文件会拿到这项设置的出厂默认——所以旧主题文件还原出来的观感与当初一模一样。
|
|
82
|
+
- **文件持久化** — 所有设置与图片保存到文件系统 `~/.dsh/.dsh-background-by-model-data/`,不依赖 `localStorage`。
|
|
83
|
+
- **自动迁移** — 旧版单壁纸配置在首次读取时自动升级,曾经放在规则上的布局模式也会被抬升到它的每一张图上。详见 [CHANGELOG.zh.md 的 v0.3.0 条目](./CHANGELOG.zh.md#v030)。
|
|
84
|
+
- **中英双语** — 完整的中英文界面,自动跟随语言设置。
|
|
85
|
+
- **主题守护** — 宿主重置主题后自动重新激活自定义主题。
|
|
86
|
+
|
|
87
|
+
### 多图轮换
|
|
88
|
+
|
|
89
|
+
按规则开关,且**默认关闭** —— 轮换是真要花流量、内存和电的,不该由默认值替你决定。
|
|
90
|
+
|
|
91
|
+
- **按规则开启** — 开关就在规则卡片里,规则至少有两张图之后才能打开。
|
|
92
|
+
- **每张停留** — 10 秒 / 30 秒 / 1 分钟 / 5 分钟 / 30 分钟 / 1 小时,也可以自己填秒数(限制在 5 秒 – 24 小时)。
|
|
93
|
+
- **换图顺序** — 「按顺序」自上而下走完一圈再回到第一张;「随机」会在**除当前这张之外**的所有图里等概率挑一张,因为抽到同一张看起来就跟这一次没生效一模一样。
|
|
94
|
+
- **切换模型时也换一张** — 可选的第二种触发方式:每次切换模型落到这条规则上就往前走一张。对「每次都想看到不一样」的规则来说,这就是全部功能,而且不用挂任何定时器。
|
|
95
|
+
- **只有正在生效的规则会轮换** — 全插件只有一个定时器,始终对准当前模型解析出的那条规则。标签页不可见时它会停下、回来时重新计时;只有一张图的规则(以及所有[节日](#节日特殊背景))从不排期。
|
|
96
|
+
- **下一张** — 立刻换一张,方便当场检查这组图。
|
|
97
|
+
- **跟着规则走的是外观,跟着图片走的是布局、取景与颜色** — 透明度、模糊度留在规则上、原地不动;**布局模式、取景、主题色属于图片**,所以一组图可以一张高截图用适应、旁边那张横图用填充,也可以依次是绿的、红的、以及跟随系统主题的,界面配色跟着壁纸一起换。过渡用的就是切换模型时那套交叉淡入。
|
|
98
|
+
- **布局模式、取景、颜色都是逐图的** — 适应/填充决定的是**这一张**图怎么铺进这块区域,构图和配色也都属于某一张图:每张图各自保留自己的三项,同时共享规则的透明度与模糊度。胶片条会标出哪些图已经各自有颜色,调色区上方也会写明当前编辑的是哪一张。
|
|
99
|
+
- **只加载用得到的图** — 启动时只读每条规则的**第一张**,其余的在展开卡片时、或者在轮换即将用到它时再读。所以「五条规则各十张图」不等于首帧之前先传五十张壁纸。
|
|
100
|
+
|
|
101
|
+
### 切换效果(全局)
|
|
102
|
+
|
|
103
|
+
壁纸**发生变化**时长什么样。它放在 **「配置」** 页,对所有规则是同一个(规则本身没有「切换效果」这个概念),并且覆盖壁纸变化的所有来源:切模型、[轮换](#多图轮换)换图、手动「下一张」,以及[节日](#节日特殊背景)接管。
|
|
104
|
+
|
|
105
|
+
- **四种效果** — **淡入淡出**(此前每个版本都在用的混合方式,因此是默认)、**直接切换**(硬切)、**缩放淡入**(新图从大 6% 收拢到位)、**平移推入**(新图从侧向推入)。缩放与平移动的是 `transform`,壁纸层此前从未用过它,所以两者都不增加一个字节的传输。
|
|
106
|
+
- **缓动** — 标准 / 匀速 / 先快后慢 / 两端慢。效果为**「直接切换」**时这一行不渲染:硬切没有曲线可调,而一个什么都不做的控件比没有这个控件更糟。
|
|
107
|
+
- **所有切换共用一个时长** — `0`–`3000 ms`,而 `0` 就是硬切,不会被当成「没设置」。它取代了每条规则的 `rotate.fadeMs`:那个字段从 0.7.0 起就**没有任何界面能改**(只能手改配置),所以手改过的值会在旧配置第一次被读取时折进这里(等于出厂 320ms 的值会被忽略,普通配置照旧拿默认值)。
|
|
108
|
+
- **「直接切换」和 0 秒是同一种硬切** — 同一个诉求的两种说法,所以两者都照做,而不是把其中一个读成「没设置」。
|
|
109
|
+
- **「减少动态效果」是否决而不是缩短动画** — 系统处于 `prefers-reduced-motion: reduce` 时完全不做动画,并且卡片会直说,而不是预览一个界面根本不会执行的效果。
|
|
110
|
+
- **有一个预览块,因为壁纸淡入到它自己身上是看不见的** — 拿已经在屏上的壁纸回放效果,什么都看不到,而这正是本插件一直在设计上规避的「我改了但什么都没发生」。预览块用**此刻真实切换会用的时长**回放所选效果,换一个效果也会立刻重放一次。
|
|
111
|
+
- **界面配色走同一个时钟** — 一次主题色变化就是一次 token 块重写,以前它会让所有表面在一帧里跳完,而壁纸却在淡入。现在这些 alias token 被注册成颜色、按本设置的时长与缓动插值,包括那些不继承而是自己重声明这些 token 的面,以及插件内联绘制的那两处。有一个刻意的例外:**浅↔深互切立即切换**——那是换了一整套调色板而不是同一套的色调变化,在两者之间插值会让界面经过一段两个方向的字色都读不清的中间态。壁纸不受影响,照旧有动画。
|
|
112
|
+
- **它不是滑块** — 只有调色板真的变了才武装渐变。拖动滑块会在每一帧重写同一个 token 块,那里若挂着过渡,表面就会滞后于指针。
|
|
113
|
+
|
|
114
|
+
### 节日特殊背景
|
|
115
|
+
|
|
116
|
+
小小一个,不是一整块设置:**「配置」页上一个开关,别的什么都没有**。它默认就是开的;到了日子背景自己换,第二天早上自己换回。
|
|
117
|
+
|
|
118
|
+
- **行为** — 中秋与国庆当天,壁纸换成那个节日自己的图片,并配上该节日固定的主题色(中秋 `#384A77`、国庆 `#FFF6EB`);第二天交还给模型规则。这份配色同时写在节日条目和它的图片上——主题色现在住在图片里——所以以后节日也能多图轮换、每张带自己的配色。
|
|
119
|
+
- **中秋节** — 农历八月十五当天。它在公历上逐年移动(2024-09-17、2025-10-06、2026-09-25、2027-09-15……),所以是运行时按农历换算的,时区钉在 **Asia/Shanghai** —— 农历日期在北京时间午夜翻页,不是你那边的午夜。
|
|
120
|
+
- **国庆节** — 公历 10 月 1–7 日。
|
|
121
|
+
- **两者重叠时中秋优先** — 它们确实会撞(2025-10-06 就是同一天),一个精确的单日比七天窗口里的某一天更值得采信。
|
|
122
|
+
- **没有图的节日会回落到模型规则**,而不是把背景刷空。
|
|
123
|
+
- **内置壁纸** — 两个节日都自带一张压缩过的壁纸(原生分辨率下 228 KB 与 500 KB,原图共 8.37 MB)。只会去取**今天真能生效**的那一张,所以不在节日的配置一点都不会传。
|
|
124
|
+
- **图片和配色都不可替换,这是刻意的** — 一个要求用户去配置的彩蛋就不是彩蛋了。节日槽位是只读的:往 `modelbg-h-midautumn` / `modelbg-h-nationalday` 里放文件不会被任何一次读取采用,插件也拒绝写入、抓取和删除这两个槽位。主题色是节日定义里的常量、每次读取都强制覆盖——**节日条目和它的图片两处都覆盖**,所以手改 `theme-config.json` 里的 `color` 也换不掉节日配色。布局模式同理固定为定义里的**填充**(这些画本来就是满幅的,一个残留的 `fit` 会给它加黑边),而旁边的**取景**仍然是你自己的。导出的主题文件只包含你自己的规则。
|
|
125
|
+
- **不想要它** — 关掉「配置」页那个开关,或者在同一个文件里写 `"holidays": { "enabled": false }`。
|
|
126
|
+
|
|
127
|
+
### 规则与图片各自的设置
|
|
128
|
+
|
|
129
|
+
- **背景图片** — 一条规则可以放一张或多张图,每张图是独立文件。胶片条决定你正在编辑哪一张;不轮换时规则画的是**第一张**。规则也可以是**一张图都没有**的:这时它不再铺壁纸,但只要它有自己的主题色就照旧参与匹配与兜底(只是把界面按那个颜色配色),连主题色也没有才会被匹配跳过,直到你给它一点内容。
|
|
130
|
+
- **主题色** — HSL 色轮 + 数值输入 + 灵感色板,外加「从本图提取」和吸管「从图片取色」。**颜色属于图片**:这些控件编辑的是胶片条里选中的那张,胶片条上会标出哪些图已经各自有颜色,而没有自己颜色的图**跟随系统主题**、不会去继承规则的颜色。**一张图都没有**的规则只剩它自己的主题色可编辑——那正是这种规则唯一能画的东西。实时生成整套 CSS 设计令牌。跟随系统主题时,界面配色交还宿主,而壁纸与「界面」页的透明度、模糊照旧生效——表面颜色是从宿主自己的令牌读出来后套上你的透明度的,所以壁纸不会被一块不透明底板盖住。
|
|
131
|
+
- **布局模式** — 适应 / 填充 / 拉伸 / 平铺 / 居中,并且**按图分别保存**:同一组轮换里可以一张适应、一张填充。规则还没有图片时这一行是**禁用**而不是隐藏(没有图可布局),这样卡片本身就说明了加上图片后会多出什么可调项。
|
|
132
|
+
- **取景** — 在视口比例的编辑器中拖动平移、滚轮缩放;**仅「适应」模式下可编辑**,提交的构图在窗口缩放、跨屏移动后保持一致。按图分别保存。
|
|
133
|
+
- **背景透明度** — `0–100%`,作用于该规则的壁纸层。
|
|
134
|
+
- **背景模糊** — `0–60 px`,作用于壁纸层。
|
|
135
|
+
|
|
136
|
+
### 全局设置(「界面」页)
|
|
137
|
+
|
|
138
|
+
- **分部位界面透明度** — 主背景、左侧栏、右侧栏、卡片面板(含对话框周围的选项框/菜单)、输入框与控件(发送框、Cordis 插件面板)、设置面板与对话文本框各自独立滑块。与主题色无关:某条规则没有主题色时这些滑块同样生效。
|
|
139
|
+
- **分部位界面模糊度** — 每个界面部位可独立调整毛玻璃 `backdrop-filter` 模糊(`0–60 px`),并通过宿主的稳定选择器为发送框与 Cordis 面板提供真实背景模糊。
|
|
140
|
+
- **对话与轨迹页** — 消息列表自动包裹为半透明卡片,轨迹页可整页调节透明度与模糊,让壁纸从内容后方透出来。
|
|
141
|
+
- **右侧栏** — 点开文件后从右侧滑出的那一栏有了自己的卡片:透明度默认跟随「主背景」(拖动后本卡片接管),模糊则在主背景模糊之上再叠加;关闭时不占位置、无副作用。
|
|
142
|
+
|
|
143
|
+
## 设置界面
|
|
144
|
+
|
|
145
|
+
设置的 **「主题」** 分类下现在有三个选项卡:
|
|
146
|
+
|
|
147
|
+
| 选项卡 | 作用范围 | 内容 |
|
|
148
|
+
| --- | --- | --- |
|
|
149
|
+
| **界面** | 全局,所有模型共用 | 主背景、左侧栏、右侧栏、卡片面板、输入框与控件、设置面板、对话文本框、轨迹页的透明度与模糊度 |
|
|
150
|
+
| **模型背景** | 每条规则、每张图片 | 有序规则列表、顶部实时状态,以及每条规则的图片(胶片条)、**逐图布局模式 / 取景 / 主题色**,加上规则自己的透明度、模糊度与[多图轮换](#多图轮换) |
|
|
151
|
+
| **配置** | — | 全局[切换效果](#切换效果全局)、导入 / 导出整套规则(`dsh-background-by-model-theme.json`),外加[节日特殊背景](#节日特殊背景)那一个开关 |
|
|
152
|
+
|
|
153
|
+
原先的 **「色彩」** 选项卡已删除——主题色改为每条规则自己的属性;原 **「背景」** 选项卡已改造成 **「模型背景」**。
|
|
154
|
+
|
|
155
|
+
## 存储位置
|
|
156
|
+
|
|
157
|
+
数据目录:`~/.dsh/.dsh-background-by-model-data/`(Windows:`C:\Users\<你>\.dsh\.dsh-background-by-model-data\`)
|
|
158
|
+
|
|
159
|
+
| 文件 | 内容 |
|
|
160
|
+
| --- | --- |
|
|
161
|
+
| `theme-config.json` | 规则列表(每条规则含图片列表与轮换设置)+ 全局「界面」设置 + 全局切换效果 + 节日覆盖配置 |
|
|
162
|
+
| `modelbg-<slot>` | 一张图片,保存为原始字节,无扩展名 —— 一张图一个文件,所以一条有三张图的规则占三个槽位 |
|
|
163
|
+
| `modelbg-h-midautumn` / `modelbg-h-nationalday` | 不使用:两张节日壁纸都随包发布,直接从包内送出 |
|
|
164
|
+
|
|
165
|
+
## 安装
|
|
166
|
+
|
|
167
|
+
### 方式一:npm 安装(推荐)
|
|
168
|
+
|
|
169
|
+
```sh
|
|
170
|
+
dsh plugin --profile web add dsh-background-by-model
|
|
171
|
+
# 或者直接从仓库安装:
|
|
172
|
+
dsh plugin --profile web add github:HarmlessFunny/dsh-background-by-model
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
装完需要重启 `dsh web`。
|
|
176
|
+
|
|
177
|
+
插件会出现在设置面板的 **“主题”** 分类中。
|
|
178
|
+
|
|
179
|
+
### 方式二:npx(无需全局安装)
|
|
180
|
+
|
|
181
|
+
```sh
|
|
182
|
+
npx @deepseek-ai/dsh plugin --profile web add github:HarmlessFunny/dsh-background-by-model
|
|
183
|
+
npx @deepseek-ai/dsh web
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### 方式三:本地构建(开发)
|
|
187
|
+
|
|
188
|
+
`lib/` 目录已提交,安装后无需构建。修改 `src/` 后重新构建:
|
|
189
|
+
|
|
190
|
+
```sh
|
|
191
|
+
git clone https://github.com/HarmlessFunny/dsh-background-by-model.git
|
|
192
|
+
cd dsh-background-by-model
|
|
193
|
+
pnpm install
|
|
194
|
+
pnpm run bundle # 产物在 lib/
|
|
195
|
+
pnpm run typecheck
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
本地开发挂载方式:在 profile 的 `package.json` 里加 `link:` 依赖并把它加进 `dsh.profile.bundles`:
|
|
199
|
+
|
|
200
|
+
```jsonc
|
|
201
|
+
{
|
|
202
|
+
"dependencies": {
|
|
203
|
+
"dsh-background-by-model": "link:E:/DeepSeek/dsh-background-by-model"
|
|
204
|
+
},
|
|
205
|
+
"dsh": {
|
|
206
|
+
"profile": {
|
|
207
|
+
"bundles": ["dsh-background-by-model"]
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
改完 `src/` 必须重新执行 `pnpm run bundle` 才会生效——挂载的 profile 加载的是 `lib/`。
|
|
214
|
+
|
|
215
|
+
`pnpm test` 会构建、类型检查并跑六道校验(`tsdown && tsc -p tsconfig.json && node scripts/holiday-check.ts && node scripts/rotation-check.ts && node scripts/transition-check.ts && node scripts/repaint-check.ts && node scripts/ui-strings-check.ts && node scripts/node-half-check.mjs`)。六道都不需要依赖、不需要转译器、也不需要浏览器,也可以单独跑:`pnpm check:holiday` / `pnpm check:rotation` / `pnpm check:transition` / `pnpm check:repaint` / `pnpm check:ui` / `pnpm check:node`。
|
|
216
|
+
|
|
217
|
+
- **`check:holiday`** — 两个节日窗口对照已知日期、北京时间的跨日边界(23:59 与 00:01)、1900–2100 年间的闰八月,以及 `pickHoliday` 允许节日接管背景之前必须通过的四道闸门。
|
|
218
|
+
- **`check:rotation`** — 轮换的判定(`nextIndex` / `isRotating`):不会走越界、随机不会重复当前这张(在整个随机取值范围内穷举)、也不会把只有一张图的规则报成「正在轮换」。
|
|
219
|
+
- **`check:transition`** — 切换效果的判定(`resolveFadeMs` / `transitionPlan`),代码在 `src/client/transition.ts`,正是那些不报错、只是「看起来没生效」的部分:出厂默认仍然必须产出**与旧版本逐字符相同**的过渡串(`opacity 320ms ease`,且只动 opacity——没有变化的属性不能被写进过渡列表);`直接切换`、时长为 `0`、统一时长为 `0`、以及时长不是数字,四者都必须等于硬切;「减少动态效果」是否决而不是缩短;每个效果的起点都必须与终点不同(也就是「换了新效果却什么都没发生」);每个效果结束时都必须完全可见且**没有残留缩放**——一次没有复位的 zoom 会让之后每一张壁纸都被放大裁掉一圈。
|
|
220
|
+
- **`check:repaint`** — 「这次编辑要不要重画界面」的判定(`shouldRepaint`),其中就包含实际踩过的那个坑:**这次编辑本身**制造出了生效规则(某条规则的第一张图、第一个颜色或自动提取出的颜色)时,即使被编辑的规则此刻还不是生效规则,也必须立刻重画。它同时还会在 `src/client/index.tsx` 里任何一条写入路径不再询问这个判定时报错——也就是说,把老的 `id === activeRuleId` 判断写回去,会是构建校验失败,而不是你下一次上传时界面不动;轮换步骤不再重发调色板(主题色属于图片,换图就是换配色)同样会被它拦下。
|
|
221
|
+
- **`check:ui`** — 每个 `t('…')` 键在中英两本字典里都存在、两本字典键集完全一致、每个 `dab-…` 类在样式表里都有规则,且没有字典条目变成没人引用的死键。
|
|
222
|
+
- **`check:node`** — 把构建好的 node 半边通过它真实的 RPC 处理器跑一遍,`DSH_HOME` 指向临时目录:节日配置块穿过共享的 sanitizer、内置壁纸从空槽位被送出(且不会因此写进数据目录)、节日槽位拒绝写入 / 删除 / 抓取而丢进去的文件被忽略、普通规则槽位照常写入和删除,以及手改过的配置无法把节日指向别的规则的图片。它还覆盖逐图主题色这套形状:读取时抬升的两个方向(缺键继承规则色、显式 `null` 不继承)、颜色经过文件往返后各自独立,以及 `null` 是写出键而不是省略。切换效果同样在覆盖范围内:旧配置拿到的出厂默认、选定的效果 / 缓动 / 统一时长能原样穿过文件往返、非法值回退而夸张时长被夹紧、时长为 `0` 被保留而不是回退成默认,以及 `transition` 内部的字段漂移会被上报而不是悄悄丢掉。
|
|
223
|
+
|
|
224
|
+
## 常见问题
|
|
225
|
+
|
|
226
|
+
**所有模型看起来都一样,为什么?**
|
|
227
|
+
多半是第 1 条规则的匹配串是空的,它成了纯兜底、把整个列表兜住了。给规则 1 填一个匹配串,或把更具体的规则加到兜底规则**上面**。
|
|
228
|
+
|
|
229
|
+
**`GLM-Flash` 命中了不是我想用的规则。**
|
|
230
|
+
匹配是先命中者胜,而不是最精确者胜。把更具体的规则往上拖,或调整顺序让你想要的规则排在前面。
|
|
231
|
+
|
|
232
|
+
**图片存在哪?**
|
|
233
|
+
在 `~/.dsh/.dsh-background-by-model-data/`:每张图一个 `modelbg-<slot>` 文件,外加 `theme-config.json`。
|
|
234
|
+
|
|
235
|
+
**我开了轮换,背景却一直没变。**
|
|
236
|
+
有三件事会拦住它:规则至少要有两张图;标签页必须可见(隐藏的标签页什么都不画,轮换跟着一起停);只有当前模型解析出的那条规则在轮换——没生效的规则,「下一张」按钮就是灰的,正是这个原因。
|
|
237
|
+
|
|
238
|
+
**轮换有代价吗?**
|
|
239
|
+
有,所以默认关闭。每张图都按原始保真度保存(不做重编码),所以一条放了十张 8 MB 壁纸的规则就是十份 8 MB;每次换图还会重画整个界面。建议一组控制在两到五张、节奏也别太密。启动时只读每条规则的第一张,轮换也会提前预热它下一张要用的图,所以代价落在内存和磁盘上,而不是启动时间上。
|
|
240
|
+
|
|
241
|
+
**删掉规则里的图片之后,主题色为什么不起作用了?**
|
|
242
|
+
这是已经修掉的旧行为,根因是「有没有图」被当成了「这条规则是否可用」:图片删光的规则不再参与匹配,效果自然也就无从谈起,而它原本负责的模型还会被交给下一条规则。现在只要规则**有图、或者有自己的主题色**就仍然生效:不铺壁纸,只按这个颜色给界面配色(面板上会写明当前属于哪种状态)。连主题色也没有、也就是一点内容都没有的规则才会被跳过——「这条规则还没有图片,也没有自己的主题色:没有可显示的内容,匹配和兜底都会跳过它」。
|
|
243
|
+
|
|
244
|
+
**我更新了插件,面板说我的改动没有保存。**
|
|
245
|
+
浏览器半边和宿主半边是分开加载的:刷新页面后新客户端可能已经生效,而 DSH 主进程还在跑上一个版本的插件——它读不懂新的配置格式(`SCHEMA_VERSION` 比它低就知道),下一次写入就可能把规则丢掉。客户端检测到这种情况会**扣住所有配置写入**并提示你:重启 DSH 之后,多图配置、轮换设置等一切都会正常保存。
|
|
246
|
+
|
|
247
|
+
**我给一张图设了颜色,其它图片却没跟着变。**
|
|
248
|
+
这是设计如此:从 0.7.1 起主题色属于**图片**而不是规则,所以一组图可以依次是不同调性(绿的、红的、以及跟随系统主题的)。调色控件作用于胶片条里选中的那一张,控件上方的提示会写明是哪一张。唯一例外是**一张图都没有**的规则:那时控件编辑的是规则自己的主题色——那正是这种规则能画的东西,而且它刻意不作为该规则图片的默认值。
|
|
249
|
+
|
|
250
|
+
**更新之前我设的主题色去哪了?**
|
|
251
|
+
哪儿也没去:在「逐图主题色」之前写下的图片条目**根本没有** `color` 这个键,而这正是加载时用来区分「从来没有自己的颜色」和「被主动清空过」的依据——前者会把规则的颜色抬升到每一张这样的图上。所以带主题色的规则升级后观感完全一致,此后每张图就可以各自改色了。
|
|
252
|
+
|
|
253
|
+
**能分享整套配置吗?**
|
|
254
|
+
可以,在 **「配置」** 页导出即可;导出的 JSON 会把每条规则的图片内联进去。
|
|
255
|
+
|
|
256
|
+
**支持视频或生成式背景吗?**
|
|
257
|
+
不支持。两者都在 0.3.0 中移除,每条规则使用一张静态图片。
|
|
258
|
+
|
|
259
|
+
**把主题色切回「系统主题」后,界面和设置弹窗为什么不是一套配色?**
|
|
260
|
+
这是已经修掉的旧行为:清空主题色时插件只撤掉了 `body` 上那套令牌,设置弹窗里那三个**没有宿主回退**的重定向(`--dsw-alias-bg-layer-*` → 插件私有变量)以及轨迹页、三栏的内联背景都还留着上一次的颜色,于是出现「深色界面 + 浅色弹窗、白底白字」。现在这些表面统一由一个调色板来源驱动:有主题色时用规则自己的令牌,没有时**读取宿主当前令牌**再套上你的透明度重发,切换时一并交还宿主。
|
|
261
|
+
|
|
262
|
+
**切回「系统主题」后一开始还是浅色,拖一下滑块才变深,为什么?**
|
|
263
|
+
同一个洞的另一半:插件在持有主题色时会**强改** `body[data-ds-dark-theme]`(深色调色板写标记、浅色调色板直接删掉),而宿主只在**主题快照变化时**才重写这个标记(它不监听属性)。于是浅色皮肤留下的「标记被删」会一直生效,插件在切回系统主题那一刻读到的就是宿主的浅色调色板,并且之后没有任何事件再去重读——直到你碰了某个滑块。现在:切换时同步交还标记(宿主深色就写成宿主的布尔形式),并把宿主解析出的配色方案(`ctx.theme` 的 `active.colorScheme`,过期则回退到 `html[data-ds-theme-source]` + `prefers-color-scheme`)推给渲染层;每秒的守护定时器在「无主题色」状态下也会重读一次宿主调色板,变了就重画。
|
|
264
|
+
|
|
265
|
+
**为什么「自定义颜色」点下去就有颜色了?**
|
|
266
|
+
因为按下它就等于离开「跟随系统主题」,必须给出一个起始色。它先跑一次「从本图提取」(和「从本图提取」按钮同一条链路),取不到鲜明颜色时才退回默认色,所以不会再出现「点一下就从浅色跳成一块跟壁纸无关的深蓝」。
|
|
267
|
+
|
|
268
|
+
**我换了新的切换效果,壁纸还是直接跳过去。**
|
|
269
|
+
有两件事会拦住它,而且两件都在那张卡上:效果是**「直接切换」**;或者时长是 `0`(效果和时长是同一个硬切的两种说法,而效果优先)。第三件不在插件里:系统开了**「减少动态效果」**时完全不做动画,卡片也会直说。
|
|
270
|
+
|
|
271
|
+
## 近期优化
|
|
272
|
+
|
|
273
|
+
> 这里只列最近两个版本;更早的版本(v0.7.3 及以前)见 [CHANGELOG.zh.md](./CHANGELOG.zh.md)。
|
|
274
|
+
|
|
275
|
+
### v0.7.5
|
|
276
|
+
|
|
277
|
+
- **布局模式属于图片,不属于规则** —— 适应 / 填充 / 拉伸 / 平铺 / 居中 此前是每条规则一个值,于是一轮里既有横构图照片又有竖屏截图时,没法让一张留黑边、另一张铺满。现在它存在 `images[].bgMode` 上、从**正在画的那张图**读回,胶片条下面那排胶囊编辑的也是那里选中的图(规则还没有图片时是**禁用**而不是隐藏)。`SCHEMA_VERSION` 因此升到 **6**,因为两个方向都是无声的:schema 5 的宿主会在第一次写入时丢掉逐图模式(设成 拉伸 的图变回 适应),而 schema 6 读老配置时会把规则级的值抬到每一张图上,现成壁纸不会掉到默认值。节日的图按**定义**就是 填充(和它旁边的槽位、颜色同一条规矩),旁边的取景仍然是你自己的。
|
|
278
|
+
- **渐变只作用于当前调色板真正写入的东西(修复)** —— 「有时候切换背景时,白色色块会渐变为黑色色块…白色渐变完黑色后立马切到白色」,白色值量到 `237, 243, 254`。那就是 `#edf3fe` = `--dsw-static-deepseek-50`,也就是宿主浅色方案的 `--dsw-specific-bubble`(你自己的消息气泡;深色方案是 `#2c2c2e`)。渐变之所以注册了这个名字,是因为它要的是**深色**分支的 token 表、又把整张表交给了 `:root`/`body` —— 浅色分支只写这 80 个名字里的 35 个,剩下 45 个(气泡、设置里的下拉框底色、提示与气泡框、代码块右上角小按钮、状态色)仍然归**宿主**;而让宿主短暂换方案的正是插件自己:每次换配色都销毁并重新注册主题,宿主的销毁器把偏好重置为 `system`,在深色桌面上那一瞬间画的就是宿主的深色调色板。配上报告里 3000ms 的切换时长,一帧的错色就成了三秒的渐变。现在只有当前调色板真正写入的 token 才会拿到过渡(注册表仍是全部 80 个,深色调色板完全没变),配色方案没变也不再重建皮肤。实测:`body` 的过渡列表 80 → 35 个名字,气泡与下拉框出局,`--dsw-alias-bg-base` / `-layer-2` / 代码块底板仍在。
|
|
279
|
+
- **代码块跟着调色板走,底板有了自己的透明度(修复)** —— 「代码块背景有点问题」:浅色界面里深绿文字压在近黑底板上。宿主的 shiki 表在 `:root` 上声明 `--shiki-background: var(--dsw-alias-markdown-code-block)`,而该 token 只声明在 `body` 上,于是根元素只能读到过渡注册的 `initial-value` —— 采样一次的宿主颜色。现在调色板规则对 `:root` 一并发出(`:root` 也加入渐变作用域),底板与 banner 重新是调色板的染色,并新增 **`code`** 档位驱动这两块表面、各读自己的变量,默认不透明。
|
|
280
|
+
- **四个小修** —— 删图删到不足两张时轮换开关不再卡在「开」(面板在那里本来就把它禁用了,于是也关不掉;`normalizeRule` 对导入的配置强制同一条不变量);「切换时长」只印一次;资料页页脚的包名与品牌磁贴现在是指向仓库的链接,`check:ui` 拿那一个地址和 `package.json` 对比。
|
|
281
|
+
- **门禁** —— `pnpm test` 现在是**八道**:`check:code-plate` 与 `check:image-mode` 加入,`check:rotation` 增加开关不变量,`check:ui` 增加链接一致性,`check:transition` 增加渐变归属规则,`check:repaint` 钉住武装渐变的那两行。
|
|
282
|
+
|
|
283
|
+
### v0.7.4
|
|
284
|
+
|
|
285
|
+
- **弹窗里的控件现在和壁纸走同一个时钟,而不是等它切完再跳(修复)** —— 换主题色那一下,「节日特殊背景」的开关填充和「平移推入」「标准」这些胶囊按钮会**整整一套切换时长**停在上一套颜色上,直到背景切完才瞬间换成新的:一次 3 秒的换图看起来就是"界面先不管它、末尾来一下硬切"。成因是插件自己造成的:淡入把**整张 token 表**挂到了三个元素上,而其中两个(设置弹窗与轨迹页根节点)**只重新声明**三个 layer token、其余全靠继承。给一个*继承来的* token 挂过渡,该元素的过渡目标就是武装那一刻它看到的值 —— 祖先正在插值,那个值还是旧的 —— 于是它变成一条被阻尼的过渡、整棵子树跟着走(实测:1200ms 过渡在 t=1500ms 只走到 113/255,而只继承、自己没有过渡的消费者是逐帧跟随)。现在过渡表按作用域给,每个作用域只拿自己声明的 token。
|
|
286
|
+
- **用插件自有颜色画的那几块表面,现在也淡入了(修复)** —— 设置弹窗底板、文件预览面板、Cordis 面板都不是用注册过的 alias token 画的,而是用插件自有、内联写在 `<html>` 上的变量;未注册的变量根本不能插值,所以它们在一帧之内硬切,而周围每一块都在渐变。现在淡入作用域可以点一个**标准属性**(`background-color`),并且每条上色规则与它的淡入共用同一个选择器常量,两半不可能再走岔。拿真实产出的 CSS 实测、跑一次 3000ms `ease`:底板、右侧面板、Cordis 面板在第一次采样时就已经是**终色**并且再没动过,而现在五块表面每一次采样都处在同一进度 —— t=1500ms 时 80.2%,恰好是 `ease(0.5)`。
|
|
287
|
+
|
|
288
|
+
## Star History
|
|
289
|
+
|
|
290
|
+
[](https://www.star-history.com/?repos=HarmlessFunny%2Fdsh-background-by-model&type=timeline&legend=bottom-right)
|
|
291
|
+
|
|
292
|
+
## 许可
|
|
293
|
+
|
|
294
|
+
MIT
|