```
feat(game): update websocket URL configuration and improve game room logic - Change VITE_GAME_WS_URL from /api/v1/ws to /ws in .env.development - Update proxy configuration in vite.config.ts to match new websocket path - Refactor leave room functionality to properly disconnect websocket and destroy room state - Add e2e testing script to package.json ```
This commit is contained in:
@@ -101,64 +101,62 @@ const wallBacks = computed<Record<SeatKey, string[]>>(() => {
|
||||
const seatDecor = computed<Record<SeatKey, SeatPlayerCardModel>>(() => {
|
||||
const scoreMap = roomState.value.game?.state?.scores ?? {}
|
||||
const dealerIndex = roomState.value.game?.state?.dealerIndex ?? -1
|
||||
const emptyLabel = missingSuitLabel(null)
|
||||
const defaultMissingSuitLabel = missingSuitLabel(null)
|
||||
|
||||
return seatViews.value.reduce(
|
||||
(acc, seat, index) => {
|
||||
const playerId = seat.player?.playerId ?? ''
|
||||
const score = playerId ? scoreMap[playerId] : undefined
|
||||
const emptySeat = (avatar: string): SeatPlayerCardModel => ({
|
||||
avatar,
|
||||
name: '空位',
|
||||
money: '--',
|
||||
dealer: false,
|
||||
isTurn: false,
|
||||
isOnline: false,
|
||||
missingSuitLabel: defaultMissingSuitLabel,
|
||||
})
|
||||
|
||||
acc[seat.key] = {
|
||||
avatar: seat.isSelf ? '我' : String(index + 1),
|
||||
name: seat.player ? (seat.isSelf ? '你' : playerId) : '空位',
|
||||
money: typeof score === 'number' ? `${score}` : '--',
|
||||
dealer: seat.player?.index === dealerIndex,
|
||||
isTurn: seat.isTurn,
|
||||
isOnline: Boolean(seat.player),
|
||||
missingSuitLabel: emptyLabel,
|
||||
}
|
||||
const result: Record<SeatKey, SeatPlayerCardModel> = {
|
||||
top: emptySeat('1'),
|
||||
right: emptySeat('2'),
|
||||
bottom: emptySeat('我'),
|
||||
left: emptySeat('4'),
|
||||
}
|
||||
|
||||
return acc
|
||||
},
|
||||
{
|
||||
top: {
|
||||
avatar: '1',
|
||||
name: '空位',
|
||||
money: '--',
|
||||
dealer: false,
|
||||
isTurn: false,
|
||||
isOnline: false,
|
||||
missingSuitLabel: emptyLabel,
|
||||
},
|
||||
right: {
|
||||
avatar: '2',
|
||||
name: '空位',
|
||||
money: '--',
|
||||
dealer: false,
|
||||
isTurn: false,
|
||||
isOnline: false,
|
||||
missingSuitLabel: emptyLabel,
|
||||
},
|
||||
bottom: {
|
||||
avatar: '我',
|
||||
name: '空位',
|
||||
money: '--',
|
||||
dealer: false,
|
||||
isTurn: false,
|
||||
isOnline: false,
|
||||
missingSuitLabel: emptyLabel,
|
||||
},
|
||||
left: {
|
||||
avatar: '4',
|
||||
name: '空位',
|
||||
money: '--',
|
||||
dealer: false,
|
||||
isTurn: false,
|
||||
isOnline: false,
|
||||
missingSuitLabel: emptyLabel,
|
||||
},
|
||||
},
|
||||
)
|
||||
for (const [index, seat] of seatViews.value.entries()) {
|
||||
if (!seat.player) {
|
||||
continue
|
||||
}
|
||||
|
||||
const playerId = seat.player.playerId
|
||||
const score = scoreMap[playerId]
|
||||
result[seat.key] = {
|
||||
avatar: seat.isSelf ? '我' : String(index + 1),
|
||||
name: seat.isSelf ? '你自己' : playerId,
|
||||
money: typeof score === 'number' ? String(score) : '--',
|
||||
dealer: seat.player.index === dealerIndex,
|
||||
isTurn: seat.isTurn,
|
||||
isOnline: true,
|
||||
missingSuitLabel: defaultMissingSuitLabel,
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
})
|
||||
|
||||
const seatMarkers = computed(() => {
|
||||
const seatTitleMap: Record<SeatKey, string> = {
|
||||
top: '上家',
|
||||
right: '右家',
|
||||
bottom: '本家',
|
||||
left: '左家',
|
||||
}
|
||||
|
||||
return seatViews.value.map((seat) => ({
|
||||
key: seat.key,
|
||||
occupied: Boolean(seat.player),
|
||||
isSelf: seat.isSelf,
|
||||
isTurn: seat.isTurn,
|
||||
label: seat.player ? seatTitleMap[seat.key] : '空位',
|
||||
subLabel: seat.player ? `座位 ${seat.player.index}` : '',
|
||||
}))
|
||||
})
|
||||
|
||||
const centerTimer = computed(() => {
|
||||
@@ -174,7 +172,7 @@ const centerTimer = computed(() => {
|
||||
|
||||
function missingSuitLabel(value: string | null | undefined): string {
|
||||
if (!value) {
|
||||
return '待定'
|
||||
return '未定'
|
||||
}
|
||||
|
||||
const suitMap: Record<string, string> = {
|
||||
@@ -231,6 +229,7 @@ onBeforeUnmount(() => {
|
||||
<p class="game-subtitle">{{ roomStatusText }} · {{ currentPhaseText }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="topbar-right">
|
||||
<div class="status-chip net-chip">
|
||||
<span class="wifi-dot" :class="`is-${wsStatus}`"></span>
|
||||
@@ -249,7 +248,7 @@ onBeforeUnmount(() => {
|
||||
<strong>{{ roomState.name || roomName || '未命名房间' }}</strong>
|
||||
</span>
|
||||
<span class="room-brief-item room-brief-id">
|
||||
<em>room_id:</em>
|
||||
<em>room_id:</em>
|
||||
<strong>{{ roomId || '未选择房间' }}</strong>
|
||||
</span>
|
||||
<span class="room-brief-item">
|
||||
@@ -276,6 +275,7 @@ onBeforeUnmount(() => {
|
||||
<div class="table-felt">
|
||||
<div class="felt-frame outer"></div>
|
||||
<div class="felt-frame inner"></div>
|
||||
|
||||
<div class="table-watermark">
|
||||
<span>{{ statusRibbon }}</span>
|
||||
<strong>指尖四川麻将</strong>
|
||||
@@ -307,19 +307,21 @@ onBeforeUnmount(() => {
|
||||
<span class="wind east">东</span>
|
||||
<strong>{{ centerTimer }}</strong>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-for="seat in seatViews"
|
||||
v-for="seat in seatMarkers"
|
||||
:key="seat.key"
|
||||
class="seat"
|
||||
:class="[
|
||||
`seat-${seat.key}`,
|
||||
{ occupied: Boolean(seat.player), 'seat-me': seat.isSelf, 'seat-turn': seat.isTurn },
|
||||
{ occupied: seat.occupied, 'seat-me': seat.isSelf, 'seat-turn': seat.isTurn },
|
||||
]"
|
||||
>
|
||||
<strong>{{ seat.label }}</strong>
|
||||
<small v-if="seat.subLabel">{{ seat.subLabel }}</small>
|
||||
<span v-if="seat.isTurn" class="turn-indicator">出牌中</span>
|
||||
</div>
|
||||
|
||||
<div class="table-center">
|
||||
<p>成都麻将</p>
|
||||
<p>{{ roomState.id || roomId || '等待中...' }}</p>
|
||||
@@ -330,7 +332,7 @@ onBeforeUnmount(() => {
|
||||
<div class="ws-panel-head">
|
||||
<strong>实时消息</strong>
|
||||
<div class="ws-actions">
|
||||
<span class="ws-state" :class="`is-${wsStatus}`">{{ wsStatus }}</span>
|
||||
<span class="ws-state" :class="`is-${wsStatus}`">{{ networkLabel }}</span>
|
||||
<button class="ghost-btn ws-reconnect" type="button" @click="connectWs">重连</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user