Compare commits

...

2 Commits

Author SHA1 Message Date
tsui110
9309277047 Merge branch 'main' of https://git.1024tool.vip/zfc/bindbox-mini
# Conflicts:
#	pages-game/game/minesweeper/play.vue
2026-01-03 16:39:36 +08:00
tsui110
3d37bbc8d3 fix:修复了扫雷不弹出结算窗口 2026-01-03 16:38:41 +08:00
4 changed files with 193 additions and 4 deletions

View File

@ -520,12 +520,47 @@ function cleanAvatar(avatar) {
}
const MATCHING_GAME_CACHE_KEY = 'matching_game_cache_v1'
const MATCHING_GAME_TIMESTAMP_KEY = 'matching_game_last_timestamp' //
function getMatchingGameCache() {
const obj = uni.getStorageSync(MATCHING_GAME_CACHE_KEY) || {}
return typeof obj === 'object' && obj ? obj : {}
}
/**
* 记录对对碰游戏卡片获取时间戳
* 当成功调用 /api/app/matching/cards 接口时调用
*/
function recordMatchingGameCardsTimestamp() {
const timestamp = Date.now()
uni.setStorageSync(MATCHING_GAME_TIMESTAMP_KEY, timestamp)
console.log('[MatchingGame] 记录卡片获取时间戳:', new Date(timestamp).toISOString())
}
/**
* 检查对对碰游戏缓存是否过期
* @param {number} maxAgeSeconds - 最大有效期默认100秒
* @returns {boolean} true表示未过期false表示已过期
*/
function isMatchingGameCacheValid(maxAgeSeconds = 100) {
const timestamp = uni.getStorageSync(MATCHING_GAME_TIMESTAMP_KEY)
if (!timestamp) return false
const now = Date.now()
const ageSeconds = (now - timestamp) / 1000
const isValid = ageSeconds < maxAgeSeconds
console.log('[MatchingGame] 检查缓存有效期:', {
timestamp: new Date(timestamp).toISOString(),
now: new Date(now).toISOString(),
ageSeconds: ageSeconds.toFixed(2),
maxAgeSeconds,
isValid
})
return isValid
}
function findLatestMatchingGameCacheEntry(aid) {
const activityKey = String(aid || '')
if (!activityKey) return null
@ -550,6 +585,17 @@ function findLatestMatchingGameCacheEntry(aid) {
}
function syncResumeGame(aid) {
// 100
if (!isMatchingGameCacheValid(100)) {
console.log('[MatchingGame] 缓存已过期,清除所有缓存')
//
uni.removeStorageSync(MATCHING_GAME_CACHE_KEY)
uni.removeStorageSync(MATCHING_GAME_TIMESTAMP_KEY)
resumeIssueId.value = ''
resumeGame.value = null
return null
}
const latest = findLatestMatchingGameCacheEntry(aid)
if (!latest || !latest.entry || !latest.entry.game_id) {
resumeIssueId.value = ''
@ -1413,7 +1459,10 @@ async function doDraw() {
// 4.
const cardsRes = await getMatchingGameCards(gameId)
if (!cardsRes) throw new Error('获取游戏数据失败')
//
recordMatchingGameCardsTimestamp()
const allCards = normalizeAllCards(cardsRes.all_cards || cardsRes.data?.all_cards || [])
if (!allCards.length) throw new Error('游戏数据为空')

View File

@ -1242,6 +1242,22 @@
font-size: 40rpx;
font-weight: 900;
color: $text-dark-main;
margin-top: $spacing-md;
}
.result-details {
margin: $spacing-lg 0;
padding: $spacing-md;
background: rgba($bg-dark-card, 0.5);
border-radius: $radius-md;
width: 100%;
.detail-text {
font-size: $font-md;
color: $text-dark-sub;
text-align: center;
line-height: 1.6;
}
}
// =====================================

View File

@ -81,7 +81,7 @@
<view v-else class="game-screen">
<!-- 顶部状态栏 -->
<view class="game-header">
<view class="round-badge">Round {{ gameState.round }}</view>
<view class="round-badge">Round {{ gameState.globalTurnCount || gameState.round || 0 }}</view>
<text class="header-title">动物扫雷</text>
<view class="header-actions">
<view class="btn-icon" @tap="showGuide = true">📜</view>
@ -232,12 +232,24 @@
</view>
<!-- 结算弹窗 -->
<<<<<<< HEAD
<view v-if="shouldShowResultModal" class="modal-overlay">
<view class="modal-content glass-card">
<text class="modal-emoji">{{ gameState.winnerId === myUserId ? '🏆' : '💀' }}</text>
<text class="modal-title">{{ gameState.winnerId === myUserId ? '胜利!' : '很遗憾失败了' }}</text>
<view class="result-details" v-if="gameState.players">
<text class="detail-text">{{ getResultMessage() }}</text>
</view>
<view
class="btn-primary"
=======
<view v-if="gameState && !gameState.gameStarted && gameState.winnerId" class="modal-overlay">
<view class="modal-content glass-card">
<text class="modal-emoji">{{ gameState.winnerId === 'draw' ? '🤝' : (gameState.winnerId === myUserId ? '🏆' : '💀') }}</text>
<text class="modal-title">{{ gameState.winnerId === 'draw' ? '平局' : (gameState.winnerId === myUserId ? '胜利!' : '很遗憾失败了') }}</text>
<view
class="btn-primary"
>>>>>>> c028a29943b7b201a73114cb14a1109deb3af339
:class="{ disabled: isRefreshing }"
@tap="refreshAndPlayAgain"
>
@ -352,6 +364,27 @@ export default {
},
globalLabels() {
return this.floatingLabels.filter(l => l.cellIndex === undefined && l.targetUserId === undefined);
},
//
shouldShowResultModal() {
//
if (!this.gameState) return false;
// gameStarted false
const isGameOver = this.gameState.gameStarted === false;
//
const hasWinner = !!this.gameState.winnerId;
console.log('[shouldShowResultModal] 检查弹窗显示条件:', {
isGameOver,
hasWinner,
winnerId: this.gameState.winnerId,
myUserId: this.myUserId,
shouldShow: isGameOver && hasWinner
});
return isGameOver && hasWinner;
}
},
watch: {
@ -602,15 +635,48 @@ export default {
} else if (opCode === 5) {
this.handleEvent(data);
} else if (opCode === 6) {
// -
console.log('[游戏结束] 接收到游戏结束数据:', data);
if (data.gameState) {
this.gameState = data.gameState;
//
this.gameState = {
...data.gameState,
gameStarted: false, //
winnerId: data.winnerId || data.gameState.winnerId
};
} else {
this.gameState = data;
this.gameState = {
...data,
gameStarted: false //
};
}
// winnerId
if (!this.gameState.winnerId && data.winnerId) {
this.gameState.winnerId = data.winnerId;
}
console.log('[游戏结束] 最终游戏状态:', this.gameState);
console.log('[游戏结束] winnerId:', this.gameState.winnerId);
console.log('[游戏结束] gameStarted:', this.gameState.gameStarted);
console.log('[游戏结束] 是否显示弹窗:', !this.gameState.gameStarted && !!this.gameState.winnerId);
this.addLog('system', `战局结束:${this.gameState.winnerId === this.myUserId ? '🎉 您获得了胜利!' : '💀 很遗憾失败了'}`);
//
if (this.gameState.winnerId === this.myUserId) {
uni.vibrateShort({ type: 'success' });
} else {
uni.vibrateShort({ type: 'fail' });
}
<<<<<<< HEAD
=======
let endMsg = '';
if (data.winnerId === 'draw') endMsg = '平局:无人幸存';
else endMsg = `战局结束:${data.winnerId === this.myUserId ? '您获得了胜利!' : '很遗憾失败了'}`;
this.addLog('system', endMsg);
>>>>>>> c028a29943b7b201a73114cb14a1109deb3af339
}
},
handleEvent(event) {
@ -740,6 +806,20 @@ export default {
100: '请求游戏状态'
};
return map[code] || '未知';
},
//
getResultMessage() {
if (!this.gameState || !this.gameState.players) return '';
const winnerId = this.gameState.winnerId;
const winner = this.gameState.players[winnerId];
const winnerName = winner ? (winner.username || '对手') : '未知';
if (winnerId === this.myUserId) {
return '恭喜您战胜了所有对手,获得胜利!';
} else {
return `${winnerName.substring(0, 10)} 获得了胜利,下次好运!`;
}
}
}
}

View File

@ -4,6 +4,7 @@
const REWARD_CACHE_KEY = 'reward_cache_v2' // v2: 修复概率精度问题
const MATCHING_GAME_CACHE_KEY = 'matching_game_cache_v1'
const MATCHING_GAME_TIMESTAMP_KEY = 'matching_game_last_timestamp' // 对对碰最后获取卡片数据的时间
/**
* 判断缓存是否新鲜
@ -171,3 +172,46 @@ export function findLatestMatchingGameCacheEntry(activityId) {
if (!bestEntry) return null
return { issue_id: bestIssueId, entry: bestEntry }
}
/**
* 记录对对碰游戏卡片获取时间戳
* 当成功调用 /api/app/matching/cards 接口时调用
*/
export function recordMatchingGameCardsTimestamp() {
const timestamp = Date.now()
uni.setStorageSync(MATCHING_GAME_TIMESTAMP_KEY, timestamp)
console.log('[MatchingGame] 记录卡片获取时间戳:', new Date(timestamp).toISOString())
}
/**
* 检查对对碰游戏缓存是否过期
* @param {number} maxAgeSeconds - 最大有效期默认100秒
* @returns {boolean} true表示未过期false表示已过期
*/
export function isMatchingGameCacheValid(maxAgeSeconds = 100) {
const timestamp = uni.getStorageSync(MATCHING_GAME_TIMESTAMP_KEY)
if (!timestamp) return false
const now = Date.now()
const ageSeconds = (now - timestamp) / 1000
const isValid = ageSeconds < maxAgeSeconds
console.log('[MatchingGame] 检查缓存有效期:', {
timestamp: new Date(timestamp).toISOString(),
now: new Date(now).toISOString(),
ageSeconds: ageSeconds.toFixed(2),
maxAgeSeconds,
isValid
})
return isValid
}
/**
* 清除对对碰游戏缓存和时间戳
*/
export function clearMatchingGameAllCache() {
uni.removeStorageSync(MATCHING_GAME_CACHE_KEY)
uni.removeStorageSync(MATCHING_GAME_TIMESTAMP_KEY)
console.log('[MatchingGame] 已清除所有对对碰缓存')
}