test(cache): 修复CacheConfigTest边界值测试
- 修改 shouldVerifyCacheManager_withMaximumIntegerTtl 为 shouldVerifyCacheManager_withMaximumAllowedTtl - 使用正确的最大TTL值(10080分钟,7天)而不是 Integer.MAX_VALUE - 新增 shouldThrowException_whenTtlExceedsMaximum 测试验证边界检查 - 所有1266个测试用例通过 - 覆盖率: 指令81.89%, 行88.48%, 分支51.55% docs: 添加项目状态报告 - 生成 PROJECT_STATUS_REPORT.md 详细记录项目当前状态 - 包含质量指标、已完成功能、待办事项和技术债务
This commit is contained in:
@@ -1,8 +1,14 @@
|
||||
package com.mosquito.project.dto;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
public class ActivityGraphResponse {
|
||||
@NoArgsConstructor
|
||||
public class ActivityGraphResponse implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private List<Node> nodes;
|
||||
private List<Edge> edges;
|
||||
@@ -28,7 +34,10 @@ public class ActivityGraphResponse {
|
||||
this.edges = edges;
|
||||
}
|
||||
|
||||
public static class Node {
|
||||
@NoArgsConstructor
|
||||
public static class Node implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String id;
|
||||
private String label;
|
||||
|
||||
@@ -54,7 +63,10 @@ public class ActivityGraphResponse {
|
||||
}
|
||||
}
|
||||
|
||||
public static class Edge {
|
||||
@NoArgsConstructor
|
||||
public static class Edge implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String from;
|
||||
private String to;
|
||||
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
package com.mosquito.project.dto;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
public class ActivityStatsResponse {
|
||||
@NoArgsConstructor
|
||||
public class ActivityStatsResponse implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private long totalParticipants;
|
||||
private long totalShares;
|
||||
@@ -38,7 +44,10 @@ public class ActivityStatsResponse {
|
||||
this.dailyStats = dailyStats;
|
||||
}
|
||||
|
||||
public static class DailyStats {
|
||||
@NoArgsConstructor
|
||||
public static class DailyStats implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String date;
|
||||
private int participants;
|
||||
private int shares;
|
||||
|
||||
31
src/main/java/com/mosquito/project/dto/ApiKeyResponse.java
Normal file
31
src/main/java/com/mosquito/project/dto/ApiKeyResponse.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package com.mosquito.project.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
/**
|
||||
* API密钥响应DTO
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class ApiKeyResponse {
|
||||
private String message;
|
||||
private String data;
|
||||
private String error;
|
||||
|
||||
public ApiKeyResponse(String message, String data, String error) {
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public static ApiKeyResponse success(String data) {
|
||||
return new ApiKeyResponse("操作成功", data, null);
|
||||
}
|
||||
|
||||
public static ApiKeyResponse error(String error) {
|
||||
return new ApiKeyResponse("操作失败", null, error);
|
||||
}
|
||||
}
|
||||
179
src/main/java/com/mosquito/project/dto/ApiResponse.java
Normal file
179
src/main/java/com/mosquito/project/dto/ApiResponse.java
Normal file
@@ -0,0 +1,179 @@
|
||||
package com.mosquito.project.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 统一API响应格式
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class ApiResponse<T> {
|
||||
|
||||
/**
|
||||
* HTTP状态码
|
||||
*/
|
||||
private int code;
|
||||
|
||||
/**
|
||||
* 响应消息
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* 响应数据
|
||||
*/
|
||||
private T data;
|
||||
|
||||
/**
|
||||
* 元数据(分页等信息)
|
||||
*/
|
||||
private Meta meta;
|
||||
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
private Error error;
|
||||
|
||||
/**
|
||||
* 时间戳
|
||||
*/
|
||||
private LocalDateTime timestamp;
|
||||
|
||||
/**
|
||||
* 请求追踪ID
|
||||
*/
|
||||
private String traceId;
|
||||
|
||||
public static <T> ApiResponse<T> success(T data) {
|
||||
return ApiResponse.<T>builder()
|
||||
.code(200)
|
||||
.message("success")
|
||||
.data(data)
|
||||
.timestamp(LocalDateTime.now())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> success(T data, String message) {
|
||||
return ApiResponse.<T>builder()
|
||||
.code(200)
|
||||
.message(message)
|
||||
.data(data)
|
||||
.timestamp(LocalDateTime.now())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> paginated(T data, int page, int size, long total) {
|
||||
Meta meta = Meta.createPagination(page, size, total);
|
||||
return ApiResponse.<T>builder()
|
||||
.code(200)
|
||||
.message("success")
|
||||
.data(data)
|
||||
.meta(meta)
|
||||
.timestamp(LocalDateTime.now())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> error(int code, String message) {
|
||||
return ApiResponse.<T>builder()
|
||||
.code(code)
|
||||
.message(message)
|
||||
.timestamp(LocalDateTime.now())
|
||||
.error(new Error(message))
|
||||
.build();
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> error(int code, String message, Object details) {
|
||||
return ApiResponse.<T>builder()
|
||||
.code(code)
|
||||
.message(message)
|
||||
.timestamp(LocalDateTime.now())
|
||||
.error(new Error(message, details))
|
||||
.build();
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> error(int code, String message, Object details, String traceId) {
|
||||
return ApiResponse.<T>builder()
|
||||
.code(code)
|
||||
.message(message)
|
||||
.timestamp(LocalDateTime.now())
|
||||
.error(new Error(message, details))
|
||||
.traceId(traceId)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 元数据基类
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Meta {
|
||||
private PaginationMeta pagination;
|
||||
private Map<String, Object> extra;
|
||||
|
||||
public static Meta createPagination(int page, int size, long total) {
|
||||
Meta meta = new Meta();
|
||||
meta.setPagination(PaginationMeta.of(page, size, total));
|
||||
return meta;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页元数据
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class PaginationMeta {
|
||||
private int page;
|
||||
private int size;
|
||||
private long total;
|
||||
private int totalPages;
|
||||
private boolean hasNext;
|
||||
private boolean hasPrevious;
|
||||
|
||||
public static PaginationMeta of(int page, int size, long total) {
|
||||
int totalPages = (int) Math.ceil((double) total / size);
|
||||
boolean hasNext = page < totalPages - 1;
|
||||
boolean hasPrevious = page > 0;
|
||||
|
||||
return new PaginationMeta(page, size, total, totalPages, hasNext, hasPrevious);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public static class Error {
|
||||
private String message;
|
||||
private Object details;
|
||||
private String code;
|
||||
|
||||
public Error(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public Error(String message, Object details) {
|
||||
this.message = message;
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
public Error(String message, Object details, String code) {
|
||||
this.message = message;
|
||||
this.details = details;
|
||||
this.code = code;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.mosquito.project.dto;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor
|
||||
public class CreateApiKeyResponse {
|
||||
|
||||
private String apiKey;
|
||||
|
||||
43
src/main/java/com/mosquito/project/dto/ErrorResponse.java
Normal file
43
src/main/java/com/mosquito/project/dto/ErrorResponse.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package com.mosquito.project.dto;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class ErrorResponse {
|
||||
private OffsetDateTime timestamp;
|
||||
private String status;
|
||||
private String error;
|
||||
private String message;
|
||||
private String path;
|
||||
private Map<String, Object> details;
|
||||
private String traceId;
|
||||
|
||||
public ErrorResponse() {}
|
||||
|
||||
public ErrorResponse(OffsetDateTime timestamp, String path, String code, String message, Map<String, String> errors) {
|
||||
this.timestamp = timestamp;
|
||||
this.path = path;
|
||||
this.status = code;
|
||||
this.message = message;
|
||||
if (errors != null) {
|
||||
this.details = new HashMap<>(errors);
|
||||
}
|
||||
}
|
||||
|
||||
public OffsetDateTime getTimestamp() { return timestamp; }
|
||||
public void setTimestamp(OffsetDateTime timestamp) { this.timestamp = timestamp; }
|
||||
public String getStatus() { return status; }
|
||||
public void setStatus(String status) { this.status = status; }
|
||||
public String getError() { return error; }
|
||||
public void setError(String error) { this.error = error; }
|
||||
public String getMessage() { return message; }
|
||||
public void setMessage(String message) { this.message = message; }
|
||||
public String getPath() { return path; }
|
||||
public void setPath(String path) { this.path = path; }
|
||||
public Map<String, Object> getDetails() { return details; }
|
||||
public void setDetails(Map<String, Object> details) { this.details = details; }
|
||||
public String getTraceId() { return traceId; }
|
||||
public void setTraceId(String traceId) { this.traceId = traceId; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.mosquito.project.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
public class RegisterCallbackRequest {
|
||||
@NotBlank
|
||||
private String trackingId;
|
||||
private String externalUserId;
|
||||
private Long timestamp;
|
||||
|
||||
public String getTrackingId() { return trackingId; }
|
||||
public void setTrackingId(String trackingId) { this.trackingId = trackingId; }
|
||||
public String getExternalUserId() { return externalUserId; }
|
||||
public void setExternalUserId(String externalUserId) { this.externalUserId = externalUserId; }
|
||||
public Long getTimestamp() { return timestamp; }
|
||||
public void setTimestamp(Long timestamp) { this.timestamp = timestamp; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.mosquito.project.dto;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor
|
||||
public class RevealApiKeyResponse {
|
||||
private String apiKey;
|
||||
private String message;
|
||||
|
||||
public RevealApiKeyResponse(String apiKey, String message) {
|
||||
this.apiKey = apiKey;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getApiKey() { return apiKey; }
|
||||
public void setApiKey(String apiKey) { this.apiKey = apiKey; }
|
||||
public String getMessage() { return message; }
|
||||
public void setMessage(String message) { this.message = message; }
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.mosquito.project.dto;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Map;
|
||||
|
||||
@NoArgsConstructor
|
||||
public class ShareMetricsResponse {
|
||||
private Long activityId;
|
||||
private OffsetDateTime startTime;
|
||||
private OffsetDateTime endTime;
|
||||
private long totalClicks;
|
||||
private long uniqueVisitors;
|
||||
private Map<String, Long> sourceDistribution;
|
||||
private Map<String, Long> hourlyDistribution;
|
||||
|
||||
public Long getActivityId() { return activityId; }
|
||||
public void setActivityId(Long activityId) { this.activityId = activityId; }
|
||||
public OffsetDateTime getStartTime() { return startTime; }
|
||||
public void setStartTime(OffsetDateTime startTime) { this.startTime = startTime; }
|
||||
public OffsetDateTime getEndTime() { return endTime; }
|
||||
public void setEndTime(OffsetDateTime endTime) { this.endTime = endTime; }
|
||||
public long getTotalClicks() { return totalClicks; }
|
||||
public void setTotalClicks(long totalClicks) { this.totalClicks = totalClicks; }
|
||||
public long getUniqueVisitors() { return uniqueVisitors; }
|
||||
public void setUniqueVisitors(long uniqueVisitors) { this.uniqueVisitors = uniqueVisitors; }
|
||||
public Map<String, Long> getSourceDistribution() { return sourceDistribution; }
|
||||
public void setSourceDistribution(Map<String, Long> sourceDistribution) { this.sourceDistribution = sourceDistribution; }
|
||||
public Map<String, Long> getHourlyDistribution() { return hourlyDistribution; }
|
||||
public void setHourlyDistribution(Map<String, Long> hourlyDistribution) { this.hourlyDistribution = hourlyDistribution; }
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.mosquito.project.dto;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
@NoArgsConstructor
|
||||
public class ShareTrackingResponse {
|
||||
private String trackingId;
|
||||
private String shortCode;
|
||||
private String originalUrl;
|
||||
private Long activityId;
|
||||
private Long inviterUserId;
|
||||
private OffsetDateTime createdAt;
|
||||
|
||||
public ShareTrackingResponse(String trackingId, String shortCode, String originalUrl, Long activityId, Long inviterUserId) {
|
||||
this.trackingId = trackingId;
|
||||
this.shortCode = shortCode;
|
||||
this.originalUrl = originalUrl;
|
||||
this.activityId = activityId;
|
||||
this.inviterUserId = inviterUserId;
|
||||
this.createdAt = OffsetDateTime.now();
|
||||
}
|
||||
|
||||
public String getTrackingId() { return trackingId; }
|
||||
public void setTrackingId(String trackingId) { this.trackingId = trackingId; }
|
||||
public String getShortCode() { return shortCode; }
|
||||
public void setShortCode(String shortCode) { this.shortCode = shortCode; }
|
||||
public String getOriginalUrl() { return originalUrl; }
|
||||
public void setOriginalUrl(String originalUrl) { this.originalUrl = originalUrl; }
|
||||
public Long getActivityId() { return activityId; }
|
||||
public void setActivityId(Long activityId) { this.activityId = activityId; }
|
||||
public Long getInviterUserId() { return inviterUserId; }
|
||||
public void setInviterUserId(Long inviterUserId) { this.inviterUserId = inviterUserId; }
|
||||
public OffsetDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(OffsetDateTime createdAt) { this.createdAt = createdAt; }
|
||||
}
|
||||
14
src/main/java/com/mosquito/project/dto/ShortenRequest.java
Normal file
14
src/main/java/com/mosquito/project/dto/ShortenRequest.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package com.mosquito.project.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public class ShortenRequest {
|
||||
@NotBlank(message = "原始URL不能为空")
|
||||
@Size(min = 10, max = 2048, message = "URL长度必须在10-2048个字符之间")
|
||||
private String originalUrl;
|
||||
|
||||
public String getOriginalUrl() { return originalUrl; }
|
||||
public void setOriginalUrl(String originalUrl) { this.originalUrl = originalUrl; }
|
||||
}
|
||||
|
||||
24
src/main/java/com/mosquito/project/dto/ShortenResponse.java
Normal file
24
src/main/java/com/mosquito/project/dto/ShortenResponse.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.mosquito.project.dto;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor
|
||||
public class ShortenResponse {
|
||||
private String code;
|
||||
private String path;
|
||||
private String originalUrl;
|
||||
|
||||
public ShortenResponse(String code, String path, String originalUrl) {
|
||||
this.code = code;
|
||||
this.path = path;
|
||||
this.originalUrl = originalUrl;
|
||||
}
|
||||
|
||||
public String getCode() { return code; }
|
||||
public void setCode(String code) { this.code = code; }
|
||||
public String getPath() { return path; }
|
||||
public void setPath(String path) { this.path = path; }
|
||||
public String getOriginalUrl() { return originalUrl; }
|
||||
public void setOriginalUrl(String originalUrl) { this.originalUrl = originalUrl; }
|
||||
}
|
||||
|
||||
@@ -3,8 +3,11 @@ package com.mosquito.project.dto;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
@NoArgsConstructor
|
||||
public class UpdateActivityRequest {
|
||||
|
||||
@NotBlank(message = "活动名称不能为空")
|
||||
|
||||
17
src/main/java/com/mosquito/project/dto/UseApiKeyRequest.java
Normal file
17
src/main/java/com/mosquito/project/dto/UseApiKeyRequest.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package com.mosquito.project.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
public class UseApiKeyRequest {
|
||||
@NotBlank(message = "API密钥不能为空")
|
||||
private String apiKey;
|
||||
|
||||
public String getApiKey() {
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
public void setApiKey(String apiKey) {
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user