2025-04-24 20:39:31 +08:00
|
|
|
package repo
|
|
|
|
|
|
|
|
import (
|
|
|
|
"admin/apps/game/domain/entity"
|
|
|
|
"admin/apps/game/model"
|
|
|
|
"admin/apps/game/model/dto"
|
2025-05-12 18:43:41 +08:00
|
|
|
"admin/internal/consts"
|
2025-04-24 20:39:31 +08:00
|
|
|
"admin/internal/errcode"
|
2025-05-04 22:07:13 +08:00
|
|
|
"admin/lib/xlog"
|
2025-05-15 17:30:33 +08:00
|
|
|
"database/sql"
|
2025-04-24 20:39:31 +08:00
|
|
|
"errors"
|
2025-05-04 22:07:13 +08:00
|
|
|
"fmt"
|
2025-04-24 20:39:31 +08:00
|
|
|
"gorm.io/gorm"
|
2025-05-04 22:07:13 +08:00
|
|
|
"gorm.io/gorm/schema"
|
2025-04-24 20:39:31 +08:00
|
|
|
"reflect"
|
2025-05-04 22:07:13 +08:00
|
|
|
"strings"
|
|
|
|
"time"
|
2025-04-24 20:39:31 +08:00
|
|
|
)
|
|
|
|
|
2025-05-12 18:43:41 +08:00
|
|
|
var createHooks = map[string]func(projectEt *entity.Project, et dto.CommonDtoValues) error{
|
|
|
|
consts.ResourcesName_CDKey: cdKeyPreCreateHook,
|
|
|
|
}
|
|
|
|
|
2025-04-24 20:39:31 +08:00
|
|
|
type ICommonResourceRepo interface {
|
2025-05-09 18:28:15 +08:00
|
|
|
List(project *entity.Project, params *dto.CommonListReq) (int, []*dto.CommonDtoFieldDesc, []*entity.CommonResource, error)
|
2025-04-30 15:46:14 +08:00
|
|
|
GetById(projectEt *entity.Project, id int) ([]*dto.CommonDtoFieldDesc, *entity.CommonResource, bool, error)
|
2025-05-12 18:43:41 +08:00
|
|
|
Create(projectEt *entity.Project, resource string, et dto.CommonDtoValues) (*entity.CommonResource, error)
|
2025-04-30 15:46:14 +08:00
|
|
|
Edit(projectEt *entity.Project, et dto.CommonDtoValues) error
|
|
|
|
Delete(projectEt *entity.Project, id int) (*entity.CommonResource, bool, error)
|
2025-05-15 17:30:33 +08:00
|
|
|
ListPagination(whereSql string, whereArgs []any, f func(po model.IModel)) error
|
|
|
|
UpdateClearDelayInvokeCreateHookFieldN(id int) error
|
2025-04-24 20:39:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewCommonResourceRepo(db *gorm.DB, poTemplate model.IModel) ICommonResourceRepo {
|
|
|
|
return newCommonResourceRepoImpl(db, poTemplate)
|
|
|
|
}
|
|
|
|
|
|
|
|
type commonResourceRepoImpl struct {
|
|
|
|
db *gorm.DB
|
|
|
|
poTemplate model.IModel
|
2025-04-30 15:46:14 +08:00
|
|
|
fieldsDescInfoFun func(project *entity.Project) []*dto.CommonDtoFieldDesc
|
2025-04-24 20:39:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func newCommonResourceRepoImpl(db *gorm.DB, poTemplate model.IModel) *commonResourceRepoImpl {
|
|
|
|
fieldsInfo := (&entity.CommonResource{}).FromPo(poTemplate).GetDtoFieldsDescInfo
|
|
|
|
return &commonResourceRepoImpl{db: db, poTemplate: poTemplate, fieldsDescInfoFun: fieldsInfo}
|
|
|
|
}
|
|
|
|
|
2025-05-09 18:28:15 +08:00
|
|
|
func (repo *commonResourceRepoImpl) List(projectEt *entity.Project, params *dto.CommonListReq) (int, []*dto.CommonDtoFieldDesc, []*entity.CommonResource, error) {
|
2025-05-04 22:07:13 +08:00
|
|
|
|
2025-05-09 18:28:15 +08:00
|
|
|
pageNo := params.PageNo
|
|
|
|
pageLen := params.PageLen
|
|
|
|
whereConditions := params.ParsedWhereConditions.Conditions
|
|
|
|
|
|
|
|
if pageNo <= 0 || pageLen <= 0 {
|
|
|
|
return 0, nil, nil, errcode.New(errcode.ParamsInvalid, "page no or page len invalid:%v,%v", pageNo, pageLen)
|
2025-05-04 22:07:13 +08:00
|
|
|
}
|
|
|
|
|
2025-05-09 18:28:15 +08:00
|
|
|
limitStart := (pageNo - 1) * pageLen
|
2025-05-04 22:07:13 +08:00
|
|
|
limitLen := pageLen
|
2025-04-30 15:46:14 +08:00
|
|
|
|
2025-04-24 20:39:31 +08:00
|
|
|
listType := reflect.New(reflect.SliceOf(reflect.TypeOf(repo.poTemplate)))
|
2025-05-04 22:07:13 +08:00
|
|
|
|
2025-05-09 18:28:15 +08:00
|
|
|
var totalCount int64
|
|
|
|
var txCount, txFind *gorm.DB
|
2025-04-24 20:39:31 +08:00
|
|
|
var err error
|
2025-05-04 22:07:13 +08:00
|
|
|
if len(whereConditions) <= 0 {
|
2025-05-09 18:28:15 +08:00
|
|
|
txCount = repo.db.Model(repo.poTemplate)
|
2025-05-10 10:18:06 +08:00
|
|
|
txFind = repo.db.Offset(limitStart).Limit(limitLen).Order("created_at desc")
|
2025-04-24 20:39:31 +08:00
|
|
|
} else {
|
2025-05-04 22:07:13 +08:00
|
|
|
whereSql, whereArgs := repo.parseWhereConditions2Sql(whereConditions)
|
|
|
|
xlog.Debugf("list resource %v where sql:%v, args:%+v",
|
|
|
|
repo.poTemplate.TableName(), whereSql, whereArgs)
|
2025-05-09 18:28:15 +08:00
|
|
|
txCount = repo.db.Model(repo.poTemplate).Where(whereSql, whereArgs...)
|
2025-05-10 10:18:06 +08:00
|
|
|
txFind = repo.db.Where(whereSql, whereArgs...).Offset(limitStart).Limit(limitLen).Order("created_at desc")
|
2025-05-09 18:28:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
err = txCount.Count(&totalCount).Error
|
|
|
|
if err != nil {
|
|
|
|
return 0, nil, nil, errcode.New(errcode.DBError, "count resource %v error:%v", repo.poTemplate.TableName(), err)
|
2025-04-24 20:39:31 +08:00
|
|
|
}
|
2025-05-09 18:28:15 +08:00
|
|
|
err = txFind.Find(listType.Interface()).Error
|
2025-04-24 20:39:31 +08:00
|
|
|
if err != nil {
|
2025-05-09 18:28:15 +08:00
|
|
|
return 0, nil, nil, errcode.New(errcode.DBError, "list resource %v error:%v", repo.poTemplate.TableName(), err)
|
2025-04-24 20:39:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
listType1 := listType.Elem()
|
|
|
|
listLen := listType1.Len()
|
|
|
|
|
|
|
|
entityList := make([]*entity.CommonResource, 0, listLen)
|
|
|
|
for i := 0; i < listType1.Len(); i++ {
|
|
|
|
po := listType1.Index(i).Interface().(model.IModel)
|
|
|
|
et := &entity.CommonResource{}
|
|
|
|
et.FromPo(po)
|
|
|
|
entityList = append(entityList, et)
|
|
|
|
}
|
|
|
|
|
2025-05-09 18:28:15 +08:00
|
|
|
return int(totalCount), repo.fieldsDescInfoFun(projectEt), entityList, nil
|
2025-04-24 20:39:31 +08:00
|
|
|
}
|
|
|
|
|
2025-04-30 15:46:14 +08:00
|
|
|
func (repo *commonResourceRepoImpl) GetById(projectEt *entity.Project, id int) ([]*dto.CommonDtoFieldDesc, *entity.CommonResource, bool, error) {
|
2025-05-15 17:30:33 +08:00
|
|
|
po := repo.makeEmptyPo()
|
2025-04-30 15:46:14 +08:00
|
|
|
err := repo.db.Where("id = ?", id).First(po).Error
|
2025-04-24 20:39:31 +08:00
|
|
|
if err != nil {
|
|
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
2025-05-15 17:30:33 +08:00
|
|
|
return repo.fieldsDescInfoFun(projectEt), (&entity.CommonResource{}).FromPo(repo.makeEmptyPo()), false, nil
|
2025-04-24 20:39:31 +08:00
|
|
|
}
|
|
|
|
return nil, nil, false, errcode.New(errcode.DBError, "get resource:%v by id:%v error:%v", repo.poTemplate.TableName(), id, err)
|
|
|
|
}
|
2025-04-30 15:46:14 +08:00
|
|
|
return repo.fieldsDescInfoFun(projectEt), (&entity.CommonResource{}).FromPo(po), true, nil
|
2025-04-24 20:39:31 +08:00
|
|
|
}
|
|
|
|
|
2025-05-12 18:43:41 +08:00
|
|
|
func (repo *commonResourceRepoImpl) Create(projectEt *entity.Project, resource string, dtoObj dto.CommonDtoValues) (*entity.CommonResource, error) {
|
2025-05-15 17:30:33 +08:00
|
|
|
et := (&entity.CommonResource{}).FromPo(repo.makeEmptyPo()).FromDto(dtoObj)
|
2025-05-12 18:43:41 +08:00
|
|
|
if handler, find := createHooks[resource]; find {
|
|
|
|
if err := handler(projectEt, dtoObj); err != nil {
|
|
|
|
return et, err
|
|
|
|
}
|
|
|
|
}
|
2025-05-14 18:09:20 +08:00
|
|
|
|
2025-04-24 20:39:31 +08:00
|
|
|
err := repo.db.Create(et.Po).Error
|
|
|
|
if err != nil {
|
2025-05-08 17:33:46 +08:00
|
|
|
if strings.Contains(err.Error(), "Duplicate entry") || strings.Contains(err.Error(), "UNIQUE constraint") {
|
|
|
|
return et, errcode.New(errcode.DBInsertDuplicate, "create resource:%v obj:%+v error:%v", repo.poTemplate.TableName(), et, err)
|
|
|
|
} else {
|
|
|
|
return et, errcode.New(errcode.DBError, "create resource:%v obj:%+v error:%v", repo.poTemplate.TableName(), et, err)
|
|
|
|
}
|
2025-04-24 20:39:31 +08:00
|
|
|
}
|
|
|
|
return et, nil
|
|
|
|
}
|
|
|
|
|
2025-04-30 15:46:14 +08:00
|
|
|
func (repo *commonResourceRepoImpl) Edit(projectEt *entity.Project, dtoObj dto.CommonDtoValues) error {
|
2025-05-15 17:30:33 +08:00
|
|
|
et := (&entity.CommonResource{}).FromPo(repo.makeEmptyPo()).FromDto(dtoObj)
|
2025-05-07 18:25:31 +08:00
|
|
|
err := repo.db.Where("id=?", et.Po.GetId()).Save(et.Po).Error
|
2025-04-24 20:39:31 +08:00
|
|
|
if err != nil {
|
|
|
|
return errcode.New(errcode.DBError, "edit resource:%v obj:%+v error:%v", repo.poTemplate.TableName(), et, err)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2025-04-30 15:46:14 +08:00
|
|
|
func (repo *commonResourceRepoImpl) Delete(projectEt *entity.Project, id int) (*entity.CommonResource, bool, error) {
|
|
|
|
_, et, find, err := repo.GetById(projectEt, id)
|
2025-04-24 20:39:31 +08:00
|
|
|
if err != nil {
|
2025-04-26 13:50:26 +08:00
|
|
|
return nil, false, err
|
2025-04-24 20:39:31 +08:00
|
|
|
}
|
2025-04-26 13:50:26 +08:00
|
|
|
if !find {
|
|
|
|
return et, false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
err = repo.db.Where("id=?", id).Unscoped().Delete(repo.poTemplate).Error
|
|
|
|
if err != nil {
|
|
|
|
return nil, false, errcode.New(errcode.DBError, "delete resource:%v obj:%+v error:%v", repo.poTemplate.TableName(), id, err)
|
|
|
|
}
|
|
|
|
return et, true, nil
|
2025-04-24 20:39:31 +08:00
|
|
|
}
|
|
|
|
|
2025-05-15 17:30:33 +08:00
|
|
|
func (repo *commonResourceRepoImpl) ListPagination(whereSql string, whereArgs []any, f func(po model.IModel)) error {
|
|
|
|
pageNo := 0
|
|
|
|
pageLen := 100
|
|
|
|
for {
|
|
|
|
limitStart := pageNo * pageLen
|
|
|
|
limitLen := pageLen
|
|
|
|
listType := reflect.New(reflect.SliceOf(reflect.TypeOf(repo.poTemplate)))
|
|
|
|
var txFind *gorm.DB
|
|
|
|
var err error
|
|
|
|
if len(whereSql) <= 0 {
|
|
|
|
txFind = repo.db.Offset(limitStart).Limit(limitLen).Order("created_at desc")
|
|
|
|
} else {
|
|
|
|
txFind = repo.db.Where(whereSql, whereArgs...).Offset(limitStart).Limit(limitLen)
|
|
|
|
}
|
|
|
|
err = txFind.Find(listType.Interface()).Error
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
listType1 := listType.Elem()
|
|
|
|
listLen := listType1.Len()
|
|
|
|
|
|
|
|
for i := 0; i < listType1.Len(); i++ {
|
|
|
|
po := listType1.Index(i).Interface().(model.IModel)
|
|
|
|
f(po)
|
|
|
|
}
|
|
|
|
|
|
|
|
if listLen < limitLen {
|
|
|
|
// 遍历完了
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
pageNo++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (repo *commonResourceRepoImpl) UpdateClearDelayInvokeCreateHookFieldN(id int) error {
|
|
|
|
repo.makeEmptyPo()
|
|
|
|
err := repo.db.Model(repo.makeEmptyPo()).Where("id = ?", id).UpdateColumn("delay_invoke_create_hook", sql.NullTime{}).Error
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (repo *commonResourceRepoImpl) makeEmptyPo() model.IModel {
|
2025-04-24 20:39:31 +08:00
|
|
|
return reflect.New(reflect.TypeOf(repo.poTemplate).Elem()).Interface().(model.IModel)
|
|
|
|
}
|
2025-05-04 22:07:13 +08:00
|
|
|
|
|
|
|
func (repo *commonResourceRepoImpl) parseWhereConditions2Sql(conditions []*dto.GetWhereCondition) (whereSql string, args []any) {
|
|
|
|
namer := new(schema.NamingStrategy)
|
|
|
|
to := reflect.TypeOf(repo.poTemplate).Elem()
|
|
|
|
whereClause := make([]string, 0, len(conditions))
|
|
|
|
whereArgs := make([]interface{}, 0, len(conditions))
|
|
|
|
for _, cond := range conditions {
|
|
|
|
for i := 0; i < to.NumField(); i++ {
|
|
|
|
field := to.Field(i)
|
|
|
|
if field.Name != cond.Key {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
dbFieldName := namer.ColumnName("", field.Name)
|
|
|
|
if field.Type.Name() == "Time" {
|
2025-05-15 17:30:33 +08:00
|
|
|
if cond.Value1 == nil {
|
|
|
|
cond.Value1 = time.Time{}
|
|
|
|
} else {
|
|
|
|
cond.Value1, _ = time.ParseInLocation("2006/01/02 15:04:05", cond.Value1.(string), time.Local)
|
|
|
|
}
|
|
|
|
if cond.Value2 == nil {
|
|
|
|
cond.Value2 = time.Time{}
|
|
|
|
} else {
|
|
|
|
cond.Value2, _ = time.ParseInLocation("2006/01/02 15:04:05", cond.Value2.(string), time.Local)
|
|
|
|
}
|
|
|
|
|
2025-05-04 22:07:13 +08:00
|
|
|
}
|
|
|
|
switch field.Tag.Get("where") {
|
|
|
|
case "eq":
|
2025-05-15 17:30:33 +08:00
|
|
|
if field.Tag.Get("type") == "[]string" && field.Tag.Get("multi_choice") == "true" {
|
|
|
|
// eq也要查出来为空的
|
|
|
|
whereClause = append(whereClause, fmt.Sprintf("JSON_CONTAINS( `%v`, '\"%v\"', '$' ) or `%v` IS NULL",
|
|
|
|
dbFieldName, cond.Value1, dbFieldName))
|
|
|
|
} else {
|
|
|
|
whereClause = append(whereClause, fmt.Sprintf("`%v` = ?", dbFieldName))
|
|
|
|
whereArgs = append(whereArgs, cond.Value1)
|
|
|
|
}
|
2025-05-04 22:07:13 +08:00
|
|
|
case "gt":
|
|
|
|
whereClause = append(whereClause, fmt.Sprintf("`%v` > ?", dbFieldName))
|
|
|
|
whereArgs = append(whereArgs, cond.Value1)
|
|
|
|
case "lt":
|
|
|
|
whereClause = append(whereClause, fmt.Sprintf("`%v` < ?", dbFieldName))
|
|
|
|
whereArgs = append(whereArgs, cond.Value1)
|
|
|
|
case "le":
|
|
|
|
whereClause = append(whereClause, fmt.Sprintf("`%v` <= ?", dbFieldName))
|
|
|
|
whereArgs = append(whereArgs, cond.Value1)
|
|
|
|
case "ge":
|
|
|
|
whereClause = append(whereClause, fmt.Sprintf("`%v` >= ?", dbFieldName))
|
|
|
|
whereArgs = append(whereArgs, cond.Value1)
|
|
|
|
case "like":
|
|
|
|
whereClause = append(whereClause, fmt.Sprintf("`%v` like ?", dbFieldName))
|
|
|
|
whereArgs = append(whereArgs, cond.Value1)
|
|
|
|
case "range":
|
2025-05-15 17:30:33 +08:00
|
|
|
t1, ok1 := cond.Value1.(time.Time)
|
|
|
|
t2, ok2 := cond.Value2.(time.Time)
|
|
|
|
if ok1 || ok2 {
|
|
|
|
if !t1.IsZero() && !t2.IsZero() {
|
2025-05-14 18:09:20 +08:00
|
|
|
whereClause = append(whereClause, fmt.Sprintf("`%v` >= ? and `%v` <= ?", dbFieldName, dbFieldName))
|
|
|
|
whereArgs = append(whereArgs, cond.Value1, cond.Value2)
|
|
|
|
} else if !t1.IsZero() {
|
|
|
|
whereClause = append(whereClause, fmt.Sprintf("`%v` >= ? ", dbFieldName))
|
|
|
|
whereArgs = append(whereArgs, cond.Value1)
|
|
|
|
} else {
|
|
|
|
whereClause = append(whereClause, fmt.Sprintf("`%v` <= ? ", dbFieldName))
|
|
|
|
whereArgs = append(whereArgs, cond.Value2)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
whereClause = append(whereClause, fmt.Sprintf("`%v` >= ? and `%v` <= ?", dbFieldName, dbFieldName))
|
|
|
|
whereArgs = append(whereArgs, cond.Value1, cond.Value2)
|
|
|
|
}
|
2025-05-04 22:07:13 +08:00
|
|
|
case "":
|
|
|
|
default:
|
|
|
|
panic(fmt.Errorf("unsupport where tag %v", field.Tag))
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
whereSql = strings.Join(whereClause, " AND ")
|
|
|
|
return whereSql, whereArgs
|
|
|
|
}
|