refactor(game): 重构缺门花色处理逻辑并优化组件结构

- 移除硬编码的花色图标导入,改用动态加载方式
- 添加新的 flowerColorMap 配置文件统一管理缺门图标
- 引入 clearActiveRoom 函数用于清理活动房间状态
- 在游戏数据解析中添加缺失花色的读取函数
- 当房间数据为空时自动清理房间状态并跳转回大厅
- 统一玩家缺门花色数据处理逻辑
- 注释掉浮动状态显示区域以优化界面布局
- 调整CSS样式中缺门标记尺寸和旋转效果
- 在游戏存储模块中添加清除快照功能
- 重构座位玩家卡片组件中的花色图标计算逻辑
- 优化花色标签映射和归一化处理函数
This commit is contained in:
2026-03-28 09:59:44 +08:00
parent d60a505226
commit 4f7a54cf08
8 changed files with 136 additions and 56 deletions

View File

@@ -2,9 +2,6 @@
import {computed, onBeforeUnmount, onMounted, ref} from 'vue'
import {useRoute, useRouter} from 'vue-router'
import deskImage from '../assets/images/desk/desk_01.png'
import wanIcon from '../assets/images/flowerClolor/wan.png'
import tongIcon from '../assets/images/flowerClolor/tong.png'
import tiaoIcon from '../assets/images/flowerClolor/tiao.png'
import robotIcon from '../assets/images/icons/robot.svg'
import exitIcon from '../assets/images/icons/exit.svg'
import '../assets/styles/room.css'
@@ -30,7 +27,7 @@ import {wsClient} from '../ws/client'
import {sendWsMessage} from '../ws/sender'
import {buildWsUrl} from '../ws/url'
import {useGameStore} from '../store/gameStore'
import {setActiveRoom, useActiveRoomState} from '../store'
import {clearActiveRoom, setActiveRoom, useActiveRoomState} from '../store'
import type {MeldState, PlayerState} from '../types/state'
import type {Tile} from '../types/tile'
import {getTileImage as getBottomTileImage} from '../config/bottomTileMap.ts'
@@ -449,6 +446,14 @@ function readBoolean(source: Record<string, unknown>, ...keys: string[]): boolea
return null
}
function readMissingSuit(source: Record<string, unknown> | null | undefined): string | null {
if (!source) {
return null
}
return readString(source, 'missing_suit', 'MissingSuit', 'ding_que', 'dingQue', 'suit', 'Suit') || null
}
function tileToText(tile: Tile): string {
return `${tile.suit}${tile.value}`
}
@@ -601,6 +606,15 @@ function handleRoomInfoResponse(message: unknown): void {
const room = asRecord(payload.room)
const gameState = asRecord(payload.game_state)
const playerView = asRecord(payload.player_view)
if (!room && !gameState && !playerView) {
clearActiveRoom()
gameStore.resetGame()
wsClient.close()
void router.push('/hall')
return
}
const roomId =
readString(room ?? {}, 'room_id', 'roomId') ||
readString(gameState ?? {}, 'room_id', 'roomId') ||
@@ -657,7 +671,7 @@ function handleRoomInfoResponse(message: unknown): void {
readString(player, 'player_name', 'PlayerName', 'display_name', 'displayName', 'nickname', 'username') ||
(playerId === loggedInUserId.value ? loggedInUserName.value : '')
const ready = readBoolean(player, 'ready', 'Ready') ?? false
const missingSuit = readString(player, 'missing_suit', 'MissingSuit') || null
const missingSuit = readMissingSuit(player)
playerMap.set(playerId, {
roomPlayer: {
@@ -705,7 +719,7 @@ function handleRoomInfoResponse(message: unknown): void {
readNumber(player, 'index', 'Index', 'seat_index', 'seatIndex') ??
fallbackIndex
const displayName = existing?.gamePlayer.displayName || (playerId === loggedInUserId.value ? loggedInUserName.value : '')
const missingSuit = readString(player, 'missing_suit', 'MissingSuit') || existing?.gamePlayer.missingSuit || null
const missingSuit = readMissingSuit(player) || existing?.gamePlayer.missingSuit || null
const handCount = readNumber(player, 'hand_count', 'handCount') ?? 0
const outTiles = normalizeTiles(player.out_tiles ?? player.outTiles)
const melds = normalizeMelds(
@@ -749,9 +763,12 @@ function handleRoomInfoResponse(message: unknown): void {
if (loggedInUserId.value && playerMap.has(loggedInUserId.value)) {
const current = playerMap.get(loggedInUserId.value)
if (current) {
const selfMissingSuit = readMissingSuit(playerView)
current.roomPlayer.hand = privateHand.map((tile) => tileToText(tile))
current.roomPlayer.missingSuit = selfMissingSuit || current.roomPlayer.missingSuit
current.gamePlayer.handTiles = privateHand
current.gamePlayer.handCount = privateHand.length
current.gamePlayer.missingSuit = selfMissingSuit || current.gamePlayer.missingSuit
}
}
@@ -1030,26 +1047,11 @@ const seatDecor = computed<Record<SeatKey, SeatPlayerCardModel>>(() => {
return result
})
const floatingMissingSuit = computed(() => {
const suitMap: Record<string, string> = {
: wanIcon,
: tongIcon,
: tiaoIcon,
}
const topLabel = seatDecor.value.top?.missingSuitLabel ?? ''
const leftLabel = seatDecor.value.left?.missingSuitLabel ?? ''
const rightLabel = seatDecor.value.right?.missingSuitLabel ?? ''
return {
top: suitMap[topLabel] ?? '',
left: suitMap[leftLabel] ?? '',
right: suitMap[rightLabel] ?? '',
}
})
function missingSuitLabel(value: string | null | undefined): string {
const suitMap: Record<string, string> = {
w: '万',
t: '筒',
b: '条',
wan: '万',
tong: '筒',
tiao: '条',
@@ -1058,7 +1060,9 @@ function missingSuitLabel(value: string | null | undefined): string {
if (!value) {
return ''
}
return suitMap[value] ?? value
const normalized = value.trim().toLowerCase()
return suitMap[normalized] ?? value
}
function toggleMenu(): void {
@@ -1825,18 +1829,18 @@ onBeforeUnmount(() => {
<span v-if="wallSeats.left.hasHu" class="wall-hu-flag"></span>
</div>
<div class="floating-status top">
<img v-if="floatingMissingSuit.top" :src="floatingMissingSuit.top" alt=""/>
<span>{{ seatDecor.top.missingSuitLabel }}</span>
</div>
<div class="floating-status left">
<img v-if="floatingMissingSuit.left" :src="floatingMissingSuit.left" alt=""/>
<span>{{ seatDecor.left.missingSuitLabel }}</span>
</div>
<div class="floating-status right">
<img v-if="floatingMissingSuit.right" :src="floatingMissingSuit.right" alt=""/>
<span>{{ seatDecor.right.missingSuitLabel }}</span>
</div>
<!-- <div class="floating-status top">-->
<!-- <img v-if="floatingMissingSuit.top" :src="floatingMissingSuit.top" alt=""/>-->
<!-- <span>{{ seatDecor.top.missingSuitLabel }}</span>-->
<!-- </div>-->
<!-- <div class="floating-status left">-->
<!-- <img v-if="floatingMissingSuit.left" :src="floatingMissingSuit.left" alt=""/>-->
<!-- <span>{{ seatDecor.left.missingSuitLabel }}</span>-->
<!-- </div>-->
<!-- <div class="floating-status right">-->
<!-- <img v-if="floatingMissingSuit.right" :src="floatingMissingSuit.right" alt=""/>-->
<!-- <span>{{ seatDecor.right.missingSuitLabel }}</span>-->
<!-- </div>-->
<WindSquare class="center-wind-square" :seat-winds="seatWinds"/>