package repository import ( "context" "fmt" "gofaster/internal/auth/model" "gofaster/internal/shared/repository" "gorm.io/gorm" ) type ResourceRepository interface { Create(ctx context.Context, resource *model.Resource) error Update(ctx context.Context, resource *model.Resource) error Delete(ctx context.Context, id uint) error GetByID(ctx context.Context, id uint) (*model.Resource, error) GetByCode(ctx context.Context, code string) (*model.Resource, error) List(ctx context.Context, offset, limit int) ([]*model.Resource, int64, error) ListByModule(ctx context.Context, module string) ([]*model.Resource, error) ListByType(ctx context.Context, resourceType string) ([]*model.Resource, error) ListPublic(ctx context.Context) ([]*model.Resource, error) GetTree(ctx context.Context) ([]*model.Resource, error) BatchCreate(ctx context.Context, resources []*model.Resource) error BatchUpdate(ctx context.Context, resources []*model.Resource) error SyncFromRoutes(ctx context.Context, routes []RouteInfo) error } type resourceRepository struct { *repository.BaseRepo } func NewResourceRepository(db *gorm.DB) ResourceRepository { return &resourceRepository{ BaseRepo: repository.NewBaseRepo(db), } } func (r *resourceRepository) Create(ctx context.Context, resource *model.Resource) error { return r.DB().WithContext(ctx).Create(resource).Error } func (r *resourceRepository) Update(ctx context.Context, resource *model.Resource) error { return r.DB().WithContext(ctx).Save(resource).Error } func (r *resourceRepository) Delete(ctx context.Context, id uint) error { return r.DB().WithContext(ctx).Delete(&model.Resource{}, id).Error } func (r *resourceRepository) GetByID(ctx context.Context, id uint) (*model.Resource, error) { var resource model.Resource err := r.DB().WithContext(ctx).First(&resource, id).Error if err != nil { return nil, err } return &resource, nil } func (r *resourceRepository) GetByCode(ctx context.Context, code string) (*model.Resource, error) { var resource model.Resource err := r.DB().WithContext(ctx).Where("code = ?", code).First(&resource).Error if err != nil { return nil, err } return &resource, nil } func (r *resourceRepository) List(ctx context.Context, offset, limit int) ([]*model.Resource, int64, error) { var resources []*model.Resource var total int64 // 添加调试日志 fmt.Printf("🔍 [资源查询] 开始查询资源列表,offset=%d, limit=%d\n", offset, limit) err := r.DB().WithContext(ctx).Model(&model.Resource{}).Count(&total).Error if err != nil { fmt.Printf("🔍 [资源查询] 统计总数失败: %v\n", err) return nil, 0, err } fmt.Printf("🔍 [资源查询] 数据库中共有 %d 条资源记录\n", total) err = r.DB().WithContext(ctx).Offset(offset).Limit(limit).Order("sort ASC, id ASC").Find(&resources).Error if err != nil { fmt.Printf("🔍 [资源查询] 查询资源列表失败: %v\n", err) return nil, 0, err } fmt.Printf("🔍 [资源查询] 查询到 %d 条资源记录\n", len(resources)) return resources, total, nil } func (r *resourceRepository) ListByModule(ctx context.Context, module string) ([]*model.Resource, error) { var resources []*model.Resource err := r.DB().WithContext(ctx).Where("module = ? AND status = 1", module).Order("sort ASC, id ASC").Find(&resources).Error return resources, err } func (r *resourceRepository) ListByType(ctx context.Context, resourceType string) ([]*model.Resource, error) { var resources []*model.Resource err := r.DB().WithContext(ctx).Where("type = ? AND status = 1", resourceType).Order("sort ASC, id ASC").Find(&resources).Error return resources, err } func (r *resourceRepository) ListPublic(ctx context.Context) ([]*model.Resource, error) { var resources []*model.Resource err := r.DB().WithContext(ctx).Where("is_public = true AND status = 1").Order("sort ASC, id ASC").Find(&resources).Error return resources, err } func (r *resourceRepository) GetTree(ctx context.Context) ([]*model.Resource, error) { var resources []*model.Resource err := r.DB().WithContext(ctx).Where("status = 1").Order("sort ASC, id ASC").Find(&resources).Error if err != nil { return nil, err } // 构建树形结构 return r.buildTree(resources), nil } func (r *resourceRepository) buildTree(resources []*model.Resource) []*model.Resource { resourceMap := make(map[uint]*model.Resource) var roots []*model.Resource // 创建映射 for _, resource := range resources { resourceMap[resource.ID] = resource } // 构建树形结构 for _, resource := range resources { if resource.ParentID == nil { roots = append(roots, resource) } else { if _, exists := resourceMap[*resource.ParentID]; exists { // 这里需要添加Children字段到Resource模型中 // 暂时跳过,后续可以扩展 } } } return roots } func (r *resourceRepository) BatchCreate(ctx context.Context, resources []*model.Resource) error { return r.DB().WithContext(ctx).CreateInBatches(resources, 100).Error } func (r *resourceRepository) BatchUpdate(ctx context.Context, resources []*model.Resource) error { return r.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error { for _, resource := range resources { if err := tx.Save(resource).Error; err != nil { return err } } return nil }) } // RouteInfo 路由信息 type RouteInfo struct { Path string Method string Name string Description string Module string IsPublic bool } func (r *resourceRepository) SyncFromRoutes(ctx context.Context, routes []RouteInfo) error { return r.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error { for _, route := range routes { // 生成资源代码 code := fmt.Sprintf("%s:%s:%s", route.Module, route.Method, route.Path) // 检查资源是否已存在 var existingResource model.Resource err := tx.Where("code = ?", code).First(&existingResource).Error if err == gorm.ErrRecordNotFound { // 创建新资源 resource := &model.Resource{ Name: route.Name, Code: code, Type: "api", Path: route.Path, Method: route.Method, Description: route.Description, Module: route.Module, Status: 1, IsPublic: route.IsPublic, } if err := tx.Create(resource).Error; err != nil { return fmt.Errorf("创建资源失败: %v", err) } fmt.Printf("✅ 创建资源: %s (%s %s)\n", route.Name, route.Method, route.Path) } else if err != nil { return fmt.Errorf("查询资源失败: %v", err) } else { // 更新现有资源 existingResource.Name = route.Name existingResource.Description = route.Description existingResource.IsPublic = route.IsPublic if err := tx.Save(&existingResource).Error; err != nil { return fmt.Errorf("更新资源失败: %v", err) } fmt.Printf("🔄 更新资源: %s (%s %s)\n", route.Name, route.Method, route.Path) } } return nil }) }