fix: Fixed issue where syncing remote apps causes local app tags to be lost (#9774)

This commit is contained in:
CityFun 2025-07-31 17:21:08 +08:00 committed by GitHub
parent c7e7407f7c
commit 017424bf7b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 95 additions and 24 deletions

View file

@ -17,8 +17,10 @@ type IAppTagRepo interface {
GetByAppId(appId uint) ([]model.AppTag, error)
GetByTagIds(tagIds []uint) ([]model.AppTag, error)
DeleteBy(ctx context.Context, opts ...DBOption) error
GetFirst(opts ...DBOption) (*model.AppTag, error)
WithByTagID(tagID uint) DBOption
WithByAppID(appId uint) DBOption
}
func NewIAppTagRepo() IAppTagRepo {
@ -31,6 +33,12 @@ func (a AppTagRepo) WithByTagID(tagID uint) DBOption {
}
}
func (a AppTagRepo) WithByAppID(appId uint) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("app_id = ?", appId)
}
}
func (a AppTagRepo) BatchCreate(ctx context.Context, tags []*model.AppTag) error {
return getTx(ctx).Create(&tags).Error
}
@ -62,3 +70,12 @@ func (a AppTagRepo) GetByTagIds(tagIds []uint) ([]model.AppTag, error) {
func (a AppTagRepo) DeleteBy(ctx context.Context, opts ...DBOption) error {
return getTx(ctx, opts...).Delete(&model.AppTag{}).Error
}
func (a AppTagRepo) GetFirst(opts ...DBOption) (*model.AppTag, error) {
var appTag model.AppTag
if err := getDb(opts...).First(&appTag).Error; err != nil {
return nil, err
}
return &appTag, nil
}

View file

@ -19,6 +19,7 @@ type ITagRepo interface {
DeleteByID(ctx context.Context, id uint) error
Create(ctx context.Context, tag *model.Tag) error
Save(ctx context.Context, tag *model.Tag) error
GetByKey(key string) (*model.Tag, error)
}
func NewITagRepo() ITagRepo {
@ -41,6 +42,14 @@ func (t TagRepo) All() ([]model.Tag, error) {
return tags, nil
}
func (t TagRepo) GetByKey(key string) (*model.Tag, error) {
var tag model.Tag
if err := getDb().Where("key = ?", key).First(&tag).Error; err != nil {
return nil, err
}
return &tag, nil
}
func (t TagRepo) GetByIds(ids []uint) ([]model.Tag, error) {
var tags []model.Tag
if err := getDb().Where("id in (?)", ids).Find(&tags).Error; err != nil {

View file

@ -928,18 +928,11 @@ func (a AppService) SyncAppListFromRemote(taskID string) (err error) {
return err
}
var (
tags []*model.Tag
appTags []*model.AppTag
oldAppIds []uint
)
for _, tag := range list.Extra.Tags {
translations, _ := json.Marshal(tag.Locales)
tags = append(tags, &model.Tag{
Name: tag.Name,
Translations: string(translations),
Sort: tag.Sort,
Key: tag.Key,
})
if err = SyncTags(list.Extra); err != nil {
return err
}
deleteCustomApp()
oldApps, err := appRepo.GetBy(appRepo.WithNotLocal())
@ -1015,6 +1008,7 @@ func (a AppService) SyncAppListFromRemote(taskID string) (err error) {
}
t.LogSuccess(i18n.GetMsgByKey("SyncAppDetail"))
tags, _ := tagRepo.All()
var (
addAppArray []model.App
updateAppArray []model.App
@ -1061,17 +1055,9 @@ func (a AppService) SyncAppListFromRemote(taskID string) (err error) {
return
}
}
if err = tagRepo.DeleteAll(ctx); err != nil {
return
}
if len(tags) > 0 {
if err = tagRepo.BatchCreate(ctx, tags); err != nil {
return
}
for _, tag := range tags {
tagMap[tag.Key] = tag.ID
}
}
for _, update := range updateAppArray {
if err = appRepo.Save(ctx, &update); err != nil {
return
@ -1088,12 +1074,15 @@ func (a AppService) SyncAppListFromRemote(taskID string) (err error) {
for _, tag := range app.TagsKey {
tagId, ok := tagMap[tag]
if ok {
exist, _ := appTagRepo.GetFirst(appTagRepo.WithByTagID(tagId), appTagRepo.WithByAppID(app.ID))
if exist.ID == 0 {
appTags = append(appTags, &model.AppTag{
AppId: app.ID,
TagId: tagId,
})
}
}
}
for _, d := range app.Details {
d.AppId = app.ID
if d.ID == 0 {
@ -1134,7 +1123,7 @@ func (a AppService) SyncAppListFromRemote(taskID string) (err error) {
}
if len(oldAppIds) > 0 {
if err = appTagRepo.DeleteByAppIds(ctx, oldAppIds); err != nil {
if err = appTagRepo.DeleteByAppIds(ctx, deleteIds); err != nil {
return
}
}

View file

@ -1905,3 +1905,59 @@ func handleSSLConfig(appInstall *model.AppInstall, hasDefaultWebsite bool) error
}
return nil
}
func SyncTags(remoteProperties dto.ExtraProperties) error {
tx, ctx := getTxAndContext()
defer tx.Rollback()
localTags, _ := tagRepo.All()
localTagsMap := make(map[string]*model.Tag)
for i := range localTags {
localTagsMap[localTags[i].Key] = &localTags[i]
}
var err error
remoteTagsMap := make(map[string]*dto.Tag)
for i := range remoteProperties.Tags {
remoteTagsMap[remoteProperties.Tags[i].Key] = &remoteProperties.Tags[i]
}
for key, localTag := range localTagsMap {
if _, exists := remoteTagsMap[key]; !exists {
_ = tagRepo.DeleteByID(ctx, localTag.ID)
}
}
for _, remoteTag := range remoteProperties.Tags {
translations, _ := json.Marshal(remoteTag.Locales)
if existTag, exists := localTagsMap[remoteTag.Key]; exists {
if needsUpdate(existTag, remoteTag, string(translations)) {
existTag.Name = remoteTag.Name
existTag.Sort = remoteTag.Sort
existTag.Translations = string(translations)
if err = tagRepo.Save(ctx, existTag); err != nil {
return err
}
}
} else {
newTag := &model.Tag{
Key: remoteTag.Key,
Name: remoteTag.Name,
Sort: remoteTag.Sort,
Translations: string(translations),
}
if err = tagRepo.Create(ctx, newTag); err != nil {
return err
}
}
}
tx.Commit()
return nil
}
func needsUpdate(localTag *model.Tag, remoteTag dto.Tag, translations string) bool {
return localTag.Name != remoteTag.Name ||
localTag.Sort != remoteTag.Sort ||
localTag.Translations != translations
}