currentUser = Container::make(CurrentUser::class); } public function process(Request $request, callable $handler): Response { $controllerClass = $request->controller; $action = $request->action; $oaAnnotations = AnnotationHelper::getMethodOaAnnotations($controllerClass, $action); $oaData = $this->extractOaData($oaAnnotations); $firstOa = Arr::first($oaData); $response = $handler($request); // 检查是否需要记录操作日志(跳过匿名访问) $allowAnonymous = AnnotationHelper::getMethodAnnotation($controllerClass, $action, AllowAnonymous::class); if (!$allowAnonymous || $allowAnonymous->requirePermission) { $logData = $this->buildLogData($request, $response, $firstOa); $event = new OperationLogEvent( $logData['name'], $logData['oa_tags'], $logData['oa_description'], $logData['app'], $logData['ip'], $logData['ip_location'], $logData['browser'], $logData['os'], $logData['url'], $logData['class_name'], $logData['action'], $logData['method'], $logData['param'], $logData['result'], $logData['user_name'], $logData['user_id'] ); $event->dispatch(); } return $response; } private function extractOaData(array $oaAnnotations): array { return array_map(function ($annotation) { return [ 'type' => $annotation::class, // 注解类型(如 OpenApi\Attributes\Get) 'summary' => $annotation->summary, // 操作摘要 'tags' => $annotation->tags, // 标签 'description' => $annotation->description ?? '', // 描述 ]; }, $oaAnnotations); } private function buildLogData(Request $request, Response $response, ?array $firstOa): array { $adminInfo = $this->currentUser->admin(); return [ 'name' => $firstOa['summary'] ?? '未知操作', // 用 OA summary 作为操作名称 'oa_tags' => $firstOa['tags'] ?? [], // OA 标签 'oa_description' => $firstOa['description'] ?? '', // OA 描述 'app' => $request->app, 'ip' => $request->getRealIp(), 'ip_location' => $this->getIpLocation($request->getRealIp()), // 可选:IP 归属地 'browser' => $this->getBrowser($request->header('user-agent')), 'os' => $this->getOs($request->header('user-agent')), 'url' => trim($request->path()), 'class_name' => $request->controller, 'action' => $request->action, 'method' => $request->method(), 'param' => $this->filterParams($request->all()), // 过滤后的参数(数组) 'result' => $this->formatResponse($response), // 格式化响应(数组/字符串) 'user_name' => $adminInfo['user_name'] ?? '匿名用户', 'user_id' => $adminInfo['user_id'] ?? 0, ]; } private function getIpLocation(string $ip): string { return '未知'; } private function getBrowser($user_agent): string { $br = 'Unknown'; if (preg_match('/MSIE/i', $user_agent)) { $br = 'MSIE'; } elseif (preg_match('/Firefox/i', $user_agent)) { $br = 'Firefox'; } elseif (preg_match('/Chrome/i', $user_agent)) { $br = 'Chrome'; } elseif (preg_match('/Safari/i', $user_agent)) { $br = 'Safari'; } elseif (preg_match('/Opera/i', $user_agent)) { $br = 'Opera'; } else { $br = 'Other'; } return $br; } private function getOs($user_agent): string { $os = 'Unknown'; if (preg_match('/win/i', $user_agent)) { $os = 'Windows'; } elseif (preg_match('/mac/i', $user_agent)) { $os = 'Mac'; } elseif (preg_match('/linux/i', $user_agent)) { $os = 'Linux'; } else { $os = 'Other'; } return $os; } private function filterParams($params): string { $blackList = ['password', 'old_password', 'new_password', 'content']; foreach ($params as $key => $value) { if (in_array($key, $blackList)) { $params[$key] = '******'; } } return json_encode($params, JSON_UNESCAPED_UNICODE); } private function formatResponse(Response $response): array|string { $rawBody = $response->rawBody(); if (str_contains($rawBody, 'json')) { return json_decode($rawBody, true) ?? $rawBody; } return $rawBody; } }