You've already forked agentic-coding-workflow
feat(web): router with auth guard, AppShell, login + home views
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
<template>
|
||||
<AppShell>
|
||||
<div class="space-y-4">
|
||||
<h2 class="text-xl font-semibold">欢迎,{{ auth.user?.display_name }}</h2>
|
||||
<p>这是占位 dashboard。后续 plan 会接入项目/工作区/Issue。</p>
|
||||
</div>
|
||||
</AppShell>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import AppShell from '@/layouts/AppShell.vue'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
const auth = useAuthStore()
|
||||
</script>
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user