@Slf4j
@Transactional
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {
/**
* 查询文章
*
* @param dto
* @return
*/
@Override
public PageResponseResult findList(WmNewsPageReqDto dto) {
//0.检查参数
//分页检查
dto.checkParam();
//1.分页条件查询(其他条件查询时,查询出的内容都要实现分页功能!) :page,pageSize
// IPage page = new Page(dto.getPage(), dto.getSize());
Page page = new Page(dto.getPage(), dto.getSize()); //传入分页条件
//创建条件构造器对象
LambdaQueryWrapper<WmNews> lambdaQueryWrapper = new LambdaQueryWrapper();
//2.页面可选的条件查询
//2.1 文章状态查询
if (dto.getStatus() != null) {
lambdaQueryWrapper.eq(WmNews::getStatus, dto.getStatus());
}
//2.2 关键字查询(模糊查询)
// if (dto.getKeyword() != null){
if (StringUtils.isNotBlank(dto.getKeyword())) {
lambdaQueryWrapper.like(WmNews::getTitle, dto.getKeyword());
}
//2.3 频道查询(精确查询)
if (dto.getChannelId() != null) {
lambdaQueryWrapper.eq(WmNews::getChannelId, dto.getChannelId());
}
//2.4 发布日期查询(日期范围)
if (dto.getBeginPubDate() != null && dto.getEndPubDate() != null) {
lambdaQueryWrapper.between(WmNews::getPublishTime, dto.getBeginPubDate(), dto.getEndPubDate());
}
//3. 根据当前登录用户的用户id查询(通过任何条件的查询都是查询当前登录用户的文章信息.)
lambdaQueryWrapper.eq(WmNews::getUserId, WmThreadLocal.getUser().getId());
//4. 根据发布时间倒序查询
lambdaQueryWrapper.orderByDesc(WmNews::getPublishTime);
page = page(page, lambdaQueryWrapper);
//返回结果(将查询到的结果封装为一个PageResponseResult对象并返回.)
PageResponseResult pageResponseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int) page.getTotal());
pageResponseResult.setData(page.getRecords());
return pageResponseResult;
}
@Autowired
private WmNewsMaterialMapper wmNewsMaterialMapper;
@Autowired
private WmMaterialMapper wmMaterialMapper;
/**
* 提交发布文章
*
* @param //dto
* @return
*/
@Override
public ResponseResult submitNews(WmNewsDto dto) {
//0 条件判断,判断文章是否为空,根据dto准备文章数据.
if (dto == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
}
//1.保存或修改文章(提交文章或保存为草稿)
//新建一个文章对象,拷贝dto中的内容到该对象
WmNews wmNews = new WmNews();
//复制对象的属性值,属性拷贝--->属性名称和类型相同时才能拷贝.
BeanUtils.copyProperties(dto, wmNews); //将dto中的内容全部封装进文章对象wmNews中.
// 此时dto中的images和wmNews中的images类型不一样,不可直接拷贝,需要将结合中的元素拼接为一个完整字符串以后才能拷贝.
//2.图片的拷贝 List--->String
//[abc.png,def.png]--->"abc.png,def.png"
if (dto.getImages() != null && dto.getImages().size() > 0) {
// List
// String imageStr = StringUtils.join(imageList, ",");
String imageStr = StringUtils.join(dto.getImages(), ",");
wmNews.setImages(imageStr); // 这里只是将imageStr这个字符串拷贝给wmNews的images,而不是拷贝给content,content需要进行后续业务逻辑处理.
}
//1.3 补全该WmNews对象的其他属性
wmNews.setUserId(WmThreadLocal.getUser().getId()); //从本地线程中获取当前用户的id.
wmNews.setCreatedTime(new Date()); //创建时间为当前时间
wmNews.setSubmitedTime(new Date()); //提交时间为当前时间
//默认上架 0下架 1上架
wmNews.setEnable(1);
//2 判断该文章是否已经存在id
if (dto.getId() == null) {
//2.1 不存在id 新增文章业务
this.save(wmNews);
//或者
// save(wmNews);
} else {
//2.2 存在id 修改文章业务
//删除原来的文章图片和素材的关系
// wmNewsMaterialMapper.delete(Wrappers.lambdaQuery(WmNewsMaterial.class)
// .eq(WmNewsMaterial::getNewsId, wmNews.getId()));
wmNewsMaterialMapper.delete(Wrappers.
//修改文章(更新该WmNews对象中的信息)
this.updateById(wmNews);
}
//以上不管是修改文章还是新增文章,都要判断下一步是否要保存为草稿.
//3 判断是否要保存为草稿
// status状态 草稿为0 提交为1
// if (dto.getStatus()==0)
// if (dto.getStatus().equals(0))
if (dto.getStatus().equals(WmNews.Status.NORMAL.getCode())) {
//是草稿,操作结束,返回结果
return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}
//4 如果不是要保存为草稿,①保存文章内容和素材的关系,②保存文章封面的图片和素材的关系
//4.1 保存文章内容和图片素材的关系,此时要获取到文章内容content
// 如果选择文章封面类型为自动,则根据规则展示封面图片.如果不是选择为自动,则需要另外上传图片作为封面内容来展示.
// 只需要对类型选择为自动的情况下进行业务逻辑处理.
//type 文章封面类型 0 无图 1 单图 3 多图 -1 自动
//文章发布页面的内容填写完毕后,当用户点击发布或者保存为草稿时,此时dto会出纳递给控制层,到业务层时,进行一系列处理,将dto数据以及要补全的数据打包为一个json数据对象,然后进行其他的业务逻辑处理,将对应的结果响应在页面中.
//**************获取文章内容中的图片信息.用于关联保存文章内容和图片素材的关系***************
/*
TODO: 前端将用户发布文章时填写的数据一起封装为一个WmNewsDto对象,然后将该对象传给控制层!
TODO: 此时可通过在controller层打印输出dto的内容等方式,查看此时前端传过来的dto的数据类型:
查看此时WmNewsDto的数据类型,dto中的内容为:(可以看出该对象的content内容的类型和格式!)
小括号中的内容为该对象的所有内容:
WmNewsDto(
id=null,
title=一只小猫咪,
channelId=2,
labels=小猫,
publishTime=Sat Jul 01 13:24:33 CST 2023,
content=[
{"type":"text","value":"在这只小猫咪前面的内容"},
{"type":"image","value":"http://192.168.200.128:9000/leadnews/2023/06/29/9b3266e2e86b414d8d732d1b9c914c9e.jpg"},
{"type":"text","value":"在这只小猫咪后面的内容"},
{"type":"image","value":"http://192.168.200.128:9000/leadnews/2023/06/29/df3b9b4dbb6542229f8d8b21fb3df935.jpg"},
{"type":"text","value":"这是正文内容"}
],
type=3,
submitedTime=null,
status=1,
images=[
http://192.168.200.128:9000/leadnews/2023/06/29/a9eb7a51db1a45ac86355e21e0241a26.jpg,
http://192.168.200.128:9000/leadnews/2023/06/29/ad75bf803ffe43fcb57190462d747b45.jpg,
http://192.168.200.128:9000/leadnews/2023/06/29/6f81043f40a340c2bde6e30c43f32ced.jpg
]
)
*/
//创建一个文章内容列表,用于保存从dto中获取的图片素材信息.
List<String> contentImages = new ArrayList<>();
//获取dto中的图片内容,用于下面的业务逻辑处理.
List<String> dtoImages = dto.getImages();
//4.2 判断内容content是否存在(content是否为空!),只有内容不为空的情况下,才能对文章进行"存入草稿"或者"提交审核"操作.
// String dtoContent = dto.getContent();
if (StringUtils.isNotBlank(dto.getContent())) {
List
//4.3 保存文章内容和图片素材的关系
saveWmNewsMaterial(contentImages, wmNews.getId(), WemediaConstants.WM_CONTENT_REFERENCE);
//4.4 保存文章封面和图片素材的关系
//获取文章封面的图片
//图片封面类型为自动时,此时不需要用户上传任何封面图片,dto里的images=[]或者说dto.getImages(),即dtoImages=[].
if (dto.getType() == -1) {
if (contentImages.size() >= 3) {
//如果内容中的图片数量大于等于3--->三图
wmNews.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);
//设置封面的图片
dtoImages = contentImages.subList(0, 3); //将文章内容里的前三张图片设置为封面图片.
} else if (contentImages.size() >= 1) {
//如果内容中的图片数量大于等于1 一图
wmNews.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);
//images.addAll(contentImages.subList(0, 1));
dtoImages = Arrays.asList(contentImages.get(0));
} else {
//如果其他情况:无图
wmNews.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);
}
}
//如果选择的封面类型不是自动时,此时需要用户上传封面图片,dto里的images=[?,?,...]或者说dto.getImages(),即dtoImages=[?,?,...].
//此时可选择为无图,单图或者三图.dtoImages里的图片即为封面图片.
//处理封面图片判断图片是存在的,若存在,将图片的地址(字符串String类型)赋给wmNews对象展示为前端页面的封面图片.
//实体类WmNews中的images里面存放的就是用于展示在封面的图片的url地址,多个url对应多个封面图片.
if (CollectionUtils.isNotEmpty(dtoImages)) {
// 把list转为String
wmNews.setImages(StringUtils.join(dtoImages, ","));
}
//更新自媒体文章
this.updateById(wmNews);
//调用方法保存文章封面图片和素材的关系
saveWmNewsMaterial(dtoImages, wmNews.getId(), WemediaConstants.WM_COVER_REFERENCE);
//返回结果
return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}
/**
* 批量保存自媒体文章和素材的关系
*
* @param //imageList 图片的地址 用来反查素材id
* @param //wmNewsId 自媒体文章id
* @param //type 引用类型 0 内容引用 1 主图引用
*/
private ResponseResult saveWmNewsMaterial(List<String> imageList, Integer wmNewsId, Integer type) {
//1. 判断集合是否为空
if (CollectionUtils.isEmpty(imageList)) {
return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
}
//2. 根据图片的url地址,反查素材的id
List<Integer> ids = new ArrayList<>();
for (String url : imageList) {
Integer id = wmMaterialMapper.selectOne(Wrappers.lambdaQuery(WmMaterial.class)
.eq(WmMaterial::getUrl, url)).getId();
ids.add(id);
}
//3. 遍历素材id,创建文章素材关系对象的列表,批量保存文章素材关系.
List<WmNewsMaterial> list = new ArrayList<>();
for (Integer id : ids) {
WmNewsMaterial wmNewsMaterial = new WmNewsMaterial();
wmNewsMaterial.setMaterialId(id);//素材id
wmNewsMaterial.setNewsId(wmNewsId);//文章id
wmNewsMaterial.setType(type); // 引用类型---> 内容引用/主图引用
list.add(wmNewsMaterial);
}
wmNewsMaterialMapper.saveBatch(list);
return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}
}