252 lines
7.4 KiB
Markdown
252 lines
7.4 KiB
Markdown
|
|
# TaskId 丢失问题 - 调试指南
|
|||
|
|
|
|||
|
|
## 问题症状
|
|||
|
|
|
|||
|
|
- 打开编辑窗口后,taskId 为空或 undefined
|
|||
|
|
- 控制台显示 "5秒内未收到数据,显示空界面"
|
|||
|
|
- 编辑窗口的表单数据为空
|
|||
|
|
|
|||
|
|
## 最新修复方案(2025-10-14)
|
|||
|
|
|
|||
|
|
### 核心问题:窗口通信时序问题
|
|||
|
|
|
|||
|
|
1. **问题**:父窗口创建子窗口后才开始监听 ready 事件,导致错过子窗口的就绪通知
|
|||
|
|
2. **解决**:父窗口在创建子窗口**之前**就开始监听 ready 事件
|
|||
|
|
|
|||
|
|
### 通信流程
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
父窗口 子窗口
|
|||
|
|
| |
|
|||
|
|
|-- 1. 开始监听 ready 事件 |
|
|||
|
|
| (BEFORE creating window) |
|
|||
|
|
| |
|
|||
|
|
|-- 2. 创建窗口 ------------------> |
|
|||
|
|
| |
|
|||
|
|
| |-- 3. 窗口创建 (tauri://created)
|
|||
|
|
| |
|
|||
|
|
| |-- 4. Vue 组件 mounted
|
|||
|
|
| |
|
|||
|
|
| |-- 5. 设置事件监听器
|
|||
|
|
| |
|
|||
|
|
| |-- 6. 发送 ready 通知
|
|||
|
|
| | emit('xxx-ready')
|
|||
|
|
| |
|
|||
|
|
|<-- 7. 收到 ready 通知 -------------|
|
|||
|
|
| |
|
|||
|
|
|-- 8. 发送初始化数据 -------------> |
|
|||
|
|
| emit('init-task-edit-xxx') |
|
|||
|
|
| |
|
|||
|
|
| |<-- 9. 收到数据
|
|||
|
|
| |
|
|||
|
|
| |-- 10. 填充表单
|
|||
|
|
| |
|
|||
|
|
| |-- 11. 显示界面
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 备用超时机制
|
|||
|
|
|
|||
|
|
如果 2 秒内没收到 ready 通知(可能是通信失败),父窗口会直接发送数据:
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
setTimeout(async () => {
|
|||
|
|
if (!readySent) {
|
|||
|
|
console.log('⏰ 超时备用发送机制触发')
|
|||
|
|
readySent = true
|
|||
|
|
await sendInitData()
|
|||
|
|
}
|
|||
|
|
}, 2000)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 调试步骤
|
|||
|
|
|
|||
|
|
### 1. 打开浏览器控制台
|
|||
|
|
|
|||
|
|
在应用中打开开发者工具(F12 或 Ctrl+Shift+I)
|
|||
|
|
|
|||
|
|
### 2. 清空控制台
|
|||
|
|
|
|||
|
|
点击控制台左上角的清空按钮(🚫)
|
|||
|
|
|
|||
|
|
### 3. 触发编辑操作
|
|||
|
|
|
|||
|
|
点击列表中某一行的"编辑"按钮
|
|||
|
|
|
|||
|
|
### 4. 观察日志输出
|
|||
|
|
|
|||
|
|
#### 正常流程应该看到的日志:
|
|||
|
|
|
|||
|
|
**父窗口(AI Index):**
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
============ AI Index 创建编辑窗口 ============
|
|||
|
|
创建的窗口标签 (windowLabel): task-edit-ai-1728912345678
|
|||
|
|
将要发送的事件名 (eventName): init-task-edit-task-edit-ai-1728912345678
|
|||
|
|
等待就绪事件名 (readyEventName): task-edit-ai-1728912345678-ready
|
|||
|
|
传递的 taskData: {taskId: "123", taskName: "测试任务", ...}
|
|||
|
|
taskData.taskId: 123
|
|||
|
|
[task-edit-ai-1728912345678] 🎧 开始监听就绪事件: task-edit-ai-1728912345678-ready
|
|||
|
|
[task-edit-ai-1728912345678] ✅ 窗口已创建
|
|||
|
|
[task-edit-ai-1728912345678] 📢 收到子窗口就绪通知: {windowLabel: "task-edit-ai-1728912345678", ...}
|
|||
|
|
[task-edit-ai-1728912345678] 📤 发送事件: init-task-edit-task-edit-ai-1728912345678
|
|||
|
|
[task-edit-ai-1728912345678] 📦 payload.data.taskId: 123
|
|||
|
|
[task-edit-ai-1728912345678] ✅ 事件发送成功!
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**子窗口(Task Edit Window):**
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
============ AI Task Edit Window onMounted ============
|
|||
|
|
当前窗口标签 (windowLabel): task-edit-ai-1728912345678
|
|||
|
|
初始 form 数据: {taskId: "", ...}
|
|||
|
|
将要监听的事件名: init-task-edit-task-edit-ai-1728912345678
|
|||
|
|
[task-edit-ai-1728912345678] ai - ✅ 事件监听器已设置成功
|
|||
|
|
[task-edit-ai-1728912345678] ai - 📢 已发送就绪通知: task-edit-ai-1728912345678-ready
|
|||
|
|
[task-edit-ai-1728912345678] ai - ✅ 收到事件!event.payload: {type: "edit", data: {...}}
|
|||
|
|
[task-edit-ai-1728912345678] ai - 接收到的数据: {taskId: "123", ...}
|
|||
|
|
[task-edit-ai-1728912345678] ai - data.taskId: 123
|
|||
|
|
[task-edit-ai-1728912345678] ai - assignFields 调用后 form: {taskId: "123", ...}
|
|||
|
|
[task-edit-ai-1728912345678] ai - 赋值后 form.taskId: 123
|
|||
|
|
[task-edit-ai-1728912345678] ai - incomingId: 123
|
|||
|
|
[task-edit-ai-1728912345678] ai - resolvedId: 123
|
|||
|
|
[task-edit-ai-1728912345678] ai - 已保存到 localStorage, taskId: 123
|
|||
|
|
[task-edit-ai-1728912345678] ai - nextTick 后 form.taskId: 123
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5. 常见问题诊断
|
|||
|
|
|
|||
|
|
#### 问题 A:子窗口超时
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
[task-edit-ai-xxx] ai - ⚠️ 5秒内未收到数据,显示空界面
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**可能原因:**
|
|||
|
|
|
|||
|
|
1. 窗口标签不匹配
|
|||
|
|
2. 事件名称拼写错误
|
|||
|
|
3. 父窗口发送数据失败
|
|||
|
|
|
|||
|
|
**检查:**
|
|||
|
|
|
|||
|
|
- 确认父窗口和子窗口的 windowLabel 是否一致
|
|||
|
|
- 确认事件名称是否正确(`init-task-edit-${windowLabel}`)
|
|||
|
|
|
|||
|
|
#### 问题 B:父窗口超时发送
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
[task-edit-ai-xxx] ⏰ 超时备用发送机制触发
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**可能原因:**
|
|||
|
|
|
|||
|
|
1. 子窗口 ready 事件发送失败
|
|||
|
|
2. 父窗口监听器设置失败
|
|||
|
|
3. 子窗口加载太慢
|
|||
|
|
|
|||
|
|
**检查:**
|
|||
|
|
|
|||
|
|
- 查看子窗口是否发送了 ready 通知
|
|||
|
|
- 查看网络是否正常(子窗口资源加载)
|
|||
|
|
|
|||
|
|
#### 问题 C:taskId 为空字符串
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
[task-edit-ai-xxx] ai - data.taskId: undefined
|
|||
|
|
[task-edit-ai-xxx] ai - incomingId: undefined
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**可能原因:**
|
|||
|
|
|
|||
|
|
1. 父窗口传递的数据本身就没有 taskId
|
|||
|
|
2. 字段名不匹配(可能是 taskid 或 id)
|
|||
|
|
|
|||
|
|
**检查:**
|
|||
|
|
|
|||
|
|
- 查看父窗口日志中的 `payload.data.taskId`
|
|||
|
|
- 查看父窗口日志中的 `taskData`
|
|||
|
|
|
|||
|
|
#### 问题 D:重复发送数据
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
[task-edit-ai-xxx] ⚠️ 已经发送过数据,忽略重复通知
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**原因:**
|
|||
|
|
|
|||
|
|
- 正常现象,防止重复发送的保护机制生效
|
|||
|
|
|
|||
|
|
## 检查 localStorage
|
|||
|
|
|
|||
|
|
打开浏览器控制台,输入:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
// 查看当前存储的 taskId
|
|||
|
|
localStorage.getItem('taskId')
|
|||
|
|
|
|||
|
|
// 清空 taskId
|
|||
|
|
localStorage.removeItem('taskId')
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 检查事件监听器
|
|||
|
|
|
|||
|
|
在子窗口控制台输入:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
// 查看当前窗口标签
|
|||
|
|
await window.__TAURI__.window.getCurrent().label
|
|||
|
|
|
|||
|
|
// 手动发送就绪通知测试
|
|||
|
|
await window.__TAURI__.event.emit('task-edit-ai-xxx-ready', { test: true })
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 修复建议
|
|||
|
|
|
|||
|
|
### 如果问题仍然存在
|
|||
|
|
|
|||
|
|
1. **增加延迟**:将超时时间从 2 秒增加到 3 秒
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
}, 3000) // 从 2000 改为 3000
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
2. **直接发送(临时方案)**:在 `tauri://created` 事件中直接发送数据
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
webview.once('tauri://created', async () => {
|
|||
|
|
await new Promise((resolve) => setTimeout(resolve, 1000))
|
|||
|
|
await sendInitData()
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
3. **使用全局事件总线**:不依赖窗口标签,使用固定的事件名
|
|||
|
|
```typescript
|
|||
|
|
// 使用固定的事件名 + taskId
|
|||
|
|
const eventName = `init-task-edit-${taskData.taskId}`
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 测试清单
|
|||
|
|
|
|||
|
|
- [ ] 从列表打开编辑窗口,taskId 正确显示
|
|||
|
|
- [ ] 关闭窗口后重新打开,taskId 正确显示
|
|||
|
|
- [ ] 网络慢时打开,超时机制正常工作
|
|||
|
|
- [ ] 快速连续打开多个编辑窗口,互不干扰
|
|||
|
|
- [ ] 编辑窗口刷新后,taskId 从 localStorage 恢复
|
|||
|
|
- [ ] 关闭窗口后,localStorage 正确清理
|
|||
|
|
|
|||
|
|
## 性能优化建议
|
|||
|
|
|
|||
|
|
1. **缓存窗口**:不要每次都创建新窗口,复用已有窗口
|
|||
|
|
2. **预加载**:提前创建隐藏窗口,需要时直接显示
|
|||
|
|
3. **批量操作**:如果需要打开多个窗口,使用队列机制
|
|||
|
|
|
|||
|
|
## 联系与反馈
|
|||
|
|
|
|||
|
|
如果问题仍未解决,请收集以下信息:
|
|||
|
|
|
|||
|
|
1. 完整的控制台日志(父窗口 + 子窗口)
|
|||
|
|
2. localStorage 内容快照
|
|||
|
|
3. 网络请求记录(Network 面板)
|
|||
|
|
4. Tauri 版本号
|
|||
|
|
5. 操作系统版本
|