作者 tangxvhui

调整 文章编辑历史的保存

@@ -168,12 +168,14 @@ type ( @@ -168,12 +168,14 @@ type (
168 List []MiniArticleBackupItem `json:"list"` 168 List []MiniArticleBackupItem `json:"list"`
169 } 169 }
170 MiniArticleBackupItem { 170 MiniArticleBackupItem {
171 - Id int64 `json:"id"`  
172 - Title string `json:"title"`  
173 - Content string `json:"content"`  
174 - Images []string `json:"images"`  
175 - CreatedAt int64 `json:"createdAt"`  
176 - Location Location `json:"location"` 171 + Id int64 `json:"id"`
  172 + Title string `json:"title"`
  173 + Content string `json:"content"`
  174 + Images []string `json:"images"`
  175 + Videos []Video `json:"videos"`
  176 + ChangeField []string `json:"changeField"`
  177 + CreatedAt int64 `json:"createdAt"`
  178 + Location Location `json:"location"`
177 } 179 }
178 ) 180 )
179 // 标记人员浏览了那个文章 181 // 标记人员浏览了那个文章
@@ -51,17 +51,29 @@ func (l *MiniArticleBackupSearchLogic) MiniArticleBackupSearch(req *types.MiniAr @@ -51,17 +51,29 @@ func (l *MiniArticleBackupSearchLogic) MiniArticleBackupSearch(req *types.MiniAr
51 for _, val2 := range backupList[i].Images { 51 for _, val2 := range backupList[i].Images {
52 images = append(images, val2.Url) 52 images = append(images, val2.Url)
53 } 53 }
  54 +
  55 + videos := []types.Video{}
  56 + for _, val2 := range backupList[i].Videos {
  57 + videos = append(videos, types.Video{
  58 + Url: val2.Url,
  59 + Cover: val2.Cover,
  60 + Width: val2.Width,
  61 + Height: val2.Height,
  62 + })
  63 + }
54 resp.List[i] = types.MiniArticleBackupItem{ 64 resp.List[i] = types.MiniArticleBackupItem{
55 Id: backupList[i].Id, 65 Id: backupList[i].Id,
56 Title: backupList[i].Title, 66 Title: backupList[i].Title,
57 Content: content.String(), 67 Content: content.String(),
58 Images: images, 68 Images: images,
  69 + Videos: videos,
59 CreatedAt: backupList[i].CreatedAt, 70 CreatedAt: backupList[i].CreatedAt,
60 Location: types.Location{ 71 Location: types.Location{
61 Longitude: backupList[i].Location.Longitude, 72 Longitude: backupList[i].Location.Longitude,
62 Latitude: backupList[i].Location.Latitude, 73 Latitude: backupList[i].Location.Latitude,
63 Descript: backupList[i].Location.Descript, 74 Descript: backupList[i].Location.Descript,
64 }, 75 },
  76 + ChangeField: backupList[i].ChangeField,
65 } 77 }
66 } 78 }
67 return resp, nil 79 return resp, nil
@@ -127,7 +127,7 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR @@ -127,7 +127,7 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR
127 } 127 }
128 128
129 //切分文章分段 129 //切分文章分段
130 - sectionList := []domain.ArticleSection{} 130 + sectionList := []*domain.ArticleSection{}
131 newStr := "" 131 newStr := ""
132 for i := range req.Section { 132 for i := range req.Section {
133 strList := strings.Split(req.Section[i], "\n") 133 strList := strings.Split(req.Section[i], "\n")
@@ -141,7 +141,7 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR @@ -141,7 +141,7 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR
141 SortBy: len(sectionList), 141 SortBy: len(sectionList),
142 TotalComment: 0, 142 TotalComment: 0,
143 } 143 }
144 - sectionList = append(sectionList, newSection) 144 + sectionList = append(sectionList, &newSection)
145 } 145 }
146 } 146 }
147 147
@@ -185,11 +185,20 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR @@ -185,11 +185,20 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR
185 185
186 for i := range sectionList { 186 for i := range sectionList {
187 sectionList[i].ArticleId = newArticle.Id 187 sectionList[i].ArticleId = newArticle.Id
188 - _, err = l.svcCtx.ArticleSectionRepository.Insert(ctx, c, &sectionList[i]) 188 + _, err = l.svcCtx.ArticleSectionRepository.Insert(ctx, c, sectionList[i])
189 if err != nil { 189 if err != nil {
190 return xerr.NewErrMsgErr("创建文章内容失败", err) 190 return xerr.NewErrMsgErr("创建文章内容失败", err)
191 } 191 }
192 } 192 }
  193 +
  194 + // 生成 备份数据
  195 + backupData := newArticle.MakeBackup(articleAuthor, sectionList)
  196 + backupData.Action = "原始版本"
  197 +
  198 + _, err = l.svcCtx.ArticleBackupRepository.Insert(l.ctx, conn, backupData)
  199 + if err != nil {
  200 + return xerr.NewErrMsgErr("创建文章失败", err)
  201 + }
193 return nil 202 return nil
194 }, true) 203 }, true)
195 if err != nil { 204 if err != nil {
@@ -32,7 +32,7 @@ func NewSystemArticleRestoreLogic(ctx context.Context, svcCtx *svc.ServiceContex @@ -32,7 +32,7 @@ func NewSystemArticleRestoreLogic(ctx context.Context, svcCtx *svc.ServiceContex
32 32
33 func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticleRestoreRequest) (resp *types.SystemArticleRestoreResponse, err error) { 33 func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticleRestoreRequest) (resp *types.SystemArticleRestoreResponse, err error) {
34 var conn = l.svcCtx.DefaultDBConn() 34 var conn = l.svcCtx.DefaultDBConn()
35 - backup, err := l.svcCtx.ArticleBackupRepository.FindOne(l.ctx, conn, req.Id) 35 + oldBackup, err := l.svcCtx.ArticleBackupRepository.FindOne(l.ctx, conn, req.Id)
36 if err != nil { 36 if err != nil {
37 return nil, xerr.NewErrMsgErr("获取编辑历史记录失败", err) 37 return nil, xerr.NewErrMsgErr("获取编辑历史记录失败", err)
38 } 38 }
@@ -42,7 +42,7 @@ func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticl @@ -42,7 +42,7 @@ func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticl
42 if err != nil { 42 if err != nil {
43 return nil, xerr.NewErrMsgErr("获取当前用户信息失败", err) 43 return nil, xerr.NewErrMsgErr("获取当前用户信息失败", err)
44 } 44 }
45 - article, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, backup.ArticleId) 45 + article, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, oldBackup.ArticleId)
46 if err != nil { 46 if err != nil {
47 return nil, xerr.NewErrMsgErr("获取文章失败", err) 47 return nil, xerr.NewErrMsgErr("获取文章失败", err)
48 } 48 }
@@ -50,6 +50,7 @@ func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticl @@ -50,6 +50,7 @@ func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticl
50 if err != nil { 50 if err != nil {
51 return nil, xerr.NewErrMsgErr("获取文章段落内容失败", err) 51 return nil, xerr.NewErrMsgErr("获取文章段落内容失败", err)
52 } 52 }
  53 +
53 // 备份数据 54 // 备份数据
54 newBackUp := article.MakeBackup(domain.UserSimple{ 55 newBackUp := article.MakeBackup(domain.UserSimple{
55 Id: userToken.UserId, 56 Id: userToken.UserId,
@@ -59,15 +60,16 @@ func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticl @@ -59,15 +60,16 @@ func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticl
59 Company: userMe.CurrentCompany.Name, 60 Company: userMe.CurrentCompany.Name,
60 }, sectionList) 61 }, sectionList)
61 newBackUp.Action = "恢复" 62 newBackUp.Action = "恢复"
  63 + _ = newBackUp.CheckChangeField(oldBackup)
62 64
63 article.Version = article.Version + 1 65 article.Version = article.Version + 1
64 - article.Images = backup.Images  
65 - article.Videos = backup.Videos  
66 - article.Title = backup.Title  
67 - article.MatchUrl = backup.MatchUrl  
68 - articleSections := make([]domain.ArticleSection, 0)  
69 - lo.ForEach(backup.Section, func(item domain.ArticleSection, index int) {  
70 - articleSections = append(articleSections, domain.ArticleSection{ 66 + article.Images = oldBackup.Images
  67 + article.Videos = oldBackup.Videos
  68 + article.Title = oldBackup.Title
  69 + article.MatchUrl = oldBackup.MatchUrl
  70 + articleSections := make([]*domain.ArticleSection, 0)
  71 + lo.ForEach(oldBackup.Section, func(item domain.ArticleSection, index int) {
  72 + articleSections = append(articleSections, &domain.ArticleSection{
71 Id: item.Id, 73 Id: item.Id,
72 CompanyId: item.CompanyId, 74 CompanyId: item.CompanyId,
73 Version: article.Version, 75 Version: article.Version,
@@ -98,7 +100,7 @@ func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticl @@ -98,7 +100,7 @@ func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticl
98 return xerr.NewErrMsgErr("恢复文章版本失败", err) 100 return xerr.NewErrMsgErr("恢复文章版本失败", err)
99 } 101 }
100 } else { 102 } else {
101 - _, err = l.svcCtx.ArticleSectionRepository.Insert(ctx, c, &item) 103 + _, err = l.svcCtx.ArticleSectionRepository.Insert(ctx, c, item)
102 if err != nil { 104 if err != nil {
103 return xerr.NewErrMsgErr("恢复文章版本失败", err) 105 return xerr.NewErrMsgErr("恢复文章版本失败", err)
104 } 106 }
@@ -106,7 +108,8 @@ func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticl @@ -106,7 +108,8 @@ func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticl
106 updateSectionIds = append(updateSectionIds, item.Id) 108 updateSectionIds = append(updateSectionIds, item.Id)
107 } 109 }
108 if len(updateSectionIds) > 0 { 110 if len(updateSectionIds) > 0 {
109 - err = l.svcCtx.ArticleSectionRepository.DeleteBy(ctx, c, domain.NewQueryOptions().WithKV("articleId", article.Id).WithKV("notIds", updateSectionIds)) 111 + queryOption := domain.NewQueryOptions().WithKV("articleId", article.Id).WithKV("notIds", updateSectionIds)
  112 + err = l.svcCtx.ArticleSectionRepository.DeleteBy(ctx, c, queryOption)
110 if err != nil { 113 if err != nil {
111 return xerr.NewErrMsgErr("保存文章内容失败", err) 114 return xerr.NewErrMsgErr("保存文章内容失败", err)
112 } 115 }
@@ -57,25 +57,25 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU @@ -57,25 +57,25 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU
57 if err != nil { 57 if err != nil {
58 return nil, xerr.NewErrMsgErr("获取当前用户信息失败", err) 58 return nil, xerr.NewErrMsgErr("获取当前用户信息失败", err)
59 } 59 }
  60 + operator := domain.UserSimple{
  61 + Id: userToken.UserId,
  62 + Name: userMe.User.NickName,
  63 + Avatar: userMe.User.Avatar,
  64 + CompanyId: userToken.CompanyId,
  65 + Company: userMe.CurrentCompany.Name,
  66 + }
60 // 文章数据 67 // 文章数据
61 article, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, l.conn, req.Id) 68 article, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, l.conn, req.Id)
62 if err != nil { 69 if err != nil {
63 return nil, xerr.NewErrMsgErr("帖子不存在", err) 70 return nil, xerr.NewErrMsgErr("帖子不存在", err)
64 } 71 }
65 - _, sectionList, err := l.svcCtx.ArticleSectionRepository.Find(l.ctx, l.conn, map[string]interface{}{"articleId": article.Id}) 72 + //
  73 + queryOption := domain.NewQueryOptions().WithFindOnly().MustWithKV("articleId", req.Id)
  74 + _, sectionList, err := l.svcCtx.ArticleSectionRepository.Find(l.ctx, l.conn, queryOption)
66 if err != nil { 75 if err != nil {
67 - return nil, xerr.NewErrMsgErr("获取文章段落内容失败", err) 76 + return nil, xerr.NewErrMsgErr("帖子不存在", err)
68 } 77 }
69 - //备份数据  
70 - backup := article.MakeBackup(domain.UserSimple{  
71 - Id: userToken.UserId,  
72 - Name: userMe.User.NickName,  
73 - Avatar: userMe.User.Avatar,  
74 - CompanyId: userToken.CompanyId,  
75 - Company: userMe.CurrentCompany.Name,  
76 - }, sectionList)  
77 - backup.Action = "编辑"  
78 - 78 + oldBackup := article.MakeBackup(operator, sectionList)
79 // 获取图片的尺寸大小 79 // 获取图片的尺寸大小
80 images, err := l.getImages(req) 80 images, err := l.getImages(req)
81 if err != nil { 81 if err != nil {
@@ -126,6 +126,7 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU @@ -126,6 +126,7 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU
126 } 126 }
127 //文章内容 127 //文章内容
128 updateSectionIds := []int64{} 128 updateSectionIds := []int64{}
  129 + updateSection := []*domain.ArticleSection{}
129 for _, item := range articleSections { 130 for _, item := range articleSections {
130 if item.Id > 0 { 131 if item.Id > 0 {
131 section, err := l.svcCtx.ArticleSectionRepository.FindOne(ctx, c, item.Id) 132 section, err := l.svcCtx.ArticleSectionRepository.FindOne(ctx, c, item.Id)
@@ -142,22 +143,29 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU @@ -142,22 +143,29 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU
142 return xerr.NewErrMsgErr("保存文章段落内容失败", err) 143 return xerr.NewErrMsgErr("保存文章段落内容失败", err)
143 } 144 }
144 } else { 145 } else {
145 - _, err = l.svcCtx.ArticleSectionRepository.Insert(ctx, c, &item) 146 + _, err = l.svcCtx.ArticleSectionRepository.Insert(ctx, c, item)
146 if err != nil { 147 if err != nil {
147 return xerr.NewErrMsgErr("保存文章段落内容失败", err) 148 return xerr.NewErrMsgErr("保存文章段落内容失败", err)
148 } 149 }
149 } 150 }
150 updateSectionIds = append(updateSectionIds, item.Id) 151 updateSectionIds = append(updateSectionIds, item.Id)
  152 + updateSection = append(updateSection, item)
151 } 153 }
152 if len(updateSectionIds) > 0 { 154 if len(updateSectionIds) > 0 {
153 - err = l.svcCtx.ArticleSectionRepository.DeleteBy(ctx, c, domain.NewQueryOptions().WithKV("articleId", article.Id).WithKV("notIds", updateSectionIds)) 155 + queryOption := domain.NewQueryOptions().WithKV("articleId", article.Id).WithKV("notIds", updateSectionIds)
  156 + err = l.svcCtx.ArticleSectionRepository.DeleteBy(ctx, c, queryOption)
154 if err != nil { 157 if err != nil {
155 return xerr.NewErrMsgErr("保存文章内容失败", err) 158 return xerr.NewErrMsgErr("保存文章内容失败", err)
156 } 159 }
157 } 160 }
158 - _, err = l.svcCtx.ArticleBackupRepository.Insert(ctx, c, backup)  
159 - if err != nil {  
160 - return xerr.NewErrMsgErr("保存文章内容失败", err) 161 +
  162 + backup := article.MakeBackup(operator, updateSection)
  163 + backup.Action = "编辑"
  164 + if ok := backup.CheckChangeField(oldBackup); ok {
  165 + _, err = l.svcCtx.ArticleBackupRepository.Insert(ctx, c, backup)
  166 + if err != nil {
  167 + return xerr.NewErrMsgErr("保存文章内容失败", err)
  168 + }
161 } 169 }
162 //文章定性 170 //文章定性
163 err = l.setTags(c, article) 171 err = l.setTags(c, article)
@@ -307,8 +315,8 @@ func (l *SystemUpdateArticleLogic) getVideos(req *types.SystemArticleUpdateReque @@ -307,8 +315,8 @@ func (l *SystemUpdateArticleLogic) getVideos(req *types.SystemArticleUpdateReque
307 return videos, nil 315 return videos, nil
308 } 316 }
309 317
310 -func (l *SystemUpdateArticleLogic) getSections(req *types.SystemArticleUpdateRequest, article *domain.Article) []domain.ArticleSection {  
311 - articleSections := make([]domain.ArticleSection, 0) 318 +func (l *SystemUpdateArticleLogic) getSections(req *types.SystemArticleUpdateRequest, article *domain.Article) []*domain.ArticleSection {
  319 + articleSections := make([]*domain.ArticleSection, 0)
312 sortBy := 1 320 sortBy := 1
313 lo.ForEach(req.Section, func(item types.ArticleSection, index int) { 321 lo.ForEach(req.Section, func(item types.ArticleSection, index int) {
314 strList := strings.Split(item.Content, "\n") 322 strList := strings.Split(item.Content, "\n")
@@ -326,7 +334,7 @@ func (l *SystemUpdateArticleLogic) getSections(req *types.SystemArticleUpdateReq @@ -326,7 +334,7 @@ func (l *SystemUpdateArticleLogic) getSections(req *types.SystemArticleUpdateReq
326 if key == 0 { 334 if key == 0 {
327 section.Id = item.Id 335 section.Id = item.Id
328 } 336 }
329 - articleSections = append(articleSections, section) 337 + articleSections = append(articleSections, &section)
330 sortBy++ 338 sortBy++
331 } 339 }
332 }) 340 })
@@ -1028,12 +1028,14 @@ type MiniArticleBackupSearchResponse struct { @@ -1028,12 +1028,14 @@ type MiniArticleBackupSearchResponse struct {
1028 } 1028 }
1029 1029
1030 type MiniArticleBackupItem struct { 1030 type MiniArticleBackupItem struct {
1031 - Id int64 `json:"id"`  
1032 - Title string `json:"title"`  
1033 - Content string `json:"content"`  
1034 - Images []string `json:"images"`  
1035 - CreatedAt int64 `json:"createdAt"`  
1036 - Location Location `json:"location"` 1031 + Id int64 `json:"id"`
  1032 + Title string `json:"title"`
  1033 + Content string `json:"content"`
  1034 + Images []string `json:"images"`
  1035 + Videos []Video `json:"videos"`
  1036 + ChangeField []string `json:"changeField"`
  1037 + CreatedAt int64 `json:"createdAt"`
  1038 + Location Location `json:"location"`
1037 } 1039 }
1038 1040
1039 type MiniArticleMarkUserReadRequest struct { 1041 type MiniArticleMarkUserReadRequest struct {
@@ -10,26 +10,27 @@ import ( @@ -10,26 +10,27 @@ import (
10 ) 10 )
11 11
12 type ArticleBackup struct { 12 type ArticleBackup struct {
13 - Id int64 `gorm:"primaryKey"` // 唯一标识  
14 - CompanyId int64  
15 - CreatedAt int64  
16 - UpdatedAt int64  
17 - DeletedAt int64  
18 - IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"`  
19 - Version int  
20 - Operator domain.UserSimple `gorm:"type:jsonb;serializer:json"` // 操作人  
21 - ArticleId int64  
22 - Title string // 标题  
23 - Section []domain.ArticleSection `gorm:"type:jsonb;serializer:json"` // 分段内容  
24 - Images []domain.Image `gorm:"type:jsonb;serializer:json"` // 图片  
25 - Videos []domain.Video `gorm:"type:jsonb;serializer:json"` // 视频  
26 - Action string // 操作  
27 - WhoRead []int64 `gorm:"type:jsonb;serializer:json"` // 谁可以看  
28 - WhoReview []int64 `gorm:"type:jsonb;serializer:json"` // 评论人  
29 - Tags []int64 `gorm:"type:jsonb;serializer:json"` // 标签  
30 - Location domain.Location `gorm:"type:jsonb;serializer:json"` // 坐标  
31 - TargetUser int // 分发方式 0 分发给所有人 1 分发给指定的人  
32 - MatchUrl map[string]string `gorm:"type:jsonb;serializer:json"` // 匹配文章内容中的url文本 13 + Id int64 `gorm:"primaryKey"` // 唯一标识
  14 + CompanyId int64
  15 + CreatedAt int64
  16 + UpdatedAt int64
  17 + DeletedAt int64
  18 + IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"`
  19 + Version int
  20 + Operator domain.UserSimple `gorm:"type:jsonb;serializer:json"` // 操作人
  21 + ArticleId int64
  22 + Title string // 标题
  23 + Section []domain.ArticleSection `gorm:"type:jsonb;serializer:json"` // 分段内容
  24 + Images []domain.Image `gorm:"type:jsonb;serializer:json"` // 图片
  25 + Videos []domain.Video `gorm:"type:jsonb;serializer:json"` // 视频
  26 + ChangeField []string `gorm:"type:jsonb;serializer:json"` //
  27 + Action string // 操作
  28 + WhoRead []int64 `gorm:"type:jsonb;serializer:json"` // 谁可以看
  29 + WhoReview []int64 `gorm:"type:jsonb;serializer:json"` // 评论人
  30 + Tags []int64 `gorm:"type:jsonb;serializer:json"` // 标签
  31 + Location domain.Location `gorm:"type:jsonb;serializer:json"` // 坐标
  32 + TargetUser int // 分发方式 0 分发给所有人 1 分发给指定的人
  33 + MatchUrl map[string]string `gorm:"type:jsonb;serializer:json"` // 匹配文章内容中的url文本
33 } 34 }
34 35
35 func (m *ArticleBackup) TableName() string { 36 func (m *ArticleBackup) TableName() string {
@@ -157,25 +157,26 @@ func (repository *ArticleBackupRepository) Find(ctx context.Context, conn transa @@ -157,25 +157,26 @@ func (repository *ArticleBackupRepository) Find(ctx context.Context, conn transa
157 157
158 func (repository *ArticleBackupRepository) ModelToDomainModel(from *models.ArticleBackup) (*domain.ArticleBackup, error) { 158 func (repository *ArticleBackupRepository) ModelToDomainModel(from *models.ArticleBackup) (*domain.ArticleBackup, error) {
159 to := &domain.ArticleBackup{ 159 to := &domain.ArticleBackup{
160 - Id: from.Id,  
161 - CompanyId: from.CompanyId,  
162 - CreatedAt: from.CreatedAt,  
163 - UpdatedAt: from.CreatedAt,  
164 - DeletedAt: from.DeletedAt,  
165 - Version: from.Version,  
166 - Operator: from.Operator,  
167 - ArticleId: from.ArticleId,  
168 - Title: from.Title,  
169 - Section: from.Section,  
170 - Images: from.Images,  
171 - Action: from.Action,  
172 - TargetUser: domain.ArticleTarget(from.TargetUser),  
173 - Location: from.Location,  
174 - WhoRead: from.WhoRead,  
175 - WhoReview: from.WhoReview,  
176 - Tags: from.Tags,  
177 - MatchUrl: from.MatchUrl,  
178 - Videos: from.Videos, 160 + Id: from.Id,
  161 + CompanyId: from.CompanyId,
  162 + CreatedAt: from.CreatedAt,
  163 + UpdatedAt: from.CreatedAt,
  164 + DeletedAt: from.DeletedAt,
  165 + Version: from.Version,
  166 + Operator: from.Operator,
  167 + ArticleId: from.ArticleId,
  168 + Title: from.Title,
  169 + Section: from.Section,
  170 + Images: from.Images,
  171 + Action: from.Action,
  172 + TargetUser: domain.ArticleTarget(from.TargetUser),
  173 + Location: from.Location,
  174 + WhoRead: from.WhoRead,
  175 + WhoReview: from.WhoReview,
  176 + Tags: from.Tags,
  177 + MatchUrl: from.MatchUrl,
  178 + ChangeField: from.ChangeField,
  179 + Videos: from.Videos,
179 } 180 }
180 // err := copier.Copy(to, from) 181 // err := copier.Copy(to, from)
181 return to, nil 182 return to, nil
@@ -183,26 +184,27 @@ func (repository *ArticleBackupRepository) ModelToDomainModel(from *models.Artic @@ -183,26 +184,27 @@ func (repository *ArticleBackupRepository) ModelToDomainModel(from *models.Artic
183 184
184 func (repository *ArticleBackupRepository) DomainModelToModel(from *domain.ArticleBackup) (*models.ArticleBackup, error) { 185 func (repository *ArticleBackupRepository) DomainModelToModel(from *domain.ArticleBackup) (*models.ArticleBackup, error) {
185 to := &models.ArticleBackup{ 186 to := &models.ArticleBackup{
186 - Id: from.Id,  
187 - CompanyId: from.CompanyId,  
188 - CreatedAt: from.CreatedAt,  
189 - UpdatedAt: from.CreatedAt,  
190 - DeletedAt: from.DeletedAt,  
191 - IsDel: 0,  
192 - Version: from.Version,  
193 - Operator: from.Operator,  
194 - ArticleId: from.ArticleId,  
195 - Title: from.Title,  
196 - Section: from.Section,  
197 - Images: from.Images,  
198 - Action: from.Action,  
199 - WhoRead: from.WhoRead,  
200 - WhoReview: from.WhoReview,  
201 - Tags: from.Tags,  
202 - Location: from.Location,  
203 - TargetUser: int(from.TargetUser),  
204 - MatchUrl: from.MatchUrl,  
205 - Videos: from.Videos, 187 + Id: from.Id,
  188 + CompanyId: from.CompanyId,
  189 + CreatedAt: from.CreatedAt,
  190 + UpdatedAt: from.CreatedAt,
  191 + DeletedAt: from.DeletedAt,
  192 + IsDel: 0,
  193 + Version: from.Version,
  194 + Operator: from.Operator,
  195 + ArticleId: from.ArticleId,
  196 + Title: from.Title,
  197 + Section: from.Section,
  198 + Images: from.Images,
  199 + Action: from.Action,
  200 + WhoRead: from.WhoRead,
  201 + WhoReview: from.WhoReview,
  202 + Tags: from.Tags,
  203 + Location: from.Location,
  204 + TargetUser: int(from.TargetUser),
  205 + MatchUrl: from.MatchUrl,
  206 + Videos: from.Videos,
  207 + ChangeField: from.ChangeField,
206 } 208 }
207 // err := copier.Copy(to, from) 209 // err := copier.Copy(to, from)
208 return to, nil 210 return to, nil
@@ -130,7 +130,7 @@ func (m *Article) MakeBackup(operator UserSimple, section []*ArticleSection) *Ar @@ -130,7 +130,7 @@ func (m *Article) MakeBackup(operator UserSimple, section []*ArticleSection) *Ar
130 return &b 130 return &b
131 } 131 }
132 132
133 -func (m *Article) SetSummary(sectionList []ArticleSection) { 133 +func (m *Article) SetSummary(sectionList []*ArticleSection) {
134 if len(sectionList) == 0 { 134 if len(sectionList) == 0 {
135 return 135 return
136 } 136 }
1 package domain 1 package domain
2 2
3 import ( 3 import (
  4 + "bytes"
4 "context" 5 "context"
  6 + "encoding/json"
  7 + "fmt"
  8 + "sort"
5 9
6 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction" 10 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
7 ) 11 )
8 12
9 // 编辑文章后保存的历史记录 13 // 编辑文章后保存的历史记录
10 type ArticleBackup struct { 14 type ArticleBackup struct {
11 - Id int64 `json:"id"`  
12 - CompanyId int64 `json:"companyId"`  
13 - CreatedAt int64 `json:"createdAt,omitempty"`  
14 - UpdatedAt int64 `json:"updatedAt,omitempty"`  
15 - DeletedAt int64 `json:"deletedAt,omitempty"`  
16 - Version int `json:"version,omitempty"`  
17 - Operator UserSimple `json:"operator"` // 操作人  
18 - ArticleId int64 `json:"articleId"` //  
19 - Title string `json:"title"` // 标题  
20 - Section []ArticleSection `json:"section"` // 分段内容  
21 - Images []Image `json:"images"` // 图片  
22 - Videos []Video `json:"videos"` // 视频  
23 - Action string `json:"action"` // 操作  
24 - TargetUser ArticleTarget `json:"targetUser"` // 分发方式 0 分发给所有人 1 分发给指定的人  
25 - Location Location `json:"location"` // 定位坐标  
26 - WhoRead []int64 `json:"whoRead"` // 谁可以看  
27 - WhoReview []int64 `json:"whoReview"` // 评论人  
28 - Tags []int64 `json:"tags"` // 标签  
29 - MatchUrl map[string]string `json:"matchUrl"` // 匹配文章内容中的url文本 15 + Id int64 `json:"id"`
  16 + CompanyId int64 `json:"companyId"`
  17 + CreatedAt int64 `json:"createdAt,omitempty"`
  18 + UpdatedAt int64 `json:"updatedAt,omitempty"`
  19 + DeletedAt int64 `json:"deletedAt,omitempty"`
  20 + Version int `json:"version,omitempty"`
  21 + Operator UserSimple `json:"operator"` // 操作人
  22 + ArticleId int64 `json:"articleId"` //
  23 + Title string `json:"title"` // 标题
  24 + Section []ArticleSection `json:"section"` // 分段内容
  25 + Images []Image `json:"images"` // 图片
  26 + Videos []Video `json:"videos"` // 视频
  27 + Action string `json:"action"` // 操作
  28 + // 新的备份内容相对与旧的文章信息哪些内容发生了变更,可选值[WhoRead] 修改了分发对象, [WhoReview] 修改了评论范围,[Section] 修改了内容
  29 + ChangeField []string `json:"changeField"`
  30 + TargetUser ArticleTarget `json:"targetUser"` // 分发方式 0 分发给所有人 1 分发给指定的人
  31 + Location Location `json:"location"` // 定位坐标
  32 + WhoRead []int64 `json:"whoRead"` // 谁可以看
  33 + WhoReview []int64 `json:"whoReview"` // 评论人
  34 + Tags []int64 `json:"tags"` // 标签
  35 + MatchUrl map[string]string `json:"matchUrl"` // 匹配文章内容中的url文本
30 } 36 }
31 37
32 type ArticleBackupRepository interface { 38 type ArticleBackupRepository interface {
@@ -37,3 +43,98 @@ type ArticleBackupRepository interface { @@ -37,3 +43,98 @@ type ArticleBackupRepository interface {
37 FindOne(ctx context.Context, conn transaction.Conn, id int64) (*ArticleBackup, error) 43 FindOne(ctx context.Context, conn transaction.Conn, id int64) (*ArticleBackup, error)
38 Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*ArticleBackup, error) 44 Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*ArticleBackup, error)
39 } 45 }
  46 +
  47 +// 检查新的备份内容相对与旧的文章信息哪些内容发生了变更
  48 +// 记录ArticleBackup中数据发生变更的的字段名
  49 +func (bk *ArticleBackup) CheckChangeField(oldBackup *ArticleBackup) bool {
  50 + bk.ChangeField = make([]string, 0)
  51 + //比较 WhoRead
  52 + {
  53 + whoReadChanged := false
  54 + sort.Slice(bk.WhoRead, func(i, j int) bool {
  55 + return bk.WhoRead[i] < bk.WhoRead[j]
  56 + })
  57 + sort.Slice(oldBackup.WhoRead, func(i, j int) bool {
  58 + return oldBackup.WhoRead[i] < oldBackup.WhoRead[j]
  59 + })
  60 +
  61 + if len(bk.WhoRead) != len(oldBackup.WhoRead) {
  62 + whoReadChanged = true
  63 + } else {
  64 + for i := range bk.WhoRead {
  65 + if bk.WhoRead[i] != oldBackup.WhoRead[i] {
  66 + whoReadChanged = true
  67 + }
  68 + }
  69 + }
  70 + if whoReadChanged {
  71 + bk.ChangeField = append(bk.ChangeField, "WhoRead")
  72 + }
  73 + }
  74 +
  75 + //比较 whoReview
  76 + {
  77 + whoReviewChanged := false
  78 + sort.Slice(bk.WhoReview, func(i, j int) bool {
  79 + return bk.WhoReview[i] < bk.WhoReview[j]
  80 + })
  81 + sort.Slice(oldBackup.WhoReview, func(i, j int) bool {
  82 + return oldBackup.WhoReview[i] < oldBackup.WhoReview[j]
  83 + })
  84 +
  85 + if len(bk.WhoReview) != len(oldBackup.WhoReview) {
  86 + whoReviewChanged = true
  87 + } else {
  88 + for i := range bk.WhoReview {
  89 + if bk.WhoReview[i] != oldBackup.WhoReview[i] {
  90 + whoReviewChanged = true
  91 + }
  92 + }
  93 + }
  94 + if whoReviewChanged {
  95 + bk.ChangeField = append(bk.ChangeField, "WhoReview")
  96 + }
  97 + }
  98 + //比较段落内容+图片+视频 是否发生变更
  99 + {
  100 + sectionChanged := false
  101 + newSectionData := map[string]string{
  102 + "title": bk.Title,
  103 + }
  104 +
  105 + oldSectionData := map[string]string{
  106 + "title": oldBackup.Title,
  107 + }
  108 +
  109 + for _, val := range bk.Section {
  110 + mkey := fmt.Sprintf("section-%d", val.SortBy)
  111 + newSectionData[mkey] = val.Content
  112 + }
  113 + for _, val := range bk.Images {
  114 + newSectionData[val.Url] = ""
  115 + }
  116 + for _, val := range bk.Videos {
  117 + newSectionData[val.Url] = ""
  118 + }
  119 +
  120 + for _, val := range oldBackup.Section {
  121 + mKey := fmt.Sprintf("section-%d", val.SortBy)
  122 + oldSectionData[mKey] = val.Content
  123 + }
  124 + for _, val := range oldBackup.Images {
  125 + oldSectionData[val.Url] = ""
  126 + }
  127 + for _, val := range oldBackup.Videos {
  128 + oldSectionData[val.Url] = ""
  129 + }
  130 + newSectionJson, _ := json.Marshal(newSectionData)
  131 + oldSectionJson, _ := json.Marshal(oldSectionData)
  132 + if ok := bytes.Equal(newSectionJson, oldSectionJson); !ok {
  133 + sectionChanged = true
  134 + }
  135 + if sectionChanged {
  136 + bk.ChangeField = append(bk.ChangeField, "Section")
  137 + }
  138 + }
  139 + return len(bk.ChangeField) > 0
  140 +}