feat(frontend): add frontend-v2 modular architecture (Task 17)

- React 19 + TypeScript + Vite
- Module registration mechanism with dynamic loading
- Permission management system (basic/advanced/premium)
- Route guards for access control
- Error boundaries for module isolation
- 6 business module placeholders (AIA/ASL/PKB/DC/SSA/ST)
- Top navigation layout
- Tailwind CSS 3 + Ant Design 5
This commit is contained in:
2025-11-16 15:43:17 +08:00
parent 5579ffa78e
commit 11325f88a7
39 changed files with 8051 additions and 0 deletions

View File

@@ -0,0 +1,215 @@
import { ErrorInfo } from 'react'
import { Result, Button, Collapse, Typography } from 'antd'
import { BugOutlined, ReloadOutlined, HomeOutlined } from '@ant-design/icons'
import { useNavigate } from 'react-router-dom'
/**
* 模块错误提示组件
*
* @description
* 当模块加载或运行出错时显示的友好错误页面
* 提供重试和返回首页的操作
*
* @version Week 2 Day 7 - 任务17
*/
const { Paragraph, Text } = Typography
interface ModuleErrorFallbackProps {
/** 错误对象 */
error: Error | null
/** 错误详细信息 */
errorInfo?: ErrorInfo | null
/** 重置错误状态的回调 */
onReset?: () => void
/** 模块名称 */
moduleName?: string
}
const ModuleErrorFallback = ({
error,
errorInfo,
onReset,
moduleName,
}: ModuleErrorFallbackProps) => {
const navigate = useNavigate()
// 是否显示详细错误信息(开发环境显示,生产环境隐藏)
const isDevelopment = import.meta.env?.DEV ?? false
/**
* 处理重试
*/
const handleRetry = () => {
if (onReset) {
onReset()
} else {
// 如果没有提供onReset刷新页面
window.location.reload()
}
}
/**
* 返回首页
*/
const handleGoHome = () => {
navigate('/')
}
return (
<div className="flex-1 flex items-center justify-center bg-gray-50 p-8">
<div className="max-w-2xl w-full">
<Result
status="error"
icon={<BugOutlined style={{ fontSize: 72, color: '#ff4d4f' }} />}
title={
<span className="text-2xl">
{moduleName ? `${moduleName}模块` : '页面'}
</span>
}
subTitle={
<div className="space-y-3 mt-4">
<Paragraph className="text-gray-600">
</Paragraph>
<Paragraph className="text-gray-500 text-sm">
</Paragraph>
</div>
}
extra={
<div className="flex gap-3 justify-center">
<Button
type="primary"
icon={<ReloadOutlined />}
onClick={handleRetry}
size="large"
>
</Button>
<Button
icon={<HomeOutlined />}
onClick={handleGoHome}
size="large"
>
</Button>
</div>
}
/>
{/* 开发环境:显示详细错误信息 */}
{isDevelopment && error && (
<div className="mt-8">
<Collapse
ghost
items={[
{
key: 'error-details',
label: (
<Text type="secondary" className="text-sm">
🔧
</Text>
),
children: (
<div className="space-y-4">
{/* 错误消息 */}
<div>
<Text strong className="text-red-600"></Text>
<Paragraph
code
copyable
className="mt-2 bg-red-50 p-3 rounded"
>
{error.toString()}
</Paragraph>
</div>
{/* 错误堆栈 */}
{error.stack && (
<div>
<Text strong className="text-red-600"></Text>
<Paragraph
code
copyable
className="mt-2 bg-gray-50 p-3 rounded text-xs overflow-x-auto"
style={{ whiteSpace: 'pre-wrap' }}
>
{error.stack}
</Paragraph>
</div>
)}
{/* 组件堆栈 */}
{errorInfo?.componentStack && (
<div>
<Text strong className="text-red-600"></Text>
<Paragraph
code
copyable
className="mt-2 bg-gray-50 p-3 rounded text-xs overflow-x-auto"
style={{ whiteSpace: 'pre-wrap' }}
>
{errorInfo.componentStack}
</Paragraph>
</div>
)}
{/* 时间戳 */}
<div>
<Text type="secondary" className="text-xs">
{new Date().toLocaleString('zh-CN')}
</Text>
</div>
</div>
),
},
]}
/>
</div>
)}
{/* 生产环境错误ID提示 */}
{!isDevelopment && (
<div className="mt-6 text-center">
<Text type="secondary" className="text-xs">
ID: {Date.now().toString(36)}
</Text>
<br />
<Text type="secondary" className="text-xs">
ID
</Text>
</div>
)}
</div>
</div>
)
}
export default ModuleErrorFallback
/**
* 🎨 设计说明:
*
* 1. 用户体验:
* - ✅ 友好的错误提示(不显示技术术语)
* - ✅ 明确的操作指引(重试/返回首页)
* - ✅ 视觉上与整体风格一致Ant Design Result
*
* 2. 开发体验:
* - ✅ 开发环境显示详细错误(方便调试)
* - ✅ 错误信息可复制(方便分享给团队)
* - ✅ 显示完整堆栈(快速定位问题)
*
* 3. 生产环境:
* - ✅ 隐藏技术细节(安全性)
* - ✅ 提供错误ID方便追踪
* - ✅ 引导用户联系支持
*
* 4. 后续优化:
* - [ ] 添加"反馈问题"按钮
* - [ ] 集成错误报告系统
* - [ ] 记录用户操作路径
* - [ ] 自动重试机制(网络错误)
*/