package com.zy.asrs.controller;
|
|
import com.alibaba.fastjson.JSON;
|
import com.baomidou.mybatisplus.mapper.EntityWrapper;
|
import com.baomidou.mybatisplus.plugins.Page;
|
import com.core.annotations.ManagerAuth;
|
import com.core.common.Cools;
|
import com.core.common.R;
|
import com.zy.asrs.domain.NotifyDto;
|
import com.zy.asrs.domain.NotifySendResult;
|
import com.zy.asrs.domain.param.NotifyResendParam;
|
import com.zy.asrs.domain.vo.NotifyReportVo;
|
import com.zy.asrs.entity.HttpRequestLog;
|
import com.zy.asrs.service.HttpRequestLogService;
|
import com.zy.asrs.service.NotifyAsyncService;
|
import com.zy.asrs.utils.NotifyUtils;
|
import com.zy.common.utils.RedisUtil;
|
import com.zy.common.web.BaseController;
|
import com.zy.system.entity.Config;
|
import com.zy.system.service.ConfigService;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RestController;
|
|
import java.util.ArrayList;
|
import java.util.Comparator;
|
import java.util.HashMap;
|
import java.util.LinkedHashSet;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Set;
|
|
@RestController
|
public class NotifyReportController extends BaseController {
|
|
@Autowired
|
private RedisUtil redisUtil;
|
@Autowired
|
private NotifyUtils notifyUtils;
|
@Autowired
|
private NotifyAsyncService notifyAsyncService;
|
@Autowired
|
private HttpRequestLogService httpRequestLogService;
|
@Autowired
|
private ConfigService configService;
|
|
@RequestMapping(value = "/notifyReport/summary/auth")
|
@ManagerAuth
|
public R summary() {
|
Map<String, Object> result = new HashMap<>();
|
String notifyEnable = getConfigValue("notifyEnable");
|
String notifyUri = getConfigValue("notifyUri");
|
String notifyUriPath = getConfigValue("notifyUriPath");
|
String endpoint = buildNotifyEndpoint(notifyUri, notifyUriPath);
|
|
result.put("notifyEnable", notifyEnable);
|
result.put("notifyEnable$", "Y".equalsIgnoreCase(notifyEnable) ? "已开启" : "已关闭");
|
result.put("notifyUri", notifyUri);
|
result.put("notifyUriPath", notifyUriPath);
|
result.put("notifyEndpoint", endpoint);
|
result.put("queueCount", loadQueueRecords(null, null).size());
|
if (!Cools.isEmpty(endpoint)) {
|
result.put("logCount", httpRequestLogService.selectCount(new EntityWrapper<HttpRequestLog>().eq("name", endpoint)));
|
} else {
|
result.put("logCount", 0);
|
}
|
return R.ok(result);
|
}
|
|
@RequestMapping(value = "/notifyReport/queue/list/auth")
|
@ManagerAuth
|
public R queueList(@RequestParam(defaultValue = "1") Integer curr,
|
@RequestParam(defaultValue = "15") Integer limit,
|
@RequestParam(required = false) String notifyType,
|
@RequestParam(required = false) Integer device,
|
@RequestParam(required = false) String taskNo,
|
@RequestParam(required = false) String superTaskNo,
|
@RequestParam(required = false) String msgType,
|
@RequestParam(required = false) String condition) {
|
List<NotifyReportVo> records = loadQueueRecords(notifyType, device);
|
List<NotifyReportVo> filtered = new ArrayList<>();
|
for (NotifyReportVo record : records) {
|
if (!matchesQueue(record, notifyType, device, taskNo, superTaskNo, msgType, condition)) {
|
continue;
|
}
|
filtered.add(record);
|
}
|
filtered.sort(Comparator.comparing(NotifyReportVo::getId, Comparator.nullsLast(Long::compareTo)).reversed());
|
return R.ok(buildPage(curr, limit, filtered));
|
}
|
|
@RequestMapping(value = "/notifyReport/log/list/auth")
|
@ManagerAuth
|
public R logList(@RequestParam(defaultValue = "1") Integer curr,
|
@RequestParam(defaultValue = "15") Integer limit,
|
@RequestParam(required = false) String notifyType,
|
@RequestParam(required = false) Integer device,
|
@RequestParam(required = false) String taskNo,
|
@RequestParam(required = false) String superTaskNo,
|
@RequestParam(required = false) String msgType,
|
@RequestParam(required = false) Integer result,
|
@RequestParam(required = false) String condition) {
|
String endpoint = buildNotifyEndpoint(getConfigValue("notifyUri"), getConfigValue("notifyUriPath"));
|
EntityWrapper<HttpRequestLog> wrapper = new EntityWrapper<>();
|
if (!Cools.isEmpty(endpoint)) {
|
wrapper.eq("name", endpoint);
|
} else {
|
wrapper.like("request", "\"notifyType\"");
|
}
|
if (!Cools.isEmpty(taskNo)) {
|
wrapper.like("request", taskNo);
|
}
|
if (!Cools.isEmpty(superTaskNo)) {
|
wrapper.like("request", superTaskNo);
|
}
|
if (!Cools.isEmpty(msgType)) {
|
wrapper.like("request", msgType);
|
}
|
if (!Cools.isEmpty(notifyType)) {
|
wrapper.like("request", "\"notifyType\":\"" + notifyType + "\"");
|
}
|
if (device != null) {
|
wrapper.like("request", "\"device\":" + device);
|
}
|
if (!Cools.isEmpty(condition)) {
|
wrapper.andNew().like("request", condition).or().like("response", condition);
|
}
|
if (result != null) {
|
wrapper.eq("result", result);
|
}
|
wrapper.orderBy("create_time", false);
|
|
Page<HttpRequestLog> logPage = httpRequestLogService.selectPage(new Page<>(curr, limit), wrapper);
|
Page<NotifyReportVo> resultPage = new Page<>(curr, limit);
|
resultPage.setTotal(logPage.getTotal());
|
|
List<NotifyReportVo> rows = new ArrayList<>();
|
for (HttpRequestLog log : logPage.getRecords()) {
|
rows.add(buildLogVo(log));
|
}
|
resultPage.setRecords(rows);
|
return R.ok(resultPage);
|
}
|
|
@RequestMapping(value = "/notifyReport/resend/auth")
|
@ManagerAuth
|
public R resend(@RequestBody NotifyResendParam param) {
|
if (param == null || Cools.isEmpty(param.getSourceType())) {
|
return R.error("补发参数不能为空");
|
}
|
|
String notifyUri = getConfigValue("notifyUri");
|
String notifyUriPath = getConfigValue("notifyUriPath");
|
if (Cools.isEmpty(notifyUri) || Cools.isEmpty(notifyUriPath)) {
|
return R.error("请先配置 notifyUri 和 notifyUriPath");
|
}
|
|
List<Map<String, Object>> details = new ArrayList<>();
|
int successCount = 0;
|
int failCount = 0;
|
|
if ("queue".equalsIgnoreCase(param.getSourceType())) {
|
if (Cools.isEmpty(param.getRedisKeys())) {
|
return R.error("请选择要补发的队列通知");
|
}
|
for (String redisKey : param.getRedisKeys()) {
|
Map<String, Object> detail = resendQueue(redisKey, notifyUri, notifyUriPath);
|
details.add(detail);
|
if (Boolean.TRUE.equals(detail.get("success"))) {
|
successCount++;
|
} else {
|
failCount++;
|
}
|
}
|
} else if ("log".equalsIgnoreCase(param.getSourceType())) {
|
if (Cools.isEmpty(param.getLogIds())) {
|
return R.error("请选择要补发的通知日志");
|
}
|
for (Long logId : param.getLogIds()) {
|
Map<String, Object> detail = resendLog(logId, notifyUri, notifyUriPath);
|
details.add(detail);
|
if (Boolean.TRUE.equals(detail.get("success"))) {
|
successCount++;
|
} else {
|
failCount++;
|
}
|
}
|
} else {
|
return R.error("不支持的补发来源");
|
}
|
|
Map<String, Object> result = new HashMap<>();
|
result.put("successCount", successCount);
|
result.put("failCount", failCount);
|
result.put("allSuccess", failCount == 0);
|
result.put("details", details);
|
return R.ok(result);
|
}
|
|
private Page<NotifyReportVo> buildPage(Integer curr, Integer limit, List<NotifyReportVo> records) {
|
Page<NotifyReportVo> page = new Page<>(curr, limit);
|
page.setTotal(records.size());
|
|
int fromIndex = Math.max((curr - 1) * limit, 0);
|
if (fromIndex >= records.size()) {
|
page.setRecords(new ArrayList<>());
|
return page;
|
}
|
int toIndex = Math.min(fromIndex + limit, records.size());
|
page.setRecords(new ArrayList<>(records.subList(fromIndex, toIndex)));
|
return page;
|
}
|
|
private List<NotifyReportVo> loadQueueRecords(String notifyType, Integer device) {
|
Set<String> keys = new LinkedHashSet<>();
|
List<String> notifyTypes = new ArrayList<>();
|
if (!Cools.isEmpty(notifyType)) {
|
notifyTypes.add(notifyType);
|
} else {
|
notifyTypes.addAll(notifyUtils.getSupportedNotifyTypes());
|
}
|
|
for (String item : notifyTypes) {
|
String prefix = notifyUtils.getKeyPrefix(item);
|
if (Cools.isEmpty(prefix)) {
|
continue;
|
}
|
|
String pattern = device == null ? prefix + "*" : prefix + device + "_*";
|
Set matched = redisUtil.keys(pattern);
|
if (matched == null) {
|
continue;
|
}
|
for (Object key : matched) {
|
if (key != null) {
|
keys.add(String.valueOf(key));
|
}
|
}
|
}
|
|
List<NotifyReportVo> rows = new ArrayList<>();
|
for (String key : keys) {
|
Object object = redisUtil.get(key);
|
if (!(object instanceof NotifyDto)) {
|
continue;
|
}
|
rows.add(buildQueueVo(key, (NotifyDto) object));
|
}
|
return rows;
|
}
|
|
private NotifyReportVo buildQueueVo(String redisKey, NotifyDto dto) {
|
NotifyReportVo vo = new NotifyReportVo();
|
vo.setSourceType("queue");
|
vo.setRedisKey(redisKey);
|
vo.setId(dto.getId());
|
vo.setNotifyType(dto.getNotifyType());
|
vo.setDevice(dto.getDevice());
|
vo.setTaskNo(dto.getTaskNo());
|
vo.setSuperTaskNo(dto.getSuperTaskNo());
|
vo.setMsgType(dto.getMsgType());
|
vo.setMsgDesc(dto.getMsgDesc());
|
vo.setData(dto.getData());
|
vo.setFailTimes(dto.getFailTimes());
|
vo.setRetryTimes(dto.getRetryTimes());
|
vo.setRetryTime(dto.getRetryTime());
|
vo.setLastRetryTime(dto.getLastRetryTime());
|
vo.setRequestPayload(JSON.toJSONString(dto));
|
return vo;
|
}
|
|
private NotifyReportVo buildLogVo(HttpRequestLog log) {
|
NotifyReportVo vo = new NotifyReportVo();
|
vo.setSourceType("log");
|
vo.setLogId(log.getId());
|
vo.setCreateTime(log.getCreateTime());
|
vo.setResult(log.getResult());
|
vo.setResponse(log.getResponse());
|
vo.setRequestPayload(log.getRequest());
|
|
NotifyDto dto = parseNotifyDto(log.getRequest());
|
if (dto != null) {
|
vo.setId(dto.getId());
|
vo.setNotifyType(dto.getNotifyType());
|
vo.setDevice(dto.getDevice());
|
vo.setTaskNo(dto.getTaskNo());
|
vo.setSuperTaskNo(dto.getSuperTaskNo());
|
vo.setMsgType(dto.getMsgType());
|
vo.setMsgDesc(dto.getMsgDesc());
|
vo.setData(dto.getData());
|
vo.setFailTimes(dto.getFailTimes());
|
vo.setRetryTimes(dto.getRetryTimes());
|
vo.setRetryTime(dto.getRetryTime());
|
vo.setLastRetryTime(dto.getLastRetryTime());
|
} else {
|
vo.setData(log.getRequest());
|
}
|
return vo;
|
}
|
|
private boolean matchesQueue(NotifyReportVo record, String notifyType, Integer device, String taskNo,
|
String superTaskNo, String msgType, String condition) {
|
if (!Cools.isEmpty(notifyType) && !notifyType.equals(record.getNotifyType())) {
|
return false;
|
}
|
if (device != null && !device.equals(record.getDevice())) {
|
return false;
|
}
|
if (!containsValue(record.getTaskNo(), taskNo)) {
|
return false;
|
}
|
if (!containsValue(record.getSuperTaskNo(), superTaskNo)) {
|
return false;
|
}
|
if (!containsValue(record.getMsgType(), msgType) && !containsValue(record.getMsgDesc(), msgType)) {
|
return false;
|
}
|
if (Cools.isEmpty(condition)) {
|
return true;
|
}
|
return containsValue(record.getTaskNo(), condition)
|
|| containsValue(record.getSuperTaskNo(), condition)
|
|| containsValue(record.getMsgType(), condition)
|
|| containsValue(record.getMsgDesc(), condition)
|
|| containsValue(record.getData(), condition)
|
|| containsValue(record.getNotifyType$(), condition)
|
|| containsValue(record.getRedisKey(), condition);
|
}
|
|
private boolean containsValue(String source, String target) {
|
if (Cools.isEmpty(target)) {
|
return true;
|
}
|
if (Cools.isEmpty(source)) {
|
return false;
|
}
|
return source.contains(target);
|
}
|
|
private Map<String, Object> resendQueue(String redisKey, String notifyUri, String notifyUriPath) {
|
Map<String, Object> detail = new HashMap<>();
|
detail.put("sourceType", "queue");
|
detail.put("redisKey", redisKey);
|
|
Object object = redisUtil.get(redisKey);
|
if (!(object instanceof NotifyDto)) {
|
detail.put("success", false);
|
detail.put("message", "队列通知不存在或已被消费");
|
return detail;
|
}
|
|
NotifyDto notifyDto = (NotifyDto) object;
|
NotifySendResult result = notifyAsyncService.sendNotifyNow(notifyUri, notifyUriPath, redisKey, notifyDto, true, false);
|
detail.put("success", result.isSuccess());
|
detail.put("message", result.getMessage());
|
detail.put("taskNo", notifyDto.getTaskNo());
|
detail.put("superTaskNo", notifyDto.getSuperTaskNo());
|
detail.put("response", result.getResponse());
|
return detail;
|
}
|
|
private Map<String, Object> resendLog(Long logId, String notifyUri, String notifyUriPath) {
|
Map<String, Object> detail = new HashMap<>();
|
detail.put("sourceType", "log");
|
detail.put("logId", logId);
|
|
HttpRequestLog log = httpRequestLogService.selectById(logId);
|
if (log == null) {
|
detail.put("success", false);
|
detail.put("message", "通知日志不存在");
|
return detail;
|
}
|
|
NotifyDto notifyDto = parseNotifyDto(log.getRequest());
|
if (notifyDto == null) {
|
detail.put("success", false);
|
detail.put("message", "日志请求报文无法解析为通知对象");
|
return detail;
|
}
|
|
NotifySendResult result = notifyAsyncService.sendNotifyNow(notifyUri, notifyUriPath, null, notifyDto, false, false);
|
detail.put("success", result.isSuccess());
|
detail.put("message", result.getMessage());
|
detail.put("taskNo", notifyDto.getTaskNo());
|
detail.put("superTaskNo", notifyDto.getSuperTaskNo());
|
detail.put("response", result.getResponse());
|
return detail;
|
}
|
|
private NotifyDto parseNotifyDto(String request) {
|
if (Cools.isEmpty(request)) {
|
return null;
|
}
|
try {
|
return JSON.parseObject(request, NotifyDto.class);
|
} catch (Exception ignored) {
|
return null;
|
}
|
}
|
|
private String getConfigValue(String code) {
|
Config config = configService.selectOne(new EntityWrapper<Config>().eq("code", code));
|
return config == null ? null : config.getValue();
|
}
|
|
private String buildNotifyEndpoint(String notifyUri, String notifyUriPath) {
|
if (Cools.isEmpty(notifyUri) || Cools.isEmpty(notifyUriPath)) {
|
return null;
|
}
|
return notifyUri + notifyUriPath;
|
}
|
}
|