feat: 初始化短剧服务端(管理后台 API + 客户端 API)

Spring Boot 3.2 / MyBatis-Plus / PostgreSQL,7 个 Maven 模块;含认证鉴权、内容与媒资管理、操作日志,以及客户端 /app/** 接口。
This commit is contained in:
Vicky committed 2026-10-14 18:02:47 +08:00
commit a4aa749cc6
152 files changed
+8027

No files matched your search

+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.reelshort</groupId>
<artifactId>reelshort</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>reelshort-common</artifactId>
<name>reelshort-common</name>
<description>通用模块:统一响应、分页、异常、工具</description>
</project>
@@ -0,0 +1,39 @@
package com.reelshort.common.exception;
import lombok.Getter;
/**
* 全局错误码,详见 docs/architecture-design.md 附录 A。
*/
@Getter
public enum ErrorCode {
SUCCESS(0, "ok"),
BAD_REQUEST(400, "参数校验失败"),
UNAUTHORIZED(401, "未登录或登录已过期"),
FORBIDDEN(403, "无权限"),
NOT_FOUND(404, "资源不存在"),
TOO_MANY_REQUESTS(429, "请求过于频繁"),
INTERNAL_ERROR(500, "系统异常"),
LOGIN_FAILED(100000, "账号或密码错误"),
ACCOUNT_DISABLED(100001, "账号已停用"),
COIN_NOT_ENOUGH(100002, "金币余额不足"),
EPISODE_NOT_AVAILABLE(100003, "剧集未发布或不存在"),
EPISODE_UNLOCKED(100004, "剧集已解锁"),
ORDER_STATUS_INVALID(100005, "订单已支付或已关闭"),
VIP_EXPIRED(100006, "VIP 已过期"),
DATA_EXISTS(200001, "数据已存在"),
DATA_NOT_FOUND(200002, "数据不存在"),
OPERATION_NOT_ALLOWED(200003, "当前状态不允许该操作");
private final int code;
private final String message;
ErrorCode(int code, String message) {
this.code = code;
this.message = message;
}
}
@@ -0,0 +1,31 @@
package com.reelshort.common.exception;
import lombok.Getter;
/**
* 业务异常:带业务错误码,由全局异常处理器转成统一响应。
*/
@Getter
public class ServiceException extends RuntimeException {
private final int code;
public ServiceException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.code = errorCode.getCode();
}
public ServiceException(ErrorCode errorCode, String message) {
super(message);
this.code = errorCode.getCode();
}
public ServiceException(String message) {
super(message);
this.code = ErrorCode.INTERNAL_ERROR.getCode();
}
public static ServiceException of(ErrorCode errorCode) {
return new ServiceException(errorCode);
}
}
@@ -0,0 +1,30 @@
package com.reelshort.common.pojo;
import lombok.Data;
/**
* 分页请求参数,pageIndex 从 1 开始,与前端一致。
*/
@Data
public class PageParam {
private static final int MAX_PAGE_SIZE = 200;
private Integer pageIndex = 1;
private Integer pageSize = 10;
public long getOffset() {
return (long) (getSafePageIndex() - 1) * getSafePageSize();
}
public int getSafePageIndex() {
return pageIndex == null || pageIndex < 1 ? 1 : pageIndex;
}
public int getSafePageSize() {
if (pageSize == null || pageSize < 1) {
return 10;
}
return Math.min(pageSize, MAX_PAGE_SIZE);
}
}
@@ -0,0 +1,21 @@
package com.reelshort.common.pojo;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.List;
/**
* 分页响应,字段名与前端表格组件(total / list)保持一致。
*/
@Getter
@AllArgsConstructor
public class PageResult<T> {
private final long total;
private final List<T> list;
public static <T> PageResult<T> empty() {
return new PageResult<>(0L, List.of());
}
}
@@ -0,0 +1,37 @@
package com.reelshort.common.pojo;
import com.reelshort.common.exception.ErrorCode;
import lombok.Getter;
/**
* 统一响应体,与前端 axios 拦截器约定一致:{ code, message, data }。
*/
@Getter
public class Result<T> {
private final int code;
private final String message;
private final T data;
private Result(int code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
public static Result<Void> ok() {
return new Result<>(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMessage(), null);
}
public static <T> Result<T> ok(T data) {
return new Result<>(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMessage(), data);
}
public static <T> Result<T> error(ErrorCode errorCode) {
return new Result<>(errorCode.getCode(), errorCode.getMessage(), null);
}
public static <T> Result<T> error(int code, String message) {
return new Result<>(code, message, null);
}
}