作者 tangxvhui
... ... @@ -10,9 +10,9 @@ type Location {
type Video {
Url string `json:"url"` //视频文件的地址
Cover string `json:"cover"` //封面
Width int `json:"width"` //封面图片宽
Height int `json:"height"` //封面图片长
Cover string `json:"cover,optional"` //封面
Width int `json:"width,optional"` //封面图片宽
Height int `json:"height,optional"` //封面图片长
}
... ...
... ... @@ -2,6 +2,8 @@ package article
import (
"context"
"github.com/jinzhu/copier"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/message"
"strconv"
"unicode/utf8"
... ... @@ -25,6 +27,7 @@ type SystemUpdateArticleLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
conn transaction.Conn
}
func NewSystemUpdateArticleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SystemUpdateArticleLogic {
... ... @@ -32,39 +35,33 @@ func NewSystemUpdateArticleLogic(ctx context.Context, svcCtx *svc.ServiceContext
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
conn: svcCtx.DefaultDBConn(),
}
}
func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleUpdateRequest) (resp *types.SystemArticleUpdateResponse, err error) {
var conn = l.svcCtx.DefaultDBConn()
//var conn = l.svcCtx.DefaultDBConn()
userToken := contextdata.GetUserTokenFromCtx(l.ctx)
// 预处理参数
if req.TargetUser == 0 {
//TargetUser 设定为分发给所有人,清空 WhoRead
req.WhoRead = make([]int64, 0)
}
// 检查文字数量
wordNum := 0
for i := range req.Section {
num := utf8.RuneCountInString(req.Section[i].Content)
wordNum += num
}
if wordNum >= 1000 {
return nil, xerr.NewErrMsgErr("最多只能输入1000字", err)
if err = l.validateTextLimit(req); err != nil {
return nil, err
}
// 获取当前用户信息
userMe, err := l.svcCtx.ApiAuthService.MeInfo(l.ctx, authlib.RequestUserMeQuery{Token: req.AccessToken})
if err != nil {
return nil, xerr.NewErrMsgErr("获取当前用户信息失败", err)
}
// 文章数据
article, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, req.Id)
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, conn, map[string]interface{}{"articleId": article.Id})
_, sectionList, err := l.svcCtx.ArticleSectionRepository.Find(l.ctx, l.conn, map[string]interface{}{"articleId": article.Id})
if err != nil {
return nil, xerr.NewErrMsgErr("获取文章段落内容失败", err)
}
... ... @@ -79,111 +76,45 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU
backup.Action = "编辑"
// 获取图片的尺寸大小
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,
})
images, err := l.getImages(req)
if err != nil {
return nil, err
}
//视频
videos, err := l.getVideos(req)
if err != nil {
return nil, err
}
//检查文章可被哪些人查看
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)
whoRead, err := l.validateAndGetWhoRead(req, article)
if err != nil {
return nil, xerr.NewErrMsgErr("文章可查看人设置错误", err)
}
if u.CompanyId != article.CompanyId {
return nil, xerr.NewErrMsg("文章可查看人设置错误")
}
}
return nil, err
}
//检查文章可被哪些人评论
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 != article.CompanyId {
return nil, xerr.NewErrMsg("文章可评论人设置错误")
}
}
}
//验证可评论
if err = l.validateWhoReview(whoRead, whoReview, article); err != nil {
return nil, err
}
//验证tag
if len(req.Tags) > 0 {
req.Tags = lo.Uniq(req.Tags)
for _, value := range req.Tags {
t, err := l.svcCtx.ArticleTagRepository.FindOne(l.ctx, conn, value)
if err != nil {
return nil, xerr.NewErrMsgErr("文章标签设置错误", err)
}
if t.CompanyId != article.CompanyId {
return nil, xerr.NewErrMsgErr("文章标签设置错误", err)
}
}
validTags := l.validateTags(req, article)
if validTags != nil {
return nil, validTags
}
article.Title = req.Title
article.Version = article.Version + 1
article.Images = images
article.Videos = videos
article.WhoRead = whoRead
article.WhoReview = whoReview
article.TargetUser = domain.ArticleTarget(req.TargetUser)
article.Tags = req.Tags
//文章内容
articleSections := []domain.ArticleSection{}
sortBy := 1
lo.ForEach(req.Section, func(item types.ArticleSection, index int) {
strList := strings.Split(item.Content, "\n")
for key, value := range strList {
if value == "" {
continue
}
section := domain.ArticleSection{
CompanyId: article.CompanyId,
Version: article.Version,
ArticleId: article.Id,
Content: value,
SortBy: sortBy,
}
if key == 0 {
section.Id = item.Id
}
articleSections = append(articleSections, section)
sortBy++
}
})
articleSections := l.getSections(req, article)
//设置内容概要
if len(req.Section) > 0 {
// 截取内容 50个字
... ... @@ -199,7 +130,7 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU
article.Summary = req.Section[0].Content[0:stringIndex]
}
err = transaction.UseTrans(l.ctx, conn.DB(), func(ctx context.Context, c transaction.Conn) error {
err = transaction.UseTrans(l.ctx, l.conn.DB(), func(ctx context.Context, c transaction.Conn) error {
_, err = l.svcCtx.ArticleRepository.Update(l.ctx, c, article)
if err != nil {
return xerr.NewErrMsgErr("保存文章失败", err)
... ... @@ -239,6 +170,11 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU
if err != nil {
return xerr.NewErrMsgErr("保存文章内容失败", err)
}
//文章定性
err = l.setTags(c, article)
if err != nil {
return err
}
return nil
}, true)
resp = &types.SystemArticleUpdateResponse{
... ... @@ -252,5 +188,193 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU
TargetUser: int(article.TargetUser),
Tags: article.Tags,
}
_ = copier.Copy(&resp.Videos, videos)
return
}
// validateTextLimit 验证输入文本长度
func (l *SystemUpdateArticleLogic) validateTextLimit(req *types.SystemArticleUpdateRequest) error {
wordNum := 0
for i := range req.Section {
num := utf8.RuneCountInString(req.Section[i].Content)
wordNum += num
}
if wordNum >= 1000 {
return xerr.NewErrMsg("最多只能输入1000字")
}
return nil
}
// validateAndGetWhoRead 验证并获取可阅读
func (l *SystemUpdateArticleLogic) validateAndGetWhoRead(req *types.SystemArticleUpdateRequest, article *domain.Article) ([]int64, error) {
whoRead := make([]int64, 0)
if len(req.WhoRead) > 0 {
whoRead = lo.Uniq(req.WhoRead)
var u *domain.User
var err error
for _, val := range whoRead {
u, err = l.svcCtx.UserRepository.FindOne(l.ctx, l.conn, val)
if err != nil {
return whoRead, xerr.NewErrMsgErr("文章可查看人设置错误", err)
}
if u.CompanyId != article.CompanyId {
return whoRead, xerr.NewErrMsg("文章可查看人设置错误")
}
}
}
return whoRead, nil
}
// validateWhoReview 验证可评论
func (l *SystemUpdateArticleLogic) validateWhoReview(whoRead []int64, whoReview []int64, article *domain.Article) error {
//有指定可查看人的情况
if len(whoRead) > 0 {
if len(whoReview) > 0 {
// 检查 whoRead 是否 完全包含 whoReview
ok := lo.Every(whoRead, whoReview)
if !ok {
return xerr.NewErrMsg("文章可评论人设置错误")
}
}
if len(whoReview) == 0 {
//有指定可查看人 ,但未指定可评论人
return xerr.NewErrMsg("文章可评论人设置错误")
}
}
//没有指定可查看人的情况
if len(whoRead) == 0 {
if len(whoReview) > 0 {
// 未指定可查看人(全员可看),有指定可评论人,
var u *domain.User
var err error
for _, val := range whoReview {
u, err = l.svcCtx.UserRepository.FindOne(l.ctx, l.conn, val)
if err != nil {
return xerr.NewErrMsgErr("文章可评论人设置错误", err)
}
if u.CompanyId != article.CompanyId {
return xerr.NewErrMsg("文章可评论人设置错误")
}
}
}
}
return nil
}
// validateTags 验证标签
func (l *SystemUpdateArticleLogic) validateTags(req *types.SystemArticleUpdateRequest, article *domain.Article) error {
if len(req.Tags) > 0 {
req.Tags = lo.Uniq(req.Tags)
for _, value := range req.Tags {
t, err := l.svcCtx.ArticleTagRepository.FindOne(l.ctx, l.conn, value)
if err != nil {
return xerr.NewErrMsgErr("文章标签设置错误", err)
}
if t.CompanyId != article.CompanyId {
return xerr.NewErrMsgErr("文章标签设置错误", err)
}
}
}
return nil
}
// getImages 获取图片信息
func (l *SystemUpdateArticleLogic) getImages(req *types.SystemArticleUpdateRequest) ([]domain.Image, error) {
// 获取图片的尺寸大小
images := make([]domain.Image, 0)
for _, val := range req.Images {
fInfo, err := oss.GetImageInfo(val)
if err != nil {
return images, xerr.NewErrMsg("获取图片失败")
}
w, _ := strconv.Atoi(fInfo.ImageWidth.Value)
h, _ := strconv.Atoi(fInfo.ImageHeight.Value)
images = append(images, domain.Image{
Url: val,
Width: w,
Height: h,
})
}
return images, nil
}
// getVideo 获取视频信息
func (l *SystemUpdateArticleLogic) getVideos(req *types.SystemArticleUpdateRequest) ([]domain.Video, error) {
videos := make([]domain.Video, 0)
if len(req.Videos) > 0 {
for _, item := range req.Videos {
cover, w, h, err := oss.GetVideoCover(item.Url)
if err != nil {
return videos, xerr.NewErrMsg("获取视频信息失败")
}
videos = append(videos, domain.Video{
Url: item.Url,
Cover: cover,
Width: w,
Height: h,
})
}
}
return videos, nil
}
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")
for key, value := range strList {
if value == "" {
continue
}
section := domain.ArticleSection{
CompanyId: article.CompanyId,
Version: article.Version,
ArticleId: article.Id,
Content: value,
SortBy: sortBy,
}
if key == 0 {
section.Id = item.Id
}
articleSections = append(articleSections, section)
sortBy++
}
})
return articleSections
}
// setTags 设置定性标签
func (l *SystemUpdateArticleLogic) setTags(conn transaction.Conn, article *domain.Article) error {
_, oldTags, err := l.svcCtx.ArticleAndTagRepository.Find(l.ctx, conn, domain.NewQueryOptions().WithFindOnly().WithKV("articleId", article.Id))
if err != nil {
return xerr.NewErrMsgErr("检查文章的标签失败", err)
}
//删除旧标签
for _, v := range oldTags {
_, err = l.svcCtx.ArticleAndTagRepository.Delete(l.ctx, conn, v)
if err != nil {
return xerr.NewErrMsg(err.Error())
}
}
if len(article.Tags) > 0 {
for _, tagId := range article.Tags {
articleTag := &domain.ArticleAndTag{
CompanyId: article.CompanyId,
ArticleId: article.Id,
TagId: tagId,
}
_, err = l.svcCtx.ArticleAndTagRepository.Insert(l.ctx, conn, articleTag)
if err != nil {
return xerr.NewErrMsg(err.Error())
}
}
//发送定性通知
messageLogic := message.NewMiniSystemLogic(l.ctx, l.svcCtx)
err = messageLogic.ArticleDefined(conn, article.CompanyId, article.AuthorId, article.Title)
if err != nil {
return xerr.NewErrMsg(err.Error())
}
}
return nil
}
... ...
... ... @@ -827,9 +827,9 @@ type Location struct {
type Video struct {
Url string `json:"url"` //视频文件的地址
Cover string `json:"cover"` //封面
Width int `json:"width"` //封面图片宽
Height int `json:"height"` //封面图片长
Cover string `json:"cover,optional"` //封面
Width int `json:"width,optional"` //封面图片宽
Height int `json:"height,optional"` //封面图片长
}
type ArticleAuthor struct {
... ...