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