/** * 系统状态监控 API * * GET: 获取系统整体状态和统计数据 * * 参考:flnxi_sucai/app/api/admin/system-status/route.ts */ import { NextRequest, NextResponse } from 'next/server' import { getServerSession } from 'next-auth' import { authOptions } from '@/lib/auth' import { prisma } from '@/lib/prisma' export async function GET(req: NextRequest) { try { const session = await getServerSession(authOptions) // 检查管理员权限 if (!session || (session.user as any).role !== 'ADMIN') { return NextResponse.json( { error: '无权限访问系统状态' }, { status: 403 } ) } // 计算时间范围(30天前和7天前) const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) // 并行查询基础数据 let newUsersThisMonth: any, newMaterialsThisMonth: any, siteSettings: any, recentMaterials: any, totalUsers: number, totalMaterials: number, activeUsers: number, departmentStats: any[], roleStats: any[] try { [newUsersThisMonth, newMaterialsThisMonth, siteSettings, recentMaterials, totalUsers, totalMaterials, activeUsers, departmentStats, roleStats] = await Promise.all([ prisma.user.aggregate({ _count: { id: true }, where: { createdAt: { gte: thirtyDaysAgo } }, }), prisma.material.aggregate({ _count: { id: true }, where: { createdAt: { gte: thirtyDaysAgo }, deletedAt: null } as any, }), prisma.systemSettings.findFirst({ select: { siteName: true }, }), prisma.material.findMany({ take: 10, orderBy: { createdAt: 'desc' }, where: { deletedAt: null } as any, select: { id: true, productModel: true, createdAt: true, user: { select: { username: true, email: true, }, }, }, }), prisma.user.count(), prisma.material.count({ where: { deletedAt: null } as any }), prisma.user.count({ where: { updatedAt: { gte: sevenDaysAgo } } }), prisma.user.groupBy({ by: ['department'], _count: { id: true }, }), prisma.user.groupBy({ by: ['role'], _count: { id: true }, }), ]) } catch (error: any) { console.error('[SystemStatus] Database query error:', error) // 降级处理 newUsersThisMonth = { _count: { id: 0 } } newMaterialsThisMonth = { _count: { id: 0 } } siteSettings = null recentMaterials = [] totalUsers = 0 totalMaterials = 0 activeUsers = 0 departmentStats = [] roleStats = [] } // 获取素材统计(兼容旧数据库) let materialStats: any = {} try { // 尝试按素材类型分组统计 const materialTypeStats = await prisma.material.groupBy({ by: ['materialType'], _count: { id: true, }, where: { deletedAt: null, // 只统计未删除的素材 } as any, }) const totalMaterials = materialTypeStats.reduce((sum, stat) => sum + stat._count.id, 0) materialStats = { total: totalMaterials, byType: materialTypeStats.reduce((acc, stat) => { acc[stat.materialType] = stat._count.id return acc }, {} as Record), } // 获取已删除素材数量 try { const deletedCount = await prisma.material.count({ where: { deletedAt: { not: null }, } as any, }) materialStats.deleted = deletedCount } catch { // deletedAt 字段不存在,跳过 materialStats.deleted = 0 } } catch (error: any) { // 如果 deletedAt 字段不存在,降级统计 if (error?.meta?.column?.includes('deletedAt')) { const materialTypeStats = await prisma.material.groupBy({ by: ['materialType'], _count: { id: true, }, }) const totalMaterials = materialTypeStats.reduce((sum, stat) => sum + stat._count.id, 0) materialStats = { total: totalMaterials, byType: materialTypeStats.reduce((acc, stat) => { acc[stat.materialType] = stat._count.id return acc }, {} as Record), deleted: 0, // 旧数据库没有软删除 } } else { throw error } } // 获取下载统计(最近7天) let downloadStats: any = {} try { const recentDownloads = await (prisma as any).materialDownloadLog.count({ where: { downloadedAt: { gte: sevenDaysAgo, }, }, }) const totalDownloads = await (prisma as any).materialDownloadLog.count() downloadStats = { total: totalDownloads, recent7Days: recentDownloads, } } catch (error: any) { // 如果下载日志表不存在 if (error?.meta?.table?.includes('material_download_logs')) { downloadStats = { total: 0, recent7Days: 0, } } else { throw error } } // 获取收藏统计 let favoriteStats: any = {} try { const totalFavorites = await (prisma as any).materialFavorite.count() favoriteStats = { total: totalFavorites, } } catch (error: any) { // 如果收藏表不存在 if (error?.meta?.table?.includes('material_favorites')) { favoriteStats = { total: 0, } } else { throw error } } // 获取存储统计(素材文件大小) const storageStats = await prisma.material.aggregate({ _sum: { zipFileSize: true, }, }) const totalStorageBytes = Number(storageStats._sum.zipFileSize || 0) const totalStorageGB = (totalStorageBytes / (1024 * 1024 * 1024)).toFixed(2) // 从roleStats计算管理员和普通用户数量 const adminUsers = roleStats.find((r: any) => r.role === 'ADMIN')?._count?.id || 0 const regularUsers = roleStats.find((r: any) => r.role === 'USER')?._count?.id || 0 // 系统信息 const systemInfo = { nodeVersion: process.version, platform: process.platform, uptime: process.uptime(), memoryUsage: process.memoryUsage(), timestamp: new Date().toISOString(), } return NextResponse.json({ users: { total: totalUsers, admin: adminUsers, regular: regularUsers, }, materials: materialStats, downloads: downloadStats, favorites: favoriteStats, storage: { totalBytes: totalStorageBytes, totalGB: parseFloat(totalStorageGB), }, system: systemInfo, }) } catch (error) { console.error('[Admin] System status error:', error) return NextResponse.json( { error: '获取系统状态失败' }, { status: 500 } ) } }