diff --git a/web/src/app/layout.tsx b/web/src/app/layout.tsx
index ff1e4814..e541adcf 100644
--- a/web/src/app/layout.tsx
+++ b/web/src/app/layout.tsx
@@ -71,6 +71,7 @@ export function Layout() {
) : (
diff --git a/web/src/app/router.tsx b/web/src/app/router.tsx
index 63ec7c54..50750aed 100644
--- a/web/src/app/router.tsx
+++ b/web/src/app/router.tsx
@@ -42,10 +42,17 @@ const rootRoute = createRootRoute({
component: Layout,
})
-async function requireAuth() {
+function buildReturnTo(location: { pathname: string; searchStr?: string; hash?: string }) {
+ return `${location.pathname}${location.searchStr ?? ''}${location.hash ?? ''}`
+}
+
+async function requireAuth({ location }: { location: { pathname: string; searchStr?: string; hash?: string } }) {
const user = await getCurrentUser()
if (!user) {
- throw redirect({ to: '/login' })
+ throw redirect({
+ to: '/login',
+ search: { returnTo: buildReturnTo(location) },
+ })
}
return { user }
}
@@ -59,12 +66,18 @@ const skillsRoute = createRoute({
const loginRoute = createRoute({
getParentRoute: () => rootRoute,
path: 'login',
+ validateSearch: (search: Record) => ({
+ returnTo: typeof search.returnTo === 'string' ? search.returnTo : '',
+ }),
component: LoginPage,
})
const registerRoute = createRoute({
getParentRoute: () => rootRoute,
path: 'register',
+ validateSearch: (search: Record) => ({
+ returnTo: typeof search.returnTo === 'string' ? search.returnTo : '',
+ }),
component: RegisterPage,
})
@@ -152,8 +165,8 @@ const dashboardReviewDetailRoute = createRoute({
const dashboardPromotionsRoute = createRoute({
getParentRoute: () => rootRoute,
path: 'dashboard/promotions',
- beforeLoad: async () => {
- const { user } = await requireAuth()
+ beforeLoad: async (ctx) => {
+ const { user } = await requireAuth(ctx)
if (!user.platformRoles?.includes('SKILL_ADMIN') && !user.platformRoles?.includes('SUPER_ADMIN')) {
throw redirect({ to: '/dashboard' })
}
@@ -199,8 +212,8 @@ const settingsAccountsRoute = createRoute({
const adminUsersRoute = createRoute({
getParentRoute: () => rootRoute,
path: 'admin/users',
- beforeLoad: async () => {
- const { user } = await requireAuth()
+ beforeLoad: async (ctx) => {
+ const { user } = await requireAuth(ctx)
if (!user.platformRoles?.includes('USER_ADMIN') && !user.platformRoles?.includes('SUPER_ADMIN')) {
throw redirect({ to: '/dashboard' })
}
@@ -212,8 +225,8 @@ const adminUsersRoute = createRoute({
const adminAuditLogRoute = createRoute({
getParentRoute: () => rootRoute,
path: 'admin/audit-log',
- beforeLoad: async () => {
- const { user } = await requireAuth()
+ beforeLoad: async (ctx) => {
+ const { user } = await requireAuth(ctx)
if (!user.platformRoles?.includes('AUDITOR') && !user.platformRoles?.includes('SUPER_ADMIN')) {
throw redirect({ to: '/dashboard' })
}
diff --git a/web/src/pages/login.tsx b/web/src/pages/login.tsx
index 8c639e1c..f4fab058 100644
--- a/web/src/pages/login.tsx
+++ b/web/src/pages/login.tsx
@@ -1,4 +1,4 @@
-import { Link } from '@tanstack/react-router'
+import { Link, useNavigate, useSearch } from '@tanstack/react-router'
import { useState } from 'react'
import { LoginButton } from '@/features/auth/login-button'
import { useLocalLogin } from '@/features/auth/use-local-auth'
@@ -7,15 +7,19 @@ import { Input } from '@/shared/ui/input'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/shared/ui/tabs'
export function LoginPage() {
+ const navigate = useNavigate()
+ const search = useSearch({ from: '/login' })
const loginMutation = useLocalLogin()
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
+ const returnTo = search.returnTo && search.returnTo.startsWith('/') ? search.returnTo : '/dashboard'
+
async function handleSubmit(event: React.FormEvent) {
event.preventDefault()
try {
await loginMutation.mutateAsync({ username, password })
- window.location.href = '/dashboard'
+ await navigate({ to: returnTo })
} catch {
// mutation state drives the error UI
}
@@ -73,7 +77,11 @@ export function LoginPage() {
还没有账号?
{' '}
-
+
立即注册
diff --git a/web/src/pages/register.tsx b/web/src/pages/register.tsx
index 6bb2ba90..c6e79f62 100644
--- a/web/src/pages/register.tsx
+++ b/web/src/pages/register.tsx
@@ -1,4 +1,4 @@
-import { Link } from '@tanstack/react-router'
+import { Link, useNavigate, useSearch } from '@tanstack/react-router'
import { useState } from 'react'
import { LoginButton } from '@/features/auth/login-button'
import { useLocalRegister } from '@/features/auth/use-local-auth'
@@ -8,16 +8,20 @@ import { Input } from '@/shared/ui/input'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/shared/ui/tabs'
export function RegisterPage() {
+ const navigate = useNavigate()
+ const search = useSearch({ from: '/register' })
const registerMutation = useLocalRegister()
const [username, setUsername] = useState('')
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
+ const returnTo = search.returnTo && search.returnTo.startsWith('/') ? search.returnTo : '/dashboard'
+
async function handleSubmit(event: React.FormEvent) {
event.preventDefault()
try {
await registerMutation.mutateAsync({ username, email, password })
- window.location.href = '/dashboard'
+ await navigate({ to: returnTo })
} catch {
// mutation state drives the error UI
}
@@ -80,7 +84,11 @@ export function RegisterPage() {
已有账号?
{' '}
-
+
返回登录
diff --git a/web/src/pages/skill-detail.tsx b/web/src/pages/skill-detail.tsx
index dd201188..1dc4b995 100644
--- a/web/src/pages/skill-detail.tsx
+++ b/web/src/pages/skill-detail.tsx
@@ -1,4 +1,4 @@
-import { useParams, useNavigate } from '@tanstack/react-router'
+import { useParams, useNavigate, useRouterState } from '@tanstack/react-router'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { MarkdownRenderer } from '@/features/skill/markdown-renderer'
import { FileTree } from '@/features/skill/file-tree'
@@ -20,6 +20,7 @@ import {
export function SkillDetailPage() {
const navigate = useNavigate()
+ const location = useRouterState({ select: (s) => s.location })
const queryClient = useQueryClient()
const { namespace, slug } = useParams({ from: '/@$namespace/$slug' })
const { user, hasRole } = useAuth()
@@ -53,7 +54,12 @@ export function SkillDetailPage() {
})
const requireLogin = () => {
- navigate({ to: '/login' })
+ navigate({
+ to: '/login',
+ search: {
+ returnTo: `${location.pathname}${location.searchStr}${location.hash}`,
+ },
+ })
}
if (isLoadingSkill) {