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