优化
This commit is contained in:
+93
-46
@@ -75,6 +75,10 @@ func (r *dictionaryRepo) CreateDictionary(ctx context.Context, v *biz.Dictionary
|
||||
}
|
||||
|
||||
func (r *dictionaryRepo) ImportDictionary(ctx context.Context, dictionary *biz.Dictionary, details []*biz.DictionaryDetail) error {
|
||||
var existing dictionaryPO
|
||||
if err := r.data.gormDB.WithContext(ctx).Where("type = ?", dictionary.Type).First(&existing).Error; !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.New("存在相同的type,不允许导入")
|
||||
}
|
||||
return r.data.gormDB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
po := dictionaryPO{Name: dictionary.Name, Type: dictionary.Type, Status: dictionary.Status, Desc: dictionary.Desc, ParentID: dictionary.ParentID}
|
||||
if err := tx.Create(&po).Error; err != nil {
|
||||
@@ -183,15 +187,13 @@ func (r *dictionaryRepo) FindDictionary(ctx context.Context, id uint, typ string
|
||||
}
|
||||
out := dictionaryFromPO(po)
|
||||
if details {
|
||||
out.Details, _, err = r.ListDictionaryDetails(ctx, 0, 0, biz.DictionaryDetailFilter{DictionaryID: out.ID})
|
||||
if err == nil {
|
||||
filtered := out.Details[:0]
|
||||
for _, item := range out.Details {
|
||||
if item.Status != nil && *item.Status {
|
||||
filtered = append(filtered, item)
|
||||
}
|
||||
}
|
||||
out.Details = filtered
|
||||
var detailPOs []dictionaryDetailPO
|
||||
if err = db.Where("sys_dictionary_id = ? AND status = ?", out.ID, true).Order("sort").Find(&detailPOs).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out.Details = make([]*biz.DictionaryDetail, 0, len(detailPOs))
|
||||
for _, detail := range detailPOs {
|
||||
out.Details = append(out.Details, detailFromPO(detail))
|
||||
}
|
||||
}
|
||||
return out, err
|
||||
@@ -203,11 +205,14 @@ func (r *dictionaryRepo) ExportDictionary(ctx context.Context, id uint) (*biz.Di
|
||||
return nil, err
|
||||
}
|
||||
value := dictionaryFromPO(po)
|
||||
details, _, err := r.ListDictionaryDetails(ctx, 0, 0, biz.DictionaryDetailFilter{DictionaryID: id})
|
||||
if err != nil {
|
||||
var detailPOs []dictionaryDetailPO
|
||||
if err := r.data.gormDB.WithContext(ctx).Where("sys_dictionary_id = ?", id).Order("sort").Find(&detailPOs).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
value.Details = details
|
||||
value.Details = make([]*biz.DictionaryDetail, 0, len(detailPOs))
|
||||
for _, detail := range detailPOs {
|
||||
value.Details = append(value.Details, detailFromPO(detail))
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
func (r *dictionaryRepo) ListDictionaries(ctx context.Context, page, size int, name, typ string, details bool) ([]*biz.Dictionary, int64, error) {
|
||||
@@ -221,19 +226,26 @@ func (r *dictionaryRepo) ListDictionaries(ctx context.Context, page, size int, n
|
||||
return nil, 0, err
|
||||
}
|
||||
var pos []dictionaryPO
|
||||
if err := applyPagination(db.Order("id"), page, size, 0).Find(&pos).Error; err != nil {
|
||||
// Both dictionary-list endpoints are intentionally unpaged. The page and
|
||||
// size parameters remain in the repository seam for existing callers, but
|
||||
// the administration contract ignores them.
|
||||
if err := db.Find(&pos).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
parentIDs := make([]uint, 0, len(pos))
|
||||
dictionaryIDs := make([]uint, 0, len(pos))
|
||||
for _, po := range pos {
|
||||
parentIDs = append(parentIDs, po.ID)
|
||||
dictionaryIDs = append(dictionaryIDs, po.ID)
|
||||
// The reference list-with-details endpoint only preloads details;
|
||||
// its ordinary list endpoint preloads one level of dictionary children.
|
||||
if !details {
|
||||
parentIDs = append(parentIDs, po.ID)
|
||||
}
|
||||
}
|
||||
childrenByParent := make(map[uint][]dictionaryPO)
|
||||
if len(parentIDs) > 0 {
|
||||
if !details && len(parentIDs) > 0 {
|
||||
var children []dictionaryPO
|
||||
if err := r.data.gormDB.WithContext(ctx).Where("parent_id IN ?", parentIDs).Order("id").Find(&children).Error; err != nil {
|
||||
if err := r.data.gormDB.WithContext(ctx).Where("parent_id IN ?", parentIDs).Find(&children).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
for _, child := range children {
|
||||
@@ -255,13 +267,16 @@ func (r *dictionaryRepo) ListDictionaries(ctx context.Context, page, size int, n
|
||||
out := make([]*biz.Dictionary, 0, len(pos))
|
||||
for _, po := range pos {
|
||||
v := dictionaryFromPO(po)
|
||||
for _, child := range childrenByParent[po.ID] {
|
||||
v.Children = append(v.Children, dictionaryFromPO(child))
|
||||
}
|
||||
if details {
|
||||
v.Details = make([]*biz.DictionaryDetail, 0, len(detailsByDictionary[v.ID]))
|
||||
for _, detail := range detailsByDictionary[v.ID] {
|
||||
v.Details = append(v.Details, detailFromPO(detail))
|
||||
}
|
||||
} else {
|
||||
v.Children = make([]*biz.Dictionary, 0, len(childrenByParent[po.ID]))
|
||||
for _, child := range childrenByParent[po.ID] {
|
||||
v.Children = append(v.Children, dictionaryFromPO(child))
|
||||
}
|
||||
}
|
||||
out = append(out, v)
|
||||
}
|
||||
@@ -309,28 +324,25 @@ func (r *dictionaryRepo) UpdateDictionaryDetail(ctx context.Context, v *biz.Dict
|
||||
level = parent.Level + 1
|
||||
path = strings.Trim(strings.Join([]string{parent.Path, fmt.Sprint(parent.ID)}, ","), ",")
|
||||
}
|
||||
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 r.updateDictionaryDetailChildren(tx, v.ID, level, path)
|
||||
})
|
||||
if err := db.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 r.updateDictionaryDetailChildren(db, 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 {
|
||||
// updateDictionaryDetailChildren recomputes descendants after a move. Updating
|
||||
// level as well as path matters when a subtree is moved beneath a different depth.
|
||||
func (r *dictionaryRepo) updateDictionaryDetailChildren(db *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 {
|
||||
if err := db.Where("parent_id = ?", parentID).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 {
|
||||
if err := db.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 {
|
||||
if err := r.updateDictionaryDetailChildren(db, child.ID, parentLevel+1, childPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -378,7 +390,7 @@ func (r *dictionaryRepo) ListDictionaryDetails(ctx context.Context, page, size i
|
||||
return nil, 0, err
|
||||
}
|
||||
var pos []dictionaryDetailPO
|
||||
if err := applyPagination(db.Order("sort,id"), page, size, 100).Find(&pos).Error; err != nil {
|
||||
if err := applyRequiredPagination(db.Order("sort,id"), page, size, 100).Find(&pos).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
out := make([]*biz.DictionaryDetail, 0, len(pos))
|
||||
@@ -398,22 +410,57 @@ func (r *dictionaryRepo) DictionaryDetailTree(ctx context.Context, dictionaryID
|
||||
}
|
||||
dictionaryID = dictionary.ID
|
||||
}
|
||||
items, _, err := r.ListDictionaryDetails(ctx, 0, 0, biz.DictionaryDetailFilter{DictionaryID: dictionaryID})
|
||||
if err != nil {
|
||||
var pos []dictionaryDetailPO
|
||||
if err := r.data.gormDB.WithContext(ctx).Where("sys_dictionary_id = ? AND parent_id IS NULL", dictionaryID).Order("sort").Find(&pos).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
byID := map[uint]*biz.DictionaryDetail{}
|
||||
for _, item := range items {
|
||||
item.Children = []*biz.DictionaryDetail{}
|
||||
byID[item.ID] = item
|
||||
}
|
||||
roots := []*biz.DictionaryDetail{}
|
||||
for _, item := range items {
|
||||
if item.ParentID != nil && byID[*item.ParentID] != nil {
|
||||
byID[*item.ParentID].Children = append(byID[*item.ParentID].Children, item)
|
||||
} else if item.ParentID == nil {
|
||||
roots = append(roots, item)
|
||||
roots := make([]*biz.DictionaryDetail, 0, len(pos))
|
||||
for _, po := range pos {
|
||||
item := detailFromPO(po)
|
||||
if err := r.loadDictionaryDetailChildren(ctx, item); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
roots = append(roots, item)
|
||||
}
|
||||
return roots, nil
|
||||
}
|
||||
|
||||
func (r *dictionaryRepo) DictionaryDetailsByParent(ctx context.Context, dictionaryID uint, parentID *uint, includeChildren bool) ([]*biz.DictionaryDetail, error) {
|
||||
db := r.data.gormDB.WithContext(ctx).Where("sys_dictionary_id = ?", dictionaryID)
|
||||
if parentID == nil {
|
||||
db = db.Where("parent_id IS NULL")
|
||||
} else {
|
||||
db = db.Where("parent_id = ?", *parentID)
|
||||
}
|
||||
var pos []dictionaryDetailPO
|
||||
if err := db.Order("sort").Find(&pos).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items := make([]*biz.DictionaryDetail, 0, len(pos))
|
||||
for _, po := range pos {
|
||||
item := detailFromPO(po)
|
||||
if includeChildren {
|
||||
if err := r.loadDictionaryDetailChildren(ctx, item); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
items = append(items, item)
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func (r *dictionaryRepo) loadDictionaryDetailChildren(ctx context.Context, parent *biz.DictionaryDetail) error {
|
||||
var pos []dictionaryDetailPO
|
||||
if err := r.data.gormDB.WithContext(ctx).Where("parent_id = ?", parent.ID).Order("sort").Find(&pos).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
parent.Children = make([]*biz.DictionaryDetail, 0, len(pos))
|
||||
for _, po := range pos {
|
||||
child := detailFromPO(po)
|
||||
if err := r.loadDictionaryDetailChildren(ctx, child); err != nil {
|
||||
return err
|
||||
}
|
||||
parent.Children = append(parent.Children, child)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user