diff --git a/backend/app/Command/RouteSyncCommand.php b/backend/app/Command/RouteSyncCommand.php new file mode 100644 index 0000000..adba0c0 --- /dev/null +++ b/backend/app/Command/RouteSyncCommand.php @@ -0,0 +1,107 @@ +setDescription('同步 Hyperf 注解路由到 routes 表'); + } + + public function handle(): void + { + $factory = $this->container->get(DispatcherFactory::class); + $router = $factory->getRouter('http'); + $routes = $this->extractRoutes($router); + + $synced = 0; + foreach ($routes as $route_info) { + Route::query()->updateOrCreate( + ['method' => $route_info['method'], 'path' => $route_info['path']], + ['name' => $route_info['name']] + ); + $synced++; + } + + $this->info("Synced {$synced} routes to database."); + } + + /** + * 从路由收集器中提取所有 API 路由 + * + * @return array + */ + protected function extractRoutes(RouteCollector $router): array + { + $routes = []; + [$staticRouters, $variableRouters] = $router->getData(); + + // 静态路由(无路径参数) + foreach ($staticRouters as $method => $items) { + foreach ($items as $handler) { + $this->collectRoute($routes, $method, $handler); + } + } + + // 动态路由(含路径参数如 {id}) + foreach ($variableRouters as $method => $items) { + foreach ($items as $item) { + if (is_array($item['routeMap'] ?? false)) { + foreach ($item['routeMap'] as $routeMap) { + $this->collectRoute($routes, $method, $routeMap[0]); + } + } + } + } + + return $routes; + } + + /** + * 收集单条路由信息,仅同步 /api/ 前缀的路由 + */ + protected function collectRoute(array &$routes, string $method, Handler $handler): void + { + $path = $handler->route; + + // 仅同步 API 路由 + if (!str_starts_with($path, '/api/')) { + return; + } + + // 解析 action 名称 + $name = null; + if (is_array($handler->callback)) { + $name = $handler->callback[0] . '::' . $handler->callback[1]; + } elseif (is_string($handler->callback)) { + $name = $handler->callback; + } + + $key = $method . '|' . $path; + if (!isset($routes[$key])) { + $routes[$key] = [ + 'method' => $method, + 'path' => $path, + 'name' => $name, + ]; + } + } +} diff --git a/backend/app/Model/RouteGroup.php b/backend/app/Model/RouteGroup.php new file mode 100644 index 0000000..138a62b --- /dev/null +++ b/backend/app/Model/RouteGroup.php @@ -0,0 +1,53 @@ + 'integer', + 'sort_order' => 'integer', + 'created_at' => 'datetime', + ]; + + /** + * 分组下的路由 + */ + public function routes(): HasMany + { + return $this->hasMany(Route::class, 'group_id'); + } + + /** + * 拥有此分组的角色 + */ + public function roles(): BelongsToMany + { + return $this->belongsToMany(Role::class, 'role_route_groups', 'group_id', 'role_id'); + } +}