// ============================================================================= // SQL 业务操作封装 // 提供向后兼容的CRUD操作方法,支持 PostgreSQL // ============================================================================= package sql import ( "context" "gitea.com/red-future/common/beans" "gitea.com/red-future/common/utils" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/util/gconv" ) const ( PageSize = 20 ) type sqlDB struct { noTenantId bool } func DB(cache ...bool) *sqlDB { return &sqlDB{ noTenantId: false, } } // NoTenantId 不使用租户过滤 func (s *sqlDB) NoTenantId() *sqlDB { s.noTenantId = true return s } // Count 查询总数 func (s *sqlDB) Count(ctx context.Context, model *gdb.Model) (int64, error) { user, err := utils.GetUserInfo(ctx) if err != nil { return 0, err } // 如果没有调用 noTenantId,则添加 tenantId 过滤 if !s.noTenantId && !g.IsEmpty(user.TenantId) { model = model.Where("tenant_id", user.TenantId) } model = model.Where("is_deleted", false) // 执行查询 count, _ := model.Count(ctx) return int64(count), nil } // Insert 插入记录(集合版本) func (s *sqlDB) Insert(ctx context.Context, data interface{}, collection string) ([]any, error) { user, err := utils.GetUserInfo(ctx) if err != nil { return nil, err } model := g.DB().Model(collection) // 处理切片类型数据 var resultSlice []any if slice, ok := data.([]interface{}); ok { for _, item := range slice { // 转换为map dataMap := gconv.Map(item) delete(dataMap, "id") // 设置租户ID if !g.IsEmpty(user.TenantId) && g.IsEmpty(dataMap["tenant_id"]) { dataMap["tenant_id"] = user.TenantId } // 设置创建人 if !g.IsEmpty(user.UserName) && g.IsEmpty(dataMap["creator"]) { dataMap["creator"] = user.UserName } // 设置更新人 if !g.IsEmpty(user.UserName) && g.IsEmpty(dataMap["updater"]) { dataMap["updater"] = user.UserName } // 设置时间 now := gtime.Now().Time if g.IsEmpty(dataMap["created_at"]) { dataMap["created_at"] = now } if g.IsEmpty(dataMap["updated_at"]) { dataMap["updated_at"] = now } // 设置删除标记 if g.IsEmpty(dataMap["is_deleted"]) { dataMap["is_deleted"] = false } resultSlice = append(resultSlice, dataMap) } // 批量插入 result, err := model.Data(resultSlice).Insert(ctx) if err != nil { return nil, err } id, err := result.LastInsertId() if err != nil { return nil, err } return []any{id}, nil } // 单条数据插入 dataMap := gconv.Map(data) delete(dataMap, "id") // 设置租户ID if !g.IsEmpty(user.TenantId) && g.IsEmpty(dataMap["tenant_id"]) { dataMap["tenant_id"] = user.TenantId } // 设置创建人 if !g.IsEmpty(user.UserName) && g.IsEmpty(dataMap["creator"]) { dataMap["creator"] = user.UserName } // 设置更新人 if !g.IsEmpty(user.UserName) && g.IsEmpty(dataMap["updater"]) { dataMap["updater"] = user.UserName } // 设置时间 now := gtime.Now().Time if g.IsEmpty(dataMap["created_at"]) { dataMap["created_at"] = now } if g.IsEmpty(dataMap["updated_at"]) { dataMap["updated_at"] = now } // 设置删除标记 if g.IsEmpty(dataMap["is_deleted"]) { dataMap["is_deleted"] = false } // 执行插入 result, err := model.Data(dataMap).Insert(ctx) if err != nil { return nil, err } id, err := result.LastInsertId() if err != nil { return nil, err } return []any{id}, nil } // FindOne 根据ID查询单条记录 func (s *sqlDB) FindOne(ctx context.Context, id string, collection string, result interface{}) error { user, err := utils.GetUserInfo(ctx) if err != nil { return err } model := g.DB().Model(collection).Where("id", id) // 如果没有调用 noTenantId,则添加 tenantId 过滤 if !s.noTenantId && !g.IsEmpty(user.TenantId) { model = model.Where("tenant_id", user.TenantId) } model = model.Where("is_deleted", false) // 执行查询 return model.Scan(ctx, result) } // FindOneWithResult 根据ID查询单条记录并返回结果 func (s *sqlDB) FindOneWithResult(ctx context.Context, id string, collection string, result interface{}) (interface{}, error) { user, err := utils.GetUserInfo(ctx) if err != nil { return nil, err } model := g.DB().Model(collection).Where("id", id) // 如果没有调用 noTenantId,则添加 tenantId 过滤 if !s.noTenantId && !g.IsEmpty(user.TenantId) { model = model.Where("tenant_id", user.TenantId) } model = model.Where("is_deleted", false) // 执行查询 err = model.Scan(ctx, result) return result, err } // FindOneByModel 根据Model查询单条记录 func (s *sqlDB) FindOneByModel(ctx context.Context, model *gdb.Model, result interface{}) error { user, err := utils.GetUserInfo(ctx) if err != nil { return err } // 如果没有调用 noTenantId,则添加 tenantId 过滤 if !s.noTenantId && !g.IsEmpty(user.TenantId) { model = model.Where("tenant_id", user.TenantId) } model = model.Where("is_deleted", false) // 执行查询 return model.Scan(ctx, result) } // Find 查询多条记录(集合版本) func (s *sqlDB) Find(ctx context.Context, model *gdb.Model, collection string, result interface{}, page *beans.Page, orderBy []beans.OrderBy) (int64, error) { if model == nil { model = g.DB().Model(collection) } user, err := utils.GetUserInfo(ctx) if err != nil { return 0, err } // 如果没有调用 noTenantId,则添加 tenantId 过滤 if !s.noTenantId && !g.IsEmpty(user.TenantId) { model = model.Where("tenant_id", user.TenantId) } model = model.Where("is_deleted", false) // 分页处理 limit := int64(PageSize) offset := int64(0) if page != nil && !g.IsEmpty(page.PageNum) && !g.IsEmpty(page.PageSize) { limit = page.PageSize if limit != -1 { offset = (page.PageNum - 1) * limit } } // 排序处理 if orderBy != nil && len(orderBy) > 0 { for _, o := range orderBy { orderStr := string(o.Order) if orderStr == "asc" || orderStr == "ASC" { model = model.OrderAsc(o.Field) } else { model = model.OrderDesc(o.Field) } } } else { model = model.OrderDesc("created_at") } // 执行查询 if limit != -1 { total, err := s.Count(ctx, model) if err != nil { return 0, err } if total == 0 { return 0, nil } err = model.Offset(int(offset)).Limit(int(limit)).Scan(ctx, result) if err != nil { return 0, err } return total, nil } // 不分页,查询全部 err = model.Scan(ctx, result) if err != nil { return 0, err } // 获取结果集长度 return 0, nil } // Update 更新记录(ID版本) func (s *sqlDB) Update(ctx context.Context, id string, collection string, data interface{}) (int64, error) { user, err := utils.GetUserInfo(ctx) if err != nil { return 0, err } model := g.DB().Model(collection).Where("id", id) // 如果没有调用 noTenantId,则添加 tenantId 过滤 if !s.noTenantId && !g.IsEmpty(user.TenantId) { model = model.Where("tenant_id", user.TenantId) } model = model.Where("is_deleted", false) // 转换为map dataMap := gconv.Map(data) delete(dataMap, "id") // 设置更新人 if !g.IsEmpty(user.UserName) && g.IsEmpty(dataMap["updater"]) { dataMap["updater"] = user.UserName } // 设置更新时间 dataMap["updated_at"] = gtime.Now().Time // 执行更新 result, err := model.Data(dataMap).Update(ctx) if err != nil { return 0, err } affected, err := result.RowsAffected() if err != nil { return 0, err } return affected, err } // Delete 软删除(ID版本) func (s *sqlDB) Delete(ctx context.Context, id string, collection string) (int64, error) { user, err := utils.GetUserInfo(ctx) if err != nil { return 0, err } model := g.DB().Model(collection).Where("id", id) // 如果没有调用 noTenantId,则添加 tenantId 过滤 if !s.noTenantId && !g.IsEmpty(user.TenantId) { model = model.Where("tenant_id", user.TenantId) } model = model.Where("is_deleted", false) // 软删除 data := map[string]interface{}{ "is_deleted": true, "updater": user.UserName, "updated_at": gtime.Now().Time, } result, err := model.Data(data).Update(ctx) if err != nil { return 0, err } affected, err := result.RowsAffected() if err != nil { return 0, err } return affected, err } // DeleteByModel 软删除(Model版本) func (s *sqlDB) DeleteSoftByModel(ctx context.Context, model *gdb.Model) (int64, error) { user, err := utils.GetUserInfo(ctx) if err != nil { return 0, err } // 如果没有调用 noTenantId,则添加 tenantId 过滤 if !s.noTenantId && !g.IsEmpty(user.TenantId) { model = model.Where("tenant_id", user.TenantId) } model = model.Where("is_deleted", false) // 软删除 data := map[string]interface{}{ "is_deleted": true, "updater": user.UserName, "updated_at": gtime.Now().Time, } result, err := model.Data(data).Update(ctx) if err != nil { return 0, err } affected, err := result.RowsAffected() if err != nil { return 0, err } return affected, err } // Increment 字段自增 func (s *sqlDB) Increment(ctx context.Context, id string, collection string, field string, value int64) (int64, error) { user, err := utils.GetUserInfo(ctx) if err != nil { return 0, err } model := g.DB().Model(collection).Where("id", id) // 如果没有调用 noTenantId,则添加 tenantId 过滤 if !s.noTenantId && !g.IsEmpty(user.TenantId) { model = model.Where("tenant_id", user.TenantId) } model = model.Where("is_deleted", false) // 设置更新人和时间 data := map[string]interface{}{ "updater": user.UserName, "updated_at": gtime.Now().Time, } // 使用原生SQL实现自增 data[field] = gdb.Raw(field + " + " + gconv.String(value) + "::bigint") // 执行更新 result, err := model.Data(data).Update(ctx) if err != nil { return 0, err } affected, err := result.RowsAffected() if err != nil { return 0, err } return affected, err } // DeleteSoft 软删除(ID版本) func (s *sqlDB) DeleteSoft(ctx context.Context, id string, collection string) (int64, error) { return s.Delete(ctx, id, collection) } // Model 获取Model func (s *sqlDB) Model(collection string) *gdb.Model { return g.DB().Model(collection) } // BuildUpdateData 构建更新数据 func BuildUpdateData(ctx context.Context, req interface{}) (map[string]interface{}, error) { return gconv.Map(req), nil }