Files
CloudSearch/packages/frontend/src/pages/admin/AdminLogin.vue

170 lines
4.4 KiB
Vue
Executable File
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="admin-login-page">
<div class="login-bg-pattern"></div>
<div class="login-card">
<div class="login-brand">
<div class="login-logo"></div>
<h1 class="login-title">{{ siteName || 'CloudSearch' }}</h1>
<p class="login-subtitle">管理后台</p>
</div>
<el-form ref="formRef" :model="form" :rules="rules" label-width="0" size="large" @keyup.enter="handleLogin">
<el-form-item prop="username">
<el-input v-model="form.username" placeholder="用户名" prefix-icon="User" />
</el-form-item>
<el-form-item prop="password">
<el-input v-model="form.password" type="password" placeholder="密码" prefix-icon="Lock" show-password />
</el-form-item>
<el-form-item>
<el-button type="primary" :loading="loading" class="login-btn" @click="handleLogin">
{{ loading ? '登录中...' : ' ' }}
</el-button>
</el-form-item>
</el-form>
<p v-if="errorMsg" class="error-msg">{{ errorMsg }}</p>
<p class="login-footer">CloudSearch v{{ appVersion }}</p>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { User, Lock } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { getSiteConfig, adminLogin } from '../../api'
import type { ElForm } from 'element-plus'
const formRef = ref<InstanceType<typeof ElForm>>()
const loading = ref(false)
const errorMsg = ref('')
const siteName = ref('')
const appVersion = ref('')
getSiteConfig().then(cfg => {
if (cfg.site_name) siteName.value = cfg.site_name
}).catch(() => {})
const form = reactive({
username: '',
password: '',
})
const rules = {
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
}
async function handleLogin() {
const valid = await formRef.value?.validate().catch(() => false)
if (!valid) return
loading.value = true
errorMsg.value = ''
try {
const res = await adminLogin(form.username, form.password)
localStorage.setItem('admin_token', res.token)
ElMessage.success('登录成功')
window.location.href = '/admin'
} catch (e: any) {
errorMsg.value = e?.response?.data?.message || e?.message || '登录失败'
} finally {
loading.value = false
}
}
onMounted(async () => {
try {
const h = await fetch('/health')
const hv = await h.json()
appVersion.value = hv.version || ''
} catch {}
})
</script>
<style scoped>
.admin-login-page {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%);
position: relative;
overflow: hidden;
}
.login-bg-pattern {
position: absolute;
inset: 0;
background:
radial-gradient(circle at 20% 50%, rgba(102, 126, 234, 0.12) 0%, transparent 50%),
radial-gradient(circle at 80% 30%, rgba(118, 75, 162, 0.12) 0%, transparent 50%),
radial-gradient(circle at 50% 80%, rgba(64, 158, 255, 0.08) 0%, transparent 50%);
}
.login-card {
position: relative;
width: 400px;
padding: 48px 40px 36px;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(20px);
border-radius: var(--radius-xl);
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.25);
}
.login-brand {
text-align: center;
margin-bottom: 36px;
}
.login-logo {
font-size: 48px;
margin-bottom: 8px;
line-height: 1;
}
.login-title {
font-size: 26px;
font-weight: 800;
color: #1d2129;
margin: 0 0 4px;
letter-spacing: 1px;
}
.login-subtitle {
font-size: 14px;
color: #86909c;
margin: 0;
letter-spacing: 2px;
}
.login-btn {
width: 100%;
height: 44px;
font-size: 15px;
letter-spacing: 4px;
border-radius: var(--radius-md);
}
.error-msg {
text-align: center;
color: #f56c6c;
font-size: 13px;
margin-top: 12px;
padding: 8px 12px;
background: #fef0f0;
border-radius: var(--radius-sm);
line-height: 1.4;
}
.login-footer {
text-align: center;
color: #c9cdd4;
font-size: 11px;
margin-top: 20px;
margin-bottom: 0;
}
[data-theme="dark"] .login-card {
background: rgba(29, 29, 29, 0.95);
}
[data-theme="dark"] .login-title {
color: #e5e5e5;
}
[data-theme="dark"] .login-subtitle {
color: #666666;
}
[data-theme="dark"] .error-msg {
background: rgba(245, 108, 108, 0.12);
}
</style>