orderBy('created_at', 'desc'); // 筛选条件 if ($request->filled('user_id')) { $query->where('user_id', $request->user_id); } if ($request->filled('user_name')) { $query->where('user_name', 'like', "%{$request->user_name}%"); } if ($request->filled('module')) { $query->where('module', $request->module); } if ($request->filled('action')) { $query->where('action', $request->action); } if ($request->filled('method')) { $query->where('method', $request->method); } if ($request->filled('path')) { $query->where('path', 'like', "%{$request->path}%"); } if ($request->filled('ip')) { $query->where('ip', 'like', "%{$request->ip}%"); } if ($request->filled('response_code')) { if ($request->response_code === 'success') { $query->where('response_code', '<', 400); } elseif ($request->response_code === 'error') { $query->where('response_code', '>=', 400); } else { $query->where('response_code', $request->response_code); } } if ($request->filled('keyword')) { $keyword = $request->keyword; $query->where(function ($q) use ($keyword) { $q->where('user_name', 'like', "%{$keyword}%") ->orWhere('module', 'like', "%{$keyword}%") ->orWhere('action', 'like', "%{$keyword}%") ->orWhere('path', 'like', "%{$keyword}%") ->orWhere('ip', 'like', "%{$keyword}%") ->orWhere('remark', 'like', "%{$keyword}%"); }); } if ($request->filled('date_range')) { $dates = explode(',', $request->date_range); if (count($dates) === 2) { $query->whereBetween('created_at', [$dates[0], $dates[1]]); } } $perPage = $request->input('limit', 20); $logs = $query->paginate($perPage); return response()->json([ 'code' => 200, 'data' => [ 'list' => $logs->items(), 'total' => $logs->total(), 'current_page' => $logs->currentPage(), 'last_page' => $logs->lastPage(), ], 'message' => 'success' ]); } /** * 操作日志详情 */ public function show(string $id) { $log = OperationLog::with('user')->find($id); if (!$log) { return response()->json([ 'code' => 404, 'message' => '日志不存在' ], 404); } return response()->json([ 'code' => 200, 'data' => $log, 'message' => 'success' ]); } /** * 删除操作日志 */ public function destroy(string $id) { $log = OperationLog::find($id); if (!$log) { return response()->json([ 'code' => 404, 'message' => '日志不存在' ], 404); } try { $log->delete(); return response()->json([ 'code' => 200, 'message' => '操作日志删除成功' ]); } catch (\Exception $e) { return response()->json([ 'code' => 500, 'message' => '删除失败: ' . $e->getMessage() ], 500); } } /** * 批量删除操作日志 */ public function batchDelete(Request $request) { $request->validate([ 'log_ids' => 'required|array|min:1', 'log_ids.*' => 'integer|exists:operation_logs,id', ]); $successCount = 0; $failedLogs = []; try { foreach ($request->log_ids as $logId) { $log = OperationLog::find($logId); if (!$log) { $failedLogs[] = ['id' => $logId, 'reason' => '日志不存在']; continue; } $log->delete(); $successCount++; } return response()->json([ 'code' => 200, 'data' => [ 'success_count' => $successCount, 'failed_logs' => $failedLogs, ], 'message' => "批量删除成功,成功 {$successCount} 个" ]); } catch (\Exception $e) { return response()->json([ 'code' => 500, 'message' => '批量删除失败: ' . $e->getMessage() ], 500); } } /** * 清空操作日志 */ public function clear(Request $request) { $request->validate([ 'days' => 'nullable|integer|min:1|max:365', ]); try { $query = OperationLog::query(); if ($request->filled('days')) { $date = now()->subDays($request->days); $query->where('created_at', '<', $date); } $deletedCount = $query->delete(); return response()->json([ 'code' => 200, 'data' => ['deleted_count' => $deletedCount], 'message' => "成功清空 {$deletedCount} 条操作日志" ]); } catch (\Exception $e) { return response()->json([ 'code' => 500, 'message' => '清空失败: ' . $e->getMessage() ], 500); } } /** * 获取操作统计 */ public function statistics(Request $request) { $request->validate([ 'start_date' => 'nullable|date', 'end_date' => 'nullable|date', 'group_by' => 'nullable|string|in:day,week,month', ]); $startDate = $request->start_date ?: now()->subDays(30)->toDateString(); $endDate = $request->end_date ?: now()->toDateString(); $groupBy = $request->group_by ?: 'day'; // 总体统计 $overallStats = OperationLog::getStatistics($startDate, $endDate); // 时间趋势统计 $trendQuery = OperationLog::whereBetween('created_at', [$startDate, $endDate]); switch ($groupBy) { case 'day': $trendQuery->selectRaw('DATE(created_at) as date, COUNT(*) as count') ->groupBy(DB::raw('DATE(created_at)')) ->orderBy('date', 'asc'); break; case 'week': $trendQuery->selectRaw('YEARWEEK(created_at, 1) as week, COUNT(*) as count') ->groupBy(DB::raw('YEARWEEK(created_at, 1)')) ->orderBy('week', 'asc'); break; case 'month': $trendQuery->selectRaw('DATE_FORMAT(created_at, "%Y-%m") as month, COUNT(*) as count') ->groupBy(DB::raw('DATE_FORMAT(created_at, "%Y-%m")')) ->orderBy('month', 'asc'); break; } $trendStats = $trendQuery->get(); // 模块统计详情 $moduleStats = OperationLog::whereBetween('created_at', [$startDate, $endDate]) ->selectRaw('module, COUNT(*) as total, SUM(CASE WHEN response_code < 400 THEN 1 ELSE 0 END) as success, SUM(CASE WHEN response_code >= 400 THEN 1 ELSE 0 END) as error') ->groupBy('module') ->orderBy('total', 'desc') ->get(); // 用户操作统计 $userStats = OperationLog::whereBetween('created_at', [$startDate, $endDate]) ->selectRaw('user_id, user_name, COUNT(*) as total') ->groupBy('user_id', 'user_name') ->orderBy('total', 'desc') ->limit(20) ->get(); // 响应时间统计 $responseTimeStats = OperationLog::whereBetween('created_at', [$startDate, $endDate]) ->selectRaw('AVG(execution_time) as avg_time, MIN(execution_time) as min_time, MAX(execution_time) as max_time') ->first(); return response()->json([ 'code' => 200, 'data' => [ 'overall' => $overallStats, 'trend' => $trendStats, 'modules' => $moduleStats, 'users' => $userStats, 'response_time' => $responseTimeStats, 'date_range' => [ 'start_date' => $startDate, 'end_date' => $endDate, ], ], 'message' => 'success' ]); } /** * 获取模块列表 */ public function getModules() { $modules = OperationLog::select('module') ->distinct() ->orderBy('module', 'asc') ->pluck('module'); return response()->json([ 'code' => 200, 'data' => $modules, 'message' => 'success' ]); } /** * 获取操作类型列表 */ public function getActions() { $actions = OperationLog::select('action') ->distinct() ->orderBy('action', 'asc') ->pluck('action'); return response()->json([ 'code' => 200, 'data' => $actions, 'message' => 'success' ]); } /** * 导出操作日志 */ public function export(Request $request) { $request->validate([ 'format' => 'required|string|in:csv,excel', 'columns' => 'nullable|array', 'start_date' => 'nullable|date', 'end_date' => 'nullable|date', ]); $query = OperationLog::with('user')->orderBy('created_at', 'desc'); if ($request->filled('start_date')) { $query->where('created_at', '>=', $request->start_date); } if ($request->filled('end_date')) { $query->where('created_at', '<=', $request->end_date); } $logs = $query->get(); // TODO: 实现导出功能 // 这里返回导出信息,实际导出需要前端处理或使用Laravel Excel return response()->json([ 'code' => 200, 'data' => [ 'total' => $logs->count(), 'format' => $request->format, 'download_url' => null, // 实际项目中这里应该是导出文件的URL ], 'message' => '导出请求已接收' ]); } }