- 实现 ChengduGamePage.vue 组件,包含完整的麻将游戏界面 - 实现 HallPage.vue 组件,支持房间列表展示、创建和加入功能 - 添加 mahjong API 接口用于房间管理操作 - 集成 store 状态管理和本地存储功能 - 实现 ChengduBottomActions 等游戏控制组件 - 添加 websocket 连接和游戏会话管理逻辑 - 实现游戏倒计时、结算等功能模块
113 lines
3.4 KiB
Vue
113 lines
3.4 KiB
Vue
<script setup lang="ts">
|
|
import type { ActionCountdownView } from '../../views/chengdu/types'
|
|
|
|
defineProps<{
|
|
leaveRoomPending: boolean
|
|
menuOpen: boolean
|
|
menuTriggerActive: boolean
|
|
isTrustMode: boolean
|
|
wallCount: number
|
|
networkLabel: string
|
|
wsStatus: string
|
|
formattedClock: string
|
|
roomName: string
|
|
currentPhaseText: string
|
|
playerCount: number
|
|
maxPlayers: number
|
|
roundText: string
|
|
roomStatusText: string
|
|
wsError: string
|
|
actionCountdown: ActionCountdownView | null
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
toggleMenu: []
|
|
toggleTrustMode: []
|
|
leaveRoom: []
|
|
}>()
|
|
</script>
|
|
|
|
<template>
|
|
<div class="top-left-tools">
|
|
<div class="menu-trigger-wrap">
|
|
<button
|
|
class="metal-circle menu-trigger"
|
|
:class="{ 'is-feedback': menuTriggerActive }"
|
|
type="button"
|
|
:disabled="leaveRoomPending"
|
|
@click.stop="emit('toggleMenu')"
|
|
>
|
|
<span class="menu-trigger-icon">☰</span>
|
|
</button>
|
|
<transition name="menu-pop">
|
|
<div v-if="menuOpen" class="menu-popover" @click.stop>
|
|
<div class="menu-list">
|
|
<button class="menu-item menu-item-delay-1" type="button" @click="emit('toggleTrustMode')">
|
|
<slot name="robot-icon" />
|
|
<span>{{ isTrustMode ? '取消托管' : '托管' }}</span>
|
|
</button>
|
|
<button
|
|
class="menu-item menu-item-danger menu-item-delay-2"
|
|
type="button"
|
|
:disabled="leaveRoomPending"
|
|
@click="emit('leaveRoom')"
|
|
>
|
|
<slot name="exit-icon" />
|
|
<span>{{ leaveRoomPending ? '退出中...' : '退出' }}</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</transition>
|
|
</div>
|
|
<div class="left-counter">
|
|
<span class="counter-light"></span>
|
|
<strong>{{ wallCount }}</strong>
|
|
</div>
|
|
<span v-if="isTrustMode" class="trust-chip">托管中</span>
|
|
</div>
|
|
|
|
<div class="top-right-clock">
|
|
<div class="signal-chip">
|
|
<span class="wifi-dot" :class="`is-${wsStatus}`"></span>
|
|
<strong>{{ networkLabel }}</strong>
|
|
</div>
|
|
<span>{{ formattedClock }}</span>
|
|
</div>
|
|
|
|
<div class="room-status-panel">
|
|
<div class="room-status-grid">
|
|
<div class="room-status-item">
|
|
<span>房间</span>
|
|
<strong>{{ roomName || '未命名' }}</strong>
|
|
</div>
|
|
<div class="room-status-item">
|
|
<span>阶段</span>
|
|
<strong>{{ currentPhaseText }}</strong>
|
|
</div>
|
|
<div class="room-status-item">
|
|
<span>人数</span>
|
|
<strong>{{ playerCount }}/{{ maxPlayers }}</strong>
|
|
</div>
|
|
<div v-if="roundText" class="room-status-item">
|
|
<span>局数</span>
|
|
<strong>{{ roundText }}</strong>
|
|
</div>
|
|
<div class="room-status-item">
|
|
<span>状态</span>
|
|
<strong>{{ roomStatusText }}</strong>
|
|
</div>
|
|
</div>
|
|
<p v-if="wsError" class="room-status-error">{{ wsError }}</p>
|
|
</div>
|
|
|
|
<div v-if="actionCountdown" class="action-countdown" :class="{ 'is-self': actionCountdown.isSelf }">
|
|
<div class="action-countdown-head">
|
|
<span>{{ actionCountdown.playerLabel }}操作倒计时</span>
|
|
<strong>{{ actionCountdown.remaining }}s</strong>
|
|
</div>
|
|
<div class="action-countdown-track">
|
|
<span class="action-countdown-fill" :style="{ width: `${actionCountdown.progress}%` }"></span>
|
|
</div>
|
|
</div>
|
|
</template>
|