package dao import ( "context" "fmt" "reflect" "time" "gogs.baozhida.cn/Cold_Logistic_libs/pkg/contrib/errors" "gorm.io/gorm" "Cold_Logistic/internal/pkg/common/global" "Cold_Logistic/internal/server/infra/models" ) type DbBaseStore interface { Create(ctx context.Context, value models.BaseEntity) error Save(ctx context.Context, value models.BaseEntity, omit ...string) error UpdateById(ctx context.Context, value models.BaseEntity, selected ...string) error FirstById(ctx context.Context, dest models.BaseEntity, id int) error GetById(ctx context.Context, dest models.BaseEntity, id int) error GetByIds(ctx context.Context, dest, ids interface{}) error DeleteByIds(ctx context.Context, ids interface{}) error GetIntValueMapByIds(ctx context.Context, ids []int, fieldName string) (map[int]int, error) GetStringValueMapByIds(ctx context.Context, ids []int, fieldName string) (map[int]string, error) } var _ DbBaseStore = &dbBase{} type dbBase struct { store *DataStore baseEntity models.BaseEntity } func (ds *dbBase) Create(ctx context.Context, m models.BaseEntity) error { db := ds.store.optionDB(ctx) v := reflect.ValueOf(m).Elem() if v.CanAddr() { accountId := global.GetTokenInfoFromContext(ctx).AccountId if field := v.FieldByName("CreatedTime"); field.IsValid() { field.Set(reflect.ValueOf(models.MyTime{Time: time.Now()})) } if field := v.FieldByName("Deleted"); field.IsValid() { field.SetInt(models.DeleteNo) } if field := v.FieldByName("CreatedBy"); field.IsValid() && accountId != 0 { field.Set(reflect.ValueOf(accountId)) } } return db.Table(m.TableName()).Create(m).Error } func (ds *dbBase) Save(ctx context.Context, m models.BaseEntity, omit ...string) error { db := ds.store.optionDB(ctx) v := reflect.ValueOf(m).Elem() if v.CanAddr() { accountId := global.GetTokenInfoFromContext(ctx).AccountId if field := v.FieldByName("Id"); field.IsValid() && field.IsZero() { if field := v.FieldByName("CreatedTime"); field.IsValid() { field.Set(reflect.ValueOf(models.MyTime{Time: time.Now()})) } if field := v.FieldByName("CreatedBy"); field.IsValid() && accountId != 0 { field.Set(reflect.ValueOf(accountId)) } if field := v.FieldByName("Deleted"); field.IsValid() { field.SetInt(models.DeleteNo) } } else { if field := v.FieldByName("UpdatedTime"); field.IsValid() { field.Set(reflect.ValueOf(models.MyTime{Time: time.Now()})) } if field := v.FieldByName("UpdatedBy"); field.IsValid() && accountId != 0 { field.Set(reflect.ValueOf(accountId)) } } } return db.Table(m.TableName()).Omit(omit...).Save(m).Error } func (ds *dbBase) UpdateById(ctx context.Context, m models.BaseEntity, selected ...string) error { db := ds.store.optionDB(ctx) v := reflect.ValueOf(m).Elem() if v.CanAddr() { accountId := global.GetTokenInfoFromContext(ctx).AccountId if field := v.FieldByName("UpdatedTime"); field.IsValid() { field.Set(reflect.ValueOf(models.MyTime{Time: time.Now()})) if len(selected) > 0 { selected = append(selected, "UpdatedTime") } } if field := v.FieldByName("UpdatedBy"); field.IsValid() && accountId != 0 { field.Set(reflect.ValueOf(accountId)) if len(selected) > 0 { selected = append(selected, "UpdatedBy") } } } return db.Table(m.TableName()).Select(selected).Updates(m).Error } func (ds *dbBase) FirstById(ctx context.Context, dest models.BaseEntity, id int) error { return ds.firstByOptions(ctx, dest, ds.store.withByID(id), ds.store.withByNotDeleted()) } func (ds *dbBase) GetById(ctx context.Context, dest models.BaseEntity, id int) error { return ds.findByOptions(ctx, dest, ds.store.withByID(id), ds.store.withByNotDeleted()) } func (ds *dbBase) GetByIds(ctx context.Context, dest, ids interface{}) error { db := ds.store.optionDB(ctx) err := db.Table(ds.baseEntity.TableName()).Where("deleted = ?", models.DeleteNo). Where("id in (?)", ids). Find(dest).Error return err } func (ds *dbBase) DeleteByIds(ctx context.Context, ids interface{}) error { destVal := reflect.ValueOf(ds.baseEntity) if destVal.Kind() == reflect.Ptr { destVal = destVal.Elem() } v := reflect.New(destVal.Type()) v = v.Elem() if field := v.FieldByName("DeletedTime"); field.IsValid() { field.Set(reflect.ValueOf(models.MyTime{Time: time.Now()})) } if field := v.FieldByName("DeletedBy"); field.IsValid() { field.Set(reflect.ValueOf(global.GetTokenInfoFromContext(ctx).AccountId)) } if field := v.FieldByName("Deleted"); field.IsValid() { field.Set(reflect.ValueOf(models.DeleteYes)) } db := ds.store.optionDB(ctx) err := db.Table(ds.baseEntity.TableName()). Where("deleted = ?", models.DeleteNo). Where("id IN (?)", ids). Updates(v.Interface()).Error return err } func (ds *dbBase) GetIntValueMapByIds(ctx context.Context, ids []int, fieldName string) (map[int]int, error) { res := make(map[int]int, len(ids)) if len(ids) == 0 { return res, nil } slicePtr := ds.makeSlice(len(ids)) err := ds.findByOptions(ctx, slicePtr.Interface(), ds.store.withByNotDeleted(), ds.store.withByColumnInVal("id", ids), ds.store.withBySelects("id", fieldName)) if err != nil { return nil, err } sliceVal := slicePtr.Elem() for i := 0; i < sliceVal.Len(); i++ { elem := sliceVal.Index(i) if fieldValue := elem.FieldByName(fieldName); fieldValue.IsValid() { res[elem.FieldByName("Id").Interface().(int)] = fieldValue.Interface().(int) } else { return nil, errors.New(fmt.Sprintf("fieldName %s not found", fieldName)) } } return res, nil } func (ds *dbBase) GetStringValueMapByIds(ctx context.Context, ids []int, fieldName string) (map[int]string, error) { res := make(map[int]string, len(ids)) if len(ids) == 0 { return res, nil } slicePtr := ds.makeSlice(len(ids)) err := ds.findByOptions(ctx, slicePtr.Interface(), ds.store.withByNotDeleted(), ds.store.withByColumnInVal("id", ids), ds.store.withBySelects("id", fieldName)) if err != nil { return nil, err } sliceVal := slicePtr.Elem() for i := 0; i < sliceVal.Len(); i++ { elem := sliceVal.Index(i) if fieldValue := elem.FieldByName(fieldName); fieldValue.IsValid() { res[elem.FieldByName("Id").Interface().(int)] = fieldValue.Interface().(string) } else { return nil, errors.New(fmt.Sprintf("fieldName %s not found", fieldName)) } } return res, nil } func (ds *dbBase) makeSlice(cap int) reflect.Value { elemType := reflect.TypeOf(ds.baseEntity) if elemType.Kind() == reflect.Ptr { elemType = elemType.Elem() } slice := reflect.MakeSlice(reflect.SliceOf(elemType), 0, cap) results := reflect.New(slice.Type()) results.Elem().Set(slice) return results } func (ds *dbBase) firstByOptions(ctx context.Context, m models.BaseEntity, opts ...dbOption) error { db := ds.store.optionDB(ctx, opts...) err := db.Table(m.TableName()).First(m).Error if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { return errors.WithStackOnce(err) } return err } func (ds *dbBase) findByOptions(ctx context.Context, dest interface{}, opts ...dbOption) error { db := ds.store.optionDB(ctx, opts...) err := db.Table(ds.baseEntity.TableName()).Find(dest).Error return err }