diff --git a/src/main/java/com/gxwebsoft/cms/entity/CmsNavigation.java b/src/main/java/com/gxwebsoft/cms/entity/CmsNavigation.java index 75385aa..c38ccbd 100644 --- a/src/main/java/com/gxwebsoft/cms/entity/CmsNavigation.java +++ b/src/main/java/com/gxwebsoft/cms/entity/CmsNavigation.java @@ -121,9 +121,21 @@ public class CmsNavigation implements Serializable { @TableField(exist = false) private Integer parentPosition; - @Schema(description = "绑定的页面(已废弃)") + @Schema(description = "绑定的单页ID(cms_page.page_id),单页管理页「关联导航」写入,与单页一一对应") private Integer pageId; + @Schema(description = "绑定单页的访问路径slug(VO 透传,来自 cms_page.path)") + @TableField(exist = false) + private String pagePath; + + @Schema(description = "绑定单页的标题(VO 透传,来自 cms_page.title)") + @TableField(exist = false) + private String pageTitle; + + @Schema(description = "绑定单页的状态 0草稿1已发布2已下线(VO 透传,来自 cms_page.status)") + @TableField(exist = false) + private Integer pageStatus; + @Schema(description = "详情页ID") private Integer itemId; diff --git a/src/main/java/com/gxwebsoft/cms/entity/CmsPage.java b/src/main/java/com/gxwebsoft/cms/entity/CmsPage.java index 2c6f1b5..d1919b4 100644 --- a/src/main/java/com/gxwebsoft/cms/entity/CmsPage.java +++ b/src/main/java/com/gxwebsoft/cms/entity/CmsPage.java @@ -86,6 +86,10 @@ public class CmsPage implements Serializable { @TableField(exist = false) private String statusText; + @Schema(description = "关联的导航栏目ID(cms_navigation.navigation_id),存于 cms_navigation.page_id;本实体不持久化该字段,仅作为 VO 透传与写回导航的入参") + @TableField(exist = false) + private Integer navigationId; + public String getStatusText() { if (this.status == null) return ""; switch (this.status) { diff --git a/src/main/java/com/gxwebsoft/cms/mapper/xml/CmsNavigationMapper.xml b/src/main/java/com/gxwebsoft/cms/mapper/xml/CmsNavigationMapper.xml index f887e07..b5938ad 100644 --- a/src/main/java/com/gxwebsoft/cms/mapper/xml/CmsNavigationMapper.xml +++ b/src/main/java/com/gxwebsoft/cms/mapper/xml/CmsNavigationMapper.xml @@ -4,11 +4,13 @@ - SELECT a.*, b.title as parentName, b.position as parentPosition, c.name as modelName + SELECT a.*, b.title as parentName, b.position as parentPosition, c.name as modelName, + p.path AS pagePath, p.title AS pageTitle, p.status AS pageStatus FROM cms_navigation a LEFT JOIN cms_navigation b ON a.parent_id = b.navigation_id AND b.deleted = 0 AND b.tenant_id = a.tenant_id LEFT JOIN cms_model c ON a.model = c.model AND c.deleted = 0 AND c.tenant_id = a.tenant_id + LEFT JOIN cms_page p ON p.page_id = a.page_id AND p.deleted = 0 AND a.navigation_id = #{param.navigationId} diff --git a/src/main/java/com/gxwebsoft/cms/mapper/xml/CmsPageMapper.xml b/src/main/java/com/gxwebsoft/cms/mapper/xml/CmsPageMapper.xml index 9fa5349..118101f 100644 --- a/src/main/java/com/gxwebsoft/cms/mapper/xml/CmsPageMapper.xml +++ b/src/main/java/com/gxwebsoft/cms/mapper/xml/CmsPageMapper.xml @@ -4,12 +4,16 @@ - SELECT a.* + SELECT a.*, n.navigation_id AS navigationId FROM cms_page a + LEFT JOIN cms_navigation n ON n.page_id = a.page_id AND n.deleted = 0 AND n.tenant_id = a.tenant_id AND a.page_id = #{param.pageId} + + AND n.navigation_id = #{param.navigationId} + AND a.title LIKE CONCAT('%', #{param.title}, '%') diff --git a/src/main/java/com/gxwebsoft/cms/param/CmsPageParam.java b/src/main/java/com/gxwebsoft/cms/param/CmsPageParam.java index 930e88d..ef2d71e 100644 --- a/src/main/java/com/gxwebsoft/cms/param/CmsPageParam.java +++ b/src/main/java/com/gxwebsoft/cms/param/CmsPageParam.java @@ -49,4 +49,9 @@ public class CmsPageParam extends BaseParam { @Schema(description = "单页ID集查询") @TableField(exist = false) private java.util.Set pageIds; + + @Schema(description = "关联的导航栏目ID(cms_navigation.navigation_id),用于按导航过滤单页") + @TableField(exist = false) + @QueryField(type = QueryType.EQ) + private Integer navigationId; } diff --git a/src/main/java/com/gxwebsoft/cms/service/impl/CmsPageServiceImpl.java b/src/main/java/com/gxwebsoft/cms/service/impl/CmsPageServiceImpl.java index 17772ac..93afe30 100644 --- a/src/main/java/com/gxwebsoft/cms/service/impl/CmsPageServiceImpl.java +++ b/src/main/java/com/gxwebsoft/cms/service/impl/CmsPageServiceImpl.java @@ -4,15 +4,19 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.gxwebsoft.cms.entity.CmsNavigation; import com.gxwebsoft.cms.entity.CmsPage; +import com.gxwebsoft.cms.mapper.CmsNavigationMapper; import com.gxwebsoft.cms.mapper.CmsPageMapper; import com.gxwebsoft.cms.param.CmsPageParam; import com.gxwebsoft.cms.service.CmsPageService; import com.gxwebsoft.common.core.web.PageParam; import com.gxwebsoft.common.core.web.PageResult; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; +import java.io.Serializable; import java.util.List; /** @@ -24,6 +28,9 @@ import java.util.List; @Service public class CmsPageServiceImpl extends com.baomidou.mybatisplus.extension.service.impl.ServiceImpl implements CmsPageService { + @Resource + private CmsNavigationMapper cmsNavigationMapper; + @Override public PageResult pageRel(CmsPageParam param) { PageParam page = new PageParam<>(param); @@ -72,6 +79,7 @@ public class CmsPageServiceImpl extends com.baomidou.mybatisplus.extension.servi } @Override + @Transactional(rollbackFor = Exception.class) public boolean saveRel(CmsPage page) { if (StrUtil.isBlank(page.getPath())) { return false; @@ -88,10 +96,15 @@ public class CmsPageServiceImpl extends com.baomidou.mybatisplus.extension.servi if (page.getViews() == null) { page.setViews(0); } - return save(page); + boolean saved = save(page); + if (saved && page.getNavigationId() != null) { + bindNavigation(page.getPageId(), page.getNavigationId(), page.getTenantId()); + } + return saved; } @Override + @Transactional(rollbackFor = Exception.class) public boolean updateByIdRel(CmsPage page) { if (page.getPageId() == null) { return false; @@ -102,6 +115,49 @@ public class CmsPageServiceImpl extends com.baomidou.mybatisplus.extension.servi if (page.getSortNumber() == null) { page.setSortNumber(0); } - return updateById(page); + boolean updated = updateById(page); + if (updated) { + bindNavigation(page.getPageId(), page.getNavigationId(), page.getTenantId()); + } + return updated; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean removeById(Serializable id) { + // 先清空所有指向该单页的导航引用(navigation.page_id = NULL),再逻辑删除单页 + cmsNavigationMapper.update(null, Wrappers.lambdaUpdate(CmsNavigation.class) + .eq(CmsNavigation::getPageId, (Integer) id) + .set(CmsNavigation::getPageId, null)); + return super.removeById(id); + } + + /** + * 维护「单页 ↔ 导航」的一一对应关系: + * 1) navigationId 为 null → 解绑(清掉所有绑了该 page 的导航引用) + * 2) 否则:先清目标导航此前绑定的其他单页、再清本单页此前绑定的其他导航,最后建立新绑定 + * 依赖 UNIQUE(tenant_id, page_id) 保证一个 page 只被一个导航绑; + * navigationId 为单值列(每个导航最多一个 page_id),天然保证一个导航只绑一篇单页。 + */ + private void bindNavigation(Integer pageId, Integer navigationId, Integer tenantId) { + if (navigationId == null) { + cmsNavigationMapper.update(null, Wrappers.lambdaUpdate(CmsNavigation.class) + .eq(CmsNavigation::getPageId, pageId) + .set(CmsNavigation::getPageId, null)); + return; + } + // 清掉目标导航此前绑定的其他单页(保证一个导航只绑一篇单页) + cmsNavigationMapper.update(null, Wrappers.lambdaUpdate(CmsNavigation.class) + .eq(CmsNavigation::getNavigationId, navigationId) + .set(CmsNavigation::getPageId, null)); + // 清掉本单页此前绑定的其他导航(换绑场景) + cmsNavigationMapper.update(null, Wrappers.lambdaUpdate(CmsNavigation.class) + .eq(CmsNavigation::getPageId, pageId) + .set(CmsNavigation::getPageId, null)); + // 建立新绑定 + cmsNavigationMapper.update(null, Wrappers.lambdaUpdate(CmsNavigation.class) + .eq(CmsNavigation::getNavigationId, navigationId) + .eq(CmsNavigation::getTenantId, tenantId) + .set(CmsNavigation::getPageId, pageId)); } }