import { logError } from "@/lib/logger"; import { NextRequest, NextResponse } from "next/server"; import { query } from "@/lib/db"; export const runtime = "nodejs"; interface AuditLog { source: "user_activity" | "project_audit"; id: number; actor_uid: string | null; action: string; resource: string | null; ip_address: string | null; user_agent: string | null; created_at: string; } export async function GET(req: NextRequest) { try { const { searchParams } = req.nextUrl; const page = Math.max(1, parseInt(searchParams.get("page") || "1", 10)); const pageSize = Math.max(1, parseInt(searchParams.get("pageSize") || "20", 10)); const source = searchParams.get("source") || "all"; const action = searchParams.get("action") || ""; const offset = (page - 1) * pageSize; const actionPattern = action ? `%${action}%` : null; const limitOffsetParams: unknown[] = [pageSize, offset]; let userQuery = ""; let projectQuery = ""; let userParams: unknown[] = []; let projectParams: unknown[] = []; // Build user_activity_log query if (source !== "project") { if (action) { userParams = [actionPattern, ...limitOffsetParams]; userQuery = `SELECT 'user_activity' as source, id, COALESCE(user_uid::text, '') as actor_uid, action, NULL::text as resource, ip_address, user_agent, created_at::text as created_at FROM user_activity_log WHERE action ILIKE $1 ORDER BY created_at DESC LIMIT $2 OFFSET $3`; } else { userParams = limitOffsetParams; userQuery = `SELECT 'user_activity' as source, id, COALESCE(user_uid::text, '') as actor_uid, action, NULL::text as resource, ip_address, user_agent, created_at::text as created_at FROM user_activity_log ORDER BY created_at DESC LIMIT $1 OFFSET $2`; } } // Build project_audit_log query if (source !== "user") { if (action) { projectParams = [actionPattern, ...limitOffsetParams]; projectQuery = `SELECT 'project_audit' as source, id, COALESCE(actor::text, '') as actor_uid, action, details as resource, ip_address, NULL as user_agent, created_at::text as created_at FROM project_audit_log WHERE action ILIKE $1 ORDER BY created_at DESC LIMIT $2 OFFSET $3`; } else { projectParams = limitOffsetParams; projectQuery = `SELECT 'project_audit' as source, id, COALESCE(actor::text, '') as actor_uid, action, details as resource, ip_address, NULL as user_agent, created_at::text as created_at FROM project_audit_log ORDER BY created_at DESC LIMIT $1 OFFSET $2`; } } const [userLogs, projectLogs] = await Promise.all([ userQuery ? query(userQuery, userParams) : Promise.resolve({ rows: [] as AuditLog[] }), projectQuery ? query(projectQuery, projectParams) : Promise.resolve({ rows: [] as AuditLog[] }), ]); // 合并并排序 const combined = [...userLogs.rows, ...projectLogs.rows].sort( (a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime() ); // 总数 const [userCountRes, projectCountRes] = await Promise.all([ userCountQuery(userParams, action), projectCountQuery(projectParams, action), ]); const total = parseInt(String(userCountRes.rows[0]?.count || "0"), 10) + parseInt(String(projectCountRes.rows[0]?.count || "0"), 10); return NextResponse.json({ logs: combined.slice(0, pageSize), total, page, pageSize }); } catch (e) { logError("Platform audit logs error:", e); return NextResponse.json({ error: "服务器错误" }, { status: 500 }); } } async function userCountQuery(params: unknown[], action: string | null) { if (!params.length) return { rows: [] as { count: string }[] }; if (action) { return query<{ count: string }>( `SELECT COUNT(*) FROM user_activity_log WHERE action ILIKE $1`, [params[0]] ); } return query<{ count: string }>(`SELECT COUNT(*) FROM user_activity_log`); } async function projectCountQuery(params: unknown[], action: string | null) { if (!params.length) return { rows: [] as { count: string }[] }; if (action) { return query<{ count: string }>( `SELECT COUNT(*) FROM project_audit_log WHERE action ILIKE $1`, [params[0]] ); } return query<{ count: string }>(`SELECT COUNT(*) FROM project_audit_log`); }