优化
This commit is contained in:
+80
-15
@@ -23,7 +23,7 @@ type dictionaryPO struct {
|
||||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||
Name string
|
||||
Type string
|
||||
Status bool
|
||||
Status *bool
|
||||
Desc string
|
||||
ParentID *uint
|
||||
}
|
||||
@@ -38,7 +38,7 @@ type dictionaryDetailPO struct {
|
||||
Label string
|
||||
Value string
|
||||
Extend string
|
||||
Status bool
|
||||
Status *bool
|
||||
Sort int
|
||||
DictionaryID uint `gorm:"column:sys_dictionary_id;index"`
|
||||
ParentID *uint
|
||||
@@ -59,11 +59,18 @@ func parameterFromPO(po parameterPO) *biz.SystemParameter {
|
||||
}
|
||||
|
||||
func (r *dictionaryRepo) CreateDictionary(ctx context.Context, v *biz.Dictionary) error {
|
||||
var existing dictionaryPO
|
||||
if err := r.data.gormDB.WithContext(ctx).Where("type = ?", v.Type).First(&existing).Error; err == nil {
|
||||
return errors.New("存在相同的type,不允许创建")
|
||||
} else if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
po := dictionaryPO{Name: v.Name, Type: v.Type, Status: v.Status, Desc: v.Desc, ParentID: v.ParentID}
|
||||
if err := r.data.gormDB.WithContext(ctx).Create(&po).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
v.ID = po.ID
|
||||
v.CreatedAt, v.UpdatedAt = po.CreatedAt, po.UpdatedAt
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -108,7 +115,46 @@ func (r *dictionaryRepo) ImportDictionary(ctx context.Context, dictionary *biz.D
|
||||
})
|
||||
}
|
||||
func (r *dictionaryRepo) UpdateDictionary(ctx context.Context, v *biz.Dictionary) error {
|
||||
return r.data.gormDB.WithContext(ctx).Model(&dictionaryPO{}).Where("id = ?", v.ID).Updates(map[string]any{"name": v.Name, "type": v.Type, "status": v.Status, "desc": v.Desc, "parent_id": v.ParentID}).Error
|
||||
db := r.data.gormDB.WithContext(ctx)
|
||||
var current dictionaryPO
|
||||
if err := db.Where("id = ?", v.ID).First(¤t).Error; err != nil {
|
||||
return errors.New("查询字典数据失败")
|
||||
}
|
||||
if current.Type != v.Type {
|
||||
var duplicate dictionaryPO
|
||||
if err := db.Where("type = ?", v.Type).First(&duplicate).Error; err == nil {
|
||||
return errors.New("存在相同的type,不允许创建")
|
||||
} else if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if v.ParentID != nil && *v.ParentID != 0 {
|
||||
if err := r.checkDictionaryCircularReference(ctx, v.ID, *v.ParentID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return db.Model(¤t).Updates(map[string]any{"name": v.Name, "type": v.Type, "status": v.Status, "desc": v.Desc, "parent_id": v.ParentID}).Error
|
||||
}
|
||||
|
||||
// checkDictionaryCircularReference mirrors the compatible recursive parent-chain
|
||||
// check. A missing parent is allowed (the reference implementation permits a
|
||||
// dangling parent ID); only a self-reference or an ancestor cycle is rejected.
|
||||
func (r *dictionaryRepo) checkDictionaryCircularReference(ctx context.Context, currentID, parentID uint) error {
|
||||
if currentID == parentID {
|
||||
return errors.New("不能将字典设置为自己的父级")
|
||||
}
|
||||
var parent dictionaryPO
|
||||
err := r.data.gormDB.WithContext(ctx).Where("id = ?", parentID).First(&parent).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if parent.ParentID != nil && *parent.ParentID != 0 {
|
||||
return r.checkDictionaryCircularReference(ctx, currentID, *parent.ParentID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (r *dictionaryRepo) DeleteDictionary(ctx context.Context, id uint) error {
|
||||
db := r.data.gormDB.WithContext(ctx)
|
||||
@@ -141,7 +187,7 @@ func (r *dictionaryRepo) FindDictionary(ctx context.Context, id uint, typ string
|
||||
if err == nil {
|
||||
filtered := out.Details[:0]
|
||||
for _, item := range out.Details {
|
||||
if item.Status {
|
||||
if item.Status != nil && *item.Status {
|
||||
filtered = append(filtered, item)
|
||||
}
|
||||
}
|
||||
@@ -226,7 +272,7 @@ func (r *dictionaryRepo) CreateDictionaryDetail(ctx context.Context, v *biz.Dict
|
||||
po := dictionaryDetailPO{Label: v.Label, Value: v.Value, Extend: v.Extend, Status: v.Status, Sort: v.Sort, DictionaryID: v.DictionaryID, ParentID: v.ParentID}
|
||||
po.Level = 0
|
||||
po.Path = ""
|
||||
if v.ParentID != nil && *v.ParentID != 0 {
|
||||
if v.ParentID != nil {
|
||||
var parent dictionaryDetailPO
|
||||
if err := r.data.gormDB.WithContext(ctx).First(&parent, *v.ParentID).Error; err != nil {
|
||||
return err
|
||||
@@ -244,40 +290,59 @@ func (r *dictionaryRepo) CreateDictionaryDetail(ctx context.Context, v *biz.Dict
|
||||
}
|
||||
func (r *dictionaryRepo) UpdateDictionaryDetail(ctx context.Context, v *biz.DictionaryDetail) error {
|
||||
var po dictionaryDetailPO
|
||||
if err := r.data.gormDB.WithContext(ctx).First(&po, v.ID).Error; err != nil {
|
||||
db := r.data.gormDB.WithContext(ctx)
|
||||
if err := db.First(&po, v.ID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
level, path := 0, ""
|
||||
if v.ParentID != nil && *v.ParentID != 0 {
|
||||
if v.ParentID != nil {
|
||||
if *v.ParentID == v.ID {
|
||||
return errors.New("不能将自身设为父级")
|
||||
return errors.New("不能将字典详情设置为自己或其子项的父级")
|
||||
}
|
||||
var parent dictionaryDetailPO
|
||||
if err := r.data.gormDB.WithContext(ctx).First(&parent, *v.ParentID).Error; err != nil {
|
||||
if err := db.First(&parent, *v.ParentID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.Contains(","+parent.Path+",", fmt.Sprintf(",%d,", v.ID)) {
|
||||
return errors.New("不能移动到自己的子级")
|
||||
return errors.New("不能将字典详情设置为自己或其子项的父级")
|
||||
}
|
||||
level = parent.Level + 1
|
||||
path = strings.Trim(strings.Join([]string{parent.Path, fmt.Sprint(parent.ID)}, ","), ",")
|
||||
}
|
||||
oldPrefix := strings.Trim(strings.Join([]string{po.Path, fmt.Sprint(po.ID)}, ","), ",")
|
||||
newPrefix := strings.Trim(strings.Join([]string{path, fmt.Sprint(po.ID)}, ","), ",")
|
||||
return r.data.gormDB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Model(&dictionaryDetailPO{}).Where("id = ?", v.ID).Updates(map[string]any{"label": v.Label, "value": v.Value, "extend": v.Extend, "status": v.Status, "sort": v.Sort, "sys_dictionary_id": v.DictionaryID, "parent_id": v.ParentID, "level": level, "path": path}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Model(&dictionaryDetailPO{}).Where("path = ? OR path LIKE ?", oldPrefix, oldPrefix+",%").Update("path", gorm.Expr("REPLACE(path, ?, ?)", oldPrefix, newPrefix)).Error
|
||||
return r.updateDictionaryDetailChildren(tx, v.ID, level, path)
|
||||
})
|
||||
}
|
||||
|
||||
// updateDictionaryDetailChildren recomputes descendants after a move, as the
|
||||
// The service does this recursively. Updating level as well as path matters when a
|
||||
// subtree is moved beneath a different depth.
|
||||
func (r *dictionaryRepo) updateDictionaryDetailChildren(tx *gorm.DB, parentID uint, parentLevel int, parentPath string) error {
|
||||
var children []dictionaryDetailPO
|
||||
if err := tx.Where("parent_id = ?", parentID).Order("sort,id").Find(&children).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
for _, child := range children {
|
||||
childPath := strings.Trim(strings.Join([]string{parentPath, fmt.Sprint(parentID)}, ","), ",")
|
||||
if err := tx.Model(&dictionaryDetailPO{}).Where("id = ?", child.ID).Updates(map[string]any{"level": parentLevel + 1, "path": childPath}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := r.updateDictionaryDetailChildren(tx, child.ID, parentLevel+1, childPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (r *dictionaryRepo) DeleteDictionaryDetail(ctx context.Context, id uint) error {
|
||||
var count int64
|
||||
if err := r.data.gormDB.WithContext(ctx).Model(&dictionaryDetailPO{}).Where("parent_id = ?", id).Count(&count).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if count > 0 {
|
||||
return errors.New("存在子级不可删除")
|
||||
return errors.New("该字典详情下还有子项,无法删除")
|
||||
}
|
||||
return r.data.gormDB.WithContext(ctx).Delete(&dictionaryDetailPO{}, id).Error
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user