diff --git a/pom.xml b/pom.xml
index a6fb3a7..be6c37d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,7 +33,7 @@
1.18.30
3.5.5
4.3.1
- 8.0.33
+ 8.0.33
@@ -43,14 +43,14 @@
-
+
org.springframework.boot
spring-boot-starter-jdbc
-
+
com.mysql
mysql-connector-j
- ${mysql.version}
+ ${mysql.version}
com.baomidou
@@ -70,26 +70,26 @@
true
-
- io.jsonwebtoken
- jjwt-api
- 0.11.5
-
-
- io.jsonwebtoken
- jjwt-impl
- 0.11.5
-
-
- io.jsonwebtoken
- jjwt-jackson
- 0.11.5
-
-
-
- org.springframework.boot
- spring-boot-starter-validation
-
+
+ io.jsonwebtoken
+ jjwt-api
+ 0.11.5
+
+
+ io.jsonwebtoken
+ jjwt-impl
+ 0.11.5
+
+
+ io.jsonwebtoken
+ jjwt-jackson
+ 0.11.5
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
org.springdoc
diff --git a/src/main/java/icu/sunway/ai_spring_example/Controller/AuthController/AuthController.java b/src/main/java/icu/sunway/ai_spring_example/Controller/AuthController/AuthController.java
new file mode 100644
index 0000000..1d603c1
--- /dev/null
+++ b/src/main/java/icu/sunway/ai_spring_example/Controller/AuthController/AuthController.java
@@ -0,0 +1,10 @@
+package icu.sunway.ai_spring_example.Controller.AuthController;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/api/v1/auth")
+public class AuthController {
+
+}
diff --git a/src/main/java/icu/sunway/ai_spring_example/Controller/AuthController/docs.md b/src/main/java/icu/sunway/ai_spring_example/Controller/AuthController/docs.md
new file mode 100644
index 0000000..0aa8619
--- /dev/null
+++ b/src/main/java/icu/sunway/ai_spring_example/Controller/AuthController/docs.md
@@ -0,0 +1,422 @@
+# Auth模块接口文档
+
+## 文档说明
+
+本文档为Auth(认证授权)模块的接口详情,遵循《接口开发通用规范文档》的所有约定,基础路径为`/api/v1/auth`,数据交互格式为JSON,字符编码UTF-8,时间戳单位为毫秒。
+
+## 1. 登录接口
+
+### 接口基本信息
+
+- 接口名称:用户登录
+- 接口路径:`/api/v1/auth/login`
+- 请求方法:POST
+- 接口描述:用户通过账号(手机号/用户名)+密码/验证码完成登录,返回登录令牌(token)
+
+### 请求头
+
+| 字段名 | 类型 | 必填性 | 示例值 |
+| --------------- | ------ | ------ | ---------------- |
+| Content-Type | String | 是 | application/json |
+| Accept-Language | String | 否 | zh-CN |
+
+### 请求参数(Body)
+
+| 字段名 | 类型 | 必填性 | 描述 | 示例值 |
+| ---------- | ------- | ------ | ------------------------------------------------ | ------------- |
+| account | String | 是 | 登录账号(手机号/用户名) | "13800138000" |
+| password | String | 否 | 登录密码(与verifyCode二选一) | "Abc123456" |
+| verifyCode | String | 否 | 验证码(与password二选一) | "8888" |
+| isRemember | Boolean | 否 | 是否记住登录(默认false,记住则token有效期延长) | true |
+
+### 响应示例(成功)
+
+```json
+{
+ "code": 200,
+ "message": "登录成功",
+ "timestamp": 1744238900000,
+ "data": {
+ "token": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjEsInVzZXJuYW1lIjoiYWRtaW4iLCJleHAiOjE3NDQ4NDM3MDB9.QP8kXjZ8e7R5t5s7k9L2m1n8b7v6c5x4s3a2d1f0g9h8j7k6l5p4o3i2u1y0t9s8r7e6w5q4a3s2d1f0g",
+ "expireTime": 1744843700000,
+ "userInfo": {
+ "userId": 1,
+ "userName": "admin",
+ "phoneNumber": "138****8000",
+ "role": "ADMIN",
+ "isEnabled": true,
+ "createTime": 1743238900000
+ }
+ }
+}
+```
+
+### 响应示例(失败)
+
+```json
+{
+ "code": 400,
+ "message": "验证码错误或已过期",
+ "timestamp": 1744238900000,
+ "data": null
+}
+```
+
+### 状态码说明
+
+| 状态码 | 说明 |
+| ------ | -------------------------------- |
+| 200 | 登录成功 |
+| 400 | 参数错误/验证码错误/账号密码错误 |
+| 403 | 账号被封禁 |
+| 429 | 登录失败次数过多,账号临时锁定 |
+| 500 | 服务器内部错误 |
+
+## 2. 退出登录接口
+
+### 接口基本信息
+
+- 接口名称:用户退出登录
+- 接口路径:`/api/v1/auth/logout`
+- 请求方法:DELETE
+- 接口描述:销毁当前用户的登录令牌,退出登录状态
+
+### 请求头
+
+| 字段名 | 类型 | 必填性 | 示例值 |
+| --------------- | ------ | ------ | ------------------------------ |
+| Authorization | String | 是 | Bearer eyJhbGciOiJIUzI1NiJ9... |
+| Content-Type | String | 是 | application/json |
+| Accept-Language | String | 否 | zh-CN |
+
+### 请求参数
+
+无业务请求参数(仅需请求头携带token)
+
+### 响应示例(成功)
+
+```json
+{
+ "code": 200,
+ "message": "退出登录成功",
+ "timestamp": 1744238900000,
+ "data": null
+}
+```
+
+### 响应示例(失败)
+
+```json
+{
+ "code": 401,
+ "message": "Token已过期,请重新登录",
+ "timestamp": 1744238900000,
+ "data": null
+}
+```
+
+### 状态码说明
+
+| 状态码 | 说明 |
+| ------ | ---------------- |
+| 200 | 退出登录成功 |
+| 401 | Token失效/未登录 |
+| 500 | 服务器内部错误 |
+
+## 3. 刷新Token接口
+
+### 接口基本信息
+
+- 接口名称:刷新登录令牌
+- 接口路径:`/api/v1/auth/refresh-token`
+- 请求方法:POST
+- 接口描述:通过旧Token刷新获取新的登录令牌,延长登录有效期
+
+### 请求头
+
+| 字段名 | 类型 | 必填性 | 示例值 |
+| --------------- | ------ | ------ | ------------------------------ |
+| Authorization | String | 是 | Bearer eyJhbGciOiJIUzI1NiJ9... |
+| Content-Type | String | 是 | application/json |
+| Accept-Language | String | 否 | zh-CN |
+
+### 请求参数(Body)
+
+| 字段名 | 类型 | 必填性 | 描述 | 示例值 |
+| ------ | ------ | ------ | ------------ | ------------------------- |
+| token | String | 是 | 旧的登录令牌 | "eyJhbGciOiJIUzI1NiJ9..." |
+
+### 响应示例(成功)
+
+```json
+{
+ "code": 200,
+ "message": "Token刷新成功",
+ "timestamp": 1744238900000,
+ "data": {
+ "newToken": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjEsInVzZXJuYW1lIjoiYWRtaW4iLCJleHAiOjE3NDU0NDg1MDB9.Z7x6y5w4v3u2t1s0r9e8w7q6a5z4s3d2f1g0h9j8k7l6p5o4i3u2y1t0s9r8e7w6q5a4s3d2f1g0h9j8k7l6p5o4i",
+ "expireTime": 1745448500000
+ }
+}
+```
+
+### 响应示例(失败)
+
+```json
+{
+ "code": 401,
+ "message": "Token已失效,无法刷新,请重新登录",
+ "timestamp": 1744238900000,
+ "data": null
+}
+```
+
+### 状态码说明
+
+| 状态码 | 说明 |
+| ------ | ------------------ |
+| 200 | Token刷新成功 |
+| 400 | 旧Token格式错误 |
+| 401 | 旧Token已过期/无效 |
+| 500 | 服务器内部错误 |
+
+## 4. 获取当前用户信息接口
+
+### 接口基本信息
+
+- 接口名称:获取当前登录用户信息
+- 接口路径:`/api/v1/auth/user/info`
+- 请求方法:GET
+- 接口描述:根据登录令牌获取当前用户的基础信息(脱敏展示敏感字段)
+
+### 请求头
+
+| 字段名 | 类型 | 必填性 | 示例值 |
+| --------------- | ------ | ------ | ------------------------------ |
+| Authorization | String | 是 | Bearer eyJhbGciOiJIUzI1NiJ9... |
+| Content-Type | String | 是 | application/json |
+| Accept-Language | String | 否 | zh-CN |
+
+### 请求参数
+
+无业务请求参数(仅需请求头携带token)
+
+### 响应示例(成功)
+
+```json
+{
+ "code": 200,
+ "message": "查询用户信息成功",
+ "timestamp": 1744238900000,
+ "data": {
+ "userId": 1,
+ "userName": "admin",
+ "phoneNumber": "138****8000",
+ "idCard": "310**********1234",
+ "roleList": ["ADMIN"],
+ "isEnabled": true,
+ "createTime": 1743238900000,
+ "createTimeStr": "2025-01-01 10:00:00",
+ "lastLoginTime": 1744152500000,
+ "lastLoginTimeStr": "2025-04-10 08:00:00"
+ }
+}
+```
+
+### 响应示例(失败)
+
+```json
+{
+ "code": 401,
+ "message": "未登录,请先登录",
+ "timestamp": 1744238900000,
+ "data": null
+}
+```
+
+### 状态码说明
+
+| 状态码 | 说明 |
+| ------ | ---------------- |
+| 200 | 查询用户信息成功 |
+| 401 | Token失效/未登录 |
+| 404 | 用户信息不存在 |
+| 500 | 服务器内部错误 |
+
+## 5. 发送登录验证码接口
+
+### 接口基本信息
+
+- 接口名称:发送登录验证码
+- 接口路径:`/api/v1/auth/send-login-code`
+- 请求方法:POST
+- 接口描述:向指定手机号发送登录验证码,限制发送频率
+
+### 请求头
+
+| 字段名 | 类型 | 必填性 | 示例值 |
+| --------------- | ------ | ------ | ---------------- |
+| Content-Type | String | 是 | application/json |
+| Accept-Language | String | 否 | zh-CN |
+
+### 请求参数(Body)
+
+| 字段名 | 类型 | 必填性 | 描述 | 示例值 |
+| ----------- | ------ | ------ | ------------------ | ------------- |
+| phoneNumber | String | 是 | 接收验证码的手机号 | "13800138000" |
+
+### 响应示例(成功)
+
+```json
+{
+ "code": 200,
+ "message": "验证码发送成功,请注意查收",
+ "timestamp": 1744238900000,
+ "data": {
+ "expireTime": 1744239200000 // 验证码过期时间戳(5分钟有效期)
+ }
+}
+```
+
+### 响应示例(失败)
+
+```json
+{
+ "code": 429,
+ "message": "验证码发送过于频繁,请1分钟后重试",
+ "timestamp": 1744238900000,
+ "data": null
+}
+```
+
+### 状态码说明
+
+| 状态码 | 说明 |
+| ------ | ------------------------------ |
+| 200 | 验证码发送成功 |
+| 400 | 手机号格式错误 |
+| 429 | 发送频率超限 |
+| 404 | 手机号未注册 |
+| 500 | 验证码发送失败(短信服务异常) |
+
+## 6. 重置密码接口
+
+### 接口基本信息
+
+- 接口名称:重置登录密码
+- 接口路径:`/api/v1/auth/reset-password`
+- 请求方法:PUT
+- 接口描述:用户通过手机号+验证码重置登录密码(全量更新密码)
+
+### 请求头
+
+| 字段名 | 类型 | 必填性 | 示例值 |
+| --------------- | ------ | ------ | ---------------- |
+| Content-Type | String | 是 | application/json |
+| Accept-Language | String | 否 | zh-CN |
+
+### 请求参数(Body)
+
+| 字段名 | 类型 | 必填性 | 描述 | 示例值 |
+| ----------- | ------ | ------ | ----------------------------------------------- | ------------- |
+| phoneNumber | String | 是 | 绑定的手机号 | "13800138000" |
+| verifyCode | String | 是 | 验证码 | "8888" |
+| newPassword | String | 是 | 新密码(需符合密码规则:8-20位,含大小写+数字) | "Abc123456" |
+
+### 响应示例(成功)
+
+```json
+{
+ "code": 200,
+ "message": "密码重置成功,请重新登录",
+ "timestamp": 1744238900000,
+ "data": null
+}
+```
+
+### 响应示例(失败)
+
+```json
+{
+ "code": 400,
+ "message": "新密码格式不符合要求,需包含大小写字母和数字,长度8-20位",
+ "timestamp": 1744238900000,
+ "data": null
+}
+```
+
+### 状态码说明
+
+| 状态码 | 说明 |
+| ------ | -------------------------------- |
+| 200 | 密码重置成功 |
+| 400 | 参数错误/验证码错误/密码格式错误 |
+| 429 | 验证码发送频率超限/验证次数过多 |
+| 404 | 手机号未注册 |
+| 500 | 服务器内部错误 |
+
+## 7. 校验Token有效性接口
+
+### 接口基本信息
+
+- 接口名称:校验Token有效性
+- 接口路径:`/api/v1/auth/verify-token`
+- 请求方法:GET
+- 接口描述:校验当前登录令牌是否有效,返回令牌基础信息
+
+### 请求头
+
+| 字段名 | 类型 | 必填性 | 示例值 |
+| --------------- | ------ | ------ | ------------------------------ |
+| Authorization | String | 是 | Bearer eyJhbGciOiJIUzI1NiJ9... |
+| Content-Type | String | 是 | application/json |
+| Accept-Language | String | 否 | zh-CN |
+
+### 请求参数
+
+无业务请求参数(仅需请求头携带token)
+
+### 响应示例(成功)
+
+```json
+{
+ "code": 200,
+ "message": "Token有效",
+ "timestamp": 1744238900000,
+ "data": {
+ "userId": 1,
+ "token": "eyJhbGciOiJIUzI1NiJ9...",
+ "isValid": true,
+ "expireTime": 1744843700000
+ }
+}
+```
+
+### 响应示例(失败)
+
+```json
+{
+ "code": 401,
+ "message": "Token无效或已过期",
+ "timestamp": 1744238900000,
+ "data": {
+ "isValid": false
+ }
+}
+```
+
+### 状态码说明
+
+| 状态码 | 说明 |
+| ------ | ---------------- |
+| 200 | Token有效 |
+| 401 | Token无效/已过期 |
+| 500 | 服务器内部错误 |
+
+## 通用说明
+
+1. 所有接口响应均遵循通用响应格式,包含`code`、`message`、`timestamp`字段,`data`字段按需返回;
+2. 敏感信息(手机号、身份证号)均做脱敏处理,符合安全规范;
+3. 接口频率限制遵循通用规范:验证码接口1分钟/次、1小时/5次,登录接口5分钟连续失败5次锁定15分钟,通用接口QPS≤10;
+4. 所有入参均做合法性校验,参数错误返回400状态码并提示具体错误信息;
+5. Token格式为`Bearer + 空格 + token`,需登录的接口未传/传错Token均返回401状态码。
diff --git a/src/main/java/icu/sunway/ai_spring_example/Controller/PermissionController/PermissionController.java b/src/main/java/icu/sunway/ai_spring_example/Controller/PermissionController/PermissionController.java
index 70a4264..3c390fa 100644
--- a/src/main/java/icu/sunway/ai_spring_example/Controller/PermissionController/PermissionController.java
+++ b/src/main/java/icu/sunway/ai_spring_example/Controller/PermissionController/PermissionController.java
@@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
@RestController
-@RequestMapping("/permission")
+@RequestMapping("/api/v1/permission")
public class PermissionController {
@Resource
diff --git a/src/main/java/icu/sunway/ai_spring_example/Controller/RoleController/RoleController.java b/src/main/java/icu/sunway/ai_spring_example/Controller/RoleController/RoleController.java
index 52bdb82..a66bac7 100644
--- a/src/main/java/icu/sunway/ai_spring_example/Controller/RoleController/RoleController.java
+++ b/src/main/java/icu/sunway/ai_spring_example/Controller/RoleController/RoleController.java
@@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
@RestController
-@RequestMapping("/role")
+@RequestMapping("/api/v1/role")
public class RoleController {
@Resource
diff --git a/src/main/java/icu/sunway/ai_spring_example/Controller/RolePermissionController/RolePermissionController.java b/src/main/java/icu/sunway/ai_spring_example/Controller/RolePermissionController/RolePermissionController.java
index 6e2e32b..12aa74f 100644
--- a/src/main/java/icu/sunway/ai_spring_example/Controller/RolePermissionController/RolePermissionController.java
+++ b/src/main/java/icu/sunway/ai_spring_example/Controller/RolePermissionController/RolePermissionController.java
@@ -11,7 +11,7 @@ import jakarta.annotation.Resource;
import java.util.List;
@RestController
-@RequestMapping("/role-permission")
+@RequestMapping("/api/v1/role-permission")
public class RolePermissionController {
@Resource
diff --git a/src/main/java/icu/sunway/ai_spring_example/Controller/UserController/UserController.java b/src/main/java/icu/sunway/ai_spring_example/Controller/UserController/UserController.java
index 8fcd251..fe5bb70 100644
--- a/src/main/java/icu/sunway/ai_spring_example/Controller/UserController/UserController.java
+++ b/src/main/java/icu/sunway/ai_spring_example/Controller/UserController/UserController.java
@@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
@RestController
-@RequestMapping("/user")
+@RequestMapping("/api/v1/user")
public class UserController {
@Resource
diff --git a/src/main/java/icu/sunway/ai_spring_example/Controller/UserRoleController/UserRoleController.java b/src/main/java/icu/sunway/ai_spring_example/Controller/UserRoleController/UserRoleController.java
index 21546a0..ac950c3 100644
--- a/src/main/java/icu/sunway/ai_spring_example/Controller/UserRoleController/UserRoleController.java
+++ b/src/main/java/icu/sunway/ai_spring_example/Controller/UserRoleController/UserRoleController.java
@@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
@RestController
-@RequestMapping("/user-role")
+@RequestMapping("/api/v1/user-role")
public class UserRoleController {
@Resource
diff --git a/src/main/java/icu/sunway/ai_spring_example/Controller/api-doc-standard.md b/src/main/java/icu/sunway/ai_spring_example/Controller/api-doc-standard.md
new file mode 100644
index 0000000..8676a52
--- /dev/null
+++ b/src/main/java/icu/sunway/ai_spring_example/Controller/api-doc-standard.md
@@ -0,0 +1,218 @@
+# 接口开发通用规范文档
+
+## 文档说明
+
+本规范为项目所有接口的通用开发准则,适用于前后端接口对接、后端接口开发、接口文档编写等场景,所有业务接口均需遵循本规范。
+
+### 基础约定
+
+- 接口基础路径:`/api/v1`(各业务模块在基础路径后追加,如Auth模块:`/api/v1/auth`)
+- 数据交互格式:JSON
+- 字符编码:UTF-8
+- 时间戳单位:毫秒(整数类型)
+- 接口版本管理:通过URL路径版本号(如v1)区分,不使用请求参数/请求头区分
+
+## 一、通用请求规范
+
+### 1. 请求方式(RESTful规范)
+
+| 操作类型 | 请求方法 | 典型场景 | 示例 |
+| ------------- | -------- | -------------------------------- | ----------------------------- |
+| 新增/提交数据 | POST | 登录、发送验证码、创建资源 | `/api/v1/auth/login` |
+| 查询数据 | GET | 获取详情、校验状态、列表查询 | `/api/v1/auth/user/info` |
+| 修改数据 | PUT | 全量更新(如重置密码、修改信息) | `/api/v1/auth/reset-password` |
+| 部分更新 | PATCH | 局部更新(如修改用户昵称) | `/api/v1/user/nickname` |
+| 删除数据 | DELETE | 退出登录、删除资源 | `/api/v1/auth/logout` |
+
+### 2. 请求头规范
+
+| 字段名 | 类型 | 必填性 | 描述 | 示例 |
+| --------------- | ------ | ------ | --------------------------------------------------------- | -------------------------------- |
+| Authorization | String | 非必选 | 登录令牌,格式为`Bearer + 空格 + token`(需登录接口必传) | "Bearer eyJhbGciOiJIUzI1NiJ9..." |
+| Content-Type | String | 必选 | 请求体格式,仅支持`application/json` | "application/json" |
+| Accept-Language | String | 非必选 | 语言类型,默认zh-CN | "zh-CN" |
+
+### 3. 分页请求参数(列表接口必传)
+
+所有列表查询接口均需支持分页,分页参数统一通过`GET`请求参数传递(POST请求可放在Body中),参数规范如下:
+
+| 字段名 | 类型 | 必填性 | 默认值 | 描述 | 示例 |
+| ------ | ------- | ------ | ------ | ----------------------------- | ---- |
+| page | Integer | 否 | 1 | 当前页码(从1开始) | 1 |
+| limit | Integer | 否 | 10 | 每页显示条数(最大不超过100) | 10 |
+
+#### 示例
+
+```plain
+GET /api/v1/user/list?current=1&size=10
+```
+
+### 4. 请求参数命名规范
+
+- 字段名使用**小驼峰命名**(如`userName`、`phoneNumber`),禁止使用下划线/连字符;
+- 布尔类型字段命名:使用`isXXX`格式(如`isRemember`、`isEnabled`);
+- 时间类字段:统一使用`createTime`、`updateTime`等,禁止使用`create_at`;
+- 参数值:手机号、身份证号等字符串类型参数,值为纯数字时仍以字符串传递。
+
+## 二、通用响应规范
+
+### 1. 基础响应格式(所有接口统一)
+
+所有接口响应必须包含`code`、`message`、`timestamp`字段,`data`字段为可选(无业务数据时返回`null`)。
+
+#### 格式定义
+
+```json
+{
+ "code": 200, // 整数,业务状态码
+ "message": "操作成功", // 字符串,提示信息(前端可直接展示)
+ "timestamp": 1744238900000, // 整数,服务器响应时间戳(毫秒)
+ "data": {} // 任意类型,业务数据(无数据时为null)
+}
+```
+
+#### 字段说明
+
+| 字段名 | 类型 | 必填性 | 描述 |
+| --------- | ------- | ------ | --------------------------------------------------------------------------- |
+| code | Integer | 是 | 业务状态码(200表示成功,非200表示异常) |
+| message | String | 是 | 响应提示信息(成功/失败描述,需友好、简洁) |
+| timestamp | Integer | 是 | 服务器处理请求的时间戳(毫秒),前端可用于时间展示/校验 |
+| data | Any | 否 | 业务数据体:1. 无数据时为null;2. 单条数据为Object;3. 列表数据遵循分页规范 |
+
+### 2. 分页响应格式(列表接口专用)
+
+列表接口的`data`字段必须遵循以下结构,禁止自定义分页字段名/格式。
+
+#### 格式定义
+
+```json
+{
+ "code": 200,
+ "message": "查询成功",
+ "timestamp": 1744238900000,
+ "data": {
+ "records": [], // 数组,当前页数据列表
+ "total": 0, // 整数,符合条件的总记录数
+ "size": 10, // 整数,每页显示条数(实际返回条数)
+ "current": 1, // 整数,当前页码
+ "pages": 0 // 整数,总页数(total/size向上取整)
+ }
+}
+```
+
+#### 字段说明
+
+| 字段名 | 类型 | 必填性 | 描述 |
+| ------- | ------- | ------ | ----------------------------------------- |
+| records | Array | 是 | 当前页数据列表(无数据时为空数组) |
+| total | Integer | 是 | 总记录数(用于计算总页数/分页展示) |
+| size | Integer | 是 | 每页请求条数(与请求参数size一致) |
+| current | Integer | 是 | 当前页码(与请求参数current一致) |
+| pages | Integer | 是 | 总页数(计算公式:Math.ceil(total/size)) |
+
+#### 分页响应示例
+
+```json
+{
+ "code": 200,
+ "message": "用户列表查询成功",
+ "timestamp": 1744238900000,
+ "data": {
+ "records": [
+ {"id": 1, "username": "admin", "role": "ADMIN"},
+ {"id": 2, "username": "user1", "role": "USER"}
+ ],
+ "total": 20,
+ "size": 10,
+ "current": 1,
+ "pages": 2
+ }
+}
+```
+
+### 3. 通用状态码规范
+
+| 状态码 | 含义 | 核心场景 |
+| ------ | -------------- | -------------------------------------- |
+| 200 | 操作成功 | 所有接口正常响应 |
+| 400 | 参数错误 | 请求参数缺失/格式错误/校验不通过 |
+| 401 | 未授权 | token失效/未登录/令牌格式错误 |
+| 403 | 禁止访问 | 账号被封禁/权限不足/IP受限 |
+| 404 | 资源不存在 | 用户不存在/接口路径错误/数据记录不存在 |
+| 409 | 资源冲突 | 用户名重复/手机号已绑定/操作重复提交 |
+| 429 | 请求过于频繁 | 验证码发送频率超限/接口调用频率超限 |
+| 500 | 服务器内部错误 | 服务端逻辑异常/第三方接口调用失败 |
+
+## 三、接口命名规范
+
+### 1. URL路径命名
+
+- 路径全部使用**小写字母**,多个单词用连字符(-)分隔(如`/api/v1/auth/refresh-token`);
+- 路径使用名词而非动词(RESTful规范),如`/api/v1/user`(用户资源)而非`/api/v1/getUser`;
+- 资源ID放在路径末尾,如`/api/v1/user/123`(查询ID为123的用户)。
+
+### 2. 响应字段命名
+
+- 与请求参数一致,使用**小驼峰命名**;
+- 时间字段:优先返回时间戳(Integer,毫秒),如需返回格式化时间,字段名加`Str`后缀(如`createTimeStr`);
+- 金额字段:以分为单位返回整数(避免浮点精度问题),字段名加`Cent`后缀(如`amountCent`)。
+
+## 四、安全规范(必遵循)
+
+### 1. 密码/敏感信息处理
+
+- 敏感信息返回:手机号、身份证号等脱敏展示(如`138****8000`);
+- Token处理:JWT Token不存储敏感信息(如密码),Redis存储的Token设置合理过期时间。
+
+### 2. 接口频率限制
+
+- 验证码接口:同一手机号1分钟内最多1次,1小时内最多5次;
+- 登录接口:同一账号5分钟内连续失败5次,临时锁定15分钟;
+- 通用接口:单IP/单用户接口调用频率不超过QPS 10。
+
+### 3. 数据校验
+
+- 所有入参必须做合法性校验(格式、长度、范围);
+
+## 五、异常响应示例
+
+### 1. 参数错误(400)
+
+```json
+{
+ "code": 400,
+ "message": "手机号格式错误",
+ "timestamp": 1744238900000,
+ "data": null
+}
+```
+
+### 2. 未授权(401)
+
+```json
+{
+ "code": 401,
+ "message": "Token已过期,请重新登录",
+ "timestamp": 1744238900000,
+ "data": null
+}
+```
+
+### 3. 服务器错误(500)
+
+```json
+{
+ "code": 500,
+ "message": "服务器内部错误,请稍后重试",
+ "timestamp": 1744238900000,
+ "data": null
+}
+```
+
+## 总结
+
+1. 所有接口必须遵循**统一响应格式**(包含code/message/timestamp),列表接口强制分页并使用指定分页结构;
+2. 接口命名、参数/字段命名需符合RESTful规范和小驼峰/小写连字符约定,保证可读性;
+3. 安全规范是核心底线,密码、Token、频率限制等规则必须严格执行,避免安全漏洞;
+4. 本规范为基础准则,各业务模块可在本规范基础上补充模块专属规则,但不得与本规范冲突。
diff --git a/src/main/java/icu/sunway/ai_spring_example/Docs/api-dev-standard.md b/src/main/java/icu/sunway/ai_spring_example/Docs/api-dev-standard.md
new file mode 100644
index 0000000..3549bd3
--- /dev/null
+++ b/src/main/java/icu/sunway/ai_spring_example/Docs/api-dev-standard.md
@@ -0,0 +1,256 @@
+# 接口开发规范
+
+## 0. 与API文档规范对照说明
+
+本开发规范与`Controller/api-doc-standard.md`互为补充:
+
+- **api-dev-standard.md**:指导**代码实现**(如何编写符合规范的代码)
+- **api-doc-standard.md**:定义**接口契约**(请求/响应格式标准)
+
+### 关键一致性说明
+
+| 规范维度 | 代码实现规范 (本文件) | 接口文档规范 (api-doc-standard) | 对齐状态 |
+| ------------ | -------------------------------- | ----------------------------------- | -------------------------------------- |
+| **响应格式** | 必须使用ResponseUtils生成响应 | 强制要求code/message/timestamp/data | ✅ 对齐 |
+| **分页参数** | 代码中参数名: `page`/`limit` | 文档中参数名: `page`/`limit` | ✅ 语义对齐(page=current, limit=size) |
+| **状态码** | ResponseUtils需支持400/401等状态 | 明确200/400/401等状态码语义 | ⚠️ 需增强 |
+| **时间字段** | Entity用LocalDateTime | 响应用时间戳(Integer) | ⚠️ 需转换 |
+
+> **特别说明**:当前代码中`ResponseUtils`实现需扩展以完全符合api-doc-standard,但开发规范以**实际代码结构**为准。
+
+---
+
+## 1. 整体架构规范
+
+### 1.1 分层结构
+
+遵循CLAUDE.md定义的分层架构,特别注意:
+
+- **Controller层**:业务逻辑的主要编写位置
+- **Service层**:仅包含接口定义和MyBatis Plus继承实现
+ - 接口:`I{Name}Service` 继承 `IService`
+ - 实现:`{Name}ServiceImpl` 继承 `ServiceImpl`
+- **业务逻辑不应下沉到Service层**,Controller直接调用Service提供的CRUD方法
+
+### 1.2 目录规范
+
+- Controller按实体划分目录:`Controller/{EntityName}Controller/`
+- **Entity目录**:`Entity/` 下直接存放实体类(**无需子目录**)
+- **Mapper目录**:`Mapper/` 下直接存放Mapper接口(**无需子目录**)
+- **Service目录**:
+ - 接口:`Service/`
+ - 实现:`Service/Implements/`
+- 示例:
+ - `User.java` → `Entity/User.java`
+ - `UserMapper.java` → `Mapper/UserMapper.java`
+
+## 2. Controller编写规范
+
+### 2.1 服务注入
+
+```java
+@Resource
+private IUserService userService;
+```
+
+- **必须**使用`@Resource`而非`@Autowired`
+- **不得**在Service层编写业务逻辑
+
+### 2.2 响应处理(必须遵守)
+
+**所有接口必须使用ResponseUtils统一响应格式**:
+
+对于 Controller 中的函数返回类型,统一使用 Object 类型,而不是具体的实体类。
+
+如果需要编写具体 VO 实体类,在对应的 Controller 目录下创建 vo 文件夹并在其中定义。
+
+```java
+// 成功响应
+return ResponseUtils.success(data);
+
+// 失败响应(需指定状态码)
+return ResponseUtils.fail(400, "用户名格式错误");
+```
+
+- **必须包含**:
+ - `code`:按[api-doc-standard#状态码规范](Controller/api-doc-standard.md#三、通用状态码规范)设置
+ - `timestamp`:当前时间戳(`System.currentTimeMillis()`)
+ - `data`:业务数据(列表接口需返回标准分页结构)
+- **禁止**直接返回原始对象
+
+### 2.3 分页处理
+
+**必须使用MyBatis Plus原生Page对象**:
+
+```java
+@GetMapping
+public Object getAllUsers(
+ @RequestParam(defaultValue = "1") Integer page,
+ @RequestParam(defaultValue = "10") Integer limit) {
+
+ Page pageObj = new Page<>(page, limit);
+ return ResponseUtils.success(userService.page(pageObj));
+}
+```
+
+- **关键点**:
+ - Page对象字段与API响应结构完全匹配(records/total/size/current/pages)
+ - **禁止**手动构建分页响应
+ - 分页参数**代码中命名为`page`/`limit`**
+
+### 2.4 查询操作
+
+**简单查询**直接使用Service方法:
+
+```java
+@GetMapping("/{id}")
+public Object getUserById(@PathVariable Long id) {
+ return ResponseUtils.success(userService.getById(id));
+}
+```
+
+**复杂查询**使用QueryWrapper:
+
+```java
+@GetMapping("/username/{username}")
+public Object getUserByUsername(@PathVariable String username) {
+ QueryWrapper wrapper = new QueryWrapper<>();
+ wrapper.eq("username", username);
+ return ResponseUtils.success(userService.getOne(wrapper));
+}
+```
+
+- **注意**:查询条件构建应在Controller层完成
+
+## 3. Entity层规范
+
+### 3.1 基础结构
+
+```java
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@TableName("user")
+public class User {
+ @TableId(type = IdType.AUTO)
+ private Long id;
+ private String username;
+ private String password;
+ // ...其他字段
+}
+```
+
+- **必须使用**:
+ - Lombok注解:`@Data` + `@NoArgsConstructor` + `@AllArgsConstructor`
+ - MyBatis Plus注解:`@TableName` + `@TableId`
+- **字段命名**:小驼峰命名(`createTime`而非`create_time`)
+
+### 3.2 时间字段处理
+
+- **Entity层**:使用`LocalDateTime`类型(如`createTime`)
+
+## 4. Mapper层规范
+
+### 4.1 基础结构
+
+```java
+@Mapper
+public interface UserMapper extends BaseMapper {
+ // 仅允许MyBatis Plus内置方法,自定义SQL需走Service层
+}
+```
+
+- **必须**继承`BaseMapper`
+- **禁止**在Mapper接口中添加方法(自定义SQL需通过Service层)
+
+## 5. Service层规范
+
+### 5.1 接口定义
+
+```java
+public interface IUserService extends IService {
+ // 仅允许扩展MyBatis Plus未提供的方法
+}
+```
+
+- **必须**继承`IService`
+- **仅当需要**扩展MyBatis Plus未提供的方法时才添加方法
+
+### 5.2 实现类
+
+```java
+@Service
+public class UserServiceImpl extends ServiceImpl implements IUserService {
+ @Resource
+ private UserMapper userMapper;
+}
+```
+
+- **必须**继承`ServiceImpl`
+- **禁止**在实现类中编写业务逻辑(仅用于注入Mapper)
+
+## 6. 禁止行为清单
+
+| 类型 | 错误示例 | 正确做法 |
+| ------------ | ----------------------------------- | ------------------------------------ |
+| 业务逻辑位置 | 在ServiceImpl中编写业务 | 所有业务逻辑放在Controller |
+| 响应格式 | 直接返回`new ResponseEntity<>(...)` | 用ResponseUtils生成带timestamp的响应 |
+| 分页参数 | 使用`offset`/`pageSize` | 统一用`page`/`limit`参数 |
+| 状态码 | 所有错误返回500 | 按[api-doc-standard]返回400/401等 |
+| 时间字段 | 直接返回LocalDateTime | 转换为时间戳或格式化字符串 |
+
+## 7. 必须使用的工具类
+
+| 工具类 | 用途 | 示例 |
+| --------------- | -------------- | ------------------------------------- |
+| `ResponseUtils` | 生成标准化响应 | `ResponseUtils.fail(400, "参数错误")` |
+
+## 8. 接口设计原则
+
+1. **RESTful规范**:
+ - 路径使用**复数名词**:`/users`而非`/user`
+ - **参数命名**:代码用`page`/`limit`,文档用`current`/`size`
+
+2. **字段转换**:
+ - Entity的`LocalDateTime` → 接口响应需转为时间戳
+ - 敏感字段(如密码)需在Controller层过滤:`user.setPassword(null)`
+
+3. **错误处理**:
+ - 按[api-doc-standard#通用状态码规范](Controller/api-doc-standard.md#三、通用状态码规范)返回精确错误
+ - 示例:`return ResponseUtils.fail(409, "用户名已存在");`
+
+## 9. 完整示例
+
+```java
+@RestController
+@RequestMapping("/users")
+public class UserController {
+
+ @Resource
+ private IUserService userService;
+
+ @GetMapping("/{id}")
+ public Object getUser(@PathVariable Long id) {
+ User user = userService.getById(id);
+ // 过滤敏感字段
+ user.setPassword(null);
+ // 转换时间格式
+ return ResponseUtils.success(user);
+ }
+
+ @GetMapping
+ public Object listUsers(
+ @RequestParam(defaultValue = "1") Integer page,
+ @RequestParam(defaultValue = "10") Integer limit) {
+
+ // 参数校验
+ if (limit > 100) {
+ return ResponseUtils.fail(400, "每页数量不能超过100");
+ }
+
+ Page pageObj = new Page<>(page, limit);
+ Page resultPage = userService.page(pageObj);
+ return ResponseUtils.success(resultPage);
+ }
+}
+```
diff --git a/src/main/java/icu/sunway/ai_spring_example/Utils/JsonUtils.java b/src/main/java/icu/sunway/ai_spring_example/Utils/JsonUtils.java
index 578843b..75201ee 100644
--- a/src/main/java/icu/sunway/ai_spring_example/Utils/JsonUtils.java
+++ b/src/main/java/icu/sunway/ai_spring_example/Utils/JsonUtils.java
@@ -145,19 +145,6 @@ public class JsonUtils {
return toObject(json, Map.class, keyClazz, valueClazz);
}
- /**
- * 将对象转换为Map
- *
- * @param obj 对象
- * @return Map
- */
- public static Map toMap(Object obj) {
- if (obj == null) {
- return null;
- }
- return objectMapper.convertValue(obj, Map.class);
- }
-
/**
* 验证JSON字符串是否有效
*
diff --git a/src/main/java/icu/sunway/ai_spring_example/Utils/PageUtils.java b/src/main/java/icu/sunway/ai_spring_example/Utils/PageUtils.java
deleted file mode 100644
index b2acda4..0000000
--- a/src/main/java/icu/sunway/ai_spring_example/Utils/PageUtils.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package icu.sunway.ai_spring_example.Utils;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.List;
-
-/**
- * 分页工具类
- */
-public class PageUtils {
-
- /**
- * 默认页码
- */
- public static final Integer DEFAULT_PAGE = 1;
-
- /**
- * 默认每页数量
- */
- public static final Integer DEFAULT_LIMIT = 10;
-
- /**
- * 最大每页数量
- */
- public static final Integer MAX_LIMIT = 100;
-
- /**
- * 分页结果类
- *
- * @param 数据类型
- */
- @Data
- @AllArgsConstructor
- @NoArgsConstructor
- public static class PaginationResult {
- private Integer currentPage;
- private Integer pageSize;
- private Long totalItems;
- private Integer totalPages;
- private List list;
- }
-
- /**
- * 验证和调整分页参数
- *
- * @param page 页码
- * @param limit 每页数量
- * @return 调整后的分页参数数组 [page, limit]
- */
- public static Integer[] validatePageParams(Integer page, Integer limit) {
- // 验证页码
- if (page == null || page < 1) {
- page = DEFAULT_PAGE;
- }
-
- // 验证每页数量
- if (limit == null || limit < 1 || limit > MAX_LIMIT) {
- limit = DEFAULT_LIMIT;
- }
-
- return new Integer[] { page, limit };
- }
-
- /**
- * 创建Page对象
- *
- * @param page 页码
- * @param limit 每页数量
- * @return Page对象
- */
- public static Page createPage(Integer page, Integer limit) {
- Integer[] params = validatePageParams(page, limit);
- return new Page<>(params[0], params[1]);
- }
-
- /**
- * 将MyBatis Plus的Page结果转换为分页结果
- *
- * @param pageResult MyBatis Plus的Page结果
- * @return 分页结果
- */
- public static PaginationResult createPaginationResult(IPage pageResult) {
- return new PaginationResult<>(
- (int) pageResult.getCurrent(),
- (int) pageResult.getSize(),
- pageResult.getTotal(),
- (int) pageResult.getPages(),
- pageResult.getRecords());
- }
-
- /**
- * 创建空的分页结果
- *
- * @param page 页码
- * @param limit 每页数量
- * @return 空的分页结果
- */
- public static PaginationResult createEmptyPaginationResult(Integer page, Integer limit) {
- Integer[] params = validatePageParams(page, limit);
- return new PaginationResult<>(
- params[0],
- params[1],
- 0L,
- 0,
- List.of());
- }
-}