8959456eb7
- 修复 AuthLoader 组件中 router.push 在渲染期间调用的 React 警告
- 追问问题改为只在最新 AI 回复下方显示(修复多处显示问题)
- 新增 LLM 生成追问 API:POST /api/v1/apps/{id}/suggestions
- 前端调用 LLM API 生成智能追问,失败时降级到规则生成
- 登录页填入默认测试账号 kj-admin@govai.gov.cn
76 lines
2.2 KiB
TypeScript
76 lines
2.2 KiB
TypeScript
"use client";
|
|
|
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
import { useRef, useEffect } from "react";
|
|
import { useRouter, usePathname } from "next/navigation";
|
|
import { useAuthStore } from "@/stores/auth";
|
|
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
|
|
// 公开路由(无需鉴权)
|
|
const PUBLIC_PATHS = ["/login", "/register"];
|
|
|
|
function AuthLoader({ children }: { children: React.ReactNode }) {
|
|
const fetchUser = useAuthStore((s) => s.fetchUser);
|
|
const isLoading = useAuthStore((s) => s.isLoading);
|
|
const isAuthenticated = useAuthStore((s) => s.isAuthenticated);
|
|
const router = useRouter();
|
|
const pathname = usePathname();
|
|
|
|
const isPublic = PUBLIC_PATHS.some((p) => pathname === p || pathname.startsWith(p + "/"));
|
|
|
|
useEffect(() => {
|
|
if (!isPublic) {
|
|
fetchUser();
|
|
}
|
|
}, [fetchUser, isPublic]);
|
|
|
|
// 鉴权路由:未登录则跳转(useEffect 中执行,避免渲染期间调用 router)
|
|
useEffect(() => {
|
|
if (!isLoading && !isAuthenticated && !isPublic) {
|
|
router.push("/login");
|
|
}
|
|
}, [isLoading, isAuthenticated, isPublic, router]);
|
|
|
|
// 公开路由:直接渲染,不阻塞
|
|
if (isPublic) {
|
|
return <>{children}</>;
|
|
}
|
|
|
|
// 加载中或未认证
|
|
if (isLoading || !isAuthenticated) {
|
|
return (
|
|
<div className="flex h-screen items-center justify-center">
|
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return <>{children}</>;
|
|
}
|
|
|
|
export function Providers({ children }: { children: React.ReactNode }) {
|
|
const queryClientRef = useRef<QueryClient>(null);
|
|
if (!queryClientRef.current) {
|
|
queryClientRef.current = new QueryClient({
|
|
defaultOptions: {
|
|
queries: {
|
|
// 高频变更数据(审计、用户列表)
|
|
staleTime: 30 * 1000,
|
|
gcTime: 5 * 60 * 1000,
|
|
refetchOnWindowFocus: false,
|
|
retry: 1,
|
|
refetchOnMount: "always",
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
return (
|
|
<QueryClientProvider client={queryClientRef.current}>
|
|
<TooltipProvider>
|
|
<AuthLoader>{children}</AuthLoader>
|
|
</TooltipProvider>
|
|
</QueryClientProvider>
|
|
);
|
|
}
|