Some checks failed
Deploy / deploy (push) Has been cancelled
Full-stack web application for Telegram management - Frontend: Vue 3 + Vben Admin - Backend: NestJS - Features: User management, group broadcast, statistics 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
143 lines
3.7 KiB
Vue
143 lines
3.7 KiB
Vue
<template>
|
|
<div class="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
|
|
<div class="max-w-md w-full space-y-8">
|
|
<div>
|
|
<h2 class="mt-6 text-center text-3xl font-extrabold text-gray-900">
|
|
{{ t('auth.login') }}
|
|
</h2>
|
|
<p class="mt-2 text-center text-sm text-gray-600">
|
|
Telegram Marketing Agent System
|
|
</p>
|
|
</div>
|
|
|
|
<el-form
|
|
ref="formRef"
|
|
:model="form"
|
|
:rules="rules"
|
|
class="mt-8 space-y-6"
|
|
@submit.prevent="handleSubmit"
|
|
>
|
|
<el-form-item prop="username">
|
|
<el-input
|
|
v-model="form.username"
|
|
:placeholder="t('auth.username')"
|
|
size="large"
|
|
prefix-icon="User"
|
|
/>
|
|
</el-form-item>
|
|
|
|
<el-form-item prop="password">
|
|
<el-input
|
|
v-model="form.password"
|
|
type="password"
|
|
:placeholder="t('auth.password')"
|
|
size="large"
|
|
prefix-icon="Lock"
|
|
show-password
|
|
/>
|
|
</el-form-item>
|
|
|
|
<el-form-item>
|
|
<el-checkbox v-model="form.rememberMe">
|
|
{{ t('auth.rememberMe') }}
|
|
</el-checkbox>
|
|
</el-form-item>
|
|
|
|
<el-form-item>
|
|
<el-button
|
|
type="primary"
|
|
size="large"
|
|
:loading="loading"
|
|
native-type="submit"
|
|
class="w-full"
|
|
>
|
|
{{ t('auth.login') }}
|
|
</el-button>
|
|
</el-form-item>
|
|
|
|
<div class="flex items-center justify-between">
|
|
<router-link
|
|
to="/register"
|
|
class="text-sm text-primary-600 hover:text-primary-500"
|
|
>
|
|
{{ t('auth.register') }}
|
|
</router-link>
|
|
|
|
<a href="#" class="text-sm text-primary-600 hover:text-primary-500">
|
|
{{ t('auth.forgotPassword') }}
|
|
</a>
|
|
</div>
|
|
</el-form>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, reactive } from 'vue'
|
|
import { useRouter, useRoute } from 'vue-router'
|
|
import { useI18n } from 'vue-i18n'
|
|
import { ElMessage } from 'element-plus'
|
|
import { useAuthStore } from '@/stores/auth'
|
|
|
|
const { t } = useI18n()
|
|
const router = useRouter()
|
|
const route = useRoute()
|
|
const authStore = useAuthStore()
|
|
|
|
const formRef = ref()
|
|
const loading = ref(false)
|
|
|
|
const form = reactive({
|
|
username: '',
|
|
password: '',
|
|
rememberMe: false
|
|
})
|
|
|
|
const rules = {
|
|
username: [
|
|
{ required: true, message: 'Please enter username', trigger: 'blur' }
|
|
],
|
|
password: [
|
|
{ required: true, message: 'Please enter password', trigger: 'blur' },
|
|
{ min: 6, message: 'Password must be at least 6 characters', trigger: 'blur' }
|
|
]
|
|
}
|
|
|
|
const handleSubmit = async () => {
|
|
const valid = await formRef.value.validate()
|
|
if (!valid) return
|
|
|
|
loading.value = true
|
|
|
|
try {
|
|
const result = await authStore.login({
|
|
username: form.username,
|
|
password: form.password
|
|
})
|
|
|
|
loading.value = false
|
|
|
|
console.log('Login result:', result)
|
|
|
|
if (result.success) {
|
|
ElMessage.success(t('auth.loginSuccess'))
|
|
const redirect = route.query.redirect || '/'
|
|
console.log('Redirecting to:', redirect)
|
|
|
|
// Add delay to see message
|
|
setTimeout(() => {
|
|
router.push(redirect).catch(err => {
|
|
console.error('Router push error:', err)
|
|
ElMessage.error('Navigation failed: ' + err.message)
|
|
})
|
|
}, 1000)
|
|
} else {
|
|
ElMessage.error(result.message)
|
|
}
|
|
} catch (error) {
|
|
loading.value = false
|
|
console.error('Login error:', error)
|
|
ElMessage.error('Login failed: ' + error.message)
|
|
}
|
|
}
|
|
</script> |