Files
pengcheng-exam-teacher/TASKID_FIX_SUMMARY.md
2025-10-20 15:37:28 +08:00

193 lines
5.0 KiB
Markdown
Raw 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.

# TaskId 丢失问题修复说明
## 问题描述
在 Tauri 两个独立窗口之间通信时,容易出现 taskId 丢失的情况,导致编辑窗口中的 taskId 为空,影响后续操作。
## 根本原因
1. **缺少数据持久化**窗口之间传递数据时如果事件丢失或延迟taskId 会丢失
2. **缺少数据准备状态控制**:组件在数据未到达时就开始渲染,导致 taskId 为空
3. **缺少兜底机制**没有处理不同字段名taskId/taskid/id的情况
4. **缺少超时机制**:如果事件一直没收到,窗口会一直处于等待状态
## 修复方案
### 1. 引入 taskStorage 模块
使用 localStorage 持久化存储 taskId确保数据不会因窗口通信失败而丢失
```typescript
import {
setTaskId,
bindBeforeUnloadClear,
clearTaskId,
unbindBeforeUnloadClear,
getTaskId
} from '../../../taskStorage'
```
### 2. 添加数据准备状态控制
添加 `isDataReady` 状态,在数据未准备好之前显示加载界面:
```typescript
const isDataReady = ref(false)
```
```vue
<div v-if="!isDataReady" class="loading-overlay">
<el-empty description="正在加载数据..." />
</div>
```
### 3. 添加超时机制
如果 5 秒内没有收到数据,也显示界面(避免永久等待):
```typescript
const timeout = setTimeout(() => {
console.warn(`5秒内未收到数据显示空界面`)
isDataReady.value = true
}, 5000)
```
### 4. 规范化和兜底 taskId
支持多种字段名,并使用 localStorage 作为兜底:
```typescript
// 规范化并兜底 taskId支持 taskid/id最后再持久化
const incomingId = data?.taskId ?? data?.taskid ?? data?.id
const resolvedId = (incomingId ?? getTaskId() ?? '').toString()
if (!form.taskId && resolvedId) {
form.taskId = resolvedId
}
if (form.taskId) setTaskId(form.taskId)
```
### 5. 清理机制
在窗口关闭或组件卸载时清理 taskId
```typescript
const handleCancel = async () => {
clearTaskId() // 主动关闭时清空 taskId
await emit('task-edit-closed')
await getCurrentWindow().close()
}
onUnmounted(() => {
clearTaskId()
unbindBeforeUnloadClear()
})
```
## 修复文件列表
1.`src/views/task/selftrans/ai/components/task-edit-window.vue`
2.`src/views/task/selftrans/random/components/task-edit-window.vue`
3.`src/views/task/selftrans/module/components/task-edit-window.vue`
4.`src/views/task/selftrans/collegeexam/components/task-edit-window.vue`
## 已存在的正确实现参考
- `src/views/task/exam/components/task-edit-window.vue` - 已经包含完整的 taskId 持久化机制
## 关键改进点
### 前置
```typescript
// ❌ 旧代码
let unlistenFunc: (() => void) | null = null
// ✅ 新代码
const isDataReady = ref(false)
let unlistenFunc: any = null
```
### 事件监听
```typescript
// ❌ 旧代码
unlistenFunc = await listen(eventName, (event: any) => {
const { data } = event.payload || {}
if (data) {
assignFields(data)
activeStep.value = 0
}
})
// ✅ 新代码
const timeout = setTimeout(() => {
isDataReady.value = true
}, 5000)
unlistenFunc = await listen(eventName, (event: any) => {
clearTimeout(timeout)
const { data } = event.payload || {}
if (data) {
isDataReady.value = false
assignFields(data)
// 规范化和兜底
const incomingId = data?.taskId ?? data?.taskid ?? data?.id
const resolvedId = (incomingId ?? getTaskId() ?? '').toString()
if (!form.taskId && resolvedId) {
form.taskId = resolvedId
}
if (form.taskId) setTaskId(form.taskId)
isDataReady.value = true
activeStep.value = 0
}
})
```
### 清理
```typescript
// ❌ 旧代码
onUnmounted(() => {
if (unlistenFunc) {
unlistenFunc()
}
})
// ✅ 新代码
onUnmounted(() => {
if (unlistenFunc) {
unlistenFunc()
unlistenFunc = null
}
clearTaskId()
unbindBeforeUnloadClear()
})
```
## 测试建议
1. **正常流程测试**:从列表页打开编辑窗口,检查 taskId 是否正确传递
2. **延迟测试**:模拟网络延迟,检查超时机制是否正常工作
3. **重复打开测试**:多次打开和关闭编辑窗口,检查是否有 taskId 残留
4. **跨步骤测试**:在编辑窗口的不同步骤间切换,检查 taskId 是否始终存在
5. **刷新测试**:在编辑窗口中刷新页面,检查 taskId 是否能从 localStorage 恢复
## 注意事项
1. **TypeScript 编译错误是正常的**在文件保存后TypeScript 会重新编译,导入的函数会被识别为已使用
2. **bindBeforeUnloadClear 暂未使用**:这个函数在某些场景下可能需要,暂时保留导入
3. **不同模块的路径**:注意 `taskStorage` 的导入路径根据文件位置可能不同(`../../../taskStorage`
## 预期效果
修复后taskId 将更加稳定:
- ✅ 窗口通信失败时有 localStorage 兜底
- ✅ 数据加载时显示友好的加载界面
- ✅ 支持多种字段名格式
- ✅ 超时后不会永久卡住
- ✅ 窗口关闭后正确清理数据