Files
number/frontend/src/views/admin/login.vue
2026-03-17 12:09:43 +08:00

173 lines
4.1 KiB
Vue

<template>
<div class="admin-login-page">
<div class="login-container">
<div class="login-card">
<div class="login-header">
<el-icon :size="48" color="#409eff"><Setting /></el-icon>
<h2>管理后台</h2>
<p>OpenClaw Skills 管理系统</p>
</div>
<el-form ref="formRef" :model="form" :rules="rules" @submit.prevent="handleLogin">
<el-form-item prop="username">
<el-input
v-model="form.username"
placeholder="请输入用户名"
size="large"
prefix-icon="User"
/>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="form.password"
type="password"
placeholder="请输入密码"
size="large"
prefix-icon="Lock"
show-password
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
size="large"
:loading="loading"
@click="handleLogin"
style="width: 100%"
>
登录
</el-button>
</el-form-item>
</el-form>
<div class="demo-accounts">
<el-divider>演示账号</el-divider>
<div class="account-list">
<div class="account-item" @click="fillDemo('admin', 'admin123')">
<span>超级管理员</span>
<span>admin / admin123</span>
</div>
<div class="account-item" @click="fillDemo('operator', 'operator123')">
<span>运营管理员</span>
<span>operator / operator123</span>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
import { useRouter } from 'vue-router'
import { useAdminStore } from '@/stores'
import { ElMessage } from 'element-plus'
const router = useRouter()
const adminStore = useAdminStore()
const formRef = ref(null)
const loading = ref(false)
const form = reactive({
username: '',
password: ''
})
const rules = {
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
}
const handleLogin = async () => {
if (!formRef.value) return
await formRef.value.validate(async (valid) => {
if (valid) {
loading.value = true
const result = adminStore.login(form.username, form.password)
loading.value = false
if (result.success) {
sessionStorage.setItem('admin_user', JSON.stringify(result.data))
ElMessage.success('登录成功')
router.push('/admin')
} else {
ElMessage.error(result.message)
}
}
})
}
const fillDemo = (username, password) => {
form.username = username
form.password = password
}
</script>
<style lang="scss" scoped>
.admin-login-page {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #001529 0%, #003a70 100%);
.login-container {
width: 100%;
max-width: 400px;
padding: 20px;
}
.login-card {
background: #fff;
border-radius: 12px;
padding: 40px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
.login-header {
text-align: center;
margin-bottom: 30px;
h2 {
font-size: 24px;
color: #303133;
margin: 16px 0 8px;
}
p {
color: #909399;
}
}
.demo-accounts {
margin-top: 24px;
.account-list {
display: flex;
flex-direction: column;
gap: 8px;
.account-item {
display: flex;
justify-content: space-between;
padding: 12px;
background: #f5f7fa;
border-radius: 6px;
cursor: pointer;
transition: background 0.3s;
&:hover {
background: #e6e8eb;
}
span {
font-size: 13px;
color: #606266;
}
}
}
}
}
}
</style>