diff --git a/src/main/java/com/gxwebsoft/cms/controller/CmsNavigationController.java b/src/main/java/com/gxwebsoft/cms/controller/CmsNavigationController.java index 3b62c5f..74ccb10 100644 --- a/src/main/java/com/gxwebsoft/cms/controller/CmsNavigationController.java +++ b/src/main/java/com/gxwebsoft/cms/controller/CmsNavigationController.java @@ -21,6 +21,7 @@ import com.gxwebsoft.cms.param.CmsNavigationParam; import com.gxwebsoft.common.core.web.ApiResult; import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.common.core.web.BatchParam; +import com.gxwebsoft.common.core.exception.BusinessException; import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.service.UserService; import io.swagger.v3.oas.annotations.tags.Tag; @@ -103,6 +104,8 @@ public class CmsNavigationController extends BaseController { } // 去除前面空格 cmsNavigation.setTitle(StrUtil.trimStart(cmsNavigation.getTitle())); + // 单页模型绑定唯一性校验:同一租户下同一个单页只能绑定一个栏目 + checkPageBindingUnique(cmsNavigation); if (cmsNavigationService.save(cmsNavigation)) { // 添加成功事务处理 cmsNavigationService.saveAsync(cmsNavigation); @@ -116,6 +119,8 @@ public class CmsNavigationController extends BaseController { @Operation(summary = "修改网站导航记录表") @PutMapping() public ApiResult update(@RequestBody CmsNavigation cmsNavigation) { + // 单页模型绑定唯一性校验:同一租户下同一个单页只能绑定一个栏目 + checkPageBindingUnique(cmsNavigation); if (cmsNavigationService.updateById(cmsNavigation)) { // 修改成功事务处理 cmsNavigationService.saveAsync(cmsNavigation); @@ -281,6 +286,26 @@ public class CmsNavigationController extends BaseController { } } + /** + * 校验单页绑定唯一性:同一租户下同一个单页(pageId)只能绑定一个栏目, + * 避免触发 cms_navigation.uk_navigation_tenant_page 唯一索引导致用户看到"操作失败"。 + */ + private void checkPageBindingUnique(CmsNavigation cmsNavigation) { + if (!"page".equals(cmsNavigation.getModel()) || cmsNavigation.getPageId() == null) { + return; + } + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(CmsNavigation::getTenantId, getTenantId()) + .eq(CmsNavigation::getPageId, cmsNavigation.getPageId()) + .eq(CmsNavigation::getDeleted, 0); + if (cmsNavigation.getNavigationId() != null) { + wrapper.ne(CmsNavigation::getNavigationId, cmsNavigation.getNavigationId()); + } + if (cmsNavigationService.count(wrapper) > 0) { + throw new BusinessException("该单页已被其他栏目绑定,请先解绑后再绑定"); + } + } + /** * 递归创建子级导航 */ diff --git a/src/main/java/com/gxwebsoft/cms/controller/CmsWebsiteController.java b/src/main/java/com/gxwebsoft/cms/controller/CmsWebsiteController.java index ddf42de..fbd0f63 100644 --- a/src/main/java/com/gxwebsoft/cms/controller/CmsWebsiteController.java +++ b/src/main/java/com/gxwebsoft/cms/controller/CmsWebsiteController.java @@ -134,6 +134,9 @@ public class CmsWebsiteController extends BaseController { cmsWebsite.setWebsiteCode(null); } if (cmsWebsiteService.updateById(cmsWebsite)) { + // 站点信息(含 domain / templateId 等)有 1 天 Redis 缓存,改完必须立刻失效, + // 否则公开站与后台链接拼接最长 1 天读到旧值(与 CmsNavigationController 写操作保持一致)。 + clearSiteInfoCacheQuietly(); return success("修改成功"); } return fail("修改失败"); @@ -144,11 +147,30 @@ public class CmsWebsiteController extends BaseController { @PutMapping("/updateAll") public ApiResult updateAll(@RequestBody CmsWebsite cmsWebsite) { if (cmsWebsiteService.updateByIdAll(cmsWebsite)) { + clearSiteInfoCacheQuietly(); return success("修改成功"); } return fail("修改失败"); } + /** + * 清除当前租户的站点信息缓存。 + * 缓存失效属于写操作的附带动作,异常不应影响主流程(更新本身已成功)。 + */ + private void clearSiteInfoCacheQuietly() { + try { + Integer tenantId = getTenantId(); + if (ObjectUtil.isEmpty(tenantId)) { + return; + } + redisUtil.delete(SITE_INFO_KEY_PREFIX.concat(tenantId.toString())); + redisUtil.delete(MP_INFO_KEY_PREFIX.concat(tenantId.toString())); + log.info("已清除站点信息缓存,租户ID: {}", tenantId); + } catch (Exception e) { + log.warn("清除站点信息缓存失败: {}", e.getMessage()); + } + } + @PreAuthorize("hasAuthority('cms:website:remove')") @Operation(summary = "删除网站信息记录表") @DeleteMapping("/{id}")