import { Activity, Building2, Server, ShieldCheck, Users } from "lucide-react"; import { Badge } from "@/components/ui/badge"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Table } from "@/components/ui/table"; import type { AuditLog, JoinRequest, Membership, Organization, PublicAccount, RoleDefinition, SystemIncident, } from "@/modules/core/types"; import { ROLE_LABELS } from "@/modules/core/types"; import { UserManagementClient } from "@/modules/settings/components/UserManagementClient"; import type { RoleId } from "@/modules/core/types"; type SettingsOverviewProps = { accounts: PublicAccount[]; roles: RoleDefinition[]; auditLogs: AuditLog[]; organizations: Organization[]; memberships: Membership[]; joinRequests: JoinRequest[]; incidents: SystemIncident[]; }; function formatRoleLabel(role: string): string { if (role in ROLE_LABELS) { return ROLE_LABELS[role as RoleId]; } return role; } export function SettingsOverview({ accounts, roles, auditLogs, organizations, memberships, joinRequests, incidents, }: SettingsOverviewProps): React.ReactElement { const activeAccountCount = accounts.filter((account) => account.status === "active").length; const disabledAccountCount = accounts.length - activeAccountCount; const activeOrganizationCount = organizations.filter((organization) => organization.status === "active").length; const openIncidentCount = incidents.filter((incident) => incident.status === "open").length; const deniedAuditCount = auditLogs.filter((log) => log.result === "denied").length; const failureAuditCount = auditLogs.filter((log) => log.result === "failure").length; const successAuditCount = auditLogs.filter((log) => log.result === "success").length; const totalPermissionCount = roles.reduce((sum, role) => sum + role.permissions.length, 0); const actionCounts = auditLogs.reduce>((counts, log) => { counts[log.action] = (counts[log.action] ?? 0) + 1; return counts; }, {}); const topActions = Object.entries(actionCounts) .sort((left, right) => right[1] - left[1]) .slice(0, 4); return (
System configuration

系统设置

机构、用户、角色、权限、审计和故障中心。

机构租户 {organizations.length}

启用 {activeOrganizationCount} 个,多租户数据隔离

系统账号 {accounts.length}

启用 {activeAccountCount} 个,停用 {disabledAccountCount} 个

角色数量 {roles.length}

累计覆盖 {totalPermissionCount} 项权限

0 ? "border-red-200 bg-red-50/70" : undefined}>
0 ? "text-red-700" : undefined}>故障事件 0 ? "mt-2 text-3xl text-red-700" : "mt-2 text-3xl"}> {openIncidentCount}
0 ? "size-5 text-red-600" : "size-5 text-primary"} aria-hidden="true" />

0 ? "text-sm text-red-700" : "text-sm text-muted-foreground"}> 总计 {incidents.length} 条,开放 {openIncidentCount} 条

审计日志 {auditLogs.length}

成功 {successAuditCount} 条,最近 100 条

风险标记
红色:拒绝/失败审计 {deniedAuditCount + failureAuditCount}
开放故障 {openIncidentCount}
黄色:停用账号 {disabledAccountCount}
绿色:成功审计 {successAuditCount}
高频动作 {topActions.map(([action, count]) => (
{action} {count} 次
))} {topActions.length === 0 ?

暂无审计动作统计

: null}
机构租户
机构 Slug 状态 创建时间 {organizations.map((organization) => ( {organization.name} {organization.slug} {organization.status === "active" ? "启用" : "停用"} {new Date(organization.createdAt).toLocaleString("zh-CN")} ))} {organizations.length === 0 ? ( 暂无机构 ) : null}
故障中心 {incidents.slice(0, 6).map((incident) => (

{incident.title}

{incident.status}

{incident.description}

{incident.source} / {new Date(incident.createdAt).toLocaleString("zh-CN")}

))} {incidents.length === 0 ?

暂无故障事件

: null}
角色与权限 {roles.map((role) => (

{role.label}

{role.permissions.length} 权限

{role.description}

{role.permissions.map((permission) => ( {permission} ))}
))}
账号列表
账号 角色 状态 创建时间 {accounts.map((account) => (

{account.name}

{account.email}

{formatRoleLabel(account.role)} {account.status === "active" ? "启用" : account.status === "pending" ? "待审批" : "停用"} {new Date(account.createdAt).toLocaleString("zh-CN")}
))}
机构成员关系
账号 ID 机构 ID 角色 状态 创建时间 {memberships.map((membership) => ( {membership.accountId.slice(0, 8)} {membership.organizationId.slice(0, 8)} {membership.roleLabel} {membership.status} {new Date(membership.createdAt).toLocaleString("zh-CN")} ))} {memberships.length === 0 ? ( 暂无成员关系 ) : null}
审计日志
时间 操作者 动作 对象 结果 原因 {auditLogs.map((log) => ( {new Date(log.timestamp).toLocaleString("zh-CN")} {log.actorEmail ?? "系统"} {log.action} {log.targetType} {log.targetId ? ` / ${log.targetId.slice(0, 8)}` : ""} {log.result} {log.reason} ))} {auditLogs.length === 0 ? ( 暂无审计日志 ) : null}
); }