初始提交:彩票推测系统前端代码
This commit is contained in:
447
src/views/admin/AdminLogin.vue
Normal file
447
src/views/admin/AdminLogin.vue
Normal file
@@ -0,0 +1,447 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user