前言
衔接《黑马点评》项目学习3:自媒体素材与文章管理,进行发布文章部分的实现
一、需求分析
1.文章标题
2.文章内容:
包含文本输入(直接输入)和图片输入(素材库、本地),且含有修改删除功能
3.文章标签、频道分类
4.文章定时发布
5.文章封面图片
单图,三图,无图,自动:
选择为自动时,文章内容的图片作为封面图片,匹配规则是:
内容中无图:无图
内容中图片(1,3):单图
内容中图片(3,+∞):三图
6.按钮选择
存入草稿/提交审核。
二、表结构设计
首先需要wm_news表,已经在前面的项目里设计好了;



三、接口定义


四、功能实现
内容一致化较为明显,这里只粘贴主要功能代码:
/**
* 发布修改文章或保存为草稿
* @param dto
* @return
*/
@Override
public ResponseResult submitNews(WmNewsDto dto) {
//0.条件判断
if(dto == null || dto.getContent() == null){
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
}
//1.保存或修改文章
WmNews wmNews = new WmNews();
//属性拷贝,属性名称和类型相同时才能拷贝
BeanUtils.copyProperties(dto, wmNews);
//封面图片 list --> string
if(dto.getImages() != null && dto.getImages().size() > 0) {
String imageStr = org.apache.commons.lang3.StringUtils.join(dto.getImages(), ",");
wmNews.setImages(imageStr);
}
//如果当前封面类型为自动 -1
if(dto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)) {
wmNews.setType(null);
}
saveOrUpdateWmNews(wmNews);
//2.判断是否为草稿,如果为草稿结束当前方法
if(dto.getStatus().equals(WmNews.Status.NORMAL.getCode())){
return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}
//3.不是草稿,保存文章内容图片与素材的关系
//获取文章内容中的图片信息
List<String> materials = ectractUrlInfo(dto.getContent());
saveRelativeInfoForContent(materials, wmNews.getId());
//4.不是草稿,保存文章封面图片与素材的关系,如果当前布局是自动,需要匹配封面图片
saveRelativeInfoForCover(dto, wmNews, materials);
return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}
/**
* 1.如果当前封面类型为自动,则设置封面类型的数据
* 匹配规则:
* 内容图片(1,3) 单图 type 1
* 内容图片(3,+∞) 多图 type 3
* 没有图片 无图 type 0
* 2.保存封面图片与素材的关系
* @param dto
* @param wmNews
* @param materials
*/
private void saveRelativeInfoForCover(WmNewsDto dto, WmNews wmNews, List<String> materials) {
List<String> images = dto.getImages();
//如果当前封面类型为自动,则设置封面类型的数据
if(dto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)){
if(materials.size() >= 3){
//多图
wmNews.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);
images = materials.stream().limit(3).collect(Collectors.toList());
}else if (materials.size() >= 1 && materials.size() < 3){
//单图
wmNews.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);
images = materials.stream().limit(1).collect(Collectors.toList());
}else {
//无图
wmNews.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);
}
//修改文章
if(images != null && images.size() > 0){
wmNews.setImages(StringUtils.join(images,","));
}
updateById(wmNews);
}
//保存封面图片与素材的关系
if(images != null && images.size() > 0){
saveRelativeInfo(images, wmNews.getId(), WemediaConstants.WM_COVER_REFERENCE);
}
}
/**
* 处理文章内容与素材的关系
* @param materials
* @param newsId
*/
private void saveRelativeInfoForContent(List<String> materials, Integer newsId) {
saveRelativeInfo(materials, newsId, WemediaConstants.WM_CONTENT_REFERENCE);
}
@Autowired
private WmMaterialMapper wmMaterialMapper;
/**
* 保存文章图片与素材关系到数据库中
* @param materials
* @param newsId
* @param type
*/
private void saveRelativeInfo(List<String> materials, Integer newsId, Short type) {
if(materials != null && !materials.isEmpty()){
//通过图片的url查询图片的id
List<WmMaterial> dbMaterials = wmMaterialMapper.selectList(Wrappers
.<WmMaterial>lambdaQuery().in(WmMaterial::getUrl, materials));
//判断素材是否有效
if(dbMaterials == null || dbMaterials.size() == 0){
//手动抛出异常 1:提示调用者素材失效了;2:进行数据的回滚
throw new CustomException(AppHttpCodeEnum.MATERIAL_REFERENCE_FAIL);
}
if(dbMaterials.size() != materials.size()){
throw new CustomException(AppHttpCodeEnum.MATERIAL_REFERENCE_FAIL);
}
List<Integer> dbList = dbMaterials.stream().map(WmMaterial::getId).collect(Collectors.toList());
//批量保存
wmNewsMaterialMapper.saveRelations(dbList, newsId, type);
}
}
/**
* 提取文章中的内容信息
* @param content
* @return
*/
private List<String> ectractUrlInfo(String content){
List<String> materials = new ArrayList<>();
List<Map> maps = JSON.parseArray(content, Map.class);
for (Map map : maps) {
if(map.get("type").equals("image")){
String imgUrl = (String) map.get("value");
materials.add(imgUrl);
}
}
return materials;
}
@Autowired
private WmNewsMaterialMapper wmNewsMaterialMapper;
/**
* 保存或修改文章
* @param wmNews
*/
private void saveOrUpdateWmNews(WmNews wmNews) {
//补全属性
wmNews.setUserId(WmThreadLocalUtil.getUser().getId());
wmNews.setCreatedTime(new Date());
wmNews.setSubmitedTime(new Date());
wmNews.setEnable((short) 1);//默认上架
if(wmNews.getId() == null){
//保存
save(wmNews);
}else {
//修改
//删除文章图片与素材的关系
wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery()
.eq(WmNewsMaterial::getId, wmNews.getId()));
}
}
遇见的问题与debug
无
拓展知识点的学习
1.Mapper创建文件,需要在resource里添加配置文件,实现方法
2.BeanUtils.copyProperties(Object source, Object target)函数可以批量拷贝,不过只能针对属性名称和类型相同的情况。在本次项目中的一个应用是将WmNewsDto里的参数拷贝到WmNews实体类中
3.org.apache.commons.lang3.StringUtils.join(Iterable<?> iterable, String separator):
用于将一个数组(或集合)中的元素连接成一个字符串,并可以通过指定分隔符来分隔这些元素
4.JSON字符串可以直接被String接收,其格式如下:
String jsonString = "[{\"name\":\"Alice\",\"age\":25},{\"name\":\"Bob\",\"age\":30}]";
4.JSON.parseArray(String text, Class clazz)第一个参数是要解析的 JSON 字符串,第二个参数是要将 JSON 中的元素解析成的 Java 对象的类型
8267






