营销活动: 新增文章管理

This commit is contained in:
puhui999
2023-10-15 16:16:41 +08:00
parent a47ab32800
commit 55eed1377a
21 changed files with 971 additions and 11 deletions

View File

@@ -0,0 +1,99 @@
package cn.iocoder.yudao.module.promotion.controller.admin.article;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.*;
import cn.iocoder.yudao.module.promotion.convert.article.ArticleConvert;
import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO;
import cn.iocoder.yudao.module.promotion.service.article.ArticleService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 文章管理")
@RestController
@RequestMapping("/promotion/article")
@Validated
public class ArticleController {
@Resource
private ArticleService articleService;
@PostMapping("/create")
@Operation(summary = "创建文章管理")
@PreAuthorize("@ss.hasPermission('promotion:article:create')")
public CommonResult<Long> createArticle(@Valid @RequestBody ArticleCreateReqVO createReqVO) {
return success(articleService.createArticle(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新文章管理")
@PreAuthorize("@ss.hasPermission('promotion:article:update')")
public CommonResult<Boolean> updateArticle(@Valid @RequestBody ArticleUpdateReqVO updateReqVO) {
articleService.updateArticle(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除文章管理")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('promotion:article:delete')")
public CommonResult<Boolean> deleteArticle(@RequestParam("id") Long id) {
articleService.deleteArticle(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得文章管理")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('promotion:article:query')")
public CommonResult<ArticleRespVO> getArticle(@RequestParam("id") Long id) {
ArticleDO article = articleService.getArticle(id);
return success(ArticleConvert.INSTANCE.convert(article));
}
@GetMapping("/list")
@Operation(summary = "获得文章管理列表")
@Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
@PreAuthorize("@ss.hasPermission('promotion:article:query')")
public CommonResult<List<ArticleRespVO>> getArticleList(@RequestParam("ids") Collection<Long> ids) {
List<ArticleDO> list = articleService.getArticleList(ids);
return success(ArticleConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@Operation(summary = "获得文章管理分页")
@PreAuthorize("@ss.hasPermission('promotion:article:query')")
public CommonResult<PageResult<ArticleRespVO>> getArticlePage(@Valid ArticlePageReqVO pageVO) {
PageResult<ArticleDO> pageResult = articleService.getArticlePage(pageVO);
return success(ArticleConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@Operation(summary = "导出文章管理 Excel")
@PreAuthorize("@ss.hasPermission('promotion:article:export')")
@OperateLog(type = EXPORT)
public void exportArticleExcel(@Valid ArticleExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<ArticleDO> list = articleService.getArticleList(exportReqVO);
// 导出 Excel
List<ArticleExcelVO> datas = ArticleConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "文章管理.xls", "数据", ArticleExcelVO.class, datas);
}
}

View File

@@ -0,0 +1,60 @@
package cn.iocoder.yudao.module.promotion.controller.admin.article.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 文章管理 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class ArticleBaseVO {
@Schema(description = "文章分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15458")
@NotNull(message = "文章分类编号不能为空")
private Long categoryId;
@Schema(description = "关联商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22378")
@NotNull(message = "关联商品不能为空")
private Long spuId;
@Schema(description = "文章标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "这是一个标题")
@NotNull(message = "文章标题不能为空")
private String title;
@Schema(description = "文章作者", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
private String author;
@Schema(description = "文章封面图片地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn")
@NotNull(message = "文章封面图片地址不能为空")
private String picUrl;
@Schema(description = "文章简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "这是一个简介")
private String introduction;
@Schema(description = "浏览次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "111")
private String browseCount;
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "排序不能为空")
private Integer sort;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@NotNull(message = "状态不能为空")
private Integer status;
@Schema(description = "是否热门(小程序)", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否热门(小程序)不能为空")
private Boolean recommendHot;
@Schema(description = "是否轮播图(小程序)", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否轮播图(小程序)不能为空")
private Boolean recommendBanner;
@Schema(description = "文章内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "这是文章内容")
@NotNull(message = "文章内容不能为空")
private String content;
}

View File

@@ -0,0 +1,14 @@
package cn.iocoder.yudao.module.promotion.controller.admin.article.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 文章管理创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ArticleCreateReqVO extends ArticleBaseVO {
}

View File

@@ -0,0 +1,63 @@
package cn.iocoder.yudao.module.promotion.controller.admin.article.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 文章管理 Excel VO
*
* @author HUIHUI
*/
@Data
public class ArticleExcelVO {
@ExcelProperty("文章编号")
private Long id;
@ExcelProperty("文章分类编号")
private Long categoryId;
@ExcelProperty("关联商品编号")
private Long spuId;
@ExcelProperty("文章标题")
private String title;
@ExcelProperty("文章作者")
private String author;
@ExcelProperty("文章封面图片地址")
private String picUrl;
@ExcelProperty("文章简介")
private String introduction;
@ExcelProperty("浏览次数")
private String browseCount;
@ExcelProperty("排序")
private Integer sort;
@ExcelProperty(value = "状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.COMMON_STATUS)
private Integer status;
@ExcelProperty("是否热门(小程序)")
private Boolean recommendHot;
@ExcelProperty("是否轮播图(小程序)")
private Boolean recommendBanner;
@ExcelProperty("文章内容")
private String content;
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,40 @@
package cn.iocoder.yudao.module.promotion.controller.admin.article.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 文章管理 Excel 导出 Request VO参数和 ArticlePageReqVO 是一致的")
@Data
public class ArticleExportReqVO {
@Schema(description = "文章分类编号", example = "15458")
private Long categoryId;
@Schema(description = "关联商品编号", example = "22378")
private Long spuId;
@Schema(description = "文章标题")
private String title;
@Schema(description = "文章作者")
private String author;
@Schema(description = "状态", example = "2")
private Integer status;
@Schema(description = "是否热门(小程序)")
private Boolean recommendHot;
@Schema(description = "是否轮播图(小程序)")
private Boolean recommendBanner;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@@ -0,0 +1,45 @@
package cn.iocoder.yudao.module.promotion.controller.admin.article.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 文章管理分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ArticlePageReqVO extends PageParam {
@Schema(description = "文章分类编号", example = "15458")
private Long categoryId;
@Schema(description = "关联商品编号", example = "22378")
private Long spuId;
@Schema(description = "文章标题")
private String title;
@Schema(description = "文章作者")
private String author;
@Schema(description = "状态", example = "2")
private Integer status;
@Schema(description = "是否热门(小程序)")
private Boolean recommendHot;
@Schema(description = "是否轮播图(小程序)")
private Boolean recommendBanner;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.promotion.controller.admin.article.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 文章管理 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ArticleRespVO extends ArticleBaseVO {
@Schema(description = "文章编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8606")
private Long id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.promotion.controller.admin.article.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 文章管理更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ArticleUpdateReqVO extends ArticleBaseVO {
@Schema(description = "文章编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8606")
@NotNull(message = "文章编号不能为空")
private Long id;
}

View File

@@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.promotion.convert.article;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.ArticleCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.ArticleExcelVO;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.ArticleRespVO;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.ArticleUpdateReqVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* 文章管理 Convert
*
* @author HUIHUI
*/
@Mapper
public interface ArticleConvert {
ArticleConvert INSTANCE = Mappers.getMapper(ArticleConvert.class);
ArticleDO convert(ArticleCreateReqVO bean);
ArticleDO convert(ArticleUpdateReqVO bean);
ArticleRespVO convert(ArticleDO bean);
List<ArticleRespVO> convertList(List<ArticleDO> list);
PageResult<ArticleRespVO> convertPage(PageResult<ArticleDO> page);
List<ArticleExcelVO> convertList02(List<ArticleDO> list);
}

View File

@@ -0,0 +1,81 @@
package cn.iocoder.yudao.module.promotion.dal.dataobject.article;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* 文章管理 DO
*
* @author HUIHUI
*/
@TableName("promotion_article")
@KeySequence("promotion_article_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ArticleDO extends BaseDO {
/**
* 文章管理编号
*/
@TableId
private Long id;
/**
* 分类编号 ArticleCategoryDO#id
*/
private Long categoryId;
/**
* 关联商品编号 ProductSpuDO#id
*/
private Long spuId;
/**
* 文章标题
*/
private String title;
/**
* 文章作者
*/
private String author;
/**
* 文章封面图片地址
*/
private String picUrl;
/**
* 文章简介
*/
private String introduction;
/**
* 浏览次数
*/
private String browseCount;
/**
* 排序
*/
private Integer sort;
/**
* 状态
*
* 枚举 {@link CommonStatusEnum}
*/
private Integer status;
/**
* 是否热门(小程序)
*/
private Boolean recommendHot;
/**
* 是否轮播图(小程序)
*/
private Boolean recommendBanner;
/**
* 文章内容
*/
private String content;
}

View File

@@ -0,0 +1,47 @@
package cn.iocoder.yudao.module.promotion.dal.mysql.article;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.ArticleExportReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.ArticlePageReqVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 文章管理 Mapper
*
* @author HUIHUI
*/
@Mapper
public interface ArticleMapper extends BaseMapperX<ArticleDO> {
default PageResult<ArticleDO> selectPage(ArticlePageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<ArticleDO>()
.eqIfPresent(ArticleDO::getCategoryId, reqVO.getCategoryId())
.eqIfPresent(ArticleDO::getTitle, reqVO.getTitle())
.eqIfPresent(ArticleDO::getAuthor, reqVO.getAuthor())
.eqIfPresent(ArticleDO::getStatus, reqVO.getStatus())
.eqIfPresent(ArticleDO::getSpuId, reqVO.getSpuId())
.eqIfPresent(ArticleDO::getRecommendHot, reqVO.getRecommendHot())
.eqIfPresent(ArticleDO::getRecommendBanner, reqVO.getRecommendBanner())
.betweenIfPresent(ArticleDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(ArticleDO::getId));
}
default List<ArticleDO> selectList(ArticleExportReqVO reqVO) {
return selectList(new LambdaQueryWrapperX<ArticleDO>()
.eqIfPresent(ArticleDO::getCategoryId, reqVO.getCategoryId())
.eqIfPresent(ArticleDO::getTitle, reqVO.getTitle())
.eqIfPresent(ArticleDO::getAuthor, reqVO.getAuthor())
.eqIfPresent(ArticleDO::getStatus, reqVO.getStatus())
.eqIfPresent(ArticleDO::getSpuId, reqVO.getSpuId())
.eqIfPresent(ArticleDO::getRecommendHot, reqVO.getRecommendHot())
.eqIfPresent(ArticleDO::getRecommendBanner, reqVO.getRecommendBanner())
.betweenIfPresent(ArticleDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(ArticleDO::getId));
}
}

View File

@@ -0,0 +1,75 @@
package cn.iocoder.yudao.module.promotion.service.article;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.ArticleCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.ArticleExportReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.ArticlePageReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.ArticleUpdateReqVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
/**
* 文章管理 Service 接口
*
* @author HUIHUI
*/
public interface ArticleService {
/**
* 创建文章管理
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createArticle(@Valid ArticleCreateReqVO createReqVO);
/**
* 更新文章管理
*
* @param updateReqVO 更新信息
*/
void updateArticle(@Valid ArticleUpdateReqVO updateReqVO);
/**
* 删除文章管理
*
* @param id 编号
*/
void deleteArticle(Long id);
/**
* 获得文章管理
*
* @param id 编号
* @return 文章管理
*/
ArticleDO getArticle(Long id);
/**
* 获得文章管理列表
*
* @param ids 编号
* @return 文章管理列表
*/
List<ArticleDO> getArticleList(Collection<Long> ids);
/**
* 获得文章管理分页
*
* @param pageReqVO 分页查询
* @return 文章管理分页
*/
PageResult<ArticleDO> getArticlePage(ArticlePageReqVO pageReqVO);
/**
* 获得文章管理列表, 用于 Excel 导出
*
* @param exportReqVO 查询条件
* @return 文章管理列表
*/
List<ArticleDO> getArticleList(ArticleExportReqVO exportReqVO);
}

View File

@@ -0,0 +1,90 @@
package cn.iocoder.yudao.module.promotion.service.article;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.ArticleCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.ArticleExportReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.ArticlePageReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.ArticleUpdateReqVO;
import cn.iocoder.yudao.module.promotion.convert.article.ArticleConvert;
import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO;
import cn.iocoder.yudao.module.promotion.dal.mysql.article.ArticleMapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.ARTICLE_NOT_EXISTS;
/**
* 文章管理 Service 实现类
*
* @author HUIHUI
*/
@Service
@Validated
public class ArticleServiceImpl implements ArticleService {
@Resource
private ArticleMapper articleMapper;
@Override
public Long createArticle(ArticleCreateReqVO createReqVO) {
// 插入
ArticleDO article = ArticleConvert.INSTANCE.convert(createReqVO);
articleMapper.insert(article);
// 返回
return article.getId();
}
@Override
public void updateArticle(ArticleUpdateReqVO updateReqVO) {
// 校验存在
validateArticleExists(updateReqVO.getId());
// 更新
ArticleDO updateObj = ArticleConvert.INSTANCE.convert(updateReqVO);
articleMapper.updateById(updateObj);
}
@Override
public void deleteArticle(Long id) {
// 校验存在
validateArticleExists(id);
// 删除
articleMapper.deleteById(id);
}
private void validateArticleExists(Long id) {
if (articleMapper.selectById(id) == null) {
throw exception(ARTICLE_NOT_EXISTS);
}
}
@Override
public ArticleDO getArticle(Long id) {
return articleMapper.selectById(id);
}
@Override
public List<ArticleDO> getArticleList(Collection<Long> ids) {
if (CollUtil.isEmpty(ids)) {
return ListUtil.empty();
}
return articleMapper.selectBatchIds(ids);
}
@Override
public PageResult<ArticleDO> getArticlePage(ArticlePageReqVO pageReqVO) {
return articleMapper.selectPage(pageReqVO);
}
@Override
public List<ArticleDO> getArticleList(ArticleExportReqVO exportReqVO) {
return articleMapper.selectList(exportReqVO);
}
}