Просмотр исходного кода

docs: 环境搭建指南(换电脑快速上手)+ 澄清真机测试未用技能

## 新增 docs/05-operations/环境搭建指南-换电脑快速上手.md
覆盖新电脑从零到打出 APK 的完整路径:
- 必需软件与**实测版本**(Node 22.22 / JDK 21.0.8 / SDK 36 / NDK 27.1)
- 各平台安装步骤(Windows 为主,macOS/Linux 标注差异)
- 依赖清单与为什么锁死某些版本(pdfjs 4.10.38 不可升级)
- **Gradle 下载超时的两种解法**(本机用本地缓存 gradle,通用方案是配国内镜像)
- 真机调试手法:adb 命令、uiautomator 定位、**CDP 连 WebView 读内部状态**
- 常见问题表 + 新电脑接手检查清单

## 澄清:真机测试没有使用技能/MCP
mobile-mcp 一直连接超时,全程是手搓 adb 命令 + 临时 Playwright 脚本。
这一点写进环境指南第六节和进度文档,避免后续误以为有现成工具。

Co-Authored-By: Claude Code <noreply@anthropic.com>
Huccct 4 часов назад
Родитель
Сommit
1007ea8443

+ 4 - 0
CLAUDE.md

@@ -6,6 +6,10 @@
 
 > **完整记录**:`docs/00-tracking/当前进度-给AI接手.md`(30 秒版,含时间线/踩坑/文件索引)
 > **测试详情**:`docs/00-tracking/2026-11-15-真机验证完整记录.md`(24 项逐条 + 第三轮)
+> **换电脑搭环境**:`docs/05-operations/环境搭建指南-换电脑快速上手.md`
+
+**⚠️ 手机端测试没有用任何技能/MCP**:`mobile-mcp` 连不上,全程是 adb 命令 +
+临时 Playwright 脚本(连 WebView 调试端口)。手法见环境指南第六节。
 
 **现在做到哪了**:Android 包已产出并可安装,真机验证 **21/24 项通过**。
 核心功能(登录/收发消息/传文件/Word 预览/通知/深链)可用。

+ 15 - 1
docs/00-tracking/当前进度-给AI接手.md

@@ -1,8 +1,22 @@
 # 项目当前进度(AI 接手必读)
 
-> **最后更新:2026-11-15 14:00**
+> **最后更新:2026-11-15 15:00**
 > **用途:任何 AI 接手本项目时,先读这里,30 秒知道现在做到哪了。**
 > 详细验证记录见 `docs/00-tracking/2026-11-15-真机验证完整记录.md`
+> **换电脑搭建环境**:`docs/05-operations/环境搭建指南-换电脑快速上手.md`
+
+---
+
+## ⚠️ 首先明确:手机端测试用的不是「技能」
+
+我之前做真机测试,**没有使用任何 MCP 服务或技能**:
+
+- `mobile-mcp` 这个 MCP 服务**配置了但一直连接超时**,全程没用上
+- 用的是 **adb 命令**(截图/点击/输日志/`uiautomator dump`)+ **我当场写的临时 Playwright 脚本**
+- 那些 `.tmp-*.mjs` 都是临时产物,用完删了,**不在仓库里**
+
+换电脑后要重做真机调试,得重新搭这套手法 —— 具体步骤见
+`docs/05-operations/环境搭建指南-换电脑快速上手.md` 第六节「真机调试手法」。
 
 ---
 

+ 349 - 0
docs/05-operations/环境搭建指南-换电脑快速上手.md

@@ -0,0 +1,349 @@
+# 环境搭建指南(换电脑快速上手)
+
+> **目标**:在一台新电脑上,从零把本项目跑起来并打出 Android APK。
+> **适用**:Windows(当前环境)· macOS / Linux 标注了差异
+> **最后核对**:2026-11-15,下列版本均为**本机实测版本**
+
+---
+
+## 〇、先看这个(30 秒)
+
+```bash
+# 1. 基础环境:Node 22 + JDK 21 + Android SDK
+# 2. 克隆代码
+git clone https://git.fmode.cn/ice-static/fmode-app.git
+cd fmode-app
+
+# 3. 装依赖(postinstall 会自动生成 pdf worker)
+npm install
+
+# 4. 跑 Web 端
+npm start          # → http://localhost:4200
+
+# 5. 打包 Android
+node scripts/copy-pdf-worker.mjs
+npm run build && npx cap sync android
+cd android && ./gradlew assembleDebug
+```
+
+**构建成功后**:`android/app/build/outputs/apk/debug/app-debug.apk`
+
+> ⚠️ 第 5 步的 `./gradlew` 在本机**会因下载超时而失败**,详见「四、Gradle 坑」。
+
+---
+
+## 一、必需软件(版本必须对)
+
+| 软件 | **本机实测版本** | 要求 | 为什么 |
+|---|---|---|---|
+| **Node.js** | **v22.22.3** | ≥ 20 | Angular 20 要求;Capacitor 8 要求 Node ≥ 20 |
+| **npm** | **10.9.8** | 随 Node | 项目用 npm(**不是 pnpm**,根目录的 `pnpm-lock.yaml` 是历史遗留,忽略它) |
+| **JDK** | **21.0.8 (Microsoft OpenJDK)** | **必须 21** | Capacitor 8 的 AGP 要求 JDK 21;17 会报错 |
+| **Android SDK** | platform **36** / build-tools **36.x** / NDK 27.1 | compileSdk 36 | `capacitor.config.ts` 里 targetSdk=36 |
+| **Android Studio** | AI-251(2025.1) | 可选 | 只为可视化调试;纯命令行构建不装也行 |
+| **adb** | Platform-Tools 36.0.1 | 随 SDK | 装 App / 看日志 / 截图 |
+
+### 本机的实际安装位置(换电脑时作参考,无需照搬)
+
+```
+JDK        E:\coding-environment\jdks\21          (JAVA_HOME)
+AndroidSDK E:\coding-environment\AndroidSDK       (需设为 ANDROID_HOME)
+adb        E:\coding-environment\adb\adb
+Android Studio E:\coding-environment\Android
+Gradle 缓存 ~/.gradle/wrapper/dists/gradle-8.14.3-bin
+Playwright ~/AppData/Local/ms-playwright
+```
+
+---
+
+## 二、安装步骤
+
+### 2.1 Node.js
+
+**Windows**:装 [nvm-windows](https://github.com/coreybutler/nvm-windows) 后
+```bash
+nvm install 22
+nvm use 22
+```
+或直接下 [Node 22 LTS 安装包](https://nodejs.org/)。
+
+**macOS/Linux**:`nvm install 22 && nvm use 22`
+
+验证:`node -v` 应输出 `v22.x`
+
+### 2.2 JDK 21
+
+**Windows**:
+```bash
+# 用 winget
+winget install Microsoft.OpenJDK.21
+# 或 scoop
+scoop install temurin21-jdk
+```
+装完设置环境变量:
+```powershell
+[Environment]::SetEnvironmentVariable('JAVA_HOME','C:\Program Files\Microsoft\jdk-21','User')
+```
+
+**macOS**:`brew install --cask temurin@21`
+**Linux**:`sudo apt install openjdk-21-jdk`
+
+验证:`java -version` 必须是 **21.x**
+
+> 🔴 **JDK 版本是最容易踩的坑**。项目历史上装的是 21,如果新机器是 17,AGP 会直接报
+> `Unsupported class file major version` 之类。**别用 17,别用 24。**
+
+### 2.3 Android SDK
+
+**推荐用 Android Studio 的 SDK Manager 装**(最省事):
+1. 装 [Android Studio](https://developer.android.com/studio)
+2. SDK Manager → SDK Platforms 勾 **Android 16 (API 36)**
+3. SDK Tools 勾 **Android SDK Build-Tools 36.x**、**Platform-Tools**、**NDK 27.1**
+
+**纯命令行**(不装 Studio):
+```bash
+# 下载 commandline-tools,解压到 <SDK_ROOT>/cmdline-tools/latest
+sdkmanager "platforms;android-36" "build-tools;36.0.0" "platform-tools" "ndk;27.1.12297006"
+```
+
+**设置环境变量**(本项目**必须**,否则 Gradle 找不到 SDK):
+```bash
+export ANDROID_HOME="<你的SDK路径>"        # Windows: E:/coding-environment/AndroidSDK
+export ANDROID_SDK_ROOT="$ANDROID_HOME"
+```
+Windows 持久化:
+```powershell
+[Environment]::SetEnvironmentVariable('ANDROID_HOME','E:\coding-environment\AndroidSDK','User')
+```
+
+> 🔴 **本机的 `ANDROID_HOME` 目前是空的**(每次构建我都是临时 `export`)。
+> 换电脑时建议**直接写进系统环境变量**,省得每次手动设。
+
+---
+
+## 三、项目依赖
+
+```bash
+npm install
+```
+
+`postinstall` 会自动跑 `scripts/copy-pdf-worker.mjs`,生成 `public/pdf.worker.js`。
+
+### 关键运行时依赖(不用单独装,`npm install` 全搞定)
+
+| 包 | 版本 | 用途 |
+|---|---|---|
+| `@angular/*` | ^20.3.0 | 框架 |
+| `@capacitor/core` / `android` / `cli` | ^8.6.2 | 打包 |
+| `@capacitor/app` | ^8.1.2 | 深链监听、回前台事件 |
+| `@capacitor/local-notifications` | ^8.3.1 | 权限查询(**发通知已改用自建插件**) |
+| `@capacitor/status-bar` | ^8.0.4 | 状态栏安全区 |
+| `@capacitor/share` | ^8.0.3 | 向外分享(已装未启用) |
+| `pdfjs-dist` | **4.10.38(锁死)** | PDF 预览,**不可随便升级** |
+| `@silurus/ooxml` | ^0.66.3 | Word/Excel 预览 |
+| `matrix-js-sdk` | ^42.4.0 | 消息收发(懒加载) |
+
+### Playwright(真机/CDP 调试用)
+
+```bash
+npm install          # playwright 在 devDependencies 里
+npx playwright install msedge      # 或用系统已装的 Edge
+```
+> 本机用的是 **系统 Edge**(`chromium.launch({ channel: 'msedge' })`),
+> 因为 `playwright install chromium` 没装浏览器时连不上。新机器要么装 Edge(Windows 自带),
+> 要么 `npx playwright install chromium`。
+
+---
+
+## 四、Gradle 坑(本机实测,**换电脑必看**)
+
+### 症状
+
+```
+java.net.SocketTimeoutException: Connect timed out
+    at org.gradle.wrapper.Install.forceFetch
+```
+
+`./gradlew` 会去 `services.gradle.org` 下载 Gradle 发行包,**国内经常超时**。
+
+### 两种解法
+
+**解法 A(本机采用):改用本地已缓存的 gradle**
+
+```bash
+# 先看本地有什么版本
+ls ~/.gradle/wrapper/dists/
+
+# 直接用解压好的可执行文件(跳过 wrapper 下载)
+~/.gradle/wrapper/dists/gradle-8.14.3-bin/<hash>/gradle-8.14.3/bin/gradle assembleDebug
+```
+
+**解法 B(更通用):配国内镜像**
+
+编辑 `android/gradle/wrapper/gradle-wrapper.properties`,把
+`distributionUrl` 换成:
+```properties
+distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.14.3-bin.zip
+```
+(或用阿里云镜像 `https://mirrors.aliyun.com/macports/distfiles/gradle/`)
+
+> 🔴 `gradle-wrapper.properties` 里原来是 `-all` 包(100+MB),
+> 本机已改成 `-bin`(约 60MB),下载量小一半。
+
+### 另一个坑:Maven 依赖下载慢
+
+首次构建要下几十个 AndroidX 依赖。可以在 `android/build.gradle` 和
+`android/settings.gradle` 的 `repositories` 里加阿里云镜像:
+
+```groovy
+maven { url 'https://maven.aliyun.com/repository/google' }
+maven { url 'https://maven.aliyun.com/repository/public' }
+```
+
+---
+
+## 五、跑起来
+
+### 5.1 Web 端(开发调试最快)
+
+```bash
+npm start              # ng serve → http://localhost:4200
+# 或指定端
+open http://localhost:4200/mobile/messages
+open http://localhost:4200/desktop/chat
+```
+
+**免登录开发**:项目根有 `.claude/dev-login.json`(**不入库**),
+`npm run dev:logged-in` 会自动注入登录态。
+
+### 5.2 Android App
+
+```bash
+# 一次性完整流程
+export ANDROID_HOME="E:/coding-environment/AndroidSDK"
+node scripts/copy-pdf-worker.mjs
+npm run build && npx cap sync android
+cd android && ~/.gradle/wrapper/dists/gradle-8.14.3-bin/*/gradle-8.14.3/bin/gradle assembleDebug
+
+# 装到手机(先开 USB 调试)
+adb install -r app/build/outputs/apk/debug/app-debug.apk
+```
+
+也可以用 npm 脚本:`npm run cap:sync` / `npm run cap:open` / `npm run cap:apk`。
+
+---
+
+## 六、真机调试手法(**这些是手搓的,没有现成技能**)
+
+> 🔴 **重要说明**:手机端测试**没有用任何 MCP 服务或技能**。
+> `mobile-mcp` 配置了但一直连接超时,全程是手工拼 `adb` 命令 + 临时写 Playwright 脚本。
+
+### 6.1 基础 adb
+
+```bash
+adb devices -l                              # 设备列表
+adb shell screencap -p /sdcard/s.png        # 截图
+adb pull /sdcard/s.png ./shot.png           # 拉回本地
+adb shell input tap 640 1200                # 点击(坐标是**物理像素**)
+adb shell input text "hello"                # 输入(**只支持 ASCII**,中文会崩)
+adb shell input keyevent 4                  # 返回键
+adb shell input keyevent 3                  # Home
+adb logcat -d | grep -i fmode               # 看日志
+```
+
+> 🔴 **坐标换算**:截图在终端里显示时会缩放。Read 工具会提示
+> 「multiply coordinates by 1.39」,意思是**显示坐标 × 1.39 = 物理坐标**。
+> 直接按看到的坐标点会点偏。
+
+### 6.2 精确定位元素(比目测坐标靠谱)
+
+```bash
+adb shell uiautomator dump /sdcard/ui.xml
+adb shell cat /sdcard/ui.xml | tr '>' '\n' | grep '通知'
+# 输出里找 bounds="[46,426][1234,703]" → 中心点 (640, 565)
+```
+
+**点击通知栏通知必须用这个**,目测坐标会点空(踩过)。
+
+### 6.3 连进 WebView 读内部状态(最有用的手法)
+
+```bash
+# 1. 拿到 App 的 PID
+PID=$(adb shell ps -A | grep cn.fmode.app | awk '{print $2}' | head -1)
+
+# 2. 把 WebView 调试端口转发到本机
+adb forward tcp:9400 localabstract:webview_devtools_remote_$PID
+
+# 3. 用 Playwright 连上去(脚本自己写)
+```
+
+脚本模板(存成任意 `.mjs`,用 `node xxx.mjs` 跑):
+
+```js
+import { chromium } from 'playwright';
+const b = await chromium.connectOverCDP('http://127.0.0.1:9400');
+const p = b.contexts()[0].pages()[0];
+
+// 读 DOM / 执行任意 JS
+const v = await p.evaluate(() => {
+  return getComputedStyle(document.documentElement).getPropertyValue('--mob-safe-top');
+});
+console.log(v);
+
+await b.close();
+```
+
+**能干什么**:
+- 读 CSS 变量实际值(排查安全区问题就靠这个)
+- 查 DOM 结构、元素数量
+- 直接调 Capacitor 插件:`window.Capacitor.Plugins.LocalNotifications.checkPermissions()`
+- **触发文件选择器**:`p.waitForEvent('filechooser')` + `chooser.setFiles(路径)`
+- 走 Angular 的路由/服务状态
+
+> 🔴 **注意**:连 App 的 WebView 用 `waitUntil: 'domcontentloaded'`,
+> **不要用 `networkidle`** —— Matrix 长轮询永远不会 idle,会一直等到超时。
+
+---
+
+## 七、环境变量清单
+
+| 变量 | 值 | 必需 |
+|---|---|---|
+| `JAVA_HOME` | JDK 21 目录 | ✅ |
+| `ANDROID_HOME` | Android SDK 目录 | ✅(构建 Android) |
+| `ANDROID_SDK_ROOT` | 同 ANDROID_HOME | 建议 |
+| `PATH` | 含 `%JAVA_HOME%\bin`、`%ANDROID_HOME%\platform-tools` | ✅ |
+
+---
+
+## 八、常见问题
+
+| 现象 | 原因 | 解法 |
+|---|---|---|
+| `gradlew` 超时 | Gradle 发行包下载慢 | 见「四、Gradle 坑」 |
+| `ANDROID_HOME not set` | 环境变量没配 | 见 2.3 |
+| `Unsupported class file major version` | JDK 版本不对 | 换 JDK 21 |
+| **PDF 一直转圈** | `public/pdf.worker.js` 是旧版 | `node scripts/copy-pdf-worker.mjs`(有断言会告诉你) |
+| `npm install` ECONNRESET | 网络抖动 | `npm i --fetch-retries=5` |
+| `playwright` 找不到浏览器 | 没装浏览器 | `npx playwright install chromium` 或用系统 Edge |
+| App 里字体/样式不对 | 没跑 `cap sync` | `npm run build && npx cap sync android` |
+| 真机白屏 | 见 `docs/00-tracking/` 对应事故文档 | — |
+
+---
+
+## 九、新电脑接手检查清单
+
+跑完下面这些全部通过,说明环境 OK:
+
+```bash
+node -v                    # v22.x
+java -version              # 21.x
+echo $ANDROID_HOME         # 非空,且目录存在
+npm install                # 无报错,且自动生成了 public/pdf.worker.js
+node scripts/copy-pdf-worker.mjs   # 输出「已校验」,字节数一致
+npm run build              # Output location: dist/fmode-app-v2
+npx tsc --noEmit -p tsconfig.app.json   # 无输出(无错误)
+adb devices                # 能看到设备(真机调试才需要)
+```
+
+**然后**:读 `docs/00-tracking/当前进度-给AI接手.md` 了解进度再动手。