docs: 添加H5接口Swagger文档注解

Controller层:
- H5AuthController: 添加详细的接口说明、参数说明、返回值说明
- H5MemberController: 添加认证要求、操作说明
- H5BaseDataController: 添加数据获取流程说明

DTO/VO层:
- 所有字段添加@Schema注解,包含描述、示例值、枚举值等
- 标注必填/选填、数据格式要求

其他:
- 统一作者为pangu
This commit is contained in:
神码-方晓辉 2026-02-02 21:48:36 +08:00
parent a47536315b
commit 0b35da7f85
21 changed files with 555 additions and 263 deletions

View File

@ -7,7 +7,7 @@ import org.springframework.stereotype.Component;
/**
* H5短信配置属性
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
@Data
@Component

View File

@ -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认证接口
* <p>
* 提供H5端用户认证相关功能包括登录注册验证码等
* 所有接口均无需Token认证
* </p>
*
* @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<H5CaptchaVo> 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<Void> 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<H5LoginVo> 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<H5LoginVo> 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<H5LoginVo> 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<H5LoginVo> 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<Void> logout() {
authService.logout();

View File

@ -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基础数据接口
* <p>
* 提供H5端基础数据查询功能包括区域学校年级班级学科等
* 所有接口均无需Token认证
* </p>
*
* @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<List<Map<String, Object>>> getRegions() {
List<PgRegion> regions = regionMapper.selectList(
@ -56,7 +89,6 @@ public class H5BaseDataController {
.orderByAsc(PgRegion::getOrderNum)
);
// 构建树形结构
List<Map<String, Object>> tree = buildRegionTree(regions, 0L);
return R.ok(tree);
}
@ -64,6 +96,27 @@ public class H5BaseDataController {
/**
* 根据区域获取学校列表
*/
@Operation(
summary = "根据区域获取学校列表",
description = """
根据区域ID获取该区域下的学校列表
**返回字段**
- schoolId: 学校ID
- schoolName: 学校名称
- schoolCode: 学校编码
**调用顺序** 先调用 /regions 获取区域ID再调用本接口
"""
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "获取成功",
content = @Content(schema = @Schema(implementation = List.class)))
})
@Parameters({
@Parameter(name = "regionId", description = "区域ID", required = true, in = ParameterIn.QUERY,
schema = @Schema(type = "integer", format = "int64"), example = "420100")
})
@GetMapping("/schools")
public R<List<Map<String, Object>>> getSchools(@RequestParam Long regionId) {
List<PgSchool> schools = schoolMapper.selectList(
@ -87,6 +140,27 @@ public class H5BaseDataController {
/**
* 根据学校获取年级列表
*/
@Operation(
summary = "根据学校获取年级列表",
description = """
根据学校ID获取该学校下的年级列表
**返回字段**
- schoolGradeId: 学校年级关联ID用于后续接口
- gradeId: 基础年级ID
- gradeName: 年级名称高一高二高三
**调用顺序** 先调用 /schools 获取学校ID再调用本接口
"""
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "获取成功",
content = @Content(schema = @Schema(implementation = List.class)))
})
@Parameters({
@Parameter(name = "schoolId", description = "学校ID", required = true, in = ParameterIn.QUERY,
schema = @Schema(type = "integer", format = "int64"), example = "1")
})
@GetMapping("/grades")
public R<List<Map<String, Object>>> getGrades(@RequestParam Long schoolId) {
List<PgSchoolGrade> schoolGrades = schoolGradeMapper.selectList(
@ -94,7 +168,6 @@ public class H5BaseDataController {
.eq(PgSchoolGrade::getSchoolId, schoolId)
);
// 获取基础年级信息
Set<Long> gradeIds = schoolGrades.stream()
.map(PgSchoolGrade::getGradeId)
.filter(Objects::nonNull)
@ -122,6 +195,30 @@ public class H5BaseDataController {
/**
* 根据年级获取班级列表
*/
@Operation(
summary = "根据年级获取班级列表",
description = """
根据学校年级关联ID获取该年级下的班级列表
**返回字段**
- schoolClassId: 学校班级关联ID用于绑定学生等接口
- classId: 基础班级ID
- className: 班级名称1班2班3班
**调用顺序** 先调用 /grades 获取 schoolGradeId再调用本接口
**注意** 参数是 schoolGradeId学校年级关联ID不是 gradeId
"""
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "获取成功",
content = @Content(schema = @Schema(implementation = List.class)))
})
@Parameters({
@Parameter(name = "schoolGradeId", description = "学校年级关联ID从/grades接口返回的schoolGradeId",
required = true, in = ParameterIn.QUERY,
schema = @Schema(type = "integer", format = "int64"), example = "1")
})
@GetMapping("/classes")
public R<List<Map<String, Object>>> getClasses(@RequestParam Long schoolGradeId) {
List<PgSchoolClass> schoolClasses = schoolClassMapper.selectList(
@ -129,7 +226,6 @@ public class H5BaseDataController {
.eq(PgSchoolClass::getSchoolGradeId, schoolGradeId)
);
// 获取基础班级信息
Set<Long> classIds = schoolClasses.stream()
.map(PgSchoolClass::getClassId)
.filter(Objects::nonNull)
@ -157,6 +253,23 @@ public class H5BaseDataController {
/**
* 获取学科列表
*/
@Operation(
summary = "获取学科列表",
description = """
获取所有可用的学科列表
**返回字段**
- subjectId: 学科ID
- subjectName: 学科名称语文数学英语
- subjectCode: 学科编码
**使用场景** 教师设置教育身份时选择任教学科
"""
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "获取成功",
content = @Content(schema = @Schema(implementation = List.class)))
})
@GetMapping("/subjects")
public R<List<Map<String, Object>>> getSubjects() {
List<PgSubject> subjects = subjectMapper.selectList(

View File

@ -1,5 +1,15 @@
package org.dromara.pangu.h5.controller;
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.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
@ -18,9 +28,15 @@ import java.util.List;
/**
* H5会员接口
* <p>
* 提供H5端会员信息管理功能包括个人信息密码教育身份学生绑定等
* 所有接口均需要Token认证
* </p>
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
@Tag(name = "H5会员接口", description = "会员信息管理包括个人信息、密码、教育身份、学生绑定等需要Token认证")
@SecurityRequirement(name = "Authorization")
@Validated
@RestController
@RequestMapping("/h5/member")
@ -32,14 +48,48 @@ public class H5MemberController {
/**
* 获取当前会员信息
*/
@Operation(
summary = "获取当前会员信息",
description = """
获取当前登录会员的详细信息
**返回内容包括**
- 基本信息会员ID编号手机号脱敏昵称头像性别生日注册时间
- 身份类型parent家长teacher教师
- 教育信息如果是教师身份包含学校年级班级学科信息
- 绑定学生当前会员绑定的所有学生列表
"""
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "获取成功",
content = @Content(schema = @Schema(implementation = H5MemberInfoVo.class))),
@ApiResponse(responseCode = "401", description = "未登录或Token已过期")
})
@GetMapping("/info")
public R<H5MemberInfoVo> getInfo() {
return R.ok(memberService.getMemberInfo());
}
/**
* 修改会员信息昵称/性别/生日
* 修改会员信息
*/
@Operation(
summary = "修改会员基本信息",
description = """
修改当前会员的基本信息
**可修改字段**
- nickname: 昵称
- gender: 性别0未知1男2女
- birthday: 生日
**注意** 手机号不可修改
"""
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "修改成功"),
@ApiResponse(responseCode = "401", description = "未登录或Token已过期")
})
@PutMapping("/info")
public R<Void> updateInfo(@RequestBody H5MemberUpdateDto dto) {
memberService.updateMemberInfo(dto);
@ -49,6 +99,22 @@ public class H5MemberController {
/**
* 修改密码
*/
@Operation(
summary = "修改登录密码",
description = """
修改当前会员的登录密码
**要求**
- 需要验证当前密码
- 新密码至少6位
- 新密码和确认密码必须一致
"""
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "修改成功"),
@ApiResponse(responseCode = "401", description = "未登录或Token已过期"),
@ApiResponse(responseCode = "500", description = "修改失败,可能原因:当前密码错误、两次密码不一致")
})
@PutMapping("/password")
public R<Void> updatePassword(@Valid @RequestBody H5PasswordUpdateDto dto) {
memberService.updatePassword(dto);
@ -58,6 +124,29 @@ public class H5MemberController {
/**
* 添加/修改教育身份
*/
@Operation(
summary = "设置教育身份(教师)",
description = """
设置或修改会员的教育身份信息设置后身份类型变为"教师"
**必填信息**
- 学校
- 年级
- 班级
- 学科
**数据获取**
- 学校列表GET /h5/base/schools?regionId=xxx
- 年级列表GET /h5/base/grades?schoolId=xxx
- 班级列表GET /h5/base/classes?schoolGradeId=xxx
- 学科列表GET /h5/base/subjects
"""
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "设置成功"),
@ApiResponse(responseCode = "401", description = "未登录或Token已过期"),
@ApiResponse(responseCode = "500", description = "设置失败,可能原因:学校/年级/班级/学科不存在")
})
@PostMapping("/education")
public R<Void> saveEducation(@Valid @RequestBody H5EducationDto dto) {
memberService.saveEducation(dto);
@ -67,6 +156,15 @@ public class H5MemberController {
/**
* 获取教育身份
*/
@Operation(
summary = "获取教育身份信息",
description = "获取当前会员的教育身份信息学校、年级、班级、学科。如果未设置教育身份返回null。"
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "获取成功",
content = @Content(schema = @Schema(implementation = H5EducationVo.class))),
@ApiResponse(responseCode = "401", description = "未登录或Token已过期")
})
@GetMapping("/education")
public R<H5EducationVo> getEducation() {
return R.ok(memberService.getEducation());
@ -75,6 +173,14 @@ public class H5MemberController {
/**
* 删除教育身份
*/
@Operation(
summary = "删除教育身份",
description = "清除当前会员的教育身份信息,身份类型将变为空。"
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "删除成功"),
@ApiResponse(responseCode = "401", description = "未登录或Token已过期")
})
@DeleteMapping("/education")
public R<Void> deleteEducation() {
memberService.deleteEducation();
@ -84,6 +190,31 @@ public class H5MemberController {
/**
* 绑定学生
*/
@Operation(
summary = "绑定学生",
description = """
绑定一个学生到当前会员家长和教师身份均可绑定学生
**必填信息**
- 学生姓名
- 学号
- 出生日期
- 性别0未知1男2女
- 所在地区
- 学校
- 年级
- 班级
**注意**
- 一个会员可以绑定多个学生
- 首次绑定学生后如果会员无身份类型默认设为"家长"
"""
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "绑定成功"),
@ApiResponse(responseCode = "401", description = "未登录或Token已过期"),
@ApiResponse(responseCode = "500", description = "绑定失败,可能原因:学校/年级/班级不存在")
})
@PostMapping("/student")
public R<Void> bindStudent(@Valid @RequestBody H5StudentBindDto dto) {
memberService.bindStudent(dto);
@ -93,6 +224,15 @@ public class H5MemberController {
/**
* 获取绑定的学生列表
*/
@Operation(
summary = "获取绑定的学生列表",
description = "获取当前会员绑定的所有学生信息,包含学校、年级、班级名称。"
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "获取成功",
content = @Content(schema = @Schema(implementation = H5StudentVo.class))),
@ApiResponse(responseCode = "401", description = "未登录或Token已过期")
})
@GetMapping("/students")
public R<List<H5StudentVo>> getStudents() {
return R.ok(memberService.getStudents());
@ -101,6 +241,18 @@ public class H5MemberController {
/**
* 修改学生信息
*/
@Operation(
summary = "修改学生信息",
description = "修改指定学生的信息。只能修改当前会员绑定的学生。"
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "修改成功"),
@ApiResponse(responseCode = "401", description = "未登录或Token已过期"),
@ApiResponse(responseCode = "500", description = "修改失败,可能原因:学生不存在或无权限修改")
})
@Parameters({
@Parameter(name = "studentId", description = "学生ID", required = true, in = ParameterIn.PATH)
})
@PutMapping("/student/{studentId}")
public R<Void> updateStudent(@PathVariable Long studentId, @Valid @RequestBody H5StudentBindDto dto) {
memberService.updateStudent(studentId, dto);
@ -110,6 +262,18 @@ public class H5MemberController {
/**
* 解绑学生
*/
@Operation(
summary = "解绑学生",
description = "解除当前会员与指定学生的绑定关系。解绑后学生记录仍然保留,但不再关联到当前会员。"
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "解绑成功"),
@ApiResponse(responseCode = "401", description = "未登录或Token已过期"),
@ApiResponse(responseCode = "500", description = "解绑失败,可能原因:学生不存在或无权限操作")
})
@Parameters({
@Parameter(name = "studentId", description = "学生ID", required = true, in = ParameterIn.PATH)
})
@DeleteMapping("/student/{studentId}")
public R<Void> unbindStudent(@PathVariable Long studentId) {
memberService.unbindStudent(studentId);

View File

@ -1,37 +1,31 @@
package org.dromara.pangu.h5.domain.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* H5教育身份请求DTO
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
@Data
@Schema(description = "教育身份设置请求参数(教师身份)")
public class H5EducationDto {
/**
* 学校ID
*/
@Schema(description = "学校ID从/h5/base/schools获取", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "请选择学校")
private Long schoolId;
/**
* 年级ID
*/
@Schema(description = "学校年级关联ID从/h5/base/grades获取的schoolGradeId", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "请选择年级")
private Long schoolGradeId;
/**
* 班级ID
*/
@Schema(description = "学校班级关联ID从/h5/base/classes获取的schoolClassId", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "请选择班级")
private Long schoolClassId;
/**
* 学科ID
*/
@Schema(description = "学科ID从/h5/base/subjects获取", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "请选择学科")
private Long subjectId;
}

View File

@ -1,5 +1,6 @@
package org.dromara.pangu.h5.domain.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Date;
@ -7,23 +8,18 @@ import java.util.Date;
/**
* H5会员信息修改请求DTO
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
@Data
@Schema(description = "会员信息修改请求参数")
public class H5MemberUpdateDto {
/**
* 昵称
*/
@Schema(description = "昵称", example = "张三")
private String nickname;
/**
* 性别0未知 1男 2女
*/
@Schema(description = "性别0-未知1-男2-女", example = "1", allowableValues = {"0", "1", "2"})
private String gender;
/**
* 生日
*/
@Schema(description = "生日", example = "1990-01-15")
private Date birthday;
}

View File

@ -1,5 +1,6 @@
package org.dromara.pangu.h5.domain.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
@ -7,38 +8,29 @@ import lombok.Data;
/**
* H5密码登录请求DTO
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
@Data
@Schema(description = "密码登录请求参数")
public class H5PasswordLoginDto {
/**
* 手机号
*/
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13812345678")
@NotBlank(message = "手机号不能为空")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
/**
* 密码
*/
@Schema(description = "登录密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
@NotBlank(message = "密码不能为空")
private String password;
/**
* 图形验证码
*/
@Schema(description = "图形验证码答案", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotBlank(message = "验证码不能为空")
private String captchaCode;
/**
* 验证码标识
*/
@Schema(description = "图形验证码标识(从/captcha接口获取", requiredMode = Schema.RequiredMode.REQUIRED, example = "abc123def456")
@NotBlank(message = "验证码标识不能为空")
private String uuid;
/**
* 记住我
*/
@Schema(description = "记住我true时refreshToken有效期30天否则7天", example = "false")
private Boolean rememberMe = false;
}

View File

@ -1,5 +1,6 @@
package org.dromara.pangu.h5.domain.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
@ -7,27 +8,22 @@ import lombok.Data;
/**
* H5修改密码请求DTO
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
@Data
@Schema(description = "修改密码请求参数")
public class H5PasswordUpdateDto {
/**
* 当前密码
*/
@Schema(description = "当前密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "oldpass123")
@NotBlank(message = "当前密码不能为空")
private String oldPassword;
/**
* 新密码
*/
@Schema(description = "新密码至少6位", requiredMode = Schema.RequiredMode.REQUIRED, example = "newpass456")
@NotBlank(message = "新密码不能为空")
@Size(min = 6, message = "新密码至少6位")
private String newPassword;
/**
* 确认新密码
*/
@Schema(description = "确认新密码(必须与新密码一致)", requiredMode = Schema.RequiredMode.REQUIRED, example = "newpass456")
@NotBlank(message = "确认密码不能为空")
private String confirmPassword;
}

View File

@ -1,5 +1,6 @@
package org.dromara.pangu.h5.domain.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
@ -8,39 +9,30 @@ import lombok.Data;
/**
* H5注册请求DTO
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
@Data
@Schema(description = "会员注册请求参数")
public class H5RegisterDto {
/**
* 手机号
*/
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13812345678")
@NotBlank(message = "手机号不能为空")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
/**
* 短信验证码
*/
@Schema(description = "短信验证码6位数字", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
@NotBlank(message = "短信验证码不能为空")
private String smsCode;
/**
* 图形验证码
*/
@Schema(description = "图形验证码答案", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotBlank(message = "图形验证码不能为空")
private String captchaCode;
/**
* 验证码标识
*/
@Schema(description = "图形验证码标识(从/captcha接口获取", requiredMode = Schema.RequiredMode.REQUIRED, example = "abc123def456")
@NotBlank(message = "验证码标识不能为空")
private String uuid;
/**
* 密码
*/
@Schema(description = "登录密码至少6位", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
@NotBlank(message = "密码不能为空")
@Size(min = 6, message = "密码至少6位")
private String password;

View File

@ -1,5 +1,6 @@
package org.dromara.pangu.h5.domain.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
@ -7,33 +8,26 @@ import lombok.Data;
/**
* H5短信验证码登录请求DTO
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
@Data
@Schema(description = "短信验证码登录请求参数")
public class H5SmsLoginDto {
/**
* 手机号
*/
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13812345678")
@NotBlank(message = "手机号不能为空")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
/**
* 短信验证码
*/
@Schema(description = "短信验证码6位数字", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
@NotBlank(message = "短信验证码不能为空")
private String smsCode;
/**
* 图形验证码
*/
@Schema(description = "图形验证码答案", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotBlank(message = "图形验证码不能为空")
private String captchaCode;
/**
* 验证码标识
*/
@Schema(description = "图形验证码标识(从/captcha接口获取", requiredMode = Schema.RequiredMode.REQUIRED, example = "abc123def456")
@NotBlank(message = "验证码标识不能为空")
private String uuid;
}

View File

@ -1,5 +1,6 @@
package org.dromara.pangu.h5.domain.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
@ -7,33 +8,26 @@ import lombok.Data;
/**
* H5发送短信验证码请求DTO
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
@Data
@Schema(description = "发送短信验证码请求参数")
public class H5SmsSendDto {
/**
* 手机号
*/
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13812345678")
@NotBlank(message = "手机号不能为空")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
/**
* 图形验证码
*/
@Schema(description = "图形验证码答案", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotBlank(message = "图形验证码不能为空")
private String captchaCode;
/**
* 验证码标识
*/
@Schema(description = "图形验证码标识(从/captcha接口获取", requiredMode = Schema.RequiredMode.REQUIRED, example = "abc123def456")
@NotBlank(message = "验证码标识不能为空")
private String uuid;
/**
* 类型login-登录register-注册
*/
@Schema(description = "验证码类型login-登录验证码register-注册验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "login", allowableValues = {"login", "register"})
@NotBlank(message = "类型不能为空")
private String type;
}

View File

@ -1,5 +1,6 @@
package org.dromara.pangu.h5.domain.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@ -9,56 +10,41 @@ import java.util.Date;
/**
* H5绑定学生请求DTO
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
@Data
@Schema(description = "绑定学生请求参数")
public class H5StudentBindDto {
/**
* 学生姓名
*/
@Schema(description = "学生姓名", requiredMode = Schema.RequiredMode.REQUIRED, example = "张小明")
@NotBlank(message = "学生姓名不能为空")
private String studentName;
/**
* 学号
*/
@Schema(description = "学号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024001")
@NotBlank(message = "学号不能为空")
private String studentNo;
/**
* 出生日期
*/
@Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2010-05-20")
@NotNull(message = "出生日期不能为空")
private Date birthday;
/**
* 性别0未知 1男 2女
*/
@Schema(description = "性别0-未知1-男2-女", requiredMode = Schema.RequiredMode.REQUIRED, example = "1", allowableValues = {"0", "1", "2"})
@NotBlank(message = "性别不能为空")
private String gender;
/**
* 区域ID
*/
@Schema(description = "区域ID从/h5/base/regions获取", requiredMode = Schema.RequiredMode.REQUIRED, example = "420100")
@NotNull(message = "请选择所在地区")
private Long regionId;
/**
* 学校ID
*/
@Schema(description = "学校ID从/h5/base/schools获取", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "请选择学校")
private Long schoolId;
/**
* 年级ID
*/
@Schema(description = "学校年级关联ID从/h5/base/grades获取的schoolGradeId", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "请选择年级")
private Long schoolGradeId;
/**
* 班级ID
*/
@Schema(description = "学校班级关联ID从/h5/base/classes获取的schoolClassId", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "请选择班级")
private Long schoolClassId;
}

View File

@ -1,22 +1,20 @@
package org.dromara.pangu.h5.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* H5图形验证码响应VO
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
@Data
@Schema(description = "图形验证码响应结果")
public class H5CaptchaVo {
/**
* 验证码标识
*/
@Schema(description = "验证码标识(后续接口需要传递此值)", example = "abc123def456")
private String uuid;
/**
* 验证码图片Base64
*/
@Schema(description = "验证码图片Base64编码前端使用<img src='data:image/png;base64,{captchaImg}'/>", example = "iVBORw0KGgoAAAANSUhEUgAA...")
private String captchaImg;
}

View File

@ -1,52 +1,38 @@
package org.dromara.pangu.h5.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* H5教育身份响应VO
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
@Data
@Schema(description = "教育身份信息(教师)")
public class H5EducationVo {
/**
* 学校ID
*/
@Schema(description = "学校ID", example = "1")
private Long schoolId;
/**
* 学校名称
*/
@Schema(description = "学校名称", example = "武汉市第一中学")
private String schoolName;
/**
* 年级ID
*/
@Schema(description = "学校年级关联ID", example = "1")
private Long schoolGradeId;
/**
* 年级名称
*/
@Schema(description = "年级名称", example = "高一")
private String gradeName;
/**
* 班级ID
*/
@Schema(description = "学校班级关联ID", example = "1")
private Long schoolClassId;
/**
* 班级名称
*/
@Schema(description = "班级名称", example = "1班")
private String className;
/**
* 学科ID
*/
@Schema(description = "学科ID", example = "1")
private Long subjectId;
/**
* 学科名称
*/
@Schema(description = "学科名称", example = "语文")
private String subjectName;
}

View File

@ -1,52 +1,38 @@
package org.dromara.pangu.h5.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* H5登录响应VO
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
@Data
@Schema(description = "登录响应结果")
public class H5LoginVo {
/**
* 访问令牌
*/
@Schema(description = "访问令牌用于请求需要认证的接口放在Header: Authorization: Bearer {token}", example = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...")
private String accessToken;
/**
* 刷新令牌
*/
@Schema(description = "刷新令牌用于刷新accessTokenaccessToken过期时使用", example = "abc123def456ghi789")
private String refreshToken;
/**
* 过期时间
*/
@Schema(description = "accessToken过期时间默认2小时=7200秒", example = "7200")
private Long expiresIn;
/**
* 会员ID
*/
@Schema(description = "会员ID", example = "1234567890123456789")
private Long memberId;
/**
* 会员编号
*/
@Schema(description = "会员编号", example = "M170900000012345678")
private String memberCode;
/**
* 手机号脱敏
*/
@Schema(description = "手机号脱敏中间4位用*替代)", example = "138****5678")
private String phone;
/**
* 昵称
*/
@Schema(description = "昵称", example = "user_5678")
private String nickname;
/**
* 身份类型
*/
@Schema(description = "身份类型1-家长2-教师null-未设置", example = "1")
private String identityType;
}

View File

@ -1,5 +1,6 @@
package org.dromara.pangu.h5.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Date;
@ -8,63 +9,42 @@ import java.util.List;
/**
* H5会员信息响应VO
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
@Data
@Schema(description = "会员信息响应结果")
public class H5MemberInfoVo {
/**
* 会员ID
*/
@Schema(description = "会员ID", example = "1234567890123456789")
private Long memberId;
/**
* 会员编号
*/
@Schema(description = "会员编号", example = "M170900000012345678")
private String memberCode;
/**
* 手机号脱敏
*/
@Schema(description = "手机号(脱敏)", example = "138****5678")
private String phone;
/**
* 昵称
*/
@Schema(description = "昵称", example = "张老师")
private String nickname;
/**
* 头像
*/
@Schema(description = "头像URL", example = "https://example.com/avatar.jpg")
private String avatar;
/**
* 性别0未知 1男 2女
*/
@Schema(description = "性别0-未知1-男2-女", example = "1")
private String gender;
/**
* 生日
*/
@Schema(description = "生日", example = "1990-01-15")
private Date birthday;
/**
* 注册时间
*/
@Schema(description = "注册时间", example = "2024-01-01 12:00:00")
private Date registerTime;
/**
* 身份类型parent/teacher
*/
@Schema(description = "身份类型1-家长2-教师", example = "2")
private String identityType;
/**
* 教育信息教师身份
*/
@Schema(description = "教育身份信息(仅教师身份有值)")
private H5EducationVo education;
/**
* 绑定的学生列表
*/
@Schema(description = "绑定的学生列表")
private List<H5StudentVo> students;
}

View File

@ -1,5 +1,6 @@
package org.dromara.pangu.h5.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Date;
@ -7,73 +8,48 @@ import java.util.Date;
/**
* H5学生信息响应VO
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
@Data
@Schema(description = "学生信息")
public class H5StudentVo {
/**
* 学生ID
*/
@Schema(description = "学生ID", example = "1234567890123456789")
private Long studentId;
/**
* 学生姓名
*/
@Schema(description = "学生姓名", example = "张小明")
private String studentName;
/**
* 学号
*/
@Schema(description = "学号", example = "2024001")
private String studentNo;
/**
* 性别
*/
@Schema(description = "性别0-未知1-男2-女", example = "1")
private String gender;
/**
* 出生日期
*/
@Schema(description = "出生日期", example = "2010-05-20")
private Date birthday;
/**
* 区域ID
*/
@Schema(description = "区域ID", example = "420100")
private Long regionId;
/**
* 区域名称
*/
@Schema(description = "区域名称(如:湖北省武汉市武昌区)", example = "湖北省武汉市武昌区")
private String regionName;
/**
* 学校ID
*/
@Schema(description = "学校ID", example = "1")
private Long schoolId;
/**
* 学校名称
*/
@Schema(description = "学校名称", example = "武汉市第一中学")
private String schoolName;
/**
* 年级ID
*/
@Schema(description = "学校年级关联ID", example = "1")
private Long schoolGradeId;
/**
* 年级名称
*/
@Schema(description = "年级名称", example = "高一")
private String gradeName;
/**
* 班级ID
*/
@Schema(description = "学校班级关联ID", example = "1")
private Long schoolClassId;
/**
* 班级名称
*/
@Schema(description = "班级名称", example = "1班")
private String className;
}

View File

@ -10,7 +10,7 @@ import org.dromara.pangu.h5.domain.vo.H5LoginVo;
/**
* H5认证服务接口
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
public interface H5AuthService {

View File

@ -13,7 +13,7 @@ import java.util.List;
/**
* H5会员服务接口
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
public interface H5MemberService {

View File

@ -44,7 +44,7 @@ import java.util.LinkedHashMap;
/**
* H5认证服务实现
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
@Slf4j
@Service

View File

@ -41,7 +41,7 @@ import java.util.List;
/**
* H5会员服务实现
*
* @author 湖北新华业务中台研发团队
* @author pangu
*/
@Slf4j
@Service