82 lines
2.5 KiB
PHP
82 lines
2.5 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace App\Service;
|
||
|
||
use App\Model\OperationLog;
|
||
use App\Model\User;
|
||
use App\Utils\Log;
|
||
use Qbhy\HyperfAuth\AuthManager;
|
||
use Swoole\Coroutine;
|
||
|
||
class OperationLogService
|
||
{
|
||
/**
|
||
* 记录操作日志(异步写库,不阻塞业务)
|
||
*/
|
||
public static function log(
|
||
int $user_id,
|
||
string $action,
|
||
string $target_type,
|
||
?int $target_id,
|
||
string $description,
|
||
?array $detail = null,
|
||
?string $ip = null,
|
||
): void {
|
||
Coroutine::defer(static function () use (
|
||
$user_id, $action, $target_type, $target_id, $description, $detail, $ip
|
||
): void {
|
||
try {
|
||
OperationLog::query()->create([
|
||
'user_id' => $user_id,
|
||
'action' => $action,
|
||
'target_type' => $target_type,
|
||
'target_id' => $target_id,
|
||
'description' => $description,
|
||
'detail' => $detail,
|
||
'ip' => $ip,
|
||
]);
|
||
} catch (\Throwable $e) {
|
||
Log::get()->error('OperationLogService: 写入操作日志失败', [
|
||
'error' => $e->getMessage(),
|
||
'action' => $action,
|
||
]);
|
||
}
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 从当前认证上下文获取用户 ID
|
||
*
|
||
* 优先从 request attribute 获取(兼容 API Key 认证),再 fallback 到 JWT guard
|
||
*/
|
||
public static function getCurrentUserId(): ?int
|
||
{
|
||
try {
|
||
// 优先从 request context 获取(API Key 认证存储在 auth_user attribute)
|
||
$request = \Hyperf\Context\Context::get(\Psr\Http\Message\ServerRequestInterface::class);
|
||
if ($request) {
|
||
$user = $request->getAttribute('auth_user');
|
||
if ($user instanceof User) {
|
||
return $user->id;
|
||
}
|
||
}
|
||
|
||
// Fallback: JWT guard
|
||
$container = \Hyperf\Context\ApplicationContext::getContainer();
|
||
$auth = $container->get(AuthManager::class);
|
||
$user = $auth->guard('jwt')->user();
|
||
if ($user instanceof User) {
|
||
return $user->id;
|
||
}
|
||
return $user?->getId();
|
||
} catch (\Throwable $e) {
|
||
Log::get()->warning('OperationLogService: 获取当前用户 ID 失败', [
|
||
'error' => $e->getMessage(),
|
||
]);
|
||
return null;
|
||
}
|
||
}
|
||
}
|