Эх сурвалжийг харах

更新文件控制器和助手类

Your Name 8 сар өмнө
parent
commit
c32eaee885

+ 1 - 0
.roo/rules-code/rules.md

@@ -2,6 +2,7 @@
 - 这不是一个标准 Laravel 项目,不要用 Laravel 的思维进行开发
 - Validation不是Validator,有本质区别,阅读 ucore/Validation/README.md 了解
 - 命令执行一次只执行一个操作,避免使用`&&`进行批量操作
+- 使用目录(往目录里增加/修改/删除文件)先阅读目录的README.md
 
 # 开发流程
 1. 理解需求

+ 25 - 0
app/Module/File/Databases/GenerateSql/file_storage_config_histories.sql

@@ -0,0 +1,25 @@
+-- ******************************************************************
+-- 表 kku_file_storage_config_histories 的创建SQL
+-- 对应的Model: App\Module\File\Models\FileStorageConfigHistory
+-- 警告: 此文件由系统自动生成,禁止手动修改!
+-- ******************************************************************
+
+DROP TABLE IF EXISTS `kku_file_storage_config_histories`;
+CREATE TABLE `kku_file_storage_config_histories` (
+  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `config_id` bigint NOT NULL COMMENT '关联的存储配置ID',
+  `old_driver` varchar(50) DEFAULT NULL COMMENT '旧存储驱动',
+  `new_driver` varchar(50) DEFAULT NULL COMMENT '新存储驱动',
+  `old_config` text COMMENT '旧配置值',
+  `new_config` text COMMENT '新配置值',
+  `old_status` tinyint(1) DEFAULT NULL COMMENT '旧状态',
+  `new_status` tinyint(1) DEFAULT NULL COMMENT '新状态',
+  `changed_at` timestamp NOT NULL COMMENT '变更时间',
+  `changed_by` int NOT NULL DEFAULT '0' COMMENT '变更人ID',
+  `change_reason` varchar(500) DEFAULT '' COMMENT '变更原因',
+  `created_at` timestamp NOT NULL COMMENT '创建时间',
+  `updated_at` timestamp NOT NULL COMMENT '更新时间',
+  PRIMARY KEY (`id`),
+  KEY `idx_config_id` (`config_id`),
+  KEY `idx_changed_at` (`changed_at`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='文件存储配置变更历史表';

+ 26 - 0
app/Module/File/Databases/GenerateSql/file_storage_configs.sql

@@ -0,0 +1,26 @@
+-- ******************************************************************
+-- 表 kku_file_storage_configs 的创建SQL
+-- 对应的Model: App\Module\File\Models\FileStorageConfig
+-- 警告: 此文件由系统自动生成,禁止手动修改!
+-- ******************************************************************
+
+DROP TABLE IF EXISTS `kku_file_storage_configs`;
+CREATE TABLE `kku_file_storage_configs` (
+  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `name` varchar(100) NOT NULL COMMENT '存储磁盘名称,唯一',
+  `driver` varchar(50) NOT NULL COMMENT '存储驱动(local, s3, oss等)',
+  `config` text NOT NULL COMMENT '配置值,JSON格式',
+  `description` varchar(500) DEFAULT '' COMMENT '配置描述',
+  `is_default` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否默认存储,1表示是,0表示否',
+  `is_temp` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否用于临时存储,1表示是,0表示否',
+  `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态:1-启用,0-禁用',
+  `env` varchar(50) NOT NULL DEFAULT 'production' COMMENT '环境(development, testing, production)',
+  `created_at` timestamp NOT NULL COMMENT '创建时间',
+  `updated_at` timestamp NOT NULL COMMENT '更新时间',
+  `created_by` int NOT NULL DEFAULT '0' COMMENT '创建人ID',
+  `updated_by` int NOT NULL DEFAULT '0' COMMENT '更新人ID',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `idx_name_env` (`name`,`env`),
+  KEY `idx_status` (`status`),
+  KEY `idx_env` (`env`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='文件存储配置表';

+ 24 - 0
app/Module/File/Repositories/StorageConfigHistoryRepository.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Module\File\Repositories;
+
+use App\Module\File\Models\FileStorageConfigHistory;
+use Dcat\Admin\Repositories\EloquentRepository;
+
+/**
+ * 存储配置历史记录仓库类
+ * 
+ * 提供存储配置历史记录数据的访问和操作,专门用于后台管理界面
+ */
+class StorageConfigHistoryRepository extends EloquentRepository
+{
+    /**
+     * 关联的Eloquent模型类
+     * 
+     * @var string
+     */
+    protected $eloquentClass = FileStorageConfigHistory::class;
+
+    
+    
+}

+ 25 - 0
app/Module/File/Repositories/StorageConfigRepository.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace App\Module\File\Repositories;
+
+use App\Module\File\Models\FileStorageConfig;
+use App\Module\File\Models\FileStorageConfigHistory;
+use Dcat\Admin\Repositories\EloquentRepository;
+use Illuminate\Support\Facades\DB;
+
+/**
+ * 存储配置仓库类
+ *
+ * 提供存储配置数据的访问和操作,专门用于后台管理界面
+ */
+class StorageConfigRepository extends EloquentRepository
+{
+    /**
+     * 关联的Eloquent模型类
+     *
+     * @var string
+     */
+    protected $eloquentClass = FileStorageConfig::class;
+
+    
+}

+ 413 - 0
app/Module/File/Services/StorageConfigService.php

@@ -0,0 +1,413 @@
+<?php
+
+namespace App\Module\File\Services;
+
+use App\Module\File\Models\FileStorageConfig;
+use App\Module\File\Models\FileStorageConfigHistory;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Log;
+
+/**
+ * 存储配置服务类
+ * 
+ * 提供存储配置的业务逻辑处理,包括配置的读取、更新和缓存管理
+ */
+class StorageConfigService
+{
+    /**
+     * 缓存前缀
+     */
+    const CACHE_PREFIX = 'file_storage_config:';
+    
+    /**
+     * 缓存过期时间(秒)
+     */
+    const CACHE_TTL = 3600; // 1小时
+
+    /**
+     * 获取默认存储磁盘配置
+     *
+     * @return FileStorageConfig|null 存储配置模型
+     */
+    public function getDefaultDisk()
+    {
+        return Cache::remember(self::CACHE_PREFIX . 'default:' . app()->environment(), self::CACHE_TTL, function () {
+            return FileStorageConfig::where('is_default', true)
+                ->where('status', true)
+                ->where('env', app()->environment())
+                ->first();
+        });
+    }
+
+    /**
+     * 获取临时存储磁盘配置
+     *
+     * @return FileStorageConfig|null 存储配置模型
+     */
+    public function getTempDisk()
+    {
+        return Cache::remember(self::CACHE_PREFIX . 'temp:' . app()->environment(), self::CACHE_TTL, function () {
+            return FileStorageConfig::where('is_temp', true)
+                ->where('status', true)
+                ->where('env', app()->environment())
+                ->first();
+        });
+    }
+
+    /**
+     * 获取指定名称的存储磁盘配置
+     *
+     * @param string $name 存储磁盘名称
+     * @return FileStorageConfig|null 存储配置模型
+     */
+    public function getDisk(string $name)
+    {
+        return Cache::remember(self::CACHE_PREFIX . 'name:' . $name . ':' . app()->environment(), self::CACHE_TTL, function () use ($name) {
+            return FileStorageConfig::where('name', $name)
+                ->where('status', true)
+                ->where('env', app()->environment())
+                ->first();
+        });
+    }
+
+    /**
+     * 获取所有启用的存储磁盘配置
+     *
+     * @param string|null $env 环境名称,为null时获取当前环境
+     * @return \Illuminate\Database\Eloquent\Collection 存储配置集合
+     */
+    public function getAllDisks(string $env = null)
+    {
+        $env = $env ?: app()->environment();
+        
+        return Cache::remember(self::CACHE_PREFIX . 'all:' . $env, self::CACHE_TTL, function () use ($env) {
+            return FileStorageConfig::where('status', true)
+                ->where('env', $env)
+                ->get();
+        });
+    }
+
+    /**
+     * 创建存储磁盘配置
+     *
+     * @param string $name 存储磁盘名称
+     * @param string $driver 存储驱动
+     * @param array $config 配置值
+     * @param string $description 配置描述
+     * @param bool $isDefault 是否默认存储
+     * @param bool $isTemp 是否用于临时存储
+     * @param string $env 环境名称
+     * @param int $createdBy 创建人ID
+     * @return FileStorageConfig 存储配置模型
+     */
+    public function createDisk(string $name, string $driver, array $config, string $description = '', bool $isDefault = false, bool $isTemp = false, string $env = 'production', int $createdBy = 0)
+    {
+        // 如果设置为默认存储,则将其他配置的默认标志设为false
+        if ($isDefault) {
+            $this->resetDefaultFlag($env);
+        }
+        
+        // 如果设置为临时存储,则将其他配置的临时标志设为false
+        if ($isTemp) {
+            $this->resetTempFlag($env);
+        }
+        
+        $storageConfig = new FileStorageConfig();
+        $storageConfig->name = $name;
+        $storageConfig->driver = $driver;
+        $storageConfig->config = $config;
+        $storageConfig->description = $description;
+        $storageConfig->is_default = $isDefault;
+        $storageConfig->is_temp = $isTemp;
+        $storageConfig->env = $env;
+        $storageConfig->status = true;
+        $storageConfig->created_by = $createdBy;
+        $storageConfig->updated_by = $createdBy;
+        $storageConfig->save();
+        
+        // 清除缓存
+        $this->clearCache();
+        
+        return $storageConfig;
+    }
+
+    /**
+     * 更新存储磁盘配置
+     *
+     * @param int $id 存储配置ID
+     * @param string $driver 存储驱动
+     * @param array $config 配置值
+     * @param string $description 配置描述
+     * @param bool $isDefault 是否默认存储
+     * @param bool $isTemp 是否用于临时存储
+     * @param int $status 状态
+     * @param int $updatedBy 更新人ID
+     * @param string $reason 变更原因
+     * @return FileStorageConfig 存储配置模型
+     */
+    public function updateDisk(int $id, string $driver, array $config, string $description = '', bool $isDefault = false, bool $isTemp = false, int $status = 1, int $updatedBy = 0, string $reason = '')
+    {
+        $storageConfig = FileStorageConfig::findOrFail($id);
+        $oldData = $storageConfig->toArray();
+        
+        // 如果设置为默认存储,则将其他配置的默认标志设为false
+        if ($isDefault && !$storageConfig->is_default) {
+            $this->resetDefaultFlag($storageConfig->env);
+        }
+        
+        // 如果设置为临时存储,则将其他配置的临时标志设为false
+        if ($isTemp && !$storageConfig->is_temp) {
+            $this->resetTempFlag($storageConfig->env);
+        }
+        
+        $storageConfig->driver = $driver;
+        $storageConfig->config = $config;
+        $storageConfig->description = $description;
+        $storageConfig->is_default = $isDefault;
+        $storageConfig->is_temp = $isTemp;
+        $storageConfig->status = (bool)$status;
+        $storageConfig->updated_by = $updatedBy;
+        $storageConfig->save();
+        
+        // 记录变更历史
+        $this->recordHistory($id, $oldData, $storageConfig->toArray(), $updatedBy, $reason);
+        
+        // 清除缓存
+        $this->clearCache();
+        
+        return $storageConfig;
+    }
+
+    /**
+     * 删除存储磁盘配置
+     *
+     * @param int $id 存储配置ID
+     * @param int $deletedBy 删除人ID
+     * @param string $reason 删除原因
+     * @return bool 是否成功
+     */
+    public function deleteDisk(int $id, int $deletedBy = 0, string $reason = '')
+    {
+        $storageConfig = FileStorageConfig::findOrFail($id);
+        $oldData = $storageConfig->toArray();
+        
+        // 记录删除历史
+        $this->recordHistory($id, $oldData, [], $deletedBy, $reason ?: '删除配置');
+        
+        $result = $storageConfig->delete();
+        
+        // 清除缓存
+        $this->clearCache();
+        
+        return $result;
+    }
+
+    /**
+     * 设置默认存储磁盘
+     *
+     * @param int $id 存储配置ID
+     * @param int $updatedBy 更新人ID
+     * @return bool 是否成功
+     */
+    public function setDefaultDisk(int $id, int $updatedBy = 0)
+    {
+        $storageConfig = FileStorageConfig::findOrFail($id);
+        $oldData = $storageConfig->toArray();
+        
+        // 重置当前环境中的所有默认标志
+        $this->resetDefaultFlag($storageConfig->env);
+        
+        // 设置当前配置为默认
+        $storageConfig->is_default = true;
+        $storageConfig->updated_by = $updatedBy;
+        $result = $storageConfig->save();
+        
+        // 记录变更历史
+        $this->recordHistory($id, $oldData, $storageConfig->toArray(), $updatedBy, '设置为默认存储磁盘');
+        
+        // 清除缓存
+        $this->clearCache();
+        
+        return $result;
+    }
+
+    /**
+     * 设置临时存储磁盘
+     *
+     * @param int $id 存储配置ID
+     * @param int $updatedBy 更新人ID
+     * @return bool 是否成功
+     */
+    public function setTempDisk(int $id, int $updatedBy = 0)
+    {
+        $storageConfig = FileStorageConfig::findOrFail($id);
+        $oldData = $storageConfig->toArray();
+        
+        // 重置当前环境中的所有临时标志
+        $this->resetTempFlag($storageConfig->env);
+        
+        // 设置当前配置为临时存储
+        $storageConfig->is_temp = true;
+        $storageConfig->updated_by = $updatedBy;
+        $result = $storageConfig->save();
+        
+        // 记录变更历史
+        $this->recordHistory($id, $oldData, $storageConfig->toArray(), $updatedBy, '设置为临时存储磁盘');
+        
+        // 清除缓存
+        $this->clearCache();
+        
+        return $result;
+    }
+
+    /**
+     * 获取存储磁盘配置变更历史
+     *
+     * @param int $configId 存储配置ID
+     * @return \Illuminate\Database\Eloquent\Collection 配置历史集合
+     */
+    public function getHistory(int $configId)
+    {
+        return FileStorageConfigHistory::where('config_id', $configId)
+            ->orderBy('id', 'desc')
+            ->get();
+    }
+
+    /**
+     * 清除存储配置缓存
+     *
+     * @return void
+     */
+    public function clearCache()
+    {
+        $cacheKeys = [
+            self::CACHE_PREFIX . 'default:' . app()->environment(),
+            self::CACHE_PREFIX . 'temp:' . app()->environment(),
+            self::CACHE_PREFIX . 'all:' . app()->environment()
+        ];
+        
+        foreach ($cacheKeys as $key) {
+            Cache::forget($key);
+        }
+        
+        // 清除所有名称缓存
+        $disks = FileStorageConfig::where('env', app()->environment())->get();
+        foreach ($disks as $disk) {
+            Cache::forget(self::CACHE_PREFIX . 'name:' . $disk->name . ':' . app()->environment());
+        }
+        
+        Log::info('存储配置缓存已清除');
+    }
+
+    /**
+     * 重置默认存储标志
+     *
+     * @param string $env 环境名称
+     * @return void
+     */
+    protected function resetDefaultFlag(string $env)
+    {
+        FileStorageConfig::where('env', $env)
+            ->where('is_default', true)
+            ->update(['is_default' => false]);
+    }
+
+    /**
+     * 重置临时存储标志
+     *
+     * @param string $env 环境名称
+     * @return void
+     */
+    protected function resetTempFlag(string $env)
+    {
+        FileStorageConfig::where('env', $env)
+            ->where('is_temp', true)
+            ->update(['is_temp' => false]);
+    }
+
+    /**
+     * 记录存储配置变更历史
+     *
+     * @param int $configId 存储配置ID
+     * @param array $oldData 旧数据
+     * @param array $newData 新数据
+     * @param int $changedBy 变更人ID
+     * @param string $reason 变更原因
+     * @return FileStorageConfigHistory 配置历史模型
+     */
+    protected function recordHistory(int $configId, array $oldData, array $newData, int $changedBy, string $reason = '')
+    {
+        return FileStorageConfigHistory::create([
+            'config_id' => $configId,
+            'old_driver' => $oldData['driver'] ?? null,
+            'new_driver' => $newData['driver'] ?? null,
+            'old_config' => isset($oldData['config']) ? $oldData['config'] : null,
+            'new_config' => isset($newData['config']) ? $newData['config'] : null,
+            'old_status' => $oldData['status'] ?? null,
+            'new_status' => $newData['status'] ?? null,
+            'changed_by' => $changedBy,
+            'change_reason' => $reason,
+        ]);
+    }
+
+    /**
+     * 测试存储配置连接
+     *
+     * @param string $driver 存储驱动
+     * @param array $config 配置值
+     * @return array 测试结果,包含success和message字段
+     */
+    public function testConnection(string $driver, array $config)
+    {
+        try {
+            // 创建临时磁盘配置
+            $diskName = 'temp_test_' . time();
+            $fullConfig = array_merge(['driver' => $driver], $config);
+            config(["filesystems.disks.{$diskName}" => $fullConfig]);
+            
+            // 测试连接
+            $disk = \Storage::disk($diskName);
+            $testFile = 'test_' . time() . '.txt';
+            $disk->put($testFile, 'Testing connection at ' . now());
+            $content = $disk->get($testFile);
+            $disk->delete($testFile);
+            
+            return [
+                'success' => true,
+                'message' => '连接成功!测试文件已成功创建和删除。',
+            ];
+        } catch (\Exception $e) {
+            Log::error('存储配置连接测试失败', [
+                'driver' => $driver,
+                'config' => $config,
+                'error' => $e->getMessage(),
+            ]);
+            
+            return [
+                'success' => false,
+                'message' => '连接失败:' . $e->getMessage(),
+            ];
+        }
+    }
+
+    /**
+     * 注册存储配置到Laravel文件系统
+     *
+     * @return void
+     */
+    public function registerStorageConfigs()
+    {
+        $disks = $this->getAllDisks();
+        
+        foreach ($disks as $disk) {
+            $config = array_merge(['driver' => $disk->driver], $disk->config);
+            config(["filesystems.disks.{$disk->name}" => $config]);
+        }
+        
+        // 设置默认磁盘
+        $defaultDisk = $this->getDefaultDisk();
+        if ($defaultDisk) {
+            config(['filesystems.default' => $defaultDisk->name]);
+        }
+    }
+}