fix(cms): 增强单页绑定唯一性校验和缓存失效处理
- 在CmsNavigationController新增checkPageBindingUnique方法,确保同一租户下同一单页只能绑定一个栏目 - 在新增和修改网站导航时调用绑定唯一性校验,避免唯一索引冲突导致操作失败 - 在CmsWebsiteController修改后立即清理站点信息缓存,避免缓存数据延迟导致旧数据读取 - clearSiteInfoCacheQuietly方法中捕获异常,确保缓存清理失败不会影响主流程 - 添加了缓存清理的日志记录,方便问题追踪
This commit is contained in:
@@ -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<CmsNavigation> 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("该单页已被其他栏目绑定,请先解绑后再绑定");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归创建子级导航
|
||||
*/
|
||||
|
||||
@@ -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}")
|
||||
|
||||
Reference in New Issue
Block a user