Compare commits

...

15 Commits

Author SHA1 Message Date
maguodong f50930ec74 refactor(database): 更新时间模型的钩子函数实现
- 将 BeforeCreate 中的时间设置从直接赋值改为使用 scope.Set 方法
- 将 BeforeUpdate 中的时间设置从直接赋值改为使用 scope.Set 方法
- 移除 AfterDelete 钩子函数并注释掉 AfterFind 钩子函数
- 统一使用 GORM 的 scope 机制处理时间字段更新
2026-03-30 10:32:50 +08:00
maguodong d50f150d98 fix(test): 修正Crud泛型类型声明
- 将Crud[interface{}]更改为Crud[interface{}, interface{}]以匹配正确的泛型参数数量
2026-03-28 18:18:10 +08:00
maguodong 0238ec9a01 docs(curd): 更新Crud结构体注释文档
- 为Crud结构体添加C参数的说明
- 明确C参数为对应模型结构体的字段结构体
- 完善泛型CURD封装的功能描述
2026-03-28 18:17:31 +08:00
maguodong 1cc976ed72 refactor(database): 重构基础模型包结构
- 将 model 包重命名为 base 包
- 移动 base.go 文件到 database/base 目录
- 更新包导入路径以匹配新的目录结构
2026-03-28 18:03:54 +08:00
maguodong 7d3ddc62e3 refactor(database): 重构基础模型结构和时间处理逻辑
- 将 BaseModel 拆分为 IdModel 和 TimeModel 两个独立结构体
- 替换标准库 time 包为 gf 框架的 gtime 包进行时间处理
- 修改字段标签定义,优化数据库列映射配置
- 重写 BeforeCreate、BeforeUpdate 钩子方法实现
- 新增 AfterDelete 钩子方法处理删除后的时间转换
- 统一时间格式化为字符串类型存储到数据库中
2026-03-28 18:01:44 +08:00
maguodong 427f568db6 fix(model): 修改BaseModel主键ID数据类型
- 将Id字段从uint类型改为int类型
- 保持GORM标签和JSON序列化配置不变
2026-03-28 16:22:53 +08:00
maguodong 828e19de93 refactor(database): 修改BaseModel中的ID字段命名规范
- 将ID字段名改为Id以符合Go语言命名约定
- 保持gorm标签和json标签的一致性
- 确保数据库映射功能不受影响
2026-03-28 16:21:02 +08:00
maguodong 1e18be8326 refactor(database): 简化基础模型时间处理逻辑
- 移除自定义 DateTime 类型及其 JSON 序列化/反序列化实现
- 将 CreateTime 和 UpdateTime 字段类型从 DateTime 改为 string
- 添加 GORM 的 BeforeCreate 和 BeforeUpdate 钩子函数
- 使用 time.Now().Format 直接格式化时间字符串
- 移除冗余的 driver.Valuer 和 sql.Scanner 接口实现
2026-03-28 16:13:54 +08:00
maguodong 21e9f7c79d refactor(database): 重构数据库基础模型时间类型
- 将 LocalTime 类型重命名为 DateTime 并改进实现
- 添加完整的 JSON 序列化和反序列化支持
- 实现了 MarshalJSON 和 UnmarshalJSON 方法
- 改进 Scan 方法以支持字符串类型转换
- 更新 BaseModel 结构体字段定义和标签
- 移除指针类型改为值类型并优化 GORM 标签配置
2026-03-28 15:58:46 +08:00
maguodong 93fbb99ee0 feat(database): 添加自定义时间类型支持空值
- 新增 LocalTime 自定义时间类型,支持 null 值处理
- 实现 MarshalJSON 方法支持 JSON 序列化
- 实现 Value 方法支持数据库存储
- 实现 Scan 方法支持数据库读取
- 修改 BaseModel 使用 LocalTime 类型替代原生 time.Time
- 移除 BaseModel 中的时间处理钩子函数
2026-03-28 15:52:33 +08:00
maguodong d41b554acf feat(database): 添加数据库模型查询后时间戳更新功能
- 在 BaseModel 中实现 AfterFind 钩子函数,用于查询后更新 UpdateTime 字段
- 集成 time 包支持时间操作
- 配置 GORM NowFunc 使用本地时间,确保时间戳准确性
- 统一数据库操作的时间处理逻辑,提高数据一致性
2026-03-28 15:34:10 +08:00
maguodong 7b6026950a refactor(database): 更新基础模型的时间字段配置
- 修改 CreateTime 字段的 JSON 标签从 created_at 到 create_time
- 修改 UpdateTime 字段的 JSON 标签从 updated_at 到 update_time
- 添加 autoCreateTime 和 autoUpdateTime GORM 标签实现自动时间戳
- 移除手动时间设置的相关注释
- 统一字段标签格式为 common 格式
2026-03-28 14:37:40 +08:00
maguodong 80ad00f98d feat(database): 添加基础数据模型
- 创建 BaseModel 结构体,包含主键 ID、创建时间和更新时间字段
- 实现 BeforeCreate 钩子函数,自动设置创建和更新时间为当前时间
- 实现 BeforeUpdate 钩子函数,自动更新更新时间为当前时间
- 配置 GORM 数据库映射标签,包括主键、列名、数据类型等
- 添加 JSON 序列化标签支持,便于 API 返回数据
2026-03-28 14:36:43 +08:00
maguodong 3209cfe830 feat(database): 添加数据库初始化和配置管理功能
- 实现了数据库连接初始化,支持 MySQL 和 SQLite 两种类型
- 添加了 GORM 配置构建,包含事务控制和命名策略设置
- 集成了查询日志功能,可配置是否开启 GORM 日志
- 创建了数据库配置管理模块,使用 Viper 进行配置读取
- 添加了配置文件自动生成和默认值设置功能
- 实现了配置变更监听和热更新机制
- 定义了基础配置结构体,包含服务器、数据库和 JWT 配置
2026-03-28 13:57:31 +08:00
maguodong ed7d18a72a feat(curd): 添加泛型CURD核心功能模块
- 实现基于GORM的泛型CURD操作接口
- 提供分页查询、条件构建、字段转换等核心功能
- 支持AND/OR混合查询条件构建器
- 集成事务处理和预加载关联查询功能
- 实现字段名风格转换(驼峰与下划线互转)
- 提供按主键和条件进行增删改查的完整操作集
2026-03-28 11:49:10 +08:00
6 changed files with 107 additions and 52 deletions

View File

@ -60,6 +60,7 @@ func SetDefault() {
viper.Set("SERVER.mode", "release")
viper.Set("DATABASE.type", "sqlite")
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.expire", 86400)
}

View File

@ -17,6 +17,7 @@ type ServerConfig struct {
type DataBaseConfig struct {
Dns string `mapstructure:"dns"`
Type string `mapstructure:"type"`
Debug bool `mapstructure:"debug"` // 是否开启 GORM 查询日志
}
// JwtConfig JWT配置

View File

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

View File

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

31
database/base/base.go Normal file
View File

@ -0,0 +1,31 @@
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,6 +3,7 @@ package database
import (
"database/sql"
"fmt"
"time"
"git.magicany.cc/black1552/gin-base/config"
"git.magicany.cc/black1552/gin-base/log"
@ -11,6 +12,7 @@ import (
"github.com/gogf/gf/v2/os/gfile"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"gorm.io/gorm/schema"
)
@ -35,13 +37,28 @@ func init() {
log.Info("使用 sqlite 数据库")
sqliteInit()
}
Db, err = gorm.Open(Type, &gorm.Config{
// 构建 GORM 配置
gormConfig := &gorm.Config{
SkipDefaultTransaction: true,
NowFunc: func() time.Time {
return time.Now().Local()
},
// 命名策略:保持与模型一致,避免字段/表名转换问题
NamingStrategy: schema.NamingStrategy{
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 {
log.Error("数据库连接失败: ", err)
return