package system import ( "context" "errors" "strings" "kra/internal/biz/system" "kra/internal/data/model" "kra/internal/data/query" "gorm.io/gorm" ) type apiRepo struct { db *gorm.DB } // NewApiRepo 创建API仓储 func NewApiRepo(db *gorm.DB) system.ApiRepo { return &apiRepo{db: db} } func (r *apiRepo) Create(ctx context.Context, api *system.Api) error { _, err := query.SysAPI.WithContext(ctx).Where( query.SysAPI.Path.Eq(api.Path), query.SysAPI.Method.Eq(api.Method), ).First() if err == nil { return errors.New("存在相同api") } if !errors.Is(err, gorm.ErrRecordNotFound) { return err } m := toModelAPI(api) return query.SysAPI.WithContext(ctx).Create(m) } func (r *apiRepo) Update(ctx context.Context, api *system.Api) error { old, err := query.SysAPI.WithContext(ctx).Where(query.SysAPI.ID.Eq(int64(api.ID))).First() if err != nil { return err } if old.Path != api.Path || old.Method != api.Method { dup, ferr := query.SysAPI.WithContext(ctx).Where( query.SysAPI.Path.Eq(api.Path), query.SysAPI.Method.Eq(api.Method), ).First() if ferr == nil && dup.ID != int64(api.ID) { return errors.New("存在相同api路径") } if ferr != nil && !errors.Is(ferr, gorm.ErrRecordNotFound) { return ferr } } m := toModelAPI(api) _, err = query.SysAPI.WithContext(ctx).Where(query.SysAPI.ID.Eq(int64(api.ID))).Updates(m) return err } func (r *apiRepo) Delete(ctx context.Context, id uint) error { _, err := query.SysAPI.WithContext(ctx).Where(query.SysAPI.ID.Eq(int64(id))).Delete() return err } func (r *apiRepo) DeleteByIds(ctx context.Context, ids []uint) error { int64Ids := make([]int64, len(ids)) for i, id := range ids { int64Ids[i] = int64(id) } _, err := query.SysAPI.WithContext(ctx).Where(query.SysAPI.ID.In(int64Ids...)).Delete() return err } func (r *apiRepo) FindByID(ctx context.Context, id uint) (*system.Api, error) { m, err := query.SysAPI.WithContext(ctx).Where(query.SysAPI.ID.Eq(int64(id))).First() if err != nil { return nil, err } return toBizAPI(m), nil } func (r *apiRepo) FindByPathMethod(ctx context.Context, path, method string) (*system.Api, error) { m, err := query.SysAPI.WithContext(ctx).Where( query.SysAPI.Path.Eq(path), query.SysAPI.Method.Eq(method), ).First() if err != nil { return nil, err } return toBizAPI(m), nil } func (r *apiRepo) List(ctx context.Context, page, pageSize int, filters map[string]string, orderKey string, desc bool) ([]*system.Api, int64, error) { q := query.SysAPI.WithContext(ctx) if v, ok := filters["path"]; ok && v != "" { q = q.Where(query.SysAPI.Path.Like("%" + v + "%")) } if v, ok := filters["description"]; ok && v != "" { q = q.Where(query.SysAPI.Description.Like("%" + v + "%")) } if v, ok := filters["method"]; ok && v != "" { q = q.Where(query.SysAPI.Method.Eq(v)) } if v, ok := filters["api_group"]; ok && v != "" { q = q.Where(query.SysAPI.APIGroup.Eq(v)) } total, err := q.Count() if err != nil { return nil, 0, err } orderMap := map[string]bool{"id": true, "path": true, "api_group": true, "description": true, "method": true} if orderKey != "" && orderMap[orderKey] { switch orderKey { case "id": if desc { q = q.Order(query.SysAPI.ID.Desc()) } else { q = q.Order(query.SysAPI.ID) } case "path": if desc { q = q.Order(query.SysAPI.Path.Desc()) } else { q = q.Order(query.SysAPI.Path) } case "api_group": if desc { q = q.Order(query.SysAPI.APIGroup.Desc()) } else { q = q.Order(query.SysAPI.APIGroup) } case "description": if desc { q = q.Order(query.SysAPI.Description.Desc()) } else { q = q.Order(query.SysAPI.Description) } case "method": if desc { q = q.Order(query.SysAPI.Method.Desc()) } else { q = q.Order(query.SysAPI.Method) } } } else { q = q.Order(query.SysAPI.ID.Desc()) } offset := (page - 1) * pageSize list, err := q.Offset(offset).Limit(pageSize).Find() if err != nil { return nil, 0, err } apis := make([]*system.Api, len(list)) for i, m := range list { apis[i] = toBizAPI(m) } return apis, total, nil } func (r *apiRepo) FindAll(ctx context.Context) ([]*system.Api, error) { list, err := query.SysAPI.WithContext(ctx).Order(query.SysAPI.ID.Desc()).Find() if err != nil { return nil, err } apis := make([]*system.Api, len(list)) for i, m := range list { apis[i] = toBizAPI(m) } return apis, nil } func (r *apiRepo) FindByIds(ctx context.Context, ids []uint) ([]*system.Api, error) { int64Ids := make([]int64, len(ids)) for i, id := range ids { int64Ids[i] = int64(id) } list, err := query.SysAPI.WithContext(ctx).Where(query.SysAPI.ID.In(int64Ids...)).Find() if err != nil { return nil, err } apis := make([]*system.Api, len(list)) for i, m := range list { apis[i] = toBizAPI(m) } return apis, nil } func (r *apiRepo) GetApiGroups(ctx context.Context) ([]string, map[string]string, error) { list, err := query.SysAPI.WithContext(ctx).Find() if err != nil { return nil, nil, err } groupMap := make(map[string]bool) apiGroupMap := make(map[string]string) var groups []string for _, m := range list { if !groupMap[m.APIGroup] { groupMap[m.APIGroup] = true groups = append(groups, m.APIGroup) } if len(m.Path) > 1 { parts := strings.Split(m.Path, "/") if len(parts) > 1 { apiGroupMap[parts[1]] = m.APIGroup } } } return groups, apiGroupMap, nil } func (r *apiRepo) CreateIgnoreApi(ctx context.Context, path, method string) error { m := &model.SysIgnoreAPI{ Path: path, Method: method, } return r.db.WithContext(ctx).Create(m).Error } func (r *apiRepo) DeleteIgnoreApi(ctx context.Context, path, method string) error { return r.db.WithContext(ctx).Unscoped().Where("path = ? AND method = ?", path, method).Delete(&model.SysIgnoreAPI{}).Error } func (r *apiRepo) FindAllIgnoreApis(ctx context.Context) ([]*system.IgnoreApi, error) { var list []model.SysIgnoreAPI if err := r.db.WithContext(ctx).Find(&list).Error; err != nil { return nil, err } result := make([]*system.IgnoreApi, len(list)) for i, m := range list { result[i] = &system.IgnoreApi{ Path: m.Path, Method: m.Method, } } return result, nil } // 转换函数 func toModelAPI(a *system.Api) *model.SysAPI { return &model.SysAPI{ ID: int64(a.ID), Path: a.Path, Description: a.Description, APIGroup: a.ApiGroup, Method: a.Method, } } func toBizAPI(m *model.SysAPI) *system.Api { return &system.Api{ ID: uint(m.ID), Path: m.Path, Description: m.Description, ApiGroup: m.APIGroup, Method: m.Method, } }