RestructureExternalManagementMenu.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. <?php
  2. namespace App\Module\ThirdParty\Commands;
  3. use Illuminate\Console\Command;
  4. use Illuminate\Support\Facades\DB;
  5. /**
  6. * 重构外接管理菜单结构
  7. *
  8. * 将外接管理菜单重新组织为两个二级模块:OpenAPI模块和ThirdParty模块
  9. *
  10. * 使用方法: php artisan thirdparty:restructure-external-menu
  11. */
  12. class RestructureExternalManagementMenu extends Command
  13. {
  14. /**
  15. * 命令签名
  16. *
  17. * @var string
  18. */
  19. protected $signature = 'thirdparty:restructure-external-menu {--force : 强制重新创建菜单结构}';
  20. /**
  21. * 命令描述
  22. *
  23. * @var string
  24. */
  25. protected $description = '重构外接管理菜单结构,组织为OpenAPI模块和ThirdParty模块';
  26. /**
  27. * 外接管理父菜单ID
  28. *
  29. * @var int
  30. */
  31. protected int $parentMenuId = 533;
  32. /**
  33. * 新的菜单结构配置
  34. *
  35. * @var array
  36. */
  37. protected array $menuStructure = [
  38. 'openapi' => [
  39. 'title' => 'OpenAPI模块',
  40. 'icon' => 'fa-plug',
  41. 'order' => 10,
  42. 'children' => [
  43. [
  44. 'title' => 'OpenAPI应用管理',
  45. 'uri' => 'openapi-apps',
  46. 'icon' => 'fa-key',
  47. 'order' => 10,
  48. ],
  49. [
  50. 'title' => 'API密钥管理',
  51. 'uri' => 'openapi-keys',
  52. 'icon' => 'fa-key',
  53. 'order' => 20,
  54. ],
  55. [
  56. 'title' => 'API调用日志',
  57. 'uri' => 'openapi-logs',
  58. 'icon' => 'fa-list-alt',
  59. 'order' => 30,
  60. ],
  61. ],
  62. ],
  63. 'thirdparty' => [
  64. 'title' => 'ThirdParty模块',
  65. 'icon' => 'fa-server',
  66. 'order' => 20,
  67. 'children' => [
  68. [
  69. 'title' => '第三方服务管理',
  70. 'uri' => 'thirdparty/services',
  71. 'icon' => 'fa-server',
  72. 'order' => 10,
  73. ],
  74. [
  75. 'title' => '认证凭证管理',
  76. 'uri' => 'thirdparty/credentials',
  77. 'icon' => 'fa-shield-alt',
  78. 'order' => 20,
  79. ],
  80. [
  81. 'title' => '调用日志管理',
  82. 'uri' => 'thirdparty/logs',
  83. 'icon' => 'fa-file-text',
  84. 'order' => 30,
  85. ],
  86. [
  87. 'title' => '配额管理',
  88. 'uri' => 'thirdparty/quotas',
  89. 'icon' => 'fa-tachometer-alt',
  90. 'order' => 40,
  91. ],
  92. [
  93. 'title' => '监控记录',
  94. 'uri' => 'thirdparty/monitors',
  95. 'icon' => 'fa-heartbeat',
  96. 'order' => 50,
  97. ],
  98. [
  99. 'title' => '统计报告',
  100. 'uri' => 'thirdparty/reports/overview',
  101. 'icon' => 'fa-chart-bar',
  102. 'order' => 60,
  103. ],
  104. ],
  105. ],
  106. ];
  107. /**
  108. * 执行命令
  109. *
  110. * @return int
  111. */
  112. public function handle(): int
  113. {
  114. try {
  115. // 检查父菜单是否存在
  116. if (!$this->checkParentMenu()) {
  117. $this->error("父菜单 '外接管理' (ID: {$this->parentMenuId}) 不存在");
  118. return 1;
  119. }
  120. $this->info("开始重构外接管理菜单结构...");
  121. // 显示当前菜单结构
  122. $this->displayCurrentStructure();
  123. // 确认操作
  124. if (!$this->option('force') && !$this->confirm('确定要重构菜单结构吗?这将删除现有的子菜单并重新创建。')) {
  125. $this->info('操作已取消');
  126. return 0;
  127. }
  128. // 备份现有菜单
  129. $this->backupCurrentMenus();
  130. // 删除现有子菜单
  131. $this->deleteExistingSubMenus();
  132. // 创建新的菜单结构
  133. $this->createNewMenuStructure();
  134. // 显示新的菜单结构
  135. $this->displayNewStructure();
  136. $this->info("✅ 菜单结构重构完成!");
  137. return 0;
  138. } catch (\Exception $e) {
  139. $this->error("重构菜单失败: " . $e->getMessage());
  140. return 1;
  141. }
  142. }
  143. /**
  144. * 检查父菜单是否存在
  145. *
  146. * @return bool
  147. */
  148. protected function checkParentMenu(): bool
  149. {
  150. return DB::table('admin_menu')
  151. ->where('id', $this->parentMenuId)
  152. ->where('title', '外接管理')
  153. ->exists();
  154. }
  155. /**
  156. * 显示当前菜单结构
  157. *
  158. * @return void
  159. */
  160. protected function displayCurrentStructure(): void
  161. {
  162. $this->info("\n当前菜单结构:");
  163. $this->line("外接管理 (fa-plug)");
  164. $currentMenus = DB::table('admin_menu')
  165. ->where('parent_id', $this->parentMenuId)
  166. ->orderBy('order')
  167. ->get(['title', 'uri', 'icon']);
  168. foreach ($currentMenus as $menu) {
  169. $icon = $menu->icon ? "({$menu->icon})" : '';
  170. $this->line(" ├── {$menu->title} {$icon} -> {$menu->uri}");
  171. }
  172. }
  173. /**
  174. * 备份现有菜单
  175. *
  176. * @return void
  177. */
  178. protected function backupCurrentMenus(): void
  179. {
  180. $timestamp = now()->format('Y_m_d_H_i_s');
  181. $backupTable = "kku_admin_menu_backup_{$timestamp}";
  182. // 创建备份表
  183. DB::statement("CREATE TABLE {$backupTable} AS SELECT * FROM kku_admin_menu WHERE parent_id = {$this->parentMenuId}");
  184. $this->info("✓ 已备份现有菜单到表: {$backupTable}");
  185. }
  186. /**
  187. * 删除现有子菜单
  188. *
  189. * @return void
  190. */
  191. protected function deleteExistingSubMenus(): void
  192. {
  193. $deletedCount = DB::table('admin_menu')
  194. ->where('parent_id', $this->parentMenuId)
  195. ->delete();
  196. $this->info("✓ 删除了 {$deletedCount} 个现有子菜单");
  197. }
  198. /**
  199. * 创建新的菜单结构
  200. *
  201. * @return void
  202. */
  203. protected function createNewMenuStructure(): void
  204. {
  205. $now = now();
  206. foreach ($this->menuStructure as $moduleKey => $module) {
  207. // 创建模块菜单(二级菜单)
  208. $moduleId = DB::table('admin_menu')->insertGetId([
  209. 'parent_id' => $this->parentMenuId,
  210. 'order' => $module['order'],
  211. 'title' => $module['title'],
  212. 'icon' => $module['icon'],
  213. 'uri' => '',
  214. 'extension' => '',
  215. 'show' => 1,
  216. 'created_at' => $now,
  217. 'updated_at' => $now,
  218. ]);
  219. $this->line("✓ 创建模块菜单: {$module['title']} (ID: {$moduleId})");
  220. // 创建模块下的子菜单(三级菜单)
  221. foreach ($module['children'] as $child) {
  222. $childId = DB::table('admin_menu')->insertGetId([
  223. 'parent_id' => $moduleId,
  224. 'order' => $child['order'],
  225. 'title' => $child['title'],
  226. 'icon' => $child['icon'],
  227. 'uri' => $child['uri'],
  228. 'extension' => '',
  229. 'show' => 1,
  230. 'created_at' => $now,
  231. 'updated_at' => $now,
  232. ]);
  233. $this->line(" ├── 创建子菜单: {$child['title']} (ID: {$childId}) -> {$child['uri']}");
  234. }
  235. }
  236. }
  237. /**
  238. * 显示新的菜单结构
  239. *
  240. * @return void
  241. */
  242. protected function displayNewStructure(): void
  243. {
  244. $this->info("\n新的菜单结构:");
  245. $this->line("外接管理 (fa-plug)");
  246. // 获取二级菜单
  247. $modules = DB::table('admin_menu')
  248. ->where('parent_id', $this->parentMenuId)
  249. ->orderBy('order')
  250. ->get(['id', 'title', 'icon']);
  251. foreach ($modules as $module) {
  252. $icon = $module->icon ? "({$module->icon})" : '';
  253. $this->line("├── {$module->title} {$icon}");
  254. // 获取三级菜单
  255. $children = DB::table('admin_menu')
  256. ->where('parent_id', $module->id)
  257. ->orderBy('order')
  258. ->get(['title', 'uri', 'icon']);
  259. foreach ($children as $child) {
  260. $childIcon = $child->icon ? "({$child->icon})" : '';
  261. $this->line("│ ├── {$child->title} {$childIcon} -> {$child->uri}");
  262. }
  263. }
  264. }
  265. /**
  266. * 获取菜单统计信息
  267. *
  268. * @return array
  269. */
  270. protected function getMenuStats(): array
  271. {
  272. $modules = DB::table('admin_menu')
  273. ->where('parent_id', $this->parentMenuId)
  274. ->count();
  275. $totalChildren = DB::table('admin_menu as parent')
  276. ->join('admin_menu as child', 'parent.id', '=', 'child.parent_id')
  277. ->where('parent.parent_id', $this->parentMenuId)
  278. ->count();
  279. return [
  280. 'modules' => $modules,
  281. 'total_children' => $totalChildren,
  282. ];
  283. }
  284. /**
  285. * 验证菜单结构
  286. *
  287. * @return bool
  288. */
  289. protected function validateMenuStructure(): bool
  290. {
  291. $stats = $this->getMenuStats();
  292. $expectedModules = count($this->menuStructure);
  293. $expectedChildren = array_sum(array_map(fn($module) => count($module['children']), $this->menuStructure));
  294. if ($stats['modules'] !== $expectedModules) {
  295. $this->warn("模块数量不匹配: 期望 {$expectedModules} 个,实际 {$stats['modules']} 个");
  296. return false;
  297. }
  298. if ($stats['total_children'] !== $expectedChildren) {
  299. $this->warn("子菜单数量不匹配: 期望 {$expectedChildren} 个,实际 {$stats['total_children']} 个");
  300. return false;
  301. }
  302. return true;
  303. }
  304. }