diff --git a/push-service/src/main/java/com/xuqm/push/controller/PushManagementController.java b/push-service/src/main/java/com/xuqm/push/controller/PushManagementController.java new file mode 100644 index 0000000..8d01b1c --- /dev/null +++ b/push-service/src/main/java/com/xuqm/push/controller/PushManagementController.java @@ -0,0 +1,67 @@ +package com.xuqm.push.controller; + +import com.xuqm.common.model.ApiResponse; +import com.xuqm.push.entity.DeviceLoginLogEntity; +import com.xuqm.push.service.PushDiagnosticsService; +import org.springframework.data.domain.Page; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +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.Map; + +@RestController +@RequestMapping("/api/push/admin") +public class PushManagementController { + + private final PushDiagnosticsService diagnosticsService; + + public PushManagementController(PushDiagnosticsService diagnosticsService) { + this.diagnosticsService = diagnosticsService; + } + + @GetMapping("/user-status") + public ResponseEntity> userStatus( + @RequestParam String appId, + @RequestParam String userId) { + return ResponseEntity.ok(ApiResponse.success(diagnosticsService.searchByUserId(appId, userId))); + } + + @GetMapping("/device-logs") + public ResponseEntity>> deviceLogs( + @RequestParam String appId, + @RequestParam String userId, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "20") int size) { + Page result = diagnosticsService.deviceLogs(appId, userId, page, size); + return ResponseEntity.ok(ApiResponse.success(Map.of( + "content", result.getContent(), + "total", result.getTotalElements(), + "totalPages", result.getTotalPages() + ))); + } + + @PostMapping("/test-offline") + public ResponseEntity> testOffline( + @RequestBody TestOfflineRequest request) { + PushDiagnosticsService.TestPushResult result = diagnosticsService.sendTestOfflineMessage( + request.appId(), + request.userId(), + request.title(), + request.body(), + request.payload()); + return ResponseEntity.ok(ApiResponse.success(result)); + } + + public record TestOfflineRequest( + String appId, + String userId, + String title, + String body, + String payload + ) {} +} diff --git a/push-service/src/main/java/com/xuqm/push/service/PushDiagnosticsService.java b/push-service/src/main/java/com/xuqm/push/service/PushDiagnosticsService.java index 0432196..62d818e 100644 --- a/push-service/src/main/java/com/xuqm/push/service/PushDiagnosticsService.java +++ b/push-service/src/main/java/com/xuqm/push/service/PushDiagnosticsService.java @@ -90,6 +90,28 @@ public class PushDiagnosticsService { devices.stream().map(DeviceInfo::from).toList()); } + public PushTokenDiagnostics searchByUserId(String appId, String userId) { + ImPresenceClient.PresenceStatus presence = presenceClient.userStatus(appId, userId) + .orElse(new ImPresenceClient.PresenceStatus(appId, userId, false, 0L)); + List devices = tokenRepository.findByAppIdAndUserIdOrderByLastLoginAtDescUpdatedAtDesc(appId, userId); + List deliverableDevices = pushDispatcher.selectedPushTargets(appId, userId) + .stream() + .map(DeviceInfo::from) + .toList(); + DeviceInfo deliverable = deliverableDevices.isEmpty() ? null : deliverableDevices.get(0); + boolean canSendOffline = !presence.online() && !deliverableDevices.isEmpty(); + return new PushTokenDiagnostics( + "USER", + appId, + userId, + presence.online(), + presence.lastSeenAt(), + canSendOffline, + deliverable, + deliverableDevices, + devices.stream().map(DeviceInfo::from).toList()); + } + public TestPushResult sendTestOfflineMessage(String appId, String userId, String title, String body, String payload) { List targets = pushDispatcher.selectedPushTargets(appId, userId) .stream()