@szc-ft/mcp-szcd-client 0.35.0 → 0.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/agents/build.js +59 -1
  2. package/agents/platforms.json +7 -0
  3. package/agents/szcd-component-expert.qoder.md +2 -0
  4. package/opencode-extension/opencode.json +9 -0
  5. package/opencode-extension/skills/local-browser-test/SKILL.md +91 -0
  6. package/opencode-extension/skills/local-browser-test/config.example.yaml +51 -0
  7. package/opencode-extension/skills/local-browser-test/lib/api-call-executor.js +251 -0
  8. package/opencode-extension/skills/local-browser-test/lib/browser-engine.js +95 -21
  9. package/opencode-extension/skills/local-browser-test/lib/config-loader.js +104 -0
  10. package/opencode-extension/skills/local-browser-test/lib/console-archiver.js +100 -0
  11. package/opencode-extension/skills/local-browser-test/lib/global-setup.js +72 -0
  12. package/opencode-extension/skills/local-browser-test/lib/har-collector.js +124 -0
  13. package/opencode-extension/skills/local-browser-test/lib/html-reporter.js +248 -0
  14. package/opencode-extension/skills/local-browser-test/lib/projects.js +46 -0
  15. package/opencode-extension/skills/local-browser-test/lib/raw-script-helpers.js +93 -0
  16. package/opencode-extension/skills/local-browser-test/lib/redact.js +94 -0
  17. package/opencode-extension/skills/local-browser-test/lib/report-retain.js +84 -0
  18. package/opencode-extension/skills/local-browser-test/lib/retry-policy.js +160 -0
  19. package/opencode-extension/skills/local-browser-test/lib/storage-state.js +111 -0
  20. package/opencode-extension/skills/local-browser-test/lib/tag-runner.js +103 -0
  21. package/opencode-extension/skills/local-browser-test/lib/test-plan.js +2 -0
  22. package/opencode-extension/skills/local-browser-test/lib/trace-collector.js +94 -0
  23. package/opencode-extension/skills/local-browser-test/lib/trend-aggregator.js +97 -0
  24. package/opencode-extension/skills/local-browser-test/lib/workspace-init.js +178 -0
  25. package/opencode-extension/skills/local-browser-test/local-browser-executor.js +226 -2
  26. package/opencode-extension/skills/local-browser-test/tests/integration/pr-01.test.js +254 -0
  27. package/opencode-extension/skills/local-browser-test/tests/integration/pr-02.test.js +263 -0
  28. package/opencode-extension/skills/local-browser-test/tests/integration/pr-03.test.js +308 -0
  29. package/opencode-extension/skills/local-browser-test/tests/integration/pr-04.test.js +168 -0
  30. package/opencode-extension/skills/local-browser-test/tests/integration/pr-05.test.js +183 -0
  31. package/opencode-extension/skills/local-browser-test/tests/integration/pr-06.test.js +252 -0
  32. package/opencode-extension/skills/local-browser-test/tests/integration/pr-07.test.js +168 -0
  33. package/opencode-extension/skills/local-browser-test/tests/integration/pr-08.test.js +293 -0
  34. package/opencode-extension/skills/shadcn-design-to-code/SKILL.md +352 -0
  35. package/opencode-extension/skills/shadcn-design-to-code/examples/1.1-overview-page.tsx +382 -0
  36. package/opencode-extension/skills/shadcn-design-to-code/references/install-pitfalls.md +526 -0
  37. package/opencode-extension/skills/shadcn-design-to-code/references/layouts.md +551 -0
  38. package/opencode-extension/skills/shadcn-design-to-code/references/sketch-mapping.md +247 -0
  39. package/opencode-extension/skills/shadcn-design-to-code/references/tokens.md +534 -0
  40. package/opencode-extension/skills/szcd-upload-zip/SKILL.md +45 -0
  41. package/package.json +70 -70
  42. package/qwen-extension/qwen-extension.json +10 -1
  43. package/qwen-extension/skills/local-browser-test/SKILL.md +91 -0
  44. package/qwen-extension/skills/local-browser-test/config.example.yaml +51 -0
  45. package/qwen-extension/skills/local-browser-test/lib/api-call-executor.js +251 -0
  46. package/qwen-extension/skills/local-browser-test/lib/browser-engine.js +95 -21
  47. package/qwen-extension/skills/local-browser-test/lib/config-loader.js +104 -0
  48. package/qwen-extension/skills/local-browser-test/lib/console-archiver.js +100 -0
  49. package/qwen-extension/skills/local-browser-test/lib/global-setup.js +72 -0
  50. package/qwen-extension/skills/local-browser-test/lib/har-collector.js +124 -0
  51. package/qwen-extension/skills/local-browser-test/lib/html-reporter.js +248 -0
  52. package/qwen-extension/skills/local-browser-test/lib/projects.js +46 -0
  53. package/qwen-extension/skills/local-browser-test/lib/raw-script-helpers.js +93 -0
  54. package/qwen-extension/skills/local-browser-test/lib/redact.js +94 -0
  55. package/qwen-extension/skills/local-browser-test/lib/report-retain.js +84 -0
  56. package/qwen-extension/skills/local-browser-test/lib/retry-policy.js +160 -0
  57. package/qwen-extension/skills/local-browser-test/lib/storage-state.js +111 -0
  58. package/qwen-extension/skills/local-browser-test/lib/tag-runner.js +103 -0
  59. package/qwen-extension/skills/local-browser-test/lib/test-plan.js +2 -0
  60. package/qwen-extension/skills/local-browser-test/lib/trace-collector.js +94 -0
  61. package/qwen-extension/skills/local-browser-test/lib/trend-aggregator.js +97 -0
  62. package/qwen-extension/skills/local-browser-test/lib/workspace-init.js +178 -0
  63. package/qwen-extension/skills/local-browser-test/local-browser-executor.js +226 -2
  64. package/qwen-extension/skills/local-browser-test/tests/integration/pr-01.test.js +254 -0
  65. package/qwen-extension/skills/local-browser-test/tests/integration/pr-02.test.js +263 -0
  66. package/qwen-extension/skills/local-browser-test/tests/integration/pr-03.test.js +308 -0
  67. package/qwen-extension/skills/local-browser-test/tests/integration/pr-04.test.js +168 -0
  68. package/qwen-extension/skills/local-browser-test/tests/integration/pr-05.test.js +183 -0
  69. package/qwen-extension/skills/local-browser-test/tests/integration/pr-06.test.js +252 -0
  70. package/qwen-extension/skills/local-browser-test/tests/integration/pr-07.test.js +168 -0
  71. package/qwen-extension/skills/local-browser-test/tests/integration/pr-08.test.js +293 -0
  72. package/qwen-extension/skills/shadcn-design-to-code/SKILL.md +352 -0
  73. package/qwen-extension/skills/shadcn-design-to-code/examples/1.1-overview-page.tsx +382 -0
  74. package/qwen-extension/skills/shadcn-design-to-code/references/install-pitfalls.md +526 -0
  75. package/qwen-extension/skills/shadcn-design-to-code/references/layouts.md +551 -0
  76. package/qwen-extension/skills/shadcn-design-to-code/references/sketch-mapping.md +247 -0
  77. package/qwen-extension/skills/shadcn-design-to-code/references/tokens.md +534 -0
  78. package/qwen-extension/skills/szcd-upload-zip/SKILL.md +45 -0
  79. package/scripts/lib/common.js +7 -0
  80. package/standard-skill/local-browser-test/SKILL.md +91 -0
  81. package/standard-skill/local-browser-test/config.example.yaml +51 -0
  82. package/standard-skill/local-browser-test/lib/api-call-executor.js +251 -0
  83. package/standard-skill/local-browser-test/lib/browser-engine.js +95 -21
  84. package/standard-skill/local-browser-test/lib/config-loader.js +104 -0
  85. package/standard-skill/local-browser-test/lib/console-archiver.js +100 -0
  86. package/standard-skill/local-browser-test/lib/global-setup.js +72 -0
  87. package/standard-skill/local-browser-test/lib/har-collector.js +124 -0
  88. package/standard-skill/local-browser-test/lib/html-reporter.js +248 -0
  89. package/standard-skill/local-browser-test/lib/projects.js +46 -0
  90. package/standard-skill/local-browser-test/lib/raw-script-helpers.js +93 -0
  91. package/standard-skill/local-browser-test/lib/redact.js +94 -0
  92. package/standard-skill/local-browser-test/lib/report-retain.js +84 -0
  93. package/standard-skill/local-browser-test/lib/retry-policy.js +160 -0
  94. package/standard-skill/local-browser-test/lib/storage-state.js +111 -0
  95. package/standard-skill/local-browser-test/lib/tag-runner.js +103 -0
  96. package/standard-skill/local-browser-test/lib/test-plan.js +2 -0
  97. package/standard-skill/local-browser-test/lib/trace-collector.js +94 -0
  98. package/standard-skill/local-browser-test/lib/trend-aggregator.js +97 -0
  99. package/standard-skill/local-browser-test/lib/workspace-init.js +178 -0
  100. package/standard-skill/local-browser-test/local-browser-executor.js +226 -2
  101. package/standard-skill/local-browser-test/tests/integration/pr-01.test.js +254 -0
  102. package/standard-skill/local-browser-test/tests/integration/pr-02.test.js +263 -0
  103. package/standard-skill/local-browser-test/tests/integration/pr-03.test.js +308 -0
  104. package/standard-skill/local-browser-test/tests/integration/pr-04.test.js +168 -0
  105. package/standard-skill/local-browser-test/tests/integration/pr-05.test.js +183 -0
  106. package/standard-skill/local-browser-test/tests/integration/pr-06.test.js +252 -0
  107. package/standard-skill/local-browser-test/tests/integration/pr-07.test.js +168 -0
  108. package/standard-skill/local-browser-test/tests/integration/pr-08.test.js +293 -0
  109. package/standard-skill/shadcn-design-to-code/SKILL.md +352 -0
  110. package/standard-skill/shadcn-design-to-code/examples/1.1-overview-page.tsx +382 -0
  111. package/standard-skill/shadcn-design-to-code/references/install-pitfalls.md +526 -0
  112. package/standard-skill/shadcn-design-to-code/references/layouts.md +551 -0
  113. package/standard-skill/shadcn-design-to-code/references/sketch-mapping.md +247 -0
  114. package/standard-skill/shadcn-design-to-code/references/tokens.md +534 -0
  115. package/standard-skill/szcd-upload-zip/SKILL.md +45 -0
  116. package/opencode-extension/skills/local-browser-test/local-browser-executor.cjs +0 -742
  117. package/qwen-extension/skills/local-browser-test/local-browser-executor.cjs +0 -742
@@ -0,0 +1,382 @@
1
+ // 1.1-概览页-目录概览 - shadcn/ui 端到端生成代码骨架
2
+ // 设计稿来源:/scity/zengzhijie/mcp/1.1-概览页-目录概览(2).sketch
3
+ // 布局:L01 sidebar-main + L03 dashboard-grid
4
+ // shadcn 组件来源:npx shadcn@latest add 一次性安装(见 audit-checklist)
5
+
6
+ "use client"
7
+
8
+ import * as React from "react"
9
+ import {
10
+ Sidebar,
11
+ SidebarContent,
12
+ SidebarFooter,
13
+ SidebarGroup,
14
+ SidebarGroupContent,
15
+ SidebarGroupLabel,
16
+ SidebarHeader,
17
+ SidebarInset,
18
+ SidebarMenu,
19
+ SidebarMenuButton,
20
+ SidebarMenuItem,
21
+ SidebarProvider,
22
+ SidebarRail,
23
+ SidebarTrigger,
24
+ } from "@/components/ui/sidebar"
25
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
26
+ import { Button } from "@/components/ui/button"
27
+ import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
28
+ import { Badge } from "@/components/ui/badge"
29
+ import { Separator } from "@/components/ui/separator"
30
+ import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "@/components/ui/breadcrumb"
31
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
32
+ import { ChartContainer, ChartTooltip, ChartTooltipContent, type ChartConfig } from "@/components/ui/chart"
33
+ import { Skeleton } from "@/components/ui/skeleton"
34
+ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"
35
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"
36
+ import { Bell, ChevronDown, Database, FileText, Folder, Home, LayoutDashboard, ListChecks, Search, Settings, User } from "lucide-react"
37
+ import { Line, LineChart, XAxis, YAxis, CartesianGrid, ResponsiveContainer, Bar, BarChart, PieChart, Pie, Cell, Legend } from "recharts"
38
+
39
+ // === 设计 token(从 sketch 提取,HSL 通道) ===
40
+ // globals.css
41
+ // :root {
42
+ // --background: 0 0% 100%;
43
+ // --foreground: 222 47% 11%; /* #0f172a 主文字 */
44
+ // --card: 0 0% 100%;
45
+ // --card-foreground: 222 47% 11%;
46
+ // --primary: 217 91% 60%; /* #3b82f6 品牌主色 */
47
+ // --primary-foreground: 0 0% 100%;
48
+ // --secondary: 210 40% 96%; /* #f1f5f9 */
49
+ // --muted: 210 40% 96%;
50
+ // --muted-foreground: 215 16% 47%; /* #64748b */
51
+ // --border: 214 32% 91%; /* #e2e8f0 */
52
+ // --radius: 0.5rem;
53
+ // }
54
+ // .dark { ... }
55
+ // bg-sketch: #f5f7fa (用 bg-[#f5f7fa] arbitrary value)
56
+
57
+ // === 侧边栏导航数据(从 sketch "编目配置" "知识" "编目" 等节点反查)===
58
+ const navMain = [
59
+ {
60
+ title: "总览",
61
+ items: [
62
+ { title: "目录概览", url: "/", icon: LayoutDashboard, isActive: true },
63
+ { title: "数据集目录", url: "/datasets", icon: Database },
64
+ { title: "库表目录", url: "/tables", icon: FileText },
65
+ ],
66
+ },
67
+ {
68
+ title: "编目管理",
69
+ items: [
70
+ { title: "编目配置", url: "/config", icon: Settings },
71
+ { title: "编目任务", url: "/tasks", icon: ListChecks },
72
+ ],
73
+ },
74
+ {
75
+ title: "知识中心",
76
+ items: [
77
+ { title: "知识库", url: "/knowledge", icon: Folder },
78
+ ],
79
+ },
80
+ ]
81
+
82
+ // === 4 个 Stat 卡片数据(从 sketch "已上线目录 2999 个" 等反查)===
83
+ const stats = [
84
+ {
85
+ title: "已上线数据集",
86
+ value: 2999,
87
+ unit: "个",
88
+ trend: { value: 2, label: "近 7 天", up: true },
89
+ icon: Database,
90
+ },
91
+ {
92
+ title: "已上线库表目录",
93
+ value: 1999,
94
+ unit: "个",
95
+ trend: { value: 2, label: "近 7 天", up: true },
96
+ icon: FileText,
97
+ },
98
+ {
99
+ title: "已上线语料",
100
+ value: 1820,
101
+ unit: "个",
102
+ trend: { value: 5, label: "近 7 天", up: true },
103
+ icon: Folder,
104
+ },
105
+ {
106
+ title: "待编目资源",
107
+ value: 423,
108
+ unit: "个",
109
+ trend: { value: 12, label: "较昨日", up: false },
110
+ icon: ListChecks,
111
+ },
112
+ ]
113
+
114
+ // === 折线图数据(模拟)===
115
+ const lineChartData = [
116
+ { date: "02-15", dataset: 2800, table: 1900, corpus: 1700 },
117
+ { date: "02-16", dataset: 2850, table: 1920, corpus: 1720 },
118
+ { date: "02-17", dataset: 2900, table: 1940, corpus: 1740 },
119
+ { date: "02-18", dataset: 2920, table: 1960, corpus: 1760 },
120
+ { date: "02-19", dataset: 2950, table: 1970, corpus: 1780 },
121
+ { date: "02-20", dataset: 2970, table: 1980, corpus: 1800 },
122
+ { date: "02-21", dataset: 2999, table: 1999, corpus: 1820 },
123
+ ]
124
+
125
+ const lineChartConfig = {
126
+ dataset: { label: "数据集", color: "hsl(217 91% 60%)" },
127
+ table: { label: "库表", color: "hsl(160 84% 39%)" },
128
+ corpus: { label: "语料", color: "hsl(38 92% 50%)" },
129
+ } satisfies ChartConfig
130
+
131
+ // === 饼图数据(数据类型分布)===
132
+ const pieChartData = [
133
+ { name: "图片", value: 1234, color: "hsl(217 91% 60%)" },
134
+ { name: "文本", value: 856, color: "hsl(160 84% 39%)" },
135
+ { name: "音频", value: 432, color: "hsl(38 92% 50%)" },
136
+ { name: "视频", value: 287, color: "hsl(280 70% 60%)" },
137
+ { name: "其他", value: 190, color: "hsl(215 16% 47%)" },
138
+ ]
139
+
140
+ // === 最近编目任务(从 sketch 推测)===
141
+ const recentTasks = [
142
+ { id: "1", name: "电商评论数据集 v2.1", status: "success", time: "2 分钟前", count: 12340 },
143
+ { id: "2", name: "客服对话语料 2024Q1", status: "running", time: "进行中", count: 8920 },
144
+ { id: "3", name: "商品图片库 春季", status: "success", time: "1 小时前", count: 5612 },
145
+ { id: "4", name: "用户行为日志 D-7", status: "failed", time: "3 小时前", count: 0 },
146
+ { id: "5", name: "新闻资讯聚合 W-1", status: "success", time: "昨天", count: 23500 },
147
+ ]
148
+
149
+ // === Stat 卡片组件 ===
150
+ function StatCard({ stat }: { stat: typeof stats[number] }) {
151
+ const Icon = stat.icon
152
+ return (
153
+ <Card className="relative overflow-hidden border-0 shadow-sm bg-gradient-to-br from-white to-slate-50 dark:from-slate-900 dark:to-slate-950">
154
+ <CardContent className="p-6">
155
+ <div className="flex items-start justify-between">
156
+ <div className="space-y-2">
157
+ <p className="text-sm text-muted-foreground">{stat.title}</p>
158
+ <div className="flex items-baseline gap-1">
159
+ <span className="text-3xl font-semibold tracking-tight">
160
+ {stat.value.toLocaleString()}
161
+ </span>
162
+ <span className="text-sm text-muted-foreground">{stat.unit}</span>
163
+ </div>
164
+ <div className="flex items-center gap-1 text-xs">
165
+ {stat.trend.up ? (
166
+ <span className="inline-flex items-center text-emerald-600 dark:text-emerald-400">
167
+ <ChevronDown className="h-3 w-3 -rotate-180" />
168
+ {stat.trend.value}
169
+ </span>
170
+ ) : (
171
+ <span className="inline-flex items-center text-rose-600 dark:text-rose-400">
172
+ <ChevronDown className="h-3 w-3" />
173
+ {stat.trend.value}
174
+ </span>
175
+ )}
176
+ <span className="text-muted-foreground">{stat.trend.label}</span>
177
+ </div>
178
+ </div>
179
+ <div className="rounded-lg bg-primary/10 p-3">
180
+ <Icon className="h-5 w-5 text-primary" />
181
+ </div>
182
+ </div>
183
+ </CardContent>
184
+ </Card>
185
+ )
186
+ }
187
+
188
+ // === 主页面 ===
189
+ export default function OverviewPage() {
190
+ return (
191
+ <TooltipProvider>
192
+ <SidebarProvider>
193
+ {/* ===== 侧边栏(L01 sidebar-main 模式) ===== */}
194
+ <Sidebar>
195
+ <SidebarHeader>
196
+ <div className="flex items-center gap-2 px-4 py-3">
197
+ <div className="h-8 w-8 rounded-md bg-primary flex items-center justify-center">
198
+ <Database className="h-5 w-5 text-primary-foreground" />
199
+ </div>
200
+ <div>
201
+ <p className="text-sm font-semibold">AI 数据集目录</p>
202
+ <p className="text-xs text-muted-foreground">管理平台</p>
203
+ </div>
204
+ </div>
205
+ </SidebarHeader>
206
+ <SidebarContent>
207
+ {navMain.map((group) => (
208
+ <SidebarGroup key={group.title}>
209
+ <SidebarGroupLabel>{group.title}</SidebarGroupLabel>
210
+ <SidebarGroupContent>
211
+ <SidebarMenu>
212
+ {group.items.map((item) => (
213
+ <SidebarMenuItem key={item.title}>
214
+ <SidebarMenuButton asChild isActive={item.isActive}>
215
+ <a href={item.url}>
216
+ <item.icon />
217
+ <span>{item.title}</span>
218
+ </a>
219
+ </SidebarMenuButton>
220
+ </SidebarMenuItem>
221
+ ))}
222
+ </SidebarMenu>
223
+ </SidebarGroupContent>
224
+ </SidebarGroup>
225
+ ))}
226
+ </SidebarContent>
227
+ <SidebarFooter>
228
+ <SidebarMenu>
229
+ <SidebarMenuItem>
230
+ <DropdownMenu>
231
+ <DropdownMenuTrigger asChild>
232
+ <SidebarMenuButton>
233
+ <Avatar className="h-6 w-6">
234
+ <AvatarImage src="/avatars/user.png" />
235
+ <AvatarFallback>U</AvatarFallback>
236
+ </Avatar>
237
+ <span>用户</span>
238
+ <ChevronDown className="ml-auto" />
239
+ </SidebarMenuButton>
240
+ </DropdownMenuTrigger>
241
+ <DropdownMenuContent side="top" className="w-[--radix-popper-anchor-width]">
242
+ <DropdownMenuLabel>账户</DropdownMenuLabel>
243
+ <DropdownMenuSeparator />
244
+ <DropdownMenuItem><User className="mr-2 h-4 w-4" />个人中心</DropdownMenuItem>
245
+ <DropdownMenuItem><Settings className="mr-2 h-4 w-4" />设置</DropdownMenuItem>
246
+ </DropdownMenuContent>
247
+ </DropdownMenu>
248
+ </SidebarMenuItem>
249
+ </SidebarMenu>
250
+ </SidebarFooter>
251
+ <SidebarRail />
252
+ </Sidebar>
253
+
254
+ {/* ===== 主内容区 ===== */}
255
+ <SidebarInset>
256
+ {/* 顶部固定导航(从 sketch "顶部-固定" group 反查) */}
257
+ <header className="sticky top-0 z-10 flex h-12 items-center gap-4 border-b bg-background px-6">
258
+ <SidebarTrigger />
259
+ <Separator orientation="vertical" className="h-4" />
260
+ <Breadcrumb>
261
+ <BreadcrumbList>
262
+ <BreadcrumbItem>
263
+ <BreadcrumbLink href="/"><Home className="h-4 w-4" /></BreadcrumbLink>
264
+ </BreadcrumbItem>
265
+ <BreadcrumbSeparator />
266
+ <BreadcrumbItem>
267
+ <BreadcrumbPage>目录概览</BreadcrumbPage>
268
+ </BreadcrumbItem>
269
+ </BreadcrumbList>
270
+ </Breadcrumb>
271
+ <div className="ml-auto flex items-center gap-2">
272
+ <div className="text-xs text-muted-foreground">
273
+ 数据更新截至:2024-02-21 18:00
274
+ </div>
275
+ <Button variant="ghost" size="icon"><Bell className="h-4 w-4" /></Button>
276
+ </div>
277
+ </header>
278
+
279
+ {/* 主内容(背景色从 sketch 提取 #f5f7fa) */}
280
+ <main className="flex-1 space-y-6 bg-[#f5f7fa] dark:bg-slate-950 p-6">
281
+ {/* 4 个 Stat 卡片(grid-cols-1 md:grid-cols-2 lg:grid-cols-4) */}
282
+ <div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4">
283
+ {stats.map((stat) => <StatCard key={stat.title} stat={stat} />)}
284
+ </div>
285
+
286
+ {/* 中部 2 列:左侧 7 列表格 + 右侧 5 列饼图 */}
287
+ <div className="grid grid-cols-1 gap-4 lg:grid-cols-7">
288
+ {/* 折线图(占 4 列) */}
289
+ <Card className="lg:col-span-4">
290
+ <CardHeader>
291
+ <div className="flex items-center justify-between">
292
+ <div>
293
+ <CardTitle>资源增长趋势</CardTitle>
294
+ <CardDescription>近 7 天各类目录数量变化</CardDescription>
295
+ </div>
296
+ <Tabs defaultValue="7d">
297
+ <TabsList>
298
+ <TabsTrigger value="7d">7 天</TabsTrigger>
299
+ <TabsTrigger value="30d">30 天</TabsTrigger>
300
+ <TabsTrigger value="90d">90 天</TabsTrigger>
301
+ </TabsList>
302
+ </Tabs>
303
+ </div>
304
+ </CardHeader>
305
+ <CardContent>
306
+ <ChartContainer config={lineChartConfig} className="h-[280px]">
307
+ <LineChart data={lineChartData}>
308
+ <CartesianGrid strokeDasharray="3 3" />
309
+ <XAxis dataKey="date" />
310
+ <YAxis />
311
+ <ChartTooltip content={<ChartTooltipContent />} />
312
+ <Line type="monotone" dataKey="dataset" stroke="var(--color-dataset)" strokeWidth={2} />
313
+ <Line type="monotone" dataKey="table" stroke="var(--color-table)" strokeWidth={2} />
314
+ <Line type="monotone" dataKey="corpus" stroke="var(--color-corpus)" strokeWidth={2} />
315
+ </LineChart>
316
+ </ChartContainer>
317
+ </CardContent>
318
+ </Card>
319
+
320
+ {/* 饼图(占 3 列) */}
321
+ <Card className="lg:col-span-3">
322
+ <CardHeader>
323
+ <CardTitle>数据类型分布</CardTitle>
324
+ <CardDescription>已编目资源按类型</CardDescription>
325
+ </CardHeader>
326
+ <CardContent>
327
+ <ChartContainer config={{}} className="h-[280px]">
328
+ <PieChart>
329
+ <Pie data={pieChartData} dataKey="value" nameKey="name" cx="50%" cy="50%" outerRadius={80} label>
330
+ {pieChartData.map((entry, i) => (
331
+ <Cell key={i} fill={entry.color} />
332
+ ))}
333
+ </Pie>
334
+ <ChartTooltip content={<ChartTooltipContent />} />
335
+ <Legend />
336
+ </PieChart>
337
+ </ChartContainer>
338
+ </CardContent>
339
+ </Card>
340
+ </div>
341
+
342
+ {/* 底部:最近编目任务列表 */}
343
+ <Card>
344
+ <CardHeader>
345
+ <div className="flex items-center justify-between">
346
+ <div>
347
+ <CardTitle>最近编目任务</CardTitle>
348
+ <CardDescription>展示最近 5 个编目任务的状态</CardDescription>
349
+ </div>
350
+ <Button variant="ghost" size="sm">查看全部</Button>
351
+ </div>
352
+ </CardHeader>
353
+ <CardContent>
354
+ <div className="space-y-3">
355
+ {recentTasks.map((task) => (
356
+ <div key={task.id} className="flex items-center gap-4 rounded-lg border p-3 hover:bg-muted/50">
357
+ <div className="h-10 w-10 rounded-md bg-muted flex items-center justify-center">
358
+ <FileText className="h-5 w-5 text-muted-foreground" />
359
+ </div>
360
+ <div className="flex-1 min-w-0">
361
+ <p className="text-sm font-medium truncate">{task.name}</p>
362
+ <p className="text-xs text-muted-foreground">
363
+ {task.count > 0 && `${task.count.toLocaleString()} 条 · `}{task.time}
364
+ </p>
365
+ </div>
366
+ <Badge variant={
367
+ task.status === "success" ? "default" :
368
+ task.status === "running" ? "secondary" : "destructive"
369
+ }>
370
+ {task.status === "success" ? "完成" : task.status === "running" ? "进行中" : "失败"}
371
+ </Badge>
372
+ </div>
373
+ ))}
374
+ </div>
375
+ </CardContent>
376
+ </Card>
377
+ </main>
378
+ </SidebarInset>
379
+ </SidebarProvider>
380
+ </TooltipProvider>
381
+ )
382
+ }