优化
This commit is contained in:
@@ -9,7 +9,12 @@
|
||||
"mcp__server-mysql__execute",
|
||||
"Bash(git rm:*)",
|
||||
"Bash(git add:*)",
|
||||
"Bash(npx tsc:*)"
|
||||
"Bash(npx tsc:*)",
|
||||
"Bash(pnpm vue-tsc:*)",
|
||||
"Bash(find node_modules/.pnpm -name *.mjs -path *vue-router*)",
|
||||
"Bash(grep -r \"routeMeta\\\\|definePage\\\\|<route\" node_modules/.pnpm/vue-router*/node_modules/vue-router/dist/*.mjs)",
|
||||
"Bash(grep -r \"route block\\\\|customBlock\\\\|defineCustomBlock\" node_modules/.pnpm/vue-router*/dist/*.mjs)",
|
||||
"Bash(find node_modules/.pnpm -path *vue-router* -name *.mjs)"
|
||||
],
|
||||
"additionalDirectories": [
|
||||
"/Users/sion/Desktop/projects/monisuo/monisuo-admin/.git"
|
||||
|
||||
@@ -19,7 +19,7 @@ export function useAuth() {
|
||||
}
|
||||
|
||||
function toHome() {
|
||||
router.push({ path: '/dashboard' })
|
||||
router.push({ path: '/monisuo/dashboard' })
|
||||
}
|
||||
|
||||
async function login(username: string, password: string) {
|
||||
|
||||
8
monisuo-admin/src/pages/auth.vue
Normal file
8
monisuo-admin/src/pages/auth.vue
Normal file
@@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<router-view />
|
||||
</template>
|
||||
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: false
|
||||
</route>
|
||||
97
monisuo-admin/src/pages/auth/sign-in.vue
Normal file
97
monisuo-admin/src/pages/auth/sign-in.vue
Normal file
@@ -0,0 +1,97 @@
|
||||
<script setup lang="ts">
|
||||
import { Eye, EyeOff, Lock, User } from 'lucide-vue-next'
|
||||
|
||||
import { useAuth } from '@/composables/use-auth'
|
||||
|
||||
const username = ref('')
|
||||
const password = ref('')
|
||||
const showPassword = ref(false)
|
||||
|
||||
const { login, loading, error, isLogin } = useAuth()
|
||||
const router = useRouter()
|
||||
|
||||
// 已登录则跳转首页
|
||||
watchEffect(() => {
|
||||
if (unref(isLogin)) {
|
||||
router.push('/dashboard')
|
||||
}
|
||||
})
|
||||
|
||||
async function handleSubmit() {
|
||||
if (!username.value || !password.value)
|
||||
return
|
||||
await login(username.value, password.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="min-h-screen flex items-center justify-center bg-gradient-to-br from-background to-muted p-4">
|
||||
<UiCard class="w-full max-w-md">
|
||||
<UiCardHeader class="space-y-1 text-center">
|
||||
<div class="flex justify-center mb-4">
|
||||
<div class="size-12 rounded-xl bg-primary flex items-center justify-center">
|
||||
<Lock class="size-6 text-primary-foreground" />
|
||||
</div>
|
||||
</div>
|
||||
<UiCardTitle class="text-2xl font-bold">
|
||||
Monisuo Admin
|
||||
</UiCardTitle>
|
||||
<UiCardDescription>
|
||||
管理员登录
|
||||
</UiCardDescription>
|
||||
</UiCardHeader>
|
||||
<UiCardContent>
|
||||
<form @submit.prevent="handleSubmit" class="space-y-4">
|
||||
<div class="space-y-2">
|
||||
<UiLabel for="username">用户名</UiLabel>
|
||||
<div class="relative">
|
||||
<User class="absolute left-3 top-1/2 -translate-y-1/2 size-4 text-muted-foreground" />
|
||||
<UiInput
|
||||
id="username"
|
||||
v-model="username"
|
||||
type="text"
|
||||
placeholder="请输入用户名"
|
||||
class="pl-9"
|
||||
:disabled="loading"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<UiLabel for="password">密码</UiLabel>
|
||||
<div class="relative">
|
||||
<Lock class="absolute left-3 top-1/2 -translate-y-1/2 size-4 text-muted-foreground" />
|
||||
<UiInput
|
||||
id="password"
|
||||
v-model="password"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
placeholder="请输入密码"
|
||||
class="pl-9 pr-9"
|
||||
:disabled="loading"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground"
|
||||
@click="showPassword = !showPassword"
|
||||
>
|
||||
<Eye v-if="!showPassword" class="size-4" />
|
||||
<EyeOff v-else class="size-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<UiAlert v-if="error" variant="destructive">
|
||||
<UiAlertDescription>{{ error }}</UiAlertDescription>
|
||||
</UiAlert>
|
||||
<UiButton type="submit" class="w-full" :disabled="loading">
|
||||
<UiSpinner v-if="loading" class="size-4 mr-2" />
|
||||
{{ loading ? '登录中...' : '登录' }}
|
||||
</UiButton>
|
||||
</form>
|
||||
</UiCardContent>
|
||||
</UiCard>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: blank
|
||||
</route>
|
||||
@@ -5,33 +5,22 @@ import { storeToRefs } from 'pinia'
|
||||
import pinia from '@/plugins/pinia/setup'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
|
||||
// 需要认证的 Monisuo 路由前缀
|
||||
const MONISUO_AUTH_ROUTES = ['/monisuo/']
|
||||
// 需要认证的路由前缀
|
||||
const AUTH_ROUTES = ['/monisuo/', '/dashboard', '/users', '/tasks', '/settings']
|
||||
|
||||
export function authGuard(router: Router) {
|
||||
router.beforeEach((to, _from) => {
|
||||
const authStore = useAuthStore(pinia)
|
||||
const { isLogin } = storeToRefs(authStore)
|
||||
|
||||
// 检查是否是需要认证的 Monisuo 路由
|
||||
const isMonisuoRoute = MONISUO_AUTH_ROUTES.some(prefix => to.path.startsWith(prefix))
|
||||
// 检查是否是需要认证的路由
|
||||
const needsAuth = to.meta.auth || AUTH_ROUTES.some(prefix => to.path.startsWith(prefix))
|
||||
|
||||
// 如果页面需要登录但用户未登录,重定向到登录页并记录原始目标页面
|
||||
if ((to.meta.auth || isMonisuoRoute) && !unref(isLogin)) {
|
||||
// Monisuo 路由重定向到 Monisuo 登录页
|
||||
if (isMonisuoRoute && to.name !== '/auth/monisuo-sign-in') {
|
||||
return {
|
||||
name: '/auth/monisuo-sign-in',
|
||||
query: { redirect: to.fullPath },
|
||||
}
|
||||
}
|
||||
|
||||
// 其他需要认证的路由重定向到默认登录页
|
||||
if (to.meta.auth && to.name !== '/auth/sign-in') {
|
||||
return {
|
||||
name: '/auth/sign-in',
|
||||
query: { redirect: to.fullPath },
|
||||
}
|
||||
if (needsAuth && !unref(isLogin) && to.name !== '/auth/sign-in') {
|
||||
return {
|
||||
name: '/auth/sign-in',
|
||||
query: { redirect: to.fullPath },
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
27
monisuo-admin/src/types/route-map.d.ts
vendored
27
monisuo-admin/src/types/route-map.d.ts
vendored
@@ -40,6 +40,20 @@ declare module 'vue-router/auto-routes' {
|
||||
{ path: ParamValue<false> },
|
||||
| never
|
||||
>,
|
||||
'/auth': RouteRecordInfo<
|
||||
'/auth',
|
||||
'/auth',
|
||||
Record<never, never>,
|
||||
Record<never, never>,
|
||||
| '/auth/sign-in'
|
||||
>,
|
||||
'/auth/sign-in': RouteRecordInfo<
|
||||
'/auth/sign-in',
|
||||
'/auth/sign-in',
|
||||
Record<never, never>,
|
||||
Record<never, never>,
|
||||
| never
|
||||
>,
|
||||
'/dashboard/': RouteRecordInfo<
|
||||
'/dashboard/',
|
||||
'/dashboard',
|
||||
@@ -128,6 +142,19 @@ declare module 'vue-router/auto-routes' {
|
||||
views:
|
||||
| never
|
||||
}
|
||||
'src/pages/auth.vue': {
|
||||
routes:
|
||||
| '/auth'
|
||||
| '/auth/sign-in'
|
||||
views:
|
||||
| 'default'
|
||||
}
|
||||
'src/pages/auth/sign-in.vue': {
|
||||
routes:
|
||||
| '/auth/sign-in'
|
||||
views:
|
||||
| never
|
||||
}
|
||||
'src/pages/dashboard/index.vue': {
|
||||
routes:
|
||||
| '/dashboard/'
|
||||
|
||||
Reference in New Issue
Block a user