Bundle
dsh-mobile-ux
DeepSeek Harness 手机端访问体验优化插件:纯客户端移动 UI 层(响应式抽屉布局、字号/间距适配、触控目标、按钮/菜单/表格移动端交互、安全区适配),桌面宽度显示不受影响。
- Source
- wangyuanchuan2022
- License
- GPL-2.0
- Updated
- Updated 5 days ago
Readme
<p align="center">
<h1 align="center">dsh-mobile-ux</h1>
<p align="center">面向手机端访问体验的 <b>DeepSeek Harness</b> UI 优化插件(纯客户端)</p>
</p>
<p align="center">
<a href="README.md">中文</a> | <a href="README.en.md">English</a>
</p>
> 一个包、零配置:把 DeepSeek Harness 网页版在手机宽度下的体验从头打磨一遍——响应式抽屉布局、字号/间距适配、≥44px 触控目标、按钮/菜单/表格移动端交互、安全区适配。**桌面宽度显示与使用完全不受影响。**
## 这是什么
DeepSeek Harness 网页版默认按桌面三列布局设计,在手机宽度下会出现:侧栏挤压主内容、正文 16px 偏大、触控目标过小、宽表格/代码块把横向滚动条推给视口、设置页两列布局留大片死区等问题。
`dsh-mobile-ux` 是一个**纯客户端插件**(宿主侧零逻辑):在窄屏(`max-width: 1023px`,与 shell 的 `SIDEBAR_AUTO_COLLAPSE` 一致)自动注入一套移动 UI 优化层;在宽屏(`≥1024px`)所有移动控件一律隐藏,桌面布局原样保留。
它基于 [dsh-pocket](https://github.com/shaobeichen/dsh-pocket) 的「单包客户端插件」组织方式,但移动 UI 层为**从零实现**(不依赖 `dsh-web-mobile`)。既可单独使用,也可与 `dsh-pocket` 并存——后者继续负责「扫码远程访问」,本插件只负责「手机上的界面更好用」。
## 安装
**前提**:已装好 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(`dsh` CLI)。
```sh
# 从 GitHub 直装
dsh plugin --profile web add "github:wangyuanchuan2022/dsh-mobile-ux" -w
# 重启 dsh web 生效
npx @deepseek-ai/dsh web
```
> 本地开发/试用可用 link 安装(不依赖网络,指向本地路径):
>
> ```sh
> dsh plugin --profile web add "link:/绝对/路径/dsh-mobile-ux" -w
> ```
>
> 提示 1:手机扫码访问本身由 [dsh-pocket](https://github.com/shaobeichen/dsh-pocket) 提供(局域网/公网二维码),本插件只负责手机端 UI。
>
> 提示 2:`dsh-pocket` 自带一套移动抽屉层;二者可互相替代,**不建议同时启用**——同时安装会出现两套移动控件。若已装 `dsh-pocket` 且想单用本插件的移动 UI,可先 `dsh plugin --profile web remove dsh-pocket -w`(代价是失去扫码远程访问),或接受两者并存。
## ✨ 优化点逐项说明
所有规则都只作用于窄屏(`max-width: 1023px`);宽屏(`min-width: 1024px`)下移动控件全部 `display:none`,桌面布局不受任何影响。
| # | 优化点 | 实现方式 | 效果 |
|---|---|---|---|
| 1 | **响应式抽屉布局** | AppFrame 打上 `data-mobile-ux="frame"` 标记;三列网格重排为 `minmax(0,1fr) 0 0`,把中心列拉回第 1 轨;侧栏列改为绝对定位的左侧抽屉(`translateX(-105%)` 收起 / `transform:none` 展开,`max-width:84vw`) | 侧栏不再挤压主内容,会话区域全宽;抽屉滑入滑出,点遮罩/点外部/点导航项自动关闭 |
| 2 | **字号与间距适配** | 正文容器 `font-size:15px`、左右留白从 32px 收紧到 16px;去掉桌面滚动条占位 `scrollbar-gutter` 与滚动条 | 一屏可读更多内容,列精确居中,无桌面滚动条挤偏移 |
| 3 | **触控目标 ≥44px** | FAB 直接 44×44px;头部目录开关 28px 视觉 + `::after{inset:-8px}` 扩展命中区至 44×44px;设置页关闭按钮 40px 圆形基座;外观卡 `min-height:44px` | 符合移动端可用性基线(Apple HIG / Material 建议 ≥44px),点按不易误触 |
| 4 | **头部/菜单移动端交互** | 会话头部注入目录开关(`conversation.session.header.actions`);hero/空白阶段注入浮动目录按钮 FAB(`shell.overlay`);backdrop 纯视觉压暗(`pointer-events:none`),关闭交给 document 级「抽屉外点击」监听 | 无论有无会话都能一键唤出目录;遮罩不抢点击,抽屉内点击不被吞掉 |
| 5 | **设置页下沉为 sheet** | 桌面两列设置对话框在窄屏改为近全宽 sheet(`left:8px; width:calc(100vw - 16px)`);导航 tab 折成 3 列网格;选项行「标题+描述在上、控件在下」堆叠;外观三卡改横向三连;工具栏两端展开 | 设置页在手机上无死区、无横向溢出、tab 全部可见,实测 390px 下 `width:374px` 完整显示 |
| 6 | **宽内容防溢出(表格/代码块)** | 消息区内的 `table`、`pre` 设 `max-width:100%; overflow-x:auto`;消息动作行 `overflow:hidden` + 省略号 | 长表格/长代码/长串只在自身容器内横滑,**绝不把横向滚动条推给视口** |
| 7 | **会话统计行横滑** | 客户端按文本锚定 turns/steps/LLM/TTFT/cache 那行,打 `data-mobile-ux="stats"`,CSS 排成固定 28px 高、横向滚动的单行条(含 TPS 并入) | 全部指标通过滑动触达,行高不涨、不换行、不省略 |
| 8 | **输入区优化** | 模型胶囊改为可收缩(`flex:1 1 auto`)、权限胶囊保持自然宽度,避免权限胶囊被挤成 15px;hero 空态 textarea 收缩为一行 | 输入区底行在窄屏不再溢出/重叠,hero 空态更紧凑 |
| 9 | **会话头部布局** | 头部排成 `[目录开关][会话标题][模式徽标]` 一行;「导出会话日志」胶囊从头部搬迁到抽屉底部(功能不丢) | 头部信息密度合理,窄屏不再被长胶囊顶破 |
| 10 | **安全区适配** | 客户端把 viewport meta 改成 `viewport-fit=cover`,CSS 用 `env(safe-area-inset-top)` 把内容推到状态栏/刘海之下;`theme-color` 跟随主题底色 | 刘海屏/状态栏不遮挡内容,状态栏读起来像 UI 的一部分 |
| 11 | **双击缩放抑制** | `html,body{touch-action:manipulation}` + 旧 iOS `gesturestart` 兜底 | 消除双击缩放与 300ms 点击延迟,保留平移与捏合缩放 |
| 12 | **降级/可访问性** | 抽屉支持 `Escape` 关闭(有模态框时让位);`prefers-reduced-motion` 下关闭动画;控件带 `aria-label`/`focus-visible` 焦点环 | 键盘与辅助技术可用,动效敏感用户不受影响 |
## ✅ 验收实测
在隔离 DSH 实例(`dsh web --port 3090`)上用无头 Edge(CDP)实测:
| 视口 | 横向滚动条 | frame 改写 | 移动控件 | 触控交互 |
|---|---|---|---|---|
| 桌面 1280×800 | ✅ 无(`scrollWidth==1280`) | ✅ 未改写(桌面原样) | ✅ 全部隐藏 | — |
| 手机 390×844 | ✅ 无(`scrollWidth==390`) | ✅ 抽屉布局生效 | ✅ FAB 44×44 可见 | ✅ 触摸/鼠标/点击均能打开抽屉 |
| 手机 430×932 | ✅ 无(`scrollWidth==430`) | ✅ 抽屉布局生效 | ✅ FAB 44×44 可见 | ✅ |
- 设置页 sheet 实测:390px 下 `x:8, width:374, right:382`,无横向溢出,导航 tab 完整可见。
- 触控目标实测:FAB `getBoundingClientRect()` = **44×44px**,命中区满足 ≥44px 基线。
复现方式见下方「开发」;输出报告与截图落在 `.verify-out/`(已 gitignore)。
## 🗂 架构(单包,纯客户端)
| 文件 | 说明 |
|---|---|
| `lib/index.js` | 宿主侧入口:仅导出合法的 cordis 插件标识(`name`/`inject`/`apply`),无任何宿主逻辑,作用是让 Loader 建立 fiber 以编入客户端图谱 |
| `cordis.patch.yml` | `dsh.bundle` manifest:把插件插入 profile bundle 层 |
| `client/index.jsx` | 客户端入口:导出 `apply`/`name`/`inject`,挂载移动 UI 层 |
| `client/build.mjs` | esbuild 打包:`client/index.jsx → client/client.js`(`window.__ModuleLoader__.load` 包装) |
| `client/mobile/mobile.css.ts` | 移动端样式表(从零实现,仅用稳定框架契约选择器) |
| `client/mobile/mobile-apply.tsx` | 客户端 apply:注入样式 + 手机 chrome + 统计行标记 + 三个 slot 组件 |
| `client/mobile/MobileNavToggle.tsx` | 会话头部目录开关 |
| `client/mobile/MobileNavOverlay.tsx` | shell 覆盖层:frame 标记 + backdrop + FAB + 抽屉交互 |
| `client/mobile/MobileDrawerFooter.tsx` | 抽屉底部「导出会话日志」 |
| `client/mobile/locales.ts` | `mobileUx` 词典(zh/en) |
| `scripts/verify-mobile.mjs` | 无头 Edge + CDP 移动验收脚本(桌面/手机宽度 + 触控交互) |
| `scripts/verify-settings.mjs` | 设置页 sheet 验收脚本 |
| `test/*.test.js` | 单元测试(host 契约 / package 契约 / locale 一致 / CSS 契约 / bundle 冒烟) |
## 🛠 开发
```sh
npm install
npm run build:client # 改 client/ 后重新打包
npm test # 单元测试(19 项)
```
移动端实测(需要一个隔离的 `dsh web` 实例):
```sh
# 终端 1:隔离实例(用独立 DSH_HOME 与端口,不影响日常实例)
$env:DSH_HOME = "D:\path\to\.dsh-test" # Windows PowerShell
dsh plugin --profile web add "link:D:/path/to/dsh-mobile-ux" -w
dsh web --port 3090
# 终端 2:跑验收脚本(无头 Edge + CDP)
node scripts/verify-mobile.mjs
node scripts/verify-settings.mjs
```
## 🤝 致谢与关系
- 插件组织方式(单包客户端插件、`dsh.client`/`cordis.patch.yml`/`__ModuleLoader__` 打包)参考 [dsh-pocket](https://github.com/shaobeichen/dsh-pocket)(GPL-2.0)。
- 移动 UI 层为**独立从零实现**,未复用 [dsh-web-mobile](https://github.com/mexiaosqwq/dsh-web-mobile) 代码;二者可互相替代(不建议同时启用两个移动抽屉层)。
## 📄 License
[GPL-2.0](LICENSE) —— 自由软件许可:可自由使用、修改、分发,但**修改版必须同样以 GPL 开源**并保留版权声明。
---
**有问题?欢迎反馈**:到 [GitHub Issues](https://github.com/wangyuanchuan2022/dsh-mobile-ux/issues) 告诉我们。
Install
dsh plugin --profile web add github:wangyuanchuan2022/dsh-mobile-ux#63d2c71dd7c7962119b7ed2f0389bbda74e745fc
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-mobile-ux from the hub