dsh-workbuddy 🐂
> 今天还有多久下班?
我来上班只为三件事,尿喝白,电充饱,等下班。
给 DeepSeek Harness 加一个不打扰工作的下班倒计时、有效工时进度条和久坐提醒。
距离下班
02:37:18
██████████████░░░░ 72%> “现在出现的新需求原则上属于明天。”
---
四大誓言
这个插件可以不好玩,但不能违背以下四条。
1. Time Engine 必须准
- 倒计时与进度是两套计算:现实的
15:00 → 18:00就是还有三小时,午休不从倒计时里扣; - 进度只算有效工时:
09:00-12:00 / 13:30-18:00,12:45 的进度是 40%,不是 50%; - 每一秒都用
new Date()绝对时间重算,绝不remaining -= 1000:
17:40 合上电脑、18:10 打开,直接显示下班!,不许出现"还剩 20 分钟";
- 时间逻辑全部是纯函数,60+ 个单元测试盯着:边界时刻(12:00/13:30/18:00)、
特殊节点(60/30/10/1 分钟)、周末、休眠唤醒,全部要过。
2. UI 必须不侵入
- 只用 DSH 官方 Slot,不 querySelector、不改官方 DOM:
侧栏底部 sidebar.footer.action 一个 chip,全局浮层 shell.overlay 一个面板, 设置页 settings.plugin.item 一张与官方同款的可折叠卡片(默认收起,不抢视线);
- 浮层默认 click-through,不挡聊天、不抢焦点;
- 不占聊天区域,不弹模态框打断你干活;
- 通过 DSH 插件管理器安装和卸载,不修改官方页面 DOM。
3. 文案必须有梗
- 文案不写死在组件里:
messages[风格][场景]随机抽取; - 三种风格:正常 / 牛马 / 发疯;
- 每个阶段都有专属阴阳怪气:
```text 👀 最后一个小时。不要在这个时候接大需求。
🚪 10 分钟。现在出现的新需求,原则上属于明天。
🎉 下班!你今天已经失去了继续工作的权限。 ```
- 欢迎社区贡献新文案(
src/core/messages.ts,加一句话的事)。
4. 提醒必须不烦
- 久坐提醒按有效工时计时:午休自动暂停,不会在你吃饭时叫你起来走路;
- 同一次提醒绝不重复触发(去重 key 持久化,刷新页面也不补刀);
- 提醒卡片只有一个 [知道了]——没有"稍后提醒"、没有"今天关闭"、没有"永久关闭",
提醒间隔由你设置,最低 15 个有效工作分钟;
- 浏览器系统通知默认关闭,想要的人自己去设置里开。
---
功能一览
- 侧栏鱼进度:展开时鱼头沿灰色轨道游到当前进度,右侧跑马灯展示状态或提醒;侧栏收起后只保留可点击迷你鱼;
- 六种状态版式:上班前 / 上午 / 午休 / 下午 / 已下班 / 非工作日;
- 特殊阶段:剩余 60 / 30 / 10 / 1 分钟逐级切换文案,最后 1 分钟进入"准备跑路"版式,最后 10 秒巨型倒数;
- 下班庆祝:到点 🎉 动画 5 秒,纯 CSS,不用图片资源;
- 周末关怀:
😎 今天不用上班。你为什么打开了 DSH?(绝不显示"距离周一还有 37 小时",太折磨人); - 设置热生效:保存即写入
settings.yaml,倒计时立刻按新时间走,无需重启。
<details> <summary>查看设置界面</summary>

</details>
安装
前提:Node.js 22.19+,并已安装或可以通过 npx 运行 DSH。
从 GitHub 安装:
dsh plugin --profile web add github:heyxin-68/dsh-workbuddy发布到 npm 后也可以直接按包名安装:
dsh plugin --profile web add dsh-workbuddy本地开发时使用 link 安装:
dsh plugin --profile web add link:<本包绝对路径>插件声明了标准 dsh.bundle,DSH 会自动合并 cordis.patch.yml,无需手工编辑 profile。安装后刷新一次页面,侧栏底部就会出现倒计时 chip。
设置
DSH Settings → 插件 → 插件配置:工作时间、工作日、久坐提醒间隔、文案风格、系统通知。 保存后立即生效(写入 $DSH_HOME/settings.yaml 的 xiaban: 段,热重载)。
默认:
workStart: "09:00"
lunchStart: "12:00"
lunchEnd: "13:30"
workEnd: "18:00"
workdays: [1, 2, 3, 4, 5] # 周一到周五
reminderEnabled: true
reminderIntervalMinutes: 60
showSeconds: true
messageStyle: cow # normal / cow / crazy
browserNotifications: false开发
pnpm install
pnpm test # 时间引擎/提醒/文案/保存/发布清单
pnpm typecheck
pnpm build # 产出 lib/index.js(宿主)+ lib/client.js(浏览器 bundle)
pnpm pack --dry-run # 检查最终发布文件架构(实施方案 §21-§24):
src/
├── index.ts 宿主入口:注册 xiaban 设置命名空间
├── namespace.ts 宿主/客户端共享常量
├── types.ts 核心类型
├── config/
│ ├── schema.ts schemastery schema(宿主用)
│ ├── defaults.ts 默认配置
│ ├── validate.ts 保存前校验
│ └── wire.ts settings.yaml 扁平字段 ↔ 内部配置
├── core/ 纯函数,不依赖 React/DSH,全部可单测
│ ├── time.ts 状态机 / 倒计时 / 进度(绝对时间重算,防休眠漂移)
│ ├── reminder.ts 有效工时计时 / 触发判定 / 去重 key
│ ├── messages.ts 三种风格文案库
│ └── viewmodel.ts Time Engine → ViewModel
└── client/
├── index.ts apply(ctx):注册三处 UI 槽位
├── controller.ts 定时器 / 设置同步 / 提醒 / 庆祝
├── useXiaban.ts useSyncExternalStore 桥
├── XiabanChip.tsx 侧栏底部 chip
├── XiabanPanel.tsx 详细面板(六状态分支)
├── XiabanOverlay.tsx 面板 / 久坐提醒卡 / 下班庆祝
├── XiabanSettingsCard.tsx Plugins 设置卡片
└── styles.ts 全部 CSS(DSH 设计令牌)原则:UI 只消费 ViewModel,不做任何时间判断。所有"现在几点算什么状态"的问题, 只允许问 core/。
不做的事
番茄钟、Todo、工时系统、打卡、云同步、数据分析、夜班跨日班次。 不要把一个下班倒计时做成企业 OA。
许可
[MIT](LICENSE)