diff --git a/src/main/java/com/ycwl/basic/controller/mobile/notify/WechatSubscribeNotifyController.java b/src/main/java/com/ycwl/basic/controller/mobile/notify/WechatSubscribeNotifyController.java index d294e34d..d509eafb 100644 --- a/src/main/java/com/ycwl/basic/controller/mobile/notify/WechatSubscribeNotifyController.java +++ b/src/main/java/com/ycwl/basic/controller/mobile/notify/WechatSubscribeNotifyController.java @@ -1,5 +1,6 @@ package com.ycwl.basic.controller.mobile.notify; +import com.ycwl.basic.annotation.IgnoreToken; import com.ycwl.basic.model.mobile.notify.resp.WechatSubscribeSceneTemplatesResp; import com.ycwl.basic.model.pc.notify.entity.WechatSubscribeTemplateConfigEntity; import com.ycwl.basic.service.notify.WechatSubscribeNotifyConfigService; @@ -41,6 +42,7 @@ public class WechatSubscribeNotifyController { * 获取“场景”下可申请授权的模板列表(支持按 scenicId 覆盖模板ID/开关/文案) */ @GetMapping("/scenic/{scenicId}/scenes/{sceneKey}/templates") + @IgnoreToken public ApiResponse listSceneTemplates(@PathVariable("scenicId") Long scenicId, @PathVariable("sceneKey") String sceneKey) { if (scenicId == null) { @@ -56,6 +58,9 @@ public class WechatSubscribeNotifyController { WechatSubscribeSceneTemplatesResp resp = new WechatSubscribeSceneTemplatesResp(); resp.setScenicId(scenicId); resp.setSceneKey(sceneKey); + if (memberId == null) { + return ApiResponse.success(resp); + } List templates = new ArrayList<>(); for (WechatSubscribeTemplateConfigEntity cfg : configs) { diff --git a/src/main/java/com/ycwl/basic/repository/WechatSubscribeNotifyConfigRepository.java b/src/main/java/com/ycwl/basic/repository/WechatSubscribeNotifyConfigRepository.java index cf6748ee..e51dde10 100644 --- a/src/main/java/com/ycwl/basic/repository/WechatSubscribeNotifyConfigRepository.java +++ b/src/main/java/com/ycwl/basic/repository/WechatSubscribeNotifyConfigRepository.java @@ -1,44 +1,81 @@ package com.ycwl.basic.repository; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.fasterxml.jackson.core.type.TypeReference; import com.ycwl.basic.mapper.WechatSubscribeEventTemplateMapper; import com.ycwl.basic.mapper.WechatSubscribeSceneTemplateMapper; import com.ycwl.basic.mapper.WechatSubscribeTemplateConfigMapper; import com.ycwl.basic.model.pc.notify.entity.WechatSubscribeEventTemplateEntity; import com.ycwl.basic.model.pc.notify.entity.WechatSubscribeSceneTemplateEntity; import com.ycwl.basic.model.pc.notify.entity.WechatSubscribeTemplateConfigEntity; +import com.ycwl.basic.utils.JacksonUtil; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * 微信订阅消息配置仓库(scenic 覆盖:scenic_id=具体值 > scenic_id=0) + * 支持 Redis 缓存,减少数据库查询 * * @Author: System * @Date: 2025/12/31 */ +@Slf4j @Component public class WechatSubscribeNotifyConfigRepository { private static final long DEFAULT_SCENIC_ID = 0L; + /** + * 场景模板配置缓存KEY + */ + private static final String SCENE_TEMPLATE_CONFIGS_KEY = "wechat:subscribe:scene:configs:%s:%s"; + + /** + * 事件模板配置缓存KEY + */ + private static final String EVENT_TEMPLATE_CONFIGS_KEY = "wechat:subscribe:event:configs:%s:%s"; + + /** + * 景区所有场景缓存KEY前缀(用于批量清除) + */ + private static final String SCENE_TEMPLATE_SCENIC_PREFIX = "wechat:subscribe:scene:configs:%s:*"; + + /** + * 景区所有事件缓存KEY前缀(用于批量清除) + */ + private static final String EVENT_TEMPLATE_SCENIC_PREFIX = "wechat:subscribe:event:configs:%s:*"; + + /** + * 缓存过期时间(小时) + */ + private static final long CACHE_EXPIRE_HOURS = 1; + private final WechatSubscribeTemplateConfigMapper templateConfigMapper; private final WechatSubscribeSceneTemplateMapper sceneTemplateMapper; private final WechatSubscribeEventTemplateMapper eventTemplateMapper; + private final RedisTemplate redisTemplate; public WechatSubscribeNotifyConfigRepository(WechatSubscribeTemplateConfigMapper templateConfigMapper, WechatSubscribeSceneTemplateMapper sceneTemplateMapper, - WechatSubscribeEventTemplateMapper eventTemplateMapper) { + WechatSubscribeEventTemplateMapper eventTemplateMapper, + RedisTemplate redisTemplate) { this.templateConfigMapper = templateConfigMapper; this.sceneTemplateMapper = sceneTemplateMapper; this.eventTemplateMapper = eventTemplateMapper; + this.redisTemplate = redisTemplate; } public List listEffectiveSceneTemplateMappings(Long scenicId, String sceneKey) { @@ -170,4 +207,210 @@ public class WechatSubscribeNotifyConfigRepository { } return null; } + + // ==================== 带缓存的配置查询方法 ==================== + + /** + * 获取场景模板配置列表(带缓存) + * 缓存最终的配置列表,避免重复查询和处理覆盖逻辑 + * + * @param scenicId 景区ID + * @param sceneKey 场景标识 + * @return 启用的模板配置列表 + */ + public List getSceneTemplateConfigsCached(Long scenicId, String sceneKey) { + Objects.requireNonNull(scenicId, "scenicId is null"); + if (StringUtils.isBlank(sceneKey)) { + throw new IllegalArgumentException("sceneKey is blank"); + } + + String cacheKey = String.format(SCENE_TEMPLATE_CONFIGS_KEY, scenicId, sceneKey); + + // 1. 尝试从缓存读取 + Boolean hasKey = redisTemplate.hasKey(cacheKey); + if (Boolean.TRUE.equals(hasKey)) { + String cacheValue = redisTemplate.opsForValue().get(cacheKey); + if (cacheValue != null) { + log.debug("从缓存读取场景模板配置: scenicId={}, sceneKey={}", scenicId, sceneKey); + return JacksonUtil.parseObject(cacheValue, new TypeReference>() {}); + } + } + + // 2. 从数据库查询 + List configs = loadSceneTemplateConfigs(scenicId, sceneKey); + + // 3. 写入缓存 + String json = JacksonUtil.toJSONString(configs); + redisTemplate.opsForValue().set(cacheKey, json, CACHE_EXPIRE_HOURS, TimeUnit.HOURS); + log.debug("场景模板配置缓存写入: scenicId={}, sceneKey={}, count={}", scenicId, sceneKey, configs.size()); + + return configs; + } + + /** + * 获取事件模板配置列表(带缓存) + * + * @param scenicId 景区ID + * @param eventKey 事件标识 + * @return 启用的模板配置列表 + */ + public List getEventTemplateConfigsCached(Long scenicId, String eventKey) { + Objects.requireNonNull(scenicId, "scenicId is null"); + if (StringUtils.isBlank(eventKey)) { + throw new IllegalArgumentException("eventKey is blank"); + } + + String cacheKey = String.format(EVENT_TEMPLATE_CONFIGS_KEY, scenicId, eventKey); + + // 1. 尝试从缓存读取 + Boolean hasKey = redisTemplate.hasKey(cacheKey); + if (Boolean.TRUE.equals(hasKey)) { + String cacheValue = redisTemplate.opsForValue().get(cacheKey); + if (cacheValue != null) { + log.debug("从缓存读取事件模板配置: scenicId={}, eventKey={}", scenicId, eventKey); + return JacksonUtil.parseObject(cacheValue, new TypeReference>() {}); + } + } + + // 2. 从数据库查询 + List configs = loadEventTemplateConfigs(scenicId, eventKey); + + // 3. 写入缓存 + String json = JacksonUtil.toJSONString(configs); + redisTemplate.opsForValue().set(cacheKey, json, CACHE_EXPIRE_HOURS, TimeUnit.HOURS); + log.debug("事件模板配置缓存写入: scenicId={}, eventKey={}, count={}", scenicId, eventKey, configs.size()); + + return configs; + } + + /** + * 加载场景模板配置(内部方法,处理覆盖逻辑) + */ + private List loadSceneTemplateConfigs(Long scenicId, String sceneKey) { + List mappings = listEffectiveSceneTemplateMappings(scenicId, sceneKey); + if (CollectionUtils.isEmpty(mappings)) { + return new ArrayList<>(); + } + + Set templateKeys = mappings.stream() + .map(WechatSubscribeSceneTemplateEntity::getTemplateKey) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + Map configMap = getEffectiveTemplateConfigs(scenicId, templateKeys); + + List result = new ArrayList<>(); + for (WechatSubscribeSceneTemplateEntity mapping : mappings) { + WechatSubscribeTemplateConfigEntity cfg = configMap.get(mapping.getTemplateKey()); + if (cfg == null || !Objects.equals(cfg.getEnabled(), 1)) { + continue; + } + result.add(cfg); + } + return result; + } + + /** + * 加载事件模板配置(内部方法,处理覆盖逻辑) + */ + private List loadEventTemplateConfigs(Long scenicId, String eventKey) { + List mappings = listEffectiveEventTemplateMappings(scenicId, eventKey); + if (CollectionUtils.isEmpty(mappings)) { + return new ArrayList<>(); + } + + Set templateKeys = mappings.stream() + .map(WechatSubscribeEventTemplateEntity::getTemplateKey) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + Map configMap = getEffectiveTemplateConfigs(scenicId, templateKeys); + + List result = new ArrayList<>(); + for (WechatSubscribeEventTemplateEntity mapping : mappings) { + WechatSubscribeTemplateConfigEntity cfg = configMap.get(mapping.getTemplateKey()); + if (cfg == null || !Objects.equals(cfg.getEnabled(), 1)) { + continue; + } + result.add(cfg); + } + return result; + } + + // ==================== 缓存清除方法 ==================== + + /** + * 清除指定场景的模板配置缓存 + * + * @param scenicId 景区ID + * @param sceneKey 场景标识 + */ + public void clearSceneTemplateConfigsCache(Long scenicId, String sceneKey) { + if (scenicId == null || StringUtils.isBlank(sceneKey)) { + return; + } + String cacheKey = String.format(SCENE_TEMPLATE_CONFIGS_KEY, scenicId, sceneKey); + redisTemplate.delete(cacheKey); + log.debug("清除场景模板配置缓存: scenicId={}, sceneKey={}", scenicId, sceneKey); + } + + /** + * 清除指定事件的模板配置缓存 + * + * @param scenicId 景区ID + * @param eventKey 事件标识 + */ + public void clearEventTemplateConfigsCache(Long scenicId, String eventKey) { + if (scenicId == null || StringUtils.isBlank(eventKey)) { + return; + } + String cacheKey = String.format(EVENT_TEMPLATE_CONFIGS_KEY, scenicId, eventKey); + redisTemplate.delete(cacheKey); + log.debug("清除事件模板配置缓存: scenicId={}, eventKey={}", scenicId, eventKey); + } + + /** + * 清除景区下所有订阅消息配置缓存 + * 在景区配置变更时调用 + * + * @param scenicId 景区ID + */ + public void clearAllConfigsCacheByScenic(Long scenicId) { + if (scenicId == null) { + return; + } + + // 清除场景配置缓存 + String scenePattern = String.format(SCENE_TEMPLATE_SCENIC_PREFIX, scenicId); + deleteByPattern(scenePattern); + + // 清除事件配置缓存 + String eventPattern = String.format(EVENT_TEMPLATE_SCENIC_PREFIX, scenicId); + deleteByPattern(eventPattern); + + log.info("清除景区所有订阅消息配置缓存: scenicId={}", scenicId); + } + + /** + * 清除所有订阅消息配置缓存 + * 在全局配置变更时调用(如默认配置修改) + */ + public void clearAllConfigsCache() { + deleteByPattern("wechat:subscribe:scene:configs:*"); + deleteByPattern("wechat:subscribe:event:configs:*"); + log.warn("清除所有订阅消息配置缓存"); + } + + /** + * 根据模式删除缓存 + */ + private void deleteByPattern(String pattern) { + try { + var keys = redisTemplate.keys(pattern); + if (keys != null && !keys.isEmpty()) { + redisTemplate.delete(keys); + log.debug("删除缓存: pattern={}, count={}", pattern, keys.size()); + } + } catch (Exception e) { + log.error("删除缓存失败: pattern={}", pattern, e); + } + } } diff --git a/src/main/java/com/ycwl/basic/service/notify/WechatSubscribeNotifyConfigService.java b/src/main/java/com/ycwl/basic/service/notify/WechatSubscribeNotifyConfigService.java index 3343cd6b..bf590ef4 100644 --- a/src/main/java/com/ycwl/basic/service/notify/WechatSubscribeNotifyConfigService.java +++ b/src/main/java/com/ycwl/basic/service/notify/WechatSubscribeNotifyConfigService.java @@ -1,21 +1,14 @@ package com.ycwl.basic.service.notify; -import com.ycwl.basic.model.pc.notify.entity.WechatSubscribeEventTemplateEntity; -import com.ycwl.basic.model.pc.notify.entity.WechatSubscribeSceneTemplateEntity; import com.ycwl.basic.model.pc.notify.entity.WechatSubscribeTemplateConfigEntity; import com.ycwl.basic.repository.WechatSubscribeNotifyConfigRepository; import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; -import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; /** - * 微信订阅消息配置查询服务(仅负责“配置解析”,不包含授权/发送逻辑) + * 微信订阅消息配置查询服务(仅负责"配置解析",不包含授权/发送逻辑) + * 底层通过 Repository 实现 Redis 缓存 * * @Author: System * @Date: 2025/12/31 @@ -29,53 +22,53 @@ public class WechatSubscribeNotifyConfigService { this.configRepository = configRepository; } + /** + * 获取场景下的模板配置列表(带缓存) + * + * @param scenicId 景区ID + * @param sceneKey 场景标识 + * @return 启用的模板配置列表 + */ public List listSceneTemplateConfigs(Long scenicId, String sceneKey) { - List mappings = - configRepository.listEffectiveSceneTemplateMappings(scenicId, sceneKey); - if (CollectionUtils.isEmpty(mappings)) { - return new ArrayList<>(); - } - - Set templateKeys = mappings.stream() - .map(WechatSubscribeSceneTemplateEntity::getTemplateKey) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - Map configMap = - configRepository.getEffectiveTemplateConfigs(scenicId, templateKeys); - - List result = new ArrayList<>(); - for (WechatSubscribeSceneTemplateEntity mapping : mappings) { - WechatSubscribeTemplateConfigEntity cfg = configMap.get(mapping.getTemplateKey()); - if (cfg == null || !Objects.equals(cfg.getEnabled(), 1)) { - continue; - } - result.add(cfg); - } - return result; + return configRepository.getSceneTemplateConfigsCached(scenicId, sceneKey); } + /** + * 获取事件下的模板配置列表(带缓存) + * + * @param scenicId 景区ID + * @param eventKey 事件标识 + * @return 启用的模板配置列表 + */ public List listEventTemplateConfigs(Long scenicId, String eventKey) { - List mappings = - configRepository.listEffectiveEventTemplateMappings(scenicId, eventKey); - if (CollectionUtils.isEmpty(mappings)) { - return new ArrayList<>(); - } + return configRepository.getEventTemplateConfigsCached(scenicId, eventKey); + } - Set templateKeys = mappings.stream() - .map(WechatSubscribeEventTemplateEntity::getTemplateKey) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - Map configMap = - configRepository.getEffectiveTemplateConfigs(scenicId, templateKeys); + /** + * 清除指定场景的配置缓存 + */ + public void clearSceneConfigsCache(Long scenicId, String sceneKey) { + configRepository.clearSceneTemplateConfigsCache(scenicId, sceneKey); + } - List result = new ArrayList<>(); - for (WechatSubscribeEventTemplateEntity mapping : mappings) { - WechatSubscribeTemplateConfigEntity cfg = configMap.get(mapping.getTemplateKey()); - if (cfg == null || !Objects.equals(cfg.getEnabled(), 1)) { - continue; - } - result.add(cfg); - } - return result; + /** + * 清除指定事件的配置缓存 + */ + public void clearEventConfigsCache(Long scenicId, String eventKey) { + configRepository.clearEventTemplateConfigsCache(scenicId, eventKey); + } + + /** + * 清除景区下所有订阅消息配置缓存 + */ + public void clearAllConfigsCacheByScenic(Long scenicId) { + configRepository.clearAllConfigsCacheByScenic(scenicId); + } + + /** + * 清除所有订阅消息配置缓存(全局配置变更时调用) + */ + public void clearAllConfigsCache() { + configRepository.clearAllConfigsCache(); } } diff --git a/src/main/java/com/ycwl/basic/service/pc/impl/WechatSubscribeNotifyAdminServiceImpl.java b/src/main/java/com/ycwl/basic/service/pc/impl/WechatSubscribeNotifyAdminServiceImpl.java index ae8f39bd..c3c9e95e 100644 --- a/src/main/java/com/ycwl/basic/service/pc/impl/WechatSubscribeNotifyAdminServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/pc/impl/WechatSubscribeNotifyAdminServiceImpl.java @@ -19,6 +19,7 @@ import com.ycwl.basic.model.pc.notify.req.WechatSubscribeSceneTemplateSaveReq; import com.ycwl.basic.model.pc.notify.req.WechatSubscribeSendLogPageReq; import com.ycwl.basic.model.pc.notify.req.WechatSubscribeTemplateConfigPageReq; import com.ycwl.basic.model.pc.notify.req.WechatSubscribeTemplateConfigSaveReq; +import com.ycwl.basic.service.notify.WechatSubscribeNotifyConfigService; import com.ycwl.basic.service.pc.WechatSubscribeNotifyAdminService; import com.ycwl.basic.utils.ApiResponse; import com.ycwl.basic.utils.JacksonUtil; @@ -47,15 +48,18 @@ public class WechatSubscribeNotifyAdminServiceImpl implements WechatSubscribeNot private final WechatSubscribeSceneTemplateMapper sceneTemplateMapper; private final WechatSubscribeEventTemplateMapper eventTemplateMapper; private final WechatSubscribeSendLogMapper sendLogMapper; + private final WechatSubscribeNotifyConfigService configService; public WechatSubscribeNotifyAdminServiceImpl(WechatSubscribeTemplateConfigMapper templateConfigMapper, WechatSubscribeSceneTemplateMapper sceneTemplateMapper, WechatSubscribeEventTemplateMapper eventTemplateMapper, - WechatSubscribeSendLogMapper sendLogMapper) { + WechatSubscribeSendLogMapper sendLogMapper, + WechatSubscribeNotifyConfigService configService) { this.templateConfigMapper = templateConfigMapper; this.sceneTemplateMapper = sceneTemplateMapper; this.eventTemplateMapper = eventTemplateMapper; this.sendLogMapper = sendLogMapper; + this.configService = configService; } @Override @@ -123,29 +127,33 @@ public class WechatSubscribeNotifyAdminServiceImpl implements WechatSubscribeNot entity.setDescription(StringUtils.trimToNull(req.getDescription())); entity.setUpdateTime(new Date()); + boolean success; if (req.getId() != null) { WechatSubscribeTemplateConfigEntity existing = templateConfigMapper.selectById(req.getId()); if (existing == null) { return ApiResponse.fail("记录不存在"); } entity.setId(req.getId()); - int updated = templateConfigMapper.updateById(entity); - return ApiResponse.success(updated > 0); + success = templateConfigMapper.updateById(entity) > 0; + } else { + // upsert by (template_key, scenic_id) + WechatSubscribeTemplateConfigEntity existing = templateConfigMapper.selectOne(new QueryWrapper() + .eq("template_key", entity.getTemplateKey()) + .eq("scenic_id", entity.getScenicId())); + if (existing != null) { + entity.setId(existing.getId()); + success = templateConfigMapper.updateById(entity) > 0; + } else { + entity.setCreateTime(new Date()); + success = templateConfigMapper.insert(entity) > 0; + } } - // upsert by (template_key, scenic_id) - WechatSubscribeTemplateConfigEntity existing = templateConfigMapper.selectOne(new QueryWrapper() - .eq("template_key", entity.getTemplateKey()) - .eq("scenic_id", entity.getScenicId())); - if (existing != null) { - entity.setId(existing.getId()); - int updated = templateConfigMapper.updateById(entity); - return ApiResponse.success(updated > 0); + // 清除缓存:模板配置变更影响场景和事件查询 + if (success) { + clearConfigCacheByScenic(req.getScenicId()); } - - entity.setCreateTime(new Date()); - int inserted = templateConfigMapper.insert(entity); - return ApiResponse.success(inserted > 0); + return ApiResponse.success(success); } catch (DuplicateKeyException e) { return ApiResponse.fail("保存失败:唯一键冲突(templateKey+scenicId已存在)"); } catch (Exception e) { @@ -160,7 +168,17 @@ public class WechatSubscribeNotifyAdminServiceImpl implements WechatSubscribeNot if (id == null) { return ApiResponse.fail("id不能为空"); } - return ApiResponse.success(templateConfigMapper.deleteById(id) > 0); + // 先查询获取 scenicId 用于清除缓存 + WechatSubscribeTemplateConfigEntity existing = templateConfigMapper.selectById(id); + if (existing == null) { + return ApiResponse.success(false); + } + boolean success = templateConfigMapper.deleteById(id) > 0; + // 清除缓存 + if (success) { + clearConfigCacheByScenic(existing.getScenicId()); + } + return ApiResponse.success(success); } catch (Exception e) { log.error("订阅消息|模板配置删除失败 id={}", id, e); return ApiResponse.fail("模板配置删除失败: " + e.getMessage()); @@ -228,29 +246,33 @@ public class WechatSubscribeNotifyAdminServiceImpl implements WechatSubscribeNot entity.setSortOrder(Objects.requireNonNullElse(req.getSortOrder(), 0)); entity.setUpdateTime(new Date()); + boolean success; if (req.getId() != null) { WechatSubscribeSceneTemplateEntity existing = sceneTemplateMapper.selectById(req.getId()); if (existing == null) { return ApiResponse.fail("记录不存在"); } entity.setId(req.getId()); - int updated = sceneTemplateMapper.updateById(entity); - return ApiResponse.success(updated > 0); + success = sceneTemplateMapper.updateById(entity) > 0; + } else { + WechatSubscribeSceneTemplateEntity existing = sceneTemplateMapper.selectOne(new QueryWrapper() + .eq("scene_key", entity.getSceneKey()) + .eq("template_key", entity.getTemplateKey()) + .eq("scenic_id", entity.getScenicId())); + if (existing != null) { + entity.setId(existing.getId()); + success = sceneTemplateMapper.updateById(entity) > 0; + } else { + entity.setCreateTime(new Date()); + success = sceneTemplateMapper.insert(entity) > 0; + } } - WechatSubscribeSceneTemplateEntity existing = sceneTemplateMapper.selectOne(new QueryWrapper() - .eq("scene_key", entity.getSceneKey()) - .eq("template_key", entity.getTemplateKey()) - .eq("scenic_id", entity.getScenicId())); - if (existing != null) { - entity.setId(existing.getId()); - int updated = sceneTemplateMapper.updateById(entity); - return ApiResponse.success(updated > 0); + // 清除场景配置缓存 + if (success) { + configService.clearSceneConfigsCache(req.getScenicId(), req.getSceneKey().trim()); } - - entity.setCreateTime(new Date()); - int inserted = sceneTemplateMapper.insert(entity); - return ApiResponse.success(inserted > 0); + return ApiResponse.success(success); } catch (DuplicateKeyException e) { return ApiResponse.fail("保存失败:唯一键冲突(sceneKey+templateKey+scenicId已存在)"); } catch (Exception e) { @@ -265,7 +287,17 @@ public class WechatSubscribeNotifyAdminServiceImpl implements WechatSubscribeNot if (id == null) { return ApiResponse.fail("id不能为空"); } - return ApiResponse.success(sceneTemplateMapper.deleteById(id) > 0); + // 先查询获取 scenicId 和 sceneKey 用于清除缓存 + WechatSubscribeSceneTemplateEntity existing = sceneTemplateMapper.selectById(id); + if (existing == null) { + return ApiResponse.success(false); + } + boolean success = sceneTemplateMapper.deleteById(id) > 0; + // 清除场景配置缓存 + if (success) { + configService.clearSceneConfigsCache(existing.getScenicId(), existing.getSceneKey()); + } + return ApiResponse.success(success); } catch (Exception e) { log.error("订阅消息|场景映射删除失败 id={}", id, e); return ApiResponse.fail("场景映射删除失败: " + e.getMessage()); @@ -335,29 +367,33 @@ public class WechatSubscribeNotifyAdminServiceImpl implements WechatSubscribeNot entity.setDedupSeconds(Objects.requireNonNullElse(req.getDedupSeconds(), 0)); entity.setUpdateTime(new Date()); + boolean success; if (req.getId() != null) { WechatSubscribeEventTemplateEntity existing = eventTemplateMapper.selectById(req.getId()); if (existing == null) { return ApiResponse.fail("记录不存在"); } entity.setId(req.getId()); - int updated = eventTemplateMapper.updateById(entity); - return ApiResponse.success(updated > 0); + success = eventTemplateMapper.updateById(entity) > 0; + } else { + WechatSubscribeEventTemplateEntity existing = eventTemplateMapper.selectOne(new QueryWrapper() + .eq("event_key", entity.getEventKey()) + .eq("template_key", entity.getTemplateKey()) + .eq("scenic_id", entity.getScenicId())); + if (existing != null) { + entity.setId(existing.getId()); + success = eventTemplateMapper.updateById(entity) > 0; + } else { + entity.setCreateTime(new Date()); + success = eventTemplateMapper.insert(entity) > 0; + } } - WechatSubscribeEventTemplateEntity existing = eventTemplateMapper.selectOne(new QueryWrapper() - .eq("event_key", entity.getEventKey()) - .eq("template_key", entity.getTemplateKey()) - .eq("scenic_id", entity.getScenicId())); - if (existing != null) { - entity.setId(existing.getId()); - int updated = eventTemplateMapper.updateById(entity); - return ApiResponse.success(updated > 0); + // 清除事件配置缓存 + if (success) { + configService.clearEventConfigsCache(req.getScenicId(), req.getEventKey().trim()); } - - entity.setCreateTime(new Date()); - int inserted = eventTemplateMapper.insert(entity); - return ApiResponse.success(inserted > 0); + return ApiResponse.success(success); } catch (DuplicateKeyException e) { return ApiResponse.fail("保存失败:唯一键冲突(eventKey+templateKey+scenicId已存在)"); } catch (Exception e) { @@ -372,7 +408,17 @@ public class WechatSubscribeNotifyAdminServiceImpl implements WechatSubscribeNot if (id == null) { return ApiResponse.fail("id不能为空"); } - return ApiResponse.success(eventTemplateMapper.deleteById(id) > 0); + // 先查询获取 scenicId 和 eventKey 用于清除缓存 + WechatSubscribeEventTemplateEntity existing = eventTemplateMapper.selectById(id); + if (existing == null) { + return ApiResponse.success(false); + } + boolean success = eventTemplateMapper.deleteById(id) > 0; + // 清除事件配置缓存 + if (success) { + configService.clearEventConfigsCache(existing.getScenicId(), existing.getEventKey()); + } + return ApiResponse.success(success); } catch (Exception e) { log.error("订阅消息|事件映射删除失败 id={}", id, e); return ApiResponse.fail("事件映射删除失败: " + e.getMessage()); @@ -529,5 +575,23 @@ public class WechatSubscribeNotifyAdminServiceImpl implements WechatSubscribeNot } return null; } + + /** + * 清除景区相关的配置缓存 + * 模板配置变更会影响场景和事件的查询结果,需要清除该景区下所有缓存 + * + * @param scenicId 景区ID + */ + private void clearConfigCacheByScenic(Long scenicId) { + if (scenicId == null) { + return; + } + // scenicId=0 表示默认配置,变更时需要清除所有缓存 + if (scenicId == 0L) { + configService.clearAllConfigsCache(); + } else { + configService.clearAllConfigsCacheByScenic(scenicId); + } + } }