This commit is contained in:
2026-03-17 15:55:13 +08:00
parent 4eb74366ec
commit b34c44a590
5 changed files with 575 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace App\Model;
/**
* 操作日志模型
*
* 记录关键业务操作(用户管理、权限变更、登录退出)的审计追踪
*
* @property int $id
* @property int $user_id
* @property string $action
* @property string $target_type
* @property int|null $target_id
* @property string $description
* @property array|null $detail
* @property string|null $ip
* @property \Carbon\Carbon $created_at
*/
class OperationLog extends Model
{
protected ?string $table = 'operation_logs';
public bool $timestamps = true;
public const UPDATED_AT = null;
protected array $fillable = [
'user_id', 'action', 'target_type', 'target_id',
'description', 'detail', 'ip',
];
protected array $casts = [
'id' => 'integer',
'user_id' => 'integer',
'target_id' => 'integer',
'detail' => 'json',
'created_at' => 'datetime',
];
}
@@ -0,0 +1,82 @@
<?php
declare(strict_types=1);
namespace App\Service;
use App\Middleware\RequestLogMiddleware;
use App\Model\OperationLog;
use App\Model\User;
use App\Utils\Log;
use Psr\Http\Message\ServerRequestInterface;
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,
]);
}
});
}
/**
* 从当前请求上下文获取客户端 IP
*/
public static function getRequestIp(): ?string
{
try {
$container = \Hyperf\Context\ApplicationContext::getContainer();
$request = $container->get(ServerRequestInterface::class);
return RequestLogMiddleware::getClientIp($request);
} catch (\Throwable) {
return null;
}
}
/**
* 从当前认证上下文获取用户 ID
*/
public static function getCurrentUserId(): ?int
{
try {
$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) {
return null;
}
}
}