IM2005 — 2005 年代即时通讯风格皮肤 · DeepSeek Harness
把 DeepSeek Harness 桌面端换成 2005 年即时通讯软件的样子:直角窗口、1px 硬边框、宋体、蓝色渐变标题栏、好友分组式侧栏,还有一条"形象秀"右侧列。
这是一个非官方的第三方皮肤插件。 与任何即时通讯厂商(包括腾讯 / QQ)无关联、未获授权、未获赞助。
插件内不含任何第三方图片、图标、商标或字体资源 —— 全部美术为原创 SVG(详见 NOTICE.md)。
效果
📸 截图(实例,图片要本地设置,尊重版权问题):
功能
安装
前置
- 已安装 DeepSeek Harness 桌面端
- Node.js(如果要用命令行安装方式)
方式 A:命令行安装(推荐)
# 1) 把本仓库放到一个固定位置(link 安装后不能删)
# 例如 D:\plugins\dsh-skin-im2005
# 2) 指向它安装(把 <DSH安装目录> 换成你自己的)
$env:DSH_HOME = "$env:USERPROFILE\.dsh"
& '<DSH安装目录>\resources\runtime\cli\bin\dsh.cmd' plugin --profile desktop `
add 'link:D:\plugins\dsh-skin-im2005'
# 3) 完全退出并重启客户端
方式 B:手工放置
- 把整个文件夹放到
<DSH_HOME>\profiles\desktop\node_modules\dsh-skin-im2005
- 编辑
<DSH_HOME>\profiles\desktop\package.json,在 dsh.profile.bundles 里加上 "dsh-skin-im2005"
- 完全退出并重启客户端
⚠️ 注意:命令行安装方式会重算 dsh.profile.bundles,有可能挤掉你已装的其它插件条目。
装完请检查那个 package.json,必要时手工补回。
卸载
& '<DSH安装目录>\resources\runtime\cli\bin\dsh.cmd' plugin --profile desktop remove dsh-skin-im2005
使用
数据存在浏览器本地(localStorage),不上传、不采集:
自定义美术
插件只带原创 SVG 兜底,默认没有任何照片。想换成自己的图:
# 1) 准备三张图,放进 assets/,按这个命名:
# my-show.jpg 形象秀立绘(人像/角色图)
# mascot.png 小图标(方形、建议带透明通道)
# avatar.png 头像(方形)
# 2) 内联进 client.js
node tools/embed-asset.mjs
# 3) 刷新客户端
删掉 assets/ 里任意一张图也不会坏 —— 对应位置会自动回退到内置原创 SVG,界面不会缺图。
请只放入你有权使用的图片。把别人的美术资源打包分发可能侵权,与本项目无关。
开发
# 语法检查
node --check client.js
# 回归测试(40+ 断言:复刻宿主真实的 token 校验规则、渲染全部组件、点击所有控件)
node tools/self-test.mjs
项目结构
package.json # dsh.bundle.patch + dsh.client{platform,immediately,inject}
cordis.patch.yml # 只 insert 一行:挂载本包
index.js # Host 半区(空实现,只为满足 bundle 契约)
client.js # 全部视觉逻辑:主题 token + 8 条 slot 注册 + chrome CSS
locale/{zh,en}.json # 插件卡片文案
icon.svg # 原创图标
tools/embed-asset.mjs # 把 assets/ 里的图内联进 client.js(可选,见"自定义美术")
tools/self-test.mjs # 离线回归测试,不需要启动客户端
实现要点(想改代码的话)
插件只做三件事,不读写其它插件的 DOM、不注册全局:
- 主题层 ——
ctx.theme.overrideTokens() 覆盖约 42 个设计 token(圆角 / 描边 / 阴影 / 字体 / 颜色),按 {light, dark} 成对给。
- 装饰层 —— 往宿主声明的
list 槽里注册自己的 React 组件(每一条都套了错误边界,插件渲染出错不会拖垮宿主)。
- chrome CSS —— 一小段注入的
<style>,用语义属性([data-windows-titlebar]、[data-chat-flow-kind]、[data-clock]、[data-row-key] …)和 CSS-module 局部名后缀给宿主已有元素上色。选择器匹配不上时是无害空操作,不可能让宿主编译或运行失败。
许可
- 代码:MIT —— 随便用、改、分发,保留版权声明即可。
- 美术:本项目自带的美术(
icon.svg、内置 SVG 立绘/图标)为原创。
- 不含第三方资源:仓库里没有形象秀立绘、图标、表情包、字体等任何第三方素材。
免责声明
本项目是独立开发的、非官方的界面美化插件,出于对 2005 年代即时通讯软件视觉语言的致敬性再创作。
- 与腾讯、QQ 或任何即时通讯厂商无任何关联,未获其授权、赞助或认可。
- 不包含、不要求、不分发任何第三方的商标、图片、图标、字体或其它受版权保护的资源。
- 界面风格为年代风格的通用视觉元素(直角窗口、1px 硬边框、宋体、蓝色渐变标题栏、分组列表),并非任何特定产品的复制品。
- 若权利人认为本项目有任何不妥,请开 issue 联系,会立即处理。
致谢
更新日志
v1.16.3
修:皮肤浮窗仍盖住宿主菜单("选了工作区又弹回未选择")
- 症状:新开会话后选择工作区,选完自动弹回未选择;侧栏里那个会话显示在未定义工作区。
- 根因:v1.16.2 把皮肤层级从
2147483000 降到 900,以为"只要低于模态框(1000)就行"。但
宿主的下拉菜单只有 z-index: 101(primitives/Menu.module.css),而工作区选择器正是宿主的一个菜单 ——
目录浏览器(模态框)确实能打开了,可菜单里的项仍被皮肤压住点不到,于是选择不生效。
- 修法:皮肤层级降到 90,落在 (70, 100):压过布局框架(10–20)、侧栏按钮(30)、dockkit 右栏(40/70),
但低于菜单(100/101)与模态框(1000)。宿主的下拉、菜单、对话框从此全部正常接收点击。
- 教训写进了 README §4.14:"只要低于模态框就行"是错的,菜单只有 101 ——
凡是"宿主弹出来让用户选一个东西"的层,皮肤都必须让路。
- 断言升级:源码里每一处
zIndex 表达式必须落在 (70, 100),且不许再出现"压过一切"的字面量
(改回 900 或 2147483000,测试立刻变红 —— 两种都验证过)。
- 其它一律没动:功能、按钮位置、四个小游戏、所有存档格式不变。
v1.16.2
修:皮肤浮窗压在宿主对话框之上("选不了工作区")
- 症状:在一个工作区里新开会话后,「选择工作区」的目录选择器点不动、选不中。
- 根因:皮肤所有浮窗用的层级是
2147483000,而宿主的模态框层是 z-index: 1000 ——
皮肤每一个浮窗(右侧 QQ 秀列、各游戏窗口、跨会话备注框、余额框…)都盖在模态框和它的遮罩之上,
点击落在皮肤上,模态框收不到事件。
- 修法:皮肤层级降到 900:仍压过布局框架(10–20)、侧栏按钮(30)、菜单(100/101),
但低于模态框(1000)与模态框内的弹层(1100) —— 任何宿主对话框都会盖在皮肤之上、正常接收点击。
- 顺带钉住:源码里每一处
zIndex 表达式求值必须落在 (101, 1000);代码里不许再出现
2147483000 这种"压过一切"的字面量(改回旧值测试立刻变红)。
- 其它一律没动:功能、按钮位置、四个小游戏、所有存档格式不变。
v1.16.1
修:德州扑克拿到顺子时牌桌会消失
- 症状:玩着玩着牌桌自己没了(只剩一个小红
⚠),重开也一样。
- 根因:评估器"顺子"那一支把「参与比大小的 5 张牌」写成了内部对象
{high, ranks},
界面给这 5 张牌描金边时调 .indexOf() 抛错。牌型判定、牌型名、摊牌解释其实全对,
只有金边高亮这一步炸掉 —— 但抛在渲染期,被错误边界隔离,代价是整张牌桌消失。
自己拿到顺子时才触发(四个人打,十几局就会遇到一次)。
- 修法:那一支传真正的 5 张牌数组;金边高亮加数组类型防御(画不出金边可以忍,把窗口搞没不行)。
- 顺带:渲染之外的引擎调用全部兜底并把错误写真到可查处;错误边界也会留错误原文;
新增"耐久测试"——200 局、每个动作之后都渲染一次真实界面,这次就是它抓到的
(单元断言与牌型穷举都发现不了:那个错误只在"我拿到顺子"这种具体牌面下出现)。
v1.16.0
新增:德州扑克(6 人桌)
- 工具条上的
德州扑克 按钮。你 + 5 个电脑,翻牌前 / 翻牌 / 转牌 / 河牌四轮,
动作只有 过牌 / 跟注 / 下注-加注(固定档位)/ 弃牌;筹码独立于工具栏「余额」,输光自动重买。
- 核心是牌型辅助(这是做它的原因):
- 右侧常驻九档天梯(高 → 低),当前牌型高亮;每档还带一列「打平时怎么比」
—— 七张牌口径下一对 + 两对 + 高牌占 84.7% 的牌局,新手真正输钱的地方是踢脚,不是九档顺序。
- 实时读数
你:两对(K 和 7):由 7 选 5 的最优组合算出,并把参与比大小的那 5 张描上金边。
- 摊牌时给一句人话解释:
两家都是同花,从大到小逐张比:菲菲 的 K 比 Q 大。
- 还差什么:同花听牌 / 两头顺 / 卡顺。不显示任何没前提的胜率数字。
- 天梯是 9 档不是 10 档:皇家同花顺 = A 高同花顺,只作第一档的标注 —— 避免"两个皇家谁大"的伪问题,
公共牌成皇家时也能正确判平局。
- 电脑有五种打法(紧凶 / 跟注站 / 岩石 / 松凶 / 疯子,悬停可见),诈唬频率刻意低于 GTO 但不为 0;
胜率函数只吃自己的底牌 + 公共牌,物理上看不到别人的牌。
- 每步自动存档,关掉再开接着打;音效同样受「专注模式」管辖。
修
- 工具条按钮顺序:
德州扑克 与另外三个游戏挨着(排在 后台任务 左边,专注模式 仍是最后一个)。
v1.15.0
新增
-
专注模式:工具条最右边的 专注模式 按钮,输入专注几分钟(1–180,默认 25),这段时间内插件一声都不响 ——
八球 / 扫雷 / 农场的音效全部静音,时间到自动恢复,也可以提前结束。面板关掉不影响计时;
存档存的是绝对结束时间,刷新界面、重开客户端都还算数。
这个功能的思路来自同作者的 dsh-quiet,两边管的是不同通道:
dsh-quiet 走宿主事件接缝做「窗口不在前台时闪任务栏」,本插件的专注模式走界面内静音。
它们各自独立计时、互不感知,可以同时用 —— 从这边开专注不会让 dsh-quiet 一起进入专注,反之亦然。
静音不改任何开关:判定写的是「现在是否还在专注时段」,所以在专注期间你不会发现
「游戏音效开关被偷偷关掉了」——专注结束后一切照旧。三个游戏各自的音效开关仍然各管各的。
v1.14.1
修复
- 美式八球:打进自己那一组的最后一颗球会被误判成犯规。"该打 8 号了吗"原来按击球之后的台面算,
而这一杆正好把自己最后一颗打进,于是被回灌成"你该打 8 号、却先碰到了别的球" = 犯规,回合白送对手。
用户那边看到的是"我明明打进最后一颗,怎么突然轮到电脑了"。
现在按出杆前的局面判定:打进最后一颗 → 继续出杆,下一杆才轮到打 8 号。
- 美式八球:轮到电脑时提示行无条件写"电脑在想…",把刚打完那一杆的判定(犯规原因 / 换人)全挡住了,
出错时没有任何线索。现在优先显示判定结果。
v1.14.0
新增
- 后台任务:工具条
后台任务,点开列出正在跑的会话(用时 / 子代理数 / 工具调用数 / 当前阶段 / 计划任务)。
刻意做成纯被动,不点就看不到(按钮上没有红点或角标),跑完不响也不弹提示。
用时由插件自己从"第一次看见它在跑"起算,界面抖动不会重置计时;只有窗口开着时才刷新,不做后台轮询。
改进
- 生成器清空输出目录时保留
.git 与 README.md(此前会连仓库历史一起删掉)。
v1.13.0
修复
- 美式八球:打开窗口时画布可能是空白的 —— 改为"渲染即同步画布 + 50ms 兜底重绘"。
- Token农场:音效开关不再改写全局音效状态(此前关掉农场声音会连带影响提醒音与其它小游戏)。
新增
- 跨会话备注框:所有会话共享的一块草稿纸,切换会话/重开窗口内容都在;每次输入即保存。
- 扫雷 20×20:左键翻开 · 右键插旗 · 单击数字连开(不必双击)。
- Token农场:一株植物,生长无上限(7 档视觉 +
×N 无限递进)。每完成一轮 AI 回复 +1 滴水,余额每降 ¥0.10 +1 滴;纯时间也会缓慢生长。没有收菜、进度不会倒退;植物:X 只换品种。
改进
- 新增静态审计断言:功能之间不许互相改写共享状态、不许跨功能写存储键。
- 发布校验:残留检查只扫描代码,注释中的品牌字样不再误报。
- 画布类窗口统一"打开即可见",不再需要先动一下鼠标。