feat(web): router with auth guard, AppShell, login + home views

This commit is contained in:
2026-04-29 10:02:45 +08:00
parent 3eb595cf5e
commit 9d93bcd24b
8 changed files with 181 additions and 4 deletions
+51
View File
@@ -0,0 +1,51 @@
<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" block>
登录
</NButton>
</NForm>
<p v-if="error" class="text-red-500 text-sm">{{ error }}</p>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } 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 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 next = (router.currentRoute.value.query.next as string) || '/'
await router.replace(next)
} catch (e) {
error.value = e instanceof ApiException ? e.body.message : '登录失败'
} finally {
loading.value = false
}
}
</script>