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

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
})
}