feat(admin-portal): 完整实现 admin-portal 管理端微前端
包含 src 全部实现、Dockerfile、配置文件等
This commit is contained in:
267
apps/admin-portal/src/app/admin/dashboard/page.tsx
Normal file
267
apps/admin-portal/src/app/admin/dashboard/page.tsx
Normal file
@@ -0,0 +1,267 @@
|
||||
"use client";
|
||||
|
||||
import { type ReactNode } from "react";
|
||||
import { useDashboard } from "@/hooks/use-dashboard";
|
||||
import {
|
||||
PageHeader,
|
||||
PaperCard,
|
||||
LoadingState,
|
||||
ErrorState,
|
||||
Badge,
|
||||
} from "@/components/ui";
|
||||
import { NotificationPanel } from "@/components/notification-panel";
|
||||
import { t } from "@/lib/i18n";
|
||||
|
||||
interface StatCardProps {
|
||||
label: string;
|
||||
value: number | string;
|
||||
suffix?: string;
|
||||
}
|
||||
|
||||
function StatCard({ label, value, suffix }: StatCardProps): ReactNode {
|
||||
return (
|
||||
<PaperCard className="p-4">
|
||||
<p
|
||||
style={{
|
||||
fontSize: 11,
|
||||
color: "var(--color-ink-muted)",
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: "0.05em",
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</p>
|
||||
<p
|
||||
style={{
|
||||
fontFamily: "var(--font-serif)",
|
||||
fontSize: 28,
|
||||
color: "var(--color-ink)",
|
||||
margin: "8px 0 0 0",
|
||||
}}
|
||||
>
|
||||
{value}
|
||||
{suffix && (
|
||||
<span
|
||||
style={{
|
||||
fontSize: 14,
|
||||
color: "var(--color-ink-muted)",
|
||||
marginLeft: 4,
|
||||
}}
|
||||
>
|
||||
{suffix}
|
||||
</span>
|
||||
)}
|
||||
</p>
|
||||
</PaperCard>
|
||||
);
|
||||
}
|
||||
|
||||
export default function DashboardPage(): ReactNode {
|
||||
const { data, loading, error } = useDashboard();
|
||||
|
||||
return (
|
||||
<div style={{ padding: 32, maxWidth: 1200, margin: "0 auto" }}>
|
||||
<PageHeader
|
||||
title={t("admin.dashboard.title")}
|
||||
description="全局概览与系统健康"
|
||||
/>
|
||||
|
||||
<NotificationPanel />
|
||||
|
||||
{loading && <LoadingState />}
|
||||
{error && <ErrorState message={error.message} />}
|
||||
{data && (
|
||||
<div className="flex flex-col gap-6">
|
||||
{/* 统计卡片 */}
|
||||
<div className="grid grid-cols-4 gap-4">
|
||||
<StatCard
|
||||
label={t("admin.dashboard.totalTeachers")}
|
||||
value={data.totalTeachers}
|
||||
/>
|
||||
<StatCard
|
||||
label={t("admin.dashboard.totalStudents")}
|
||||
value={data.totalStudents}
|
||||
/>
|
||||
<StatCard
|
||||
label={t("admin.dashboard.totalClasses")}
|
||||
value={data.totalClasses}
|
||||
/>
|
||||
<StatCard
|
||||
label={t("admin.dashboard.totalSchools")}
|
||||
value={data.totalSchools}
|
||||
/>
|
||||
<StatCard
|
||||
label={t("admin.dashboard.schoolAvgScore")}
|
||||
value={data.schoolAvgScore.toFixed(1)}
|
||||
/>
|
||||
<StatCard
|
||||
label={t("admin.dashboard.activeUsersToday")}
|
||||
value={data.activeUsersToday}
|
||||
/>
|
||||
<StatCard
|
||||
label={t("admin.dashboard.auditEventsToday")}
|
||||
value={data.auditEventsToday}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 趋势图(简化的表格) */}
|
||||
<PaperCard className="p-4">
|
||||
<h3
|
||||
style={{
|
||||
fontFamily: "var(--font-serif)",
|
||||
fontSize: 16,
|
||||
color: "var(--color-ink)",
|
||||
marginBottom: 12,
|
||||
}}
|
||||
>
|
||||
{t("admin.dashboard.trend")}
|
||||
</h3>
|
||||
<div style={{ overflowX: "auto" }}>
|
||||
<table
|
||||
style={{
|
||||
width: "100%",
|
||||
borderCollapse: "collapse",
|
||||
fontSize: 12,
|
||||
}}
|
||||
>
|
||||
<thead>
|
||||
<tr style={{ borderBottom: "1px solid var(--color-rule)" }}>
|
||||
<th
|
||||
style={{
|
||||
textAlign: "left",
|
||||
padding: "6px 8px",
|
||||
color: "var(--color-ink-muted)",
|
||||
}}
|
||||
>
|
||||
日期
|
||||
</th>
|
||||
<th
|
||||
style={{
|
||||
textAlign: "right",
|
||||
padding: "6px 8px",
|
||||
color: "var(--color-ink-muted)",
|
||||
}}
|
||||
>
|
||||
教师
|
||||
</th>
|
||||
<th
|
||||
style={{
|
||||
textAlign: "right",
|
||||
padding: "6px 8px",
|
||||
color: "var(--color-ink-muted)",
|
||||
}}
|
||||
>
|
||||
学生
|
||||
</th>
|
||||
<th
|
||||
style={{
|
||||
textAlign: "right",
|
||||
padding: "6px 8px",
|
||||
color: "var(--color-ink-muted)",
|
||||
}}
|
||||
>
|
||||
平均分
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data.trend.map((row) => (
|
||||
<tr
|
||||
key={row.date}
|
||||
style={{ borderBottom: "1px solid var(--color-rule)" }}
|
||||
>
|
||||
<td
|
||||
style={{
|
||||
padding: "6px 8px",
|
||||
color: "var(--color-ink)",
|
||||
}}
|
||||
>
|
||||
{row.date}
|
||||
</td>
|
||||
<td
|
||||
style={{
|
||||
padding: "6px 8px",
|
||||
textAlign: "right",
|
||||
color: "var(--color-ink)",
|
||||
}}
|
||||
>
|
||||
{row.teachers}
|
||||
</td>
|
||||
<td
|
||||
style={{
|
||||
padding: "6px 8px",
|
||||
textAlign: "right",
|
||||
color: "var(--color-ink)",
|
||||
}}
|
||||
>
|
||||
{row.students}
|
||||
</td>
|
||||
<td
|
||||
style={{
|
||||
padding: "6px 8px",
|
||||
textAlign: "right",
|
||||
color: "var(--color-ink)",
|
||||
fontFamily: "var(--font-mono)",
|
||||
}}
|
||||
>
|
||||
{row.avgScore.toFixed(1)}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</PaperCard>
|
||||
|
||||
{/* 服务健康 */}
|
||||
<PaperCard className="p-4">
|
||||
<h3
|
||||
style={{
|
||||
fontFamily: "var(--font-serif)",
|
||||
fontSize: 16,
|
||||
color: "var(--color-ink)",
|
||||
marginBottom: 12,
|
||||
}}
|
||||
>
|
||||
{t("admin.dashboard.serviceHealth")}
|
||||
</h3>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
{data.serviceHealth.map((svc) => (
|
||||
<div
|
||||
key={svc.serviceName}
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
padding: "8px 12px",
|
||||
borderBottom: "1px solid var(--color-rule)",
|
||||
}}
|
||||
>
|
||||
<span
|
||||
style={{
|
||||
fontFamily: "var(--font-mono)",
|
||||
fontSize: 12,
|
||||
color: "var(--color-ink)",
|
||||
}}
|
||||
>
|
||||
{svc.serviceName}
|
||||
</span>
|
||||
<div
|
||||
style={{ display: "flex", alignItems: "center", gap: 8 }}
|
||||
>
|
||||
<span
|
||||
style={{ fontSize: 11, color: "var(--color-ink-muted)" }}
|
||||
>
|
||||
{svc.latencyMs}ms
|
||||
</span>
|
||||
<Badge status={svc.status} />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</PaperCard>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user