dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
浏览器式的整页缩放,给 DeepSeek Harness 桌面版用:按住 Ctrl 滚动滚轮(触控板双指捏合同理)即可像浏览器一样缩放整个界面,Ctrl + 0 回到 100%。
浏览器式的整页缩放,给 DeepSeek Harness 桌面版用:按住 Ctrl 滚动滚轮(触控板双指捏合同理)即可像浏览器一样缩放整个界面,Ctrl + 0 回到 100%。
网页版(浏览器打开的 Harness 地址)不受影响——浏览器自己已经有缩放快捷键,插件只在桌面窗口里生效(靠
window.dshDesktop是否存在来判断)。
这是一个 Harness bundle(客户端插件),装进你的 profile 即可:
plugin_manager → action: install_bundle → target: <这个目录的绝对路径>
装完在「插件」列表里能看到 Page zoom / 页面缩放,界面顶部按 Ctrl + 滚轮就会出百分比胶囊。
@deepseek-ai/dsh-desktop);开发时验证过 0.2.1-rc.2。dsh.client.inject 依赖 @deepseek-ai/dsh-client-ui-layout(百分比胶囊挂在 shell.overlay 槽位上),这是 Harness 自带的包。dsh-page-zoom。桌面壳(安装目录 resources/app.asar 里的 lib/main.js)是只读打包的安装产物,而且完全没有暴露缩放接口(既没有 webContents.setZoomFactor,也没有 IPC 通道),改它等于改安装目录、还会被下次更新覆盖。所以缩放放在页面里做:
<body> 设 CSS zoom —— 这是真正的重排缩放(文字清晰、布局跟着变),不是 transform: scale 那种位图放大;<html> 和 <body> 的宽高设成「视口 ÷ 缩放倍数」,让 html → body → #root → 框架 这条 100% 高度链在放大后仍然正好填满窗口。<html> 那一步不能省:它默认还是整屏高度,会撑出竖向滚动条,界面底部被裁掉;<body> 加 contain: layout,把 position: fixed 的浮层(弹窗、toast、菜单)锚定到 body 上,这样它们随页面一起缩放,任何倍数下都正好盖住可见区域;getBoundingClientRect() / getClientRects()(含 Range)的返回值除以倍数,innerWidth / innerHeight 和 documentElement.clientWidth/Height 也除以倍数。CSS zoom 默认把这些量乘进了视觉尺寸,而 Harness 用它量列宽、算浮层定位和拖拽;不校正的话列宽会被算成「放大后的视觉宽度」,右侧面板、菜单、拖拽把手都会错位。MouseEvent 的 clientX/clientY、pageX/pageY、offsetX/offsetY、x/y、movementX/movementY 除以倍数;document.elementFromPoint() / elementsFromPoint() 在内部先乘回倍数再问浏览器,调用方照旧传布局像素。WheelEvent 的 deltaX/deltaY 不换算——它描述滚轮走了多远,不是文档滚了多远(详见下面的滚轮口径)。visualViewport 的 width/height/offsetLeft/offsetTop/pageLeft/pageTop 同样除以倍数:底部工作台(dsh-better-sidebar)按 visualViewport.height 算展开高度,不换算的话高度会按视觉像素算出来、再被 CSS zoom 放大一遍,面板就会比实际可用空间高一截、跟内容错位。vh/dvh/vw)在 zoom 子树里仍然按真实窗口解析,于是「按视口高度定尺寸」的盒子会被再放大一遍、伸出窗口下沿。插件注入一小段样式把它们重新指向布局视口(--page-zoom-vh 每次缩放时由插件写入):底部工作台宿主 [data-dsh-panel-host]{height:100vh} → 100%,Harness 弹窗的 100dvh 上限与可滚动区的 100vh 上限 → 同一个变量的 calc()。100% 时这些值与原生一致,等于没改。WebContentsView 按窗口 DIP 坐标盖上去的。它量的是占位元素的 getBoundingClientRect(),这个边界必须拿视觉尺寸,所以插件对「带 role="dialog" aria-modal="true" 且首个子元素是 header[data-window-drag] 的浮层」内部元素不做除法,让原生视图盖在正确的位置和大小上。不这么做的话,平台页会被摆成布局尺寸:只盖住窗口左上角一小块,返回栏也被压住,看起来就是「显示不完整」。ResizeObserver 上报,而换缩放倍数并不会改变占位元素的尺寸 —— observer 不触发,原生视图就停在上一个倍数的框里。插件每次改倍数(以及窗口 resize)时把占位元素临时撑高 0.5px、下一帧再还原,让 observer 连发两次、把当前边界重新报给桌面壳。这是浏览器「页面缩放」的等效实现:布局按缩放后的 CSS 尺寸重排,测量出来的是布局尺寸。原生
webContents.setZoomFactor拿不到,才用这套等价手段。
| 操作 | 效果 |
|---|---|
| Ctrl + 滚轮 / 双指捏合 | 按档位放大、缩小 |
| Ctrl + Shift + = / - | 键盘放大、缩小(没有滚轮时用) |
| Ctrl + 0 | 回到 100% |
| 顶部短暂出现的胶囊 | − / 百分比 / + / ↺,1.8 秒后自动消失 |
档位是浏览器那套常用值:50% 67% 75% 80% 90% 100% 110% 125% 150% 175% 200% 250% 300%。
滚轮的口径跟浏览器一致:一个物理格 = 一个档位(Chromium 一格约 100px,阈值 50px 以上直接算一格,剩余量丢弃);触控板捏合和线性滚轮(deltaMode=1/3)是小步长连续事件,累加满一格才走一档,所以捏合是平滑推进而不是一格一格蹦。WheelEvent 的 deltaX/deltaY 不做倍数换算——它描述的是滚轮/触控板走了多远,不是文档滚了多远;换算过的话高倍率下(300% 时一格只剩 33px)一格会被误判成捏合。
Ctrl + = / -(不带 Shift)故意不接管:那是 Harness 自己的字号步进(文本/代码/终端字号 +1px),两边各管各的。
缩放倍数存在 localStorage 的 dsh.page-zoom.v1(origin 是 dsh-app://app),下次打开桌面版自动恢复;因为恢复值不是 100% 时会先亮一下胶囊,不会让人莫名其妙。
自检页在 test/selftest.html(加载真实 client.js,28 条断言覆盖:尺寸链、滚动条、测量面、指针坐标、elementFromPoint、visualViewport、vh 宿主、原生视图 bounds、滚轮灵敏度、原生占位元素重报、复位与卸载还原):
chrome --headless=new --disable-gpu --user-data-dir=<临时目录> \
--window-size=1280,820 --virtual-time-budget=8000 --dump-dom \
"file://<repo>/test/selftest.html" | grep -o '<title>[^<]*</title>'
tools/cdp-zoom-hit.mjs 是更严格的一套 CDP 回归(真实鼠标/滚轮输入、elementFromPoint、原生视图 bounds)。它需要占一个本地调试端口,某些环境会拒绝 bind()(WSAEACCES),那时用自检页即可。
100vh/100dvh/100vw 的写法(确认弹窗、可滚动区、toast 的最大宽度)。它们是「视口单位不受 CSS zoom 影响」的老问题,插件用一小段样式把它们重新指向布局视口;只在内容特别高的弹窗上可能顶出窗口下沿,一般弹窗不受影响。Element / Range / MouseEvent / VisualViewport 的原型 getter,卸载时全部还原。如果别的插件也硬编码了 vh/vw 尺寸或不经过 getBoundingClientRect() 的定位计算,需要各自按同样思路适配。| 文件 | 作用 |
|---|---|
client.js | 客户端一半:缩放引擎 + 测量/坐标校正 + 百分比胶囊 |
index.js | 宿主一半:空实现,仅让 bundle patch 能挂载 |
cordis.patch.yml | 把 dsh-page-zoom 插进 profile |
locale/en.json、locale/zh.json | 插件管理里显示的标题和说明 |
icon.svg | 插件图标 |
test/selftest.html | 自检页(见上) |
test/hit2.html | CDP 回归用的命中测试页 |
tools/cdp-zoom-hit.mjs | CDP 回归脚本(见上) |
LICENSE | MIT |
client.js 的生效方式:win32 版没有「重新加载页面」快捷键,所以要么重启桌面版,要么在插件管理里把 page-zoom 禁用再启用(宿主会重新下发客户端代码)。client.js,换机器、换目录都能跑;CDP 脚本用 CHROME=<path> 指定浏览器,跑完会自己删掉临时 profile。dsh client 体系的槽位与主题令牌;client.js 里所有 DOM 操作都发生在 <body>/<head> 上的缩放宿主与胶囊上,不往 document.body 追加业务节点。node --check client.js + 自检页(28/28)。CDP 脚本需要能监听本地端口,沙箱里常被拒(WSAEACCES),属已知限制。