Files
webgame-frontend/src/components/baseLayouts/CreateRoomDialog.vue
2026-06-22 09:28:15 +08:00

187 lines
4.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<el-dialog
v-model="visible"
:title="dialogTitle"
width="420px"
:close-on-click-modal="false"
@closed="handleClosed"
>
<el-form
ref="formRef"
:model="form"
:rules="rules"
label-width="72px"
label-position="left"
@submit.prevent="handleSubmit"
>
<!-- 房间名称可选 -->
<el-form-item label="房间名" prop="name">
<el-input
v-model="form.name"
placeholder="留空自动生成桌号"
maxlength="20"
show-word-limit
clearable
/>
<div class="create-room-dialog__hint">留空将自动生成"桌 XX"编号</div>
</el-form-item>
<!-- 游戏模式 -->
<el-form-item label="模式" prop="mode">
<el-select v-model="form.mode" placeholder="请选择模式">
<el-option v-for="m in gameConfig?.modes ?? []" :key="m" :label="m" :value="m" />
</el-select>
</el-form-item>
<!-- 底注金额 -->
<el-form-item label="底注" prop="stakes">
<el-select v-model="form.stakes" placeholder="请选择底注">
<el-option
v-for="s in gameConfig?.stakesOptions ?? []"
:key="s"
:label="`${s} 金币`"
:value="s"
/>
</el-select>
</el-form-item>
<!-- 房间密码可选 -->
<el-form-item label="密码" prop="password">
<el-input
v-model="form.password"
type="password"
placeholder="留空为公开房间"
maxlength="16"
show-password
clearable
/>
<div class="create-room-dialog__hint">设置密码后其他玩家需输入密码才能加入</div>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" :loading="submitting" @click="handleSubmit"> 确认创建 </el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import { useBaseLayoutStore } from '@/stores'
import { storeToRefs } from 'pinia'
import type { GameConfig } from '@/api/modules/game'
import { createRoom } from '@/api/modules/game'
/** 创建房间表单数据 */
interface CreateRoomForm {
name: string
mode: string
stakes: number | undefined
password: string
}
const props = defineProps<{
modelValue: boolean
}>()
const emit = defineEmits<{
(e: 'update:modelValue', value: boolean): void
(e: 'created'): void
}>()
const baseLayoutStore = useBaseLayoutStore()
const { activeGameName, activeGameConfig } = storeToRefs(baseLayoutStore)
const formRef = ref<FormInstance>()
const submitting = ref(false)
/** 对话框可见性(双向绑定) */
const visible = computed({
get: () => props.modelValue,
set: (val: boolean) => emit('update:modelValue', val)
})
/** 对话框标题 */
const dialogTitle = computed(() => `创建房间 — ${activeGameName.value}`)
/** 当前游戏配置(只读) */
const gameConfig = computed<GameConfig | null>(() => activeGameConfig.value)
/** 表单数据 */
const form = reactive<CreateRoomForm>({
name: '',
mode: '',
stakes: undefined,
password: ''
})
/** 初始化默认值:取当前游戏配置的第一个选项 */
function initDefaults() {
if (gameConfig.value) {
form.mode = gameConfig.value.modes[0] ?? ''
form.stakes = gameConfig.value.stakesOptions[0]
}
form.name = ''
form.password = ''
}
/** 弹窗打开时设置默认值 */
watch(
() => props.modelValue,
(val) => {
if (val) initDefaults()
}
)
/** 切换游戏时重置默认值 */
watch(activeGameConfig, () => {
if (props.modelValue) initDefaults()
})
const rules: FormRules = {
mode: [{ required: true, message: '请选择游戏模式', trigger: 'change' }],
stakes: [{ required: true, message: '请选择底注金额', trigger: 'change' }],
name: [{ max: 20, message: '房间名不超过 20 个字符', trigger: 'blur' }],
password: [{ max: 16, message: '密码不超过 16 个字符', trigger: 'blur' }]
}
/** 提交创建房间 */
async function handleSubmit() {
const valid = await formRef.value?.validate().catch(() => false)
if (!valid) return
submitting.value = true
try {
await createRoom({
gameId: baseLayoutStore.activeGameId,
name: form.name.trim() || undefined,
password: form.password || undefined,
mode: form.mode,
stakes: form.stakes!,
maxPlayers: gameConfig.value?.maxPlayers ?? 0
})
visible.value = false
emit('created')
} finally {
submitting.value = false
}
}
/** 弹窗关闭动画结束后重置表单 */
function handleClosed() {
initDefaults()
formRef.value?.resetFields()
}
</script>
<style scoped lang="scss">
.create-room-dialog__hint {
font-size: 12px;
color: var(--text-tertiary);
margin-top: 4px;
line-height: 1.4;
}
</style>