2026-01-31 16:48:20 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<div class="login-container">
|
|
|
|
|
|
<div class="login-card">
|
|
|
|
|
|
<!-- 标题 -->
|
|
|
|
|
|
<div class="login-header">
|
|
|
|
|
|
<h2>盘古用户平台</h2>
|
|
|
|
|
|
<p>统一用户管理系统</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 登录表单 -->
|
|
|
|
|
|
<el-form ref="loginFormRef" :model="loginForm" :rules="loginRules" class="login-form">
|
|
|
|
|
|
<el-form-item prop="username">
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="loginForm.username"
|
|
|
|
|
|
placeholder="请输入用户名"
|
|
|
|
|
|
:prefix-icon="User"
|
|
|
|
|
|
size="large"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
<el-form-item prop="password">
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="loginForm.password"
|
|
|
|
|
|
type="password"
|
|
|
|
|
|
placeholder="请输入密码"
|
|
|
|
|
|
:prefix-icon="Lock"
|
|
|
|
|
|
size="large"
|
|
|
|
|
|
show-password
|
|
|
|
|
|
@keyup.enter="handleLogin"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
<el-form-item prop="code">
|
|
|
|
|
|
<div class="captcha-row">
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="loginForm.code"
|
|
|
|
|
|
placeholder="请输入验证码"
|
|
|
|
|
|
:prefix-icon="Picture"
|
|
|
|
|
|
size="large"
|
|
|
|
|
|
style="flex: 1"
|
|
|
|
|
|
@keyup.enter="handleLogin"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<img
|
|
|
|
|
|
:src="captchaImg"
|
|
|
|
|
|
class="captcha-img"
|
|
|
|
|
|
@click="getCaptcha"
|
|
|
|
|
|
title="点击刷新验证码"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
<el-form-item>
|
|
|
|
|
|
<el-checkbox v-model="loginForm.rememberMe">记住密码</el-checkbox>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
<el-form-item>
|
|
|
|
|
|
<el-button
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
size="large"
|
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
|
:loading="loading"
|
|
|
|
|
|
@click="handleLogin"
|
|
|
|
|
|
>
|
|
|
|
|
|
登录
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 提示 -->
|
|
|
|
|
|
<div class="login-tip">
|
|
|
|
|
|
默认账号: admin / admin123
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 登录页面(占位,Agent-2会完善)
|
2026-01-31 23:14:11 +08:00
|
|
|
|
* @author pangu
|
2026-01-31 16:48:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
import { useUserStore } from '@/store/user'
|
|
|
|
|
|
import request from '@/utils/request'
|
|
|
|
|
|
import { Lock, Picture, User } from '@element-plus/icons-vue'
|
|
|
|
|
|
import { ElMessage } from 'element-plus'
|
|
|
|
|
|
import { onMounted, ref } from 'vue'
|
|
|
|
|
|
import { useRouter } from 'vue-router'
|
|
|
|
|
|
|
|
|
|
|
|
const router = useRouter()
|
|
|
|
|
|
const userStore = useUserStore()
|
|
|
|
|
|
|
|
|
|
|
|
const loginFormRef = ref()
|
|
|
|
|
|
const loading = ref(false)
|
|
|
|
|
|
const captchaImg = ref('')
|
|
|
|
|
|
const uuid = ref('')
|
|
|
|
|
|
|
|
|
|
|
|
const loginForm = ref({
|
|
|
|
|
|
username: 'admin',
|
|
|
|
|
|
password: 'admin123',
|
|
|
|
|
|
code: '',
|
|
|
|
|
|
rememberMe: false
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const loginRules = {
|
|
|
|
|
|
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
|
|
|
|
|
|
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
|
2026-02-01 12:13:25 +08:00
|
|
|
|
code: [{ required: false, message: '请输入验证码', trigger: 'blur' }]
|
2026-01-31 16:48:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取验证码
|
|
|
|
|
|
const getCaptcha = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await request.get('/api/captchaImage')
|
|
|
|
|
|
if (res.code === 200) {
|
2026-02-01 12:13:25 +08:00
|
|
|
|
captchaImg.value = res.data.img
|
|
|
|
|
|
uuid.value = res.data.uuid
|
|
|
|
|
|
// 如果验证码未启用,设置验证规则为非必填
|
|
|
|
|
|
if (!res.data.captchaEnabled) {
|
|
|
|
|
|
loginRules.code[0].required = false
|
|
|
|
|
|
}
|
2026-01-31 16:48:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('获取验证码失败:', error)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 登录
|
|
|
|
|
|
const handleLogin = () => {
|
|
|
|
|
|
loginFormRef.value?.validate(async (valid) => {
|
|
|
|
|
|
if (!valid) return
|
|
|
|
|
|
|
|
|
|
|
|
loading.value = true
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await request.post('/api/login', {
|
|
|
|
|
|
username: loginForm.value.username,
|
|
|
|
|
|
password: loginForm.value.password,
|
|
|
|
|
|
code: loginForm.value.code,
|
|
|
|
|
|
uuid: uuid.value
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
|
userStore.setToken(res.token)
|
|
|
|
|
|
ElMessage.success('登录成功')
|
|
|
|
|
|
router.push('/')
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
// 登录失败刷新验证码
|
|
|
|
|
|
getCaptcha()
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
loading.value = false
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
getCaptcha()
|
|
|
|
|
|
})
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
.login-container {
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.login-card {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
max-width: 400px;
|
|
|
|
|
|
padding: 40px;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.login-header {
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
margin-bottom: 32px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.login-header h2 {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
font-size: 28px;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.login-header p {
|
|
|
|
|
|
margin: 8px 0 0;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #909399;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.login-form {
|
|
|
|
|
|
margin-top: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.captcha-row {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.captcha-img {
|
|
|
|
|
|
width: 100px;
|
|
|
|
|
|
height: 40px;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
border: 1px solid #dcdfe6;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.login-tip {
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: #909399;
|
|
|
|
|
|
margin-top: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|