10 KiB
10 KiB
俱乐部信息自动刷新 v2.1.2
📅 更新时间
2025-10-12 23:15
🎯 问题描述
现象
进入"游戏功能"页面后,俱乐部信息不会自动刷新,需要手动点击"刷新"按钮才能加载数据。
原因分析
ClubInfo.vue 组件缺少自动刷新逻辑:
- ❌ 没有在
onMounted时调用refreshClub() - ❌ 没有检查 WebSocket 连接状态
- ❌ 没有处理异步初始化时序问题
✅ 解决方案
实现逻辑
参考月度任务的成功实现,采用相同的自动刷新机制:
-
延迟启动(500ms)
- 等待组件完全挂载
- 避免过早调用导致失败
-
轮询检查 WebSocket 状态(每秒一次)
- 检查
selectedToken是否存在 - 检查 WebSocket 连接状态是否为
connected - 最多检查 10 次(10 秒超时)
- 检查
-
连接成功后自动刷新
- 延迟 1 秒执行
refreshClub() - 设置
clubInfoFetched标志,防止重复刷新
- 延迟 1 秒执行
-
Token 切换监听
- 监听
selectedToken变化 - 切换 Token 时重置
clubInfoFetched标志
- 监听
🔧 代码实现
新增导入
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
新增状态
const clubInfoFetched = ref(false)
let wsCheckInterval = null
let checkCount = 0
const maxCheckCount = 10
onMounted 生命周期
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 清理
onUnmounted(() => {
console.log('🏛️ [俱乐部] ClubInfo 组件卸载,清理定时器')
if (wsCheckInterval) {
clearInterval(wsCheckInterval)
}
})
Token 切换监听
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/10,WebSocket 状态: connecting
🏛️ [俱乐部] 检查 2/10,WebSocket 状态: connecting
🏛️ [俱乐部] 检查 3/10,WebSocket 状态: connected
🏛️ [俱乐部] WebSocket 已连接,准备自动刷新
🏛️ [俱乐部] 执行自动刷新
📤 发送消息: legion_getinfo {}
📥 收到响应: legion_getinforesp { info: {...} }
🏛️ 军团信息已更新: { hasInfo: true, clubName: "xxx俱乐部", memberCount: 30 }
🏛️ [俱乐部] 已成功获取数据,停止检查
Token 未选中
🏛️ [俱乐部] ClubInfo 组件已挂载
🏛️ [俱乐部] 检查 1/10,Token 未选中,继续等待...
🏛️ [俱乐部] 检查 2/10,Token 未选中,继续等待...
🏛️ [俱乐部] 检查 3/10,Token 未选中,继续等待...
...
🏛️ [俱乐部] 超过最大检查次数,停止自动刷新
WebSocket 连接失败
🏛️ [俱乐部] ClubInfo 组件已挂载
🏛️ [俱乐部] 检查 1/10,WebSocket 状态: connecting
🏛️ [俱乐部] 检查 2/10,WebSocket 状态: connecting
🏛️ [俱乐部] 检查 3/10,WebSocket 状态: error
🏛️ [俱乐部] 检查 4/10,WebSocket 状态: 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
变更内容
- ✅ 新增
onMounted、onUnmounted、watch导入 - ✅ 新增
clubInfoFetched状态标志 - ✅ 实现 WebSocket 状态轮询检查
- ✅ 实现自动刷新逻辑
- ✅ 实现定时器清理
- ✅ 实现 Token 切换监听
🧪 测试验证
测试用例1:正常自动刷新
前置条件:
- Token 已选中
- WebSocket 已连接
操作步骤:
- 进入"游戏功能"页面
- 等待 2-3 秒
预期结果:
- ✅ 俱乐部信息自动加载
- ✅ 显示俱乐部名称、成员数等信息
- ✅ 控制台输出自动刷新日志
测试用例2:Token 未选中
前置条件:
- 未选中任何 Token
操作步骤:
- 进入"游戏功能"页面
- 等待 10 秒
预期结果:
- ✅ 显示"暂无俱乐部"空状态
- ✅ 控制台提示"Token 未选中"
- ✅ 10 秒后停止检查
测试用例3:WebSocket 连接中
前置条件:
- Token 已选中
- WebSocket 正在连接中
操作步骤:
- 进入"游戏功能"页面
- 观察自动刷新过程
预期结果:
- ✅ 持续检查 WebSocket 状态
- ✅ 连接成功后自动刷新
- ✅ 俱乐部信息正确显示
测试用例4:Token 切换
前置条件:
- 已有多个 Token
操作步骤:
- 进入"游戏功能"页面
- 等待俱乐部信息加载完成
- 切换到另一个 Token
预期结果:
- ✅
clubInfoFetched标志重置 - ✅ 允许下次进入页面时重新自动刷新
测试用例5:快速切换页面
操作步骤:
- 进入"游戏功能"页面
- 立即切换到其他页面
预期结果:
- ✅ 组件卸载,定时器被清理
- ✅ 无内存泄漏
- ✅ 无错误日志
💡 使用说明
自动刷新
- 确保已选中 Token
- 进入"游戏功能"页面
- 等待 2-3 秒,俱乐部信息自动加载
手动刷新
- 点击右上角"刷新"按钮
- 立即重新获取俱乐部信息
查看调试日志
打开浏览器控制台,查看以 🏛️ [俱乐部] 开头的日志
🔮 后续优化方向
1. 统一自动刷新机制(P1)
目前月度任务和俱乐部信息都使用相似的逻辑,可以抽取为公共 composable:
// 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
状态:✅ 完成并可测试
🎊 现在刷新页面,进入游戏功能,俱乐部信息应该自动加载了! 🚀