Files
app_03_pregnancy/docs/miniprogram-fix-plan.md

119 lines
3.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 小程序 web-view Token 传递问题分析与修复方案
---
## 一、问题现象
H5 页面一直显示"正在获取登录信息...",无法正常加载首页。
## 二、排查过程
### 2.1 小程序端日志 ✅
```
[web_view] 原始URL: ✅ https://mp.yizhezhe.com/app_03/?token=eyJ0eX...
[web_view] 最终传给 web-view 的 URL: ✅ https://mp.yizhezhe.com/app_03/?token=eyJ0eX...
[web_view] token: ✅ eyJ0eXAiOiJ...
[web_view] JWT payload: { ✅ 解码正常
"uid": 7, "phone": "13693687880", "openid": "oauWC1zc7..."
}
```
### 2.2 H5 端日志 ❌
```
initialUrl: https://mp.yizhezhe.com/app_03/ ← 无 token
url: https://mp.yizhezhe.com/app_03/ ← 无 token
hasTokenParam: false ← URL 无 token 参数
search: [] ← query string 为空
step: wx-postMessage-done
```
### 2.3 根因定位
**Nginx 配置**(之前排查过一次已修复)、**小程序代码**、**URL 拼接逻辑** 都没有问题。
问题出在 **微信 web-view 组件的内部机制**:当 uni-app 在 `onLoad` 中动态设置 `<web-view>` 的 `src` 属性时,微信内部加载 web-view 的**首次页面请求会丢弃 query string(`?token=xxx`)**,导致 H5 收到的 URL 不带 token。
这是微信 web-view 的已知行为,跟 Nginx 无关,跟小程序代码逻辑也无关。
---
## 三、修复方案
### 3.1 方案:用 hash(`#token=xxx`)替代 query(`?token=xxx`)
微信 web-view 在 URL 重定向/动态设 src 时,**hash 片段是唯一 100% 不被丢弃的部分**。
### 3.2 小程序端改动(uni-app)
改一个文件(`index.vue` 或 web-view 所在页面),构造 URL 时把 `?` 改为 `#`:
```javascript
// ─── 改前(query) ───
const base = 'https://mp.yizhezhe.com/app_03/';
const url = base + '?token=' + encodeURIComponent(token);
// 最终: https://mp.yizhezhe.com/app_03/?token=eyJ0eX...
// ↑ 被微信 web-view 丢弃
// ─── 改后(hash) ───
const base = 'https://mp.yizhezhe.com/app_03/';
const url = base + '#token=' + encodeURIComponent(token);
// 最终: https://mp.yizhezhe.com/app_03/#token=eyJ0eX...
// ↑ 微信任何场景都不丢 hash
```
### 3.3 H5 端改动(已部署)
H5 的 `LoginPage.tsx` 已更新,读取 token 的逻辑改为:
```typescript
// 1. 优先从 query 读(兼容开发环境和直接 URL 访问)
const params = new URLSearchParams(window.location.search);
let token = params.get('token');
// 2. query 没有则从 hash 读(微信 web-view 场景)
if (!token) {
const hash = window.location.hash;
if (hash.startsWith('#token=')) {
token = decodeURIComponent(hash.replace('#token=', ''));
}
}
// 3. 后续解码逻辑不变...
```
**不需要额外操作,部署后直接生效。**
### 3.4 改动量
| 端 | 改几个文件 | 改几行 |
|----|----------|--------|
| 小程序 | 1 个文件(web-view 页面) | 1 行(`?` → `#`) |
| H5 | 已部署,无需再改 | 0 |
---
## 四、验证步骤
1. 小程序端改 `?` 为 `#`
2. 重新编译小程序
3. 点击进入 web-view
4. H5 顶部 Debug 面板的 `step` 应该显示 `token-from-hash`,然后跳到 decode-ok → fetch-ok → 跳首页
5. 确认无误后 H5 端可清理 DebugPanel 代码
---
## 五、补充说明
### 为什么不用其他方案?
| 方案 | 问题 |
|------|------|
| `postMessage` 双向通信 | 小程序 → H5 没有直接 API,只能通过 URL 变化 |
| 在 web-view 初始化前等 token | 同当前方案,需前端额外处理竞态 |
| `wx.miniProgram.navigateTo` 重定向 | 会造成页面闪烁,且 query 同样可能丢失 |
| `evalJavascript` | 各版本兼容性不一致 |
**hash 方案改动最小、最可靠。**