feat: 凭证生成、成本分析、AI问答、前端页面、集成测试与E2E测试
- 后端: 凭证生成引擎、金蝶导出器、凭证模板服务 - 后端: 成本分析服务、AI问答服务 - 后端: 科目映射CRUD API、分析API、QA API - 后端: 集成测试(认证/任务/凭证) 49个测试全部通过 - 前端: 凭证管理、成本分析、导出中心、知识库、系统设置页面 - 前端: AuthGuard认证守卫、Dashboard AI聊天功能 - 前端: Playwright E2E测试 16 passed, 1 skipped - 基础设施: Docker Compose、Nginx反向代理、.env.example - 文档: 用户手册、管理员手册、发布检查清单
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useAuthStore } from "@/lib/stores/auth-store";
|
||||
|
||||
/**
|
||||
* 认证守卫组件
|
||||
* 检查用户是否已登录,未登录时重定向到登录页
|
||||
*/
|
||||
export function AuthGuard({ children }: { children: React.ReactNode }) {
|
||||
const router = useRouter();
|
||||
const { user, token } = useAuthStore();
|
||||
const [checked, setChecked] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// zustand persist 从 localStorage 恢复是异步的,需要等待一帧
|
||||
if (!user || !token) {
|
||||
router.replace("/login");
|
||||
} else {
|
||||
setChecked(true);
|
||||
}
|
||||
}, [user, token, router]);
|
||||
|
||||
if (!checked) {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-background">
|
||||
<div className="flex flex-col items-center gap-3">
|
||||
<svg className="animate-spin w-6 h-6 text-primary" viewBox="0 0 24 24">
|
||||
<circle
|
||||
className="opacity-25"
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
stroke="currentColor"
|
||||
strokeWidth="4"
|
||||
fill="none"
|
||||
/>
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<span className="text-sm text-muted-foreground">加载中...</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return <>{children}</>;
|
||||
}
|
||||
@@ -9,7 +9,11 @@ import {
|
||||
AlertTriangle,
|
||||
Settings,
|
||||
ChevronLeft,
|
||||
ChevronRight
|
||||
ChevronRight,
|
||||
BarChart3,
|
||||
Receipt,
|
||||
Download,
|
||||
BookOpen,
|
||||
} from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useState } from "react";
|
||||
@@ -30,6 +34,26 @@ const navItems = [
|
||||
href: "/exceptions",
|
||||
icon: AlertTriangle
|
||||
},
|
||||
{
|
||||
label: "成本分析",
|
||||
href: "/analysis",
|
||||
icon: BarChart3
|
||||
},
|
||||
{
|
||||
label: "凭证管理",
|
||||
href: "/vouchers",
|
||||
icon: Receipt
|
||||
},
|
||||
{
|
||||
label: "导出中心",
|
||||
href: "/exports",
|
||||
icon: Download
|
||||
},
|
||||
{
|
||||
label: "知识库",
|
||||
href: "/knowledge",
|
||||
icon: BookOpen
|
||||
},
|
||||
{
|
||||
label: "规则设置",
|
||||
href: "/settings/rules",
|
||||
|
||||
Reference in New Issue
Block a user