Files
cpzs-frontend-new/src/views/admin/AdminLogin.vue

447 lines
11 KiB
Vue
Raw Normal View History

<template>
<div class="admin-login">
<div class="login-container">
<!-- 左侧装饰区域 -->
<div class="login-banner">
<div class="banner-content">
<div class="logo">
<img src="/favicon.ico" alt="Logo" />
<h1>彩票推测系统</h1>
</div>
<div class="banner-text">
<h2>后台管理系统</h2>
<p>专业的数据管理与用户服务</p>
</div>
<div class="banner-features">
<div class="feature-item">
<el-icon><User /></el-icon>
<span>用户管理</span>
</div>
<div class="feature-item">
<el-icon><Key /></el-icon>
<span>会员码管理</span>
</div>
<div class="feature-item">
<el-icon><Document /></el-icon>
<span>数据导入</span>
</div>
</div>
</div>
</div>
<!-- 右侧登录表单 -->
<div class="login-form">
<div class="form-container">
<div class="form-header">
<h2>管理员登录</h2>
<p>请输入您的管理员账号和密码</p>
</div>
<!-- 被踢出提示 -->
<el-alert
v-if="showKickedOutAlert"
title="账号已在其他设备登录"
type="warning"
description="为保障账号安全,您的管理员账号已在其他设备登录,当前会话已失效。请重新登录。"
show-icon
:closable="true"
@close="showKickedOutAlert = false"
style="margin-bottom: 20px"
/>
<el-form
ref="loginFormRef"
:model="loginForm"
:rules="loginRules"
class="login-form-content"
@keyup.enter="handleLogin"
>
<el-form-item prop="userAccount">
<el-input
v-model="loginForm.userAccount"
placeholder="请输入管理员账号"
size="large"
clearable
>
<template #prefix>
<el-icon><User /></el-icon>
</template>
</el-input>
</el-form-item>
<el-form-item prop="userPassword">
<el-input
v-model="loginForm.userPassword"
type="password"
placeholder="请输入密码"
size="large"
show-password
clearable
>
<template #prefix>
<el-icon><Lock /></el-icon>
</template>
</el-input>
</el-form-item>
<el-form-item>
<el-button
type="primary"
size="large"
:loading="loading"
class="login-button"
@click="handleLogin"
>
{{ loading ? '登录中...' : '登录' }}
</el-button>
</el-form-item>
</el-form>
<div class="login-tips">
<el-alert
v-if="errorMessage"
:title="errorMessage"
type="error"
:closable="true"
@close="errorMessage = ''"
/>
</div>
<div class="form-footer">
<p>© 2024 彩票推测系统 - 后台管理</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { ref, reactive, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { User, Lock, Key, Document } from '@element-plus/icons-vue'
import { lotteryApi } from '../../api/index.js'
import { userStore } from '../../store/user.js'
export default {
name: 'AdminLogin',
components: {
User,
Lock,
Key,
Document
},
setup() {
const router = useRouter()
const loginFormRef = ref()
const loading = ref(false)
const errorMessage = ref('')
const showKickedOutAlert = ref(false)
const loginForm = reactive({
userAccount: '',
userPassword: ''
})
const loginRules = {
userAccount: [
{ required: true, message: '请输入管理员账号', trigger: 'blur' },
{ min: 3, max: 20, message: '账号长度在 3 到 20 个字符', trigger: 'blur' }
],
userPassword: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, max: 20, message: '密码长度在 6 到 20 个字符', trigger: 'blur' }
]
}
const handleLogin = async () => {
try {
await loginFormRef.value.validate()
loading.value = true
errorMessage.value = ''
// 使用真实的登录接口
const response = await lotteryApi.userLogin(loginForm.userAccount, loginForm.userPassword)
if (response && response.success) {
// 保存用户信息到session存储
userStore.setUserInfo(response.data)
// 获取完整用户信息,检查角色
const userResponse = await lotteryApi.getLoginUser()
if (userResponse && userResponse.success && userResponse.data) {
const userRole = userResponse.data.userRole
// 检查用户角色是否有权限访问后台
if (userRole && userRole !== 'user') {
// 确保将用户角色信息保存到session中
const userData = userResponse.data
userData.userRole = userRole
userStore.setUserInfo(userData)
ElMessage({
type: 'success',
message: '登录成功,欢迎使用后台管理系统'
})
// 跳转到后台管理首页
router.push('/cpzsadmin/dashboard')
} else {
// 无权限访问
errorMessage.value = '您的账号无权限访问后台管理系统'
userStore.adminLogout() // 使用专门的管理员登出方法
}
} else {
errorMessage.value = userResponse?.message || '获取用户信息失败'
userStore.adminLogout() // 使用专门的管理员登出方法
}
} else {
errorMessage.value = response?.message || '登录失败,请检查账号密码'
}
} catch (error) {
console.error('登录失败:', error)
errorMessage.value = error?.response?.data?.message || '登录失败,请重试'
} finally {
loading.value = false
}
}
// 检查是否因为被踢出而跳转到登录页
onMounted(() => {
if (userStore.isKickedOut) {
showKickedOutAlert.value = true
// 显示提示后重置状态
setTimeout(() => {
userStore.resetKickedOutStatus()
}, 500)
}
})
return {
loginFormRef,
loginForm,
loginRules,
loading,
errorMessage,
showKickedOutAlert,
handleLogin
}
}
}
</script>
<style scoped>
.admin-login {
min-height: 100vh;
height: 100vh;
width: 100vw;
background: linear-gradient(135deg, #2563eb 0%, #06b6d4 100%);
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: auto;
}
.login-container {
width: 100%;
max-width: 1200px;
height: 600px;
background: white;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.1);
display: flex;
overflow: hidden;
}
/* 左侧装饰区域 */
.login-banner {
flex: 1;
background: linear-gradient(135deg, #2563eb 0%, #06b6d4 100%);
display: flex;
align-items: center;
justify-content: center;
padding: 40px;
position: relative;
overflow: hidden;
}
.login-banner::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="25" cy="25" r="1" fill="white" opacity="0.1"/><circle cx="75" cy="75" r="1" fill="white" opacity="0.1"/><circle cx="50" cy="10" r="0.5" fill="white" opacity="0.1"/><circle cx="10" cy="60" r="0.5" fill="white" opacity="0.1"/><circle cx="90" cy="40" r="0.5" fill="white" opacity="0.1"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>');
opacity: 0.3;
}
.banner-content {
text-align: center;
color: white;
position: relative;
z-index: 1;
}
.logo {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 30px;
}
.logo img {
width: 48px;
height: 48px;
margin-right: 15px;
}
.logo h1 {
font-size: 28px;
font-weight: 600;
margin: 0;
}
.banner-text h2 {
font-size: 32px;
font-weight: 700;
margin-bottom: 10px;
}
.banner-text p {
font-size: 16px;
opacity: 0.9;
margin-bottom: 40px;
}
.banner-features {
display: flex;
flex-direction: column;
gap: 20px;
}
.feature-item {
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
font-size: 16px;
opacity: 0.9;
}
.feature-item .el-icon {
font-size: 20px;
}
/* 右侧登录表单 */
.login-form {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 40px;
}
.form-container {
width: 100%;
max-width: 400px;
}
.form-header {
text-align: center;
margin-bottom: 40px;
}
.form-header h2 {
font-size: 28px;
font-weight: 600;
color: #333;
margin-bottom: 10px;
}
.form-header p {
color: #666;
font-size: 14px;
}
.login-form-content {
margin-bottom: 30px;
}
.login-button {
width: 100%;
height: 48px;
font-size: 16px;
font-weight: 600;
background: linear-gradient(135deg, #2563eb, #06b6d4);
border: none;
}
.login-button:hover {
background: linear-gradient(135deg, #3b82f6, #22d3ee);
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(6, 182, 212, 0.4);
}
.login-tips {
margin-bottom: 20px;
}
.login-tips p {
margin: 5px 0;
font-size: 14px;
}
.form-footer {
text-align: center;
color: #999;
font-size: 12px;
}
/* 响应式设计 */
@media (max-width: 768px) {
.login-container {
flex-direction: column;
height: auto;
max-width: 400px;
}
.login-banner {
padding: 30px 20px;
}
.banner-text h2 {
font-size: 24px;
}
.login-form {
padding: 30px 20px;
}
}
@media (max-width: 480px) {
.admin-login {
padding: 10px;
}
.login-container {
border-radius: 15px;
}
.logo h1 {
font-size: 20px;
}
.banner-text h2 {
font-size: 20px;
}
}
</style>