feat(database): 添加用户角色权限系统及相关监控功能

- 创建用户表(users)包含基本信息和认证字段
- 创建角色表(roles)用于权限控制
- 创建权限表(permissions)定义系统权限
- 创建用户角色关联表(user_roles)建立用户与角色关系
- 创建角色权限关联表(role_permissions)建立角色与权限关系
- 创建迁移记录表(migrations)追踪数据库变更
- 添加AdminController提供管理员面板功能
- 实现系统监控、配置管理、缓存清理等功能
- 添加AOP切面编程支持的各种通知类型
- 实现告警管理AlertManager支持多渠道告警
- 添加文档注解接口规范
This commit is contained in:
Lawson
2026-04-08 17:00:28 +08:00
commit 2782d765fb
270 changed files with 107192 additions and 0 deletions

View File

@@ -0,0 +1,198 @@
<?php
declare(strict_types=1);
namespace Fendx\File;
use Fendx\File\Storage\StorageInterface;
use Fendx\File\Storage\LocalStorage;
use Fendx\Common\Exception\BusinessException;
final class FileManager
{
private static ?self $instance = null;
private StorageInterface $storage;
private array $config;
private function __construct(array $config = [])
{
$this->config = $config;
$this->storage = $this->createStorage($config);
}
public static function getInstance(array $config = []): self
{
if (self::$instance === null) {
self::$instance = new self($config);
}
return self::$instance;
}
private function createStorage(array $config): StorageInterface
{
$type = $config['type'] ?? 'local';
switch ($type) {
case 'local':
$root = $config['root'] ?? runtime_path('storage');
$urlPrefix = $config['url_prefix'] ?? '';
return new LocalStorage($root, $urlPrefix);
default:
throw new BusinessException(500, 'Unsupported storage type: ' . $type);
}
}
public function put(string $path, string $content, array $options = []): bool
{
return $this->storage->put($path, $content, $options);
}
public function putFile(string $path, string $localPath, array $options = []): bool
{
return $this->storage->putFile($path, $localPath, $options);
}
public function get(string $path): ?string
{
return $this->storage->get($path);
}
public function exists(string $path): bool
{
return $this->storage->exists($path);
}
public function delete(string $path): bool
{
return $this->storage->delete($path);
}
public function copy(string $from, string $to): bool
{
return $this->storage->copy($from, $to);
}
public function move(string $from, string $to): bool
{
return $this->storage->move($from, $to);
}
public function size(string $path): ?int
{
return $this->storage->size($path);
}
public function lastModified(string $path): ?int
{
return $this->storage->lastModified($path);
}
public function url(string $path): ?string
{
return $this->storage->url($path);
}
public function list(string $directory): array
{
return $this->storage->list($directory);
}
public function allFiles(string $directory): array
{
return $this->storage->allFiles($directory);
}
public function deleteDirectory(string $directory): bool
{
return $this->storage->deleteDirectory($directory);
}
public function upload(string $key, array $options = []): ?string
{
if (!isset($_FILES[$key]) || $_FILES[$key]['error'] !== UPLOAD_ERR_OK) {
return null;
}
$file = $_FILES[$key];
$originalName = $file['name'];
$extension = pathinfo($originalName, PATHINFO_EXTENSION);
// 生成唯一文件名
$filename = uniqid() . '.' . $extension;
// 支持自定义目录
$directory = $options['directory'] ?? 'uploads/' . date('Y/m/d');
$path = $directory . '/' . $filename;
if ($this->putFile($path, $file['tmp_name'], $options)) {
return $path;
}
return null;
}
public function uploadMultiple(string $key, array $options = []): array
{
if (!isset($_FILES[$key])) {
return [];
}
$files = $_FILES[$key];
$paths = [];
// 处理多个文件上传
if (is_array($files['name'])) {
$count = count($files['name']);
for ($i = 0; $i < $count; $i++) {
if ($files['error'][$i] !== UPLOAD_ERR_OK) {
continue;
}
$tmpName = $files['tmp_name'][$i];
$originalName = $files['name'][$i];
$extension = pathinfo($originalName, PATHINFO_EXTENSION);
$filename = uniqid() . '.' . $extension;
$directory = $options['directory'] ?? 'uploads/' . date('Y/m/d');
$path = $directory . '/' . $filename;
if ($this->putFile($path, $tmpName, $options)) {
$paths[] = $path;
}
}
} else {
// 单个文件
if ($files['error'] === UPLOAD_ERR_OK) {
$path = $this->upload($key, $options);
if ($path) {
$paths[] = $path;
}
}
}
return $paths;
}
public function setStorage(StorageInterface $storage): void
{
$this->storage = $storage;
}
public function getStorage(): StorageInterface
{
return $this->storage;
}
public function getConfig(): array
{
return $this->config;
}
}
if (!function_exists('runtime_path')) {
function runtime_path(string $path = ''): string
{
return dirname(__DIR__, 4) . '/runtime/' . ltrim($path, '/');
}
}