diff --git a/src/components/DailyTaskStatus.vue b/src/components/DailyTaskStatus.vue index 4c07533..60549fc 100644 --- a/src/components/DailyTaskStatus.vue +++ b/src/components/DailyTaskStatus.vue @@ -12,9 +12,9 @@

当前进度

- +
-
任务详情
- + @@ -89,7 +90,7 @@ 任务设置
- +
@@ -101,7 +102,7 @@ size="small" />
- +
@@ -111,7 +112,7 @@ size="small" />
- +
@@ -121,7 +122,7 @@ size="small" />
- +
@@ -130,35 +131,41 @@ v-model:value="settings.claimBottle" />
- +
领挂机
- +
竞技场
- +
开宝箱
- +
领取邮件奖励
- +
+ 黑市购买物品 + +
+
付费招募 每日任务详情 +
- +
-
- @@ -223,22 +238,23 @@ 任务执行日志
- +
-
{{ logItem.time }} - {{ logItem.message }} @@ -253,12 +269,13 @@ import { ref, reactive, computed, watch, onMounted, onBeforeUnmount, nextTick } from 'vue' import { useTokenStore } from '@/stores/tokenStore' import { useMessage } from 'naive-ui' -import { - Settings, +import { + Settings, Calendar, CheckmarkCircle, EllipseOutline, - DocumentText + DocumentText, + Refresh } from '@vicons/ionicons5' const tokenStore = useTokenStore() @@ -271,7 +288,7 @@ const showLog = ref(false) const busy = ref(false) const logContainer = ref(null) -// 任务设置 - 基于参考代码 +// 任务设置 const settings = reactive({ arenaFormation: 1, bossFormation: 1, @@ -281,10 +298,11 @@ const settings = reactive({ openBox: true, arenaEnable: true, claimHangUp: true, - claimEmail: true + claimEmail: true, + blackMarketPurchase: true }) -// 每日任务列表 - 基于参考代码 +// 每日任务列表 const tasks = ref([ { id: 1, name: '登录一次游戏', completed: false, loading: false }, { id: 2, name: '分享一次游戏', completed: false, loading: false }, @@ -302,7 +320,7 @@ const tasks = ref([ const formationOptions = [1,2,3,4].map(v => ({ label: `阵容${v}`, value: v })) const bossTimesOptions = [0,1,2,3,4].map(v => ({ label: `${v}次`, value: v })) -// 计算属性 - 基于参考代码逻辑 +// 计算属性 const roleInfo = computed(() => { return tokenStore.selectedTokenRoleInfo }) @@ -311,23 +329,29 @@ const roleDailyPoint = computed(() => { return roleInfo.value?.role?.dailyTask?.dailyPoint ?? 0 }) -// 进度 - 基于参考代码 const dailyPoint = computed(() => Math.min(roleDailyPoint.value, 100)) const isFull = computed(() => dailyPoint.value >= 100) const progressColor = computed(() => isFull.value ? '#10b981' : '#3b82f6') -// 日志系统 - 基于参考代码的log函数 +// WebSocket连接状态 +const isConnected = computed(() => { + if (!tokenStore.selectedToken) return false + const status = tokenStore.getWebSocketStatus(tokenStore.selectedToken.id) + return status === 'connected' +}) + +// 日志系统 const logList = ref([]) const LOG_MAX = 500 const log = (message, type = 'info') => { const time = new Date().toLocaleTimeString() logList.value.push({ time, message, type }) - + if (logList.value.length > LOG_MAX) { logList.value.splice(0, logList.value.length - LOG_MAX) } - + nextTick(() => { if (logContainer.value) { logContainer.value.scrollTop = logContainer.value.scrollHeight @@ -335,292 +359,532 @@ const log = (message, type = 'info') => { }) } -// 超时执行器 - 使用tokenStore的sendMessageWithPromise -const callWithRetry = async (fn, opt = {}) => { - const timeoutMs = opt?.timeoutMs ?? 10000 // 降低超时时间到10秒 - const retries = opt?.retries ?? 1 - const delayMs = opt?.delayMs ?? 600 - - for (let attempt = 0; attempt <= retries; attempt++) { - try { - const r = await Promise.race([ - fn(), - new Promise((_, rej) => setTimeout(() => rej(new Error(`请求超时(${timeoutMs}ms)`)), timeoutMs)) - ]) - return r - } catch (err) { - if (attempt === retries) throw err - await new Promise(res => setTimeout(res, delayMs * (attempt + 1))) - } - } - throw new Error('unexpected') -} - -// 消息错误处理 - 基于参考代码的onRaw函数 -const onRaw = (evt) => { - const err = evt?._raw?.error - if (err) log(String(err), 'error') -} - -// 同步服务器任务完成状态 - 基于参考代码的 syncCompleteFromServer 函数 +// 同步服务器任务完成状态 const syncCompleteFromServer = (resp) => { - if (!resp?.role?.dailyTask?.complete) return + if (!resp?.role?.dailyTask?.complete) { + log('角色信息中无任务完成数据', 'warning') + return + } + const complete = resp.role.dailyTask.complete const isDone = (v) => v === -1 - + + log('开始同步任务完成状态...') + log(`服务器返回的任务完成数据: ${JSON.stringify(complete)}`) + + let syncedCount = 0 + let completedCount = 0 + + // 先重置所有任务为未完成,然后根据服务器数据更新 + tasks.value.forEach(task => { + task.completed = false + }) + + // 同步服务器返回的完成状态 Object.keys(complete).forEach(k => { const id = Number(k) const idx = tasks.value.findIndex(t => t.id === id) - if (idx >= 0) tasks.value[idx].completed = isDone(complete[k]) + + if (idx >= 0) { + const isCompleted = isDone(complete[k]) + tasks.value[idx].completed = isCompleted + syncedCount++ + + if (isCompleted) { + completedCount++ + } + + log(`任务${id} "${tasks.value[idx].name}": ${isCompleted ? '已完成' : '未完成'}`, + isCompleted ? 'success' : 'info') + } else { + log(`服务器返回未知任务ID: ${id} (完成值: ${complete[k]})`, 'warning') + } }) + + // 检查本地定义但服务器未返回的任务 + tasks.value.forEach(task => { + if (!(task.id.toString() in complete)) { + log(`本地任务${task.id} "${task.name}" 在服务器数据中缺失`, 'warning') + } + }) + + log(`任务状态同步完成: ${completedCount}/${syncedCount} 已完成`) + log(`当前进度: ${roleDailyPoint.value}/100`) } -// 刷新角色信息 - 使用tokenStore的方法 +// 刷新角色信息 const refreshRoleInfo = async () => { if (!tokenStore.selectedToken) { throw new Error('没有选中的Token') } + const tokenId = tokenStore.selectedToken.id - + log('正在获取角色信息...') + try { - // 直接使用sendMessageWithPromise方法 - log('正在获取角色信息...') - - // 先检查tokenStore方法是否存在 - if (typeof tokenStore.sendMessageWithPromise !== 'function') { - throw new Error('sendMessageWithPromise方法不存在') - } - - const response = await tokenStore.sendMessageWithPromise(tokenId, 'role_getroleinfo', {}, 8000) + const response = await tokenStore.sendGetRoleInfo(tokenId) log('角色信息获取成功', 'success') - - // 更新gameData以便其他组件使用 + + // 同步任务状态 if (response) { - tokenStore.gameData.roleInfo = response + syncCompleteFromServer(response) } - + return response } catch (error) { log(`获取角色信息失败: ${error.message}`, 'error') - console.error('详细错误信息:', error) throw error } } -// 一键补差 - 简化测试版本 +// 执行单个游戏指令的封装 +const executeGameCommand = async (tokenId, cmd, params = {}, description = '', timeout = 8000) => { + try { + if (description) log(`执行: ${description}`) + + const result = await tokenStore.sendMessageWithPromise(tokenId, cmd, params, timeout) + + if (description) log(`${description} - 成功`, 'success') + return result + } catch (error) { + if (description) log(`${description} - 失败: ${error.message}`, 'error') + throw error + } +} + +// 检查是否今日可用(简化版本) +const isTodayAvailable = (statisticsTime) => { + if (!statisticsTime) return true + + // 如果有时间戳,检查是否为今天 + const today = new Date().toDateString() + const recordDate = new Date(statisticsTime).toDateString() + + return today !== recordDate +} + +// 获取今日BOSS ID +const getTodayBossId = () => { + const DAY_BOSS_MAP = [9904, 9905, 9901, 9902, 9903, 9904, 9905] // 周日~周六 + const dayOfWeek = new Date().getDay() + return DAY_BOSS_MAP[dayOfWeek] +} + +// 智能阵容切换辅助函数 +const switchToFormationIfNeeded = async (tokenId, targetFormation, formationName, logFn) => { + try { + // 首先尝试从本地缓存获取当前阵容信息 + const cachedTeamInfo = tokenStore.gameData?.presetTeam?.presetTeamInfo + let currentFormation = cachedTeamInfo?.useTeamId + + if (currentFormation) { + logFn(`从缓存获取当前阵容: ${currentFormation}`) + } else { + // 缓存中没有数据,从服务器获取 + logFn(`缓存中无阵容信息,从服务器获取...`) + const teamInfo = await executeGameCommand(tokenId, 'presetteam_getinfo', {}, '获取阵容信息') + currentFormation = teamInfo?.presetTeamInfo?.useTeamId + logFn(`从服务器获取当前阵容: ${currentFormation}`) + } + + if (currentFormation === targetFormation) { + logFn(`当前已是${formationName}${targetFormation},无需切换`, 'success') + return false // 不需要切换 + } + + logFn(`当前阵容: ${currentFormation}, 目标阵容: ${targetFormation},开始切换...`) + await executeGameCommand(tokenId, 'presetteam_saveteam', + { teamId: targetFormation }, `切换到${formationName}${targetFormation}`) + + logFn(`成功切换到${formationName}${targetFormation}`, 'success') + return true // 已切换 + } catch (error) { + logFn(`阵容检查失败,直接切换: ${error.message}`, 'warning') + // 如果检查失败,还是执行切换操作 + try { + await executeGameCommand(tokenId, 'presetteam_saveteam', + { teamId: targetFormation }, `强制切换到${formationName}${targetFormation}`) + return true + } catch (fallbackError) { + logFn(`强制切换也失败: ${fallbackError.message}`, 'error') + throw fallbackError + } + } +} + +// 每日任务执行器 +const executeDailyTasks = async (roleInfoResp, logFn, progressFn) => { + const tokenId = tokenStore.selectedToken.id + const roleData = roleInfoResp?.role + + if (!roleData) { + throw new Error('角色数据不存在') + } + + logFn('开始执行每日任务补差') + + // 检查已完成的任务 + const completedTasks = roleData.dailyTask?.complete ?? {} + const isTaskCompleted = (taskId) => completedTasks[taskId] === -1 + + // 统计数据 + const statistics = roleData.statistics ?? {} + const statisticsTime = roleData.statisticsTime ?? {} + + // 构建任务列表 + const taskList = [] + + // 1. 基础任务(根据完成状态决定是否执行) + + // 分享游戏 (任务ID: 2) + if (!isTaskCompleted(2)) { + taskList.push({ + name: '分享一次游戏', + execute: () => executeGameCommand(tokenId, 'system_mysharecallback', + { isSkipShareCard: true, type: 2 }, '分享游戏') + }) + } + + // 赠送好友金币 (任务ID: 3) + if (!isTaskCompleted(3)) { + taskList.push({ + name: '赠送好友金币', + execute: () => executeGameCommand(tokenId, 'friend_batch', {}, '赠送好友金币') + }) + } + + // 招募 (任务ID: 4) + if (!isTaskCompleted(4)) { + taskList.push({ + name: '免费招募', + execute: () => executeGameCommand(tokenId, 'hero_recruit', + { recruitType: 3, recruitNumber: 1 }, '免费招募') + }) + + if (settings.payRecruit) { + taskList.push({ + name: '付费招募', + execute: () => executeGameCommand(tokenId, 'hero_recruit', + { recruitType: 1, recruitNumber: 1 }, '付费招募') + }) + } + } + + // 点金 (任务ID: 6) + if (!isTaskCompleted(6) && isTodayAvailable(statisticsTime['buy:gold'])) { + for (let i = 0; i < 3; i++) { + taskList.push({ + name: `免费点金 ${i + 1}/3`, + execute: () => executeGameCommand(tokenId, 'system_buygold', + { buyNum: 1 }, `免费点金 ${i + 1}`) + }) + } + } + + // 挂机奖励 (任务ID: 5) + if (!isTaskCompleted(5) && settings.claimHangUp) { + // 先加钟4次 + for (let i = 0; i < 4; i++) { + taskList.push({ + name: `挂机加钟 ${i + 1}/4`, + execute: () => executeGameCommand(tokenId, 'system_mysharecallback', + { isSkipShareCard: true, type: 2 }, `挂机加钟 ${i + 1}`) + }) + } + + // 然后领取奖励 + taskList.push({ + name: '领取挂机奖励', + execute: () => executeGameCommand(tokenId, 'system_claimhangupreward', {}, '领取挂机奖励') + }) + + // 最后再加1次钟 + taskList.push({ + name: '挂机加钟 5/5', + execute: () => executeGameCommand(tokenId, 'system_mysharecallback', + { isSkipShareCard: true, type: 2 }, '挂机加钟 5') + }) + } + + // 开宝箱 (任务ID: 7) + if (!isTaskCompleted(7) && settings.openBox) { + taskList.push({ + name: '开启木质宝箱', + execute: () => executeGameCommand(tokenId, 'item_openbox', + { itemId: 2001, number: 10 }, '开启木质宝箱10个') + }) + } + + // 盐罐 (任务ID: 14) + if (!isTaskCompleted(14) && settings.claimBottle) { + taskList.push({ + name: '领取盐罐奖励', + execute: () => executeGameCommand(tokenId, 'bottlehelper_claim', {}, '领取盐罐奖励') + }) + } + + // 2. 竞技场 (任务ID: 13) + if (!isTaskCompleted(13) && settings.arenaEnable) { + taskList.push({ + name: '竞技场战斗', + execute: async () => { + logFn('开始竞技场战斗流程') + + // 智能切换到竞技场阵容 + await switchToFormationIfNeeded(tokenId, settings.arenaFormation, '竞技场阵容', logFn) + + // 开始竞技场 + await executeGameCommand(tokenId, 'arena_startarea', {}, '开始竞技场') + + // 进行3场战斗 + for (let i = 1; i <= 3; i++) { + logFn(`竞技场战斗 ${i}/3`) + + // 获取目标 + const targets = await executeGameCommand(tokenId, 'arena_getareatarget', + { refresh: false }, `获取竞技场目标${i}`) + + const targetId = targets?.roleList?.[0]?.roleId + if (targetId) { + await executeGameCommand(tokenId, 'fight_startareaarena', + { targetId }, `竞技场战斗${i}`, 10000) + } else { + logFn(`竞技场战斗${i} - 未找到目标`, 'warning') + } + + // 战斗间隔 + await new Promise(resolve => setTimeout(resolve, 1000)) + } + } + }) + } + + // 3. BOSS战斗 + if (settings.bossTimes > 0) { + // 军团BOSS + const alreadyLegionBoss = statistics['legion:boss'] ?? 0 + const remainingLegionBoss = Math.max(settings.bossTimes - alreadyLegionBoss, 0) + + if (remainingLegionBoss > 0) { + // 为军团BOSS智能切换阵容 + taskList.push({ + name: '军团BOSS阵容检查', + execute: () => switchToFormationIfNeeded(tokenId, settings.bossFormation, 'BOSS阵容', logFn) + }) + + for (let i = 0; i < remainingLegionBoss; i++) { + taskList.push({ + name: `军团BOSS ${i + 1}/${remainingLegionBoss}`, + execute: () => executeGameCommand(tokenId, 'fight_startlegionboss', {}, `军团BOSS ${i + 1}`, 12000) + }) + } + } + + // 每日BOSS + const todayBossId = getTodayBossId() + if (remainingLegionBoss === 0) { + // 如果没有军团BOSS,为每日BOSS切换阵容 + taskList.push({ + name: '每日BOSS阵容检查', + execute: () => switchToFormationIfNeeded(tokenId, settings.bossFormation, 'BOSS阵容', logFn) + }) + } + + for (let i = 0; i < 3; i++) { + taskList.push({ + name: `每日BOSS ${i + 1}/3`, + execute: () => executeGameCommand(tokenId, 'fight_startboss', + { bossId: todayBossId }, `每日BOSS ${i + 1}`, 12000) + }) + } + } + + // 4. 固定奖励领取 + const fixedRewards = [ + { name: '福利签到', cmd: 'system_signinreward' }, + { name: '俱乐部签到', cmd: 'legion_signin' }, + { name: '领取每日礼包', cmd: 'discount_claimreward' }, + { name: '领取免费礼包', cmd: 'card_claimreward' }, + { name: '领取永久卡礼包', cmd: 'card_claimreward', params: { cardId: 4003 } } + ] + + if (settings.claimEmail) { + fixedRewards.push({ name: '领取邮件奖励', cmd: 'mail_claimallattachment' }) + } + + fixedRewards.forEach(reward => { + taskList.push({ + name: reward.name, + execute: () => executeGameCommand(tokenId, reward.cmd, reward.params || {}, reward.name) + }) + }) + + // 5. 免费活动 + // 免费钓鱼 + if (isTodayAvailable(statisticsTime['artifact:normal:lottery:time'])) { + for (let i = 0; i < 3; i++) { + taskList.push({ + name: `免费钓鱼 ${i + 1}/3`, + execute: () => executeGameCommand(tokenId, 'artifact_lottery', + { lotteryNumber: 1, newFree: true, type: 1 }, `免费钓鱼 ${i + 1}`) + }) + } + } + + // 灯神免费扫荡 + const kingdoms = ['魏国', '蜀国', '吴国', '群雄'] + for (let gid = 1; gid <= 4; gid++) { + if (isTodayAvailable(statisticsTime[`genie:daily:free:${gid}`])) { + taskList.push({ + name: `${kingdoms[gid-1]}灯神免费扫荡`, + execute: () => executeGameCommand(tokenId, 'genie_sweep', + { genieId: gid }, `${kingdoms[gid-1]}灯神免费扫荡`) + }) + } + } + + // 灯神免费扫荡卷 + for (let i = 0; i < 3; i++) { + taskList.push({ + name: `领取免费扫荡卷 ${i + 1}/3`, + execute: () => executeGameCommand(tokenId, 'genie_buysweep', {}, `领取免费扫荡卷 ${i + 1}`) + }) + } + + // 6. 黑市购买任务 (任务ID: 12) + if (!isTaskCompleted(12) && settings.blackMarketPurchase) { + taskList.push({ + name: '黑市购买1次物品', + execute: () => executeGameCommand(tokenId, 'store_purchase', { goodsId: 1 }, '黑市购买1次物品') + }) + } + + // 7. 任务奖励领取 + for (let taskId = 1; taskId <= 10; taskId++) { + taskList.push({ + name: `领取任务奖励${taskId}`, + execute: () => executeGameCommand(tokenId, 'task_claimdailypoint', + { taskId }, `领取任务奖励${taskId}`, 5000) + }) + } + + // 日常和周常奖励 + taskList.push( + { + name: '领取日常任务奖励', + execute: () => executeGameCommand(tokenId, 'task_claimdailyreward', {}, '领取日常任务奖励') + }, + { + name: '领取周常任务奖励', + execute: () => executeGameCommand(tokenId, 'task_claimweekreward', {}, '领取周常任务奖励') + } + ) + + // 执行任务列表 + const totalTasks = taskList.length + logFn(`共有 ${totalTasks} 个任务待执行`) + + for (let i = 0; i < taskList.length; i++) { + const task = taskList[i] + + try { + await task.execute() + + // 更新进度 + const progress = Math.floor(((i + 1) / totalTasks) * 100) + if (progressFn) progressFn(tokenId, progress) + + // 任务间隔 + await new Promise(resolve => setTimeout(resolve, 500)) + + } catch (error) { + logFn(`任务执行失败: ${task.name} - ${error.message}`, 'error') + // 继续执行下一个任务 + } + } + + // 确保进度为100% + if (progressFn) progressFn(tokenId, 100) + logFn('所有任务执行完成', 'success') + + // 最后刷新一次角色信息 + await new Promise(resolve => setTimeout(resolve, 2000)) + await refreshRoleInfo() +} + +// 一键补差主函数 const runDailyFix = async () => { if (!tokenStore.selectedToken || busy.value) { - log('没有选中Token或正在执行中', 'error') + message.warning('没有选中Token或正在执行中') return } - + + if (!isConnected.value) { + message.error('WebSocket连接未建立,请检查连接状态') + return + } + busy.value = true showLog.value = true logList.value = [] - - log('开始执行任务...') - - const tokenId = tokenStore.selectedToken.id - log(`当前Token ID: ${tokenId}`) - - // 检查tokenStore方法 - log(`检查tokenStore方法:`) - log(`- sendMessageWithPromise: ${typeof tokenStore.sendMessageWithPromise}`) - log(`- getWebSocketStatus: ${typeof tokenStore.getWebSocketStatus}`) - log(`- selectedToken: ${!!tokenStore.selectedToken}`) - - // 检查WebSocket连接状态 - const wsStatus = tokenStore.getWebSocketStatus(tokenId) - log(`WebSocket状态: ${JSON.stringify(wsStatus)}`) - - // 修复状态检查逻辑 - wsStatus可能直接是字符串,也可能是对象 - const actualStatus = typeof wsStatus === 'string' ? wsStatus : wsStatus?.status - log(`实际状态: ${actualStatus}`) - - if (actualStatus !== 'connected') { - log('WebSocket未连接,无法继续执行', 'error') - busy.value = false - return - } - + try { - log('尝试获取游戏内角色信息...') - log('发送 role_getroleinfo 命令到游戏服务器...') - log('期望响应: role_getroleinforesp') - - // 先检查WebSocket客户端是否能接收到消息 - tokenStore.setMessageListener((message) => { - if (message?.cmd) { - log(`收到游戏消息: ${message.cmd}`, 'info') - } + log('=== 开始执行一键补差任务 ===') + + + // 1. 获取角色信息 + const roleInfo = await refreshRoleInfo() + + if (!roleInfo?.role) { + throw new Error('获取角色信息失败或数据异常') + } + + + log(`当前每日任务进度: ${roleInfo.role.dailyTask?.dailyPoint || 0}/100`) + + // 2. 执行任务 + log('第二步: 开始执行每日任务...') + await executeDailyTasks(roleInfo, log, (tokenId, progress) => { + log(`任务进度: ${progress}%`) }) - - // 增加超时时间,因为游戏服务器响应可能较慢 - const roleInfo = await tokenStore.sendMessageWithPromise(tokenId, 'role_getroleinfo', {}, 10000) - - if (roleInfo) { - log('游戏角色信息获取成功!', 'success') - - // 显示角色基本信息(如果存在) - if (roleInfo.role) { - log(`角色等级: ${roleInfo.role.level || '未知'}`) - log(`角色名称: ${roleInfo.role.name || '未知'}`) - log(`每日任务进度: ${roleInfo.role.dailyTask?.dailyPoint || 0}/100`) + + log('=== 任务执行完成 ===', 'success') + message.success('每日任务补差执行完成') + + // 3. 最终刷新角色信息 + setTimeout(async () => { + try { + await refreshRoleInfo() + log('最终角色信息刷新完成', 'success') + } catch (error) { + log(`最终刷新失败: ${error.message}`, 'warning') } - - // 现在尝试执行一个简单的游戏指令 - log('尝试执行游戏内签到...') - const signInResult = await tokenStore.sendMessageWithPromise(tokenId, 'system_signinreward', {}, 8000) - - if (signInResult) { - log('游戏签到执行成功!', 'success') - log(`签到奖励: ${signInResult.reward ? '有奖励' : '无奖励或已签到'}`) - } - - message.success('游戏指令测试成功!') - } else { - log('未收到游戏角色数据', 'error') - message.warning('未收到游戏服务器响应') - } - + }, 3000) + } catch (error) { - log(`游戏指令执行失败: ${error.message}`, 'error') - - // 分析可能的原因 - if (error.message.includes('超时') || error.message.includes('timeout')) { - log('可能原因:游戏服务器响应超时', 'error') - log('建议:检查网络连接或稍后重试', 'error') - } else if (error.message.includes('Unknown cmd')) { - log('可能原因:游戏指令未在WebSocket客户端中注册', 'error') - } else { - log('可能原因:WebSocket连接异常或游戏服务器拒绝请求', 'error') - } - - message.error(`游戏指令执行失败: ${error.message}`) + log(`任务执行失败: ${error.message}`, 'error') + console.error('详细错误信息:', error) + message.error(`任务执行失败: ${error.message}`) } finally { busy.value = false } } -// 简化的执行器函数 - 直接使用tokenStore方法 -const U = async (roleInfoResp, logFn, progress) => { - const tokenId = tokenStore.selectedToken.id - - logFn?.('开始执行每日任务') - - // 检查已完成的任务 - const completedTasks = roleInfoResp.role?.dailyTask?.complete ?? {} - const isTaskCompleted = (taskId) => completedTasks[taskId] === -1 - - // 执行任务列表 - const taskList = [] - - // 基础任务 - if (!isTaskCompleted(2)) { // 分享游戏 - taskList.push({ name: '分享一次游戏', cmd: 'system_mysharecallback', params: { isSkipShareCard: true, type: 2 } }) - } - - if (!isTaskCompleted(3)) { // 赠送好友 - taskList.push({ name: '赠送好友金币', cmd: 'friend_batch' }) - } - - if (!isTaskCompleted(4)) { // 招募 - taskList.push({ name: '免费招募', cmd: 'hero_recruit' }) - } - - if (!isTaskCompleted(6)) { // 点金 - taskList.push({ name: '免费点金', cmd: 'system_buygold' }) - } - - if (!isTaskCompleted(5) && settings.claimHangUp) { // 挂机奖励 - taskList.push({ name: '领取挂机奖励', cmd: 'system_claimhangupreward' }) - } - - if (!isTaskCompleted(7) && settings.openBox) { // 开宝箱 - taskList.push({ name: '开启宝箱', cmd: 'item_openbox', params: { itemId: 2001, number: 10 } }) - } - - if (!isTaskCompleted(14) && settings.claimBottle) { // 盐罐 - taskList.push({ name: '领取盐罐奖励', cmd: 'bottlehelper_claim' }) +// 刷新任务状态 +const handleRefreshTaskStatus = async () => { + if (!isConnected.value) { + message.warning('WebSocket未连接,无法刷新任务状态') + return } - // 常规奖励 - taskList.push( - { name: '福利签到', cmd: 'system_signinreward' }, - { name: '俱乐部签到', cmd: 'legion_signin' }, - { name: '领取每日礼包', cmd: 'discount_claimreward' }, - { name: '领取免费礼包', cmd: 'card_claimreward' } - ) - - if (settings.claimEmail) { - taskList.push({ name: '领取邮件奖励', cmd: 'mail_claimallattachment' }) + try { + log('手动刷新任务状态...') + await refreshRoleInfo() + message.success('任务状态刷新成功') + } catch (error) { + log(`刷新失败: ${error.message}`, 'error') + message.error(`刷新失败: ${error.message}`) } - - // 任务奖励领取 - for (let i = 1; i <= 10; i++) { - taskList.push({ name: `领取任务奖励${i}`, cmd: 'task_claimdailypoint', params: { taskId: i } }) - } - taskList.push( - { name: '领取日常任务奖励', cmd: 'task_claimdailyreward' }, - { name: '领取周常任务奖励', cmd: 'task_claimweekreward' } - ) - - // 竞技场 - if (!isTaskCompleted(13) && settings.arenaEnable) { - logFn?.('开始竞技场战斗') - try { - // 获取队伍信息 - const teamInfo = await tokenStore.sendMessageWithPromise(tokenId, 'presetteam_getinfo', {}, 5000) - - // 切换阵容(如果需要) - if (teamInfo?.presetTeamInfo?.useTeamId !== settings.arenaFormation) { - await tokenStore.sendMessageWithPromise(tokenId, 'presetteam_saveteam', { teamId: settings.arenaFormation }, 5000) - logFn?.(`切换到竞技场阵容 ${settings.arenaFormation}`) - } - - // 开始竞技场 - await tokenStore.sendMessageWithPromise(tokenId, 'arena_startarea', {}, 5000) - - // 进行3场战斗 - for (let i = 1; i <= 3; i++) { - logFn?.(`竞技场战斗 ${i}/3`) - const targets = await tokenStore.sendMessageWithPromise(tokenId, 'arena_getareatarget', {}, 5000) - const targetId = targets?.roleList?.[0]?.roleId - - if (targetId) { - await tokenStore.sendMessageWithPromise(tokenId, 'fight_startareaarena', { targetId }, 8000) - logFn?.(`完成竞技场战斗 ${i}`, 'success') - } - } - } catch (error) { - logFn?.(`竞技场战斗失败: ${error.message}`, 'error') - } - } - - // 执行任务列表 - const total = taskList.length - for (let i = 0; i < taskList.length; i++) { - const task = taskList[i] - logFn?.(task.name) - - try { - await tokenStore.sendMessageWithPromise(tokenId, task.cmd, task.params || {}, 5000) - logFn?.(`${task.name} 成功`, 'success') - } catch (error) { - logFn?.(`${task.name} 失败: ${error.message}`, 'error') - } - - // 更新进度 - const progress_pct = Math.floor(((i + 1) / total) * 100) - if (progress && tokenId) progress(tokenId, progress_pct) - - // 小延迟避免过快 - await new Promise(resolve => setTimeout(resolve, 300)) - } - - // 确保进度为100% - if (progress && tokenId) progress(tokenId, 100) - logFn?.('所有任务执行完成', 'success') } // 辅助函数 @@ -632,21 +896,21 @@ const loadSettings = (roleId) => { try { const raw = localStorage.getItem(`daily-settings:${roleId}`) return raw ? JSON.parse(raw) : null - } catch (error) { + } catch (error) { console.error('Failed to load settings:', error) - return null + return null } } const saveSettings = (roleId, s) => { - try { - localStorage.setItem(`daily-settings:${roleId}`, JSON.stringify(s)) + try { + localStorage.setItem(`daily-settings:${roleId}`, JSON.stringify(s)) } catch (error) { console.error('Failed to save settings:', error) } } -// 监听设置变化 - 基于参考代码的watch逻辑 +// 监听设置变化 watch(settings, (cur) => { const role = getCurrentRole() if (role) saveSettings(role.roleId, cur) @@ -655,29 +919,41 @@ watch(settings, (cur) => { // 监听token选择变化 watch(() => tokenStore.selectedToken, async (newToken, oldToken) => { if (newToken && newToken !== oldToken) { + log(`切换到Token: ${newToken.name}`) + // 加载新token的设置 const saved = loadSettings(newToken.id) if (saved) Object.assign(settings, saved) - - // 同步任务状态 - syncCompleteFromServer(tokenStore.selectedTokenRoleInfo) + + // 如果WebSocket已连接,尝试获取最新角色信息 + if (isConnected.value) { + try { + await refreshRoleInfo() + } catch (error) { + console.warn('切换token后获取角色信息失败:', error.message) + } + } } }, { immediate: true }) -// 生命周期 - 基于参考代码的onMounted函数 +// 监听角色信息变化,自动同步任务状态 +watch(() => tokenStore.selectedTokenRoleInfo, (newRoleInfo) => { + if (newRoleInfo?.role?.dailyTask?.complete) { + log('角色信息更新,同步任务状态') + syncCompleteFromServer(newRoleInfo) + } +}, { immediate: true, deep: true }) + +// 生命周期 onMounted(async () => { - // 首次拉取角色信息(如果有选中的token) - if (tokenStore.selectedToken) { + log('组件初始化完成') + + // 首次拉取角色信息(如果有选中的token且已连接) + if (tokenStore.selectedToken && isConnected.value) { try { await refreshRoleInfo() } catch (error) { console.warn('初始化时获取角色信息失败:', error.message) - // 如果获取失败,尝试发送普通消息(不等待响应) - try { - tokenStore.sendMessage(tokenStore.selectedToken.id, 'role_getroleinfo', {}) - } catch (sendError) { - console.warn('发送角色信息请求失败:', sendError.message) - } } } @@ -687,13 +963,11 @@ onMounted(async () => { if (saved) Object.assign(settings, saved) } - // 同步完成态(使用现有的角色信息) - syncCompleteFromServer(tokenStore.selectedTokenRoleInfo) + // 初始化时的任务状态同步会通过 watch selectedTokenRoleInfo 自动处理 }) -// 清理监听 - 基于参考代码的onBeforeUnmount onBeforeUnmount(() => { - tokenStore.setMessageListener(undefined) + log('组件即将卸载') }) @@ -851,7 +1125,34 @@ onBeforeUnmount(() => { .modal-header { display: flex; align-items: center; + justify-content: space-between; gap: var(--spacing-sm); + width: 100%; +} + +.refresh-button { + display: flex; + align-items: center; + gap: var(--spacing-xs); + padding: var(--spacing-xs) var(--spacing-sm); + border: 1px solid var(--border-light); + border-radius: var(--border-radius-medium); + background: white; + color: var(--text-secondary); + font-size: var(--font-size-sm); + cursor: pointer; + transition: all var(--transition-fast); + + &:hover:not(:disabled) { + background: var(--bg-tertiary); + border-color: var(--primary-color); + color: var(--primary-color); + } + + &:disabled { + opacity: 0.5; + cursor: not-allowed; + } } .settings-content { @@ -941,7 +1242,7 @@ onBeforeUnmount(() => { background: var(--bg-tertiary); border-radius: var(--border-radius-medium); padding: var(--spacing-md); - max-height: 300px; + max-height: 400px; overflow-y: auto; } @@ -968,6 +1269,10 @@ onBeforeUnmount(() => { &.success { color: var(--success-color); } + + &.warning { + color: #f59e0b; + } } // 响应式设计 @@ -982,4 +1287,4 @@ onBeforeUnmount(() => { justify-content: center; } } - \ No newline at end of file + diff --git a/src/components/TeamStatus.vue b/src/components/TeamStatus.vue index 382ed26..7447315 100644 --- a/src/components/TeamStatus.vue +++ b/src/components/TeamStatus.vue @@ -2,30 +2,30 @@
队伍图标

队伍阵容

当前使用的战斗阵容

+
@@ -36,236 +36,227 @@
当前阵容 - 阵容 {{ currentTeam }} + + + +
- +
-
-
+
- -
- {{ hero.name?.substring(0, 2) || '?' }} +
+ +
+ {{ hero.name?.substring(0, 2) || '?' }} +
{{ hero.name || '未知' }}
- -
+ +

暂无队伍信息

+ +

正在加载队伍信息…

- \ No newline at end of file + diff --git a/src/components/TowerStatus.vue b/src/components/TowerStatus.vue index 231d320..23d75f0 100644 --- a/src/components/TowerStatus.vue +++ b/src/components/TowerStatus.vue @@ -43,7 +43,7 @@ > {{ isClimbing.value ? '爬塔中...' : '开始爬塔' }} - +