---
url: /wave-agent/specs/remote/remote-mobile.md
description: 触控设备上的远控页：整屏装得下、聚焦不被自动放大、文字与图标按钮按手指给足的那一档尺寸
---

# 功能规格说明：移动端适配

**创建日期**：2026-10-13（2026-10-30 从 `ui/remote-control.md` 拆出）

本文只讲**触控设备**上的这一页：整屏怎么装得下、聚焦文本控件时不被浏览器放大、字号与图标按钮按手指给足的那一档。页面本身（连接、首屏、降级入口）见 `remote-web.md`，主屏安装与锁屏通知见 `remote-pwa.md`。

## 用户场景与测试 *（必填）*

### 用户故事：触控设备上的尺寸与字号（优先级：P1）

作为用手机打开这一页的人，我希望文字不用捏合就看得清、按钮不用瞄准就点得中，以便它真的能当手机界面用。

**为什么是这个优先级**：这一页是五端里唯一**一种宿主对应两种设备**的一页——同一张 `/remote/` 既被手机打开、也被 PC 浏览器打开。沿用插件那一档密度，正文在手机上就明显偏小，而这一页既没有 ESC 键也没有终端，捏合与瞄准是仅有的补偿手段。它不决定功能能不能用，但决定这一页在手机上是不是能用。

**独立测试**：在手机上打开一次：顶栏与输入区同屏可见、页面本身不产生纵向滚动，两端都不被系统 UI 遮挡；聚焦任一输入框时整页不放大、且页面仍可双指缩放；正文与辅助信息不必捏合即可读；顶栏右侧与输入区左下角的图标按钮不必瞄准即可点中，且相邻两个不会互相误触；同一地址在 PC 浏览器里打开时字号与设计稿一致（文本类控件也不例外）、图标按钮也仍是设计稿尺寸，且本机 IDE 与桌面端的同一份 UI 视觉不变。

**验收场景**：

1. **假设** 页面在手机上打开（浏览器标签页里，或「添加到主屏幕」之后的独立窗口里），**则** 它必须**整屏装得下**：顶栏与输入区在同一屏内同时可见、页面自身不产生纵向滚动，**顶部与横屏两端**也都不被系统 UI 压住——浏览器工具栏的伸缩（地址栏与底部工具栏的收起 / 展开）与全面屏的安全区（状态栏、灵动岛、横屏时的圆角区）都不得把这两个区域推出可视范围或盖在它们上面；**底部则不再额外让位**：输入区底边就落在可视区底边上（只留输入区自身的常规内边距），不按底部安全区再往上抬一条。**依据**：这是唯一跑在浏览器里的宿主，它的高度由**浏览器的可视区**决定，而不是由承载它的窗口决定；本地四端嵌在没有动态工具栏、也没有安全区的窗口里，这条约束在它们身上恒成立（页面高度与窗口高度逐像素相等）。因此这是 Web 页独有的要求，按宿主收口，不改动其余四端的布局。顶部与底部之所以**不对称**：页面声明了 `black-translucent`，内容画到状态栏底下，顶部不让位就是「顶栏按钮被系统图标压住、点不动」（真机实测）；底部反过来——独立窗口形态下浏览器给出的视口高度本身已经扣掉了底部安全区，再让一条会在输入区下方多出一倍宽的同色空带（真机实测「底部有空白」），而最下面那一条是系统手势保留区、页面本来就画不进去，输入区贴到可视区底边已经在它之上。

2. **假设** 用户在 iPhone 的浏览器里（含「添加到主屏幕」后打开的窗口）聚焦页面上的任一文本类输入控件，**则** 页面**不得被浏览器自动放大**（聚焦前后整页的视觉缩放比不变，`visualViewport.scale` 保持 1），**且**用户仍然可以自行双指缩放页面——**不得以关掉用户缩放为代价**换来前一条。**依据**：iOS Safari 对**字号偏小**的文本控件会在聚焦时把整页放大到它认为可读的那一档，且此后不自动还原；字号抬到它认定的可读档以上才不会触发。两条路并不等价：**不让页面被缩放**（`maximum-scale=1`）确实能挡住自动放大，但会把用户的手动缩放一并关掉；**把文本控件抬到可读档**才能两条都要到。他 2026-10-14 先按前者上过真机，用下来判「这一页的字本来就偏小、现在连放大都没得用」不可接受，于是改回后者——**页面上的每一个文本类控件都必须给到这个档，不止消息输入区**。这条下限**与第 3 条同一条判据（触控设备）**：触控设备上文本类控件一律抬到可读档，PC 浏览器保持设计稿密度（输入框回落各组件自己的基线）。**依据（2026-10-16 改）**：触发这条的是 iOS 的**字号阈值**机制；Android 的同族机制并不相同——Chrome 聚焦输入框时的放大是**视野补偿**（页面被缩小过才把输入框放大并居中），它的文本膨胀只作用于**未按设备宽度布局**的页面，而本页声明 `width=device-width, initial-scale=1.0`，两条都不成立。也就是说这条只对「触控 + iOS」是必需的、理论上可以只给 iOS，但样式里**没有可靠的 iOS 判据**（能区分 Safari 的写法随版本失效，无公认解法），而「主输入是手指」是稳定判据、本页档位组已经在用；反过来「只给 iOS」会让 Android 上的控件掉回组件基线，与已抬过一档的正文并排比现状更不协调。初版写的是「不按设备开关、宁可一律给足」，他 2026-10-16 在 PC 上打开这一页时报「输入控件看着偏大」——同一屏正文还是插件那一档——据此收进触控媒体查询。该要求**只作用于远控页**：其余四端不跑在移动端浏览器里，不受这条约束，也不该为它改动共享样式。

3. **假设** 用户用**触控设备**（手机或平板）打开远控页，**则** 页面上的文字按**手机档**渲染，而不是沿用插件（IDE）那一档：消息正文与输入区一类阅读主体抬到移动端可读的尺寸，工具与代码块、辅助信息、弹窗与审批卡、**会话列表的行标题**随之**整体抬一档**（不是只把某一个控件调大——只调一处会让它在整页里显得孤立地大）。**判据是设备能力，不是页面身份**：同一张远控页在 PC 浏览器里也会被打开（它本就能，也常被这么用），那里要保持设计稿的密度；而「主输入是手指、没有悬停」（`pointer: coarse` / `hover: none`）正好是手机与平板的共同点，把两端分开——这也是业界的判据（claude.ai 的共享样式里就有多处 `@media (pointer:coarse), (hover:none)`）。**不用宽度断点代替**：宽度是连续量——窄的手机视口、小平板、PC 窗口什么宽度都有——「多大算手机」没有自然分界，必须任选一个阈值，而阈值两侧都是误判：PC 上把窗口拉窄会被判成手机（那里原本是设计稿的密度），平板又会被判成桌面。横屏手机是宽度方案会漏掉的又一种，但他 2026-10-14 判「这一页竖着才装得下更多信息，横屏概率很低」，所以这条只作补充、不是选触控的主因。**依据**：同一份 webview 服务五端，字号此前是全站硬编码、只有两档（插件的高密度档 / 桌面的中密度档，后者是 `host-desktop.css` 里 60 余处 `[data-host="desktop"]` 覆写）；远控页落在插件那一档，正文与辅助信息在手机上都比设计稿小一档，既偏小，又因为上一条不能再靠捏合弥补。业界对「一套代码、两端字号不同」的主流解法是把同一套组件**按宿主/设备选一个密度档**（另一个极端是给移动端另写一套 UI 或原生客户端，Claude Code 手机端走的是那条路）；本页是前者的特例——五端里只有它**一种宿主对应两种设备**，所以它在自己这一档里还要再按设备分一层。具体取值归设计与本档的样式文件（本规格只钉住「触控设备上的文本类控件不得低于 iOS 的可读阈值」这条下限，见第 2 条，以及「边界情况」里那条范围）。

4. **假设** 用户用**触控设备**（手机或平板）打开远控页，**则** 页面上**图标按钮**的点击目标与间距按手指给足，不沿用插件（IDE）那一档按鼠标指针定的尺寸：顶栏右侧的图标按钮族（新建对话 / 会话 / 更多；「切换电脑」不在这一族——它已从顶栏收进「更多」菜单，菜单项是整行可点的条，见 `remote-machine.md`「机器列表与切换」场景 5）、输入区左下角的图标按钮族（「+」添加、「/」快捷指令），**提问 / 审批弹窗右上角那一族**（折叠选项、关闭），**消息队列每条右边那一族**（编辑 / 立即发送 / 删除），以及**会话列表页那一族**（每行右侧的「⋯」、页面顶部的「返回」）——页面上相邻图标最密、最容易被误触的几处——每个按钮的**点击热区按移动端的最小可点目标给足**（Apple HIG 与 Material 各自的规范量级）、相邻两个之间的**间距不小于一个手指接触面的容错量**，图标字形随之抬大一档（仍然是「按钮带内边距、字形居中」的原有关系，只是整体放大一档）。**热区与间距必须同时给足**：只把热区撑大而不动间距，相邻两个按钮的可点区域就会相贴甚至重叠，误触**更**容易发生——用户 2026-10-15 报的正是这一点（「图标有点小，手指点起来很容易碰到其他图标」）；2026-10-19 他又对弹窗那两枚报了同一句「还是有点小」，那是首版按「顶栏 + 输入区」两族划范围时留下的第三族；2026-10-29 他对**消息队列每条右边那一族**（编辑 / 立即发送 / 删除）又报了同一句（「消息队列里面的立即发送那些按钮，不是移动端应该有的尺寸」），那是第四族。**判据与第 3 条同源**：`pointer: coarse` / `hover: none`（主输入是手指、没有悬停），不是页面身份、也不用宽度断点——同一张远控页在 PC 浏览器里打开时保持设计稿密度，其余四端（IDE 与桌面）的同一份 UI 一个像素都不动。**让位的对象按承载方式分**（`[data-remote-page]` 作用域的同一档）：顶栏与输入区那两族底下是**固定高度的轨道**，所以轨道跟着抬高到能装下放大后的按钮；弹窗那两枚是**绝对定位**在卡片右上角、没有轨道可抬，让位的是**标题行**——标题行的最小高度要抬到装得下按钮（否则放大后的按钮会往下压住第一道内容），标题本身也要给按钮组让出右侧位置（关闭键恒在 = 一枚按钮 + 间距；带折叠键时 = 两枚 + 两个间距）。**消息队列那一族**底下是**行轨道**：**行高即按钮高**，不额外留上下内衬（首版按「按钮 + 上下各一圈内衬」抬得更高，用户 2026-10-29 随即报「一个队列里的消息上下的空隙特别大」，那圈内衬收回），同一面板的折叠标题行（整行可点、带 chevron）一并抬到同一档；它还多一处比尺寸更靠前的问题——桌面档靠 `:hover` 才把按钮组显形（`opacity: 0`），触控设备没有悬停，这一档必须**常显**（`opacity: 1`），否则按钮放大到足够大也根本没有被按到的机会。**会话列表页那一族**同样按承载方式分：「⋯」放大后**落在行里、不抬行高**——行的本体高度（两行文字 + 内边距）本来就在按钮之上，为它单独抬行只会白占一屏；「返回」没有固定宽高、靠内边距撑起，所以给它一条**最小高度**保证热区；承载这两者的**页头**是固定高度的轨道，跟着抬高、左右内边距也加大，让按钮与屏幕边缘之间的间距给足。输入区右下角的权限档与发送按钮不在本场景内，它们的目标本就更大、也不与谁紧挨着（权限档**收成图标档时**是例外：它就是本场景这一族的尺寸，判据与收法见 `ui/model-selection.md` 的「底栏放不下时模型与权限收成图标档」——手机档一行放不下文字档时模型与权限同时收成图标）。连接状态条右侧的关闭键同属这一档，但它在状态条自己的故事里钉住（`remote-channel.md` 场景 10）：两处判据同源，谁改都别把另一处落下。**依据**：现状那套尺寸是按鼠标指针定的；手指的接触面远大于指针热区，Apple HIG 与 Material 的最小可点目标都比指针热区宽得多，按指针定的中心距在手指下必然误触。**代价照实说**：顶栏与输入区因此各高一些、弹窗标题行高一些、消息队列展开时每条高一些、会话列表页头也高一些，整屏约束（第 1 条）仍须成立——长高的量不能把消息区挤到「顶栏与输入区无法同屏」。

### 边界情况

**Web 页的高度与安全区由浏览器说了算**：本地四端（IDE / 桌面的宿主）都被嵌在一个自己就是整屏的窗口里——页面高度与窗口高度逐像素相等，没有会伸缩的浏览器工具栏，也没有被系统 UI 盖住的边缘。Web 页不是：它跑在浏览器里，可视区随工具栏收起 / 展开而变，页面若按「工具栏收起后」的高度铺满，贴底的输入区就会落到折叠线以下（用户看不到输入框 = 交互失效）；页面又刻意画到屏幕边缘以吃满全面屏，于是状态栏 / 灵动岛、Home 指示条、横屏圆角区都压在内容之上，让开它们同样是页面自己的责任——**但只让顶部与横屏两端**：独立窗口形态下视口高度已经把底部安全区扣过一次，再让一条只是多出一条同色空带（2026-10-15 真机定性，见场景 1）。这两条只对这一个宿主成立 ⇒ 按宿主收口，不落在共享布局上。
**字号档的判据是设备能力，不是页面身份**：远控页是五端里唯一会被**两种形态**打开的一页——手机浏览器与 PC 浏览器打开的是同一张 `/remote/`，所以「这是哪一页」不足以决定字号（这既是它的特点，也是它必须两端都好用的原因）。判据取**输入能力**：`pointer: coarse` / `hover: none` 表示「主输入是手指、没有悬停」，正是手机与平板的共同点，也是业界（claude.ai 共享样式里多处 `@media (pointer:coarse), (hover:none)`）的做法。宽度断点做不到这件事：宽度是连续量，「多大算手机」没有自然分界点，只能任选一个阈值，而两侧都会误判——PC 上把窗口拉窄会被判成手机、小平板又会被判成桌面；横屏手机同样是它漏掉的一种，但那属于补充（他 2026-10-14 判这一页横屏概率很低，见场景 3），不是选触控的主因。它同时也说明为什么这条差异不该写进共享样式：共享样式被五端同时加载，判据必须收在远控页这一层作用域里（`[data-remote-page]`，见上一条）。**「文本类控件不得低于 iOS 可读阈值」那条下限也归这一档**（2026-10-16 改，见场景 2）：它防的 iOS 自动放大是**字号阈值**型的，而 Android 的同族机制（聚焦时的视野补偿、未按设备宽度布局的页面上的文本膨胀）在本页都不成立 ⇒ 这条严格说只对 iOS 必需；但样式里**没有可靠的 iOS 判据**（能区分 Safari 的写法随版本失效），而「主输入是手指」正是本档已在用的稳定判据，且在触控设备上与已抬过一档的正文同档。初版按「无条件给足」写，代价是 PC 上输入框比正文明显偏大（他 2026-10-16 报）。

## 未落地与待决

* \***\*手机档的具体取值**：本规格只钉住三条硬约束（触控设备上的阅读主体可读、文本类控件不得低于 iOS 的可读阈值、图标按钮的点击热区与相邻间距按移动端规范给足），以及「只作用于远控页」这条边界；具体数值落在一个独立的样式文件里（与桌面档同一批角色选择器、比它再大一档），**尚未经设计师过一遍**——正文与字形到底取哪一档，取决于设计稿的刻度。真机观感（尤其「一屏还能看见几条消息」这个信息密度、以及顶栏长高后整屏是否仍装得下，见场景 1）与 PC 浏览器上的观感（那里只该保持设计稿密度、输入控件也不例外）只能靠人工确认。见场景 1 / 2 / 3 / 4。
* \***\*图标按钮的点击目标（2026-10-15 落地，2026-10-19 扩到第三族，2026-10-29 扩到第四族，2026-10-30 补记第五族，真机未验）**：按场景 4 把图标按钮在触控设备上放大一档（按钮热区、图标字形、相邻间距同时放大，落点在 `remote-page.css` 的手机档媒体查询内），并随之抬高装不下它们的固定高度（顶栏、输入区按钮行）。无头实测过两档：触控档逐项达标、PC 档逐项与改动前相同——具体数值以那段媒体查询与 `e2e/remote-page-controls.e2e.ts` 为准，本规格不锁数值。2026-10-19 用户报「提问弹窗右上角那两个图标还是有点小」⇒ 首批漏掉的第三族（提问 / 审批弹窗的折叠选项 + 关闭）按同一档补齐；它单独成条的理由是承载方式不同——这两枚绝对定位在卡片右上角、下面没有固定高度的轨道，要让位的是标题行（最小高度抬到装得下按钮，并给按钮组留出右侧位置），否则放大后的按钮会往下压住第一道内容。2026-10-29 用户报「消息队列里面的立即发送那些按钮，不是移动端应该有的尺寸」⇒ 第四族（队列每条右边的编辑 / 立即发送 / 删除）按同一档补齐：间距同时放大（行与行之间的两枚也算「相邻」），承载它的行轨道抬到与按钮同高（行高即按钮高；首版多留了上下内衬，用户当天报「上下空隙特别大」后收回）；它还多一处**尺寸之外**的问题：桌面档靠 `.queued-item:hover` 才把按钮组显形（`opacity: 0`），触控设备没有悬停，这一档必须常显，否则放大了也没机会被按到——两档各一条 e2e，量之前必须先把指针移出面板，否则 `.queued-item:hover` 会给手机档那条一个假绿。**第五族是 2026-10-30 补记的**：会话列表页那两处（每行右侧的「⋯」、页面顶部的「返回」）随整页会话列表一起就落在这档样式里，但当时没写进本规格——是核「spec 与手机档规则逐条对账」时找出来的口子。「⋯」放大后不抬行高（该行本体本就比按钮高），「返回」靠最小高度保证热区，页头这条固定高度的轨道跟着抬高、左右内边距也加大；间距口径不受影响（行内「⋯」的左邻是文本而非图标按钮，页头本就留了与图标同档的间距）。**仍未做的**：真机确认点准率（第五族同样未验），以及顶栏长高后「顶栏与输入区同屏」是否仍成立——无头浏览器有视口、但没有会伸缩的浏览器工具栏与安全区（那是场景 1 在本机复现不出来的同一件事）。
