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 safeString(old.Path) != api.Path || safeString(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 { path := safeString(m.Path) apiGroup := safeString(m.APIGroup) if !groupMap[apiGroup] { groupMap[apiGroup] = true groups = append(groups, apiGroup) } if len(path) > 1 { parts := strings.Split(path, "/") if len(parts) > 1 { apiGroupMap[parts[1]] = 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: safeString(m.Path), Method: safeString(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: safeString(m.Path), Description: safeString(m.Description), ApiGroup: safeString(m.APIGroup), Method: safeString(m.Method), } }