mini_create_article_logic.go 6.7 KB
package article

import (
	"context"
	"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/core"
	"strconv"
	"strings"
	"text/template"
	"unicode/utf8"

	"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/cmd/discuss/interanl/pkg/db/transaction"
	"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
	"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/tool/oss"
	"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"

	"github.com/samber/lo"
	"github.com/zeromicro/go-zero/core/logx"
)

type MiniCreateArticleLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewMiniCreateArticleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MiniCreateArticleLogic {
	return &MiniCreateArticleLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

// 创建新文章
func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateRequest) (resp *types.MiniArticleCreateResponse, err error) {
	var conn = l.svcCtx.DefaultDBConn()
	err = l.validateTextLimit(req)
	if err != nil {
		return nil, err
	}
	// 检查发布人
	author, err := l.svcCtx.UserRepository.FindOne(l.ctx, conn, req.AuthorId)
	if err != nil {
		return nil, xerr.NewErrMsgErr("创建文章内容失败", err)
	}
	companyInfo, err := l.svcCtx.CompanyRepository.FindOne(l.ctx, conn, author.CompanyId)
	if err != nil {
		return nil, xerr.NewErrMsgErr("创建文章内容失败", err)
	}
	articleAuthor := domain.UserSimple{
		Id:        author.Id,
		Name:      author.Name,
		Avatar:    author.Avatar,
		Position:  author.Position,
		Company:   companyInfo.Name,
		CompanyId: author.CompanyId,
	}
	if len(req.Images) > 9 {
		return nil, xerr.NewErrMsg("图片数量最多9张")
	}
	//获取图片的尺寸大小
	images := []domain.Image{}
	for _, val := range req.Images {
		fInfo, _ := oss.GetImageInfo(val)
		w, _ := strconv.Atoi(fInfo.ImageWidth.Value)
		h, _ := strconv.Atoi(fInfo.ImageHeight.Value)
		images = append(images, domain.Image{
			Url:    val,
			Width:  w,
			Height: h,
		})
	}

	//检查文章可被哪些人查看
	whoRead := []int64{}
	if len(req.WhoRead) > 0 {
		whoRead = lo.Uniq(req.WhoRead)
		var u *domain.User
		for _, val := range whoRead {
			u, err = l.svcCtx.UserRepository.FindOne(l.ctx, conn, val)
			if err != nil {
				return nil, xerr.NewErrMsgErr("文章可查看人设置错误", err)
			}
			if u.CompanyId != author.CompanyId {
				return nil, xerr.NewErrMsg("文章可查看人设置错误")
			}
		}
	}
	//检查文章可被哪些人评论
	whoReview := []int64{}
	if len(req.WhoReview) > 0 {
		whoReview = lo.Uniq(req.WhoReview)
	}
	//有指定可查看人的情况
	if len(whoRead) > 0 {
		if len(whoReview) > 0 {
			// 检查 whoRead 是否 完全包含 whoReview
			ok := lo.Every(whoRead, whoReview)
			if !ok {
				return nil, xerr.NewErrMsg("文章可评论人设置错误")
			}
		}
		if len(whoReview) == 0 {
			//有指定可查看人 ,但未指定可评论人
			return nil, xerr.NewErrMsg("文章可评论人设置错误")
		}
	}
	//没有指定可查看人的情况
	if len(whoRead) == 0 {
		if len(whoReview) > 0 {
			// 未指定可查看人(全员可看),有指定可评论人,
			var u *domain.User
			for _, val := range whoReview {
				u, err = l.svcCtx.UserRepository.FindOne(l.ctx, conn, val)
				if err != nil {
					return nil, xerr.NewErrMsgErr("文章可评论人设置错误", err)
				}
				if u.CompanyId != author.CompanyId {
					return nil, xerr.NewErrMsg("文章可评论人设置错误")
				}
			}
		}
		// if len(whoReview) == 0 {
		// 未指定可查看人(全员可看),未指定可评论人 ,忽略判断
		// }
	}

	//切分文章分段
	sectionList := []*domain.ArticleSection{}
	newStr := ""
	for i := range req.Section {
		strList := strings.Split(req.Section[i], "\n")
		for i2 := range strList {
			newStr = template.HTMLEscapeString(strList[i2])
			newSection := domain.ArticleSection{
				Id:           0,
				CompanyId:    author.CompanyId,
				ArticleId:    0,
				Content:      newStr,
				SortBy:       len(sectionList),
				TotalComment: 0,
			}
			sectionList = append(sectionList, &newSection)
		}
	}

	newArticle := &domain.Article{
		Id:        0,
		CompanyId: author.CompanyId,
		AuthorId:  author.Id,
		Author:    articleAuthor,
		Title:     req.Title,
		Images:    images,
		WhoRead:   whoRead,
		WhoReview: whoReview,
		Location: domain.Location{
			Longitude: req.Location.Longitude,
			Latitude:  req.Location.Latitude,
			Descript:  req.Location.Descript,
		},
		TargetUser:   domain.ArticleTargetAll,
		CountLove:    0,
		CountComment: 0,
		CountRead:    0,
		Show:         domain.ArticleShowEnable,
		Tags:         []int64{},
		MatchUrl:     map[string]string{},
		Videos:       []domain.Video{},
	}
	if len(whoRead) > 0 {
		newArticle.TargetUser = domain.ArticleTargetLimit
	}
	for k, v := range req.MatchUrl {
		newArticle.MatchUrl[k] = v
	}
	//设置内容概要
	newArticle.SetSummary(sectionList)

	err = transaction.UseTrans(l.ctx, conn.DB(), func(ctx context.Context, c transaction.Conn) error {
		newArticle, err = l.svcCtx.ArticleRepository.Insert(ctx, c, newArticle)
		if err != nil {
			return xerr.NewErrMsgErr("创建文章失败", err)
		}

		for i := range sectionList {
			sectionList[i].ArticleId = newArticle.Id
			_, 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)
		}

		// 内容安全检查
		if err = core.ContentSecurityCheck(l.ctx, l.svcCtx, conn, "", core.NewContentFromArticle(newArticle, sectionList)); err != nil {
			return err
		}
		return nil
	}, true)
	if err != nil {
		return nil, xerr.NewErrMsgErr("创建文章失败", err)
	}

	resp = &types.MiniArticleCreateResponse{
		Id: newArticle.Id,
	}
	return
}

// validateTextLimit 验证输入文本长度
func (l *MiniCreateArticleLogic) validateTextLimit(req *types.MiniArticleCreateRequest) error {

	titleWordNum := utf8.RuneCountInString(req.Title)
	if titleWordNum > 64 {
		return xerr.NewErrMsg("标题最多只能输入64字")
	}
	wordNum := 0
	for i := range req.Section {
		num := utf8.RuneCountInString(req.Section[i])
		wordNum += num
	}
	if wordNum > 1000 {
		return xerr.NewErrMsg("内容最多只能输入1000字")
	}

	return nil
}