Files
agentic-coding-workflow/web/src/views/auth/LoginView.vue
T
2026-06-12 14:01:55 +08:00

76 lines
2.0 KiB
Vue

<template>
<div class="min-h-screen flex items-center justify-center p-4">
<div class="w-full max-w-sm space-y-4">
<h1 class="text-2xl font-semibold">
登录
</h1>
<NForm @submit.prevent="onSubmit">
<NFormItem label="邮箱">
<NInput
v-model:value="email"
placeholder="admin@local"
/>
</NFormItem>
<NFormItem label="密码">
<NInput
v-model:value="password"
type="password"
show-password-on="click"
/>
</NFormItem>
<NButton
type="primary"
attr-type="submit"
:loading="loading"
:disabled="!isValid"
block
>
登录
</NButton>
</NForm>
<p
v-if="error"
class="text-red-500 text-sm"
>
{{ error }}
</p>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { NForm, NFormItem, NInput, NButton } from 'naive-ui'
import { useRouter } from 'vue-router'
import { authApi } from '@/api/auth'
import { useAuthStore } from '@/stores/auth'
import { ApiException } from '@/api/types'
const email = ref('')
const password = ref('')
const loading = ref(false)
const error = ref('')
const isValid = computed(() => email.value.trim().length > 0 && password.value.length > 0)
const auth = useAuthStore()
const router = useRouter()
async function onSubmit() {
loading.value = true
error.value = ''
try {
const out = await authApi.login(email.value, password.value)
auth.setSession(out.token, out.user)
const raw = router.currentRoute.value.query.next
const next =
typeof raw === 'string' && raw.startsWith('/') && !raw.startsWith('//') ? raw : '/'
await router.replace(next).catch(() => {})
} catch (e) {
error.value = e instanceof ApiException ? e.body.message : '登录失败'
} finally {
loading.value = false
}
}
</script>