diff --git a/pom.xml b/pom.xml
index fe7db59..e55430c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -57,6 +57,23 @@
spring-boot-starter-test
test
+
+
+ cn.hutool
+ hutool-all
+ 5.8.38
+
+
+
+ com.github.xiaoymin
+ knife4j-openapi3-jakarta-spring-boot-starter
+ 4.4.0
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
diff --git a/src/main/java/com/huangge1199/longaicodemother/common/DeleteRequest.java b/src/main/java/com/huangge1199/longaicodemother/common/DeleteRequest.java
new file mode 100644
index 0000000..283e2a3
--- /dev/null
+++ b/src/main/java/com/huangge1199/longaicodemother/common/DeleteRequest.java
@@ -0,0 +1,22 @@
+package com.huangge1199.longaicodemother.common;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 通用的删除请求类
+ *
+ * @author huangge1199
+ * @since 2025/6/30 16:21:47
+ */
+@Data
+public class DeleteRequest implements Serializable {
+
+ /**
+ * id
+ */
+ private Long id;
+
+ private static final long serialVersionUID = 1L;
+}
diff --git a/src/main/java/com/huangge1199/longaicodemother/common/HttpStatus.java b/src/main/java/com/huangge1199/longaicodemother/common/HttpStatus.java
new file mode 100644
index 0000000..ec3b0c6
--- /dev/null
+++ b/src/main/java/com/huangge1199/longaicodemother/common/HttpStatus.java
@@ -0,0 +1,94 @@
+package com.huangge1199.longaicodemother.common;
+
+/**
+ * 返回状态码
+ *
+ * @author ruoyi
+ */
+public class HttpStatus
+{
+ /**
+ * 操作成功
+ */
+ public static final int SUCCESS = 200;
+
+ /**
+ * 对象创建成功
+ */
+ public static final int CREATED = 201;
+
+ /**
+ * 请求已经被接受
+ */
+ public static final int ACCEPTED = 202;
+
+ /**
+ * 操作已经执行成功,但是没有返回数据
+ */
+ public static final int NO_CONTENT = 204;
+
+ /**
+ * 资源已被移除
+ */
+ public static final int MOVED_PERM = 301;
+
+ /**
+ * 重定向
+ */
+ public static final int SEE_OTHER = 303;
+
+ /**
+ * 资源没有被修改
+ */
+ public static final int NOT_MODIFIED = 304;
+
+ /**
+ * 参数列表错误(缺少,格式不匹配)
+ */
+ public static final int BAD_REQUEST = 400;
+
+ /**
+ * 未授权
+ */
+ public static final int UNAUTHORIZED = 401;
+
+ /**
+ * 访问受限,授权过期
+ */
+ public static final int FORBIDDEN = 403;
+
+ /**
+ * 资源,服务未找到
+ */
+ public static final int NOT_FOUND = 404;
+
+ /**
+ * 不允许的http方法
+ */
+ public static final int BAD_METHOD = 405;
+
+ /**
+ * 资源冲突,或者资源被锁
+ */
+ public static final int CONFLICT = 409;
+
+ /**
+ * 不支持的数据,媒体类型
+ */
+ public static final int UNSUPPORTED_TYPE = 415;
+
+ /**
+ * 系统内部错误
+ */
+ public static final int ERROR = 500;
+
+ /**
+ * 接口未实现
+ */
+ public static final int NOT_IMPLEMENTED = 501;
+
+ /**
+ * 系统警告消息
+ */
+ public static final int WARN = 601;
+}
diff --git a/src/main/java/com/huangge1199/longaicodemother/common/PageRequest.java b/src/main/java/com/huangge1199/longaicodemother/common/PageRequest.java
new file mode 100644
index 0000000..f038a31
--- /dev/null
+++ b/src/main/java/com/huangge1199/longaicodemother/common/PageRequest.java
@@ -0,0 +1,33 @@
+package com.huangge1199.longaicodemother.common;
+
+import lombok.Data;
+
+/**
+ * 通用的分页请求类
+ *
+ * @author huangge1199
+ * @since 2025/6/30 16:07:29
+ */
+@Data
+public class PageRequest {
+
+ /**
+ * 当前页号
+ */
+ private int current = 1;
+
+ /**
+ * 页面大小
+ */
+ private int pageSize = 10;
+
+ /**
+ * 排序字段
+ */
+ private String sortField;
+
+ /**
+ * 排序顺序(默认升序)
+ */
+ private String sortOrder = "descend";
+}
diff --git a/src/main/java/com/huangge1199/longaicodemother/common/R.java b/src/main/java/com/huangge1199/longaicodemother/common/R.java
new file mode 100644
index 0000000..1961024
--- /dev/null
+++ b/src/main/java/com/huangge1199/longaicodemother/common/R.java
@@ -0,0 +1,113 @@
+package com.huangge1199.longaicodemother.common;
+
+import java.io.Serializable;
+
+/**
+ * 响应信息主体
+ *
+ * @author ruoyi
+ */
+public class R implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 成功
+ */
+ public static final int SUCCESS = HttpStatus.SUCCESS;
+
+ /**
+ * 失败
+ */
+ public static final int FAIL = HttpStatus.ERROR;
+
+ private int code;
+
+ private String msg;
+
+ private T data;
+
+ public static R ok() {
+ return restResult(null, SUCCESS, "操作成功");
+ }
+
+ public static R ok(T data) {
+ return restResult(data, SUCCESS, "操作成功");
+ }
+
+ public static R ok(T data, String msg) {
+ return restResult(data, SUCCESS, msg);
+ }
+
+ public static R fail() {
+ return restResult(null, FAIL, "操作失败");
+ }
+
+ public static R fail(String msg) {
+ return restResult(null, FAIL, msg);
+ }
+
+ public static R fail(Exception e) {
+ String msg = e.getMessage();
+ if (e.getCause() != null) {
+ msg = e.getCause().getMessage();
+ } else {
+ return restResult(null, FAIL, msg);
+ }
+ if (e.getCause().getCause() != null) {
+ msg = e.getCause().getCause().getMessage();
+ }
+ return restResult(null, FAIL, msg);
+ }
+
+ public static R fail(T data) {
+ return restResult(data, FAIL, "操作失败");
+ }
+
+ public static R fail(T data, String msg) {
+ return restResult(data, FAIL, msg);
+ }
+
+ public static R fail(int code, String msg) {
+ return restResult(null, code, msg);
+ }
+
+ private static R restResult(T data, int code, String msg) {
+ R apiResult = new R<>();
+ apiResult.setCode(code);
+ apiResult.setData(data);
+ apiResult.setMsg(msg);
+ return apiResult;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getMsg() {
+ return msg;
+ }
+
+ public void setMsg(String msg) {
+ this.msg = msg;
+ }
+
+ public T getData() {
+ return data;
+ }
+
+ public void setData(T data) {
+ this.data = data;
+ }
+
+ public static Boolean isError(R ret) {
+ return !isSuccess(ret);
+ }
+
+ public static Boolean isSuccess(R ret) {
+ return R.SUCCESS == ret.getCode();
+ }
+}
diff --git a/src/main/java/com/huangge1199/longaicodemother/config/CorsConfig.java b/src/main/java/com/huangge1199/longaicodemother/config/CorsConfig.java
new file mode 100644
index 0000000..099739e
--- /dev/null
+++ b/src/main/java/com/huangge1199/longaicodemother/config/CorsConfig.java
@@ -0,0 +1,29 @@
+package com.huangge1199.longaicodemother.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * CorsConfig
+ * 全局跨域配置
+ *
+ * @author huangge1199
+ * @since 2025/6/27 16:37:44
+ */
+@Configuration
+public class CorsConfig implements WebMvcConfigurer {
+
+ @Override
+ public void addCorsMappings(CorsRegistry registry) {
+ // 覆盖所有请求
+ registry.addMapping("/**")
+ // 允许发送 Cookie
+ .allowCredentials(true)
+ // 放行哪些域名(必须用 patterns,否则 * 会和 allowCredentials 冲突)
+ .allowedOriginPatterns("*")
+ .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
+ .allowedHeaders("*")
+ .exposedHeaders("*");
+ }
+}
diff --git a/src/main/java/com/huangge1199/longaicodemother/controller/HealthController.java b/src/main/java/com/huangge1199/longaicodemother/controller/HealthController.java
new file mode 100644
index 0000000..578ea3d
--- /dev/null
+++ b/src/main/java/com/huangge1199/longaicodemother/controller/HealthController.java
@@ -0,0 +1,28 @@
+package com.huangge1199.longaicodemother.controller;
+
+import com.huangge1199.longaicodemother.common.R;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 健康检测controller
+ * HealthController
+ *
+ * @author huangge1199
+ * @since 2025/8/4 14:05:38
+ */
+@RestController
+@RequestMapping("/health")
+public class HealthController {
+
+ /**
+ * 健康检测接口
+ * @return 结果
+ */
+ @GetMapping("/")
+ public R healthCheck() {
+ return R.ok();
+ }
+}
+
diff --git a/src/main/java/com/huangge1199/longaicodemother/exception/ErrorCode.java b/src/main/java/com/huangge1199/longaicodemother/exception/ErrorCode.java
new file mode 100644
index 0000000..0b930bd
--- /dev/null
+++ b/src/main/java/com/huangge1199/longaicodemother/exception/ErrorCode.java
@@ -0,0 +1,38 @@
+package com.huangge1199.longaicodemother.exception;
+
+import lombok.Getter;
+
+/**
+ * 异常信息
+ *
+ * @author huangge1199
+ * @since 2025/6/27 16:26:54
+ */
+@Getter
+public enum ErrorCode {
+
+ SUCCESS(200, "ok"),
+ PARAMS_ERROR(40000, "请求参数错误"),
+ NOT_LOGIN_ERROR(40100, "未登录"),
+ NO_AUTH_ERROR(40101, "无权限"),
+ NOT_FOUND_ERROR(40400, "请求数据不存在"),
+ FORBIDDEN_ERROR(40300, "禁止访问"),
+ SYSTEM_ERROR(50000, "系统内部异常"),
+ OPERATION_ERROR(50001, "操作失败");
+
+ /**
+ * 状态码
+ */
+ private final int code;
+
+ /**
+ * 信息
+ */
+ private final String message;
+
+ ErrorCode(int code, String message) {
+ this.code = code;
+ this.message = message;
+ }
+
+}
diff --git a/src/main/java/com/huangge1199/longaicodemother/exception/GlobalExceptionHandler.java b/src/main/java/com/huangge1199/longaicodemother/exception/GlobalExceptionHandler.java
new file mode 100644
index 0000000..423aff2
--- /dev/null
+++ b/src/main/java/com/huangge1199/longaicodemother/exception/GlobalExceptionHandler.java
@@ -0,0 +1,29 @@
+package com.huangge1199.longaicodemother.exception;
+
+import com.huangge1199.longaicodemother.common.R;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+/**
+ * 全局异常处理器
+ *
+ * @author huangge1199
+ * @since 2025/6/30 10:56:33
+ */
+@RestControllerAdvice
+@Slf4j
+public class GlobalExceptionHandler {
+
+ @ExceptionHandler(MyException.class)
+ public R> businessExceptionHandler(MyException e) {
+ log.error("BusinessException", e);
+ return R.fail(e.getCode(), e.getMessage());
+ }
+
+ @ExceptionHandler(RuntimeException.class)
+ public R> businessExceptionHandler(RuntimeException e) {
+ log.error("RuntimeException", e);
+ return R.fail(ErrorCode.SYSTEM_ERROR, "系统错误");
+ }
+}
diff --git a/src/main/java/com/huangge1199/longaicodemother/exception/MyException.java b/src/main/java/com/huangge1199/longaicodemother/exception/MyException.java
new file mode 100644
index 0000000..9fab075
--- /dev/null
+++ b/src/main/java/com/huangge1199/longaicodemother/exception/MyException.java
@@ -0,0 +1,36 @@
+package com.huangge1199.longaicodemother.exception;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 自定义业务异常
+ *
+ * @author huangge1199
+ * @since 2025/6/30 10:42:10
+ */
+@Setter
+@Getter
+public class MyException extends RuntimeException {
+
+ /**
+ * 错误码
+ */
+ private final int code;
+
+ public MyException(int code, String message) {
+ super(message);
+ this.code = code;
+ }
+
+ public MyException(ErrorCode errorCode) {
+ super(errorCode.getMessage());
+ this.code = errorCode.getCode();
+ }
+
+ public MyException(ErrorCode errorCode, String message) {
+ super(message);
+ this.code = errorCode.getCode();
+ }
+
+}
diff --git a/src/main/java/com/huangge1199/longaicodemother/exception/ThrowUtils.java b/src/main/java/com/huangge1199/longaicodemother/exception/ThrowUtils.java
new file mode 100644
index 0000000..f34f22f
--- /dev/null
+++ b/src/main/java/com/huangge1199/longaicodemother/exception/ThrowUtils.java
@@ -0,0 +1,44 @@
+package com.huangge1199.longaicodemother.exception;
+
+/**
+ * 异常处理工具类
+ *
+ * @author huangge1199
+ * @since 2025/6/30 11:00:12
+ */
+public class ThrowUtils {
+
+ /**
+ * 条件成立则抛异常
+ *
+ * @param condition 条件
+ * @param runtimeException 异常
+ */
+ public static void throwIf(boolean condition, RuntimeException runtimeException) {
+ if (condition) {
+ throw runtimeException;
+ }
+ }
+
+ /**
+ * 条件成立则抛异常
+ *
+ * @param condition 条件
+ * @param errorCode 错误码
+ */
+ public static void throwIf(boolean condition, ErrorCode errorCode) {
+ throwIf(condition, new MyException(errorCode));
+ }
+
+ /**
+ * 条件成立则抛异常
+ *
+ * @param condition 条件
+ * @param errorCode 错误码
+ * @param message 错误信息
+ */
+ public static void throwIf(boolean condition, ErrorCode errorCode, String message) {
+ throwIf(condition, new MyException(errorCode, message));
+ }
+
+}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 42c1856..677ebd7 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -4,4 +4,14 @@ spring:
server:
port: 8123
servlet:
- context-path: /api
\ No newline at end of file
+ context-path: /api
+# springdoc-openapi
+springdoc:
+ group-configs:
+ - group: 'default'
+ packages-to-scan: com.huangge1199.longaicodemother.controller
+# knife4j
+knife4j:
+ enable: true
+ setting:
+ language: zh_cn