feat(game): 添加定缺功能支持
- 在游戏页面添加 dingQuePending 状态管理 - 实现 showDingQueChooser 计算属性控制定缺选择器显示 - 添加 chooseDingQue 函数处理定缺选择逻辑 - 集成 WebSocket 消息发送定缺选择结果 - 更新底部控制面板添加定缺选择按钮界面 - 添加相应的 CSS 样式支持定缺选择器布局和交互 - 修复房间状态更新时重置定缺待处理状态
This commit is contained in:
@@ -896,11 +896,57 @@
|
||||
}
|
||||
|
||||
.bottom-action-bar {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
justify-content: flex-end;
|
||||
min-height: 56px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.ding-que-bar {
|
||||
position: absolute;
|
||||
right: 150px;
|
||||
top: -90px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.ding-que-button {
|
||||
min-width: 64px;
|
||||
height: 46px;
|
||||
border: 1px solid rgba(220, 191, 118, 0.24);
|
||||
border-radius: 999px;
|
||||
color: #e5c472;
|
||||
font-size: 16px;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.5px;
|
||||
background:
|
||||
linear-gradient(180deg, rgba(14, 55, 40, 0.92), rgba(8, 36, 27, 0.96)),
|
||||
radial-gradient(circle at 20% 24%, rgba(237, 214, 157, 0.08), transparent 34%);
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 244, 214, 0.1),
|
||||
inset 0 -1px 0 rgba(0, 0, 0, 0.22),
|
||||
0 8px 18px rgba(0, 0, 0, 0.2);
|
||||
text-shadow:
|
||||
-1px 0 rgba(0, 0, 0, 0.38),
|
||||
0 1px rgba(0, 0, 0, 0.38),
|
||||
1px 0 rgba(0, 0, 0, 0.38),
|
||||
0 -1px rgba(0, 0, 0, 0.38);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ding-que-button:active {
|
||||
transform: translateY(1px) scale(0.96);
|
||||
}
|
||||
|
||||
.ding-que-button:disabled {
|
||||
opacity: 0.56;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.control-copy {
|
||||
margin-bottom: 10px;
|
||||
text-align: center;
|
||||
|
||||
@@ -80,6 +80,7 @@ const wsError = ref('')
|
||||
const leaveRoomPending = ref(false)
|
||||
const readyTogglePending = ref(false)
|
||||
const startGamePending = ref(false)
|
||||
const dingQuePending = ref(false)
|
||||
let clockTimer: number | null = null
|
||||
let unsubscribe: (() => void) | null = null
|
||||
let pendingRoomInfoRequest = false
|
||||
@@ -345,6 +346,19 @@ const showReadyToggle = computed(() => {
|
||||
return true
|
||||
})
|
||||
|
||||
const showDingQueChooser = computed(() => {
|
||||
const player = myPlayer.value
|
||||
if (!player) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (gameStore.phase === 'waiting' || gameStore.phase === 'settlement') {
|
||||
return false
|
||||
}
|
||||
|
||||
return player.handTiles.length > 0 && !player.missingSuit
|
||||
})
|
||||
|
||||
function applyPlayerReadyState(playerId: string, ready: boolean): void {
|
||||
const player = gameStore.players[playerId]
|
||||
if (player) {
|
||||
@@ -796,6 +810,7 @@ function handleRoomInfoResponse(message: unknown): void {
|
||||
gameStore.roomId = roomId
|
||||
if (Object.keys(nextPlayers).length > 0) {
|
||||
gameStore.players = nextPlayers
|
||||
dingQuePending.value = false
|
||||
}
|
||||
|
||||
const phaseMap: Record<string, typeof gameStore.phase> = {
|
||||
@@ -1115,6 +1130,7 @@ function handlePlayerHandResponse(message: unknown): void {
|
||||
existingPlayer.handTiles = handTiles
|
||||
existingPlayer.handCount = handTiles.length
|
||||
}
|
||||
dingQuePending.value = false
|
||||
|
||||
const room = activeRoom.value
|
||||
if (room && room.roomId === (roomId || gameStore.roomId)) {
|
||||
@@ -1455,6 +1471,21 @@ function startGame(): void {
|
||||
})
|
||||
}
|
||||
|
||||
function chooseDingQue(suit: Tile['suit']): void {
|
||||
if (dingQuePending.value || !showDingQueChooser.value) {
|
||||
return
|
||||
}
|
||||
|
||||
dingQuePending.value = true
|
||||
sendWsMessage({
|
||||
type: 'ding_que',
|
||||
roomId: gameStore.roomId,
|
||||
payload: {
|
||||
suit,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function handleLeaveRoom(): void {
|
||||
menuOpen.value = false
|
||||
backHall()
|
||||
@@ -1763,7 +1794,34 @@ onBeforeUnmount(() => {
|
||||
|
||||
|
||||
<div class="bottom-control-panel">
|
||||
<div v-if="showReadyToggle || showStartGameButton" class="bottom-action-bar">
|
||||
<div v-if="showDingQueChooser || showReadyToggle || showStartGameButton" class="bottom-action-bar">
|
||||
<div v-if="showDingQueChooser" class="ding-que-bar">
|
||||
<button
|
||||
class="ding-que-button"
|
||||
type="button"
|
||||
:disabled="dingQuePending"
|
||||
@click="chooseDingQue('W')"
|
||||
>
|
||||
万
|
||||
</button>
|
||||
<button
|
||||
class="ding-que-button"
|
||||
type="button"
|
||||
:disabled="dingQuePending"
|
||||
@click="chooseDingQue('T')"
|
||||
>
|
||||
筒
|
||||
</button>
|
||||
<button
|
||||
class="ding-que-button"
|
||||
type="button"
|
||||
:disabled="dingQuePending"
|
||||
@click="chooseDingQue('B')"
|
||||
>
|
||||
条
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button
|
||||
v-if="showReadyToggle"
|
||||
class="ready-toggle ready-toggle-inline"
|
||||
|
||||
Reference in New Issue
Block a user