feat: 全站 PageShell 设计系统与专业 UI 统一

- 新增 PageShell/PageTabs/ContentPanel/PageLoading/PageEmpty 页面骨架
- index.css 设计令牌文档化,布局令牌与纯色主按钮(去除渐变粉彩)
- 全站路由页接入 PageShell,云账单三 Tab 为标杆
- 主题体系:跟随系统 + 主流/开发者分组,新增 Dracula/Tokyo Night,One Dark 暖灰差异化
- 登录页/侧栏/顶栏去渐变光球,企业克制风
- 修复 AIAlertAnalyzer JSX 与构建依赖导入问题
This commit is contained in:
Logan committed 2026-07-01 12:45:38 +08:00
1 parent 1acb0c49af
commit e363ded445
213 files changed
+7148 -6818

No files matched your search

@@ -31,12 +31,14 @@ import {
import {
Select, SelectContent, SelectItem, SelectTrigger, SelectValue
} from '@/components/ui/select';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Label } from '@/components/ui/label';
import { Separator } from '@/components/ui/separator';
import { ScrollArea } from '@/components/ui/scroll-area';
import { toast } from 'sonner';
import { traceApi } from '@/api';
import { PageShell } from '@/components/layout/PageShell';
import { PageLoading } from '@/components/layout/PageLoading';
import { PageEmpty } from '@/components/layout/PageEmpty';
import type { JsonData } from '@/types/common';
interface Trace {
@@ -162,7 +164,7 @@ const TraceManager: React.FC = () => {
case 'success': return 'bg-green-500';
case 'error': return 'bg-red-500';
case 'pending': return 'bg-yellow-500';
default: return 'bg-gray-500';
default: return 'bg-[var(--dg-bg-active)]';
}
};
@@ -257,28 +259,14 @@ const TraceManager: React.FC = () => {
);
};
return (
<div className="space-y-6">
{/* 统计卡片 */}
<StatStrip
items={[
{ label: '总请求', value: services.reduce((sum, s) => sum + s.requestCount, 0).toLocaleString(), color: 'blue' },
{ label: '错误率', value: `${(services.reduce((sum, s) => sum + s.errorRate, 0) / (services.length || 1)).toFixed(2)}%`, color: 'red' },
{ label: '平均延迟', value: formatDuration(services.reduce((sum, s) => sum + s.avgDuration, 0) / (services.length || 1)), color: 'amber' },
{ label: '服务数', value: services.length, color: 'purple' },
]}
/>
const pageTabs = [
{ id: 'traces', label: '链路追踪' },
{ id: 'services', label: '服务拓扑' },
{ id: 'metrics', label: '性能指标' },
];
<Tabs value={activeTab} onValueChange={setActiveTab}>
<TabsList className="grid w-full grid-cols-3 lg:w-[400px]">
<TabsTrigger value="traces">链路追踪</TabsTrigger>
<TabsTrigger value="services">服务拓扑</TabsTrigger>
<TabsTrigger value="metrics">性能指标</TabsTrigger>
</TabsList>
<TabsContent value="traces" className="space-y-4">
{/* 查询工具栏 */}
<div className="flex flex-wrap items-center justify-between gap-4">
const tracesToolbar = activeTab === 'traces' ? (
<div className="flex flex-wrap items-center justify-between gap-4 w-full">
<div className="flex items-center gap-2 flex-1 min-w-[400px]">
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
@@ -324,16 +312,44 @@ const TraceManager: React.FC = () => {
</SelectContent>
</Select>
</div>
<div className="flex items-center gap-2">
<Button variant="outline" onClick={fetchTraces}>
<RefreshCw className="w-4 h-4 mr-2" />
刷新
</Button>
</div>
</div>
<div className="flex items-center gap-2">
<Button variant="outline" className="dg-btn-secondary" onClick={fetchTraces}>
<RefreshCw className="w-4 h-4 mr-2" />
刷新
</Button>
</div>
</div>
) : undefined;
{/* Trace列表 */}
<Card>
return (
<PageShell
variant="list"
title="链路追踪"
subtitle="分布式链路查询与服务性能分析"
icon={<GitBranch className="h-5 w-5" />}
tabs={pageTabs}
activeTab={activeTab}
onTabChange={setActiveTab}
toolbar={tracesToolbar}
metrics={(
<StatStrip
items={[
{ label: '总请求', value: services.reduce((sum, s) => sum + s.requestCount, 0).toLocaleString(), color: 'blue' },
{ label: '错误率', value: `${(services.reduce((sum, s) => sum + s.errorRate, 0) / (services.length || 1)).toFixed(2)}%`, color: 'red' },
{ label: '平均延迟', value: formatDuration(services.reduce((sum, s) => sum + s.avgDuration, 0) / (services.length || 1)), color: 'amber' },
{ label: '服务数', value: services.length, color: 'purple' },
]}
/>
)}
actions={activeTab === 'traces' ? undefined : (
<Button variant="outline" className="dg-btn-secondary" onClick={fetchData}>
<RefreshCw className="w-4 h-4 mr-2" />
刷新
</Button>
)}
>
{activeTab === 'traces' && (
<Card>
<CardContent className="p-0">
<div className="overflow-x-auto">
<table className="w-full">
@@ -351,17 +367,17 @@ const TraceManager: React.FC = () => {
<tbody className="divide-y">
{loading ? (
<tr>
<td colSpan={7} className="px-4 py-8 text-center text-muted-foreground">加载中...</td>
<td colSpan={7} className="px-4 py-2"><PageLoading label="加载链路数据..." /></td>
</tr>
) : filteredTraces.length === 0 ? (
<tr>
<td colSpan={7} className="px-4 py-8 text-center text-muted-foreground">暂无链路数据</td>
<td colSpan={7} className="px-4 py-2"><PageEmpty title="暂无链路数据" className="py-8" /></td>
</tr>
) : (
filteredTraces.map((trace) => (
<tr key={trace.id} className="hover:bg-muted/50">
<td className="px-4 py-3">
<span className="font-mono text-sm text-blue-500">{trace.traceId.slice(0, 16)}...</span>
<span className="font-mono text-sm dg-text-blue">{trace.traceId.slice(0, 16)}...</span>
</td>
<td className="px-4 py-3">
<div className="font-medium">{trace.operationName}</div>
@@ -394,9 +410,9 @@ const TraceManager: React.FC = () => {
</div>
</CardContent>
</Card>
</TabsContent>
)}
<TabsContent value="services" className="space-y-4">
{activeTab === 'services' && (
<Card>
<CardHeader>
<CardTitle>服务性能概览</CardTitle>
@@ -420,7 +436,7 @@ const TraceManager: React.FC = () => {
<td className="px-4 py-3 font-medium">{service.serviceName}</td>
<td className="px-4 py-3">{service.requestCount.toLocaleString()}</td>
<td className="px-4 py-3">
<span className={service.errorRate > 1 ? 'text-red-500' : 'text-green-500'}>
<span className={service.errorRate > 1 ? 'text-red-500' : 'dg-text-green'}>
{service.errorRate.toFixed(2)}%
</span>
</td>
@@ -434,9 +450,9 @@ const TraceManager: React.FC = () => {
</div>
</CardContent>
</Card>
</TabsContent>
)}
<TabsContent value="metrics" className="space-y-4">
{activeTab === 'metrics' && (
<div className="grid grid-cols-2 gap-4">
<Card>
<CardHeader>
@@ -457,8 +473,7 @@ const TraceManager: React.FC = () => {
</CardContent>
</Card>
</div>
</TabsContent>
</Tabs>
)}
{/* Trace详情对话框 */}
<Dialog open={traceDetailOpen} onOpenChange={setTraceDetailOpen}>
@@ -580,7 +595,7 @@ const TraceManager: React.FC = () => {
)}
</DialogContent>
</Dialog>
</div>
</PageShell>
);
};