作者 庄敏学

Merge branch 'dev' into test

@@ -10,9 +10,9 @@ type Location { @@ -10,9 +10,9 @@ type Location {
10 10
11 type Video { 11 type Video {
12 Url string `json:"url"` //视频文件的地址 12 Url string `json:"url"` //视频文件的地址
13 - Cover string `json:"cover"` //封面  
14 - Width int `json:"width"` //封面图片宽  
15 - Height int `json:"height"` //封面图片长 13 + Cover string `json:"cover,optional"` //封面
  14 + Width int `json:"width,optional"` //封面图片宽
  15 + Height int `json:"height,optional"` //封面图片长
16 } 16 }
17 17
18 18
@@ -2,6 +2,8 @@ package article @@ -2,6 +2,8 @@ package article
2 2
3 import ( 3 import (
4 "context" 4 "context"
  5 + "github.com/jinzhu/copier"
  6 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/message"
5 "strconv" 7 "strconv"
6 "unicode/utf8" 8 "unicode/utf8"
7 9
@@ -25,6 +27,7 @@ type SystemUpdateArticleLogic struct { @@ -25,6 +27,7 @@ type SystemUpdateArticleLogic struct {
25 logx.Logger 27 logx.Logger
26 ctx context.Context 28 ctx context.Context
27 svcCtx *svc.ServiceContext 29 svcCtx *svc.ServiceContext
  30 + conn transaction.Conn
28 } 31 }
29 32
30 func NewSystemUpdateArticleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SystemUpdateArticleLogic { 33 func NewSystemUpdateArticleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SystemUpdateArticleLogic {
@@ -32,39 +35,33 @@ func NewSystemUpdateArticleLogic(ctx context.Context, svcCtx *svc.ServiceContext @@ -32,39 +35,33 @@ func NewSystemUpdateArticleLogic(ctx context.Context, svcCtx *svc.ServiceContext
32 Logger: logx.WithContext(ctx), 35 Logger: logx.WithContext(ctx),
33 ctx: ctx, 36 ctx: ctx,
34 svcCtx: svcCtx, 37 svcCtx: svcCtx,
  38 + conn: svcCtx.DefaultDBConn(),
35 } 39 }
36 } 40 }
37 41
38 func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleUpdateRequest) (resp *types.SystemArticleUpdateResponse, err error) { 42 func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleUpdateRequest) (resp *types.SystemArticleUpdateResponse, err error) {
39 - var conn = l.svcCtx.DefaultDBConn() 43 + //var conn = l.svcCtx.DefaultDBConn()
40 userToken := contextdata.GetUserTokenFromCtx(l.ctx) 44 userToken := contextdata.GetUserTokenFromCtx(l.ctx)
41 // 预处理参数 45 // 预处理参数
42 if req.TargetUser == 0 { 46 if req.TargetUser == 0 {
43 //TargetUser 设定为分发给所有人,清空 WhoRead 47 //TargetUser 设定为分发给所有人,清空 WhoRead
44 req.WhoRead = make([]int64, 0) 48 req.WhoRead = make([]int64, 0)
45 } 49 }
46 -  
47 // 检查文字数量 50 // 检查文字数量
48 - wordNum := 0  
49 - for i := range req.Section {  
50 - num := utf8.RuneCountInString(req.Section[i].Content)  
51 - wordNum += num  
52 - }  
53 - if wordNum >= 1000 {  
54 - return nil, xerr.NewErrMsgErr("最多只能输入1000字", err) 51 + if err = l.validateTextLimit(req); err != nil {
  52 + return nil, err
55 } 53 }
56 -  
57 // 获取当前用户信息 54 // 获取当前用户信息
58 userMe, err := l.svcCtx.ApiAuthService.MeInfo(l.ctx, authlib.RequestUserMeQuery{Token: req.AccessToken}) 55 userMe, err := l.svcCtx.ApiAuthService.MeInfo(l.ctx, authlib.RequestUserMeQuery{Token: req.AccessToken})
59 if err != nil { 56 if err != nil {
60 return nil, xerr.NewErrMsgErr("获取当前用户信息失败", err) 57 return nil, xerr.NewErrMsgErr("获取当前用户信息失败", err)
61 } 58 }
62 // 文章数据 59 // 文章数据
63 - article, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, req.Id) 60 + article, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, l.conn, req.Id)
64 if err != nil { 61 if err != nil {
65 return nil, xerr.NewErrMsgErr("帖子不存在", err) 62 return nil, xerr.NewErrMsgErr("帖子不存在", err)
66 } 63 }
67 - _, sectionList, err := l.svcCtx.ArticleSectionRepository.Find(l.ctx, conn, map[string]interface{}{"articleId": article.Id}) 64 + _, sectionList, err := l.svcCtx.ArticleSectionRepository.Find(l.ctx, l.conn, map[string]interface{}{"articleId": article.Id})
68 if err != nil { 65 if err != nil {
69 return nil, xerr.NewErrMsgErr("获取文章段落内容失败", err) 66 return nil, xerr.NewErrMsgErr("获取文章段落内容失败", err)
70 } 67 }
@@ -79,110 +76,44 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU @@ -79,110 +76,44 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU
79 backup.Action = "编辑" 76 backup.Action = "编辑"
80 77
81 // 获取图片的尺寸大小 78 // 获取图片的尺寸大小
82 - images := []domain.Image{}  
83 - for _, val := range req.Images {  
84 - fInfo, _ := oss.GetImageInfo(val)  
85 - w, _ := strconv.Atoi(fInfo.ImageWidth.Value)  
86 - h, _ := strconv.Atoi(fInfo.ImageHeight.Value)  
87 - images = append(images, domain.Image{  
88 - Url: val,  
89 - Width: w,  
90 - Height: h,  
91 - })  
92 - }  
93 - //检查文章可被哪些人查看  
94 - whoRead := []int64{}  
95 - if len(req.WhoRead) > 0 {  
96 - whoRead = lo.Uniq(req.WhoRead)  
97 - var u *domain.User  
98 - for _, val := range whoRead {  
99 - u, err = l.svcCtx.UserRepository.FindOne(l.ctx, conn, val) 79 + images, err := l.getImages(req)
100 if err != nil { 80 if err != nil {
101 - return nil, xerr.NewErrMsgErr("文章可查看人设置错误", err)  
102 - }  
103 - if u.CompanyId != article.CompanyId {  
104 - return nil, xerr.NewErrMsg("文章可查看人设置错误") 81 + return nil, err
105 } 82 }
  83 + //视频
  84 + videos, err := l.getVideos(req)
  85 + if err != nil {
  86 + return nil, err
106 } 87 }
  88 + //检查文章可被哪些人查看
  89 + whoRead, err := l.validateAndGetWhoRead(req, article)
  90 + if err != nil {
  91 + return nil, err
107 } 92 }
108 //检查文章可被哪些人评论 93 //检查文章可被哪些人评论
109 whoReview := []int64{} 94 whoReview := []int64{}
110 if len(req.WhoReview) > 0 { 95 if len(req.WhoReview) > 0 {
111 whoReview = lo.Uniq(req.WhoReview) 96 whoReview = lo.Uniq(req.WhoReview)
112 } 97 }
113 - //有指定可查看人的情况  
114 - if len(whoRead) > 0 {  
115 - if len(whoReview) > 0 {  
116 - // 检查 whoRead 是否 完全包含 whoReview  
117 - ok := lo.Every(whoRead, whoReview)  
118 - if !ok {  
119 - return nil, xerr.NewErrMsg("文章可评论人设置错误")  
120 - }  
121 - }  
122 - if len(whoReview) == 0 {  
123 - //有指定可查看人 ,但未指定可评论人  
124 - return nil, xerr.NewErrMsg("文章可评论人设置错误")  
125 - }  
126 - }  
127 - //没有指定可查看人的情况  
128 - if len(whoRead) == 0 {  
129 - if len(whoReview) > 0 {  
130 - // 未指定可查看人(全员可看),有指定可评论人,  
131 - var u *domain.User  
132 - for _, val := range whoReview {  
133 - u, err = l.svcCtx.UserRepository.FindOne(l.ctx, conn, val)  
134 - if err != nil {  
135 - return nil, xerr.NewErrMsgErr("文章可评论人设置错误", err)  
136 - }  
137 - if u.CompanyId != article.CompanyId {  
138 - return nil, xerr.NewErrMsg("文章可评论人设置错误")  
139 - }  
140 - }  
141 - } 98 + //验证可评论
  99 + if err = l.validateWhoReview(whoRead, whoReview, article); err != nil {
  100 + return nil, err
142 } 101 }
143 //验证tag 102 //验证tag
144 - if len(req.Tags) > 0 {  
145 - req.Tags = lo.Uniq(req.Tags)  
146 - for _, value := range req.Tags {  
147 - t, err := l.svcCtx.ArticleTagRepository.FindOne(l.ctx, conn, value)  
148 - if err != nil {  
149 - return nil, xerr.NewErrMsgErr("文章标签设置错误", err)  
150 - }  
151 - if t.CompanyId != article.CompanyId {  
152 - return nil, xerr.NewErrMsgErr("文章标签设置错误", err)  
153 - }  
154 - } 103 + validTags := l.validateTags(req, article)
  104 + if validTags != nil {
  105 + return nil, validTags
155 } 106 }
156 article.Title = req.Title 107 article.Title = req.Title
157 article.Version = article.Version + 1 108 article.Version = article.Version + 1
158 article.Images = images 109 article.Images = images
  110 + article.Videos = videos
159 article.WhoRead = whoRead 111 article.WhoRead = whoRead
160 article.WhoReview = whoReview 112 article.WhoReview = whoReview
161 article.TargetUser = domain.ArticleTarget(req.TargetUser) 113 article.TargetUser = domain.ArticleTarget(req.TargetUser)
162 article.Tags = req.Tags 114 article.Tags = req.Tags
163 //文章内容 115 //文章内容
164 - articleSections := []domain.ArticleSection{}  
165 - sortBy := 1  
166 - lo.ForEach(req.Section, func(item types.ArticleSection, index int) {  
167 - strList := strings.Split(item.Content, "\n")  
168 - for key, value := range strList {  
169 - if value == "" {  
170 - continue  
171 - }  
172 - section := domain.ArticleSection{  
173 - CompanyId: article.CompanyId,  
174 - Version: article.Version,  
175 - ArticleId: article.Id,  
176 - Content: value,  
177 - SortBy: sortBy,  
178 - }  
179 - if key == 0 {  
180 - section.Id = item.Id  
181 - }  
182 - articleSections = append(articleSections, section)  
183 - sortBy++  
184 - }  
185 - }) 116 + articleSections := l.getSections(req, article)
186 //设置内容概要 117 //设置内容概要
187 if len(req.Section) > 0 { 118 if len(req.Section) > 0 {
188 // 截取内容 50个字 119 // 截取内容 50个字
@@ -198,7 +129,7 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU @@ -198,7 +129,7 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU
198 article.Summary = req.Section[0].Content[0:stringIndex] 129 article.Summary = req.Section[0].Content[0:stringIndex]
199 } 130 }
200 131
201 - err = transaction.UseTrans(l.ctx, conn.DB(), func(ctx context.Context, c transaction.Conn) error { 132 + err = transaction.UseTrans(l.ctx, l.conn.DB(), func(ctx context.Context, c transaction.Conn) error {
202 _, err = l.svcCtx.ArticleRepository.Update(l.ctx, c, article) 133 _, err = l.svcCtx.ArticleRepository.Update(l.ctx, c, article)
203 if err != nil { 134 if err != nil {
204 return xerr.NewErrMsgErr("保存文章失败", err) 135 return xerr.NewErrMsgErr("保存文章失败", err)
@@ -238,6 +169,11 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU @@ -238,6 +169,11 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU
238 if err != nil { 169 if err != nil {
239 return xerr.NewErrMsgErr("保存文章内容失败", err) 170 return xerr.NewErrMsgErr("保存文章内容失败", err)
240 } 171 }
  172 + //文章定性
  173 + err = l.setTags(c, article)
  174 + if err != nil {
  175 + return err
  176 + }
241 return nil 177 return nil
242 }, true) 178 }, true)
243 resp = &types.SystemArticleUpdateResponse{ 179 resp = &types.SystemArticleUpdateResponse{
@@ -251,5 +187,193 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU @@ -251,5 +187,193 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU
251 TargetUser: int(article.TargetUser), 187 TargetUser: int(article.TargetUser),
252 Tags: article.Tags, 188 Tags: article.Tags,
253 } 189 }
  190 + _ = copier.Copy(&resp.Videos, videos)
254 return 191 return
255 } 192 }
  193 +
  194 +// validateTextLimit 验证输入文本长度
  195 +func (l *SystemUpdateArticleLogic) validateTextLimit(req *types.SystemArticleUpdateRequest) error {
  196 + wordNum := 0
  197 + for i := range req.Section {
  198 + num := utf8.RuneCountInString(req.Section[i].Content)
  199 + wordNum += num
  200 + }
  201 + if wordNum >= 1000 {
  202 + return xerr.NewErrMsg("最多只能输入1000字")
  203 + }
  204 + return nil
  205 +}
  206 +
  207 +// validateAndGetWhoRead 验证并获取可阅读
  208 +func (l *SystemUpdateArticleLogic) validateAndGetWhoRead(req *types.SystemArticleUpdateRequest, article *domain.Article) ([]int64, error) {
  209 + whoRead := make([]int64, 0)
  210 + if len(req.WhoRead) > 0 {
  211 + whoRead = lo.Uniq(req.WhoRead)
  212 + var u *domain.User
  213 + var err error
  214 + for _, val := range whoRead {
  215 + u, err = l.svcCtx.UserRepository.FindOne(l.ctx, l.conn, val)
  216 + if err != nil {
  217 + return whoRead, xerr.NewErrMsgErr("文章可查看人设置错误", err)
  218 + }
  219 + if u.CompanyId != article.CompanyId {
  220 + return whoRead, xerr.NewErrMsg("文章可查看人设置错误")
  221 + }
  222 + }
  223 + }
  224 + return whoRead, nil
  225 +}
  226 +
  227 +// validateWhoReview 验证可评论
  228 +func (l *SystemUpdateArticleLogic) validateWhoReview(whoRead []int64, whoReview []int64, article *domain.Article) error {
  229 + //有指定可查看人的情况
  230 + if len(whoRead) > 0 {
  231 + if len(whoReview) > 0 {
  232 + // 检查 whoRead 是否 完全包含 whoReview
  233 + ok := lo.Every(whoRead, whoReview)
  234 + if !ok {
  235 + return xerr.NewErrMsg("文章可评论人设置错误")
  236 + }
  237 + }
  238 + if len(whoReview) == 0 {
  239 + //有指定可查看人 ,但未指定可评论人
  240 + return xerr.NewErrMsg("文章可评论人设置错误")
  241 + }
  242 + }
  243 + //没有指定可查看人的情况
  244 + if len(whoRead) == 0 {
  245 + if len(whoReview) > 0 {
  246 + // 未指定可查看人(全员可看),有指定可评论人,
  247 + var u *domain.User
  248 + var err error
  249 + for _, val := range whoReview {
  250 + u, err = l.svcCtx.UserRepository.FindOne(l.ctx, l.conn, val)
  251 + if err != nil {
  252 + return xerr.NewErrMsgErr("文章可评论人设置错误", err)
  253 + }
  254 + if u.CompanyId != article.CompanyId {
  255 + return xerr.NewErrMsg("文章可评论人设置错误")
  256 + }
  257 + }
  258 + }
  259 + }
  260 + return nil
  261 +}
  262 +
  263 +// validateTags 验证标签
  264 +func (l *SystemUpdateArticleLogic) validateTags(req *types.SystemArticleUpdateRequest, article *domain.Article) error {
  265 + if len(req.Tags) > 0 {
  266 + req.Tags = lo.Uniq(req.Tags)
  267 + for _, value := range req.Tags {
  268 + t, err := l.svcCtx.ArticleTagRepository.FindOne(l.ctx, l.conn, value)
  269 + if err != nil {
  270 + return xerr.NewErrMsgErr("文章标签设置错误", err)
  271 + }
  272 + if t.CompanyId != article.CompanyId {
  273 + return xerr.NewErrMsgErr("文章标签设置错误", err)
  274 + }
  275 + }
  276 + }
  277 + return nil
  278 +}
  279 +
  280 +// getImages 获取图片信息
  281 +func (l *SystemUpdateArticleLogic) getImages(req *types.SystemArticleUpdateRequest) ([]domain.Image, error) {
  282 + // 获取图片的尺寸大小
  283 + images := make([]domain.Image, 0)
  284 + for _, val := range req.Images {
  285 + fInfo, err := oss.GetImageInfo(val)
  286 + if err != nil {
  287 + return images, xerr.NewErrMsg("获取图片失败")
  288 + }
  289 + w, _ := strconv.Atoi(fInfo.ImageWidth.Value)
  290 + h, _ := strconv.Atoi(fInfo.ImageHeight.Value)
  291 + images = append(images, domain.Image{
  292 + Url: val,
  293 + Width: w,
  294 + Height: h,
  295 + })
  296 + }
  297 + return images, nil
  298 +}
  299 +
  300 +// getVideo 获取视频信息
  301 +func (l *SystemUpdateArticleLogic) getVideos(req *types.SystemArticleUpdateRequest) ([]domain.Video, error) {
  302 + videos := make([]domain.Video, 0)
  303 + if len(req.Videos) > 0 {
  304 + for _, item := range req.Videos {
  305 + cover, w, h, err := oss.GetVideoCover(item.Url)
  306 + if err != nil {
  307 + return videos, xerr.NewErrMsg("获取视频信息失败")
  308 + }
  309 + videos = append(videos, domain.Video{
  310 + Url: item.Url,
  311 + Cover: cover,
  312 + Width: w,
  313 + Height: h,
  314 + })
  315 + }
  316 + }
  317 + return videos, nil
  318 +}
  319 +
  320 +func (l *SystemUpdateArticleLogic) getSections(req *types.SystemArticleUpdateRequest, article *domain.Article) []domain.ArticleSection {
  321 + articleSections := make([]domain.ArticleSection, 0)
  322 + sortBy := 1
  323 + lo.ForEach(req.Section, func(item types.ArticleSection, index int) {
  324 + strList := strings.Split(item.Content, "\n")
  325 + for key, value := range strList {
  326 + if value == "" {
  327 + continue
  328 + }
  329 + section := domain.ArticleSection{
  330 + CompanyId: article.CompanyId,
  331 + Version: article.Version,
  332 + ArticleId: article.Id,
  333 + Content: value,
  334 + SortBy: sortBy,
  335 + }
  336 + if key == 0 {
  337 + section.Id = item.Id
  338 + }
  339 + articleSections = append(articleSections, section)
  340 + sortBy++
  341 + }
  342 + })
  343 + return articleSections
  344 +}
  345 +
  346 +// setTags 设置定性标签
  347 +func (l *SystemUpdateArticleLogic) setTags(conn transaction.Conn, article *domain.Article) error {
  348 + _, oldTags, err := l.svcCtx.ArticleAndTagRepository.Find(l.ctx, conn, domain.NewQueryOptions().WithFindOnly().WithKV("articleId", article.Id))
  349 + if err != nil {
  350 + return xerr.NewErrMsgErr("检查文章的标签失败", err)
  351 + }
  352 + //删除旧标签
  353 + for _, v := range oldTags {
  354 + _, err = l.svcCtx.ArticleAndTagRepository.Delete(l.ctx, conn, v)
  355 + if err != nil {
  356 + return xerr.NewErrMsg(err.Error())
  357 + }
  358 + }
  359 + if len(article.Tags) > 0 {
  360 + for _, tagId := range article.Tags {
  361 + articleTag := &domain.ArticleAndTag{
  362 + CompanyId: article.CompanyId,
  363 + ArticleId: article.Id,
  364 + TagId: tagId,
  365 + }
  366 + _, err = l.svcCtx.ArticleAndTagRepository.Insert(l.ctx, conn, articleTag)
  367 + if err != nil {
  368 + return xerr.NewErrMsg(err.Error())
  369 + }
  370 + }
  371 + //发送定性通知
  372 + messageLogic := message.NewMiniSystemLogic(l.ctx, l.svcCtx)
  373 + err = messageLogic.ArticleDefined(conn, article.CompanyId, article.AuthorId, article.Title)
  374 + if err != nil {
  375 + return xerr.NewErrMsg(err.Error())
  376 + }
  377 + }
  378 + return nil
  379 +}
@@ -827,9 +827,9 @@ type Location struct { @@ -827,9 +827,9 @@ type Location struct {
827 827
828 type Video struct { 828 type Video struct {
829 Url string `json:"url"` //视频文件的地址 829 Url string `json:"url"` //视频文件的地址
830 - Cover string `json:"cover"` //封面  
831 - Width int `json:"width"` //封面图片宽  
832 - Height int `json:"height"` //封面图片长 830 + Cover string `json:"cover,optional"` //封面
  831 + Width int `json:"width,optional"` //封面图片宽
  832 + Height int `json:"height,optional"` //封面图片长
833 } 833 }
834 834
835 type ArticleAuthor struct { 835 type ArticleAuthor struct {