Files
TERES_web_frontend/src/pages/Home.tsx
guangfei.zhao 5f93573e57 feat: implement RAG dashboard with MUI and react-router
Add new RAG dashboard feature including:
- Main application layout with header and sidebar
- Multiple pages (Home, KnowledgeBase, PipelineConfig, Dashboard, MCP)
- Theme configuration and styling
- Routing setup with protected routes
- Login page and authentication flow
- Various UI components and mock data for dashboard views
2025-10-09 17:23:15 +08:00

218 lines
6.6 KiB
TypeScript

import {
Box,
Button,
Card,
CardContent,
Grid,
LinearProgress,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Typography,
styled
} from '@mui/material';
const StyledCard = styled(Card)({
height: '100%',
display: 'flex',
flexDirection: 'column',
boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
borderRadius: '8px',
});
const CardTitle = styled(Typography)({
fontSize: '1rem',
fontWeight: 'bold',
marginBottom: '16px',
});
const MetricsContainer = styled(Box)({
display: 'flex',
justifyContent: 'space-between',
marginBottom: '16px',
});
const Metric = styled(Box)({
display: 'flex',
flexDirection: 'column',
});
const MetricValue = styled(Typography)({
fontSize: '1.5rem',
fontWeight: 'bold',
});
const MetricLabel = styled(Typography)({
fontSize: '0.75rem',
color: '#666',
});
const ProgressContainer = styled(Box)({
marginBottom: '16px',
});
const ProgressLabel = styled(Box)({
display: 'flex',
justifyContent: 'space-between',
fontSize: '0.65rem',
marginBottom: '4px',
});
const StyledLinearProgress = styled(LinearProgress)({
height: '8px',
borderRadius: '4px',
});
const StatusPill = styled(Box)<{ status?: string }>(({ status }) => ({
display: 'inline-block',
padding: '4px 8px',
borderRadius: '12px',
fontSize: '0.65rem',
fontWeight: 'bold',
backgroundColor: status === 'OK' ? '#e6f7ed' : '#ffebee',
color: status === 'OK' ? '#00a389' : '#d32f2f',
}));
const InlineNote = styled('span')({
fontSize: '0.75rem',
color: '#666',
fontWeight: 'normal',
marginLeft: '4px',
});
// 模拟数据
const recentQueries = [
{ query: 'How to reset device firmware?', latency: 732, source: 'manual.pdf', time: '09:21', status: 'OK' },
{ query: 'List authentication failure codes', latency: 801, source: 'auth_guide.html', time: '09:18', status: 'OK' },
{ query: 'Can we purge stale vectors?', latency: 915, source: 'system_kb', time: '09:10', status: 'OK' },
{ query: 'Explain retrieval scoring logic', latency: 845, source: 'design_notes', time: '08:57', status: 'OK' },
{ query: 'Pipeline concurrency limits?', latency: 1042, source: 'ops_doc', time: '08:43', status: 'OK' },
];
const Home = () => {
return (
<Box>
<Grid container spacing={3}>
{/* Knowledge Base Status Card */}
<Grid size={{ xs: 12, md: 6, lg: 4 }}>
<StyledCard>
<CardContent>
<CardTitle>Knowledge Base Status</CardTitle>
<MetricsContainer>
<Metric>
<MetricLabel>Documents</MetricLabel>
<MetricValue>4,218</MetricValue>
</Metric>
<Metric>
<MetricLabel>Sources</MetricLabel>
<MetricValue>17</MetricValue>
</Metric>
<Metric>
<MetricLabel>Vectors</MetricLabel>
<MetricValue>1.2M</MetricValue>
</Metric>
</MetricsContainer>
<ProgressContainer>
<ProgressLabel>
<span>Sync Progress</span>
<span>62%</span>
</ProgressLabel>
<StyledLinearProgress variant="determinate" value={62} />
</ProgressContainer>
<Button
variant="contained"
fullWidth
sx={{
backgroundColor: '#1a1a2e',
'&:hover': { backgroundColor: '#2a2a3e' }
}}
>
Create New Knowledge Base
</Button>
</CardContent>
</StyledCard>
</Grid>
{/* Recent Activity Card */}
<Grid size={{ xs: 12, md: 6, lg: 4 }}>
<StyledCard>
<CardContent>
<CardTitle>
Recent Activity <InlineNote>(latest 24h)</InlineNote>
</CardTitle>
<Box sx={{ fontSize: '0.7rem', lineHeight: 1.8 }}>
<Box>152 user queries processed</Box>
<Box>87 new documents ingested</Box>
<Box>4 pipeline adjustments</Box>
</Box>
<Box sx={{ marginTop: 'auto', fontSize: '0.65rem', opacity: 0.75, mt: 2 }}>
Latency stable at p95 820ms
</Box>
</CardContent>
</StyledCard>
</Grid>
{/* Model Overview Card */}
<Grid size={{ xs: 12, md: 6, lg: 4 }}>
<StyledCard>
<CardContent>
<CardTitle>Model Overview</CardTitle>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: '0.4rem', fontSize: '0.7rem' }}>
<Box>Embedding Model: <strong>text-embedding-3-large</strong></Box>
<Box>Generator: <strong>gpt-4o-mini</strong></Box>
<Box>Reranker: <strong>cross-encoder-v2</strong></Box>
<Box>Chunking: 512 tokens</Box>
<Box>Retriever Top-K: 8</Box>
</Box>
<StatusPill status="OK" sx={{ mt: 1 }}>Healthy</StatusPill>
</CardContent>
</StyledCard>
</Grid>
{/* Recent RAG Queries Table */}
<Grid size={12}>
<StyledCard>
<CardContent>
<CardTitle>
Recent RAG Queries <InlineNote>(latest 5)</InlineNote>
</CardTitle>
<TableContainer>
<Table size="small">
<TableHead>
<TableRow>
<TableCell>Query</TableCell>
<TableCell>Latency (ms)</TableCell>
<TableCell>Source</TableCell>
<TableCell>Time</TableCell>
<TableCell>Status</TableCell>
</TableRow>
</TableHead>
<TableBody>
{recentQueries.map((row, index) => (
<TableRow key={index}>
<TableCell>{row.query}</TableCell>
<TableCell>{row.latency}</TableCell>
<TableCell>{row.source}</TableCell>
<TableCell>{row.time}</TableCell>
<TableCell>
<StatusPill status={row.status}>{row.status}</StatusPill>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</CardContent>
</StyledCard>
</Grid>
</Grid>
</Box>
);
};
export default Home;