作者 yangfu
... ... @@ -65,6 +65,9 @@ service Core {
@handler MiniArticleBackupSearch
post /article_backup/search (MiniArticleBackupSearchRequest) returns (MiniArticleBackupSearchResponse)
@doc "小程序获取文章的编辑记录"
@handler MiniGetArticleBackup
get /article_backup/:id (MiniGetArticleBackupRequest) returns (MiniGetArticleBackupResponse)
@doc "小程序设置文章的定性标签"
@handler MiniArticleSetTag
... ...
... ... @@ -168,14 +168,40 @@ type (
List []MiniArticleBackupItem `json:"list"`
}
MiniArticleBackupItem {
Id int64 `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
Images []string `json:"images"`
CreatedAt int64 `json:"createdAt"`
Location Location `json:"location"`
Id int64 `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
Images []string `json:"images"`
Videos []Video `json:"videos"`
ChangeField []string `json:"changeField"`
CreatedAt int64 `json:"createdAt"`
Location Location `json:"location"`
Action string `json:"action"`
Show int `json:"show"`
}
)
type (
MiniGetArticleBackupRequest {
BackupId int64 `path:"id"`
CompanyId int64 `path:",optional"` // 服务端自动获取
}
MiniGetArticleBackupResponse {
Id int64 `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
Images []string `json:"images"`
Videos []Video `json:"videos"`
ChangeField []string `json:"changeField"`
CreatedAt int64 `json:"createdAt"`
Location Location `json:"location"`
Action string `json:"action"`
Show int `json:"show"`
}
)
// 标记人员浏览了那个文章
type (
MiniArticleMarkUserReadRequest {
... ... @@ -391,6 +417,7 @@ type (
Tags []int64 `json:"tags,optional"` //标签
Page int `json:"page"` //页码
Size int `json:"size"` //每页行数
OrderMode string `json:"orderMode,optional"` //排序方式
}
SystemArticleSearchResponse {
... ... @@ -417,7 +444,7 @@ type (
SystemArticleUpdateRequest {
Id int64 `json:"id"`
CompanyId int64 `json:"companyId,optional"`
Template int `json:"template"` // 使用哪个模板进行编辑 0、无 1、演绎式 2、归纳式
Template int `json:"template,optional"` // 使用哪个模板进行编辑 0、无 1、演绎式 2、归纳式
Section []ArticleSection `json:"section"` // 填写的内容
Title string `json:"title"` // 标题
Images []string `json:"images"` // 图片
... ...
package article
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/article"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/result"
)
func MiniGetArticleBackupHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.MiniGetArticleBackupRequest
if err := httpx.Parse(r, &req); err != nil {
result.HttpResult(r, w, nil, err)
return
}
l := article.NewMiniGetArticleBackupLogic(r.Context(), svcCtx)
resp, err := l.MiniGetArticleBackup(&req)
result.HttpResult(r, w, resp, err)
}
}
... ...
... ... @@ -529,6 +529,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Handler: article.MiniArticleBackupSearchHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/article_backup/:id",
Handler: article.MiniGetArticleBackupHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/article/set_tag",
Handler: article.MiniArticleSetTagHandler(serverCtx),
... ...
... ... @@ -51,18 +51,60 @@ func (l *MiniArticleBackupSearchLogic) MiniArticleBackupSearch(req *types.MiniAr
for _, val2 := range backupList[i].Images {
images = append(images, val2.Url)
}
resp.List[i] = types.MiniArticleBackupItem{
videos := []types.Video{}
for _, val2 := range backupList[i].Videos {
videos = append(videos, types.Video{
Url: val2.Url,
Cover: val2.Cover,
Width: val2.Width,
Height: val2.Height,
})
}
item := types.MiniArticleBackupItem{
Id: backupList[i].Id,
Title: backupList[i].Title,
Content: content.String(),
Images: images,
Title: "",
Content: "",
Images: []string{},
Videos: []types.Video{},
CreatedAt: backupList[i].CreatedAt,
Location: types.Location{
Longitude: backupList[i].Location.Longitude,
Latitude: backupList[i].Location.Latitude,
Descript: backupList[i].Location.Descript,
},
ChangeField: backupList[i].ChangeField,
Action: backupList[i].Action,
Show: int(backupList[i].Show),
}
//根据修改的内容替换展示内容
changeFiled := []string{}
for _, val := range item.ChangeField {
switch val {
case "WhoRead":
changeFiled = append(changeFiled, "修改了分发对象")
case "WhoReview":
changeFiled = append(changeFiled, "修改了评论范围")
case "Section":
{
item.Title = backupList[i].Title
item.Content = content.String()
item.Images = images
item.Videos = videos
}
}
}
if len(changeFiled) > 0 {
item.ChangeField = changeFiled
} else {
item.Title = backupList[i].Title
item.Content = content.String()
item.Images = images
item.Videos = videos
}
resp.List[i] = item
}
return resp, nil
}
... ...
... ... @@ -127,7 +127,7 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR
}
//切分文章分段
sectionList := []domain.ArticleSection{}
sectionList := []*domain.ArticleSection{}
newStr := ""
for i := range req.Section {
strList := strings.Split(req.Section[i], "\n")
... ... @@ -141,7 +141,7 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR
SortBy: len(sectionList),
TotalComment: 0,
}
sectionList = append(sectionList, newSection)
sectionList = append(sectionList, &newSection)
}
}
... ... @@ -185,11 +185,19 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR
for i := range sectionList {
sectionList[i].ArticleId = newArticle.Id
_, err = l.svcCtx.ArticleSectionRepository.Insert(ctx, c, &sectionList[i])
_, err = l.svcCtx.ArticleSectionRepository.Insert(ctx, c, sectionList[i])
if err != nil {
return xerr.NewErrMsgErr("创建文章内容失败", err)
}
}
// 生成 备份数据
var backupData domain.ArticleBackup
backupData.MakeBackup(articleAuthor, newArticle, sectionList, "原始版本")
_, err = l.svcCtx.ArticleBackupRepository.Insert(l.ctx, conn, &backupData)
if err != nil {
return xerr.NewErrMsgErr("创建文章失败", err)
}
return nil
}, true)
if err != nil {
... ...
package article
import (
"context"
"strings"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
"github.com/zeromicro/go-zero/core/logx"
)
type MiniGetArticleBackupLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewMiniGetArticleBackupLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MiniGetArticleBackupLogic {
return &MiniGetArticleBackupLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *MiniGetArticleBackupLogic) MiniGetArticleBackup(req *types.MiniGetArticleBackupRequest) (resp *types.MiniGetArticleBackupResponse, err error) {
var conn = l.svcCtx.DefaultDBConn()
backupInfo, err := l.svcCtx.ArticleBackupRepository.FindOne(l.ctx, conn, req.BackupId)
if err != nil {
return &types.MiniGetArticleBackupResponse{}, xerr.NewErrMsgErr("获取编辑记录失败", err)
}
content := strings.Builder{}
for _, val2 := range backupInfo.Section {
content.WriteString(val2.Content)
}
images := []string{}
for _, val2 := range backupInfo.Images {
images = append(images, val2.Url)
}
videos := []types.Video{}
for _, val2 := range backupInfo.Videos {
videos = append(videos, types.Video{
Url: val2.Url,
Cover: val2.Cover,
Width: val2.Width,
Height: val2.Height,
})
}
resp = &types.MiniGetArticleBackupResponse{
Id: backupInfo.Id,
Title: backupInfo.Title,
Content: content.String(),
Images: images,
Videos: videos,
CreatedAt: backupInfo.CreatedAt,
Location: types.Location{
Longitude: backupInfo.Location.Longitude,
Latitude: backupInfo.Location.Latitude,
Descript: backupInfo.Location.Descript,
},
ChangeField: backupInfo.ChangeField,
Action: backupInfo.Action,
Show: int(backupInfo.Show),
}
return
}
... ...
... ... @@ -42,25 +42,8 @@ func (l *MiniGetArticleLogic) MiniGetArticle(req *types.MiniArticleGetRequest) (
return nil, xerr.NewErrMsg("没有查看权限")
}
// 检查文章的可查看人
if articleInfo.AuthorId != int64(req.UserId) {
if len(articleInfo.WhoRead) > 0 {
inWhoRead := false
for _, val := range articleInfo.WhoRead {
if req.UserId == int(val) {
inWhoRead = true
}
}
if !inWhoRead {
// 文章内容不显示
// resp = &types.MiniArticleGetResponse{
// Id: articleInfo.Id,
// Title: articleInfo.Title,
// Show: int(domain.ArticleShowDisable),
// }
// return resp, nil
return nil, xerr.NewErrMsg("没有查看权限")
}
}
if ok := articleInfo.WhoCanRead(int64(req.UserId)); !ok {
return nil, xerr.NewErrMsg("没有查看权限")
}
if articleInfo.Show == domain.ArticleShowDisable {
// 文章内容不显示
... ... @@ -110,8 +93,8 @@ func (l *MiniGetArticleLogic) MiniGetArticle(req *types.MiniArticleGetRequest) (
follow, _ := l.svcCtx.UserFollowRepository.FindOneUserFollowing(l.ctx, conn, int64(req.UserId), articleInfo.AuthorId)
queryOption = domain.NewQueryOptions().WithFindOnly().WithOffsetLimit(1, 1).WithKV("articleId", articleInfo.Id)
_, backupList, _ := l.svcCtx.ArticleBackupRepository.Find(l.ctx, conn, queryOption)
queryOption = domain.NewQueryOptions().WithCountOnly().WithOffsetLimit(1, 1).WithKV("articleId", articleInfo.Id)
backupCount, _, _ := l.svcCtx.ArticleBackupRepository.Find(l.ctx, conn, queryOption)
sortBy := domain.SortArticleSection(sectionList)
sort.Sort(sortBy)
... ... @@ -157,7 +140,7 @@ func (l *MiniGetArticleLogic) MiniGetArticle(req *types.MiniArticleGetRequest) (
MatchUrl: map[string]string{},
Videos: []types.Video{},
}
if len(backupList) > 0 {
if backupCount > 1 {
resp.Edit = 1
}
if author != nil {
... ...
... ... @@ -39,6 +39,9 @@ func (l *MiniShowHomePageLogic) MiniShowHomePage(req *types.MiniHomePageRequest)
if err != nil {
return nil, xerr.NewErrMsgErr("获取文章汇总数量失败", err)
}
//TODO 拆分统计
countDataMap := map[int64]*domain.CountArticleTagRead{}
for _, val := range countData {
countDataMap[val.TagId] = val
... ...
... ... @@ -32,7 +32,7 @@ func NewSystemArticleRestoreLogic(ctx context.Context, svcCtx *svc.ServiceContex
func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticleRestoreRequest) (resp *types.SystemArticleRestoreResponse, err error) {
var conn = l.svcCtx.DefaultDBConn()
backup, err := l.svcCtx.ArticleBackupRepository.FindOne(l.ctx, conn, req.Id)
oldBackup, err := l.svcCtx.ArticleBackupRepository.FindOne(l.ctx, conn, req.Id)
if err != nil {
return nil, xerr.NewErrMsgErr("获取编辑历史记录失败", err)
}
... ... @@ -42,7 +42,7 @@ func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticl
if err != nil {
return nil, xerr.NewErrMsgErr("获取当前用户信息失败", err)
}
article, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, backup.ArticleId)
article, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, oldBackup.ArticleId)
if err != nil {
return nil, xerr.NewErrMsgErr("获取文章失败", err)
}
... ... @@ -50,24 +50,26 @@ func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticl
if err != nil {
return nil, xerr.NewErrMsgErr("获取文章段落内容失败", err)
}
// 备份数据
newBackUp := article.MakeBackup(domain.UserSimple{
var newBackUp domain.ArticleBackup
newBackUp.MakeBackup(domain.UserSimple{
Id: userToken.UserId,
Name: userMe.User.NickName,
Avatar: userMe.User.Avatar,
CompanyId: userToken.CompanyId,
Company: userMe.CurrentCompany.Name,
}, sectionList)
newBackUp.Action = "恢复"
}, article, sectionList, "恢复")
_ = newBackUp.CheckChangeField(oldBackup)
article.Version = article.Version + 1
article.Images = backup.Images
article.Videos = backup.Videos
article.Title = backup.Title
article.MatchUrl = backup.MatchUrl
articleSections := make([]domain.ArticleSection, 0)
lo.ForEach(backup.Section, func(item domain.ArticleSection, index int) {
articleSections = append(articleSections, domain.ArticleSection{
article.Images = oldBackup.Images
article.Videos = oldBackup.Videos
article.Title = oldBackup.Title
article.MatchUrl = oldBackup.MatchUrl
articleSections := make([]*domain.ArticleSection, 0)
lo.ForEach(oldBackup.Section, func(item domain.ArticleSection, index int) {
articleSections = append(articleSections, &domain.ArticleSection{
Id: item.Id,
CompanyId: item.CompanyId,
Version: article.Version,
... ... @@ -98,7 +100,7 @@ func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticl
return xerr.NewErrMsgErr("恢复文章版本失败", err)
}
} else {
_, err = l.svcCtx.ArticleSectionRepository.Insert(ctx, c, &item)
_, err = l.svcCtx.ArticleSectionRepository.Insert(ctx, c, item)
if err != nil {
return xerr.NewErrMsgErr("恢复文章版本失败", err)
}
... ... @@ -106,13 +108,14 @@ func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticl
updateSectionIds = append(updateSectionIds, item.Id)
}
if len(updateSectionIds) > 0 {
err = l.svcCtx.ArticleSectionRepository.DeleteBy(ctx, c, domain.NewQueryOptions().WithKV("articleId", article.Id).WithKV("notIds", updateSectionIds))
queryOption := domain.NewQueryOptions().WithKV("articleId", article.Id).WithKV("notIds", updateSectionIds)
err = l.svcCtx.ArticleSectionRepository.DeleteBy(ctx, c, queryOption)
if err != nil {
return xerr.NewErrMsgErr("保存文章内容失败", err)
}
}
_, err = l.svcCtx.ArticleBackupRepository.Insert(ctx, c, newBackUp)
_, err = l.svcCtx.ArticleBackupRepository.Insert(ctx, c, &newBackUp)
if err != nil {
return xerr.NewErrMsgErr("恢复文章版本失败", err)
}
... ...
... ... @@ -2,6 +2,7 @@ package article
import (
"context"
"github.com/samber/lo"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
... ... @@ -33,7 +34,9 @@ func (l *SystemSearchArticleLogic) SystemSearchArticle(req *types.SystemArticleS
WithKV("authorId", req.Author).
WithKV("tags", req.Tags).
WithKV("beginCreatedAt", req.BeginTime).
WithKV("endCreatedAt", req.EndTime)
WithKV("endCreatedAt", req.EndTime).
WithKV("orderMode", req.OrderMode)
total, articles, err := l.svcCtx.ArticleRepository.Find(l.ctx, conn, req.CompanyId, queryOptions)
if err != nil {
return nil, xerr.NewErrMsgErr("搜索帖子异常", err)
... ...
... ... @@ -57,24 +57,26 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU
if err != nil {
return nil, xerr.NewErrMsgErr("获取当前用户信息失败", err)
}
operator := domain.UserSimple{
Id: userToken.UserId,
Name: userMe.User.NickName,
Avatar: userMe.User.Avatar,
CompanyId: userToken.CompanyId,
Company: userMe.CurrentCompany.Name,
}
// 文章数据
article, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, l.conn, req.Id)
if err != nil {
return nil, xerr.NewErrMsgErr("帖子不存在", err)
}
_, sectionList, err := l.svcCtx.ArticleSectionRepository.Find(l.ctx, l.conn, map[string]interface{}{"articleId": article.Id})
//
queryOption := domain.NewQueryOptions().WithFindOnly().MustWithKV("articleId", req.Id)
_, sectionList, err := l.svcCtx.ArticleSectionRepository.Find(l.ctx, l.conn, queryOption)
if err != nil {
return nil, xerr.NewErrMsgErr("获取文章段落内容失败", err)
return nil, xerr.NewErrMsgErr("帖子不存在", err)
}
//备份数据
backup := article.MakeBackup(domain.UserSimple{
Id: userToken.UserId,
Name: userMe.User.NickName,
Avatar: userMe.User.Avatar,
CompanyId: userToken.CompanyId,
Company: userMe.CurrentCompany.Name,
}, sectionList)
backup.Action = "编辑"
var oldBackup domain.ArticleBackup
oldBackup.MakeBackup(operator, article, sectionList, "编辑")
// 获取图片的尺寸大小
images, err := l.getImages(req)
... ... @@ -126,6 +128,7 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU
}
//文章内容
updateSectionIds := []int64{}
updateSection := []*domain.ArticleSection{}
for _, item := range articleSections {
if item.Id > 0 {
section, err := l.svcCtx.ArticleSectionRepository.FindOne(ctx, c, item.Id)
... ... @@ -142,22 +145,29 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU
return xerr.NewErrMsgErr("保存文章段落内容失败", err)
}
} else {
_, err = l.svcCtx.ArticleSectionRepository.Insert(ctx, c, &item)
_, err = l.svcCtx.ArticleSectionRepository.Insert(ctx, c, item)
if err != nil {
return xerr.NewErrMsgErr("保存文章段落内容失败", err)
}
}
updateSectionIds = append(updateSectionIds, item.Id)
updateSection = append(updateSection, item)
}
if len(updateSectionIds) > 0 {
err = l.svcCtx.ArticleSectionRepository.DeleteBy(ctx, c, domain.NewQueryOptions().WithKV("articleId", article.Id).WithKV("notIds", updateSectionIds))
queryOption := domain.NewQueryOptions().WithKV("articleId", article.Id).WithKV("notIds", updateSectionIds)
err = l.svcCtx.ArticleSectionRepository.DeleteBy(ctx, c, queryOption)
if err != nil {
return xerr.NewErrMsgErr("保存文章内容失败", err)
}
}
_, err = l.svcCtx.ArticleBackupRepository.Insert(ctx, c, backup)
if err != nil {
return xerr.NewErrMsgErr("保存文章内容失败", err)
var backup domain.ArticleBackup
backup.MakeBackup(operator, article, updateSection, "编辑")
if ok := backup.CheckChangeField(&oldBackup); ok {
_, err = l.svcCtx.ArticleBackupRepository.Insert(ctx, c, &backup)
if err != nil {
return xerr.NewErrMsgErr("保存文章内容失败", err)
}
}
//文章定性
err = l.setTags(c, article)
... ... @@ -307,8 +317,8 @@ func (l *SystemUpdateArticleLogic) getVideos(req *types.SystemArticleUpdateReque
return videos, nil
}
func (l *SystemUpdateArticleLogic) getSections(req *types.SystemArticleUpdateRequest, article *domain.Article) []domain.ArticleSection {
articleSections := make([]domain.ArticleSection, 0)
func (l *SystemUpdateArticleLogic) getSections(req *types.SystemArticleUpdateRequest, article *domain.Article) []*domain.ArticleSection {
articleSections := make([]*domain.ArticleSection, 0)
sortBy := 1
lo.ForEach(req.Section, func(item types.ArticleSection, index int) {
strList := strings.Split(item.Content, "\n")
... ... @@ -326,7 +336,7 @@ func (l *SystemUpdateArticleLogic) getSections(req *types.SystemArticleUpdateReq
if key == 0 {
section.Id = item.Id
}
articleSections = append(articleSections, section)
articleSections = append(articleSections, &section)
sortBy++
}
})
... ...
... ... @@ -52,11 +52,8 @@ func (l *MiniCreateArticleCommentLogic) MiniCreateArticleComment(req *types.Mini
return nil, xerr.NewErrMsg("没有评论权限")
}
//查看评论权限,
if len(articleInfo.WhoReview) > 0 {
ok := lo.IndexOf(articleInfo.WhoReview, req.FromUserId)
if ok < 0 {
return nil, xerr.NewErrMsg("没有评论权限")
}
if ok := articleInfo.WhoCanReview(req.FromUserId); !ok {
return nil, xerr.NewErrMsg("没有评论权限")
}
// 对段落进行评论
var selctionInfo *domain.ArticleSection
... ... @@ -184,15 +181,7 @@ func (l *MiniCreateArticleCommentLogic) MiniCreateArticleComment(req *types.Mini
return err
}
}
//增加评论回复计数
// if pComment != nil {
// err = l.svcCtx.ArticleCommentRepository.IncreaseCountReply(l.ctx, c, 1, pComment.Id)
// if err != nil {
// return err
// }
// }
// 增加最顶层的评论回复计数
// if newComment.TopId != 0 && newComment.Pid != newComment.TopId {
if newComment.TopId != 0 {
err = l.svcCtx.ArticleCommentRepository.IncreaseCountReply(l.ctx, c, 1, newComment.TopId)
if err != nil {
... ...
... ... @@ -52,13 +52,6 @@ func (l *MiniDeleteArticleCommentLogic) MiniDeleteArticleComment(req *types.Mini
if err != nil {
return err
}
// 减少上级评论的回复数量
// if commentInfo.Pid != 0 {
// err = l.svcCtx.ArticleCommentRepository.IncreaseCountReply(l.ctx, c, -1, commentInfo.Pid)
// if err != nil {
// return err
// }
// }
// 减少最顶层的评论回复计数
// if commentInfo.TopId != 0 && commentInfo.Pid != commentInfo.TopId {
if commentInfo.TopId != 0 {
... ...
... ... @@ -80,15 +80,6 @@ func (l *SystemEditAticleCommentShowLogic) disableShow(commentId int64, companyI
if err != nil {
return err
}
// 减少上级评论的回复数量
// if commentInfo.Pid != 0 {
// err = l.svcCtx.ArticleCommentRepository.IncreaseCountReply(l.ctx, c, -1, commentInfo.Pid)
// if err != nil {
// return err
// }
// }
// 减少最顶层的评论回复计数
// if commentInfo.TopId != 0 && commentInfo.Pid != commentInfo.TopId {
if commentInfo.TopId != 0 {
err = l.svcCtx.ArticleCommentRepository.IncreaseCountReply(l.ctx, c, -1, commentInfo.TopId)
if err != nil {
... ... @@ -157,15 +148,8 @@ func (l *SystemEditAticleCommentShowLogic) enableShow(commentId int64, companyId
if err != nil {
return err
}
// 增加上级评论的回复数量
// if commetInfo.Pid != 0 {
// err = l.svcCtx.ArticleCommentRepository.IncreaseCountReply(l.ctx, c, 1, commetInfo.Pid)
// if err != nil {
// return err
// }
// }
// 增加最顶层的评论回复计数
// if commetInfo.TopId != 0 && commetInfo.Pid != commetInfo.TopId {
if commetInfo.TopId != 0 {
err = l.svcCtx.ArticleCommentRepository.IncreaseCountReply(l.ctx, c, 1, commetInfo.TopId)
if err != nil {
... ...
... ... @@ -489,10 +489,10 @@ type MiniHomepageUserNewsRequest struct {
LastArticleId int64 `json:"lastArticleId,optional"` // 最后文章ID
Size int `json:"size"` // 数量
OrderByKey string `json:"orderByKey,options=HotScore|All|Time,optional,default=desc"` // 按规则排序 (热度:HotScore All:时间排序 Time:时间排序)
OrderByValue string `json:"orderByValue,options=asc||desc,optional"`
Keywords string `json:"keywords,optional"` // 关键字
BeginTime int64 `json:"beginTime,optional"` // 开始时间
EndTime int64 `json:"endTime,optional"` // 结束时间
OrderByValue string `json:"orderByValue,options=asc||desc,optional"` // 排序值 升序 asc 降序 desc
Keywords string `json:"keywords,optional"` // 关键字
BeginTime int64 `json:"beginTime,optional"` // 开始时间
EndTime int64 `json:"endTime,optional"` // 结束时间
}
type MiniHomepageUserNewsResposne struct {
... ... @@ -1029,12 +1029,34 @@ type MiniArticleBackupSearchResponse struct {
}
type MiniArticleBackupItem struct {
Id int64 `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
Images []string `json:"images"`
CreatedAt int64 `json:"createdAt"`
Location Location `json:"location"`
Id int64 `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
Images []string `json:"images"`
Videos []Video `json:"videos"`
ChangeField []string `json:"changeField"`
CreatedAt int64 `json:"createdAt"`
Location Location `json:"location"`
Action string `json:"action"`
Show int `json:"show"`
}
type MiniGetArticleBackupRequest struct {
BackupId int64 `path:"id"`
CompanyId int64 `path:",optional"` // 服务端自动获取
}
type MiniGetArticleBackupResponse struct {
Id int64 `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
Images []string `json:"images"`
Videos []Video `json:"videos"`
ChangeField []string `json:"changeField"`
CreatedAt int64 `json:"createdAt"`
Location Location `json:"location"`
Action string `json:"action"`
Show int `json:"show"`
}
type MiniArticleMarkUserReadRequest struct {
... ... @@ -1226,6 +1248,7 @@ type SystemArticleSearchRequest struct {
Tags []int64 `json:"tags,optional"` //标签
Page int `json:"page"` //页码
Size int `json:"size"` //每页行数
OrderMode string `json:"orderMode,optional"` //排序方式
}
type SystemArticleSearchResponse struct {
... ... @@ -1250,7 +1273,7 @@ type SystemArticleSearch struct {
type SystemArticleUpdateRequest struct {
Id int64 `json:"id"`
CompanyId int64 `json:"companyId,optional"`
Template int `json:"template"` // 使用哪个模板进行编辑 0、无 1、演绎式 2、归纳式
Template int `json:"template,optional"` // 使用哪个模板进行编辑 0、无 1、演绎式 2、归纳式
Section []ArticleSection `json:"section"` // 填写的内容
Title string `json:"title"` // 标题
Images []string `json:"images"` // 图片
... ...
... ... @@ -10,26 +10,28 @@ import (
)
type ArticleBackup struct {
Id int64 `gorm:"primaryKey"` // 唯一标识
CompanyId int64
CreatedAt int64
UpdatedAt int64
DeletedAt int64
IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"`
Version int
Operator domain.UserSimple `gorm:"type:jsonb;serializer:json"` // 操作人
ArticleId int64
Title string // 标题
Section []domain.ArticleSection `gorm:"type:jsonb;serializer:json"` // 分段内容
Images []domain.Image `gorm:"type:jsonb;serializer:json"` // 图片
Videos []domain.Video `gorm:"type:jsonb;serializer:json"` // 视频
Action string // 操作
WhoRead []int64 `gorm:"type:jsonb;serializer:json"` // 谁可以看
WhoReview []int64 `gorm:"type:jsonb;serializer:json"` // 评论人
Tags []int64 `gorm:"type:jsonb;serializer:json"` // 标签
Location domain.Location `gorm:"type:jsonb;serializer:json"` // 坐标
TargetUser int // 分发方式 0 分发给所有人 1 分发给指定的人
MatchUrl map[string]string `gorm:"type:jsonb;serializer:json"` // 匹配文章内容中的url文本
Id int64 `gorm:"primaryKey"` // 唯一标识
CompanyId int64
CreatedAt int64
UpdatedAt int64
DeletedAt int64
IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"`
Version int
Operator domain.UserSimple `gorm:"type:jsonb;serializer:json"` // 操作人
ArticleId int64
Title string // 标题
Section []domain.ArticleSection `gorm:"type:jsonb;serializer:json"` // 分段内容
Images []domain.Image `gorm:"type:jsonb;serializer:json"` // 图片
Videos []domain.Video `gorm:"type:jsonb;serializer:json"` // 视频
ChangeField []string `gorm:"type:jsonb;serializer:json"` //
Action string // 操作
WhoRead []int64 `gorm:"type:jsonb;serializer:json"` // 谁可以看
WhoReview []int64 `gorm:"type:jsonb;serializer:json"` // 评论人
Tags []int64 `gorm:"type:jsonb;serializer:json"` // 标签
Location domain.Location `gorm:"type:jsonb;serializer:json"` // 坐标
TargetUser int // 分发方式 0 分发给所有人 1 分发给指定的人
MatchUrl map[string]string `gorm:"type:jsonb;serializer:json"` // 匹配文章内容中的url文本
Show int
}
func (m *ArticleBackup) TableName() string {
... ...
... ... @@ -157,25 +157,27 @@ func (repository *ArticleBackupRepository) Find(ctx context.Context, conn transa
func (repository *ArticleBackupRepository) ModelToDomainModel(from *models.ArticleBackup) (*domain.ArticleBackup, error) {
to := &domain.ArticleBackup{
Id: from.Id,
CompanyId: from.CompanyId,
CreatedAt: from.CreatedAt,
UpdatedAt: from.CreatedAt,
DeletedAt: from.DeletedAt,
Version: from.Version,
Operator: from.Operator,
ArticleId: from.ArticleId,
Title: from.Title,
Section: from.Section,
Images: from.Images,
Action: from.Action,
TargetUser: domain.ArticleTarget(from.TargetUser),
Location: from.Location,
WhoRead: from.WhoRead,
WhoReview: from.WhoReview,
Tags: from.Tags,
MatchUrl: from.MatchUrl,
Videos: from.Videos,
Id: from.Id,
CompanyId: from.CompanyId,
CreatedAt: from.CreatedAt,
UpdatedAt: from.CreatedAt,
DeletedAt: from.DeletedAt,
Version: from.Version,
Operator: from.Operator,
ArticleId: from.ArticleId,
Title: from.Title,
Section: from.Section,
Images: from.Images,
Action: from.Action,
TargetUser: domain.ArticleTarget(from.TargetUser),
Location: from.Location,
WhoRead: from.WhoRead,
WhoReview: from.WhoReview,
Tags: from.Tags,
MatchUrl: from.MatchUrl,
ChangeField: from.ChangeField,
Videos: from.Videos,
Show: domain.ArticleShow(from.Show),
}
// err := copier.Copy(to, from)
return to, nil
... ... @@ -183,26 +185,28 @@ func (repository *ArticleBackupRepository) ModelToDomainModel(from *models.Artic
func (repository *ArticleBackupRepository) DomainModelToModel(from *domain.ArticleBackup) (*models.ArticleBackup, error) {
to := &models.ArticleBackup{
Id: from.Id,
CompanyId: from.CompanyId,
CreatedAt: from.CreatedAt,
UpdatedAt: from.CreatedAt,
DeletedAt: from.DeletedAt,
IsDel: 0,
Version: from.Version,
Operator: from.Operator,
ArticleId: from.ArticleId,
Title: from.Title,
Section: from.Section,
Images: from.Images,
Action: from.Action,
WhoRead: from.WhoRead,
WhoReview: from.WhoReview,
Tags: from.Tags,
Location: from.Location,
TargetUser: int(from.TargetUser),
MatchUrl: from.MatchUrl,
Videos: from.Videos,
Id: from.Id,
CompanyId: from.CompanyId,
CreatedAt: from.CreatedAt,
UpdatedAt: from.CreatedAt,
DeletedAt: from.DeletedAt,
IsDel: 0,
Version: from.Version,
Operator: from.Operator,
ArticleId: from.ArticleId,
Title: from.Title,
Section: from.Section,
Images: from.Images,
Action: from.Action,
WhoRead: from.WhoRead,
WhoReview: from.WhoReview,
Tags: from.Tags,
Location: from.Location,
TargetUser: int(from.TargetUser),
MatchUrl: from.MatchUrl,
Videos: from.Videos,
ChangeField: from.ChangeField,
Show: int(from.Show),
}
// err := copier.Copy(to, from)
return to, nil
... ...
... ... @@ -121,7 +121,22 @@ func (repository *ArticleRepository) Find(ctx context.Context, conn transaction.
total int64
)
queryFunc := func() (interface{}, error) {
tx = tx.Model(&ms).Order("id desc").Where("company_id=?", companyId)
tx = tx.Model(&ms).Where("company_id=?", companyId)
if v, ok := queryOptions["orderMode"]; ok {
mode := v.(string)
switch mode {
case "countComment ascending":
tx = tx.Order("count_comment asc")
case "countComment descending":
tx = tx.Order("count_comment desc")
case "countLove ascending":
tx = tx.Order("count_love asc")
case "countLove descending":
tx = tx.Order("count_love desc")
default:
tx = tx.Order("created_at desc")
}
}
if v, ok := queryOptions["ids"]; ok {
tx = tx.Where("id in (?)", v)
}
... ...
... ... @@ -95,42 +95,7 @@ func (a ArticleShow) Named() string {
return ""
}
// 设置文章的备份数据
func (m *Article) MakeBackup(operator UserSimple, section []*ArticleSection) *ArticleBackup {
sectionBackup := make([]ArticleSection, len(section))
for i := range section {
sectionBackup[i] = *section[i]
}
b := ArticleBackup{
Id: 0,
CompanyId: m.CompanyId,
CreatedAt: 0,
UpdatedAt: 0,
DeletedAt: 0,
Version: m.Version,
Operator: operator,
ArticleId: m.Id,
Title: m.Title,
Section: sectionBackup,
Images: make([]Image, len(m.Images)),
Videos: make([]Video, len(m.Videos)),
Action: "",
TargetUser: m.TargetUser,
WhoRead: m.WhoRead,
WhoReview: m.WhoReview,
Tags: m.Tags,
MatchUrl: map[string]string{},
Location: m.Location,
}
copy(b.Videos, m.Videos)
copy(b.Images, m.Images)
for k, v := range m.MatchUrl {
b.MatchUrl[k] = v
}
return &b
}
func (m *Article) SetSummary(sectionList []ArticleSection) {
func (m *Article) SetSummary(sectionList []*ArticleSection) {
if len(sectionList) == 0 {
return
}
... ... @@ -156,3 +121,33 @@ func (m *Article) SetSummary(sectionList []ArticleSection) {
}
m.Summary = content[0:stringIndex]
}
func (m *Article) WhoCanRead(userId int64) bool {
if m.AuthorId == userId {
return true
}
if len(m.WhoRead) == 0 {
return true
}
for _, val := range m.WhoRead {
if userId == val {
return true
}
}
return false
}
func (m *Article) WhoCanReview(userId int64) bool {
if m.AuthorId == userId {
return true
}
if len(m.WhoReview) == 0 {
return true
}
for _, val := range m.WhoReview {
if userId == val {
return true
}
}
return false
}
... ...
package domain
import (
"bytes"
"context"
"encoding/json"
"fmt"
"sort"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
)
// 编辑文章后保存的历史记录
type ArticleBackup struct {
Id int64 `json:"id"`
CompanyId int64 `json:"companyId"`
CreatedAt int64 `json:"createdAt,omitempty"`
UpdatedAt int64 `json:"updatedAt,omitempty"`
DeletedAt int64 `json:"deletedAt,omitempty"`
Version int `json:"version,omitempty"`
Operator UserSimple `json:"operator"` // 操作人
ArticleId int64 `json:"articleId"` //
Title string `json:"title"` // 标题
Section []ArticleSection `json:"section"` // 分段内容
Images []Image `json:"images"` // 图片
Videos []Video `json:"videos"` // 视频
Action string `json:"action"` // 操作
TargetUser ArticleTarget `json:"targetUser"` // 分发方式 0 分发给所有人 1 分发给指定的人
Location Location `json:"location"` // 定位坐标
WhoRead []int64 `json:"whoRead"` // 谁可以看
WhoReview []int64 `json:"whoReview"` // 评论人
Tags []int64 `json:"tags"` // 标签
MatchUrl map[string]string `json:"matchUrl"` // 匹配文章内容中的url文本
Id int64 `json:"id"`
CompanyId int64 `json:"companyId"`
CreatedAt int64 `json:"createdAt,omitempty"`
UpdatedAt int64 `json:"updatedAt,omitempty"`
DeletedAt int64 `json:"deletedAt,omitempty"`
Version int `json:"version,omitempty"`
Operator UserSimple `json:"operator"` // 操作人
ArticleId int64 `json:"articleId"` //
Title string `json:"title"` // 标题
Section []ArticleSection `json:"section"` // 分段内容
Images []Image `json:"images"` // 图片
Videos []Video `json:"videos"` // 视频
Action string `json:"action"` // 操作
// 新的备份内容相对与旧的文章信息哪些内容发生了变更,可选值[WhoRead] 修改了分发对象, [WhoReview] 修改了评论范围,[Section] 修改了内容
ChangeField []string `json:"changeField"`
TargetUser ArticleTarget `json:"targetUser"` // 分发方式 0 分发给所有人 1 分发给指定的人
Location Location `json:"location"` // 定位坐标
WhoRead []int64 `json:"whoRead"` // 谁可以看
WhoReview []int64 `json:"whoReview"` // 评论人
Tags []int64 `json:"tags"` // 标签
MatchUrl map[string]string `json:"matchUrl"` // 匹配文章内容中的url文本
Show ArticleShow `json:"show"` // 评论的展示状态(1显示,2不显示、)
}
type ArticleBackupRepository interface {
... ... @@ -37,3 +44,137 @@ type ArticleBackupRepository interface {
FindOne(ctx context.Context, conn transaction.Conn, id int64) (*ArticleBackup, error)
Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*ArticleBackup, error)
}
// 检查新的备份内容相对与旧的文章信息哪些内容发生了变更
// 记录ArticleBackup中数据发生变更的的字段名
func (bk *ArticleBackup) CheckChangeField(oldBackup *ArticleBackup) bool {
bk.ChangeField = make([]string, 0)
//比较 WhoRead
{
whoReadChanged := false
sort.Slice(bk.WhoRead, func(i, j int) bool {
return bk.WhoRead[i] < bk.WhoRead[j]
})
sort.Slice(oldBackup.WhoRead, func(i, j int) bool {
return oldBackup.WhoRead[i] < oldBackup.WhoRead[j]
})
if len(bk.WhoRead) != len(oldBackup.WhoRead) {
whoReadChanged = true
} else {
for i := range bk.WhoRead {
if bk.WhoRead[i] != oldBackup.WhoRead[i] {
whoReadChanged = true
}
}
}
if whoReadChanged {
bk.ChangeField = append(bk.ChangeField, "WhoRead")
}
}
//比较 whoReview
{
whoReviewChanged := false
sort.Slice(bk.WhoReview, func(i, j int) bool {
return bk.WhoReview[i] < bk.WhoReview[j]
})
sort.Slice(oldBackup.WhoReview, func(i, j int) bool {
return oldBackup.WhoReview[i] < oldBackup.WhoReview[j]
})
if len(bk.WhoReview) != len(oldBackup.WhoReview) {
whoReviewChanged = true
} else {
for i := range bk.WhoReview {
if bk.WhoReview[i] != oldBackup.WhoReview[i] {
whoReviewChanged = true
}
}
}
if whoReviewChanged {
bk.ChangeField = append(bk.ChangeField, "WhoReview")
}
}
//比较段落内容+图片+视频 是否发生变更
{
sectionChanged := false
newSectionData := map[string]string{
"title": bk.Title,
}
oldSectionData := map[string]string{
"title": oldBackup.Title,
}
for _, val := range bk.Section {
mkey := fmt.Sprintf("section-%d", val.SortBy)
newSectionData[mkey] = val.Content
}
for _, val := range bk.Images {
newSectionData[val.Url] = ""
}
for _, val := range bk.Videos {
newSectionData[val.Url] = ""
}
for _, val := range oldBackup.Section {
mKey := fmt.Sprintf("section-%d", val.SortBy)
oldSectionData[mKey] = val.Content
}
for _, val := range oldBackup.Images {
oldSectionData[val.Url] = ""
}
for _, val := range oldBackup.Videos {
oldSectionData[val.Url] = ""
}
newSectionJson, _ := json.Marshal(newSectionData)
oldSectionJson, _ := json.Marshal(oldSectionData)
if ok := bytes.Equal(newSectionJson, oldSectionJson); !ok {
sectionChanged = true
}
if sectionChanged {
bk.ChangeField = append(bk.ChangeField, "Section")
}
}
return len(bk.ChangeField) > 0
}
// 创建备份信息
func (bk *ArticleBackup) MakeBackup(operator UserSimple, article *Article, section []*ArticleSection, action string) {
sectionBackup := make([]ArticleSection, len(section))
for i := range section {
sectionBackup[i] = *section[i]
}
b := ArticleBackup{
Id: 0,
CompanyId: article.CompanyId,
CreatedAt: 0,
UpdatedAt: 0,
DeletedAt: 0,
Version: article.Version,
Operator: operator,
ArticleId: article.Id,
Title: article.Title,
Section: sectionBackup,
Images: make([]Image, len(article.Images)),
Videos: make([]Video, len(article.Videos)),
Action: action,
TargetUser: article.TargetUser,
WhoRead: article.WhoRead,
WhoReview: article.WhoReview,
Tags: article.Tags,
MatchUrl: map[string]string{},
Show: article.Show,
Location: article.Location,
}
if action == "原始版本" {
b.ChangeField = append(b.ChangeField, "Section")
}
copy(b.Videos, article.Videos)
copy(b.Images, article.Images)
for k, v := range article.MatchUrl {
b.MatchUrl[k] = v
}
*bk = b
}
... ...
... ... @@ -3,14 +3,15 @@ package database
import (
"context"
"fmt"
"log"
"os"
"time"
"github.com/zeromicro/go-zero/core/logx"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"log"
"os"
"time"
)
func OpenGormDB(source string) *gorm.DB {
... ... @@ -44,6 +45,7 @@ func OpenGormPGDB(source string, logMode string) *gorm.DB {
if err != nil {
panic(err)
}
return db
}
... ...