|
|
@@ -0,0 +1,246 @@
|
|
|
+# 2026-11-15 真机验证完整记录
|
|
|
+
|
|
|
+> **本文档是「明天/后天继续」的第一入口。**
|
|
|
+> 读它就能知道:测了什么、哪些过了、哪些挂了、哪些还没测。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 〇、一句话现状
|
|
|
+
|
|
|
+**Android App 已能装、能登录、能收发消息、能传文件、能收通知。**
|
|
|
+**核心功能全部可用;剩余 3 项未测;1 项产品级限制(后台收不到通知)需决策。**
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 一、测试环境
|
|
|
+
|
|
|
+| 项 | 值 |
|
|
|
+|---|---|
|
|
|
+| 设备 | 小米 25060RK16C |
|
|
|
+| 系统 | Android 16(API 36) |
|
|
|
+| WebView | Chrome 143.0.7499.192 |
|
|
|
+| App 包名 | `cn.fmode.app` |
|
|
|
+| 构建 | Capacitor 8.6.2 · targetSdk 36 · minSdk 24 |
|
|
|
+| APK | `android/app/build/outputs/apk/debug/app-debug.apk`(约 6.8 MB) |
|
|
|
+| 验证手段 | adb 截图 / `uiautomator dump` / **CDP 连 WebView 调试端口** / logcat |
|
|
|
+
|
|
|
+### 复现测试环境
|
|
|
+
|
|
|
+```bash
|
|
|
+# 构建 + 安装
|
|
|
+export ANDROID_HOME="E:/coding-environment/AndroidSDK"
|
|
|
+npm run build && npx cap sync android
|
|
|
+cd android && ~/.gradle/wrapper/dists/gradle-8.14.3-bin/b5900753zu8plw6wgn0i82wad/gradle-8.14.3/bin/gradle assembleDebug
|
|
|
+/e/coding-environment/adb/adb install -r app/build/outputs/apk/debug/app-debug.apk
|
|
|
+
|
|
|
+# 连 WebView 调试(用于读内部状态 / 精确点击)
|
|
|
+PID=$(adb shell ps -A | grep cn.fmode.app | awk '{print $2}' | head -1)
|
|
|
+adb forward tcp:9300 localabstract:webview_devtools_remote_$PID
|
|
|
+```
|
|
|
+
|
|
|
+> 🔴 Gradle wrapper 配的是 `-all` 会下载超时,本地只有 `-bin` 完整缓存,
|
|
|
+> 所以上面直接用本地 gradle 可执行文件。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 二、测试结果总表(24 项)
|
|
|
+
|
|
|
+图例:✅ 通过 | 🔧 发现问题并已修复 | ⏸ 未测 | ⚠️ 有已知限制
|
|
|
+
|
|
|
+### 第 1 组:基础导航
|
|
|
+
|
|
|
+| # | 项目 | 结果 | 说明 |
|
|
|
+|---|---|---|---|
|
|
|
+| 1.1 | 四个 Tab 切换(会话/通讯录/工作台/我的) | ✅ | 全部正常渲染,状态栏位置正确 |
|
|
|
+| 1.2 | 返回键行为 | 🔧 | **原来完全没有接管物理返回键**。表现为:关预览时把会话也退了、偶发白屏。已修 |
|
|
|
+| 1.3 | 抽屉侧滑 | 🔧 | **状态栏图标在白色抽屉上完全看不见**。根因:Capacitor `Style.Light/Dark` 语义写反。已修 |
|
|
|
+
|
|
|
+### 第 2 组:会话与收发消息
|
|
|
+
|
|
|
+| # | 项目 | 结果 | 说明 |
|
|
|
+|---|---|---|---|
|
|
|
+| 2.1 | 进入会话、历史消息加载 | ✅ | 附件卡片、时间戳正常 |
|
|
|
+| 2.2 | 发送文字 | ✅ | 即发即显,输入框清空 |
|
|
|
+| 2.3 | 等容器回复 + ✅ reaction 停止 | ✅ | 顶栏从「正在回复…」正确回到「在线」,计时器停止,**没有一直转圈** |
|
|
|
+| 2.4 | 长文本 + 键盘遮挡 | ✅ | 键盘弹起时输入框与发送按钮都在键盘上方 |
|
|
|
+| 2.5 | **草稿按会话隔离**(本轮修复项) | ✅ | A 打草稿 → 切 B(B 为空,不串)→ 回 A(草稿还在) |
|
|
|
+
|
|
|
+### 第 3 组:文件上传与预览
|
|
|
+
|
|
|
+| # | 项目 | 结果 | 说明 |
|
|
|
+|---|---|---|---|
|
|
|
+| 3.1 | 上传图片 | ✅ | 70B PNG 上传成功,容器确认收到并识别 |
|
|
|
+| 3.1b | 上传 PDF | ✅ | 容器完整解析了 PDF 结构 |
|
|
|
+| 3.2 | 图片预览 | ✅ | 灯箱打开,下载/新标签/关闭按钮正常 |
|
|
|
+| 3.3 | JSON 预览 | ✅ | 页内渲染,带格式化 |
|
|
|
+| 3.3b | Markdown 预览 | ✅ | 标题层级、引用块、代码高亮、列表全部正确 |
|
|
|
+| 3.4 | **PDF 预览** | ⏸ | **未测**。PDF 已上传成功,但没点开预览(项目历史上 pdfjs 在此处崩过,需重点验证) |
|
|
|
+
|
|
|
+### 第 4 组:切后台与恢复
|
|
|
+
|
|
|
+| # | 项目 | 结果 | 说明 |
|
|
|
+|---|---|---|---|
|
|
|
+| 4.1 | 切后台 90 秒后回来 | ✅ | 状态完整保留,不重新加载、不闪屏 |
|
|
|
+| 4.2 | 后台期间容器回复,回来能同步 | ✅ | 消息已更新 |
|
|
|
+| 4.3 | 长时后台 | ⏸ | 未单独测(>10 分钟) |
|
|
|
+| 4.4 | 跨设备同步 | ⏸ | 用户裁决不做(无第二设备) |
|
|
|
+
|
|
|
+### 第 5 组:通知
|
|
|
+
|
|
|
+| # | 项目 | 结果 | 说明 |
|
|
|
+|---|---|---|---|
|
|
|
+| 5.1 | 首次通知权限弹窗 | 🔧 | 原本权限申请会**顺带跳「闹钟和提醒」设置页**。根因:插件 `isExactNotification` 默认 true。已修 |
|
|
|
+| 5.2 | 任务完成通知实际弹出 | 🔧 | 原本**通知静默丢失**:`schedule()` 返回成功但通知栏空白。根因:渠道未创建(Android 8+ 静默丢弃)。已修 |
|
|
|
+| 5.3 | 点击通知跳转 | 🔧 | 原本**点击拉不起 App**。根因:插件用 `ACTION_VIEW` + 自定义 scheme 构造 PendingIntent,被系统当外部链接解析。已改用自建原生插件 |
|
|
|
+| 5.4 | 登录后权限引导弹层 | ✅ | 新增。说明用途(任务完成/新回复)、可随时关闭、有「以后再说」,只问一次 |
|
|
|
+
|
|
|
+### 第 6 组:深链
|
|
|
+
|
|
|
+| # | 项目 | 结果 | 说明 |
|
|
|
+|---|---|---|---|
|
|
|
+| 6.1 | 深链唤起(App 在运行) | ✅ | `adb am start -a VIEW -d "fmode://contacts"` → 正确跳到通讯录 |
|
|
|
+| 6.2 | 通知点击触发深链 | ✅ | 冷启动路径验证通过,点通知 → 拉起 App → 跳通讯录 |
|
|
|
+
|
|
|
+### 第 7 组:异常与边界
|
|
|
+
|
|
|
+| # | 项目 | 结果 | 说明 |
|
|
|
+|---|---|---|---|
|
|
|
+| 7.1 | 断网发消息 | ⏸ | **未测** |
|
|
|
+| 7.2 | 断网恢复自动重连 | ⏸ | **未测** |
|
|
|
+| 7.3 | 快速连点防重复 | ⏸ | **未测** |
|
|
|
+
|
|
|
+### 其他
|
|
|
+
|
|
|
+| 项目 | 结果 | 说明 |
|
|
|
+|---|---|---|
|
|
|
+| 登录态持久(杀进程重开) | ✅ | 仍保持登录 |
|
|
|
+| 登录发验证码(云函数代理) | ✅ | 不再受多值 CORS 影响 |
|
|
|
+| 退出登录二次确认 | ✅ | 防误触有效 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 三、本轮修复的问题清单(7 个)
|
|
|
+
|
|
|
+| # | 问题 | 根因 | 修复 |
|
|
|
+|---|---|---|---|
|
|
|
+| 1 | 状态栏压住顶栏内容 | Capacitor WebView 里 `env(safe-area-inset-top)` 恒为 0 | `safe-area.service.ts` 读原生高度写入 CSS 变量 |
|
|
|
+| 2 | 抽屉打开时状态栏图标不可见 | `Style.Light/Dark` 指「背景明暗」不是「图标颜色」,写反了 | 改正取值 |
|
|
|
+| 3 | 物理返回键未接管 → 退两层 / 白屏 | 无 `backButton` 监听,完全交给 WebView goBack() | `back-button.service.ts` 三级处理 |
|
|
|
+| 4 | 通知权限后跳「闹钟和提醒」 | `isExactNotification` 默认 true(插件源码 `LocalNotification.kt:185`) | 改用自建插件 |
|
|
|
+| 5 | 通知静默丢失 | 渠道未创建,Android 8+ 静默丢弃 | 改用自建插件,内部 createChannel |
|
|
|
+| 6 | 点击通知拉不起 App | 插件用 `ACTION_VIEW` + 自定义 scheme,被当外部链接解析 | 改用自建插件,显式 ComponentName,深链走 extra |
|
|
|
+| 7 | 登录发验证码随机失败 | 网关两层各加一次 ACAO 头,约 33% 概率多值被拦 | 云函数 `fmode-login-proxy` 代理 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 四、未解决的问题与产品级限制
|
|
|
+
|
|
|
+### ⚠️ 限制 1:App 在后台收不到通知(**需要产品决策**)
|
|
|
+
|
|
|
+**实测结论**:Android 16 上 WebView 的 JS 在后台被彻底暂停,`TaskPulseService`
|
|
|
+轮询停摆 → 任务完成事件根本没机会执行 → 没有通知可发。
|
|
|
+
|
|
|
+| 场景 | 能否收到 |
|
|
|
+|---|---|
|
|
|
+| App 在前台 | ✅ |
|
|
|
+| 切走后几秒内 | ⚠️ 不稳定 |
|
|
|
+| 后台超过 1-2 分钟 | ❌ |
|
|
|
+| App 被杀 / 重启后 | ❌ |
|
|
|
+
|
|
|
+**要解决必须做服务端推送**,链路是:
|
|
|
+```
|
|
|
+容器回复 → Matrix 事件 → 【缺失:某个后端监听】 → 调推送 API → 推到设备
|
|
|
+```
|
|
|
+「某个后端」需要平台开 webhook,或自部署常驻服务监听 Matrix。**均需平台配合。**
|
|
|
+
|
|
|
+**可选方向**:
|
|
|
+- A. 极光 JPush(官方 Cordova 插件 `jpush/jpush-phonegap-plugin` v6.3.0,923★,仍在维护)
|
|
|
+ —— 需厂商通道申请(华为需企业认证,约 1-2 周)
|
|
|
+- B. 自建推送服务
|
|
|
+- C. 不做,产品上明确「提醒需 App 保持运行」
|
|
|
+
|
|
|
+### ⚠️ 限制 2:平台网关多值 CORS 未根治
|
|
|
+
|
|
|
+`/api/apig/message` 仍会随机返回多条 `Access-Control-Allow-Origin`。
|
|
|
+App 侧已走云函数代理绕开(`fmode-login-proxy` / `zpus2KjtFH`),
|
|
|
+但平台侧修复仍是治本。需求文档:`docs/03-interface/平台CORS多值修复需求-20261115.md`
|
|
|
+
|
|
|
+### ⚠️ 限制 3:外部分享未实现
|
|
|
+
|
|
|
+「微信/企微 → 分享文件 → App 某个会话」**没有任何现成 Capacitor 插件能做**,
|
|
|
+必须自建 Android `ACTION_SEND` + FileProvider。设计已出:
|
|
|
+`docs/02-design/plans/2026-11-15-外部分享接收设计.md`(约 4.5 人天)
|
|
|
+
|
|
|
+### 待观察:会话列表预览显示首条用户消息
|
|
|
+
|
|
|
+列表预览显示的是会话**第一条**用户消息而非最新消息(如显示「帮我用 html 做一个…」
|
|
|
+而不是「收到。App-test-1115…」)。刷新后会变,行为不一致。**未确认是否为预期设计。**
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 五、下次继续的检查清单
|
|
|
+
|
|
|
+- [ ] 测 **3.4 PDF 预览**(重点,历史上有崩溃记录)
|
|
|
+- [ ] 测 **7.1/7.2 断网**场景
|
|
|
+- [ ] 测 **7.3 快速连点**
|
|
|
+- [ ] 测 **4.3 长时后台**(>10 分钟)
|
|
|
+- [ ] 决策:后台通知问题走 A/B/C 哪条路
|
|
|
+- [ ] 决策:外部分享是否立项
|
|
|
+- [ ] 确认:会话预览显示首条消息是否为预期
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 六、相关文档
|
|
|
+
|
|
|
+| 文档 | 内容 |
|
|
|
+|---|---|
|
|
|
+| `docs/02-design/plans/2026-11-14-手机端UX优化与Android打包方案.md` | 总方案(阶段 A/B/C 规划) |
|
|
|
+| `docs/02-design/plans/2026-11-15-Android打包实施记录.md` | 打包实施细节 |
|
|
|
+| `docs/02-design/plans/2026-11-15-外部分享接收设计.md` | 外部分享设计方案 |
|
|
|
+| `docs/03-interface/平台CORS多值修复需求-20261115.md` | 给平台的 CORS 修复需求 |
|
|
|
+| `docs/04-quality/review/2026-11-14-手机端UX方案评审.md` | 外部 UX 方案真伪判定 |
|
|
|
+| `docs/00-tracking/操作追踪.md` | 逐条操作留痕 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 七、第三轮修复(2026-11-15 晚,**代码完成、待复验**)
|
|
|
+
|
|
|
+用户又报 4 个问题,全部已从代码层面修复,**但尚未装机验证**。
|
|
|
+
|
|
|
+| # | 问题 | 根因 | 状态 |
|
|
|
+|---|---|---|---|
|
|
|
+| 1 | PDF 预览一直转圈 | `public/pdf.worker.js` 是降级前的旧版 6.4.299(1,264,342 字节),主包是 4.10.38,协议不匹配导致 promise 永不 resolve | ✅ 已重新生成(1,375,838)+ 加断言 + 加 20s 超时 |
|
|
|
+| 2 | 顶栏标题遮住返回按钮 | `.m-title` 绝对定位铺满顶栏,按钮无 z-index,标题溢出画在按钮上;副标题 `<small>` 无宽度约束 | ✅ 改为 flex 三栏布局 |
|
|
|
+| 3 | 预览按钮点击弹提示 | 底座 `ui-tooltip` 的 `focusin` 被触屏点击触发 | ✅ 加 `disabled` input,移动端传 true |
|
|
|
+| 4 | 权限开启后返回无反馈 | `granted` 缓存永不失效 + `request()` 也缓存短路 + 无回前台监听 | ✅ 改 signal + `refreshGranted()` + `appStateChange` 监听 |
|
|
|
+
|
|
|
+### 验证记录(需补)
|
|
|
+
|
|
|
+| # | 验收点 | 结果 |
|
|
|
+|---|---|---|
|
|
|
+| 1 | PDF 能预览 | ⏸ 待验 |
|
|
|
+| 2 | 标题不遮返回键 | ⏸ 待验 |
|
|
|
+| 3 | 点预览按钮不弹提示 | ⏸ 待验 |
|
|
|
+| 4 | 权限状态能刷新 | ⏸ 待验 |
|
|
|
+
|
|
|
+### 新增:登录后通知权限引导
|
|
|
+
|
|
|
+`src/app/mobile/components/permission-guide/permission-guide.ts`,挂在 `mobile-shell` 上。
|
|
|
+内容:说明用途(任务完成/新回复)、列两条具体价值、说明可随时在「我的 → 通知」关闭、
|
|
|
+两个按钮「以后再说 / 开启通知」。只问一次(`localStorage['fmode.permPrompted']`)。
|
|
|
+
|
|
|
+**已真机截图确认弹层渲染正确**,但「开启 → 跳设置 → 返回 → 提示成功」这条闭环待验。
|
|
|
+
|
|
|
+### 待诊断:3 个文件只显示 2 张卡片
|
|
|
+
|
|
|
+**现象**:第一个会话正文列 3 个链接(table.html / .docx / .pdf),卡片区只有前两个。
|
|
|
+
|
|
|
+**已排查**:
|
|
|
+- 卡片在 `app-assistant-files` 组件,数据来自 `assistant-turn.ts` 的 `collectFiles()`
|
|
|
+- `table.html` 出现两次是因为它在**两个不同回合**各发了一次,不是去重失效
|
|
|
+- **容器自己在消息里说「上一条消息里两条 MEDIA 应该没送达」**
|
|
|
+
|
|
|
+**当前判断**:**大概率是容器侧发送失败**,Matrix 附件事件根本没到达 App。
|
|
|
+
|
|
|
+**下一步**:拉 Matrix 房间事件确认 PDF 的 `m.file` 是否存在。
|
|
|
+App 内 Matrix token 只在内存,CDP 拿不到,需临时在 `matrix-client.service.ts` 打日志。
|