package service import ( "context" "fmt" "regexp" "strings" "hm-server/app/main/model" "github.com/pkg/errors" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/rest" ) type ApiRegistryService struct { adminApiModel model.AdminApiModel } func NewApiRegistryService(adminApiModel model.AdminApiModel) *ApiRegistryService { return &ApiRegistryService{ adminApiModel: adminApiModel, } } // RegisterAllApis 自动注册所有API到数据库 func (s *ApiRegistryService) RegisterAllApis(ctx context.Context, routes []rest.Route) error { logx.Infof("开始注册API,共 %d 个路由", len(routes)) registeredCount := 0 skippedCount := 0 for _, route := range routes { // 跳过不需要权限控制的API if s.shouldSkipApi(route.Path) { skippedCount++ continue } // 解析API信息 apiInfo := s.parseRouteToApi(route) // 检查是否已存在 existing, err := s.adminApiModel.FindOneByApiCode(ctx, apiInfo.ApiCode) if err != nil && !errors.Is(err, model.ErrNotFound) { logx.Errorf("查询API失败: %v, apiCode: %s", err, apiInfo.ApiCode) continue } // 如果不存在则插入 if existing == nil { _, err = s.adminApiModel.Insert(ctx, nil, apiInfo) if err != nil { logx.Errorf("插入API失败: %v, apiCode: %s", err, apiInfo.ApiCode) continue } registeredCount++ logx.Infof("注册API成功: %s %s", apiInfo.Method, apiInfo.Url) } else { // 如果存在但信息有变化,则更新 if s.shouldUpdateApi(existing, apiInfo) { existing.ApiName = apiInfo.ApiName existing.Method = apiInfo.Method existing.Url = apiInfo.Url existing.Description = apiInfo.Description _, err = s.adminApiModel.Update(ctx, nil, existing) if err != nil { logx.Errorf("更新API失败: %v, apiCode: %s", err, apiInfo.ApiCode) continue } logx.Infof("更新API成功: %s %s", apiInfo.Method, apiInfo.Url) } } } logx.Infof("API注册完成,新增: %d, 跳过: %d", registeredCount, skippedCount) return nil } // shouldSkipApi 判断是否应该跳过此API func (s *ApiRegistryService) shouldSkipApi(path string) bool { // 跳过公开API skipPaths := []string{ "/api/v1/admin/auth/login", // 登录接口 "/api/v1/app/", // 前端应用接口 "/api/v1/agent/", // 代理接口 "/api/v1/user/", // 用户接口 "/api/v1/auth/", // 认证接口 "/api/v1/notification/", // 通知接口 "/api/v1/pay/", // 支付接口 "/api/v1/query/", // 查询接口 "/api/v1/product/", // 产品接口 "/api/v1/authorization/", // 授权接口 "/health", // 健康检查 } for _, skipPath := range skipPaths { if strings.HasPrefix(path, skipPath) { return true } } return false } // parseRouteToApi 将路由解析为API信息 func (s *ApiRegistryService) parseRouteToApi(route rest.Route) *model.AdminApi { // 生成API编码 apiCode := s.generateApiCode(route.Method, route.Path) // 生成API名称 apiName := s.generateApiName(route.Path) // 生成描述 description := s.generateDescription(route.Method, route.Path) return &model.AdminApi{ ApiName: apiName, ApiCode: apiCode, Method: route.Method, Url: route.Path, Status: 1, // 默认启用 Description: description, } } // generateApiCode 生成API编码 func (s *ApiRegistryService) generateApiCode(method, path string) string { // 移除路径参数,如 :id cleanPath := regexp.MustCompile(`/:[\w]+`).ReplaceAllString(path, "") // 转换为小写并替换特殊字符 apiCode := strings.ToLower(method) + "_" + strings.ReplaceAll(cleanPath, "/", "_") apiCode = strings.TrimPrefix(apiCode, "_") apiCode = strings.TrimSuffix(apiCode, "_") return apiCode } // generateApiName 生成API名称 func (s *ApiRegistryService) generateApiName(path string) string { // 从路径中提取模块和操作 parts := strings.Split(strings.Trim(path, "/"), "/") if len(parts) < 3 { return path } // 获取模块名和操作名 module := parts[len(parts)-2] action := parts[len(parts)-1] // 转换为中文描述 moduleMap := map[string]string{ "agent": "代理管理", "auth": "认证管理", "feature": "功能管理", "menu": "菜单管理", "notification": "通知管理", "order": "订单管理", "platform_user": "平台用户", "product": "产品管理", "promotion": "推广管理", "query": "查询管理", "role": "角色管理", "user": "用户管理", } actionMap := map[string]string{ "list": "列表", "create": "创建", "update": "更新", "delete": "删除", "detail": "详情", "login": "登录", "config": "配置", "example": "示例", "refund": "退款", "link": "链接", "stats": "统计", "cleanup": "清理", "record": "记录", } moduleName := moduleMap[module] if moduleName == "" { moduleName = module } actionName := actionMap[action] if actionName == "" { actionName = action } return fmt.Sprintf("%s-%s", moduleName, actionName) } // generateDescription 生成API描述 func (s *ApiRegistryService) generateDescription(method, path string) string { methodMap := map[string]string{ "GET": "查询", "POST": "创建", "PUT": "更新", "DELETE": "删除", } methodDesc := methodMap[method] if methodDesc == "" { methodDesc = method } apiName := s.generateApiName(path) return fmt.Sprintf("%s%s", methodDesc, apiName) } // shouldUpdateApi 判断是否需要更新API func (s *ApiRegistryService) shouldUpdateApi(existing, new *model.AdminApi) bool { return existing.ApiName != new.ApiName || existing.Method != new.Method || existing.Url != new.Url || existing.Description != new.Description }