Compare commits

..

No commits in common. "main" and "v1.0.1019" have entirely different histories.

7 changed files with 52 additions and 109 deletions

View File

@ -60,7 +60,6 @@ func SetDefault() {
viper.Set("SERVER.mode", "release") viper.Set("SERVER.mode", "release")
viper.Set("DATABASE.type", "sqlite") viper.Set("DATABASE.type", "sqlite")
viper.Set("DATABASE.dns", gfile.Join(gfile.Pwd(), "db", "database.db")) viper.Set("DATABASE.dns", gfile.Join(gfile.Pwd(), "db", "database.db"))
viper.Set("DATABASE.debug", true)
viper.Set("JWT.secret", "SET-YOUR-SECRET") viper.Set("JWT.secret", "SET-YOUR-SECRET")
viper.Set("JWT.expire", 86400) viper.Set("JWT.expire", 86400)
} }

View File

@ -15,9 +15,8 @@ type ServerConfig struct {
// DataBaseConfig 数据库配置 // DataBaseConfig 数据库配置
type DataBaseConfig struct { type DataBaseConfig struct {
Dns string `mapstructure:"dns"` Dns string `mapstructure:"dns"`
Type string `mapstructure:"type"` Type string `mapstructure:"type"`
Debug bool `mapstructure:"debug"` // 是否开启 GORM 查询日志
} }
// JwtConfig JWT配置 // JwtConfig JWT配置

View File

@ -16,13 +16,12 @@ type ctx = context.Context
// IDao -------------------------- 核心接口定义 -------------------------- // IDao -------------------------- 核心接口定义 --------------------------
// IDao GORM 版本的Dao接口提供GORM DB实例和表相关信息 // IDao GORM 版本的Dao接口提供GORM DB实例和表相关信息
type IDao[T any] interface { type IDao interface {
DB() *gorm.DB // 返回GORM的DB实例 DB() *gorm.DB // 返回GORM的DB实例
Table() string // 返回表名 Table() string // 返回表名
PrimaryKey() string // 返回主键字段名id PrimaryKey() string // 返回主键字段名id
Ctx(ctx context.Context) *gorm.DB // 绑定上下文的DB实例 Ctx(ctx context.Context) *gorm.DB // 绑定上下文的DB实例
Transaction(ctx context.Context, f func(ctx context.Context, tx *gorm.DB) error) error // 事务方法 Transaction(ctx context.Context, f func(ctx context.Context, tx *gorm.DB) error) error // 事务方法
Column() *T
} }
// Paginate -------------------------- 分页结构体定义 -------------------------- // Paginate -------------------------- 分页结构体定义 --------------------------
@ -48,9 +47,9 @@ var pageInfo = []string{
} }
// Crud -------------------------- 泛型CURD核心结构体 -------------------------- // Crud -------------------------- 泛型CURD核心结构体 --------------------------
// Crud GORM 版本的泛型CURD封装R为对应的模型结构体 C为对应模型结构体的字段结构体 // Crud GORM 版本的泛型CURD封装R为对应的模型结构体
type Crud[R any, C any] struct { type Crud[R any] struct {
Dao IDao[C] Dao IDao
} }
// -------------------------- 工具方法:字段名转换(保持原代码的命名风格转换) -------------------------- // -------------------------- 工具方法:字段名转换(保持原代码的命名风格转换) --------------------------
@ -78,12 +77,8 @@ func caseConvert(key string, toSnake bool) string {
return result.String() return result.String()
} }
func (c Crud[R, C]) Columns() *C {
return c.Dao.Column()
}
// BuildWhere -------------------------- 原BuildWhere对应实现构建查询条件map -------------------------- // BuildWhere -------------------------- 原BuildWhere对应实现构建查询条件map --------------------------
func (c Crud[R, C]) BuildWhere(req any, changeWhere any, subWhere any, removeFields []string, isSnake ...bool) map[string]any { func (c Crud[R]) BuildWhere(req any, changeWhere any, subWhere any, removeFields []string, isSnake ...bool) map[string]any {
// 默认使用小写下划线方式 // 默认使用小写下划线方式
toSnake := true toSnake := true
if len(isSnake) > 0 && !isSnake[0] { if len(isSnake) > 0 && !isSnake[0] {
@ -175,7 +170,7 @@ func (c Crud[R, C]) BuildWhere(req any, changeWhere any, subWhere any, removeFie
} }
// BuildMap -------------------------- 原 BuildMap 对应实现:构建变更条件 map -------------------------- // BuildMap -------------------------- 原 BuildMap 对应实现:构建变更条件 map --------------------------
func (c Crud[R, C]) BuildMap(op string, value any, field ...string) map[string]any { func (c Crud[R]) BuildMap(op string, value any, field ...string) map[string]any {
res := map[string]any{ res := map[string]any{
"op": op, "op": op,
"field": "", "field": "",
@ -206,8 +201,8 @@ type WhereCondition struct {
// ). // ).
// AND(map[string]any{"deleted": 0}). // AND(map[string]any{"deleted": 0}).
// Build() // Build()
func (c Crud[R, C]) BuildWhereAndOr() *WhereBuilder[R, C] { func (c Crud[R]) BuildWhereAndOr() *WhereBuilder[R] {
return &WhereBuilder[R, C]{ return &WhereBuilder[R]{
conditions: make([]WhereCondition, 0), conditions: make([]WhereCondition, 0),
crud: c, crud: c,
} }
@ -215,13 +210,13 @@ func (c Crud[R, C]) BuildWhereAndOr() *WhereBuilder[R, C] {
// WhereBuilder -------------------------- WHERE 条件构建器 -------------------------- // WhereBuilder -------------------------- WHERE 条件构建器 --------------------------
// WhereBuilder 流式构建 WHERE 条件R 为模型类型参数) // WhereBuilder 流式构建 WHERE 条件R 为模型类型参数)
type WhereBuilder[R any, C any] struct { type WhereBuilder[R any] struct {
conditions []WhereCondition conditions []WhereCondition
crud Crud[R, C] crud Crud[R]
} }
// AND 添加 AND 条件 // AND 添加 AND 条件
func (wb *WhereBuilder[R, C]) AND(conditions ...interface{}) *WhereBuilder[R, C] { func (wb *WhereBuilder[R]) AND(conditions ...interface{}) *WhereBuilder[R] {
if len(conditions) > 0 { if len(conditions) > 0 {
wb.conditions = append(wb.conditions, WhereCondition{ wb.conditions = append(wb.conditions, WhereCondition{
AND: conditions, AND: conditions,
@ -231,7 +226,7 @@ func (wb *WhereBuilder[R, C]) AND(conditions ...interface{}) *WhereBuilder[R, C]
} }
// OR 添加 OR 条件OR 条件内部是或关系) // OR 添加 OR 条件OR 条件内部是或关系)
func (wb *WhereBuilder[R, C]) OR(conditions ...interface{}) *WhereBuilder[R, C] { func (wb *WhereBuilder[R]) OR(conditions ...interface{}) *WhereBuilder[R] {
if len(conditions) > 0 { if len(conditions) > 0 {
wb.conditions = append(wb.conditions, WhereCondition{ wb.conditions = append(wb.conditions, WhereCondition{
OR: conditions, OR: conditions,
@ -242,7 +237,7 @@ func (wb *WhereBuilder[R, C]) OR(conditions ...interface{}) *WhereBuilder[R, C]
// Build 构建最终的查询条件 // Build 构建最终的查询条件
// 返回格式map[string]any 或者可以直接用于 GORM 的 Where 子句 // 返回格式map[string]any 或者可以直接用于 GORM 的 Where 子句
func (wb *WhereBuilder[R, C]) Build() interface{} { func (wb *WhereBuilder[R]) Build() interface{} {
if len(wb.conditions) == 0 { if len(wb.conditions) == 0 {
return nil return nil
} }
@ -284,7 +279,7 @@ func (wb *WhereBuilder[R, C]) Build() interface{} {
} }
// buildORCondition 构建 OR 条件 // buildORCondition 构建 OR 条件
func (wb *WhereBuilder[R, C]) buildORCondition(orConds []interface{}) map[string]interface{} { func (wb *WhereBuilder[R]) buildORCondition(orConds []interface{}) map[string]interface{} {
if len(orConds) == 0 { if len(orConds) == 0 {
return nil return nil
} }
@ -317,8 +312,8 @@ func (wb *WhereBuilder[R, C]) buildORCondition(orConds []interface{}) map[string
// db.Where("status = ?", 1). // db.Where("status = ?", 1).
// Where(db.Where("age >= ?", 18).Or("age < ? AND vip = ?", 18, true)). // Where(db.Where("age >= ?", 18).Or("age < ? AND vip = ?", 18, true)).
// Find(&users) // Find(&users)
func (c Crud[R, C]) BuildWhereGORM(query interface{}, args ...interface{}) *GORMWhereBuilder[R, C] { func (c Crud[R]) BuildWhereGORM(query interface{}, args ...interface{}) *GORMWhereBuilder[R] {
return &GORMWhereBuilder[R, C]{ return &GORMWhereBuilder[R]{
DB: c.Dao.DB(), DB: c.Dao.DB(),
crud: c, crud: c,
query: query, query: query,
@ -328,15 +323,15 @@ func (c Crud[R, C]) BuildWhereGORM(query interface{}, args ...interface{}) *GORM
// GORMWhereBuilder -------------------------- GORM 原生 WHERE 构建器 -------------------------- // GORMWhereBuilder -------------------------- GORM 原生 WHERE 构建器 --------------------------
// GORMWhereBuilder 使用 GORM 原生 API 构建复杂查询R 为模型类型参数) // GORMWhereBuilder 使用 GORM 原生 API 构建复杂查询R 为模型类型参数)
type GORMWhereBuilder[R any, C any] struct { type GORMWhereBuilder[R any] struct {
*gorm.DB *gorm.DB
crud Crud[R, C] crud Crud[R]
query interface{} query interface{}
args []interface{} args []interface{}
} }
// Where 添加 WHERE 条件AND 关系) // Where 添加 WHERE 条件AND 关系)
func (gwb *GORMWhereBuilder[R, C]) Where(query interface{}, args ...interface{}) *GORMWhereBuilder[R, C] { func (gwb *GORMWhereBuilder[R]) Where(query interface{}, args ...interface{}) *GORMWhereBuilder[R] {
// 如果当前已经有查询条件,先应用 // 如果当前已经有查询条件,先应用
if gwb.query != nil { if gwb.query != nil {
gwb = gwb.Where(gwb.query, gwb.args...) gwb = gwb.Where(gwb.query, gwb.args...)
@ -347,7 +342,7 @@ func (gwb *GORMWhereBuilder[R, C]) Where(query interface{}, args ...interface{})
} }
// Or 添加 OR 条件 // Or 添加 OR 条件
func (gwb *GORMWhereBuilder[R, C]) Or(query interface{}, args ...interface{}) *GORMWhereBuilder[R, C] { func (gwb *GORMWhereBuilder[R]) Or(query interface{}, args ...interface{}) *GORMWhereBuilder[R] {
// 如果当前有未应用的查询条件,先应用 // 如果当前有未应用的查询条件,先应用
if gwb.query != nil { if gwb.query != nil {
gwb = gwb.Where(gwb.query, gwb.args...) gwb = gwb.Where(gwb.query, gwb.args...)
@ -358,7 +353,7 @@ func (gwb *GORMWhereBuilder[R, C]) Or(query interface{}, args ...interface{}) *G
} }
// Not 添加 NOT 条件 // Not 添加 NOT 条件
func (gwb *GORMWhereBuilder[R, C]) Not(query interface{}, args ...interface{}) *GORMWhereBuilder[R, C] { func (gwb *GORMWhereBuilder[R]) Not(query interface{}, args ...interface{}) *GORMWhereBuilder[R] {
if gwb.query != nil { if gwb.query != nil {
gwb = gwb.Where(gwb.query, gwb.args...) gwb = gwb.Where(gwb.query, gwb.args...)
gwb.query = nil gwb.query = nil
@ -369,7 +364,7 @@ func (gwb *GORMWhereBuilder[R, C]) Not(query interface{}, args ...interface{}) *
} }
// Find 执行查询并返回结果 // Find 执行查询并返回结果
func (gwb *GORMWhereBuilder[R, C]) Find(items interface{}) error { func (gwb *GORMWhereBuilder[R]) Find(items interface{}) error {
// 应用剩余的查询条件 // 应用剩余的查询条件
if gwb.query != nil { if gwb.query != nil {
gwb = gwb.Where(gwb.query, gwb.args...) gwb = gwb.Where(gwb.query, gwb.args...)
@ -378,7 +373,7 @@ func (gwb *GORMWhereBuilder[R, C]) Find(items interface{}) error {
} }
// First 查询第一条记录 // First 查询第一条记录
func (gwb *GORMWhereBuilder[R, C]) First(result interface{}) error { func (gwb *GORMWhereBuilder[R]) First(result interface{}) error {
if gwb.query != nil { if gwb.query != nil {
gwb = gwb.Where(gwb.query, gwb.args...) gwb = gwb.Where(gwb.query, gwb.args...)
} }
@ -386,7 +381,7 @@ func (gwb *GORMWhereBuilder[R, C]) First(result interface{}) error {
} }
// Count 统计记录数 // Count 统计记录数
func (gwb *GORMWhereBuilder[R, C]) Count(count *int64) error { func (gwb *GORMWhereBuilder[R]) Count(count *int64) error {
if gwb.query != nil { if gwb.query != nil {
gwb = gwb.Where(gwb.query, gwb.args...) gwb = gwb.Where(gwb.query, gwb.args...)
} }
@ -394,7 +389,7 @@ func (gwb *GORMWhereBuilder[R, C]) Count(count *int64) error {
} }
// ClearField -------------------------- 原ClearField对应实现清理请求参数并返回有效map -------------------------- // ClearField -------------------------- 原ClearField对应实现清理请求参数并返回有效map --------------------------
func (c Crud[R, C]) ClearField(req any, delField []string, subField ...map[string]any) map[string]any { func (c Crud[R]) ClearField(req any, delField []string, subField ...map[string]any) map[string]any {
reqMap := convToMap(req) reqMap := convToMap(req)
resultMap := make(map[string]any) resultMap := make(map[string]any)
@ -423,7 +418,7 @@ func (c Crud[R, C]) ClearField(req any, delField []string, subField ...map[strin
} }
// ClearFieldPage -------------------------- 原ClearFieldPage对应实现清理参数+分页查询 -------------------------- // ClearFieldPage -------------------------- 原ClearFieldPage对应实现清理参数+分页查询 --------------------------
func (c Crud[R, C]) ClearFieldPage(ctx ctx, req any, delField []string, where any, page *Paginate, order any, with map[string]func(db *gorm.DB) *gorm.DB) (items []*R, total int64, err error) { func (c Crud[R]) ClearFieldPage(ctx ctx, req any, delField []string, where any, page *Paginate, order any, with map[string]func(db *gorm.DB) *gorm.DB) (items []*R, total int64, err error) {
// 1. 清理请求参数 // 1. 清理请求参数
filterMap := c.ClearField(req, delField) filterMap := c.ClearField(req, delField)
@ -464,7 +459,7 @@ func (c Crud[R, C]) ClearFieldPage(ctx ctx, req any, delField []string, where an
} }
// ClearFieldList -------------------------- 原ClearFieldList对应实现清理参数+列表查询(不分页) -------------------------- // ClearFieldList -------------------------- 原ClearFieldList对应实现清理参数+列表查询(不分页) --------------------------
func (c Crud[R, C]) ClearFieldList(ctx ctx, req any, delField []string, where any, order any, with map[string]func(db *gorm.DB) *gorm.DB) (items []*R, err error) { func (c Crud[R]) ClearFieldList(ctx ctx, req any, delField []string, where any, order any, with map[string]func(db *gorm.DB) *gorm.DB) (items []*R, err error) {
filterMap := c.ClearField(req, delField) filterMap := c.ClearField(req, delField)
db := c.Dao.Ctx(ctx).Model(new(R)) db := c.Dao.Ctx(ctx).Model(new(R))
@ -485,7 +480,7 @@ func (c Crud[R, C]) ClearFieldList(ctx ctx, req any, delField []string, where an
} }
// ClearFieldOne -------------------------- 原ClearFieldOne对应实现清理参数+单条查询 -------------------------- // ClearFieldOne -------------------------- 原ClearFieldOne对应实现清理参数+单条查询 --------------------------
func (c Crud[R, C]) ClearFieldOne(ctx ctx, req any, delField []string, where any, order any, with map[string]func(db *gorm.DB) *gorm.DB) (item *R, err error) { func (c Crud[R]) ClearFieldOne(ctx ctx, req any, delField []string, where any, order any, with map[string]func(db *gorm.DB) *gorm.DB) (item *R, err error) {
item = new(R) item = new(R)
filterMap := c.ClearField(req, delField) filterMap := c.ClearField(req, delField)
db := c.Dao.Ctx(ctx).Model(item) db := c.Dao.Ctx(ctx).Model(item)
@ -511,7 +506,7 @@ func (c Crud[R, C]) ClearFieldOne(ctx ctx, req any, delField []string, where any
} }
// Value -------------------------- 原Value对应实现查询单个字段值 -------------------------- // Value -------------------------- 原Value对应实现查询单个字段值 --------------------------
func (c Crud[R, C]) Value(ctx ctx, where any, field any) (interface{}, error) { func (c Crud[R]) Value(ctx ctx, where any, field any) (interface{}, error) {
var result interface{} var result interface{}
db := c.Dao.Ctx(ctx).Model(new(R)).Where(where) db := c.Dao.Ctx(ctx).Model(new(R)).Where(where)
@ -535,7 +530,7 @@ func (c Crud[R, C]) Value(ctx ctx, where any, field any) (interface{}, error) {
} }
// DeletePri -------------------------- 原DeletePri对应实现按主键删除 -------------------------- // DeletePri -------------------------- 原DeletePri对应实现按主键删除 --------------------------
func (c Crud[R, C]) DeletePri(ctx ctx, primaryKey any) error { func (c Crud[R]) DeletePri(ctx ctx, primaryKey any) error {
db := c.Dao.Ctx(ctx).Model(new(R)) db := c.Dao.Ctx(ctx).Model(new(R))
// 按主键字段构建查询 // 按主键字段构建查询
pk := c.Dao.PrimaryKey() pk := c.Dao.PrimaryKey()
@ -546,12 +541,12 @@ func (c Crud[R, C]) DeletePri(ctx ctx, primaryKey any) error {
} }
// DeleteWhere -------------------------- 原DeleteWhere对应实现按条件删除 -------------------------- // DeleteWhere -------------------------- 原DeleteWhere对应实现按条件删除 --------------------------
func (c Crud[R, C]) DeleteWhere(ctx ctx, where any) error { func (c Crud[R]) DeleteWhere(ctx ctx, where any) error {
return c.Dao.Ctx(ctx).Model(new(R)).Where(where).Delete(new(R)).Error return c.Dao.Ctx(ctx).Model(new(R)).Where(where).Delete(new(R)).Error
} }
// Sum -------------------------- 原Sum对应实现字段求和 -------------------------- // Sum -------------------------- 原Sum对应实现字段求和 --------------------------
func (c Crud[R, C]) Sum(ctx ctx, where any, field string) float64 { func (c Crud[R]) Sum(ctx ctx, where any, field string) float64 {
var sum float64 var sum float64
if field == "" { if field == "" {
panic("求和字段不能为空") panic("求和字段不能为空")
@ -565,7 +560,7 @@ func (c Crud[R, C]) Sum(ctx ctx, where any, field string) float64 {
} }
// ArrayField -------------------------- 原ArrayField对应实现查询指定字段数组 -------------------------- // ArrayField -------------------------- 原ArrayField对应实现查询指定字段数组 --------------------------
func (c Crud[R, C]) ArrayField(ctx ctx, where any, field any) []interface{} { func (c Crud[R]) ArrayField(ctx ctx, where any, field any) []interface{} {
var result []interface{} var result []interface{}
db := c.Dao.Ctx(ctx).Model(new(R)).Where(where) db := c.Dao.Ctx(ctx).Model(new(R)).Where(where)
@ -589,7 +584,7 @@ func (c Crud[R, C]) ArrayField(ctx ctx, where any, field any) []interface{} {
} }
// FindPri -------------------------- 原FindPri对应实现按主键查询单条记录 -------------------------- // FindPri -------------------------- 原FindPri对应实现按主键查询单条记录 --------------------------
func (c Crud[R, C]) FindPri(ctx ctx, primaryKey any, with map[string]func(db *gorm.DB) *gorm.DB) (model *R) { func (c Crud[R]) FindPri(ctx ctx, primaryKey any, with map[string]func(db *gorm.DB) *gorm.DB) (model *R) {
model = new(R) model = new(R)
db := c.Dao.Ctx(ctx).Model(model) db := c.Dao.Ctx(ctx).Model(model)
pk := c.Dao.PrimaryKey() pk := c.Dao.PrimaryKey()
@ -612,7 +607,7 @@ func (c Crud[R, C]) FindPri(ctx ctx, primaryKey any, with map[string]func(db *go
} }
// -------------------------- 原First对应实现按条件查询第一条记录 -------------------------- // -------------------------- 原First对应实现按条件查询第一条记录 --------------------------
func (c Crud[R, C]) First(ctx ctx, where any, order any, with map[string]func(db *gorm.DB) *gorm.DB) (model *R) { func (c Crud[R]) First(ctx ctx, where any, order any, with map[string]func(db *gorm.DB) *gorm.DB) (model *R) {
model = new(R) model = new(R)
db := c.Dao.Ctx(ctx).Model(model) db := c.Dao.Ctx(ctx).Model(model)
@ -636,7 +631,7 @@ func (c Crud[R, C]) First(ctx ctx, where any, order any, with map[string]func(db
} }
// -------------------------- 原Exists对应实现判断记录是否存在 -------------------------- // -------------------------- 原Exists对应实现判断记录是否存在 --------------------------
func (c Crud[R, C]) Exists(ctx ctx, where any) (exists bool) { func (c Crud[R]) Exists(ctx ctx, where any) (exists bool) {
var count int64 var count int64
err := c.Dao.Ctx(ctx).Model(new(R)).Where(where).Count(&count).Error err := c.Dao.Ctx(ctx).Model(new(R)).Where(where).Count(&count).Error
if err != nil { if err != nil {
@ -646,7 +641,7 @@ func (c Crud[R, C]) Exists(ctx ctx, where any) (exists bool) {
} }
// -------------------------- 原All对应实现查询所有符合条件的记录 -------------------------- // -------------------------- 原All对应实现查询所有符合条件的记录 --------------------------
func (c Crud[R, C]) All(ctx ctx, where any, order any, with map[string]func(db *gorm.DB) *gorm.DB) (items []*R) { func (c Crud[R]) All(ctx ctx, where any, order any, with map[string]func(db *gorm.DB) *gorm.DB) (items []*R) {
db := c.Dao.Ctx(ctx).Model(new(R)) db := c.Dao.Ctx(ctx).Model(new(R))
if with != nil { if with != nil {
@ -669,7 +664,7 @@ func (c Crud[R, C]) All(ctx ctx, where any, order any, with map[string]func(db *
} }
// -------------------------- 原Count对应实现统计记录总数 -------------------------- // -------------------------- 原Count对应实现统计记录总数 --------------------------
func (c Crud[R, C]) Count(ctx ctx, where any) (count int64) { func (c Crud[R]) Count(ctx ctx, where any) (count int64) {
err := c.Dao.Ctx(ctx).Model(new(R)).Where(where).Count(&count).Error err := c.Dao.Ctx(ctx).Model(new(R)).Where(where).Count(&count).Error
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
panic(fmt.Sprintf("Count查询错误: %v", err)) panic(fmt.Sprintf("Count查询错误: %v", err))
@ -678,7 +673,7 @@ func (c Crud[R, C]) Count(ctx ctx, where any) (count int64) {
} }
// -------------------------- 原Save对应实现新增/更新记录对应GORM的Save -------------------------- // -------------------------- 原Save对应实现新增/更新记录对应GORM的Save --------------------------
func (c Crud[R, C]) Save(ctx ctx, data any) { func (c Crud[R]) Save(ctx ctx, data any) {
err := c.Dao.Ctx(ctx).Model(new(R)).Create(data).Error err := c.Dao.Ctx(ctx).Model(new(R)).Create(data).Error
if err != nil { if err != nil {
panic(fmt.Sprintf("Save保存错误: %v", err)) panic(fmt.Sprintf("Save保存错误: %v", err))
@ -686,7 +681,7 @@ func (c Crud[R, C]) Save(ctx ctx, data any) {
} }
// -------------------------- 原Update对应实现按条件更新记录 -------------------------- // -------------------------- 原Update对应实现按条件更新记录 --------------------------
func (c Crud[R, C]) Update(ctx ctx, where any, data any) (count int64) { func (c Crud[R]) Update(ctx ctx, where any, data any) (count int64) {
result := c.Dao.Ctx(ctx).Model(new(R)).Where(where).Updates(data) result := c.Dao.Ctx(ctx).Model(new(R)).Where(where).Updates(data)
if errors.Is(result.Error, gorm.ErrRecordNotFound) { if errors.Is(result.Error, gorm.ErrRecordNotFound) {
panic(fmt.Sprintf("Update更新错误: %v", result.Error.Error())) panic(fmt.Sprintf("Update更新错误: %v", result.Error.Error()))
@ -695,7 +690,7 @@ func (c Crud[R, C]) Update(ctx ctx, where any, data any) (count int64) {
} }
// -------------------------- 原UpdatePri对应实现按主键更新记录 -------------------------- // -------------------------- 原UpdatePri对应实现按主键更新记录 --------------------------
func (c Crud[R, C]) UpdatePri(ctx ctx, primaryKey any, data any) (count int64) { func (c Crud[R]) UpdatePri(ctx ctx, primaryKey any, data any) (count int64) {
db := c.Dao.Ctx(ctx).Model(new(R)) db := c.Dao.Ctx(ctx).Model(new(R))
pk := c.Dao.PrimaryKey() pk := c.Dao.PrimaryKey()
@ -711,7 +706,7 @@ func (c Crud[R, C]) UpdatePri(ctx ctx, primaryKey any, data any) (count int64) {
} }
// -------------------------- 原Paginate对应实现分页查询 -------------------------- // -------------------------- 原Paginate对应实现分页查询 --------------------------
func (c Crud[R, C]) Paginate(ctx context.Context, where any, p Paginate, with map[string]func(db *gorm.DB) *gorm.DB, order any) (items []*R, total int64) { func (c Crud[R]) Paginate(ctx context.Context, where any, p Paginate, with map[string]func(db *gorm.DB) *gorm.DB, order any) (items []*R, total int64) {
db := c.Dao.Ctx(ctx).Model(new(R)) db := c.Dao.Ctx(ctx).Model(new(R))
// 1. 构建查询条件 // 1. 构建查询条件

View File

@ -98,7 +98,7 @@ func TestBuildWhere(t *testing.T) {
// TestBuildMap 测试 BuildMap 方法 // TestBuildMap 测试 BuildMap 方法
func TestBuildMap(t *testing.T) { func TestBuildMap(t *testing.T) {
// 创建一个空的 Crud 实例用于测试(不需要实际的 Dao // 创建一个空的 Crud 实例用于测试(不需要实际的 Dao
var crud Crud[interface{}, interface{}] var crud Crud[interface{}]
t.Run("BuildMapWithoutField", func(t *testing.T) { t.Run("BuildMapWithoutField", func(t *testing.T) {
result := crud.BuildMap(">", 18) result := crud.BuildMap(">", 18)
@ -131,7 +131,7 @@ func TestBuildMap(t *testing.T) {
// TestClearField 测试 ClearField 方法 // TestClearField 测试 ClearField 方法
func TestClearField(t *testing.T) { func TestClearField(t *testing.T) {
var crud Crud[interface{}, interface{}] var crud Crud[interface{}]
t.Run("ClearFieldBasic", func(t *testing.T) { t.Run("ClearFieldBasic", func(t *testing.T) {
req := struct { req := struct {
@ -210,7 +210,7 @@ func TestClearField(t *testing.T) {
// TestBuildWhereAndOr 测试 BuildWhereAndOr 方法 // TestBuildWhereAndOr 测试 BuildWhereAndOr 方法
func TestBuildWhereAndOr(t *testing.T) { func TestBuildWhereAndOr(t *testing.T) {
var crud Crud[interface{}, interface{}] var crud Crud[interface{}]
t.Run("SimpleAND", func(t *testing.T) { t.Run("SimpleAND", func(t *testing.T) {
where := crud.BuildWhereAndOr(). where := crud.BuildWhereAndOr().

View File

@ -1,31 +0,0 @@
package base
import (
"github.com/gogf/gf/v2/os/gtime"
"gorm.io/gorm"
)
type IdModel struct {
Id int `json:"id" gorm:"column:id;type:int(11);common:id"`
}
type TimeModel struct {
CreateTime string `json:"create_time" gorm:"column:create_time;type:varchar(255);common:创建时间"`
UpdateTime string `json:"update_time" gorm:"column:update_time;type:varchar(255);common:更新时间"`
}
func (tm *TimeModel) BeforeCreate(scope *gorm.DB) error {
scope.Set("create_time", gtime.Datetime())
scope.Set("update_time", gtime.Datetime())
return nil
}
func (tm *TimeModel) BeforeUpdate(scope *gorm.DB) error {
scope.Set("update_time", gtime.Datetime())
return nil
}
//func (tm *TimeModel) AfterFind(scope *gorm.DB) error {
// tm.CreateTime = gtime.New(tm.CreateTime).String()
// tm.UpdateTime = gtime.New(tm.UpdateTime).String()
// return nil
//}

View File

@ -3,7 +3,6 @@ package database
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
"time"
"git.magicany.cc/black1552/gin-base/config" "git.magicany.cc/black1552/gin-base/config"
"git.magicany.cc/black1552/gin-base/log" "git.magicany.cc/black1552/gin-base/log"
@ -12,7 +11,6 @@ import (
"github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gfile"
"gorm.io/driver/mysql" "gorm.io/driver/mysql"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/logger"
"gorm.io/gorm/schema" "gorm.io/gorm/schema"
) )
@ -26,39 +24,24 @@ var (
func init() { func init() {
if g.IsEmpty(dns) { if g.IsEmpty(dns) {
log.Error("gormDns 未配置", "请检查配置文件") log.Error("gormDns未配置", "请检查配置文件")
return return
} }
switch config.GetConfigValue("database.type", "sqlite").String() { switch config.GetConfigValue("database.type", "sqlite").String() {
case "mysql": case "mysql":
log.Info("使用 mysql 数据库") log.Info("使用mysql数据库")
mysqlInit() mysqlInit()
case "sqlite": case "sqlite":
log.Info("使用 sqlite 数据库") log.Info("使用sqlite数据库")
sqliteInit() sqliteInit()
} }
Db, err = gorm.Open(Type, &gorm.Config{
// 构建 GORM 配置
gormConfig := &gorm.Config{
SkipDefaultTransaction: true, SkipDefaultTransaction: true,
NowFunc: func() time.Time {
return time.Now().Local()
},
// 命名策略:保持与模型一致,避免字段/表名转换问题 // 命名策略:保持与模型一致,避免字段/表名转换问题
NamingStrategy: schema.NamingStrategy{ NamingStrategy: schema.NamingStrategy{
SingularTable: true, // 表名禁用复数形式(例如 User 对应 user 表,而非 users SingularTable: true, // 表名禁用复数形式(例如 User 对应 user 表,而非 users
}, },
} })
// 根据配置决定是否开启 GORM 查询日志
if config.GetConfigValue("database.debug", false).Bool() {
log.Info("已开启 GORM 查询日志")
gormConfig.Logger = logger.Default.LogMode(logger.Info)
} else {
gormConfig.Logger = logger.Default.LogMode(logger.Silent)
}
Db, err = gorm.Open(Type, gormConfig)
if err != nil { if err != nil {
log.Error("数据库连接失败: ", err) log.Error("数据库连接失败: ", err)
return return

View File

@ -55,14 +55,12 @@ func Run(g *gin.Engine) {
os.Exit(1) // 启动失败则退出程序 os.Exit(1) // 启动失败则退出程序
} }
}() }()
time.Sleep(time.Second)
log.Info("服务器启动成功....") log.Info("服务器启动成功....")
if strings.Contains(s.Addr, "127.0.0.1") || strings.Contains(s.Addr, "0.0.0.0") || strings.Contains(s.Addr, "locahost") { if strings.Contains(s.Addr, "127.0.0.1") || strings.Contains(s.Addr, "0.0.0.0") || strings.Contains(s.Addr, "locahost") {
log.Info("请使用打开:", fmt.Sprintf("http://%s\n", s.Addr)) log.Info("请使用打开:", fmt.Sprintf("http://%s\n", s.Addr))
} else { } else {
log.Info("请使用打开:", fmt.Sprintf("http://localhost%s\n", s.Addr)) log.Info("请使用打开:", fmt.Sprintf("http://localhost%s\n", s.Addr))
} }
// 等待中断信号以优雅地关闭服务器 // 等待中断信号以优雅地关闭服务器
quit := make(chan os.Signal, 1) quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)