diff --git a/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/h5/config/H5SmsProperties.java b/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/h5/config/H5SmsProperties.java
index 5212a0e..46018c1 100644
--- a/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/h5/config/H5SmsProperties.java
+++ b/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/h5/config/H5SmsProperties.java
@@ -7,7 +7,7 @@ import org.springframework.stereotype.Component;
/**
* H5短信配置属性
*
- * @author 湖北新华业务中台研发团队
+ * @author pangu
*/
@Data
@Component
diff --git a/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/h5/controller/H5AuthController.java b/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/h5/controller/H5AuthController.java
index 9879a8e..d94acb8 100644
--- a/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/h5/controller/H5AuthController.java
+++ b/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/h5/controller/H5AuthController.java
@@ -1,6 +1,15 @@
package org.dromara.pangu.h5.controller;
import cn.dev33.satoken.annotation.SaIgnore;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
@@ -16,9 +25,14 @@ import org.springframework.web.bind.annotation.*;
/**
* H5认证接口
+ *
+ * 提供H5端用户认证相关功能,包括登录、注册、验证码等。
+ * 所有接口均无需Token认证。
+ *
*
- * @author 湖北新华业务中台研发团队
+ * @author pangu
*/
+@Tag(name = "H5认证接口", description = "提供H5端登录、注册、验证码等认证功能,无需Token")
@SaIgnore
@Validated
@RestController
@@ -31,6 +45,15 @@ public class H5AuthController {
/**
* 获取图形验证码
*/
+ @Operation(
+ summary = "获取图形验证码",
+ description = "生成数学运算验证码图片,返回Base64编码的图片和uuid。uuid用于后续接口校验验证码。验证码5分钟内有效。"
+ )
+ @ApiResponses({
+ @ApiResponse(responseCode = "200", description = "获取成功",
+ content = @Content(schema = @Schema(implementation = H5CaptchaVo.class))),
+ @ApiResponse(responseCode = "500", description = "服务器错误")
+ })
@GetMapping("/captcha")
public R getCaptcha() {
return R.ok(authService.getCaptcha());
@@ -39,6 +62,32 @@ public class H5AuthController {
/**
* 发送短信验证码
*/
+ @Operation(
+ summary = "发送短信验证码",
+ description = """
+ 向指定手机号发送短信验证码。
+
+ **使用流程:**
+ 1. 先调用 /captcha 获取图形验证码
+ 2. 用户输入图形验证码后调用本接口
+ 3. 验证码6位数字,5分钟内有效
+
+ **限制规则:**
+ - 同一手机号60秒内只能发送1次
+ - 同一手机号每日最多发送10次
+ - 同一IP每分钟最多发送5次
+ - 同一IP每日最多发送50次
+ - 连续验证失败5次将被封禁30分钟
+
+ **type参数说明:**
+ - login: 登录验证码(手机号必须已注册)
+ - register: 注册验证码(手机号必须未注册)
+ """
+ )
+ @ApiResponses({
+ @ApiResponse(responseCode = "200", description = "发送成功"),
+ @ApiResponse(responseCode = "500", description = "发送失败,可能原因:验证码错误、手机号已注册/未注册、发送频率限制等")
+ })
@PostMapping("/sms/send")
public R sendSmsCode(@Valid @RequestBody H5SmsSendDto dto) {
authService.sendSmsCode(dto);
@@ -48,6 +97,30 @@ public class H5AuthController {
/**
* 密码登录
*/
+ @Operation(
+ summary = "密码登录",
+ description = """
+ 使用手机号和密码登录。
+
+ **使用流程:**
+ 1. 先调用 /captcha 获取图形验证码
+ 2. 用户输入手机号、密码、图形验证码
+ 3. 调用本接口进行登录
+
+ **返回说明:**
+ - accessToken: 访问令牌,2小时有效,用于请求需要认证的接口
+ - refreshToken: 刷新令牌,7天有效(记住我时30天),用于刷新accessToken
+ - expiresIn: accessToken过期时间(秒)
+
+ **认证方式:**
+ 请求头添加:Authorization: Bearer {accessToken}
+ """
+ )
+ @ApiResponses({
+ @ApiResponse(responseCode = "200", description = "登录成功",
+ content = @Content(schema = @Schema(implementation = H5LoginVo.class))),
+ @ApiResponse(responseCode = "500", description = "登录失败,可能原因:验证码错误、手机号或密码错误、账号被禁用")
+ })
@PostMapping("/login/password")
public R loginByPassword(@Valid @RequestBody H5PasswordLoginDto dto) {
return R.ok(authService.loginByPassword(dto));
@@ -56,6 +129,25 @@ public class H5AuthController {
/**
* 短信验证码登录
*/
+ @Operation(
+ summary = "短信验证码登录",
+ description = """
+ 使用手机号和短信验证码登录。
+
+ **使用流程:**
+ 1. 先调用 /captcha 获取图形验证码
+ 2. 调用 /sms/send 发送短信验证码(type=login)
+ 3. 用户输入短信验证码和图形验证码
+ 4. 调用本接口进行登录
+
+ **注意:** 手机号必须已注册才能使用短信登录
+ """
+ )
+ @ApiResponses({
+ @ApiResponse(responseCode = "200", description = "登录成功",
+ content = @Content(schema = @Schema(implementation = H5LoginVo.class))),
+ @ApiResponse(responseCode = "500", description = "登录失败,可能原因:验证码错误、手机号未注册、账号被禁用")
+ })
@PostMapping("/login/sms")
public R loginBySms(@Valid @RequestBody H5SmsLoginDto dto) {
return R.ok(authService.loginBySms(dto));
@@ -64,6 +156,30 @@ public class H5AuthController {
/**
* 注册
*/
+ @Operation(
+ summary = "会员注册",
+ description = """
+ 新用户注册账号。
+
+ **使用流程:**
+ 1. 先调用 /captcha 获取图形验证码
+ 2. 调用 /sms/send 发送短信验证码(type=register)
+ 3. 用户填写手机号、短信验证码、图形验证码、密码
+ 4. 调用本接口进行注册
+
+ **注册成功后:**
+ - 自动登录,返回Token
+ - 默认昵称为 user_手机号后4位
+ - 默认无身份类型,需后续设置
+
+ **密码要求:** 至少6位
+ """
+ )
+ @ApiResponses({
+ @ApiResponse(responseCode = "200", description = "注册成功并自动登录",
+ content = @Content(schema = @Schema(implementation = H5LoginVo.class))),
+ @ApiResponse(responseCode = "500", description = "注册失败,可能原因:验证码错误、手机号已注册")
+ })
@PostMapping("/register")
public R register(@Valid @RequestBody H5RegisterDto dto) {
return R.ok(authService.register(dto));
@@ -72,6 +188,28 @@ public class H5AuthController {
/**
* 刷新Token
*/
+ @Operation(
+ summary = "刷新Token",
+ description = """
+ 使用refreshToken获取新的accessToken。
+
+ **使用场景:**
+ 当accessToken过期时(2小时),使用refreshToken换取新Token,无需重新登录。
+
+ **注意事项:**
+ - refreshToken使用后会失效,返回新的refreshToken
+ - refreshToken过期后需重新登录
+ - refreshToken有效期:普通登录7天,记住我30天
+ """
+ )
+ @ApiResponses({
+ @ApiResponse(responseCode = "200", description = "刷新成功",
+ content = @Content(schema = @Schema(implementation = H5LoginVo.class))),
+ @ApiResponse(responseCode = "500", description = "刷新失败,refreshToken已过期,请重新登录")
+ })
+ @Parameters({
+ @Parameter(name = "refreshToken", description = "刷新令牌", required = true, in = ParameterIn.QUERY)
+ })
@PostMapping("/refresh")
public R refreshToken(@RequestParam String refreshToken) {
return R.ok(authService.refreshToken(refreshToken));
@@ -80,6 +218,13 @@ public class H5AuthController {
/**
* 退出登录
*/
+ @Operation(
+ summary = "退出登录",
+ description = "退出当前登录状态,清除服务端Token。客户端需同时清除本地存储的Token。"
+ )
+ @ApiResponses({
+ @ApiResponse(responseCode = "200", description = "退出成功")
+ })
@PostMapping("/logout")
public R logout() {
authService.logout();
diff --git a/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/h5/controller/H5BaseDataController.java b/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/h5/controller/H5BaseDataController.java
index 81530e4..b47e33f 100644
--- a/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/h5/controller/H5BaseDataController.java
+++ b/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/h5/controller/H5BaseDataController.java
@@ -2,16 +2,25 @@ package org.dromara.pangu.h5.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
-import org.dromara.pangu.base.domain.PgRegion;
-import org.dromara.pangu.base.domain.PgSubject;
-import org.dromara.pangu.base.mapper.PgRegionMapper;
-import org.dromara.pangu.base.mapper.PgSubjectMapper;
import org.dromara.pangu.base.domain.PgClass;
import org.dromara.pangu.base.domain.PgGrade;
+import org.dromara.pangu.base.domain.PgRegion;
+import org.dromara.pangu.base.domain.PgSubject;
import org.dromara.pangu.base.mapper.PgClassMapper;
import org.dromara.pangu.base.mapper.PgGradeMapper;
+import org.dromara.pangu.base.mapper.PgRegionMapper;
+import org.dromara.pangu.base.mapper.PgSubjectMapper;
import org.dromara.pangu.school.domain.PgSchool;
import org.dromara.pangu.school.domain.PgSchoolClass;
import org.dromara.pangu.school.domain.PgSchoolGrade;
@@ -28,9 +37,14 @@ import java.util.stream.Collectors;
/**
* H5基础数据接口
+ *
+ * 提供H5端基础数据查询功能,包括区域、学校、年级、班级、学科等。
+ * 所有接口均无需Token认证。
+ *
*
- * @author 湖北新华业务中台研发团队
+ * @author pangu
*/
+@Tag(name = "H5基础数据接口", description = "提供区域、学校、年级、班级、学科等基础数据查询,无需Token")
@SaIgnore
@RestController
@RequestMapping("/h5/base")
@@ -48,6 +62,25 @@ public class H5BaseDataController {
/**
* 获取区域树
*/
+ @Operation(
+ summary = "获取区域树",
+ description = """
+ 获取省市区三级区域树形结构数据。
+
+ **返回字段:**
+ - regionId: 区域ID
+ - regionName: 区域名称
+ - regionCode: 区域编码
+ - level: 层级(1省、2市、3区)
+ - children: 子区域列表
+
+ **使用场景:** 用于地区选择器,如绑定学生时选择所在地区
+ """
+ )
+ @ApiResponses({
+ @ApiResponse(responseCode = "200", description = "获取成功",
+ content = @Content(schema = @Schema(implementation = List.class)))
+ })
@GetMapping("/regions")
public R>> getRegions() {
List regions = regionMapper.selectList(
@@ -56,7 +89,6 @@ public class H5BaseDataController {
.orderByAsc(PgRegion::getOrderNum)
);
- // 构建树形结构
List