Files
xyzw_web_helper/MD说明文件夹/俱乐部信息自动刷新v2.1.2.md

426 lines
10 KiB
Markdown
Raw Normal View History

2025-10-17 20:56:50 +08:00
# 俱乐部信息自动刷新 v2.1.2
## 📅 更新时间
2025-10-12 23:15
## 🎯 问题描述
### 现象
进入"游戏功能"页面后,俱乐部信息不会自动刷新,需要手动点击"刷新"按钮才能加载数据。
### 原因分析
`ClubInfo.vue` 组件缺少自动刷新逻辑:
- ❌ 没有在 `onMounted` 时调用 `refreshClub()`
- ❌ 没有检查 WebSocket 连接状态
- ❌ 没有处理异步初始化时序问题
---
## ✅ 解决方案
### 实现逻辑
参考月度任务的成功实现,采用相同的自动刷新机制:
1. **延迟启动**500ms
- 等待组件完全挂载
- 避免过早调用导致失败
2. **轮询检查 WebSocket 状态**(每秒一次)
- 检查 `selectedToken` 是否存在
- 检查 WebSocket 连接状态是否为 `connected`
- 最多检查 10 次10 秒超时)
3. **连接成功后自动刷新**
- 延迟 1 秒执行 `refreshClub()`
- 设置 `clubInfoFetched` 标志,防止重复刷新
4. **Token 切换监听**
- 监听 `selectedToken` 变化
- 切换 Token 时重置 `clubInfoFetched` 标志
---
## 🔧 代码实现
### 新增导入
```javascript
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
```
### 新增状态
```javascript
const clubInfoFetched = ref(false)
let wsCheckInterval = null
let checkCount = 0
const maxCheckCount = 10
```
### onMounted 生命周期
```javascript
onMounted(() => {
console.log('🏛️ [俱乐部] ClubInfo 组件已挂载')
// 延迟 500ms 后开始检查 WebSocket 连接状态
setTimeout(() => {
wsCheckInterval = setInterval(() => {
checkCount++
if (clubInfoFetched.value) {
console.log('🏛️ [俱乐部] 已成功获取数据,停止检查')
clearInterval(wsCheckInterval)
return
}
if (checkCount > maxCheckCount) {
console.warn('🏛️ [俱乐部] 超过最大检查次数,停止自动刷新')
clearInterval(wsCheckInterval)
return
}
const token = tokenStore.selectedToken
if (!token) {
console.log('🏛️ [俱乐部] Token 未选中,继续等待...')
return
}
const status = tokenStore.getWebSocketStatus(token.id)
console.log(`🏛️ [俱乐部] 检查 ${checkCount}/${maxCheckCount}WebSocket 状态: ${status}`)
if (status === 'connected') {
console.log('🏛️ [俱乐部] WebSocket 已连接,准备自动刷新')
// 连接成功后延迟 1 秒刷新,确保组件完全初始化
setTimeout(() => {
console.log('🏛️ [俱乐部] 执行自动刷新')
refreshClub()
clubInfoFetched.value = true
}, 1000)
clearInterval(wsCheckInterval)
}
}, 1000) // 每秒检查一次
}, 500)
})
```
### onUnmounted 清理
```javascript
onUnmounted(() => {
console.log('🏛️ [俱乐部] ClubInfo 组件卸载,清理定时器')
if (wsCheckInterval) {
clearInterval(wsCheckInterval)
}
})
```
### Token 切换监听
```javascript
watch(() => tokenStore.selectedToken, (newToken, oldToken) => {
if (newToken?.id !== oldToken?.id) {
console.log('🏛️ [俱乐部] Token 切换,重置状态')
clubInfoFetched.value = false
}
})
```
---
## 🔍 工作流程
### 时序图
```
用户进入页面
组件 onMounted (延迟 500ms)
开始轮询检查 (每秒一次)
检查 Token 是否存在? ───No──→ 继续等待
↓ Yes
检查 WebSocket 状态?
↓ connected
延迟 1 秒执行刷新
调用 refreshClub()
发送 legion_getinfo 命令
接收 legion_getinforesp 响应
更新 gameData.legionInfo
UI 自动刷新computed 响应式)
设置 clubInfoFetched = true
停止轮询
```
---
## 📊 调试日志示例
### 正常流程
```
🏛️ [俱乐部] ClubInfo 组件已挂载
🏛️ [俱乐部] 检查 1/10WebSocket 状态: connecting
🏛️ [俱乐部] 检查 2/10WebSocket 状态: connecting
🏛️ [俱乐部] 检查 3/10WebSocket 状态: connected
🏛️ [俱乐部] WebSocket 已连接,准备自动刷新
🏛️ [俱乐部] 执行自动刷新
📤 发送消息: legion_getinfo {}
📥 收到响应: legion_getinforesp { info: {...} }
🏛️ 军团信息已更新: { hasInfo: true, clubName: "xxx俱乐部", memberCount: 30 }
🏛️ [俱乐部] 已成功获取数据,停止检查
```
### Token 未选中
```
🏛️ [俱乐部] ClubInfo 组件已挂载
🏛️ [俱乐部] 检查 1/10Token 未选中,继续等待...
🏛️ [俱乐部] 检查 2/10Token 未选中,继续等待...
🏛️ [俱乐部] 检查 3/10Token 未选中,继续等待...
...
🏛️ [俱乐部] 超过最大检查次数,停止自动刷新
```
### WebSocket 连接失败
```
🏛️ [俱乐部] ClubInfo 组件已挂载
🏛️ [俱乐部] 检查 1/10WebSocket 状态: connecting
🏛️ [俱乐部] 检查 2/10WebSocket 状态: connecting
🏛️ [俱乐部] 检查 3/10WebSocket 状态: error
🏛️ [俱乐部] 检查 4/10WebSocket 状态: error
...
🏛️ [俱乐部] 超过最大检查次数,停止自动刷新
```
---
## 🎯 关键参数
| 参数 | 值 | 说明 |
|------|-----|------|
| **初始延迟** | 500ms | 组件挂载后延迟启动检查 |
| **检查间隔** | 1000ms | 每秒检查一次 WebSocket 状态 |
| **最大检查次数** | 10 次 | 超过 10 次后放弃自动刷新 |
| **刷新延迟** | 1000ms | WebSocket 连接后延迟刷新 |
### 总超时时间
```
初始延迟 + (检查间隔 × 最大检查次数) = 500ms + (1000ms × 10) = 10.5s
```
---
## 🆚 与月度任务的对比
### 相同点
- ✅ 采用相同的轮询检查机制
- ✅ 相同的延迟策略500ms + 1000ms
- ✅ 相同的超时保护10 次检查)
- ✅ 相同的状态标志(防止重复刷新)
- ✅ 相同的 Token 切换监听
### 不同点
| 特性 | 月度任务 | 俱乐部信息 |
|------|---------|-----------|
| **标志名称** | `monthTaskFetched` | `clubInfoFetched` |
| **日志前缀** | `[月度任务]` | `[俱乐部]` |
| **刷新函数** | `fetchMonthlyActivity()` | `refreshClub()` |
| **命令名称** | `activity_get` | `legion_getinfo` |
| **响应名称** | `activity_getresp` | `legion_getinforesp` |
---
## 📋 修改文件清单
### 已修改文件1个
**`src/components/ClubInfo.vue`**
#### 变更内容
1. ✅ 新增 `onMounted``onUnmounted``watch` 导入
2. ✅ 新增 `clubInfoFetched` 状态标志
3. ✅ 实现 WebSocket 状态轮询检查
4. ✅ 实现自动刷新逻辑
5. ✅ 实现定时器清理
6. ✅ 实现 Token 切换监听
---
## 🧪 测试验证
### 测试用例1正常自动刷新
**前置条件**
- Token 已选中
- WebSocket 已连接
**操作步骤**
1. 进入"游戏功能"页面
2. 等待 2-3 秒
**预期结果**
- ✅ 俱乐部信息自动加载
- ✅ 显示俱乐部名称、成员数等信息
- ✅ 控制台输出自动刷新日志
### 测试用例2Token 未选中
**前置条件**
- 未选中任何 Token
**操作步骤**
1. 进入"游戏功能"页面
2. 等待 10 秒
**预期结果**
- ✅ 显示"暂无俱乐部"空状态
- ✅ 控制台提示"Token 未选中"
- ✅ 10 秒后停止检查
### 测试用例3WebSocket 连接中
**前置条件**
- Token 已选中
- WebSocket 正在连接中
**操作步骤**
1. 进入"游戏功能"页面
2. 观察自动刷新过程
**预期结果**
- ✅ 持续检查 WebSocket 状态
- ✅ 连接成功后自动刷新
- ✅ 俱乐部信息正确显示
### 测试用例4Token 切换
**前置条件**
- 已有多个 Token
**操作步骤**
1. 进入"游戏功能"页面
2. 等待俱乐部信息加载完成
3. 切换到另一个 Token
**预期结果**
-`clubInfoFetched` 标志重置
- ✅ 允许下次进入页面时重新自动刷新
### 测试用例5快速切换页面
**操作步骤**
1. 进入"游戏功能"页面
2. 立即切换到其他页面
**预期结果**
- ✅ 组件卸载,定时器被清理
- ✅ 无内存泄漏
- ✅ 无错误日志
---
## 💡 使用说明
### 自动刷新
1. 确保已选中 Token
2. 进入"游戏功能"页面
3. 等待 2-3 秒,俱乐部信息自动加载
### 手动刷新
1. 点击右上角"刷新"按钮
2. 立即重新获取俱乐部信息
### 查看调试日志
打开浏览器控制台,查看以 `🏛️ [俱乐部]` 开头的日志
---
## 🔮 后续优化方向
### 1. 统一自动刷新机制P1
目前月度任务和俱乐部信息都使用相似的逻辑,可以抽取为公共 composable
```javascript
// composables/useAutoRefresh.js
export function useAutoRefresh(options) {
const {
refreshFn, // 刷新函数
checkInterval = 1000, // 检查间隔
maxCheckCount = 10, // 最大检查次数
initialDelay = 500, // 初始延迟
refreshDelay = 1000, // 刷新延迟
logPrefix = '自动刷新' // 日志前缀
} = options
// ... 通用逻辑
}
// 使用
const { start, stop } = useAutoRefresh({
refreshFn: refreshClub,
logPrefix: '[俱乐部]'
})
```
### 2. 智能重试机制P2
- [ ] 刷新失败时自动重试
- [ ] 指数退避策略
- [ ] 最大重试次数限制
### 3. 加载状态提示P2
- [ ] 显示"正在加载俱乐部信息..."
- [ ] 显示加载进度
- [ ] 加载失败提示
### 4. 数据缓存P3
- [ ] 缓存俱乐部信息到 localStorage
- [ ] 离线模式下显示缓存数据
- [ ] 定期刷新缓存
---
## 🐛 已知问题
### 问题1重复刷新
**现象**:在某些情况下可能触发多次刷新
**原因**
- `watch` 监听可能触发额外刷新
- 手动点击刷新按钮
**解决方案**
- 使用 `clubInfoFetched` 标志防止重复
- 后续可添加防抖/节流
### 问题2检查次数固定
**现象**:超时时间固定为 10 秒
**影响**
- 网络慢时可能不够
- 网络快时有浪费
**后续优化**
- 根据网络状态动态调整
- 提供用户配置选项
---
## 📈 性能影响
### 资源占用
- **CPU**:极低(每秒一次检查,几乎可忽略)
- **内存**:极低(几个状态变量)
- **网络**1 次俱乐部信息请求
### 优化措施
- ✅ 成功后立即停止轮询
- ✅ 超时后自动停止
- ✅ 组件卸载时清理定时器
- ✅ 使用 `setInterval` 而非递归 `setTimeout`
---
**更新时间**2025-10-12 23:15
**开发人员**Claude Sonnet 4.5
**状态**:✅ 完成并可测试
🎊 **现在刷新页面,进入游戏功能,俱乐部信息应该自动加载了!** 🚀