# Windows 迁移清单 > 2026-07-09 整理。本项目从 macOS 搬到 Windows 前必读。 > > 核心结论:安装 Python 与 Android Platform Tools 后可直接运行;ADB 会自动从 `AUTOTRAIN_ADB`、PATH、旧 macOS 安装位置依次发现。 ## 一、必须一起带的文件(项目外依赖) | 依赖 | 说明 | 当前位置 | Windows 处理 | |---|---|---|---| | **ADB(platform-tools)** | 所有手机操作的运行依赖 | PATH 或 `AUTOTRAIN_ADB` | 装 Android Platform Tools,将 `adb.exe` 加 PATH 或设置 `AUTOTRAIN_ADB` | | **Python 3.12+** | 标准库 + 3 个三方包 | 系统 Python | 装 Python 3.12+;子进程自动复用当前解释器 | | **openpyxl** | 读 xlsx 名单(`invoice_tool.py:27`,try/except 守护) | pip 安装 | `pip install openpyxl` | | **pypdf** | `add_invoice_passenger_name.py` 硬 import | pip 安装 | `pip install pypdf` | | **qrcode** | 生成二维码(`invoice_tool.py:1698`,lazy import) | pip 安装 | `pip install qrcode` | | **numpy** | 可选(`invoice_tool.py:167`,try/except) | pip 安装 | `pip install numpy`(不装也能跑) | ## 二、跨平台运行机制 所有 ADB 调用已统一经过 `scripts/device_runtime.py`:每次只允许一台已授权手机,并自动带上 ADB serial。无需按设备修改源码;多台手机同时连接时会拒绝运行,避免误开票。 若 PATH 未配置,可在当前终端设置: ```cmd set AUTOTRAIN_ADB=C:\platform-tools\adb.exe ``` ## 三、不能直接跑的脚本(macOS 专属) | 脚本 | 问题 | Windows 替代 | |---|---|---| | `scripts/restart_web_ui.sh` | bash 脚本 + 用 `lsof` + `pgrep` + `launchctl` + `os.fork()` | 见下方「Windows 启动方案」 | | `scripts/web_ui_watchdog.sh` | bash 脚本 + `lsof` + `curl` 循环 | 用 `scripts/start_web_ui.cmd` 或 `python scripts/run_web_ui.py` 前台跑 | | `scripts/install_web_ui_launch_agent.sh` | 生成 macOS LaunchAgent plist | Windows 不需要,用启动菜单/任务计划程序替代 | ### Windows 启动方案 最简单:双击 `scripts\\start_web_ui.cmd`,或开个 cmd 直接前台跑。 ```cmd cd C:\path\to\autotrain python scripts\run_web_ui.py ``` 或者写个 `start_web_ui.bat`: ```bat @echo off cd /d %~dp0\.. python scripts\run_web_ui.py pause ``` ## 四、配置文件 ### config.local.json(已含识别 key,必须带) ```json { "company_title": "...", "tax_id": "...", "receiver_email": "...", "vision": { "provider": "siliconflow", "base_url": "https://api.siliconflow.cn/v1", "api_key": "sk-xxx", "model": "Qwen/Qwen3-VL-8B-Instruct" }, "invoice_success_action": "download", "invoice_output_dir": "output/01" } ``` **这个文件在 .gitignore 里,必须手动打包带过去。** 识别 key 已在里面。 ### work/ 目录(部分需要带) `work/` 整个在 .gitignore 里。需要带的: | 文件 | 必须带 | 说明 | |---|---|---| | `passenger_roster.csv` | ✅ | 当前名单(44 人),不带要重新 import-roster | | `android_invoice_progress.csv` | ✅ | 开票进度(143 completed),不带会重复开票 | | `qr_page_order.csv` | ✅ | 本二维码核查表 | | `agent_id_last8.txt` | ✅ | 代理人证件后 8 位 | | `last_qr_image.png` / `last_qr_url.txt` | ✅ | 上次扫码的二维码,H5 precheck 用 | | `device_profile.json` | ❌(不存在) | Windows 上跑 `/calibrate` 重新生成 | | `android_page_queue.csv` | ❌ | 当前页队列,临时态,可不带 | | `*.log` / `*.png`(调试截图) | ❌ | 无价值 | ### data/ 目录 `.gitignore` 忽略了 `data/input/`、`data/mail/`、`data/attachments/`。如果还要跑 import-codes / collect-mail,需要带对应输入文件。如果只跑 H5 开票,不需要。 ## 五、手机/ADB 环境(Windows 侧准备) 1. **装 Android Platform Tools**:https://developer.android.com/tools/releases/platform-tools 2. **手机开 USB 调试**:设置 -> 开发者选项 -> USB 调试 3. **验证 ADB 连通**:`adb devices` 能看到设备 4. **12306 App 装好**,登录,能到扫码开票页 ## 六、换手机/换屏幕必跑 到了 Windows + 新手机后,**第一件事**: 1. 打开 `http://127.0.0.1:8765/calibrate`(改完代码启动后) 2. 点「💾 保存设备配置」生成 `work/device_profile.json` 3. 逐状态截图校准(重点:「确认」「继续开票」「开具」) 4. `python scripts/invoice_tool.py android-h5-page-run --dry-run --max-actions 1` 验证 详见 `docs/device-adaptation.md`。 ## 七、打包压缩建议 ``` 要打包的: scripts/ (全量,含 9 个脚本) docs/ (全量,含 device-adaptation / screen-adaptation / web-ui-adaptation-log) templates/ (全量) config.local.json (关键!含识别 key) config.example.json AGENTS.md / INDEX.md / CHANGELOG.md / CODEMAP.md work/passenger_roster.csv work/android_invoice_progress.csv work/qr_page_order.csv work/agent_id_last8.txt work/last_qr_image.png work/last_qr_url.txt 不要打包的: archive/ (旧备份,体积大) output/ (已交付发票,体积大) data/input/ (原始开票码,如不跑 import-codes 不需要) data/mail/ data/attachments/ work/*.log work/*.png(调试产物) work/__pycache__/ .git/ ``` ## 八、Windows 上首次运行步骤 ```cmd REM 1. 装 Python 3.12+ 和 ADB REM 2. pip install openpyxl pypdf qrcode REM 3. 将 adb 加入 PATH,或设置 AUTOTRAIN_ADB=C:\platform-tools\adb.exe REM 4. 启动 cd C:\path\to\autotrain python scripts\run_web_ui.py REM 5. 浏览器打开 http://127.0.0.1:8765 REM 6. 进 /calibrate 自动校准当前唯一连接的手机 REM 7. dry-run 验证 python scripts\invoice_tool.py android-h5-page-run --dry-run --max-actions 1 ```