You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
6.9 KiB
214 lines
6.9 KiB
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 |
|
}) |
|
}
|
|
|