[Feature] Android 移动端交付方案:先落地 PWA,再评估 TWA/Capacitor
Author: ZhuLinsenCreated Jul 31, 2026Updated Aug 1, 2026
Labelsenhancement
功能描述 / Feature Description
评估并分阶段提供 Android 移动端体验。基于当前架构,建议先把现有 React Web 做成可安装 PWA;确认存在商店分发或原生能力需求后,再选择 TWA 或 Capacitor。现阶段不建议重写原生 UI,也不建议把完整 Python/FastAPI 分析后端打进 APK。
核心结论:
- 近期推荐:移动端适配完善 + 可安装 PWA。
- 可选第二阶段:有固定官方 HTTPS 域名并需要 Google Play 分发时,使用 TWA/Bubblewrap 打包 AAB。
- 条件触发方案:需要原生推送、系统分享、扫码配对、生物识别等能力时,再引入 Capacitor。
- 暂不实施:Flutter/React Native 重写;Android 本地嵌入完整 Python 分析后端。
使用场景 / Use Case
- 用户希望在 Android 桌面直接打开 Web 工作台,查看报告、任务、持仓、预警和策略对话。
- 官方托管服务需要 Google Play 商店入口。
- 自托管用户希望从手机访问自己的 DSA 服务。
- 后续可能需要推送通知、扫码绑定服务器、系统分享或文件导出。
需要先明确产品模式:
- 官方托管模式:Android 客户端固定连接官方 HTTPS 域名,适合 PWA/TWA。
- 自托管模式:用户访问各自服务器并安装 PWA;如需统一商店客户端,则要用 Capacitor 增加服务器地址配置、配对与移动端认证。
- 手机离线独立分析:需要把 Python 和重依赖搬到 Android,当前不建议进入实现范围。
当前实现分析
- Web 使用 React + Vite,已有移动抽屉、响应式布局等基础,主要可复用代码位于
apps/dsa-web/。 - 当前不是 PWA:没有 Web App Manifest、Service Worker 注册和完整的应用图标/安装更新流程。
- Vite 产物输出到根目录
static/,由 FastAPI 托管,适合继续保持同源部署。 - Web API 默认同源,Axios 使用
withCredentials: true。 - 现有登录依赖 HttpOnly Session Cookie,Cookie 使用
SameSite=Lax;同源 PWA/TWA 可继续复用,Capacitor 跨源访问则需要重新设计 CORS 和移动端认证。 - 页面中仍有多处
100vh布局,需要验证 Android 地址栏、软键盘和安全区。 - Electron 桌面端的“独立运行”来自本地 FastAPI + PyInstaller 后端。Android 无法低成本复用该打包链。
- 后端包含 pandas、numpy、交易日历和多个数据源 SDK;嵌入 APK 会带来原生依赖、多架构、体积、后台执行和密钥安全风险。
方案复杂度
| 方案 | 适用范围 | 粗略工作量 | 复杂度 |
|---|---|---|---|
| 可安装 PWA | Web/自托管/快速验证移动需求 | 3~7 人日 | 低到中 |
| PWA + TWA | 固定官方域名、Google Play 分发 | PWA 后增加 2~5 人日 | 中 |
| Capacitor + 官方服务 | 原生能力、固定后端 | 1~2 周 | 中 |
| Capacitor + 任意自托管服务 | 服务器配置、配对、token、证书管理 | 2~4 周 | 中到高 |
| APK 内置 Python 后端 | 手机离线独立分析 | 2~4 月以上 | 极高,不建议 |
以上是单人熟悉现有 Web/API 代码时的粗略估算,不包含商店审核等待时间。
期望实现 / Proposed Solution
Phase 1:先落地 PWA
- 增加
manifest.webmanifest,配置名称、主题色、显示模式、scope、start URL。 - 增加 192/512 图标和 maskable 图标,替换当前默认 Vite 图标和标题。
- 增加 Service Worker;只缓存 UI 静态资源和离线提示,不缓存分析结果、配置、会话和其他敏感 API 响应。
- 增加安装提示、版本更新提示和失败回退。
- 处理 Android 软键盘、返回导航、下载/上传、外部链接和网络恢复。
- 审核
100vh,按需迁移为100dvh并处理 safe-area。 - 在 HTTPS 同源部署下验证登录、退出和 Session Cookie。
- 补充 PWA 使用、部署与故障排查文档。
- 更新
docs/CHANGELOG.md。 - 如改变页面视觉或安装交互,在 PR 描述附 Android 真机截图,不把一次性验收截图提交进仓库。
Phase 1 非目标:
- 不提供业务数据离线分析。
- 不实现 Android 原生推送。
- 不引入新的移动端认证协议。
- 不打包 Python/FastAPI 后端。
- 不承诺 Google Play 上架。
Phase 2:按条件选择 TWA
仅在以下条件满足后进入:
- 已有稳定的官方 HTTPS 域名和可用性保障。
- PWA 真机验收通过并有明确的商店分发需求。
- 隐私政策、Data Safety、账号删除/数据删除路径和金融功能声明已评估。
- 签名密钥和发布责任人已明确。
实现范围:
- 在
apps/dsa-android/建立 TWA/Bubblewrap 工程。 - 配置包名、版本、图标、启动行为和 Android Target SDK。
- 在官网发布
.well-known/assetlinks.json,同时验证本地签名和 Play App Signing 指纹。 - 构建测试 APK 和商店用签名 AAB。
- 增加 Android 构建/发布工作流,签名材料只通过 GitHub Secrets 注入。
- 准备商店描述、截图、隐私政策及必要声明。
Phase 3:仅在需要原生能力时评估 Capacitor
进入条件建议为:至少存在一个 PWA/TWA 无法可靠满足的核心能力,例如原生推送、系统分享、扫码配对、生物识别或受控文件访问。
在开始前必须先收敛:
- 固定官方后端还是允许连接任意自托管后端。
- 运行时 API 地址及 HTTPS/证书策略。
- 移动端 token/配对认证、Android Keystore、安全退出和设备吊销。
- CORS 白名单,不使用允许全部来源代替正式认证设计。
- Android 返回键、深链、下载、网络恢复和应用生命周期契约。
- Web、Desktop 与 Android 的认证/API 兼容策略。
Phase 1 验收标准
- Android Chrome 可识别为可安装应用,并能从桌面以 standalone 模式启动。
- 首次加载、安装、升级、退出登录和重新登录行为正确。
- 无网络时明确显示离线状态,不展示过期行情或分析结果冒充实时数据。
- Service Worker 更新不会使用户长期停留在旧 JS/API 契约。
- 首页、聊天、持仓、决策信号、筛选、回测、预警、设置等关键页面在真机可操作。
- 软键盘弹出、横竖屏切换、返回键、长报告滚动、文件上传/下载无阻断问题。
-
cd apps/dsa-web && npm run lint && npm run test && npm run build通过。 - 运行受影响的 Playwright smoke;真机验收结果记录在 PR 描述或 Actions artifact。
风险与边界
- Service Worker 不得缓存鉴权响应、用户配置、报告数据或股票实时接口。
- 自托管用户若使用明文 HTTP、无效证书或直接暴露局域网端口,不应被移动客户端静默绕过安全检查。
- TWA 绑定具体域名,不适合直接作为连接任意自托管服务器的通用客户端。
- Capacitor “生成 Android 工程”本身不难,真正工作量主要来自跨源认证和自托管服务器信任模型。
- 股票分析应用进入 Google Play 时,需要单独评估金融功能分类、免责声明、隐私和数据处理声明。
- 当前项目仅供学习研究、不构成投资建议的边界应继续在移动端用户可见位置保留。
备选方案 / Alternatives Considered
- 保持当前响应式 Web:成本最低,但缺少安装、更新、离线壳和应用化体验。
- 直接 TWA:需要先具备合格 PWA 和固定官方域名,不适合作为第一步。
- 直接 Capacitor:可扩展原生能力,但会提前引入 Android 工程、认证和发布维护面。
- Flutter/React Native 重写:重复实现现有 React UI、API 类型和测试,当前收益不足。
- Android 内置 Python 后端:重依赖、SDK、多架构及后台运行风险过高,暂不采用。
相关信息 / Additional Context
- PWA 安装与 Manifest:
- Trusted Web Activity:
- Capacitor Android:
- Google Play Target API:
- Google Play Data Safety:
- Google Play Financial Features:
分析基线:
已执行
git fetch --all --prune。使用最新
origin/main@831ada53分析。本地工作树位于
2d1545b2;当前功能分支相对其远端 ahead 1 / behind 24,无法 fast-forward,因此未执行 pull、切分支、stash、reset 或覆盖本地提交。是否愿意贡献代码实现 / Willing to implement: 待确认
Source: ZhuLinsen/daily_stock_analysis