inleft
2022-08-31 aae48957ba971ed0a1bfbfa182701cd22bbe8694
commit | author | age
0613f2 1 /*
I 2 Copyright [2020] [https://www.xiaonuo.vip]
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8   http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15
16 Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
17
18 1.请不要删除和修改根目录下的LICENSE文件。
19 2.请不要删除和修改Snowy源码头部的版权声明。
20 3.请保留源码和相关描述文件的项目出处,作者声明等。
21 4.分发源码时候,请注明软件出处 https://gitee.com/xiaonuobase/snowy
22 5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/xiaonuobase/snowy
23 6.若您的项目无法满足以上几点,可申请商业授权,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
24  */
25 package vip.xiaonuo.modular.blogarticle.controller;
26
bd3bc1 27 import cn.hutool.core.bean.BeanUtil;
dc050f 28 import cn.hutool.core.collection.CollUtil;
ba780f 29 import cn.hutool.core.date.DateUnit;
31e475 30 import cn.hutool.core.date.DateUtil;
0613f2 31 import cn.hutool.core.util.PageUtil;
I 32 import cn.hutool.core.util.StrUtil;
33 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
20e5fc 34 import lombok.extern.slf4j.Slf4j;
552004 35 import org.springframework.validation.annotation.Validated;
I 36 import org.springframework.web.bind.annotation.*;
0613f2 37 import vip.xiaonuo.core.annotion.BusinessLog;
bd3bc1 38 import vip.xiaonuo.core.consts.MyConstant;
dc050f 39 import vip.xiaonuo.core.consts.SymbolConstant;
cfde48 40 import vip.xiaonuo.core.context.constant.ConstantContextHolder;
0613f2 41 import vip.xiaonuo.core.enums.LogAnnotionOpTypeEnum;
bd3bc1 42 import vip.xiaonuo.core.exception.BlogException;
I 43 import vip.xiaonuo.core.exception.enums.BlogExceptionEnum;
0613f2 44 import vip.xiaonuo.core.pojo.response.ResponseData;
I 45 import vip.xiaonuo.core.pojo.response.SuccessResponseData;
bd3bc1 46 import vip.xiaonuo.modular.blogarticle.entity.BlogArticle;
ba780f 47 import vip.xiaonuo.modular.blogarticle.entity.BlogArticleVo;
552004 48 import vip.xiaonuo.modular.blogarticle.param.BlogArticleAddDto;
0613f2 49 import vip.xiaonuo.modular.blogarticle.param.BlogArticleQueryDto;
I 50 import vip.xiaonuo.modular.blogarticle.service.BlogArticleService;
552004 51 import vip.xiaonuo.modular.blogarticletype.entity.BlogArticleType;
I 52 import vip.xiaonuo.modular.blogarticletype.service.BlogArticleTypeService;
cfde48 53 import vip.xiaonuo.sys.modular.file.entity.SysFileInfo;
I 54 import vip.xiaonuo.sys.modular.file.service.SysFileInfoService;
0613f2 55
I 56 import javax.annotation.Resource;
dc050f 57 import java.util.*;
20e5fc 58 import java.util.concurrent.Future;
dc050f 59 import java.util.function.Function;
0613f2 60 import java.util.stream.Collectors;
I 61
62 /**
63  * blog文章控制器 (提供给外部blog系统查询)
64  *
65  * @author inleft
66  * @date 2022-02-09 18:20:22
67  */
68 @RestController
69 @RequestMapping("/outside")
20e5fc 70 @Slf4j
0613f2 71 public class BlogArticleOutsideController {
I 72
73     @Resource
74     private BlogArticleService blogArticleService;
75
cfde48 76
I 77     @Resource
552004 78     private BlogArticleTypeService blogArticleTypeService;
I 79
80     @Resource
cfde48 81     private SysFileInfoService fileInfoService;
552004 82
I 83     @PostMapping("/blogArticle/add")
84     @BusinessLog(title = "外部blog系统_blog文章_增加", opType = LogAnnotionOpTypeEnum.ADD)
85     public ResponseData add(@RequestBody @Validated(BlogArticleAddDto.add.class) BlogArticleAddDto addDto) {
aae489 86         if (!addDto.getSecret().equals(ConstantContextHolder.getPushCode())) {
552004 87             throw new BlogException("口令错误..");
I 88         }
89
90         if (MyConstant.Yes.equals(addDto.getIsTop()) && addDto.getTopValue() == null) {
91             throw new BlogException("选择了置顶需要指定置顶值..");
92         }
93
94         if (addDto.getIsLock().equals(MyConstant.Yes)) {
95             if (addDto.getAuthStatus().equals(MyConstant.AuthStatus.authCode) && StrUtil.isEmpty(addDto.getAuthPassword())) {
96                 throw new BlogException("选择了密码授权,密码不能为空");
97             }
98         } else {
99             addDto.setAuthPassword(null);
100         }
101
102         if (MyConstant.Yes.equals(addDto.getIsOnline())) {
103             if (addDto.getArticleFileId() == null || fileInfoService.getById(addDto.getArticleFileId()) == null) {
104                 throw new BlogException("已选择在线模式..文件id非法");
105             }
106         } else {
107             if (StrUtil.isEmpty(addDto.getContent())) {
108                 throw new BlogException("已选择在线模式..文件内容非法");
109             }
110         }
111
112         if (addDto.getCoverFileId() != null && fileInfoService.getById(addDto.getCoverFileId()) == null) {
113             throw new BlogException("封面文件id非法");
114         }
115
116         if (blogArticleTypeService.lambdaQuery()
117                 .eq(BlogArticleType::getIsEnable, MyConstant.Yes)
118                 .eq(BlogArticleType::getId, addDto.getArticleTypeId())
119                 .one() == null) {
120             throw new BlogException("分类id非法");
121         }
122
123         if (addDto.getPublishDate() == null) {
124             addDto.setPublishDate(new Date());
125         }
126
127         BlogArticle article = new BlogArticle();
128         BeanUtil.copyProperties(addDto, article);
31e475 129         article.setSeparateYear(DateUtil.year(article.getPublishDate()));
ba780f 130         article.setSeparateMonth(DateUtil.month(article.getPublishDate()) + 1);
31e475 131         article.setSeparateDay(DateUtil.dayOfMonth(article.getPublishDate()));
I 132
133         article.setIsEnable(MyConstant.Yes);
134         blogArticleService.save(article);
552004 135         return new SuccessResponseData();
I 136     }
cfde48 137
0613f2 138     /**
I 139      * 查询blog文章
140      *
141      * @author inleft
142      * @date 2022-02-09 18:20:22
143      */
144     @GetMapping("/blogArticle/queryBlogArticleList")
145     @BusinessLog(title = "外部blog系统_blog文章_查询", opType = LogAnnotionOpTypeEnum.QUERY)
146     public ResponseData queryBlogArticleList(BlogArticleQueryDto queryDto) {
147
148
149         Map<String, Object> param = new HashMap<>(16);
150         param.put("pageNo", PageUtil.getStart(queryDto.getPageNo() - 1, queryDto.getPageSize()));
151         param.put("pageSize", queryDto.getPageSize());
a9c4c9 152         param.put("typeId", queryDto.getTypeId());
d80267 153         param.put("fileType", queryDto.getFileType());
fae101 154         param.put("faceExcludeFile", MyConstant.faceExcludeFile);
0613f2 155
cfde48 156         String blogSourcePrefix = ConstantContextHolder.getBlogSourcePrefix();
ba780f 157
I 158         Date now = DateUtil.date();
159         //空类型查询条件,排除笔记系列,按更新时间倒序
160         //含有类型查询,按发布时间倒序
a9c4c9 161         List<BlogArticleVo> resList = blogArticleService.searchList(param).stream().map(e -> {
504927 162             if (StrUtil.isNotEmpty(e.getCoverFileURL())) {
I 163                 if (!e.getCoverFileURL().startsWith("http")) {
164                     //补上访问参数
cfde48 165                     e.setCoverFileURL(blogSourcePrefix + e.getCoverFileURL());
504927 166                 }
0613f2 167             }
ba780f 168
20e5fc 169             //前端根据条件标注小红点(发布时间小于更新时间,且在7天内)
ba780f 170             if (e.getPublishDate().before(e.getUpdateDate())
I 171                     && DateUtil.between(e.getUpdateDate(), now, DateUnit.DAY) <= 7) {
172                 e.setIsAnyUpdate(MyConstant.Yes);
173             } else {
174                 e.setIsAnyUpdate(MyConstant.No);
175             }
176
0613f2 177             return e;
I 178         }).collect(Collectors.toList());
179
a9c4c9 180         long count = blogArticleService.searchListCount(param);
0613f2 181
I 182         Page<BlogArticleVo> queryPage = new Page<>(queryDto.getPageNo(), queryDto.getPageSize());
183         queryPage.setRecords(resList);
184         queryPage.setTotal(count);
185
186         return new SuccessResponseData(queryPage);
187     }
188
dc050f 189
I 190     /**
191      * 查询blog文章(月台专用列表)
192      *
193      * @author inleft
194      * @date 2022-02-09 18:20:22
195      */
196     @GetMapping("/blogArticle/platform")
197     @BusinessLog(title = "外部blog系统_blog月台_查询", opType = LogAnnotionOpTypeEnum.QUERY)
198     public ResponseData platform(BlogArticleQueryDto queryDto) {
199
200         Map<String, Object> param = new HashMap<>(16);
201         param.put("pageNo", PageUtil.getStart(queryDto.getPageNo() - 1, queryDto.getPageSize()));
202         param.put("pageSize", queryDto.getPageSize());
fae101 203         param.put("id", queryDto.getId());
dc050f 204
fae101 205         if (queryDto.getActiveKey().equals(MyConstant.platformType.type_1)) {
I 206             param.put("typeIds", new Long[]{66L});//临时id
207             param.put("fileType", MyConstant.FileType.fileTypeVideo_3);
208         } else if (queryDto.getActiveKey().equals(MyConstant.platformType.type_2)) {
209             param.put("typeIds", new Long[]{55L});//临时id,后续需要修改(前方高能分类)
dc050f 210             param.put("fileType", MyConstant.FileType.fileTypeVideo_3);
I 211         } else if (queryDto.getActiveKey().equals(MyConstant.platformType.type_3)) {
fae101 212             param.put("typeIds", new Long[]{99L});//临时id,后续需要修改(图组)
I 213             param.put("fileType", MyConstant.FileType.fileTypePictures_5);
dc050f 214         } else {
fae101 215             param.put("typeIds", new Long[]{66L});//临时id,后续需要修改(音乐分类)
dc050f 216             param.put("fileType", MyConstant.FileType.fileTypeVideo_3);
I 217         }
218
219         String blogSourcePrefix = ConstantContextHolder.getBlogSourcePrefix();
220
221         //空类型查询条件,排除笔记系列,按更新时间倒序
222         //含有类型查询,按发布时间倒序
223         List<BlogArticleVo> resList = blogArticleService.searchPlatformList(param).stream().map(e -> {
224             if (StrUtil.isNotEmpty(e.getCoverFileURL())) {
225                 if (!e.getCoverFileURL().startsWith("http")) {
226                     //补上访问参数
227                     e.setCoverFileURL(blogSourcePrefix + e.getCoverFileURL());
228                 }
229             }
230
231             //补充视频组,图片组的url
232             if (StrUtil.isNotEmpty(e.getPictureIds())) {
233                 e.setPictureUrlList(this.getBlogSourceURLBatch(Arrays.stream(e.getPictureIds().split(SymbolConstant.COMMA)).collect(Collectors.toList())));
234             }
235
236             return e;
237         }).collect(Collectors.toList());
238
239         long count = blogArticleService.searchPlatformListCount(param);
240
241         Page<BlogArticleVo> queryPage = new Page<>(queryDto.getPageNo(), queryDto.getPageSize());
242         queryPage.setRecords(resList);
243         queryPage.setTotal(count);
244
245         return new SuccessResponseData(queryPage);
246     }
247
bd3bc1 248     @GetMapping("/blogArticle/queryBlogArticleDetail")
I 249     @BusinessLog(title = "外部blog系统_blog文章详情_查询", opType = LogAnnotionOpTypeEnum.QUERY)
250     public ResponseData queryBlogArticleDetail(BlogArticleQueryDto queryDto) {
251         BlogArticle find = blogArticleService.lambdaQuery()
252                 .eq(BlogArticle::getIsEnable, MyConstant.Yes)
253                 .eq(BlogArticle::getEditorStatus, MyConstant.Yes)
254                 .eq(BlogArticle::getId, queryDto.getId())
255                 .one();
256
257         if (find == null) {
258             throw new BlogException(BlogExceptionEnum.article_not_found);
259         }
260
261         //加密文章
262         if (find.getAuthStatus().equals(MyConstant.AuthStatus.authCode)) {
263             //授权码缺失
264             if (StrUtil.isEmpty(queryDto.getAuthWord())) {
265                 throw new BlogException(BlogExceptionEnum.article_auth_error);
266             }
267             //授权码比对
88f419 268             if (!find.getAuthPassword().equals(queryDto.getAuthWord())) {
bd3bc1 269                 throw new BlogException(BlogExceptionEnum.article_auth_pass_error);
I 270             }
cfde48 271         } else if (find.getAuthStatus().equals(MyConstant.AuthStatus.privateCode)) {
bd3bc1 272             throw new BlogException(BlogExceptionEnum.article_auth_private_error);
I 273         }
274
20e5fc 275         //异步查询相邻记录
I 276         Future<List<BlogArticleVo>> adjoiningRecord = blogArticleService.getAdjoiningRecord(queryDto);
277
bd3bc1 278         BlogArticleVo vo = new BlogArticleVo();
I 279
280         BeanUtil.copyProperties(find, vo);
281
fae101 282         //补充视频组,图片组的url
I 283         if (StrUtil.isNotEmpty(vo.getPictureIds())) {
284             vo.setPictureUrlList(this.getBlogSourceURLBatch(Arrays.stream(vo.getPictureIds().split(SymbolConstant.COMMA)).collect(Collectors.toList())));
285         }
286         if (StrUtil.isNotEmpty(vo.getVideoIds())) {
287             vo.setVideoUrlList(this.getBlogSourceURLBatch(Arrays.stream(vo.getVideoIds().split(SymbolConstant.COMMA)).collect(Collectors.toList())));
288         }
289
31e475 290
e99de8 291         String tempURL = this.getBlogSourceURL(find.getArticleFileId());
cfde48 292
c49fa0 293         //if (StrUtil.isEmpty(tempURL))
20e5fc 294         //throw new BlogException(BlogExceptionEnum.article_file_lose);
e99de8 295
I 296         vo.setArticleFileURL(tempURL);
ff14c4 297         vo.setCoverFileURL(this.getBlogSourceURL(vo.getCoverFileId()));
20e5fc 298
I 299         while (!adjoiningRecord.isDone()) {
300             try {
1e152b 301                 Thread.sleep(50);
20e5fc 302             } catch (InterruptedException e) {
I 303             }
304         }
305
306         try {
307             vo.setPreviousRecord(adjoiningRecord.get().get(0));
308             vo.setNextRecord(adjoiningRecord.get().get(1));
309         } catch (Exception e) {
310             log.error("异步获取上下相邻日志id异常,id:{} ,msg:{}", queryDto.getId(), e.getMessage());
311         }
312
bd3bc1 313         return new SuccessResponseData(vo);
I 314     }
315
cfde48 316     private String getBlogSourceURL(Long fileId) {
I 317         SysFileInfo sysFileInfo = fileInfoService.getById(fileId);
318         if (sysFileInfo == null) {
319             return null;
320         } else {
321             String blogSourcePrefix = ConstantContextHolder.getBlogSourcePrefix();
e99de8 322             return blogSourcePrefix + sysFileInfo.getFileBucket() + "/" + sysFileInfo.getFileObjectName();
cfde48 323         }
I 324     }
0613f2 325
dc050f 326     private List<String> getBlogSourceURLBatch(List<String> fileIds) {
I 327         Map<String, SysFileInfo> sysFileInfoMap = fileInfoService.listByIds(fileIds).stream().collect(Collectors.toMap(e -> e.getId().toString(), Function.identity(), (k1, k2) -> k1));
328         if (CollUtil.isEmpty(sysFileInfoMap)) {
329             return null;
330         } else {
331             List<String> urlList = new ArrayList<>(fileIds.size());
332             String blogSourcePrefix = ConstantContextHolder.getBlogSourcePrefix();
333
334             SysFileInfo sysFileInfo;
335             for (String fileId : fileIds) {
336                 sysFileInfo = sysFileInfoMap.getOrDefault(fileId, null);
337                 if (sysFileInfo == null) {
338                     urlList.add(null);
339                 } else {
340                     urlList.add(blogSourcePrefix + sysFileInfo.getFileBucket() + "/" + sysFileInfo.getFileObjectName());
341                 }
342             }
343             return urlList;
344         }
345     }
346
0613f2 347 }