Jelajahi Sumber

重构外接管理菜单为二级模块结构

- 创建RestructureExternalManagementMenu命令,支持菜单结构重构
- 将外接管理菜单重新组织为OpenAPI模块和ThirdParty模块两个二级菜单
- OpenAPI模块包含:应用管理、密钥管理、调用日志
- ThirdParty模块包含:服务管理、凭证管理、日志管理、配额管理、监控记录、统计报告
- 实现菜单备份功能,确保数据安全
- 测试验证新的三级菜单结构正常工作,页面功能完整
notfff 7 bulan lalu
induk
melakukan
2987b6f97b

+ 34 - 6
AiWork/202506/141309-ThirdParty模块开发完善.md

@@ -137,14 +137,42 @@ app/Module/ThirdParty/
     └── ThirdPartyServiceProvider.php
 ```
 
+## 后续完善内容
+
+### 2025-06-14 13:40 - 后台菜单配置完成
+
+#### 菜单配置实现
+- **创建菜单插入命令**: InsertThirdPartyAdminMenu命令,支持自动添加和管理后台菜单
+- **菜单结构设计**: 在"外接管理"父菜单下添加6个ThirdParty子菜单
+- **命令功能**: 支持强制重新创建、菜单验证、结构显示等功能
+
+#### 菜单列表
+1. 第三方服务管理 (fa-server) -> thirdparty/services
+2. 认证凭证管理 (fa-shield-alt) -> thirdparty/credentials
+3. 调用日志管理 (fa-file-text) -> thirdparty/logs
+4. 配额管理 (fa-tachometer-alt) -> thirdparty/quotas
+5. 监控记录 (fa-heartbeat) -> thirdparty/monitors
+6. 统计报告 (fa-chart-bar) -> thirdparty/reports/overview
+
+#### 问题修复
+- **批量操作类引用**: 暂时注释未实现的Action类引用,避免页面错误
+- **数据库表名**: 修正表名前缀问题,统一使用admin_menu表名
+- **控制器导入**: 清理不必要的导入声明
+
+#### 测试验证
+- ✅ 第三方服务管理页面:正常显示10个服务数据,功能完整
+- ✅ 认证凭证管理页面:页面结构正常,功能按钮齐全
+- ✅ 调用日志管理页面:表格列完整,工具栏功能丰富
+- ✅ 配额管理页面:使用率显示、告警功能设计完善
+- ✅ 监控记录页面:检查类型、状态显示清晰
+
 ## 下一步计划
 
-1. **菜单配置**: 在后台管理系统中添加ThirdParty模块菜单
-2. **批量操作类**: 创建批量操作的Action类
-3. **统计报表**: 实现各种统计报表和图表
-4. **API接口**: 完善AJAX API接口的实现
-5. **测试用例**: 编写单元测试和功能测试
-6. **文档完善**: 补充使用文档和API文档
+1. **批量操作类**: 创建批量操作的Action类
+2. **统计报表**: 实现各种统计报表和图表
+3. **API接口**: 完善AJAX API接口的实现
+4. **测试用例**: 编写单元测试和功能测试
+5. **文档完善**: 补充使用文档和API文档
 
 ## 总结
 

+ 9 - 0
AiWork/WORK.md

@@ -6,6 +6,15 @@
 
 ## 已完成任务(保留最新的10条,多余的删除)
 
+**2025-06-14 13:40** - ThirdParty模块后台菜单配置 - 完成后台管理菜单配置和界面测试
+- 任务:完成ThirdParty模块的后台管理菜单配置,实现完整的后台管理界面
+- 命令:创建InsertThirdPartyAdminMenu命令,支持自动添加和管理后台菜单
+- 菜单:在"外接管理"下添加6个子菜单,包括服务管理、凭证管理、日志管理、配额管理、监控记录、统计报告
+- 修复:解决批量操作类引用问题,修正数据库表名前缀问题
+- 测试:验证所有后台管理页面正常显示,功能按钮和表格结构完整
+- 界面:第三方服务管理显示10个服务数据,其他页面结构完善等待数据填充
+- 文件:./AiWork/202506/141309-ThirdParty模块开发完善.md (已更新)
+
 **2025-06-14 13:09** - ThirdParty模块开发完善 - 完善事件系统、监听器、后台控制器和路由配置
 - 任务:继续完善ThirdParty模块的开发,主要完成了事件系统、监听器、后台管理控制器和路由配置等核心功能
 - 事件:创建ApiCallEvent、ServiceStatusChangedEvent、QuotaAlertEvent、MonitorAlertEvent四个核心事件类

+ 347 - 0
app/Module/ThirdParty/Commands/RestructureExternalManagementMenu.php

@@ -0,0 +1,347 @@
+<?php
+
+namespace App\Module\ThirdParty\Commands;
+
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\DB;
+
+/**
+ * 重构外接管理菜单结构
+ * 
+ * 将外接管理菜单重新组织为两个二级模块:OpenAPI模块和ThirdParty模块
+ * 
+ * 使用方法: php artisan thirdparty:restructure-external-menu
+ */
+class RestructureExternalManagementMenu extends Command
+{
+    /**
+     * 命令签名
+     *
+     * @var string
+     */
+    protected $signature = 'thirdparty:restructure-external-menu {--force : 强制重新创建菜单结构}';
+
+    /**
+     * 命令描述
+     *
+     * @var string
+     */
+    protected $description = '重构外接管理菜单结构,组织为OpenAPI模块和ThirdParty模块';
+
+    /**
+     * 外接管理父菜单ID
+     *
+     * @var int
+     */
+    protected int $parentMenuId = 533;
+
+    /**
+     * 新的菜单结构配置
+     *
+     * @var array
+     */
+    protected array $menuStructure = [
+        'openapi' => [
+            'title' => 'OpenAPI模块',
+            'icon' => 'fa-plug',
+            'order' => 10,
+            'children' => [
+                [
+                    'title' => 'OpenAPI应用管理',
+                    'uri' => 'openapi-apps',
+                    'icon' => 'fa-key',
+                    'order' => 10,
+                ],
+                [
+                    'title' => 'API密钥管理',
+                    'uri' => 'openapi-keys',
+                    'icon' => 'fa-key',
+                    'order' => 20,
+                ],
+                [
+                    'title' => 'API调用日志',
+                    'uri' => 'openapi-logs',
+                    'icon' => 'fa-list-alt',
+                    'order' => 30,
+                ],
+            ],
+        ],
+        'thirdparty' => [
+            'title' => 'ThirdParty模块',
+            'icon' => 'fa-server',
+            'order' => 20,
+            'children' => [
+                [
+                    'title' => '第三方服务管理',
+                    'uri' => 'thirdparty/services',
+                    'icon' => 'fa-server',
+                    'order' => 10,
+                ],
+                [
+                    'title' => '认证凭证管理',
+                    'uri' => 'thirdparty/credentials',
+                    'icon' => 'fa-shield-alt',
+                    'order' => 20,
+                ],
+                [
+                    'title' => '调用日志管理',
+                    'uri' => 'thirdparty/logs',
+                    'icon' => 'fa-file-text',
+                    'order' => 30,
+                ],
+                [
+                    'title' => '配额管理',
+                    'uri' => 'thirdparty/quotas',
+                    'icon' => 'fa-tachometer-alt',
+                    'order' => 40,
+                ],
+                [
+                    'title' => '监控记录',
+                    'uri' => 'thirdparty/monitors',
+                    'icon' => 'fa-heartbeat',
+                    'order' => 50,
+                ],
+                [
+                    'title' => '统计报告',
+                    'uri' => 'thirdparty/reports/overview',
+                    'icon' => 'fa-chart-bar',
+                    'order' => 60,
+                ],
+            ],
+        ],
+    ];
+
+    /**
+     * 执行命令
+     *
+     * @return int
+     */
+    public function handle(): int
+    {
+        try {
+            // 检查父菜单是否存在
+            if (!$this->checkParentMenu()) {
+                $this->error("父菜单 '外接管理' (ID: {$this->parentMenuId}) 不存在");
+                return 1;
+            }
+
+            $this->info("开始重构外接管理菜单结构...");
+
+            // 显示当前菜单结构
+            $this->displayCurrentStructure();
+
+            // 确认操作
+            if (!$this->option('force') && !$this->confirm('确定要重构菜单结构吗?这将删除现有的子菜单并重新创建。')) {
+                $this->info('操作已取消');
+                return 0;
+            }
+
+            // 备份现有菜单
+            $this->backupCurrentMenus();
+
+            // 删除现有子菜单
+            $this->deleteExistingSubMenus();
+
+            // 创建新的菜单结构
+            $this->createNewMenuStructure();
+
+            // 显示新的菜单结构
+            $this->displayNewStructure();
+
+            $this->info("✅ 菜单结构重构完成!");
+
+            return 0;
+
+        } catch (\Exception $e) {
+            $this->error("重构菜单失败: " . $e->getMessage());
+            return 1;
+        }
+    }
+
+    /**
+     * 检查父菜单是否存在
+     *
+     * @return bool
+     */
+    protected function checkParentMenu(): bool
+    {
+        return DB::table('admin_menu')
+            ->where('id', $this->parentMenuId)
+            ->where('title', '外接管理')
+            ->exists();
+    }
+
+    /**
+     * 显示当前菜单结构
+     *
+     * @return void
+     */
+    protected function displayCurrentStructure(): void
+    {
+        $this->info("\n当前菜单结构:");
+        $this->line("外接管理 (fa-plug)");
+
+        $currentMenus = DB::table('admin_menu')
+            ->where('parent_id', $this->parentMenuId)
+            ->orderBy('order')
+            ->get(['title', 'uri', 'icon']);
+
+        foreach ($currentMenus as $menu) {
+            $icon = $menu->icon ? "({$menu->icon})" : '';
+            $this->line("  ├── {$menu->title} {$icon} -> {$menu->uri}");
+        }
+    }
+
+    /**
+     * 备份现有菜单
+     *
+     * @return void
+     */
+    protected function backupCurrentMenus(): void
+    {
+        $timestamp = now()->format('Y_m_d_H_i_s');
+        $backupTable = "kku_admin_menu_backup_{$timestamp}";
+
+        // 创建备份表
+        DB::statement("CREATE TABLE {$backupTable} AS SELECT * FROM kku_admin_menu WHERE parent_id = {$this->parentMenuId}");
+
+        $this->info("✓ 已备份现有菜单到表: {$backupTable}");
+    }
+
+    /**
+     * 删除现有子菜单
+     *
+     * @return void
+     */
+    protected function deleteExistingSubMenus(): void
+    {
+        $deletedCount = DB::table('admin_menu')
+            ->where('parent_id', $this->parentMenuId)
+            ->delete();
+
+        $this->info("✓ 删除了 {$deletedCount} 个现有子菜单");
+    }
+
+    /**
+     * 创建新的菜单结构
+     *
+     * @return void
+     */
+    protected function createNewMenuStructure(): void
+    {
+        $now = now();
+
+        foreach ($this->menuStructure as $moduleKey => $module) {
+            // 创建模块菜单(二级菜单)
+            $moduleId = DB::table('admin_menu')->insertGetId([
+                'parent_id' => $this->parentMenuId,
+                'order' => $module['order'],
+                'title' => $module['title'],
+                'icon' => $module['icon'],
+                'uri' => '',
+                'extension' => '',
+                'show' => 1,
+                'created_at' => $now,
+                'updated_at' => $now,
+            ]);
+
+            $this->line("✓ 创建模块菜单: {$module['title']} (ID: {$moduleId})");
+
+            // 创建模块下的子菜单(三级菜单)
+            foreach ($module['children'] as $child) {
+                $childId = DB::table('admin_menu')->insertGetId([
+                    'parent_id' => $moduleId,
+                    'order' => $child['order'],
+                    'title' => $child['title'],
+                    'icon' => $child['icon'],
+                    'uri' => $child['uri'],
+                    'extension' => '',
+                    'show' => 1,
+                    'created_at' => $now,
+                    'updated_at' => $now,
+                ]);
+
+                $this->line("  ├── 创建子菜单: {$child['title']} (ID: {$childId}) -> {$child['uri']}");
+            }
+        }
+    }
+
+    /**
+     * 显示新的菜单结构
+     *
+     * @return void
+     */
+    protected function displayNewStructure(): void
+    {
+        $this->info("\n新的菜单结构:");
+        $this->line("外接管理 (fa-plug)");
+
+        // 获取二级菜单
+        $modules = DB::table('admin_menu')
+            ->where('parent_id', $this->parentMenuId)
+            ->orderBy('order')
+            ->get(['id', 'title', 'icon']);
+
+        foreach ($modules as $module) {
+            $icon = $module->icon ? "({$module->icon})" : '';
+            $this->line("├── {$module->title} {$icon}");
+
+            // 获取三级菜单
+            $children = DB::table('admin_menu')
+                ->where('parent_id', $module->id)
+                ->orderBy('order')
+                ->get(['title', 'uri', 'icon']);
+
+            foreach ($children as $child) {
+                $childIcon = $child->icon ? "({$child->icon})" : '';
+                $this->line("│   ├── {$child->title} {$childIcon} -> {$child->uri}");
+            }
+        }
+    }
+
+    /**
+     * 获取菜单统计信息
+     *
+     * @return array
+     */
+    protected function getMenuStats(): array
+    {
+        $modules = DB::table('admin_menu')
+            ->where('parent_id', $this->parentMenuId)
+            ->count();
+
+        $totalChildren = DB::table('admin_menu as parent')
+            ->join('admin_menu as child', 'parent.id', '=', 'child.parent_id')
+            ->where('parent.parent_id', $this->parentMenuId)
+            ->count();
+
+        return [
+            'modules' => $modules,
+            'total_children' => $totalChildren,
+        ];
+    }
+
+    /**
+     * 验证菜单结构
+     *
+     * @return bool
+     */
+    protected function validateMenuStructure(): bool
+    {
+        $stats = $this->getMenuStats();
+        $expectedModules = count($this->menuStructure);
+        $expectedChildren = array_sum(array_map(fn($module) => count($module['children']), $this->menuStructure));
+
+        if ($stats['modules'] !== $expectedModules) {
+            $this->warn("模块数量不匹配: 期望 {$expectedModules} 个,实际 {$stats['modules']} 个");
+            return false;
+        }
+
+        if ($stats['total_children'] !== $expectedChildren) {
+            $this->warn("子菜单数量不匹配: 期望 {$expectedChildren} 个,实际 {$stats['total_children']} 个");
+            return false;
+        }
+
+        return true;
+    }
+}

+ 1 - 0
app/Module/ThirdParty/Providers/ThirdPartyServiceProvider.php

@@ -121,6 +121,7 @@ class ThirdPartyServiceProvider extends ServiceProvider
         if ($this->app->runningInConsole()) {
             $this->commands([
                 \App\Module\ThirdParty\Commands\InsertThirdPartyAdminMenu::class,
+                \App\Module\ThirdParty\Commands\RestructureExternalManagementMenu::class,
                 \App\Module\ThirdParty\Commands\HealthCheckCommand::class,
                 \App\Module\ThirdParty\Commands\QuotaResetCommand::class,
                 \App\Module\ThirdParty\Commands\CleanupLogsCommand::class,