Files
ssh-manager/frontend/src/views/LoginView.vue

89 lines
3.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { useAuthStore } from '../stores/auth'
import * as authApi from '../api/auth'
import { LogIn } from 'lucide-vue-next'
const router = useRouter()
const authStore = useAuthStore()
const username = ref('')
const password = ref('')
const error = ref('')
const loading = ref(false)
async function handleSubmit() {
error.value = ''
loading.value = true
try {
const res = await authApi.login({ username: username.value, password: password.value })
authStore.setAuth(res.data.token, res.data.username, res.data.displayName)
router.push('/connections')
} catch (e: unknown) {
const err = e as { response?: { data?: { message?: string }; status?: number } }
error.value = err.response?.data?.message || (err.response?.status === 401 ? '用户名或密码错误' : '登录失败')
} finally {
loading.value = false
}
}
</script>
<template>
<div class="min-h-screen flex items-center justify-center bg-slate-900 px-4">
<div class="w-full max-w-md">
<div class="bg-slate-800 rounded-xl shadow-xl border border-slate-700 p-8">
<div class="flex items-center gap-2 mb-6">
<div class="w-10 h-10 rounded-lg bg-cyan-600 flex items-center justify-center">
<LogIn class="w-6 h-6 text-white" aria-hidden="true" />
</div>
<h1 class="text-xl font-semibold text-slate-100">SSH 管理器</h1>
</div>
<h2 class="text-lg text-slate-300 mb-6">登录您的账户</h2>
<form @submit.prevent="handleSubmit" class="space-y-4">
<div>
<label for="username" class="block text-sm font-medium text-slate-300 mb-1">
用户名
</label>
<input
id="username"
v-model="username"
type="text"
required
autocomplete="username"
class="w-full px-4 py-2.5 rounded-lg bg-slate-700 border border-slate-600 text-slate-100 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-cyan-500 focus:border-transparent transition-colors duration-200"
placeholder="admin"
/>
</div>
<div>
<label for="password" class="block text-sm font-medium text-slate-300 mb-1">
密码
</label>
<input
id="password"
v-model="password"
type="password"
required
autocomplete="current-password"
class="w-full px-4 py-2.5 rounded-lg bg-slate-700 border border-slate-600 text-slate-100 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-cyan-500 focus:border-transparent transition-colors duration-200"
placeholder="••••••••"
/>
</div>
<p v-if="error" class="text-sm text-red-400">{{ error }}</p>
<button
type="submit"
:disabled="loading"
class="w-full py-2.5 px-4 rounded-lg bg-cyan-600 hover:bg-cyan-500 text-white font-medium transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer focus:outline-none focus:ring-2 focus:ring-cyan-500 focus:ring-offset-2 focus:ring-offset-slate-800"
>
{{ loading ? '登录中...' : '登录' }}
</button>
</form>
<p class="mt-4 text-sm text-slate-500">
默认admin / admin123
</p>
</div>
</div>
</div>
</template>