Files
mahjong-web/src/views/LoginPage.vue
wsy182 7751d3b8e3 feat(game): 添加摸牌和碰杠胡操作功能
- 在游戏状态中添加 needDraw 字段用于标识当前回合是否需要摸牌
- 实现 canDrawTile 计算属性控制摸牌按钮的显示和启用状态
- 添加 claimActionPending 状态防止重复提交操作
- 实现 myClaimState、visibleClaimOptions 和 showClaimActions 计算属性
- 添加 submitClaim 方法处理碰/杠/胡/过操作
- 实现 normalizePendingClaim 函数解析服务端推送的声明状态
- 在底部手牌区域将牌图片改为按钮以便点击弃牌
- 添加摸牌按钮和声明操作栏界面元素
- 更新房间创建表单添加局数选择选项
- 添加 E2E 测试文件验证多人房间流程
- 为登录页面输入框和按钮添加 testid 属性便于测试
- 修复 test-results 文件中的失败测试记录
2026-03-29 17:46:34 +08:00

88 lines
2.4 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.
<script setup lang="ts">
import { onMounted, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { login } from '../api/auth'
import { readStoredAuth, saveAuth } from '../utils/auth-storage'
const router = useRouter()
const route = useRoute()
const form = ref({
loginId: '',
password: '',
})
const submitting = ref(false)
const errorMessage = ref('')
watch(
() => route.query.loginId,
(value) => {
if (typeof value === 'string' && value && !form.value.loginId) {
form.value.loginId = value
}
},
{ immediate: true },
)
onMounted(() => {
if (readStoredAuth()) {
void router.replace('/hall')
}
})
async function handleSubmit(): Promise<void> {
errorMessage.value = ''
if (!form.value.loginId.trim() || !form.value.password) {
errorMessage.value = '请输入登录ID和密码'
return
}
submitting.value = true
try {
const result = await login({
loginId: form.value.loginId.trim(),
password: form.value.password,
})
saveAuth(result)
const redirect = typeof route.query.redirect === 'string' ? route.query.redirect : '/hall'
await router.replace(redirect)
} catch (error) {
errorMessage.value = error instanceof Error ? error.message : '登录失败,请稍后重试'
} finally {
submitting.value = false
}
}
</script>
<template>
<section class="auth-page">
<div class="auth-card">
<h1>麻将</h1>
<p class="sub-title">先完成账号登录后续进入大厅创建/加入房间</p>
<div class="mode-tabs">
<button class="tab-btn active" type="button">登录</button>
<button class="tab-btn" type="button" @click="router.push('/register')">注册</button>
</div>
<form class="form" @submit.prevent="handleSubmit">
<label class="field">
<span>登录ID</span>
<input v-model.trim="form.loginId" data-testid="login-id" type="text" placeholder="请输入手机号或账号" />
</label>
<label class="field">
<span>密码</span>
<input v-model="form.password" data-testid="login-password" type="password" placeholder="请输入密码" />
</label>
<button class="primary-btn" data-testid="login-submit" type="submit" :disabled="submitting">
{{ submitting ? '登录中...' : '登录' }}
</button>
</form>
<p v-if="errorMessage" class="message error">{{ errorMessage }}</p>
</div>
</section>
</template>