From 5e4306f11a2094c28017f7c5040419a95794bd8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=96=8C?= <259278618@qq.com> Date: Thu, 12 Feb 2026 08:38:35 +0800 Subject: [PATCH] .gitignore --- beans/beans.go | 11 ++ sql/sql.go | 459 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 470 insertions(+) create mode 100644 sql/sql.go diff --git a/beans/beans.go b/beans/beans.go index 58c7281..31806bd 100644 --- a/beans/beans.go +++ b/beans/beans.go @@ -36,6 +36,17 @@ type MongoBaseDO struct { IsDeleted bool `bson:"isDeleted" json:"isDeleted" default:"false"` } +// SQLBaseDO SQL数据库基础实体 +type SQLBaseDO struct { + Id uint64 `json:"id"` // 主键ID + Creator string `json:"creator"` // 创建人 + CreatedAt *time.Time `json:"createdAt"` // 创建时间 + Updater string `json:"updater"` // 更新人 + UpdatedAt *time.Time `json:"updatedAt"` // 更新时间 + TenantId string `json:"tenantId"` // 租户ID + IsDeleted bool `json:"isDeleted"` // 是否删除 +} + type User struct { UserId interface{} `bson:"userId" json:"userId"` // 用户ID UserName interface{} `bson:"userName" json:"userName"` // 用户名 diff --git a/sql/sql.go b/sql/sql.go new file mode 100644 index 0000000..d792dd6 --- /dev/null +++ b/sql/sql.go @@ -0,0 +1,459 @@ +// ============================================================================= +// SQL 业务操作封装 +// 提供向后兼容的CRUD操作方法,支持 PostgreSQL +// ============================================================================= + +package sql + +import ( + "context" + + "gitee.com/red-future---jilin-g/common/beans" + "gitee.com/red-future---jilin-g/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 +}