作者 yangfu

Merge branch 'test'

@@ -65,6 +65,9 @@ service Core { @@ -65,6 +65,9 @@ service Core {
65 @handler MiniArticleBackupSearch 65 @handler MiniArticleBackupSearch
66 post /article_backup/search (MiniArticleBackupSearchRequest) returns (MiniArticleBackupSearchResponse) 66 post /article_backup/search (MiniArticleBackupSearchRequest) returns (MiniArticleBackupSearchResponse)
67 67
  68 + @doc "小程序获取文章的编辑记录"
  69 + @handler MiniGetArticleBackup
  70 + get /article_backup/:id (MiniGetArticleBackupRequest) returns (MiniGetArticleBackupResponse)
68 71
69 @doc "小程序设置文章的定性标签" 72 @doc "小程序设置文章的定性标签"
70 @handler MiniArticleSetTag 73 @handler MiniArticleSetTag
@@ -168,14 +168,40 @@ type ( @@ -168,14 +168,40 @@ 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"`
  179 + Action string `json:"action"`
  180 + Show int `json:"show"`
  181 + }
  182 +)
  183 +
  184 +type (
  185 + MiniGetArticleBackupRequest {
  186 + BackupId int64 `path:"id"`
  187 + CompanyId int64 `path:",optional"` // 服务端自动获取
  188 + }
  189 + MiniGetArticleBackupResponse {
  190 + Id int64 `json:"id"`
  191 + Title string `json:"title"`
  192 + Content string `json:"content"`
  193 + Images []string `json:"images"`
  194 + Videos []Video `json:"videos"`
  195 + ChangeField []string `json:"changeField"`
  196 + CreatedAt int64 `json:"createdAt"`
  197 + Location Location `json:"location"`
  198 + Action string `json:"action"`
  199 + Show int `json:"show"`
177 } 200 }
178 ) 201 )
  202 +
  203 +
  204 +
179 // 标记人员浏览了那个文章 205 // 标记人员浏览了那个文章
180 type ( 206 type (
181 MiniArticleMarkUserReadRequest { 207 MiniArticleMarkUserReadRequest {
@@ -391,6 +417,7 @@ type ( @@ -391,6 +417,7 @@ type (
391 Tags []int64 `json:"tags,optional"` //标签 417 Tags []int64 `json:"tags,optional"` //标签
392 Page int `json:"page"` //页码 418 Page int `json:"page"` //页码
393 Size int `json:"size"` //每页行数 419 Size int `json:"size"` //每页行数
  420 + OrderMode string `json:"orderMode,optional"` //排序方式
394 } 421 }
395 422
396 SystemArticleSearchResponse { 423 SystemArticleSearchResponse {
@@ -417,7 +444,7 @@ type ( @@ -417,7 +444,7 @@ type (
417 SystemArticleUpdateRequest { 444 SystemArticleUpdateRequest {
418 Id int64 `json:"id"` 445 Id int64 `json:"id"`
419 CompanyId int64 `json:"companyId,optional"` 446 CompanyId int64 `json:"companyId,optional"`
420 - Template int `json:"template"` // 使用哪个模板进行编辑 0、无 1、演绎式 2、归纳式 447 + Template int `json:"template,optional"` // 使用哪个模板进行编辑 0、无 1、演绎式 2、归纳式
421 Section []ArticleSection `json:"section"` // 填写的内容 448 Section []ArticleSection `json:"section"` // 填写的内容
422 Title string `json:"title"` // 标题 449 Title string `json:"title"` // 标题
423 Images []string `json:"images"` // 图片 450 Images []string `json:"images"` // 图片
  1 +package article
  2 +
  3 +import (
  4 + "net/http"
  5 +
  6 + "github.com/zeromicro/go-zero/rest/httpx"
  7 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/article"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
  10 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/result"
  11 +)
  12 +
  13 +func MiniGetArticleBackupHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
  14 + return func(w http.ResponseWriter, r *http.Request) {
  15 + var req types.MiniGetArticleBackupRequest
  16 + if err := httpx.Parse(r, &req); err != nil {
  17 + result.HttpResult(r, w, nil, err)
  18 + return
  19 + }
  20 +
  21 + l := article.NewMiniGetArticleBackupLogic(r.Context(), svcCtx)
  22 + resp, err := l.MiniGetArticleBackup(&req)
  23 + result.HttpResult(r, w, resp, err)
  24 + }
  25 +}
@@ -529,6 +529,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { @@ -529,6 +529,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
529 Handler: article.MiniArticleBackupSearchHandler(serverCtx), 529 Handler: article.MiniArticleBackupSearchHandler(serverCtx),
530 }, 530 },
531 { 531 {
  532 + Method: http.MethodGet,
  533 + Path: "/article_backup/:id",
  534 + Handler: article.MiniGetArticleBackupHandler(serverCtx),
  535 + },
  536 + {
532 Method: http.MethodPost, 537 Method: http.MethodPost,
533 Path: "/article/set_tag", 538 Path: "/article/set_tag",
534 Handler: article.MiniArticleSetTagHandler(serverCtx), 539 Handler: article.MiniArticleSetTagHandler(serverCtx),
@@ -51,18 +51,50 @@ func (l *MiniArticleBackupSearchLogic) MiniArticleBackupSearch(req *types.MiniAr @@ -51,18 +51,50 @@ 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 - resp.List[i] = types.MiniArticleBackupItem{ 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 + }
  64 + item := types.MiniArticleBackupItem{
55 Id: backupList[i].Id, 65 Id: backupList[i].Id,
56 - Title: backupList[i].Title,  
57 - Content: content.String(),  
58 - Images: images, 66 + Title: "",
  67 + Content: "",
  68 + Images: []string{},
  69 + Videos: []types.Video{},
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,
  77 + Action: backupList[i].Action,
  78 + Show: int(backupList[i].Show),
65 } 79 }
  80 + //根据修改的内容替换展示内容
  81 + changeFiled := []string{}
  82 + for _, val := range item.ChangeField {
  83 + switch val {
  84 + case "WhoRead":
  85 + changeFiled = append(changeFiled, "修改了分发对象")
  86 + case "WhoReview":
  87 + changeFiled = append(changeFiled, "修改了评论范围")
  88 + case "Section":
  89 + item.Title = backupList[i].Title
  90 + item.Content = content.String()
  91 + item.Images = images
  92 + item.Videos = videos
  93 + }
  94 + }
  95 + item.ChangeField = changeFiled
  96 + resp.List[i] = item
  97 +
66 } 98 }
67 return resp, nil 99 return resp, nil
68 } 100 }
@@ -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,19 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR @@ -185,11 +185,19 @@ 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 + var backupData domain.ArticleBackup
  196 + backupData.MakeBackup(articleAuthor, newArticle, sectionList, "原始版本")
  197 + _, err = l.svcCtx.ArticleBackupRepository.Insert(l.ctx, conn, &backupData)
  198 + if err != nil {
  199 + return xerr.NewErrMsgErr("创建文章失败", err)
  200 + }
193 return nil 201 return nil
194 }, true) 202 }, true)
195 if err != nil { 203 if err != nil {
  1 +package article
  2 +
  3 +import (
  4 + "context"
  5 + "strings"
  6 +
  7 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
  10 +
  11 + "github.com/zeromicro/go-zero/core/logx"
  12 +)
  13 +
  14 +type MiniGetArticleBackupLogic struct {
  15 + logx.Logger
  16 + ctx context.Context
  17 + svcCtx *svc.ServiceContext
  18 +}
  19 +
  20 +func NewMiniGetArticleBackupLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MiniGetArticleBackupLogic {
  21 + return &MiniGetArticleBackupLogic{
  22 + Logger: logx.WithContext(ctx),
  23 + ctx: ctx,
  24 + svcCtx: svcCtx,
  25 + }
  26 +}
  27 +
  28 +func (l *MiniGetArticleBackupLogic) MiniGetArticleBackup(req *types.MiniGetArticleBackupRequest) (resp *types.MiniGetArticleBackupResponse, err error) {
  29 + var conn = l.svcCtx.DefaultDBConn()
  30 +
  31 + backupInfo, err := l.svcCtx.ArticleBackupRepository.FindOne(l.ctx, conn, req.BackupId)
  32 + if err != nil {
  33 + return &types.MiniGetArticleBackupResponse{}, xerr.NewErrMsgErr("获取编辑记录失败", err)
  34 + }
  35 +
  36 + content := strings.Builder{}
  37 + for _, val2 := range backupInfo.Section {
  38 + content.WriteString(val2.Content)
  39 + }
  40 + images := []string{}
  41 + for _, val2 := range backupInfo.Images {
  42 + images = append(images, val2.Url)
  43 + }
  44 +
  45 + videos := []types.Video{}
  46 + for _, val2 := range backupInfo.Videos {
  47 + videos = append(videos, types.Video{
  48 + Url: val2.Url,
  49 + Cover: val2.Cover,
  50 + Width: val2.Width,
  51 + Height: val2.Height,
  52 + })
  53 + }
  54 +
  55 + resp = &types.MiniGetArticleBackupResponse{
  56 + Id: backupInfo.Id,
  57 + Title: backupInfo.Title,
  58 + Content: content.String(),
  59 + Images: images,
  60 + Videos: videos,
  61 + CreatedAt: backupInfo.CreatedAt,
  62 + Location: types.Location{
  63 + Longitude: backupInfo.Location.Longitude,
  64 + Latitude: backupInfo.Location.Latitude,
  65 + Descript: backupInfo.Location.Descript,
  66 + },
  67 + ChangeField: backupInfo.ChangeField,
  68 + Action: backupInfo.Action,
  69 + Show: int(backupInfo.Show),
  70 + }
  71 +
  72 + return
  73 +}
@@ -42,25 +42,8 @@ func (l *MiniGetArticleLogic) MiniGetArticle(req *types.MiniArticleGetRequest) ( @@ -42,25 +42,8 @@ func (l *MiniGetArticleLogic) MiniGetArticle(req *types.MiniArticleGetRequest) (
42 return nil, xerr.NewErrMsg("没有查看权限") 42 return nil, xerr.NewErrMsg("没有查看权限")
43 } 43 }
44 // 检查文章的可查看人 44 // 检查文章的可查看人
45 - if articleInfo.AuthorId != int64(req.UserId) {  
46 - if len(articleInfo.WhoRead) > 0 {  
47 - inWhoRead := false  
48 - for _, val := range articleInfo.WhoRead {  
49 - if req.UserId == int(val) {  
50 - inWhoRead = true  
51 - }  
52 - }  
53 - if !inWhoRead {  
54 - // 文章内容不显示  
55 - // resp = &types.MiniArticleGetResponse{  
56 - // Id: articleInfo.Id,  
57 - // Title: articleInfo.Title,  
58 - // Show: int(domain.ArticleShowDisable),  
59 - // }  
60 - // return resp, nil  
61 - return nil, xerr.NewErrMsg("没有查看权限")  
62 - }  
63 - } 45 + if ok := articleInfo.WhoCanRead(int64(req.UserId)); !ok {
  46 + return nil, xerr.NewErrMsg("没有查看权限")
64 } 47 }
65 if articleInfo.Show == domain.ArticleShowDisable { 48 if articleInfo.Show == domain.ArticleShowDisable {
66 // 文章内容不显示 49 // 文章内容不显示
@@ -110,8 +93,8 @@ func (l *MiniGetArticleLogic) MiniGetArticle(req *types.MiniArticleGetRequest) ( @@ -110,8 +93,8 @@ func (l *MiniGetArticleLogic) MiniGetArticle(req *types.MiniArticleGetRequest) (
110 93
111 follow, _ := l.svcCtx.UserFollowRepository.FindOneUserFollowing(l.ctx, conn, int64(req.UserId), articleInfo.AuthorId) 94 follow, _ := l.svcCtx.UserFollowRepository.FindOneUserFollowing(l.ctx, conn, int64(req.UserId), articleInfo.AuthorId)
112 95
113 - queryOption = domain.NewQueryOptions().WithFindOnly().WithOffsetLimit(1, 1).WithKV("articleId", articleInfo.Id)  
114 - _, backupList, _ := l.svcCtx.ArticleBackupRepository.Find(l.ctx, conn, queryOption) 96 + queryOption = domain.NewQueryOptions().WithCountOnly().WithOffsetLimit(1, 1).WithKV("articleId", articleInfo.Id)
  97 + backupCount, _, _ := l.svcCtx.ArticleBackupRepository.Find(l.ctx, conn, queryOption)
115 98
116 sortBy := domain.SortArticleSection(sectionList) 99 sortBy := domain.SortArticleSection(sectionList)
117 sort.Sort(sortBy) 100 sort.Sort(sortBy)
@@ -157,7 +140,7 @@ func (l *MiniGetArticleLogic) MiniGetArticle(req *types.MiniArticleGetRequest) ( @@ -157,7 +140,7 @@ func (l *MiniGetArticleLogic) MiniGetArticle(req *types.MiniArticleGetRequest) (
157 MatchUrl: map[string]string{}, 140 MatchUrl: map[string]string{},
158 Videos: []types.Video{}, 141 Videos: []types.Video{},
159 } 142 }
160 - if len(backupList) > 0 { 143 + if backupCount > 1 {
161 resp.Edit = 1 144 resp.Edit = 1
162 } 145 }
163 if author != nil { 146 if author != nil {
@@ -39,6 +39,9 @@ func (l *MiniShowHomePageLogic) MiniShowHomePage(req *types.MiniHomePageRequest) @@ -39,6 +39,9 @@ func (l *MiniShowHomePageLogic) MiniShowHomePage(req *types.MiniHomePageRequest)
39 if err != nil { 39 if err != nil {
40 return nil, xerr.NewErrMsgErr("获取文章汇总数量失败", err) 40 return nil, xerr.NewErrMsgErr("获取文章汇总数量失败", err)
41 } 41 }
  42 +
  43 + //TODO 拆分统计
  44 +
42 countDataMap := map[int64]*domain.CountArticleTagRead{} 45 countDataMap := map[int64]*domain.CountArticleTagRead{}
43 for _, val := range countData { 46 for _, val := range countData {
44 countDataMap[val.TagId] = val 47 countDataMap[val.TagId] = val
@@ -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,24 +50,26 @@ func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticl @@ -50,24 +50,26 @@ 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 + var newBackUp domain.ArticleBackup
  56 + newBackUp.MakeBackup(domain.UserSimple{
55 Id: userToken.UserId, 57 Id: userToken.UserId,
56 Name: userMe.User.NickName, 58 Name: userMe.User.NickName,
57 Avatar: userMe.User.Avatar, 59 Avatar: userMe.User.Avatar,
58 CompanyId: userToken.CompanyId, 60 CompanyId: userToken.CompanyId,
59 Company: userMe.CurrentCompany.Name, 61 Company: userMe.CurrentCompany.Name,
60 - }, sectionList)  
61 - newBackUp.Action = "恢复" 62 + }, article, sectionList, "恢复")
  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,13 +108,14 @@ func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticl @@ -106,13 +108,14 @@ 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 }
113 } 116 }
114 117
115 - _, err = l.svcCtx.ArticleBackupRepository.Insert(ctx, c, newBackUp) 118 + _, err = l.svcCtx.ArticleBackupRepository.Insert(ctx, c, &newBackUp)
116 if err != nil { 119 if err != nil {
117 return xerr.NewErrMsgErr("恢复文章版本失败", err) 120 return xerr.NewErrMsgErr("恢复文章版本失败", err)
118 } 121 }
@@ -2,6 +2,7 @@ package article @@ -2,6 +2,7 @@ package article
2 2
3 import ( 3 import (
4 "context" 4 "context"
  5 +
5 "github.com/samber/lo" 6 "github.com/samber/lo"
6 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc" 7 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
7 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types" 8 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
@@ -33,7 +34,9 @@ func (l *SystemSearchArticleLogic) SystemSearchArticle(req *types.SystemArticleS @@ -33,7 +34,9 @@ func (l *SystemSearchArticleLogic) SystemSearchArticle(req *types.SystemArticleS
33 WithKV("authorId", req.Author). 34 WithKV("authorId", req.Author).
34 WithKV("tags", req.Tags). 35 WithKV("tags", req.Tags).
35 WithKV("beginCreatedAt", req.BeginTime). 36 WithKV("beginCreatedAt", req.BeginTime).
36 - WithKV("endCreatedAt", req.EndTime) 37 + WithKV("endCreatedAt", req.EndTime).
  38 + WithKV("orderMode", req.OrderMode)
  39 +
37 total, articles, err := l.svcCtx.ArticleRepository.Find(l.ctx, conn, req.CompanyId, queryOptions) 40 total, articles, err := l.svcCtx.ArticleRepository.Find(l.ctx, conn, req.CompanyId, queryOptions)
38 if err != nil { 41 if err != nil {
39 return nil, xerr.NewErrMsgErr("搜索帖子异常", err) 42 return nil, xerr.NewErrMsgErr("搜索帖子异常", err)
@@ -57,24 +57,26 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU @@ -57,24 +57,26 @@ 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 + var oldBackup domain.ArticleBackup
  79 + oldBackup.MakeBackup(operator, article, sectionList, "编辑")
78 80
79 // 获取图片的尺寸大小 81 // 获取图片的尺寸大小
80 images, err := l.getImages(req) 82 images, err := l.getImages(req)
@@ -126,6 +128,7 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU @@ -126,6 +128,7 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU
126 } 128 }
127 //文章内容 129 //文章内容
128 updateSectionIds := []int64{} 130 updateSectionIds := []int64{}
  131 + updateSection := []*domain.ArticleSection{}
129 for _, item := range articleSections { 132 for _, item := range articleSections {
130 if item.Id > 0 { 133 if item.Id > 0 {
131 section, err := l.svcCtx.ArticleSectionRepository.FindOne(ctx, c, item.Id) 134 section, err := l.svcCtx.ArticleSectionRepository.FindOne(ctx, c, item.Id)
@@ -142,22 +145,29 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU @@ -142,22 +145,29 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU
142 return xerr.NewErrMsgErr("保存文章段落内容失败", err) 145 return xerr.NewErrMsgErr("保存文章段落内容失败", err)
143 } 146 }
144 } else { 147 } else {
145 - _, err = l.svcCtx.ArticleSectionRepository.Insert(ctx, c, &item) 148 + _, err = l.svcCtx.ArticleSectionRepository.Insert(ctx, c, item)
146 if err != nil { 149 if err != nil {
147 return xerr.NewErrMsgErr("保存文章段落内容失败", err) 150 return xerr.NewErrMsgErr("保存文章段落内容失败", err)
148 } 151 }
149 } 152 }
150 updateSectionIds = append(updateSectionIds, item.Id) 153 updateSectionIds = append(updateSectionIds, item.Id)
  154 + updateSection = append(updateSection, item)
151 } 155 }
152 if len(updateSectionIds) > 0 { 156 if len(updateSectionIds) > 0 {
153 - err = l.svcCtx.ArticleSectionRepository.DeleteBy(ctx, c, domain.NewQueryOptions().WithKV("articleId", article.Id).WithKV("notIds", updateSectionIds)) 157 + queryOption := domain.NewQueryOptions().WithKV("articleId", article.Id).WithKV("notIds", updateSectionIds)
  158 + err = l.svcCtx.ArticleSectionRepository.DeleteBy(ctx, c, queryOption)
154 if err != nil { 159 if err != nil {
155 return xerr.NewErrMsgErr("保存文章内容失败", err) 160 return xerr.NewErrMsgErr("保存文章内容失败", err)
156 } 161 }
157 } 162 }
158 - _, err = l.svcCtx.ArticleBackupRepository.Insert(ctx, c, backup)  
159 - if err != nil {  
160 - return xerr.NewErrMsgErr("保存文章内容失败", err) 163 + var backup domain.ArticleBackup
  164 + backup.MakeBackup(operator, article, updateSection, "编辑")
  165 +
  166 + if ok := backup.CheckChangeField(&oldBackup); ok {
  167 + _, err = l.svcCtx.ArticleBackupRepository.Insert(ctx, c, &backup)
  168 + if err != nil {
  169 + return xerr.NewErrMsgErr("保存文章内容失败", err)
  170 + }
161 } 171 }
162 //文章定性 172 //文章定性
163 err = l.setTags(c, article) 173 err = l.setTags(c, article)
@@ -307,8 +317,8 @@ func (l *SystemUpdateArticleLogic) getVideos(req *types.SystemArticleUpdateReque @@ -307,8 +317,8 @@ func (l *SystemUpdateArticleLogic) getVideos(req *types.SystemArticleUpdateReque
307 return videos, nil 317 return videos, nil
308 } 318 }
309 319
310 -func (l *SystemUpdateArticleLogic) getSections(req *types.SystemArticleUpdateRequest, article *domain.Article) []domain.ArticleSection {  
311 - articleSections := make([]domain.ArticleSection, 0) 320 +func (l *SystemUpdateArticleLogic) getSections(req *types.SystemArticleUpdateRequest, article *domain.Article) []*domain.ArticleSection {
  321 + articleSections := make([]*domain.ArticleSection, 0)
312 sortBy := 1 322 sortBy := 1
313 lo.ForEach(req.Section, func(item types.ArticleSection, index int) { 323 lo.ForEach(req.Section, func(item types.ArticleSection, index int) {
314 strList := strings.Split(item.Content, "\n") 324 strList := strings.Split(item.Content, "\n")
@@ -326,7 +336,7 @@ func (l *SystemUpdateArticleLogic) getSections(req *types.SystemArticleUpdateReq @@ -326,7 +336,7 @@ func (l *SystemUpdateArticleLogic) getSections(req *types.SystemArticleUpdateReq
326 if key == 0 { 336 if key == 0 {
327 section.Id = item.Id 337 section.Id = item.Id
328 } 338 }
329 - articleSections = append(articleSections, section) 339 + articleSections = append(articleSections, &section)
330 sortBy++ 340 sortBy++
331 } 341 }
332 }) 342 })
@@ -52,11 +52,8 @@ func (l *MiniCreateArticleCommentLogic) MiniCreateArticleComment(req *types.Mini @@ -52,11 +52,8 @@ func (l *MiniCreateArticleCommentLogic) MiniCreateArticleComment(req *types.Mini
52 return nil, xerr.NewErrMsg("没有评论权限") 52 return nil, xerr.NewErrMsg("没有评论权限")
53 } 53 }
54 //查看评论权限, 54 //查看评论权限,
55 - if len(articleInfo.WhoReview) > 0 {  
56 - ok := lo.IndexOf(articleInfo.WhoReview, req.FromUserId)  
57 - if ok < 0 {  
58 - return nil, xerr.NewErrMsg("没有评论权限")  
59 - } 55 + if ok := articleInfo.WhoCanReview(req.FromUserId); !ok {
  56 + return nil, xerr.NewErrMsg("没有评论权限")
60 } 57 }
61 // 对段落进行评论 58 // 对段落进行评论
62 var selctionInfo *domain.ArticleSection 59 var selctionInfo *domain.ArticleSection
@@ -184,15 +181,7 @@ func (l *MiniCreateArticleCommentLogic) MiniCreateArticleComment(req *types.Mini @@ -184,15 +181,7 @@ func (l *MiniCreateArticleCommentLogic) MiniCreateArticleComment(req *types.Mini
184 return err 181 return err
185 } 182 }
186 } 183 }
187 - //增加评论回复计数  
188 - // if pComment != nil {  
189 - // err = l.svcCtx.ArticleCommentRepository.IncreaseCountReply(l.ctx, c, 1, pComment.Id)  
190 - // if err != nil {  
191 - // return err  
192 - // }  
193 - // }  
194 // 增加最顶层的评论回复计数 184 // 增加最顶层的评论回复计数
195 - // if newComment.TopId != 0 && newComment.Pid != newComment.TopId {  
196 if newComment.TopId != 0 { 185 if newComment.TopId != 0 {
197 err = l.svcCtx.ArticleCommentRepository.IncreaseCountReply(l.ctx, c, 1, newComment.TopId) 186 err = l.svcCtx.ArticleCommentRepository.IncreaseCountReply(l.ctx, c, 1, newComment.TopId)
198 if err != nil { 187 if err != nil {
@@ -52,13 +52,6 @@ func (l *MiniDeleteArticleCommentLogic) MiniDeleteArticleComment(req *types.Mini @@ -52,13 +52,6 @@ func (l *MiniDeleteArticleCommentLogic) MiniDeleteArticleComment(req *types.Mini
52 if err != nil { 52 if err != nil {
53 return err 53 return err
54 } 54 }
55 - // 减少上级评论的回复数量  
56 - // if commentInfo.Pid != 0 {  
57 - // err = l.svcCtx.ArticleCommentRepository.IncreaseCountReply(l.ctx, c, -1, commentInfo.Pid)  
58 - // if err != nil {  
59 - // return err  
60 - // }  
61 - // }  
62 // 减少最顶层的评论回复计数 55 // 减少最顶层的评论回复计数
63 // if commentInfo.TopId != 0 && commentInfo.Pid != commentInfo.TopId { 56 // if commentInfo.TopId != 0 && commentInfo.Pid != commentInfo.TopId {
64 if commentInfo.TopId != 0 { 57 if commentInfo.TopId != 0 {
@@ -80,15 +80,6 @@ func (l *SystemEditAticleCommentShowLogic) disableShow(commentId int64, companyI @@ -80,15 +80,6 @@ func (l *SystemEditAticleCommentShowLogic) disableShow(commentId int64, companyI
80 if err != nil { 80 if err != nil {
81 return err 81 return err
82 } 82 }
83 - // 减少上级评论的回复数量  
84 - // if commentInfo.Pid != 0 {  
85 - // err = l.svcCtx.ArticleCommentRepository.IncreaseCountReply(l.ctx, c, -1, commentInfo.Pid)  
86 - // if err != nil {  
87 - // return err  
88 - // }  
89 - // }  
90 - // 减少最顶层的评论回复计数  
91 - // if commentInfo.TopId != 0 && commentInfo.Pid != commentInfo.TopId {  
92 if commentInfo.TopId != 0 { 83 if commentInfo.TopId != 0 {
93 err = l.svcCtx.ArticleCommentRepository.IncreaseCountReply(l.ctx, c, -1, commentInfo.TopId) 84 err = l.svcCtx.ArticleCommentRepository.IncreaseCountReply(l.ctx, c, -1, commentInfo.TopId)
94 if err != nil { 85 if err != nil {
@@ -157,15 +148,8 @@ func (l *SystemEditAticleCommentShowLogic) enableShow(commentId int64, companyId @@ -157,15 +148,8 @@ func (l *SystemEditAticleCommentShowLogic) enableShow(commentId int64, companyId
157 if err != nil { 148 if err != nil {
158 return err 149 return err
159 } 150 }
160 - // 增加上级评论的回复数量  
161 - // if commetInfo.Pid != 0 {  
162 - // err = l.svcCtx.ArticleCommentRepository.IncreaseCountReply(l.ctx, c, 1, commetInfo.Pid)  
163 - // if err != nil {  
164 - // return err  
165 - // }  
166 - // } 151 +
167 // 增加最顶层的评论回复计数 152 // 增加最顶层的评论回复计数
168 - // if commetInfo.TopId != 0 && commetInfo.Pid != commetInfo.TopId {  
169 if commetInfo.TopId != 0 { 153 if commetInfo.TopId != 0 {
170 err = l.svcCtx.ArticleCommentRepository.IncreaseCountReply(l.ctx, c, 1, commetInfo.TopId) 154 err = l.svcCtx.ArticleCommentRepository.IncreaseCountReply(l.ctx, c, 1, commetInfo.TopId)
171 if err != nil { 155 if err != nil {
@@ -489,10 +489,10 @@ type MiniHomepageUserNewsRequest struct { @@ -489,10 +489,10 @@ type MiniHomepageUserNewsRequest struct {
489 LastArticleId int64 `json:"lastArticleId,optional"` // 最后文章ID 489 LastArticleId int64 `json:"lastArticleId,optional"` // 最后文章ID
490 Size int `json:"size"` // 数量 490 Size int `json:"size"` // 数量
491 OrderByKey string `json:"orderByKey,options=HotScore|All|Time,optional,default=desc"` // 按规则排序 (热度:HotScore All:时间排序 Time:时间排序) 491 OrderByKey string `json:"orderByKey,options=HotScore|All|Time,optional,default=desc"` // 按规则排序 (热度:HotScore All:时间排序 Time:时间排序)
492 - OrderByValue string `json:"orderByValue,options=asc||desc,optional"`  
493 - Keywords string `json:"keywords,optional"` // 关键字  
494 - BeginTime int64 `json:"beginTime,optional"` // 开始时间  
495 - EndTime int64 `json:"endTime,optional"` // 结束时间 492 + OrderByValue string `json:"orderByValue,options=asc||desc,optional"` // 排序值 升序 asc 降序 desc
  493 + Keywords string `json:"keywords,optional"` // 关键字
  494 + BeginTime int64 `json:"beginTime,optional"` // 开始时间
  495 + EndTime int64 `json:"endTime,optional"` // 结束时间
496 } 496 }
497 497
498 type MiniHomepageUserNewsResposne struct { 498 type MiniHomepageUserNewsResposne struct {
@@ -1029,12 +1029,34 @@ type MiniArticleBackupSearchResponse struct { @@ -1029,12 +1029,34 @@ type MiniArticleBackupSearchResponse struct {
1029 } 1029 }
1030 1030
1031 type MiniArticleBackupItem struct { 1031 type MiniArticleBackupItem struct {
1032 - Id int64 `json:"id"`  
1033 - Title string `json:"title"`  
1034 - Content string `json:"content"`  
1035 - Images []string `json:"images"`  
1036 - CreatedAt int64 `json:"createdAt"`  
1037 - Location Location `json:"location"` 1032 + Id int64 `json:"id"`
  1033 + Title string `json:"title"`
  1034 + Content string `json:"content"`
  1035 + Images []string `json:"images"`
  1036 + Videos []Video `json:"videos"`
  1037 + ChangeField []string `json:"changeField"`
  1038 + CreatedAt int64 `json:"createdAt"`
  1039 + Location Location `json:"location"`
  1040 + Action string `json:"action"`
  1041 + Show int `json:"show"`
  1042 +}
  1043 +
  1044 +type MiniGetArticleBackupRequest struct {
  1045 + BackupId int64 `path:"id"`
  1046 + CompanyId int64 `path:",optional"` // 服务端自动获取
  1047 +}
  1048 +
  1049 +type MiniGetArticleBackupResponse struct {
  1050 + Id int64 `json:"id"`
  1051 + Title string `json:"title"`
  1052 + Content string `json:"content"`
  1053 + Images []string `json:"images"`
  1054 + Videos []Video `json:"videos"`
  1055 + ChangeField []string `json:"changeField"`
  1056 + CreatedAt int64 `json:"createdAt"`
  1057 + Location Location `json:"location"`
  1058 + Action string `json:"action"`
  1059 + Show int `json:"show"`
1038 } 1060 }
1039 1061
1040 type MiniArticleMarkUserReadRequest struct { 1062 type MiniArticleMarkUserReadRequest struct {
@@ -1226,6 +1248,7 @@ type SystemArticleSearchRequest struct { @@ -1226,6 +1248,7 @@ type SystemArticleSearchRequest struct {
1226 Tags []int64 `json:"tags,optional"` //标签 1248 Tags []int64 `json:"tags,optional"` //标签
1227 Page int `json:"page"` //页码 1249 Page int `json:"page"` //页码
1228 Size int `json:"size"` //每页行数 1250 Size int `json:"size"` //每页行数
  1251 + OrderMode string `json:"orderMode,optional"` //排序方式
1229 } 1252 }
1230 1253
1231 type SystemArticleSearchResponse struct { 1254 type SystemArticleSearchResponse struct {
@@ -1250,7 +1273,7 @@ type SystemArticleSearch struct { @@ -1250,7 +1273,7 @@ type SystemArticleSearch struct {
1250 type SystemArticleUpdateRequest struct { 1273 type SystemArticleUpdateRequest struct {
1251 Id int64 `json:"id"` 1274 Id int64 `json:"id"`
1252 CompanyId int64 `json:"companyId,optional"` 1275 CompanyId int64 `json:"companyId,optional"`
1253 - Template int `json:"template"` // 使用哪个模板进行编辑 0、无 1、演绎式 2、归纳式 1276 + Template int `json:"template,optional"` // 使用哪个模板进行编辑 0、无 1、演绎式 2、归纳式
1254 Section []ArticleSection `json:"section"` // 填写的内容 1277 Section []ArticleSection `json:"section"` // 填写的内容
1255 Title string `json:"title"` // 标题 1278 Title string `json:"title"` // 标题
1256 Images []string `json:"images"` // 图片 1279 Images []string `json:"images"` // 图片
@@ -10,26 +10,28 @@ import ( @@ -10,26 +10,28 @@ 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文本
  34 + Show int
33 } 35 }
34 36
35 func (m *ArticleBackup) TableName() string { 37 func (m *ArticleBackup) TableName() string {
@@ -157,25 +157,27 @@ func (repository *ArticleBackupRepository) Find(ctx context.Context, conn transa @@ -157,25 +157,27 @@ 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,
  180 + Show: domain.ArticleShow(from.Show),
179 } 181 }
180 // err := copier.Copy(to, from) 182 // err := copier.Copy(to, from)
181 return to, nil 183 return to, nil
@@ -183,26 +185,28 @@ func (repository *ArticleBackupRepository) ModelToDomainModel(from *models.Artic @@ -183,26 +185,28 @@ func (repository *ArticleBackupRepository) ModelToDomainModel(from *models.Artic
183 185
184 func (repository *ArticleBackupRepository) DomainModelToModel(from *domain.ArticleBackup) (*models.ArticleBackup, error) { 186 func (repository *ArticleBackupRepository) DomainModelToModel(from *domain.ArticleBackup) (*models.ArticleBackup, error) {
185 to := &models.ArticleBackup{ 187 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, 188 + Id: from.Id,
  189 + CompanyId: from.CompanyId,
  190 + CreatedAt: from.CreatedAt,
  191 + UpdatedAt: from.CreatedAt,
  192 + DeletedAt: from.DeletedAt,
  193 + IsDel: 0,
  194 + Version: from.Version,
  195 + Operator: from.Operator,
  196 + ArticleId: from.ArticleId,
  197 + Title: from.Title,
  198 + Section: from.Section,
  199 + Images: from.Images,
  200 + Action: from.Action,
  201 + WhoRead: from.WhoRead,
  202 + WhoReview: from.WhoReview,
  203 + Tags: from.Tags,
  204 + Location: from.Location,
  205 + TargetUser: int(from.TargetUser),
  206 + MatchUrl: from.MatchUrl,
  207 + Videos: from.Videos,
  208 + ChangeField: from.ChangeField,
  209 + Show: int(from.Show),
206 } 210 }
207 // err := copier.Copy(to, from) 211 // err := copier.Copy(to, from)
208 return to, nil 212 return to, nil
@@ -121,7 +121,22 @@ func (repository *ArticleRepository) Find(ctx context.Context, conn transaction. @@ -121,7 +121,22 @@ func (repository *ArticleRepository) Find(ctx context.Context, conn transaction.
121 total int64 121 total int64
122 ) 122 )
123 queryFunc := func() (interface{}, error) { 123 queryFunc := func() (interface{}, error) {
124 - tx = tx.Model(&ms).Order("id desc").Where("company_id=?", companyId) 124 + tx = tx.Model(&ms).Where("company_id=?", companyId)
  125 + if v, ok := queryOptions["orderMode"]; ok {
  126 + mode := v.(string)
  127 + switch mode {
  128 + case "countComment ascending":
  129 + tx = tx.Order("count_comment asc")
  130 + case "countComment descending":
  131 + tx = tx.Order("count_comment desc")
  132 + case "countLove ascending":
  133 + tx = tx.Order("count_love asc")
  134 + case "countLove descending":
  135 + tx = tx.Order("count_love desc")
  136 + default:
  137 + tx = tx.Order("id desc")
  138 + }
  139 + }
125 if v, ok := queryOptions["ids"]; ok { 140 if v, ok := queryOptions["ids"]; ok {
126 tx = tx.Where("id in (?)", v) 141 tx = tx.Where("id in (?)", v)
127 } 142 }
@@ -95,42 +95,7 @@ func (a ArticleShow) Named() string { @@ -95,42 +95,7 @@ func (a ArticleShow) Named() string {
95 return "" 95 return ""
96 } 96 }
97 97
98 -// 设置文章的备份数据  
99 -func (m *Article) MakeBackup(operator UserSimple, section []*ArticleSection) *ArticleBackup {  
100 - sectionBackup := make([]ArticleSection, len(section))  
101 - for i := range section {  
102 - sectionBackup[i] = *section[i]  
103 - }  
104 - b := ArticleBackup{  
105 - Id: 0,  
106 - CompanyId: m.CompanyId,  
107 - CreatedAt: 0,  
108 - UpdatedAt: 0,  
109 - DeletedAt: 0,  
110 - Version: m.Version,  
111 - Operator: operator,  
112 - ArticleId: m.Id,  
113 - Title: m.Title,  
114 - Section: sectionBackup,  
115 - Images: make([]Image, len(m.Images)),  
116 - Videos: make([]Video, len(m.Videos)),  
117 - Action: "",  
118 - TargetUser: m.TargetUser,  
119 - WhoRead: m.WhoRead,  
120 - WhoReview: m.WhoReview,  
121 - Tags: m.Tags,  
122 - MatchUrl: map[string]string{},  
123 - Location: m.Location,  
124 - }  
125 - copy(b.Videos, m.Videos)  
126 - copy(b.Images, m.Images)  
127 - for k, v := range m.MatchUrl {  
128 - b.MatchUrl[k] = v  
129 - }  
130 - return &b  
131 -}  
132 -  
133 -func (m *Article) SetSummary(sectionList []ArticleSection) { 98 +func (m *Article) SetSummary(sectionList []*ArticleSection) {
134 if len(sectionList) == 0 { 99 if len(sectionList) == 0 {
135 return 100 return
136 } 101 }
@@ -156,3 +121,33 @@ func (m *Article) SetSummary(sectionList []ArticleSection) { @@ -156,3 +121,33 @@ func (m *Article) SetSummary(sectionList []ArticleSection) {
156 } 121 }
157 m.Summary = content[0:stringIndex] 122 m.Summary = content[0:stringIndex]
158 } 123 }
  124 +
  125 +func (m *Article) WhoCanRead(userId int64) bool {
  126 + if m.AuthorId == userId {
  127 + return true
  128 + }
  129 + if len(m.WhoRead) == 0 {
  130 + return true
  131 + }
  132 + for _, val := range m.WhoRead {
  133 + if userId == val {
  134 + return true
  135 + }
  136 + }
  137 + return false
  138 +}
  139 +
  140 +func (m *Article) WhoCanReview(userId int64) bool {
  141 + if m.AuthorId == userId {
  142 + return true
  143 + }
  144 + if len(m.WhoReview) == 0 {
  145 + return true
  146 + }
  147 + for _, val := range m.WhoReview {
  148 + if userId == val {
  149 + return true
  150 + }
  151 + }
  152 + return false
  153 +}
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文本
  36 + Show ArticleShow `json:"show"` // 评论的展示状态(1显示,2不显示、)
30 } 37 }
31 38
32 type ArticleBackupRepository interface { 39 type ArticleBackupRepository interface {
@@ -37,3 +44,137 @@ type ArticleBackupRepository interface { @@ -37,3 +44,137 @@ type ArticleBackupRepository interface {
37 FindOne(ctx context.Context, conn transaction.Conn, id int64) (*ArticleBackup, error) 44 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) 45 Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*ArticleBackup, error)
39 } 46 }
  47 +
  48 +// 检查新的备份内容相对与旧的文章信息哪些内容发生了变更
  49 +// 记录ArticleBackup中数据发生变更的的字段名
  50 +func (bk *ArticleBackup) CheckChangeField(oldBackup *ArticleBackup) bool {
  51 + bk.ChangeField = make([]string, 0)
  52 + //比较 WhoRead
  53 + {
  54 + whoReadChanged := false
  55 + sort.Slice(bk.WhoRead, func(i, j int) bool {
  56 + return bk.WhoRead[i] < bk.WhoRead[j]
  57 + })
  58 + sort.Slice(oldBackup.WhoRead, func(i, j int) bool {
  59 + return oldBackup.WhoRead[i] < oldBackup.WhoRead[j]
  60 + })
  61 +
  62 + if len(bk.WhoRead) != len(oldBackup.WhoRead) {
  63 + whoReadChanged = true
  64 + } else {
  65 + for i := range bk.WhoRead {
  66 + if bk.WhoRead[i] != oldBackup.WhoRead[i] {
  67 + whoReadChanged = true
  68 + }
  69 + }
  70 + }
  71 + if whoReadChanged {
  72 + bk.ChangeField = append(bk.ChangeField, "WhoRead")
  73 + }
  74 + }
  75 +
  76 + //比较 whoReview
  77 + {
  78 + whoReviewChanged := false
  79 + sort.Slice(bk.WhoReview, func(i, j int) bool {
  80 + return bk.WhoReview[i] < bk.WhoReview[j]
  81 + })
  82 + sort.Slice(oldBackup.WhoReview, func(i, j int) bool {
  83 + return oldBackup.WhoReview[i] < oldBackup.WhoReview[j]
  84 + })
  85 +
  86 + if len(bk.WhoReview) != len(oldBackup.WhoReview) {
  87 + whoReviewChanged = true
  88 + } else {
  89 + for i := range bk.WhoReview {
  90 + if bk.WhoReview[i] != oldBackup.WhoReview[i] {
  91 + whoReviewChanged = true
  92 + }
  93 + }
  94 + }
  95 + if whoReviewChanged {
  96 + bk.ChangeField = append(bk.ChangeField, "WhoReview")
  97 + }
  98 + }
  99 + //比较段落内容+图片+视频 是否发生变更
  100 + {
  101 + sectionChanged := false
  102 + newSectionData := map[string]string{
  103 + "title": bk.Title,
  104 + }
  105 +
  106 + oldSectionData := map[string]string{
  107 + "title": oldBackup.Title,
  108 + }
  109 +
  110 + for _, val := range bk.Section {
  111 + mkey := fmt.Sprintf("section-%d", val.SortBy)
  112 + newSectionData[mkey] = val.Content
  113 + }
  114 + for _, val := range bk.Images {
  115 + newSectionData[val.Url] = ""
  116 + }
  117 + for _, val := range bk.Videos {
  118 + newSectionData[val.Url] = ""
  119 + }
  120 +
  121 + for _, val := range oldBackup.Section {
  122 + mKey := fmt.Sprintf("section-%d", val.SortBy)
  123 + oldSectionData[mKey] = val.Content
  124 + }
  125 + for _, val := range oldBackup.Images {
  126 + oldSectionData[val.Url] = ""
  127 + }
  128 + for _, val := range oldBackup.Videos {
  129 + oldSectionData[val.Url] = ""
  130 + }
  131 + newSectionJson, _ := json.Marshal(newSectionData)
  132 + oldSectionJson, _ := json.Marshal(oldSectionData)
  133 + if ok := bytes.Equal(newSectionJson, oldSectionJson); !ok {
  134 + sectionChanged = true
  135 + }
  136 + if sectionChanged {
  137 + bk.ChangeField = append(bk.ChangeField, "Section")
  138 + }
  139 + }
  140 + return len(bk.ChangeField) > 0
  141 +}
  142 +
  143 +// 创建备份信息
  144 +func (bk *ArticleBackup) MakeBackup(operator UserSimple, article *Article, section []*ArticleSection, action string) {
  145 + sectionBackup := make([]ArticleSection, len(section))
  146 + for i := range section {
  147 + sectionBackup[i] = *section[i]
  148 + }
  149 + b := ArticleBackup{
  150 + Id: 0,
  151 + CompanyId: article.CompanyId,
  152 + CreatedAt: 0,
  153 + UpdatedAt: 0,
  154 + DeletedAt: 0,
  155 + Version: article.Version,
  156 + Operator: operator,
  157 + ArticleId: article.Id,
  158 + Title: article.Title,
  159 + Section: sectionBackup,
  160 + Images: make([]Image, len(article.Images)),
  161 + Videos: make([]Video, len(article.Videos)),
  162 + Action: action,
  163 + TargetUser: article.TargetUser,
  164 + WhoRead: article.WhoRead,
  165 + WhoReview: article.WhoReview,
  166 + Tags: article.Tags,
  167 + MatchUrl: map[string]string{},
  168 + Show: article.Show,
  169 + Location: article.Location,
  170 + }
  171 + if action == "原始版本" {
  172 + b.ChangeField = append(b.ChangeField, "Section")
  173 + }
  174 + copy(b.Videos, article.Videos)
  175 + copy(b.Images, article.Images)
  176 + for k, v := range article.MatchUrl {
  177 + b.MatchUrl[k] = v
  178 + }
  179 + *bk = b
  180 +}
@@ -3,14 +3,15 @@ package database @@ -3,14 +3,15 @@ package database
3 import ( 3 import (
4 "context" 4 "context"
5 "fmt" 5 "fmt"
  6 + "log"
  7 + "os"
  8 + "time"
  9 +
6 "github.com/zeromicro/go-zero/core/logx" 10 "github.com/zeromicro/go-zero/core/logx"
7 "gorm.io/driver/mysql" 11 "gorm.io/driver/mysql"
8 "gorm.io/driver/postgres" 12 "gorm.io/driver/postgres"
9 "gorm.io/gorm" 13 "gorm.io/gorm"
10 "gorm.io/gorm/logger" 14 "gorm.io/gorm/logger"
11 - "log"  
12 - "os"  
13 - "time"  
14 ) 15 )
15 16
16 func OpenGormDB(source string) *gorm.DB { 17 func OpenGormDB(source string) *gorm.DB {
@@ -44,6 +45,7 @@ func OpenGormPGDB(source string, logMode string) *gorm.DB { @@ -44,6 +45,7 @@ func OpenGormPGDB(source string, logMode string) *gorm.DB {
44 if err != nil { 45 if err != nil {
45 panic(err) 46 panic(err)
46 } 47 }
  48 +
47 return db 49 return db
48 } 50 }
49 51