feat(notify): 添加批量查询用户授权余额功能

- 新增批量查询用户授权余额接口 /api/mobile/notify/auth/batch-remaining
- 实现批量检查用户对多个模板的授权记录功能
- 添加景区所有场景及模板列表查询接口并支持缓存
- 优化授权记录查询性能,使用批量查询替代逐个查询
- 新增批量查询请求对象 BatchRemainingCountReq 和响应对象 WechatSubscribeAllScenesResp
- 在数据层添加批量查询用户授权记录的 SQL 映射
- 实现缓存管理机制,支持所有场景模板配置的缓存读写与清理
This commit is contained in:
2026-01-10 17:30:48 +08:00
parent 02f1392355
commit c9cc90c842
9 changed files with 316 additions and 15 deletions

View File

@@ -1,8 +1,10 @@
package com.ycwl.basic.controller.mobile.notify;
import com.ycwl.basic.model.mobile.notify.req.BatchRemainingCountReq;
import com.ycwl.basic.model.mobile.notify.req.NotificationAuthRecordReq;
import com.ycwl.basic.model.mobile.notify.resp.NotificationAuthRecordResp;
import com.ycwl.basic.model.mobile.notify.resp.ScenicTemplateAuthResp;
import com.ycwl.basic.model.pc.notify.entity.UserNotificationAuthorizationEntity;
import com.ycwl.basic.service.UserNotificationAuthorizationService;
import com.ycwl.basic.utils.ApiResponse;
import com.ycwl.basic.utils.JwtTokenUtil;
@@ -14,7 +16,9 @@ import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 用户通知授权记录Controller (移动端API)
@@ -92,4 +96,44 @@ public class UserNotificationAuthController {
return ApiResponse.fail("记录授权失败: " + e.getMessage());
}
}
/**
* 批量查询用户授权余额
* 返回 Map<wechatTemplateId, remainingCount>
*/
@PostMapping("/batch-remaining")
public ApiResponse<Map<String, Integer>> batchGetRemainingCount(
@RequestBody BatchRemainingCountReq req) {
log.debug("批量查询用户授权余额: templateIds={}, scenicId={}",
req.getTemplateIds(), req.getScenicId());
try {
Long memberId = JwtTokenUtil.getWorker().getUserId();
if (memberId == null) {
return ApiResponse.fail("用户未登录");
}
if (CollectionUtils.isEmpty(req.getTemplateIds())) {
return ApiResponse.success(new HashMap<>());
}
Map<String, UserNotificationAuthorizationEntity> authMap =
userNotificationAuthorizationService.batchCheckAuthorization(
memberId, req.getTemplateIds(), req.getScenicId());
// 转换为 templateId -> remainingCount
Map<String, Integer> result = new HashMap<>();
for (String templateId : req.getTemplateIds()) {
UserNotificationAuthorizationEntity entity = authMap.get(templateId);
int remaining = (entity != null && entity.getRemainingCount() != null)
? entity.getRemainingCount() : 0;
result.put(templateId, remaining);
}
return ApiResponse.success(result);
} catch (Exception e) {
log.error("批量查询用户授权余额失败", e);
return ApiResponse.fail("查询失败: " + e.getMessage());
}
}
}

View File

@@ -1,6 +1,7 @@
package com.ycwl.basic.controller.mobile.notify;
import com.ycwl.basic.annotation.IgnoreToken;
import com.ycwl.basic.model.mobile.notify.resp.WechatSubscribeAllScenesResp;
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;
@@ -87,5 +88,22 @@ public class WechatSubscribeNotifyController {
scenicId, sceneKey, memberId, Objects.requireNonNullElse(templates.size(), 0));
return ApiResponse.success(resp);
}
/**
* 获取景区下所有场景及其模板列表(静态配置,带缓存)
* 不含用户授权信息,用户授权信息通过 /api/mobile/notify/auth/batch-remaining 接口获取
*/
@GetMapping("/scenic/{scenicId}/scenes")
@IgnoreToken
public ApiResponse<WechatSubscribeAllScenesResp> listAllSceneTemplates(@PathVariable("scenicId") Long scenicId) {
if (scenicId == null) {
return ApiResponse.fail("scenicId不能为空");
}
WechatSubscribeAllScenesResp resp = configService.getAllScenesWithTemplatesCached(scenicId);
log.debug("所有场景模板查询: scenicId={}, sceneCount={}",
scenicId, resp.getScenes() != null ? resp.getScenes().size() : 0);
return ApiResponse.success(resp);
}
}