diff --git a/app/Aspect/AdminReturnLogAspect.php b/app/Aspect/AdminReturnLogAspect.php index 221fc3d..90787cf 100644 --- a/app/Aspect/AdminReturnLogAspect.php +++ b/app/Aspect/AdminReturnLogAspect.php @@ -28,20 +28,16 @@ class AdminReturnLogAspect extends AbstractAspect * 切入类 * @var array|\class-string[] */ - public array $classes = [ + public array $classes = []; + + /** + * 切入方法 - 拦截所有带 ResponseFormat 注解且 format='admin' 的方法 + * @var string[] + */ + public array $annotations = [ ResponseFormat::class, ]; - /** - * @var int - */ - protected int $adminId = 0; - - /** - * @var ?AdminUser - */ - protected ?AdminUser $adminUserInfo = null; - /** * @param Logger $logger * @param RequestInterface $request @@ -51,10 +47,7 @@ class AdminReturnLogAspect extends AbstractAspect protected readonly Logger $logger, protected RequestInterface $request, protected readonly AdminUserOperationLog $adminUserOperationLogModel, - ) { - $this->adminId = Context::get('current_admin_id',0); - if ($this->adminId > 0) $this->adminUserInfo = $this->getAdminUserInfo($this->adminId); - } + ) {} /** * @param ProceedingJoinPoint $proceedingJoinPoint @@ -63,49 +56,100 @@ class AdminReturnLogAspect extends AbstractAspect */ public function process(ProceedingJoinPoint $proceedingJoinPoint) { - // 直接从方法参数获取请求数据 - $requestData = $proceedingJoinPoint->getArguments()[0] ?? []; + // 检查是否是 admin 格式 + $annotation = $proceedingJoinPoint->getAnnotationMetadata()->class[ResponseFormat::class] + ?? $proceedingJoinPoint->getAnnotationMetadata()->method[ResponseFormat::class] ?? null; - // 执行原方法并获取返回值 - $responseData = $proceedingJoinPoint->process(); + // 只处理 admin 格式的请求 + if (!$annotation || $annotation->format !== 'admin') { + return $proceedingJoinPoint->process(); + } + + // 获取当前登录的管理员ID(在 process 方法中获取,确保 Context 已设置) + $adminId = Context::get('current_admin_id', 0); // 没登录不记录日志 - if ($this->adminId <= 0) return $responseData; + if ($adminId <= 0) { + return $proceedingJoinPoint->process(); + } + + // 获取请求数据 + $requestData = $this->request->all(); + + // 执行原方法并获取返回值 + $responseData = $proceedingJoinPoint->process(); // 写日志 - $this->writeOperationLog($requestData, $responseData); + $this->writeOperationLog($adminId, $requestData, $responseData); // 返回 return $responseData; } /** + * @param int $adminId * @param array $requestData * @param array $responseData * @return void */ - private function writeOperationLog(array $requestData = [], array $responseData = []): void + private function writeOperationLog(int $adminId, array $requestData = [], array $responseData = []): void { + $router = (string) $this->request->getUri(); + $method = $this->request->getMethod(); + $ip = $this->getClientIp(); + $ipStr = current($ip) ?: '0.0.0.0'; + $context = [ - 'user_id' => $this->adminId, - 'method' => $this->request->getMethod(), - 'router' => $this->request->getUri(), - 'ip' => $this->getClientIp(), + 'user_id' => $adminId, + 'method' => $method, + 'router' => $router, + 'ip' => $ip, 'request_data' => $requestData, 'response_data' => $responseData, ]; - Coroutine::create(function () use ($requestData, $responseData, $context) { - $this->logger->request()->info('admin_request_log', $context); + // 先记录日志 + $this->logger->request()->info('admin_request_log', $context); - $this->adminUserOperationLogModel->create([ - 'admin_user_id' => $this->adminId, - 'username' => $this->adminUserInfo?->username ?? '', - 'method' => $context['method'], - 'router' => $context['router'], - 'service_name' => $context['service_name'] ?? '', - 'ip' => current($context['ip']) ?: '0.0.0.0', - ]); - }); + // 获取用户信息 + $adminUserInfo = $this->getAdminUserInfo($adminId); + $username = $adminUserInfo?->username ?? ''; + + // 异步写入数据库 + try { + Coroutine::create(function () use ($adminId, $username, $router, $method, $ipStr) { + try { + $this->adminUserOperationLogModel->create([ + 'admin_user_id' => $adminId, + 'username' => $username, + 'method' => $method, + 'router' => $router, + 'service_name' => '', + 'ip' => $ipStr, + ]); + } catch (\Throwable $e) { + $this->logger->error()->error('写入操作日志失败: ' . $e->getMessage(), [ + 'admin_id' => $adminId, + 'router' => $router, + 'exception' => $e->getMessage(), + ]); + } + }); + } catch (\Throwable $e) { + // 协程创建失败,降级为同步写入 + $this->logger->error()->error('创建协程失败,同步写入日志: ' . $e->getMessage()); + try { + $this->adminUserOperationLogModel->create([ + 'admin_user_id' => $adminId, + 'username' => $username, + 'method' => $method, + 'router' => $router, + 'service_name' => '', + 'ip' => $ipStr, + ]); + } catch (\Throwable $e2) { + $this->logger->error()->error('同步写入操作日志也失败: ' . $e2->getMessage()); + } + } } }