fix(game): 修复房间信息请求和定缺响应处理逻辑

- 将 pendingRoomInfoRequest 重命名为 needsInitialRoomInfo 以更准确表达含义
- 移除 waiting 阶段的限制条件,仅在结算阶段返回 false
- 当手牌为空时才返回空状态,避免误判
- 新增 handlePlayerDingQueResponse 函数处理玩家定缺响应
- 优化 onMounted 中的房间信息请求逻辑,确保连接状态下才发送请求
- 在消息处理器中添加对定缺响应的处理支持
This commit is contained in:
2026-03-27 17:26:33 +08:00
parent d1220cc45d
commit d60a505226

View File

@@ -83,7 +83,7 @@ const startGamePending = ref(false)
const dingQuePending = ref(false)
let clockTimer: number | null = null
let unsubscribe: (() => void) | null = null
let pendingRoomInfoRequest = false
let needsInitialRoomInfo = false
const menuOpen = ref(false)
const isTrustMode = ref(false)
@@ -352,7 +352,7 @@ const showDingQueChooser = computed(() => {
return false
}
if (gameStore.phase === 'waiting' || gameStore.phase === 'settlement') {
if (gameStore.phase === 'settlement') {
return false
}
@@ -568,18 +568,14 @@ function requestRoomInfo(): void {
const routeRoomId = typeof route.params.roomId === 'string' ? route.params.roomId : ''
const roomId = routeRoomId || gameStore.roomId || activeRoom.value?.roomId || ''
if (!roomId) {
pendingRoomInfoRequest = true
wsMessages.value.push('[client] get_room_info pending: missing roomId')
return
}
if (wsStatus.value !== 'connected') {
pendingRoomInfoRequest = true
wsMessages.value.push(`[client] get_room_info pending: ws=${wsStatus.value}`)
return
}
pendingRoomInfoRequest = false
needsInitialRoomInfo = false
wsMessages.value.push(`[client] get_room_info ${roomId}`)
sendWsMessage({
type: 'get_room_info',
@@ -920,7 +916,7 @@ const wallSeats = computed<Record<SeatKey, WallSeatState>>(() => {
left: emptyWallSeat(),
}
if (gameStore.phase === 'waiting') {
if (gameStore.phase === 'waiting' && myHandTiles.value.length === 0) {
return emptyState
}
@@ -1249,6 +1245,59 @@ function handleReadyStateResponse(message: unknown): void {
}
}
function handlePlayerDingQueResponse(message: unknown): void {
if (!message || typeof message !== 'object') {
return
}
const source = message as Record<string, unknown>
if (typeof source.type !== 'string') {
return
}
if (normalizeWsType(source.type) !== 'PLAYER_DING_QUE') {
return
}
const payload = asRecord(source.payload)
if (!payload) {
return
}
const roomId =
readString(payload, 'room_id', 'roomId') ||
readString(source, 'roomId')
if (roomId && roomId !== gameStore.roomId) {
return
}
const userId =
readString(payload, 'user_id', 'userId', 'player_id', 'playerId') ||
readString(source, 'target')
const suit = readString(payload, 'suit', 'Suit')
if (!userId || !suit) {
return
}
const player = gameStore.players[userId]
if (player) {
player.missingSuit = suit
}
const room = activeRoom.value
if (room && room.roomId === (roomId || gameStore.roomId)) {
const roomPlayer = room.players.find((item) => item.playerId === userId)
if (roomPlayer) {
roomPlayer.missingSuit = suit
}
}
if (userId === loggedInUserId.value) {
dingQuePending.value = false
}
}
function logoutToLogin(): void {
clearAuth()
auth.value = null
@@ -1558,18 +1607,20 @@ function hydrateFromActiveRoom(routeRoomId: string): void {
onMounted(() => {
const routeRoomId = typeof route.params.roomId === 'string' ? route.params.roomId : ''
pendingRoomInfoRequest = true
needsInitialRoomInfo = true
void ensureCurrentUserLoaded().finally(() => {
hydrateFromActiveRoom(routeRoomId)
if (routeRoomId) {
gameStore.roomId = routeRoomId
}
requestRoomInfo()
if (wsStatus.value === 'connected' && needsInitialRoomInfo) {
requestRoomInfo()
}
})
const handler = (status: WsStatus) => {
wsStatus.value = status
if (status === 'connected' && pendingRoomInfoRequest) {
if (status === 'connected' && needsInitialRoomInfo) {
requestRoomInfo()
}
}
@@ -1580,6 +1631,7 @@ onMounted(() => {
handleRoomInfoResponse(msg)
handlePlayerHandResponse(msg)
handleReadyStateResponse(msg)
handlePlayerDingQueResponse(msg)
const gameAction = toGameAction(msg)
if (gameAction) {
dispatchGameAction(gameAction)