|
@@ -0,0 +1,395 @@
|
|
|
+package com.cclotus.cms.service
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
|
|
|
+import com.cclotus.cms.domain.CmsPost
|
|
|
+import com.cclotus.cms.domain.CmsPostMeta
|
|
|
+import com.cclotus.cms.domain.CmsReviewForm
|
|
|
+import com.cclotus.cms.domain.CmsTermRelationships
|
|
|
+import com.cclotus.cms.mapper.CmsPostMapper
|
|
|
+import com.cclotus.cms.mapper.CmsPostMetaMapper
|
|
|
+import com.cclotus.cms.mapper.CmsTermRelationshipsMapper
|
|
|
+import com.cclotus.cms.util.EntityPathVariable
|
|
|
+import com.cclotus.cms.vo.CmsPostFormReq
|
|
|
+import com.cclotus.cms.vo.CmsPostFormRes
|
|
|
+import com.ruoyi.common.core.page.TableDataInfo
|
|
|
+import com.ruoyi.common.exception.ServiceException
|
|
|
+import com.ruoyi.common.reqParam.PageParam
|
|
|
+import com.ruoyi.common.utils.PageUtils
|
|
|
+import com.ruoyi.common.utils.TableDataInfoUtil
|
|
|
+import org.springframework.beans.BeanUtils
|
|
|
+import org.springframework.beans.factory.annotation.Autowired
|
|
|
+import org.springframework.stereotype.Service
|
|
|
+import org.springframework.transaction.annotation.Transactional
|
|
|
+
|
|
|
+@Service
|
|
|
+class CmsPostService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ lateinit var cmsTermService: CmsTermService
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ lateinit var cmsPostMapper: CmsPostMapper
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ lateinit var cmsTermRelationshipsMapper: CmsTermRelationshipsMapper
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ lateinit var cmsPostMetaMapper: CmsPostMetaMapper
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ lateinit var cmsPostMetaService: CmsPostMetaService
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ lateinit var cmsTermMetaService: CmsTermMetaService
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询内容列表
|
|
|
+ * @param termAlias 分类别名
|
|
|
+ * @param deep 是否显示栏目下子栏目的文章,默认不查询子栏目下的文章
|
|
|
+ * @param post 过滤条件
|
|
|
+ * @param pageParam 分页条件
|
|
|
+ * @param content 列表页是否返回内容详情
|
|
|
+ * @param meta 扩展属性过滤条件
|
|
|
+ */
|
|
|
+ fun list(
|
|
|
+ termAlias: String?,
|
|
|
+ deep: Boolean,
|
|
|
+ post: CmsPost,
|
|
|
+ pageParam: PageParam?,
|
|
|
+ content: Boolean,
|
|
|
+ meta: Map<String, String>? = null,
|
|
|
+ ): TableDataInfo {
|
|
|
+
|
|
|
+ // 如果别名不为空,查询符合条件的栏目信息
|
|
|
+ val terms = termAlias?.takeIf { it.isNotBlank() }?.let {
|
|
|
+ cmsTermService.getTermsByAlias(termAlias, deep)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果存在termAlias过滤条件,先查询与该termAlias关联的objectIds
|
|
|
+ val objectIds = terms?.let {
|
|
|
+ cmsTermService.getObjectIdsByTerms(it).also { ids ->
|
|
|
+ if (ids.isEmpty()) {
|
|
|
+ return TableDataInfoUtil.getDataTable(emptyList<CmsPost>())
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果存在扩展属性过滤条件,查询内容元数据表
|
|
|
+ val postIdsByMeta = if (!meta.isNullOrEmpty()) {
|
|
|
+ cmsPostMetaMapper.selectPostMetaList(meta)
|
|
|
+ } else null
|
|
|
+
|
|
|
+ val queryWrapper = QueryWrapper<CmsPost>()
|
|
|
+ if (!content) {
|
|
|
+ // content为false时,不返回content字段,避免返回的数据量过大
|
|
|
+ queryWrapper.select(CmsPost::class.java) { info -> !info.column.equals("content") }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 审核状态字段条件不为空时,判断所属栏目是否存在需要审核扩展属性,如果需要审核,添加审核过滤条件
|
|
|
+ if (!post.review.isNullOrBlank() && !deep) {
|
|
|
+ terms?.getOrNull(0)?.let {
|
|
|
+ // 查询栏目是否存在需要审核属性,并且该值为需要审核
|
|
|
+ cmsTermMetaService.selectListByTermIds(listOf(it.termId!!))
|
|
|
+ .filter { meta -> meta.metaKey == "reviewRequired" && meta.metaValue == "1" }.getOrNull(0)?.run {
|
|
|
+ queryWrapper.eq("review", post.review)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!objectIds.isNullOrEmpty()) {
|
|
|
+ // 设置termAlias过滤条件时,只返回与alias关联的objects
|
|
|
+ queryWrapper.`in`("post_id", objectIds)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!postIdsByMeta.isNullOrEmpty()) {
|
|
|
+ // 过滤符合扩展字段查询条件的文章列表
|
|
|
+ queryWrapper.`in`("post_id", postIdsByMeta)
|
|
|
+ }
|
|
|
+
|
|
|
+ queryWrapper.eq(!post.contentType.isNullOrBlank(), "content_type", post.contentType)
|
|
|
+ .like(!post.title.isNullOrBlank(), "title", post.title)
|
|
|
+ .like(!post.summary.isNullOrBlank(), "summary", post.summary)
|
|
|
+ .eq(!post.status.isNullOrBlank(), "status", post.status)
|
|
|
+ .eq(post.topStatus != null, "top_status", post.topStatus)
|
|
|
+ .eq(!post.visible.isNullOrBlank(), "visible", post.visible)
|
|
|
+ .eq(!post.createBy.isNullOrBlank(), "create_by", post.createBy)
|
|
|
+ .orderByDesc("top_status", "create_time")
|
|
|
+
|
|
|
+ // 查询post主表,并处理分页
|
|
|
+ pageParam?.let {
|
|
|
+ it.orderByColumn = null
|
|
|
+ PageUtils.startPage(it)
|
|
|
+ }
|
|
|
+ val posts = cmsPostMapper.selectList(queryWrapper).also {
|
|
|
+ if (it.isEmpty()) return TableDataInfoUtil.getDataTable(it)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询meta从表,并按postId分组
|
|
|
+ val postIds = posts.map { it.postId!! }.distinct()
|
|
|
+ val metas = cmsPostMetaService.selectListByPostIds(postIds).groupBy { it.postId!! }
|
|
|
+
|
|
|
+ // 将meta从表数据关联到post主表
|
|
|
+ posts.forEach { it.meta = metas[it.postId] ?: emptyList() }
|
|
|
+
|
|
|
+ // 构建分页查询结果,转换post并替换rows
|
|
|
+ return TableDataInfoUtil.getDataTable(posts).apply {
|
|
|
+ rows = posts.map { it.toCmsPostFormRes() }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fun CmsPost.toCmsPostFormRes(): CmsPostFormRes {
|
|
|
+ return CmsPostFormRes().apply {
|
|
|
+ BeanUtils.copyProperties(this@toCmsPostFormRes, this)
|
|
|
+ this.meta =
|
|
|
+ this@toCmsPostFormRes.meta.associate { it.metaKey!! to it.metaValue } as MutableMap<String, String?>
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据文章别名或Id获取文章详情
|
|
|
+ */
|
|
|
+ fun detail(contentType: String, post: String): CmsPostFormRes {
|
|
|
+ val cmsPost = getPostByIdentity(contentType, post)
|
|
|
+ return cmsPost.toCmsPostFormRes()
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据文章ID获取文章详情
|
|
|
+ */
|
|
|
+ fun getPostInfoEx(
|
|
|
+ catalogAlias: String?,
|
|
|
+ postType: String,
|
|
|
+ postId: Int?,
|
|
|
+ postAlias: String?,
|
|
|
+ ): CmsPostFormRes {
|
|
|
+ if (postId == null && postAlias == null) {
|
|
|
+ throw ServiceException("文章ID和别名不可同时为空", 500)
|
|
|
+ }
|
|
|
+
|
|
|
+ val cmsPost = cmsPostMapper.selectPostEx(catalogAlias, postType, postId, postAlias)
|
|
|
+ ?: throw ServiceException("指定的文章信息不存在", 500)
|
|
|
+
|
|
|
+ return cmsPost.toCmsPostFormRes()
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 新增发布内容
|
|
|
+ * @param post 发布内容
|
|
|
+ * @param poster 发布者
|
|
|
+ * @return 影响数据条数
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ fun create(post: CmsPostFormReq, poster: String): Int {
|
|
|
+
|
|
|
+ post.alias?.let {
|
|
|
+ if (it.isNotBlank()) {
|
|
|
+ val queryWrapper = QueryWrapper<CmsPost>().eq("alias", it)
|
|
|
+ if (cmsPostMapper.selectCount(queryWrapper) > 0) throw ServiceException("页面别名已存在", 500)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 插入发布内容
|
|
|
+ val cmsPost = CmsPost().apply {
|
|
|
+ BeanUtils.copyProperties(post, this)
|
|
|
+ this.contentType = this.contentType ?: "article"
|
|
|
+ this.status = this.status ?: "0"
|
|
|
+ this.topStatus = this.topStatus ?: 0
|
|
|
+ this.visible = this.visible ?: "1"
|
|
|
+ this.createBy = poster
|
|
|
+ }.also {
|
|
|
+ if (cmsPostMapper.insert(it) != 1) {
|
|
|
+ throw ServiceException("插入发布内容失败", 500)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 插入发布内容与栏目的关联关系
|
|
|
+ post.catalogIds?.forEach { catalogId ->
|
|
|
+ CmsTermRelationships().apply {
|
|
|
+ this.objectId = cmsPost.postId
|
|
|
+ this.termId = catalogId
|
|
|
+ }.also {
|
|
|
+ if (cmsTermRelationshipsMapper.insert(it) != 1) {
|
|
|
+ throw ServiceException("插入发布内容与栏目的关联关系失败", 500)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 插入发布内容的扩展属性键值列表
|
|
|
+ post.meta?.forEach { meta ->
|
|
|
+ CmsPostMeta().apply {
|
|
|
+ this.postId = cmsPost.postId
|
|
|
+ this.metaKey = meta.key
|
|
|
+ this.metaValue = meta.value
|
|
|
+ }.also {
|
|
|
+ if (cmsPostMetaMapper.insert(it) != 1) {
|
|
|
+ throw ServiceException("插入发布内容的扩展属性列表失败", 500)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 在指定的类型下创建内容
|
|
|
+ *
|
|
|
+ * @param post 内容详情
|
|
|
+ * @param poster 创建者
|
|
|
+ * @param termAlias 类型别名
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ fun createByTermAlias(post: CmsPostFormReq, poster: String, termAlias: String): Int {
|
|
|
+ val cmsTerm =
|
|
|
+ cmsTermService.getTermsByAlias(termAlias, false).getOrNull(0) ?: throw ServiceException("指定类型不存在")
|
|
|
+ val termId = cmsTerm.termId
|
|
|
+ post.catalogIds = post.catalogIds?.also {
|
|
|
+ if (!it.contains(termId)) it.add(termId!!)
|
|
|
+ } ?: mutableListOf(termId!!)
|
|
|
+ return create(post, poster)
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新发布内容
|
|
|
+ * @param post 待修改发布内容
|
|
|
+ * @return 影响数据条数
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ fun update(post: CmsPostFormReq, poster: String): Int {
|
|
|
+ val postId = requireNotNull(post.postId) { "内容Id不可为空" }
|
|
|
+
|
|
|
+ // 获取待更新发布内容
|
|
|
+ val entity = cmsPostMapper.selectById(postId) ?: throw ServiceException("文章不存在", 500)
|
|
|
+
|
|
|
+ post.alias?.let {
|
|
|
+ if (it.isNotBlank()) {
|
|
|
+ val queryWrapper = QueryWrapper<CmsPost>().eq("alias", it).ne("post_id", entity.postId)
|
|
|
+ if (cmsPostMapper.selectCount(queryWrapper) > 0) throw ServiceException("页面别名已存在", 500)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新发布内容与栏目类别的关联关系
|
|
|
+ post.catalogIds?.let {
|
|
|
+ updatePostCatalogsRelations(postId, it)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新发布内容的扩展属性键值列表
|
|
|
+ post.meta?.let {
|
|
|
+ updatePostMetas(postId, it)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新发布内容
|
|
|
+ entity.apply {
|
|
|
+ BeanUtils.copyProperties(post, this, "origin")
|
|
|
+ this.updateBy = poster
|
|
|
+ }.also {
|
|
|
+ cmsPostMapper.updateById(it)
|
|
|
+ }
|
|
|
+
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据IDs删除发布内容
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ fun deleteByIds(postIds: Array<Int>): Int {
|
|
|
+ if (postIds.isEmpty()) return 0
|
|
|
+
|
|
|
+ cmsPostMetaMapper.delete(QueryWrapper<CmsPostMeta>().`in`("post_id", postIds.toList()))
|
|
|
+
|
|
|
+ cmsTermRelationshipsMapper.deleteObjectIds(postIds.toList())
|
|
|
+
|
|
|
+ return cmsPostMapper.deleteBatchIds(postIds.toList())
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 审核内容
|
|
|
+ *
|
|
|
+ * @param contentType 内容类型
|
|
|
+ * @param post 内容标识,文章ID或者别名
|
|
|
+ * @param reviewForm 审核信息
|
|
|
+ */
|
|
|
+ fun review(contentType: String, post: String, reviewForm: CmsReviewForm) {
|
|
|
+ val cmsPost = getPostByIdentity(contentType, post)
|
|
|
+ cmsPost.review = reviewForm.review
|
|
|
+ cmsPost.comment = reviewForm.comment
|
|
|
+ cmsPostMapper.updateById(cmsPost)
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据标识获取内容信息
|
|
|
+ *
|
|
|
+ * @param contentType 内容类型
|
|
|
+ * @param identity 内容标识,ID或别名
|
|
|
+ * @return 内容详情
|
|
|
+ */
|
|
|
+ private fun getPostByIdentity(contentType: String, identity: String): CmsPost {
|
|
|
+ return EntityPathVariable.parse(identity).let {
|
|
|
+ if (it.id != null) {
|
|
|
+ cmsPostMapper.selectPostByPostId(contentType, it.id) ?: throw ServiceException(
|
|
|
+ "指定ID文章信息不存在", 500
|
|
|
+ )
|
|
|
+ } else if (it.alias != null) {
|
|
|
+ cmsPostMapper.selectPostByAlias(contentType, it.alias)
|
|
|
+ ?: throw ServiceException("指定别名的文章信息不存在", 500)
|
|
|
+ } else {
|
|
|
+ throw ServiceException("指定的文章信息不存在", 500)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新发布内容的扩展属性键值列表
|
|
|
+ */
|
|
|
+ private fun updatePostMetas(postId: Int, metas: Map<String, String>) {
|
|
|
+ // 删除旧的属性
|
|
|
+ cmsPostMetaMapper.delete(QueryWrapper<CmsPostMeta>().eq("post_id", postId))
|
|
|
+
|
|
|
+ // 插入新的属性
|
|
|
+ metas.forEach { meta ->
|
|
|
+ CmsPostMeta().apply {
|
|
|
+ this.postId = postId
|
|
|
+ this.metaKey = meta.key
|
|
|
+ this.metaValue = meta.value
|
|
|
+ }.also {
|
|
|
+ if (cmsPostMetaMapper.insert(it) != 1) {
|
|
|
+ throw ServiceException("插入发布内容的扩展属性列表失败", 500)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新发布内容与栏目类别的关联关系
|
|
|
+ */
|
|
|
+ private fun updatePostCatalogsRelations(postId: Int, catalogIds: List<Int>) {
|
|
|
+
|
|
|
+ // 获取关联的栏目类型
|
|
|
+ val rela = cmsTermRelationshipsMapper.selectCatalogRelationsByPostId(postId)
|
|
|
+ val relaCatalogIds = rela.map { r -> r.termId }.toList()
|
|
|
+
|
|
|
+ // 计算待删除栏目类别列表,和待插入栏目类别列表
|
|
|
+ val removeIds = relaCatalogIds.minus(catalogIds.toSet())
|
|
|
+ val addIds = catalogIds.minus(relaCatalogIds.toSet())
|
|
|
+
|
|
|
+ // 删除旧的关联关系
|
|
|
+ rela.forEach {
|
|
|
+ if (removeIds.contains(it.termId)) {
|
|
|
+ cmsTermRelationshipsMapper.deleteById(it.relaId)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 插入新的关联关系
|
|
|
+ // TODO: 需要检查新增的栏目类别是否合法
|
|
|
+ catalogIds.forEach {
|
|
|
+ if (addIds.contains(it)) {
|
|
|
+ CmsTermRelationships().apply {
|
|
|
+ this.objectId = postId
|
|
|
+ this.termId = it
|
|
|
+ }.also { r ->
|
|
|
+ cmsTermRelationshipsMapper.insert(r)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|