article_backup.go 5.8 KB
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"`    // 操作
	// 新的备份内容相对与旧的文章信息哪些内容发生了变更,可选值[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 {
	Insert(ctx context.Context, conn transaction.Conn, dm *ArticleBackup) (*ArticleBackup, error)
	Update(ctx context.Context, conn transaction.Conn, dm *ArticleBackup) (*ArticleBackup, error)
	UpdateWithVersion(ctx context.Context, conn transaction.Conn, dm *ArticleBackup) (*ArticleBackup, error)
	Delete(ctx context.Context, conn transaction.Conn, dm *ArticleBackup) (*ArticleBackup, error)
	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
}