dsh-anywhere-hub
📱 专为 DSH iOS App 与多端协同打造的超级连接枢纽
电脑、iPhone、iPad 多终端同时在线无缝切换,实时同屏收发;局域网 + 通用稳定公网全覆盖,锁屏切回 0.25 秒极速自愈(Fast-Resume)。
🌟 核心杀手锏:完美搭配 DSH iOS App,实现真正的多终端无缝协同
传统 Web 访问或普通手机端连接 DSH 时,最令人头疼的三大痛点:
- 多端冲突踢线:电脑开着,手机一连就把电脑挤掉,或者两边状态不同步、各打各的;
- 手机一锁屏就假死:切出微信回个消息或锁屏几秒钟,再打开界面直接白屏、断线,必须手动刷新重新进;
- 输入流不同步:手机发了消息电脑看不到,或者电脑端正在打印流,手机端一片空白。
dsh-anywhere-hub 深度重构底层传输与事件流,带来前所未有的「多端实时同屏」体验:
- 🤝 多终端同时在线,实时双向广播: 电脑端(桌面客户端或浏览器)、iPhone (DSH iOS App)、iPad 或多台移动设备可以同时打开同一个会话。无论哪一台设备敲下回车发指令,所有设备屏幕实时同步滚动、同步打印 AI 的流式回复,真正的“多端一心”。
- ⚡ 毫秒级锁屏断线自愈(Fast-Resume): 内置原生 Fast-Resume 协调机制。手机切到后台、锁屏挂起无论多久,只要重新点开 DSH iOS App,系统在 0.25 秒内自动完成静默换票重连,瞬间拉齐断网期间的所有消息增量,彻底告别白屏重载!
- 🔄 跨场景无缝切换: 在电脑前敲代码做方案,中途有事出门,直接拿起手机打开 DSH iOS App 继续聊,上下文与进行中的任务完全连贯,实现“电脑开始、手机随身走”的无缝闭环。
🚀 更多硬核能力
1. 统一 3083 端口主控(彻底告别双开冲突与端口漂移)
- 单进程绝对主控:无论是桌面端 DSH Desktop 还是无头模式,统一监听
3083端口,手机端与公网统一接入 3083。 - 彻底消除后台无头服务与桌面客户端的文件锁争抢(告别
stored session丢失),无论手机端还是电脑端,永远连入同一个进程,多端状态 100% 实时同屏!
2. 连接方式(推荐顺序:局域网优先,外网进阶)
- 🏠 首选:局域网直连(推荐所有用户)
- 手机与电脑连同一 WiFi,地址填
http://<电脑局域网IP>:3083(或直接扫码); - 局域网地址天然不变,零配置、零依赖、零风险,延迟最低,90% 的使用场景一台路由器就够了。
- 手机与电脑连同一 WiFi,地址填
- 🌐 进阶:外网远程访问(看自己的搭建能力,量力选择)
- 方案 A:免配置极速隧道(默认,开箱即用)
- 针对国内网络深度优化:内置国内镜像并发分片加速(亦可直接内置
bin/cloudflared.exe免下载),解决官方版在 GitHub 下载卡死在 0% 的致命问题; - 强制启用
--protocol http2隧道,杜绝国内运营商对 UDP/QUIC 的丢包阻断,普通用户点开即用。
- 针对国内网络深度优化:内置国内镜像并发分片加速(亦可直接内置
- 方案 B:Cloudflare Zero Trust 命名隧道(永久固定域名)
- 支持普通用户绑定自己的免费域名与 CF
Tunnel Token,重启软件外网网址永久不变。
- 支持普通用户绑定自己的免费域名与 CF
- 方案 C:自定义穿透直连(FRP / 异地组网 / 公网IP)
- 支持配合 SakuraFrp、OpenFrp、自建 FRP、Tailscale、ZeroTier 或公网 IP;
- 只需在设置中填入穿透地址,插件自动生成二维码并接管访问认证与多端协同。
- 方案 A:免配置极速隧道(默认,开箱即用)
3. 企业级安全防爆破
- 局域网与公网独立访问密码,支持自定义固定密码;
- 内置单 IP 防暴力破解防线:连续输错 5 次密码直接拉黑封禁该 IP 24 小时,杜绝公网扫描风险。
4. 老系统兼容:iOS 14 / 15 / 16.x 全通吃(含 16.3 及以下)
DSH 官方前端里使用了 RegExp 后行断言((?<=…) / (?<!…))以及 ES2022 类静态初始化块(static { ... }),这两项关键语法都需要 Safari / iOS 16.4+。
在 iOS 16.3 及更低版本上,WebKit / JavaScriptCore 引擎在解析期就抛出语法错误:
SyntaxError: Unexpected token '{'(遇到static {直接崩溃中断)SyntaxError: Invalid regular expression: invalid group specifier name(遇到/(?<=...)/直接抛错) 导致前端入口与核心包整包不执行,页面直接白屏,任何常规 polyfill 都救不回来(语法级错误发生在词法分析编译期,早于任何运行时执行)。
本插件在代理层做了全自动语法等价降级改写,对所有用户生效,不需要改动官方 DSH 客户端:
- ES2022
static { ... }静态块降级(v1.0.10 新增):自动将类体内的类静态初始化块改写为等价执行时机与语义的静态属性初始化器static _sb_<N> = (() => { ... })();,完美兼容 iOS 14.5+ / 15 / 16.0~16.3 等所有老版本 WebKit! - 正则字面量改写成运行期构造:把
/(?<=X)…/这类字面量替换成new RegExp("(?<=X)…")包一层函数。 新系统(iOS 16.4+)走try分支用原正则零开销;只有老系统才落到降级分支。 - 未知形态一律剥离:已知形态(
(?<!\S)、(?<=^|\s|\p{P}|\p{S}))做语义等价降级 (非捕获前缀 +exec内修正m[0]/m.index,捕获组编号不变); 其它没见过的形态则整体剥离后行断言 —— 匹配范围会放宽,但保证不崩、不白屏。 取舍很明确:宁可少匹配,也绝不让整页打不开。 vflag 降级:vflag(unicodeSets,iOS 17+)在做降级时自动降为u,避免老引擎因 flags 非法二次抛错。- 强缓存动态击穿机制(Cache-Buster & ETag Versioning):改写层采用版本化 ETag(
pcf2-)与条件请求校验,彻底解决手机端把未修复代码锁死在本地强缓存导致“服务端修好、手机仍旧白屏”的顽固死结!
已知边界:不含后行断言、但用了
vflag 的纯字面量不做改写。原因是按/v反推正则起点会把a / v / b这类链式除法误判成正则,误伤代价(直接崩页)大于收益。当前 DSH 前端 v flag 命中为 0。
5. 版本兼容哲学:无缝识别旧版本,全链路向下自适应(绝不搞强制升级弹窗)
在多端协同产品演进中,面对官方 DSH 宿主升级(如从 2.0.18 升级至 DSH NEXT 2.0.20)、老系统存量(iOS 14/15/16.3 等)以及移动端 App 版本差,有两种处理思路:
- ❌ 思路一(粗暴死锁):加安装限制,强推弹窗强制升级。只要版本低就直接弹窗死锁不让用。
- ✅ 思路二(本项目坚守):无缝识别旧版本,全链路向下自适应支持。把复杂度收拢在服务端改写层,把简单无感留给用户。
为什么必须选择第二种?核心原因:
- 老玩家设备环境多样:许多玩家使用巨魔(TrollStore)或自签设备,重装与签名成本很高。强加模态弹窗不仅粗暴,更会直接打断正在进行的紧急工作,产生极高沟通与客诉成本;
- 多端版本排列组合复杂:存在“电脑旧版 + 手机新版”、“电脑新版 + 手机老版”、“新系统设备 + 老系统备用机”等多种交织状态。在代理层做按需语法降级与向下自愈,能让所有版本组合均可零门槛秒开;
- 老玩家免更直接复活:由于改写完全发生在 3083 代理层,即使老玩家手机里装的是几个月前的旧版 iOS App(如 1.0.x),连上升级后的
dsh-anywhere-hub,也无需重装 App 即可立即消除白屏; - 升级提示润物细无声:不在操作路径上弹遮罩,仅在设置/关于界面做柔性状态提示,玩家自愿随时一键升级,不打扰正常使用。
6. 手机端抽屉补「设置」入口
DSH 移动端抽屉里原本没有任何设置项 —— 真正的设置藏在底部「账号菜单」弹层里 (设置 / 意见反馈 / 退出登录),而抽屉是 280px 覆盖式的,一拉开就把正文工具条整个盖住, 用户根本找不到设置。本插件在抽屉里补一个齿轮:点它 = 打开账号菜单 → 点「设置」→ 自动收起抽屉(不收起的话 280px 抽屉会盖掉设置面板的 3/4,看起来像点了没反应)。
齿轮位置(v1.0.8 定版):贴在抽屉底部「账号菜单」那一行的右端,和头像同一行。
实测账号菜单行 x=10~270 / y=862~906(430×932),行内只有头像(1640)和昵称(48146),
146~270 是纯空白 —— 齿轮放 26×26 在 x=240,不压任何子元素,
点它和点账号菜单是同一套行为(打开账号菜单 → 点「设置」→ 自动收起抽屉),
即便盖住该行右端那点空白点击区,体验也完全不变。
位置演进说明:v1.0.6 放在「账号菜单右端 −40px」(
x=230~262),压住了账号菜单按钮右半边; v1.0.7 挪到抽屉外侧右边缘(x=287~315 / y=56~84),但那正好在主界面顶栏 「打开左侧侧边栏」按钮的高度带上,看起来像凭空多出一个按钮; v1.0.8 最终回到底部账号行右端,与头像同行。
零 DOM 结构改动、零布局影响。
📦 安装与配置
✅ 包名独一无二:dsh-anywhere-hub
从 v1.2.0 起本插件定名 dsh-anywhere-hub,两条理由:
① 撞名 : dsh-anywhere@0.1.2 ← 2026-08 已被别人占用(tangwenhao)
与本项目同名,代码、功能毫无关系
② 定位 : 旧名带 "zcode" 太窄 —— 这只是第一个接入的 Web 上游,
以后还要挂更多 AI 平台、更多 Web 页面
继续叫 dsh-anywhere,别人 pnpm add dsh-anywhere 就会装到别人的代码——
没有 iOS 16.3 兼容垫片、没有手机远程页、没有 3083 多端同屏。
所以本插件改用全新独有包名:npm 上不存在,也不会再撞名。
hub 取「枢纽」意:插件本体只管 3083 多端同屏与改写层,
任何 Web 上游(ZCode 只是第一个)都通过 zcode-rc/ 这套网关接进来,
加新平台不用改包名、不用发新版。
两个名字分工,别混:
| 用途 | 值 |
|---|---|
| 包名(安装 / 更新用) | dsh-anywhere-hub |
插件实例 id、settings.yaml 配置键 |
dsh-anywhere(故意不变,升级不会产生第二个实例、不会双绑 3083) |
1. 安装插件
在你的 DSH Profile 目录(如 ~/.dsh/profiles/desktop)下执行:
# pnpm
pnpm add github:liushQAQ/dsh-anywhere-hub
# 或 npm
npm i github:liushQAQ/dsh-anywhere-hub
走 GitHub 源的好处:
- 不需要 npm 账号、不需要发包,绕开注册限制;
- 永远拿最新代码,仓库一提交就生效,不用等发版;
- 官方推荐的就是这个地址。
如果你之前装过旧名(dsh-anywhere,含 npm 上别人的同名包),先清掉再装:
pnpm remove dsh-anywhere
pnpm add github:liushQAQ/dsh-anywhere-hub
也可以直接引用本地构建产物(把路径换成你自己的 tgz 位置;Windows 与 macOS / Linux 写法均可):
pnpm add /path/to/dsh-anywhere-hub-<version>.tgz
2. 启用插件
在 settings.yaml 中配置启用(键名是实例 id dsh-anywhere,与包名无关,不用跟着改):
plugins:
dsh-anywhere:
enabled: true
3. ZCode 手机页网关(已内置,v1.1.0 起)
zcode-rc/ 整个网关随包发布,装完插件就能一条命令部署,不用另外下载:
# 在 profile 目录下执行;--task 会注册开机自启
npx zcode-rc --target D:\zcode-rc\zcode-rc-gateway --task
# 或者
node node_modules/dsh-anywhere-hub/zcode-rc/install.mjs --target D:\zcode-rc\zcode-rc-gateway --task
📱 搭配 DSH iOS App 使用指南
- 局域网同屏模式(极速低延迟):
- 手机连上与电脑相同的 Wi-Fi;
- 打开 DSH iOS App,地址输入:
http://<电脑局域网IP>:3083(或直接扫码接入)。
- 出门随身模式(公网无缝协同):
- 开启公网访问后,在 DSH iOS App 中输入公网地址;
- 无论身在何处,均可随时随地与家里的 DSH 实时对话,随时接续电脑上的工作。
🖥️ 顺带把任意 Web 上游搬到手机上(首个接入:ZCode,v1.0.12 起)
这套网关不绑死 ZCode:凡是桌面端自带「手机远程控制网页」的产品,都能用同一套办法接进来—— 改写层(ES2023 垫片 + 语法降级)、
/rc抗缓存、viewport-fit安全区、免登录注入,全是通用的。 换一个上游只要改runner.mjs里的源站地址与环境变量,包名和安装方式都不用动。这就是叫hub的原因。
ZCode 桌面端自带一个「手机远程控制」网页(官方源 https://zcode.z.ai/remote/v4)。
DSH iOS App 本身就是一个 WKWebView 壳,不用改一行 App 代码就能打开它——但直接开官方地址有三个硬伤:
需要装什么(三样,缺一不可)
| 装哪边 | 装什么 | 说明 |
|---|---|---|
| 手机 | DSH iOS App(github.com/liushQAQ/IOS) |
薄壳 WKWebView,同一个 App 既连 DSH 也开 ZCode,两边各开各的地址 |
| 电脑 | 本插件 dsh-anywhere-hub |
反代 + ES2023 垫片(改写层本体)+ 内置 zcode-rc 网关;github: 前缀不能省 |
| 电脑 | zcode-rc-gateway(随本仓库 install.mjs 装) |
ZCode 手机页的唯一入口 :3090/rc:/rc 破缓存 + viewport-fit 安全区 + 免登录注入 |
| 电脑 | ZCode 桌面端 | 保持官方原版,一个字不改;改过就连不上官方中继 |
App 内「连接说明与教程」第 4 步就是这一章的手机版图文,装机后照着点即可。
| 硬伤 | 表现 | 本插件的解法 |
|---|---|---|
| ES2023 语法 | 入口包直接调 toSorted / Object.groupBy,Safari 16.4 才有 → iOS 16.3 解析即抛错,卡在启动壳 |
代理层注入全量 ES2023 垫片(toSorted/toReversed/toSpliced/with/groupBy/fromAsync/withResolvers/URL.canParse/requestIdleCallback/CompressionStream…) |
| 语法级降级 | static {} 类静态块、(?<=…) 后行断言,16.3 在词法分析期就崩,运行时 polyfill 救不回 |
与 DSH 页面同一套改写层(见上文第 4 节),服务端把语法换成等价写法 |
| 强缓存锁死 | 改写后的 JS 被标 immutable 缓存一年,命中时连请求都不发,服务端怎么改都到不了手机 |
资源 URL 版本化(?v=)+ 资源 no-cache/ETag;独立网关再叠一层文档 no-store + /rc 毫秒戳换址 |
唯一入口:3090/rc
手机端只开这一条地址,没有第二种接法:
http://<你的电脑IP>:3090/rc
不要用 http://<电脑IP>:3083/remote/v4。 3083 是 DSH 自己的主控口,ZCode 页面虽然也吐得出来、
垫片也注入了,但它缺的三样,恰好就是 iOS 16.3 卡在启动壳的全部成因:
| 3083 缺什么 | 后果(真机复现过) |
|---|---|
没有 /rc 缓存逃生口 |
旧文档一旦被手机缓存,命中时连请求都不发,服务端怎么改都到不了手机 → 永久黑底 Z |
没开 viewport-fit=cover |
内嵌 WebView 里 env(safe-area-inset-*) 恒为 0,顶栏压状态栏、输入框贴屏底 |
| 没有免登录注入 | 每次都要重走一遍 ZCode 登录 |
独立网关(zcode-rc-gateway,allowedPaths 作用域闸,不暴露 DSH)把这三点补齐:
/rc 毫秒戳换址破缓存、viewport-fit=cover + 安全区四级兜底、免登录注入。
怎么装
电脑端(ZCode 桌面端保持官方原版,不要改它):
# Windows(PowerShell,永久) setx ZCODE_WEB_REMOTE_CONTROL_URL "http://<你的电脑IP>:3090/remote/v4" # macOS / Linux export ZCODE_WEB_REMOTE_CONTROL_URL="http://<你的电脑IP>:3090/remote/v4"设完必须重启 ZCode 桌面端才生效。设这一步是为了让桌面端生成的二维码直接指向网关。
网关侧:
node install.mjs --target <目录> --task(一条命令拷文件 + 校验 + 注册自启)。手机端:DSH iOS App 服务列表里点「ZCode 远程(局域网)」预设,把 IP 改成自己的; 或手动加
http://<你的电脑IP>:3090/rc。
三条必须提前知道的限制
- 第一次必须在桌面端点一次「生成远程二维码」,手机扫一次。
sid可以长期复用,但mid是每次二维码里的一次性邀请,中继只认它;不扫码直接开会连不上。 这是 ZCode 官方的限制,不是网关的毛病。 - 入口只用
/rc,不要用/remote/v4?sid=…,也不要用 3083。带sid的地址一旦被手机缓存过坏文档, 命中时不会发请求,服务端修不到它;/rc每次用毫秒戳拼一个从未缓存过的地址破局。 万一被旧书签锁死:/rc会自己换新址,老地址请求到达网关时也会 302 到/rc,等缓存失效即自愈。 - 只在可信内网用。网关零鉴权,同一 WiFi 谁都能开;
last-pair.json里有会话号与配对信息, 不要外传、不要做公网端口映射。要外网就用 Tailscale 这类点对点组网,别把端口暴露到公网。
兼容下限
真机验过 iOS 16.3 及以上(16.3 / 16.6 两台实测通过)。 iOS 16.0–16.2、iOS 15 理论上被同一套垫片覆盖,但没有真机验证,不打包票。
⚙️ 配置文件说明(~/.dsh/dsh-anywhere/settings.json)
插件首次运行会自动生成纯净的通用配置,不包含任何个人敏感链接:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
lanEnabled |
boolean |
true |
是否开启局域网多设备访问 |
lanAuthEnabled |
boolean |
true |
局域网访问是否需要密码验证 |
tunnelMode |
string |
"quick" |
"quick"(自动隧道)/ "named"(CF固定域名)/ "fixed"(自定义公网直连) |
tunnelHostname |
string |
"" |
named 模式下的完整自定义域名 |
tunnelToken |
string |
"" |
named 模式下的 Cloudflare Token |
fixedWanUrl |
string |
"" |
fixed 模式下的自定义外部穿透地址(如 FRP) |
🗒 更新日志
v1.2.0
- 改名:
dsh-anywhere-zcode→dsh-anywhere-hub。v1.1.0 那版带zcode的后缀太窄—— 它只覆盖第一个接入的 Web 上游,后面还要接更多 AI 平台、更多 Web 页面。hub取「枢纽」意: 插件本体(3083 多端同屏 + 改写层)与具体上游解耦,加平台不用改包名。 仓库同步改为github.com/liushQAQ/dsh-anywhere-hub(旧地址 301 自动跳转)。 插件实例 id 仍为dsh-anywhere,配置键、数据目录、已登录设备全部沿用,升级不需重新扫码。 - 文档去 ZCode 化:ZCode 章节标题改为「顺带把任意 Web 上游搬到手机上(首个接入:ZCode)」,
并写明通用化做法(换上游只改
runner.mjs源站与环境变量)。 - 包元数据更新:description / keywords / repository / homepage / bugs 全部跟随新名。
v1.1.0
- 改名:
dsh-anywhere→dsh-anywhere-zcode(已废弃,见 v1.2.0)。npm 上dsh-anywhere早在 2026-08 被他人占用,同名不同源,pnpm add dsh-anywhere会装到别人的代码。 当时选了带zcode的独有名,后来因定位太窄再改为dsh-anywhere-hub。 - 手机页网关内置:
zcode-rc/(runner / mobilefix / diag / install)随包发布, 装完插件即可npx zcode-rc --target <目录> --task一条命令部署,不再需要另找安装包。 - 更新命令跟着改名:一键更新走
dsh plugin update dsh-anywhere-hub --latest -w。
v1.0.23
- 接法收敛为唯一入口
3090/rc,撤掉 3083 那条:v1.0.22 曾把http://<电脑IP>:3083/remote/v4写成「零配置接法 A」,是错的 —— 3083 缺/rc缓存逃生口、缺viewport-fit=cover、 缺免登录注入,这三样恰好就是 iOS 16.3 卡在黑底 Z 的全部成因(真机复现过)。 文档改成单一入口,并把三条缺失逐条列成对照表,避免再被当成可选路线。 - 限制条款同步改写:入口只认
/rc,3083 与带sid的旧地址一律不推荐; 老地址被缓存锁死的自愈路径写清楚(请求到达网关即 302 →/rc)。
v1.0.22
- ZCode 章节补「需要装什么」:手机装 DSH iOS App、电脑装本插件、ZCode 桌面端保持官方原版, 三行讲清楚谁装谁;并标明 App 内「连接说明与教程」第 4 步就是这一章的手机版图文。
- 安装顺序写进文档:先装 App 再装插件,装完手机开
http://<电脑IP>:3090/rc即可。
v1.0.21
- ZCode 手机远程页进 README 正式章节:把 v1.0.12~v1.0.20 摸出来的整套东西写成可照做的文档
(环境变量怎么设、
/rc为什么是唯一入口、必须扫码一次、只在可信内网用、兼容下限 iOS 16.3)。 ZCODE_RC_ASSET_VER机制固化:凡是改动 JS/HTML 改写逻辑必须 +1(版本写进资源 URL, 老缓存自然失效)。这是「服务端修好、手机还是白屏」这个死结的唯一可靠解法,已写进代码注释。
v1.0.20
- 粘贴桥正则转义修复:桥脚本内
.replace(/\+/g,'-')在模板字符串里少一层转义, 浏览器侧实得/+/g→ 解析期SyntaxError: Nothing to repeat→ 整段<script>不执行、 桥按钮根本不出现。已修正转义并加回归单测。
v1.0.19
- OAuth 撤口修正:
webRemoteCallbackUrl真身在${n}/web-remote/callback构造器 (v1.0.18 误判${n}/remote/v4撤错口)。本条连cn/share/callback同族一并撤销 (同族同罪,都会撞 OAuth 白名单 exact-match),remoteUrl/ WS 模板改写保留。 - 粘贴桥跳转目标改为
/web-remote/callback?code&state(官方只认该路径为 OAuth 回调)。
v1.0.18
- OAuth 回调改写撤销 + 回调粘贴桥:真机实锤 z.ai OAuth 白名单 exact-match 硬拒网关
redirect_uri(Redirect URI not registered for this client),改写路线判死。redirect_uri回归官方注册值,登录后 z.ai 302 回官方源;页面注入「登录回调」粘贴桥, 剥code/state重定向回本源/remote/v4交原生handleCallback闭环。
v1.0.17
- OAuth CSRF 根治:
webRemoteCallbackUrl真身为${n}/remote/v4(n=官方源), 补齐带前缀模板改写(全 bundle 仅 1 处,裸ROUTE_PATH常量不误伤);/zcode-rc-api上游Origin/Referer改写为官方源(ESA 边缘源校验同款防线)。
v1.0.16
- OAuth 回跳闭环:
webRemoteCallbackUrl/remoteUrl改写到请求 Host 源 +/web-remote/callback回调挂载;修/zcode-rc-api/api/*上游映射缺失 (firstPath误用u.pathname致 token 交换必 404)。
v1.0.15
- 字符串形态 lookbehind 运行时垫片:16.3 真机信标定位到的盲区 ——
new RegExp("(?<=…)")是运行期编译,语法改写层看不到它,必须运行时兜。
v1.0.14
allowedPaths作用域闸:支持独立端口实例(3090 专口专用), 同一个代理内核可以只服务 ZCode,不把 DSH web 暴露出去。
v1.0.13
- 中继 WS 隧道:页面 WS 走自身 origin 再中继,根治 ESA 边缘
Origin校验 403。
v1.0.12
- ZCode 手机远程控制页反代:
/remote/*页面与资产整树镜像、/zcode-rc-api/*API 镜像、 WS 中继;注入 ES2023 垫片 +crypto.subtle纯 JS 实现,根治 iOS 16.3 白屏; 兼容 http 源上的配对 proof(crypto.subtle在非安全上下文不存在)。
v1.0.11
- 手机端左抽屉「会话」区扩容(老总反馈:会话才是重点模块):菜单行 36→28px、隐藏 Ctrl+Alt+N 快捷键提示、隐藏费用卡明细(保留「余额 ¥xx」摘要行)、压薄 logo 行,会话树自动撑到 ~400px。
- + 号弹层钉位与限高(老总反馈:忽上忽下 + 与键盘重叠):点 + 先收键盘,弹层统一钉在按钮上方、键盘弹起按 visualViewport 上抬,MutationObserver 兜底重钉;CSS 硬顶所有
[role="menu"]限高min(52vh,460px)+ 卡片内滚动——不再依赖 JS 命中,任何门户弹层(含工具卡片)都不会再撑满全屏。 - 右抽屉顶部安全区(老总反馈:按钮顶进灵动岛):
[data-sidebar-right-panel]补padding-top:max(env(safe-area-inset-top),60px),与主栏 60px 约定对齐。 - 右抽屉防偏移哨兵 rpFix(老总反馈:真机偶发左右偏移出屏):桌面全态复现几何正确,属 WKWebView 特有状态,不猜机制——面板打开期间 300ms 实测几何,x/y≠0 或宽度不足即宿主列
transform:none+ 面板归位,关闭撤内联交还宿主动画;另加html,body overflow-x:clip根治整页横漂。桌面桩测三场景(列毒写/面板毒写/关闭复原)全过。 - 会话密钥持久化(老总反馈:3083 每次打开都弹验证):登录 cookie 绑定的 sessionKey 由进程级随机改为落盘
$DSH_HOME/dsh-anywhere/session-key(0600),重启/更新后不变——手机输一次 PIN 长期免输;仅「恢复出厂设置」轮换踢掉全部设备。
v1.0.10
- 攻克 iOS 16.3 及老版本 WebKit 致命白屏(SyntaxError: Unexpected token '{'):
DSH NEXT 官方前端入口包(如
index-BXV-oxvX.js)在类体中引入了 ES2022 的static { ... }类静态初始化块特性。该特性在 Safari / WebKit 16.4 才加入支持,导致 iOS 16.3、iOS 15 等老系统在词法编译期直接报语法错误中断执行而白屏。代理层新增 AST 级patchStaticBlocks自动化改写器,等价降级为全系支持的静态属性初始化器static _sb_<N> = (() => { ... })();,时序与语义 100% 保持原生一致。 - 改写器容量防护放宽:将改写上限由 64 提升至 2048 处,彻底杜绝超大前端包因匹配项偏多被误判截断的问题。
- 缓存击穿加固(pcf2):代理层将 ETag 指纹升级为
pcf2-版本,瞬间击穿手机端 WebKit 强缓存,保证老设备一键重试即可立刻加载修复后代码。 - 移动端排队条(QueueDock)层叠优化:将
.dock纳入 composer 独立层级(relative+z-index: 1),修复 360px 窄屏下输入装饰层遮挡排队消息操作按钮的问题。
v1.0.9
- 发布规范化:新增
LICENSE(MIT)与repository/homepage/bugs/author元数据;files白名单补LICENSE。 - 打包瘦身:清出 5 个历史
.bak备份(files里的目录项会整目录包含,.bak照样进包),包体积 5.01 MB → 1.09 MB,文件数 32 → 27。 - 文档通用化:安装示例的绝对路径改成占位
/path/to/dsh-anywhere-hub-<version>.tgz;源码注释与构建产物里的内部措辞改为中性表述,client/client.js已重新构建。 - 齿轮定位改为以「账号行右界」与「抽屉右界」中更靠内的那个为基准(
anchor = min(ar.right, drawerRight),再左移 26+8px)。 起因:App 把抽屉宽度强制压到 252px 后,账号行仍排在 270,旧算法ar.right - 30让齿轮 right=266 —— 超出抽屉、被overflow:hidden裁掉右半边。 - 实测 430×932 / 393×852 / 375×667 三种尺寸,齿轮均完整落在抽屉内(right 230 / 208 / 198,抽屉右界 252 / 230 / 220)。
v1.0.8
- 设置齿轮回到底部账号行(用户反馈:齿轮落在了「打开左侧侧边栏」按钮的位置上,期望放在头像旁边):
v1.0.7 把齿轮挪到抽屉外侧右边缘,实测落在
x=287~315 / y=56~84, 那块正好在主界面顶栏「打开左侧侧边栏」按钮的高度带上,视觉上就是凭空多出一个按钮。 - 现在贴在账号菜单行右端(
ar.right - 26 - 4,与头像同一行垂直居中), 行内146~270本来就是空白,不压任何子元素;尺寸 26×26。 - 三尺寸实测(430×932 / 393×852 / 375×667):
insideAccountRow: true、overlapLabel: false(昵称右界 146,齿轮从 240 起)、clickable: true; 真点击 → 设置面板 414×651 打开、抽屉自动收drawerX: -150。
v1.0.7
- 修复设置齿轮压住账号菜单按钮(用户反馈:齿轮不该出现在页面 prompt 插件按钮的位置):
旧实现把齿轮放在「账号菜单右端 −40px」,实测 430×932 下落在
x=230~262 / y=868~900, 而账号菜单按钮本身是x=10~270 / y=862~906—— 齿轮整个压在账号菜单右半边, 把那片的点击全抢走(隐藏齿轮后逐点探测,底层清一色BUTTON.qin2_W_trigger)。 - 齿轮改到抽屉外侧右边缘(后被 v1.0.8 修正回底部账号行)。
- 新增五点位碰撞检测(
document.elementsFromPoint四角 + 中心)。 - 尺寸 32 → 28px。
v1.0.6
- 修复 iOS 16.3 及以下白屏(通用修复,非环境定制):
vendor 包里的邮箱正则是数组元素写法
[[/(?<=^|\s|\p{P}|\p{S})…/gu, Uf]], 前导字符是[,而改写器的「前导字符白名单」里没有[→ 判定不是正则起点 → 原样放行 → iOS < 16.4 解析期SyntaxError→ 整包不执行 → 白屏。白名单已补[。 - 改写器升级为真正通用:不再「只认两种已验证形态、其余放行」,任何后行断言都会被改写; 未知形态走整体剥离兜底(放宽语义保可用),混用多种形态的正则也能处理。
- 降级路径加固:二次构造
new RegExp全部包try,最后一级兜底返回空匹配正则, 任何情况下都不会再抛到调用方(原实现里二次构造失败会直接中断模块执行)。 vflag 降级:v→u,老引擎不再因 flags 非法二次抛错。- 缓存策略:bundle / asset 从
max-age=86400/31536000, immutable改为no-cache, must-revalidate—— 原来等于让手机把改写前的旧包锁死在本地, 代理层再怎么修都拿不到。 - 手机端抽屉补设置齿轮:抽屉右下角一键直达设置面板,并自动收起抽屉。
v1.0.5
- 适配最新版 DSH 内核,超越版本兼容,放宽 peerDependencies。
No comments yet. Be the first to write one.