初始化本地仓库

This commit is contained in:
2026-08-31 11:33:59 +08:00
commit 663f74b633
2390 changed files with 402918 additions and 0 deletions
@@ -0,0 +1,169 @@
<?php
declare(strict_types=1);
/**
*+------------------
* madong
*+------------------
* Copyright (c) https://gitee.com/motion-code All rights reserved.
*+------------------
* Author: Mr. April (405784684@qq.com)
*+------------------
* Official Website: http://www.madong.tech
*/
namespace app\adminapi\middleware;
use app\adminapi\CurrentUser;
use app\adminapi\event\OperationLogEvent;
use madong\helper\Arr;
use madong\swagger\attribute\AllowAnonymous;
use madong\swagger\helper\AnnotationHelper;
use support\Container;
use Webman\Http\Request;
use Webman\Http\Response;
use Webman\MiddlewareInterface;
#[\Attribute]
final class OperationMiddleware implements MiddlewareInterface
{
private CurrentUser $currentUser;
public function __construct()
{
$this->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;
}
}