1 自媒体文章列表查询

1.1 需求分析

1.2 表结构和实体类

wm_news 自媒体文章表

需求:

  1. 如果有文章标题,按照文章标题模糊查询

  2. 如果有频道信息,按照频道ID查询

  3. 如果有文章状态,按照状态信息进行查询

  4. 如果开始时间,结束时间不为空按照时间区间查询

  5. 按照登录用户ID去查询

  6. 按照创建时间降序

  7. 分页查询,返回结果设置host 地址 为图片访问前缀

自媒体文章实体类

package com.heima.model.wemedia.pojos;
​
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.apache.ibatis.type.Alias;
​
import java.io.Serializable;
import java.util.Date;
​
/*** <p>* 自媒体图文内容信息表* </p>** @author itheima*/
@Data
@TableName("wm_news")
public class WmNews implements Serializable {
​private static final long serialVersionUID = 1L;
​/*** 主键*/@TableId(value = "id", type = IdType.AUTO)private Integer id;
​/*** 自媒体用户ID*/@TableField("user_id")private Integer userId;
​/*** 标题*/@TableField("title")private String title;
​/*** 图文内容*/@TableField("content")private String content;
​/*** 文章布局0 无图文章1 单图文章3 多图文章*/@TableField("type")private Short type;
​/*** 图文频道ID*/@TableField("channel_id")private Integer channelId;
​@TableField("labels")private String labels;
​/*** 创建时间*/@TableField("created_time")private Date createdTime;
​/*** 提交时间*/@TableField("submited_time")private Date submitedTime;
​/*** 当前状态0 草稿1 提交(待审核)2 审核失败3 人工审核4 人工审核通过8 审核通过(待发布)9 已发布*/@TableField("status")private Short status;
​/*** 定时发布时间,不定时则为空*/@TableField("publish_time")private Date publishTime;
​/*** 拒绝理由*/@TableField("reason")private String reason;
​/*** 发布库文章ID*/@TableField("article_id")private Long articleId;
​/*** //图片用逗号分隔*/@TableField("images")private String images;
​@TableField("enable")private Short enable;//状态枚举类***@Alias("WmNewsStatus")public enum Status{NORMAL((short)0),SUBMIT((short)1),FAIL((short)2),ADMIN_AUTH((short)3),ADMIN_SUCCESS((short)4),SUCCESS((short)8),PUBLISHED((short)9);short code;Status(short code){this.code = code;}public short getCode(){return this.code;}}
​
}

2 频道列表展示

2.1需求分析

文章展示列表页面打开的时候,默认自动加载频道列表数据进行展示,就是查询所有频道数据

2.2 接口定义

接口描述: 查询所有频道的数据

接口地址:/api/v1/channel/channels

请求方式:GET

请求数据类型:*

响应数据类型:application/json

请求参数: 暂无

2.3 功能实现

在admin-service 端,修改AdChannelController类,添加如下方法,mapper和service在之前已经定义

@ApiOperation("查询全部频道")
    @GetMapping("/channels")
    public ResponseResult findAll() {
        List<AdChannel> list = channelService.list();
        return ResponseResult.okResult(list);
    }

2.4 修改自媒体网关

配置中心 修改 wemedia-gateway 自媒体网关的yml配置文件中添加如下配置

- id: admin
  uri: lb://leadnews-admin
  predicates:
  - Path=/admin/**
  filters:
  - StripPrefix= 1

3 自媒体文章-发布、修改、保存草稿

3.1 需求分析

保存文章,除了需要wm_news表以外,还需要另外两张表

3.2 思路分析

  1. 参数校验

  2. 保存或修改文章

    • 该功能为保存、修改(是否有id)、保存草稿的共用方法

    • 如果有id修改文章,先删除所有素材关联关系

    • 如果没有id,保存文章

  3. 关联文章和素材关系表

    • 关联内容中的图片与素材的关系

    • 关联封面中的图片与素材的关系

      封面图片如果选择是自动需要从内容中截图图片做为封面图片

      截取规则为:

      • 内容图片的个数小于等于2 则为单图截图一张图

      • 内容图片大于2,则为多图,截图三张图

      • 内容中没有图片,则为无图

  4. 封装返回成功结果

前端给后端传递的参数格式:

{
    "title":"传智教育于2021年1月12日在深交所上市",
    "type":"1",  # 0:无图 1:单图  3:多图 -1:自动
    "labels":"黑马头条",
    "publishTime":"2021-01-14T11:35:49.000Z",
    "channelId":1,
    "images":[  # 文章封面 集合
        "https://heimaleadnewsoss.oss-cn-shanghai.aliyuncs.com/material/2021/1/20210113/20214312094300211.jpg"
    ],
    "status":1,
    # 文章内容 字符串
    "content":"[  
        {
            "type":"text",
            "value":"传智教育于2021年1月12日在深交所上市"
        },
        {
            "type":"image",
            "value":"https://heimaleadnewsoss.oss-cn-shanghai.aliyuncs.com/material/2021/1/20210113/20210112100045327.jpg"
        }
    ]"
}

3.3 接口定义

接口描述: 自媒体文章-发布、修改、保存草稿

接口地址:/api/v1/news/submit

请求方式:POST

请求数据类型:application/json

响应数据类型:application/json

请求示例:

{
    "channelId": 0,
    "content": "",
    "enable": 0,
    "id": 0,
    "images": [],
    "labels": "",
    "publishTime": "",
    "reason": "",
    "status": 0,
    "submitedTime": "",
    "title": "",
    "type": 0
}

请求参数:

参数名称 参数说明 in 是否必须 数据类型 schema
wmNews wmNews body true WmNewsDto WmNewsDto
  channelId 频道id true integer(int32)
  content 文章内容 true string
  enable 是否上架 false integer(int32)
  id 文章id true integer(int32) 修改存在
  images 图片列表 false array string
  labels 标签 true string
  publishTime 定时发布时间 true string(date-time)
  reason 原因 false string
  status 文章状态 true integer(int32) 提交为1 草稿为0
  submitedTime 提交时间 false string(date-time)
  title 文章标题 true string
  type 文章类型 false integer(int32) 0 无图 1 单图 3 多图 -1 自动

WmNewsDto用于接收前端传递参数

package com.heima.model.media.dtos;

import lombok.Data;

import java.util.Date;
import java.util.List;

@Data
public class WmNewsDTO {
    // 文章ID
    private Integer id;
     /**
     * 标题
     */
    private String title;
     /**
     * 频道id
     */
    private Integer channelId;
     /**
     * 标签
     */
    private String labels;
     /**
     * 发布时间
     */
    private Date publishTime;
     /**
     * 文章内容
     */
    private String content;
     /**
     * 文章封面类型  0 无图 1 单图 3 多图 -1 自动
     */
    private Short type;
     /**
     * 是否上架  0 下架  1 上架
     */
    private Short enable;
     /**
     * 提交时间
     */
    private Date submitedTime; 
     /**
     * 状态 提交为1  草稿为0
     */
    private Short status;
     /**
     * 拒绝理由
     */
    private String reason; 
     /**
     * 封面图片列表
     */
    private List<String> images;
}

3.4 mapper定义

修改WmNewsMaterialMapper,添加一个方法,用来批量添加数据,用于素材与文章关系做关联

public interface WmNewsMaterialMapper extends BaseMapper<WmNewsMaterial> {
    /**
     * 保存文章和素材的关联关系
     * @param wmMaterialIds 素材id集合
     * @param newsId        文章ID
     * @param type          文章封面类型  0 内容引用  1 封面引用
     */
    public void saveRelations(@Param("wmMaterialIds") List<Integer> wmMaterialIds,
                              @Param("newsId") Integer newsId,
                              @Param("type") Short type);
}

新建resources\mapper\WmNewsMaterialMapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.heima.wemedia.mapper.WmNewsMaterialMapper">
    <insert id="saveRelations">
        insert into wm_news_material (material_id, news_id, type, ord)
        values
        <foreach collection="wmMaterialIds" item="materialId" index="ord" separator=",">
            (#{materialId}, #{newsId}, #{type}, #{ord})
        </foreach>
    </insert>
</mapper>

素材mapper 新增 根据素材列表查询 相关素材id方法

public interface WmMaterialMapper extends BaseMapper<WmMaterial> {
    /**
     * 根据素材资源路径,查询相关素材id
     * @param urls 素材路径
     * @param userId
     * @return
     */
    public List<Integer> selectRelationsIds(@Param("urls") List<String> urls,
                                            @Param("userId") Integer userId);
}

定义mapper.WmMaterialMapper.xml实现查询方法

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.heima.wemedia.mapper.WmMaterialMapper">
    <select id="selectRelationsIds" resultType="Integer">
        select id from wm_material
        <where>
            url IN
            <foreach item="url" collection="urls" open="(" close=")" separator=",">
                #{url}
            </foreach>
            and user_id = #{userId}
        </where>
    </select>
</mapper>

3.5 业务层代码

常量类准备:com.heima.common.constants.wemedia.WmMediaConstans

package com.heima.common.constants.wemedia;
/*** @Description: 素材常量* @Version: V1.0*/
public class WemediaConstants {// 是否收藏public static final Short COLLECT_MATERIAL = 1;//收藏public static final Short CANCEL_COLLECT_MATERIAL = 0;//取消收藏// 文章类型public static final String WM_NEWS_TYPE_IMAGE = "image";// 文章状态public static final Short WM_NEWS_DRAFT_STATUS = 0; //草稿public static final Short WM_NEWS_SUMMIT_STATUS = 1; //提交public static final Short WM_NEWS_AUTHED_STATUS = 8; //审核通过public static final Short WM_NEWS_PUBLISH_STATUS = 9; //已发布// 文章封面选图public static final Short WM_NEWS_NONE_IMAGE = 0; //无图public static final Short WM_NEWS_SINGLE_IMAGE = 1; //单图public static final Short WM_NEWS_MANY_IMAGE = 3; //多图public static final Short WM_NEWS_TYPE_AUTO = -1; //图文类型自动// 文章图片引用public static final Short WM_CONTENT_REFERENCE = 0;public static final Short WM_IMAGE_REFERENCE = 1;// 文章上下架状态public static final Short WM_NEWS_UP = 1; // 上架public static final Short WM_NEWS_DOWN = 0; // 下架
}

在WmNewsService类中新增方法

    /*** 自媒体文章发布* @param wmNewsDto* @return*/ResponseResult submitNews(WmNewsDTO dto);

3.5.1 保存或修改文章

  • 该功能为保存、修改(是否有id)、保存草稿的共用方法

  • 如果有id修改文章,先删除所有素材关联关系

  • 如果没有id,保存文章

    @Overridepublic ResponseResult submitNews(WmNewsDTO dto) {// 1 参数校验if (StringUtils.isBlank(dto.getContent())) {CustException.cust(AppHttpCodeEnum.PARAM_INVALID);}// 校验是否登陆WmUser user = WmThreadLocalUtils.getUser();if (user == null){CustException.cust(AppHttpCodeEnum.NEED_LOGIN);}// 2 保存或修改文章WmNews wmNews = new WmNews();// 将dto参数里面的值设置到wmNewsBeanUtils.copyProperties(dto, wmNews);//如果文章布局是自动,需要设置为nullif (dto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)) {wmNews.setType(null);}// 处理dto参数 images封面集合 转换成 字符串String images = imageListToStr(dto.getImages());wmNews.setImages(images);wmNews.setUserId(user.getId());saveWmNews(wmNews);// 如果是草稿  直接返回if (WemediaConstants.WM_NEWS_DRAFT_STATUS.equals(dto.getStatus())){return ResponseResult.okResult();}// TODO 3.1 抽取文章中关联的图片路径// TODO 3.2 关联文章内容中的图片和素材关系// TODO 3.3 关联文章封面中的图片和素材关系  封面可能是选择自动或者是无图return ResponseResult.okResult();}

图片集合转字符串

/*** 图片列表转字符串,并去除图片前缀* @param images 图片列表* @param webSite 图片前缀*/
private String imageListToStr(List<String> images, String webSite) {return images.stream()  // 获取流.map((url) -> url.replace(webSite, ""))  // 对流数据的中间操作.collect(Collectors.joining(","));
}

保存文章

    @AutowiredWmNewsMaterialMapper wmNewsMaterialMapper;/*** 保存或修改文章* @param wmNews 文章对象(前端传递)*/private void saveWmNews(WmNews wmNews) {wmNews.setCreatedTime(new Date());wmNews.setUserId(WmThreadLocalUtils.getUser().getId());wmNews.setSubmitedTime(new Date());wmNews.setEnable(WemediaConstants.WM_NEWS_UP); // 上架if (wmNews.getId()==null) { // 保存操作save(wmNews);}else {  // 修改// 当前文章 和 素材关系表数据删除wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId, wmNews.getId()));updateById(wmNews);}}

小知识点:

3.5.2 解析内容中图片列表

/*** 自媒体文章发布* @param wmNewsDto* @param isSubmit 是否为提交 1 为提交 0为草稿* @return*/
@Override
public ResponseResult saveNews(WmNewsDto wmNewsDto, Short isSubmit) {
​// 上面代码略 ..........................//3.1 抽取文章中关联的图片路径List<String> materials = parseContentImages(dto.getContent());// 下面代码略 ..........................
}
​/*** 抽取文章内容中 所引用的所有图片* @param content 文章内容* @return*/private List<String> parseContentImages(String content) {List<Map> contents = JSON.parseArray(content, Map.class);// 遍历文章内容   将所有 type为image的 value获取出来  去除前缀路径return contents.stream()// 过滤type=image所有的集合.filter( map -> map.get("type").equals(WemediaConstants.WM_NEWS_TYPE_IMAGE))// 获取到image下的value  图片url.map(x -> (String)x.get("value"))// 图片url去除前缀.map(url-> url.replace(webSite,"").replace(" ",""))// 去除重复的路径.distinct()// stream 转成list集合.collect(Collectors.toList());}

参考前端传递参数数据格式解析即可

3.5.3 关联文章内容中的图片和素材关系

/*** 自媒体文章发布* @param wmNewsDto* @param isSubmit 是否为提交 1 为提交 0为草稿* @return*/
@Override
public ResponseResult saveNews(WmNewsDto wmNewsDto, Short isSubmit) {// 上面代码略 ..........................
​// 3.2 关联文章内容中的图片和素材关系if (!CollectionUtils.isEmpty(materials)) {saveRelativeInfo(materials, wmNews.getId(),WemediaConstants.WM_CONTENT_REFERENCE);}// 下面代码略 ..........................
}@AutowiredWmMaterialMapper wmMaterialMapper;/*** 保存素材和文章关系* @param urls  素材列表* @param newsId     文章ID* @param type       类型 0:内容素材  1:封面素材*/private void saveRelativeInfo(List<String> urls, Integer newsId, Short type) {//1 查询文章内容中的图片对应的素材IDList<Integer> ids = wmMaterialMapper.selectRelationsIds(urls,WmThreadLocalUtils.getUser().getId());//2 判断素材是否缺失if(CollectionUtils.isEmpty(ids) || ids.size() < urls.size()){CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST,"相关素材缺失,保存文章失败");}//3 保存素材关系wmNewsMaterialMapper.saveRelations(ids,newsId,type);}

启动服务测试

  • admin-service

  • wemedia-service

  • wemedia-gateway

  • 前端自媒体服务

注意当前登录人下需要上传几张图片

3.5.4 关联文章封面中的图片和素材关系

/*** 自媒体文章发布* @param wmNewsDto* @param isSubmit 是否为提交 1 为提交 0为草稿* @return*/
@Override
public ResponseResult submitNews(WmNewsDto wmNewsDto) {// 上面代码略 ..........................// 3.3 关联文章封面中的图片和素材关系  封面可能是选择自动或者是无图saveRelativeInfoForCover(dto,materials, wmNews);return ResponseResult.okResult();
}
​/*** 【3.3】 关联文章封面中的图片和素材关系* @param dto  前端用户选择封面信息数据* @param materials  从内容中解析的图片列表* @param wmNews     文章ID    */private void saveRelativeInfoForCover(WmNewsDTO dto, List<String> materials, WmNews wmNews) {// 前端用户选择的图List<String> images = dto.getImages();// 自动获取封面 ****if (WemediaConstants.WM_NEWS_TYPE_AUTO.equals(dto.getType())) {int materialSize = materials.size();if (materialSize > 0 && materialSize <= 2) {  // 单图images =  materials.stream().limit(1).collect(Collectors.toList());wmNews.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);} else if (materialSize > 2) { // 多图images =  materials.stream().limit(3).collect(Collectors.toList());wmNews.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);} else {  // 无图wmNews.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);}if (images != null && images.size() > 0) {// 将图片集合 转为字符串  url1,url2,url3wmNews.setImages(imageListToStr(images));}updateById(wmNews);}// 保存图片列表和素材的关系if (images != null && images.size() > 0) {images = images.stream().map(x->x.replace(webSite,"").replace(" ","")).collect(Collectors.toList());saveRelativeInfo(images, wmNews.getId(), WemediaConstants.WM_IMAGE_REFERENCE);}}

3.6 控制层

在WmNewsController类中新增方法

    @ApiOperation(value = "发表文章",notes = "发表文章,保存草稿,修改文章 共用的方法")@PostMapping("/submit")public ResponseResult submitNews(@RequestBody WmNewsDTO dto) {return wmNewsService.submitNews(dto);}

3.7 测试

postman工具测试

4 自媒体文章-根据id查询

4.1 需求分析

4.2 接口定义

接口描述: 根据id查询文章

接口地址:/api/v1/news/one/{id}

请求方式:GET

请求数据类型:*

响应数据类型:application/json

请求参数:

参数名称 参数说明 in 是否必须 数据类型 schema
id 文章主键id path true integer(int32)

4.3 业务层代码编写

在WmNewsService接口中新增方法 根据id查询文章的方法

/*** 根据文章id查询文章* @return*/
ResponseResult findWmNewsById(Integer id);

实现类:

    @Overridepublic ResponseResult findWmNewsById(Integer id) {//1 参数检查if (id == null) {CustException.cust(AppHttpCodeEnum.PARAM_INVALID);}//2 执行查询WmNews wmNews = getById(id);if (wmNews == null) {CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);}//3 返回结果ResponseResult result = ResponseResult.okResult(wmNews);result.setHost(webSite);return result;}

4.4 控制层

在WmNewsController新增方法 查询文章

    @ApiOperation(value = "根据id查询自媒体文章")@GetMapping("/one/{id}")public ResponseResult findWmNewsById(@PathVariable("id") Integer id) {return wmNewsService.findWmNewsById(id);}

4.5 测试

java 黑马头条 day4 自媒体文章发布 自媒体文章列表查询 频道列表展示 自媒体文章-发布、修改、保存草稿 自媒体文章-根据id查询 自媒体文章-删除相关推荐

  1. 在linux中如何修改保存gun文件_Linux下文件重命名、创建、删除、修改及保存文件...

    一.重命名(更名) linux 给文件改名的命令是mv命令 mv命令来为文件或目录改名或将文件由一个目录移入另一个目录中.该命令等同于DOS系统下的ren和move命令的组合.它的使用权限是所有用户. ...

  2. Python黑马头条推荐系统第三天 实时计算和召回业务、推荐业务流实现与ABTest

    实时计算业务 4.1 实时计算业务介绍 学习目标 目标 了解实时计算的业务需求 知道实时计算的作用 应用 无 4.1.1 实时计算业务需求 实时(在线)计算: 解决用户冷启动问题 实时计算能够根据用户 ...

  3. std::list 修改某个值_在WordPress首页不显示某个分类文章的做法

    WordPress作为博客站点很好用,但可惜的是没有微博/twitter之类快速短文的功能,如果设置一个分类来放置这类短文,首页又会显得杂乱而没有章法,按照网络上的教程,这个问题有几种解决办法,自己采 ...

  4. 前端基础第五天项目 社交媒体黑马头条项目-文章模块和评论

    七.文章详情 创建组件并配置路由 1.创建 views/article/index.vue 组件 <template><div class="article-contain ...

  5. 黑马头条项目总结之文章发布

    文章发布功能 /*** 新增文章** @param dto 参数* @return 响应信息*/@Overridepublic ResponseResult submitNews(WmNewsDto ...

  6. 前端基础第四天项目 社交媒体黑马头条项目-登录注册和个人中心

    一.项目初始化 目标 能使用 Vue CLI 创建项目 了解 Vant 组件库的导入方式 掌握制作使用字体图标的方式 掌握如何在 Vue 项目中处理 REM 适配 理解 axios 请求模块的封装 使 ...

  7. Java在线教育项目 第九天黑马头条爬虫

    day09_爬虫文档解析整合&数据保存准备 目标 能够完成爬虫初始化url的解析代码 能够完成个人空间页的解析 能够完成文章目标页的解析 能够进行整合测试 能够编写频道的保存及查询 1 文档解 ...

  8. 新黑马头条项目经验(黑马)

      swagger (1)简介 Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务(API Documentation & Design ...

  9. 《黑马头条》 ElectricSearch 分词器 联想词 MangoDB day08-平台管理[实战]作业

    07 app端文章搜索 1) 今日内容介绍 1.1)App端搜索-效果图 1.2)今日内容 2) 搭建ElasticSearch环境 2.1) 拉取镜像 docker pull elasticsear ...

最新文章

  1. BZOJ 3132 上帝造题的七分钟(二维树状数组)
  2. oracle 创建触发器_oracle创建触发器
  3. java重入锁,再探JAVA重入锁
  4. redis——客户端
  5. 属性子集选择的基本启发方法_一文看懂数据预处理最重要的3种思想和方法
  6. 【复杂网络分析】motif、cluster、clique、community 的介绍和比较
  7. 10_Shell语言———I/O重定向详解
  8. TensorFlow 2.0要来了,tf.contrib要砍了 | 有什么意见你说啊
  9. buildroot 下载和make nconfig
  10. 此文已删除,为何删不掉?
  11. iOS的音频文件的格式转换
  12. Struts2通配符和它的各种问题总结
  13. 学生专用计算机怎么没声音,班班通电脑没声音了
  14. opencv直方图,lomo,cartoon
  15. 2019.1.30《C Primer Plus》拖了一天写完的第八章编程练习答案
  16. TOJ 4171 L-The math problem(水题)
  17. 2022-2028全球与中国呼吸系统疾病治疗市场现状及未来发展趋势
  18. 导航算法A*的简单实现
  19. Java初级面试笔记
  20. day18-面向对象作业

热门文章

  1. xamarin学习笔记A19(安卓AIDL)
  2. 腾讯地图个性化图层创建及发布
  3. 如何实现 JS 运行时的 Inspector 能力
  4. gps wgs84坐标与高德gcj02坐标互转
  5. Mysql索引、命令重点介绍
  6. 原来MAC地址还是要购买的
  7. 杯具”箴言成网络流行语
  8. JAVA专业课题研究方向有哪些_教师课题研究方向与范围有哪些
  9. python如何实现图像中特定颜色的种类识别及特定颜色的占比代码
  10. 一篇文章带你搞透redis高性能IO模型