DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

zmengle /

zmengle/dsh-plugin-sticky-wall

Verified

DSH 便签墙插件:侧栏一块可自由摆放的便签墙 + 4 个 sticky_wall_* 模型工具(A sticky-note wall for DeepSeek Harness)

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@549248ee

便签墙 · dsh-plugin-sticky-wall

DSH 侧栏里的一面便签墙:随手贴、随手拖、随手改,并且模型能直接往上贴。 不是待办清单——待办有 todo_write;便签墙放的是那些「先记一下」的碎片, 要清单也能就地长成清单。

便签墙

一张清单便签

折叠

回收站抽屉

滚动到底

提示条不互相顶掉

功能

  • 侧栏一个图标,主面板一面墙:注册 sidebar.panellist(id = sticky-wall)+ main 同名 key, 点图标切到主面板,和 QQ 机器人面板同一套机制。
  • 一行一种格式:正文 / ☐ 待办 / • 无序 / 1. 有序,四种混排。 待办点方框即「已完成」(打勾 + 删除线),抬头显示 1/3 进度。 行首敲「- 」「1. 」「- [ ] 」直接变成对应格式;悬停纸条底部还有四个格式按钮, 作用在「当前这一行」上,点一下就能切换,再点「≡」回到普通正文。
  • 横线纸可选:抬头那个「带横线的纸」图标,点一下在横线纸 / 空白纸之间切换,逐张便签独立记。 横线按 14px/22px 的行距画在每行下沿,字正好落在线上;纸高按整行增长,永远不会切半行。
  • 纸的质感:8 种纸色(亮纸 + 深墨)+ 细颗粒噪声 + 左上柔光 + 下沿压暗 + 8px 圆角(纸面内容按圆角裁切)+ 内外两层阴影。不做倾斜——旋转层里的文字会丢次像素抗锯齿, 看着发虚,所以纸是摆正的。
  • 可调大小:右下角的斜线手柄(悬停出现)拖一下就能改大小——宽 196–560px, 高按 22px 的整行增减,双击手柄回默认;窄到 240px 以下时底部调色盘自动收起,把位置让给行格式按钮。
  • 一键折叠:抬头最左边那个「∨」把纸条收成两行(底部渐隐 + 一个「展开」小胶囊),点正文或再点一次「∧」展开。 折叠只截高度、不动宽度——宽度是你拖出来的,不该被自动改掉。折叠状态跟着便签存。 折叠时正文是只读的,但可以直接选词复制:拖选不会把纸展开(只有不带选区的点击才展开)。
  • 回收站:删除(胶头 🗑、清空墙面、模型工具都算)只是把便签移进右侧回收站,不会立刻销毁; 工具栏右边的「回收站」(带数量)点开是抽屉:逐张「恢复」或「彻底删除」,也可以一次清空回收站。 抽屉默认收起,图钉可固定(固定后点别处不会自动收起,状态记在本地);删除后 toast 里还有「撤销」直达; Esc 也能关抽屉(正在写便签时 Esc 优先给输入框)。 恢复时如果原来那块地方已经被别的纸占了(重叠超过自身面积 20%),会自动挪到第一个空格子并提示。
  • 随手摆放:按住纸头(含六点抓手的那条)拖到任意位置,落点按百分比存, 面板宽窄变了也不会散架。双击空白处即在点击处新建一张。
  • 就地编辑:每行都是一个输入框,点进去直接改;输入 0.65s 后自动落盘, 失焦 / ⌘/Ctrl+Enter / Esc 都会立即保存。回车拆行、行首退格并回上一行、↑↓ 跨行移动。
  • 纸色 / 置顶 / 删除:悬停纸条出现调色圆点;置顶的纸永远在最上层(顶部一道墨色压边)。
  • 搜索 / 只看置顶 / 整理 / 清空:搜索按正文过滤;「整理」是流式重排(见下); 清空需要点两次。
  • 整理 = 对齐,不是重排:按你摆的位置把便签聚成行(y 差 56px 内算同一行), 行内保持你的左右顺序、统一左对齐、间距 16px;行与行按「这一行最高 + 16px」往下排, 左边距 18px。不会因为某张纸大就把它排到后面去——宽纸还待在它那一行里。 一行真的比面板宽时,先把行内间距压到 8px,仍放不下才把这一行末尾的几张挪到下一行。
  • 跨会话持久化:$DSH_HOME/sticky-wall.json(默认 ~/.dsh/sticky-wall.json),原子写。
  • 和模型联动:4 个工具,说一句「把这条记到便签墙」就会真的贴上; 模型贴来的 Markdown(- [ ] / - / 1. )会自动解析成复选框和列表; 模型贴的便签 6 秒内自动出现在墙面上(面板可见时轮询)。

交互一览

操作 效果
点侧栏「便签墙」图标 切到便签墙主面板
点「新建便签」 新建并聚焦第一行
双击墙面空白处 在该处新建一张
按住纸头拖动 移动便签(松手保存)
回车 在当前行下方拆出一行(同格式)
行首退格 列表/待办行先退回正文;空行则并到上一行
敲「- 」「1. 」「- [ ] 」 当前行变成无序 / 有序 / 待办
点待办方框 打勾(已完成,带删除线)
悬停 → 底部 ≡ ☐ • 1. 把当前行切成 正文 / 待办 / 无序 / 有序
悬停 → 右下角斜线手柄 拖动改大小(宽 196–560px、高按整行);双击回默认
悬停 → 抬头 ∨ / ∧ 折叠成两行 / 展开(点正文也能展开)
悬停 → 抬头方格图标 横线纸开 / 关
悬停 → 调色圆点 换纸色
悬停 → 📌 / 🗑 置顶 / 移进回收站(可撤销)
工具栏「回收站」(带数量) 打开右侧抽屉(图钉可固定,状态记在本地)
回收站 → 恢复 / 彻底删除 放回墙面(最上层)/ 真正销毁
墙面右下 ↑ / ↓ 一键到最上 / 最下(只有内容超出一屏时才出现,到头的那个变灰)
「只看置顶」筛选 只看置顶便签(和抬头那个「置顶」不是一回事)
「整理」 / 「清空」 对齐排布 / 连点两次清空(清空也进回收站)
页脚右侧的路径 数据文件位置,点一下复制路径

模型工具

工具 用途
sticky_wall_list 读墙上的便签(id、纸色、时间、正文;清单会带 - [ ] / 1. 标记),可按 pinned/query 过滤;回收站里的不列
sticky_wall_add 贴一张新便签(text 必填,支持 Markdown 清单,color、pinned 可选)
sticky_wall_update 改正文 / 纸色 / 置顶(正文会重新解析成行,勾选状态会重置;回收站里的便签要先恢复)
sticky_wall_remove 移到回收站(软删除,可用 sticky_wall_restore 恢复)
sticky_wall_restore 把回收站里的便签恢复回墙面(恢复后在最上层)

返回文本里带 [n-xxxxxx] 这样的短 id,后续 update/remove 用它。

数据与隐私

  • 全部数据只存在本机(默认 ~/.dsh/sticky-wall.json,路径可配置,见下),不上传、不联网。
  • 一张便签 = lines[](每行 kind/text/done)+ 纸色/位置/置顶/横线开关 + 尺寸(w、minLines)
    • 折叠状态(collapsed)+ 回收站标记(trashed、deletedAt); text 是从行派生的可读副本,给搜索和工具用——所以老数据(只有 text)能直接读, 下次保存时自动升级成行结构。
  • 回收站是同一份数组里的软删除(打标记),所以「恢复」是无损的:位置、尺寸、纸色、勾选状态全都还在。 容量 500 张 / 30 天:超期在加载时清掉;超过 500 张则在删除那一刻挤掉最旧的一张并打日志 ——「丢」只发生在看得见的删除动作上,读盘时绝不裁剪(老版本会按 100 截断,清空后重启会静默丢便签)。
  • 上限:500 张便签、每张 200 行 / 每行 1000 字 / 合计 4000 字;超出直接拒绝而不是悄悄截断。 回收站里的不占墙面名额(各算各的 500)。
  • 首次加载会在文件缺失时放两张欢迎便签,之后不再写入任何默认内容。

配置:把数据放到别处

默认落在 $DSH_HOME/sticky-wall.json(一般就是 ~/.dsh/sticky-wall.json)。 想换位置就改插件配置里的 storePath,然后重启 DSH:

# cordis.patch.yml
- insert:
    - id: sticky-wall
      name: dsh-plugin-sticky-wall
      config:
        storePath: D:/notes/sticky-wall.json   # 绝对路径、~/notes/...、或相对 $DSH_HOME 的路径都行
  • 换路径时如果新文件还不存在、而默认文件在,会先把默认文件复制过去,不会让老便签凭空消失。
  • 当前实际用的路径显示在面板页脚右侧(…/.dsh/sticky-wall.json),点一下复制;改过配置会高亮成主题色。
  • 这个配置只在宿主侧生效,改完需要重启 DSH(和其它宿主改动一样)。

结构与实现要点

dsh-plugin-sticky-wall/
├── package.json        # dsh.bundle.patch + dsh.client.platform=web + exports["./client"]
├── cordis.patch.yml    # 插入一行:id=sticky-wall, name=dsh-plugin-sticky-wall
├── index.js            # Host 半侧:行模型 / 存储 / HTTP 端点 / 5 个模型工具(零第三方依赖)
├── client.js           # Client 半侧:ModuleLoader bundle,两处 slot 注册 + 整面墙的 UI
└── docs/               # 截图
  • 双面插件:Host 起 webServer 前缀路由 /api/dsh-sticky-wall/*,Client 同源 fetch 读写, 不碰 typert/remote,也就没有版本适配问题。
  • 端点:/snapshot、/upsert、/remove(软删除)、/restore、/purge、/purge-all、/clear(也是软删除)。 除了 upsert 的 saved/skipped/full,回包统一带 { notes, trash, trashCount, colors, store },客户端一份合并逻辑就能覆盖所有动作。
  • 两条瘦身通道(回收站和墙都可能很大,别每次全量搬):
    • /snapshot?trash=0 只回 trashCount,明细留空。客户端轮询用它,条数变了才补拉一次明细(抽屉打开时也会补)。
    • /upsert 带 light: true 时不回整面墙(保存回包实测 1.1MB → 几 KB)。客户端保存只等 ack,本地就是权威。
  • 写盘:全量 JSON 原子写(tmp + rename),但内容没变就跳过;写失败会作废「已落盘」标记,下次同样的内容还会再写。
  • 同源校验:每个请求都过一道 Sec-Fetch-Site / Origin 检查,跨站直接 403;POST 只接受 application/json (跨站的「简单请求」只能用 text/plain,这一条把它们全挡掉)。这样本机别的页面就没法偷偷改/清你的便签了 —— 顺手也挡住了 CSRF 那类玩法(实测:本机 4398 端口的页面写入被拒,数据 0 变化)。
  • 层级:便签 z-index ≤ 40000(100 + z,置顶 +20000)→ 滚动按钮 43000 → 抽屉遮罩 44000 → 抽屉 44100 → toast 50000。 抽屉和遮罩都挂在新加的 .sw-main(工具栏以下那一块)里,所以既盖得住便签,又不会糊住工具栏和页脚。
  • 未知字段原样保留:normalizeNote 只收敛已知字段,其余键(跳过 __proto__ 之类)原样写回。 这样以后客户端只加 UI 字段时,不用再改宿主、也不用重启。
  • 折叠:collapsed 布尔值存进便签;CSS 用 max-height: calc(lh*2 + 上下内边距) 截断 + mask-image 渐隐, 正文设 pointer-events: none 让点击落到 body 上「点一下展开」;底部菜单同时 display: none。
  • 回收站抽屉的「固定/收起」偏好存在 localStorage(dsh-sticky-wall:trash),不占便签数据。
  • client.js 是手写的 ModuleLoader bundle(window.__ModuleLoader__.load({ id, factory })), 只 require('react')——平台种子表提供,不需要构建步骤,改完刷新页面即生效。
  • 渲染性能:每张便签 React.memo,只收 note + focusId 两个 prop,不订阅 store; 打字时只有正在编辑的那一张重渲染。实测 200 张便签下从 42.7ms/键降到 6.7ms/键(20 张 4.5ms/键)。
  • 行模型:lines: [{ id, kind, text, done }],kind ∈ text|todo|ul|ol。 有序列表按「连续 ol 段」在前端重新编号,所以增删行不用重写编号; textFromLines() / linesFromText() 在两端各有一份同构实现,保证工具写入与老数据解析一致。
  • 横线是 background 画的,不是额外元素: .sw-body 用 linear-gradient 画 1px、background-size: 100% 22px, background-position-y = 行距 + 上内边距,所以第一条横线正好是第一行的下沿; 每个行盒高度都吸附到 22px 的整数倍,横线不会被切半。改行距只需同步 LINE_H(JS)与 --sw-lh(CSS),NOTE_W 决定网格列数。
  • 写入的并发安全:每次本地改动会给该便签打一个自增 revision;保存回包返回时 只有 revision 没变才清 dirty,否则保留本地版本(避免「勾选的同时旧保存回包把状态盖回去」)。
  • 尺寸:w(px,196–560)与 minLines(1–30,按 22px 行高换算)。 拖手柄时只改元素的内联宽高与 --sw-min-lines(实时预览),松手才写回 store; 高度用 min-height 表达,所以便签永远「至少这么高、内容多了自己长」。
  • 窄便签自适应:.sw-note 开了 container-type: inline-size, 容器查询在 ≤240px 时收起调色盘;纸用 overflow: hidden + 8px 圆角,横线会被圆角自然裁掉。
  • 整理的量尺:直接读 DOM(offsetWidth/offsetHeight)拿每张纸的真实尺寸, 被搜索过滤掉、量不到的才用 行数 × 22 + 头尾 估算;先按现有 y 聚行、行内按 x 排序, 再统一落位。整定是幂等的:连点两次结果一样(第一次排完就已经是对齐状态)。 排完若内容高于画布,把画布 min-height 撑到 内容高 / 0.84, 既让点阵随之延长,也保证最后一行换算成百分比后不超过宿主侧 88% 的 y 上限。
  • 图标:全部是 24 网格的 path,不用文字字形(≡ ☐ • 1. 那种会受字体影响、基线与重量都不齐)。 描边按尺寸取:≤20px 用 2(12px 时正好 1px 实心线),更大的用 1.6;圆头圆角。 行格式四个按钮是 18px 图标配 22px 按钮,抬头三个小图标 13px 配 20px 按钮; 小尺寸的图形都做了减法(垃圾桶去掉内部竖线、横线纸只画两条线、抓手点放大到 1.5), 免得 12–13px 时糊成一团。
  • 纸面质感全在 CSS:SVG feTurbulence 噪声(data URI)+ 柔光 + 下沿压暗 + 内外阴影, 文字不做变形,保证 1x 屏上也是清楚的。
  • 颜色一律走 DSH 主题令牌(--dsw-alias-*),纸色是固定的亮纸深墨, 所以浅色/深色主题下都像「桌上的纸」而不是「界面里的卡片」;横线与复选框描边是 color-mix(in srgb, currentColor 16~58%, transparent),跟着纸的墨色走。
  • 样式通过 data-plugin + data-plugin-css 标记注入;热替换时若旧标签还在, installStyles() 会比较内容并原地改写,避免新样式被幂等判断挡掉。

安装 / 卸载

# 装(profile 里以 file: 依赖链接本目录)
dsh plugin add D:/workspace/dsh/dsh-plugin-sticky-wall
# 或直接让 agent 调 plugin_manager install_bundle

# 卸载
dsh plugin remove dsh-plugin-sticky-wall

已知限制

  • 便签是自由摆放的:窗口变得很窄时可能出现重叠,用「整理」重排即可。
  • 高度只有「最少几行」这一个维度:内容比它高时纸会自己长,所以拖高只会变高、不会把内容裁掉。
  • 列表只有一层,不支持嵌套;每行一个格式,不混排(正文行里不能再嵌入列表)。
  • 轮询间隔 6 秒,多窗口同开时另一边的改动最多滞后一个周期。
  • 工具改正文会重建行,勾选状态会丢;要保留勾选请只在 UI 里改。
  • 删除有回收站兜底(30 天 / 500 张),但「彻底删除」和「清空回收站」不可撤销。
  • 写盘是整文件重写:实测 50 张(94KB)一次保存往返 3.4ms,顶到上限 500 张 + 100 张回收站(1.1MB)是 11.4ms ——够用,但再往上(几千张)就该换成增量格式或 SQLite 了。这也是「单文件 + 全量写」这个设计的真实上限。
  • 不做富文本/附件——便签就该是纯文本。
  • 鉴权沿用 DSH 自身的本地回环边界:接口做了同源校验(跨站 403、非 JSON 415), 但同一台机器上的进程(脚本、其它本地程序)仍然能直接读写那个 JSON 文件——这是本地应用的固有边界。
—/ 5

No ratings yet

Verified DSH bundle

Commit 549248ee3e8b

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout