# 团课管理模块 API 文档 > **文档版本**: v1.0 > **创建日期**: 2026-06-02 > **作者**: 张翔 > **状态**: 正式发布 --- ## 📋 目录 1. [概述](#概述) 2. [基础路径](#基础路径) 3. [团课管理接口](#团课管理接口) - [获取所有团课](#获取所有团课) - [分页获取团课](#分页获取团课) - [根据ID获取团课详情](#根据ID获取团课详情) - [创建团课](#创建团课) - [更新团课](#更新团课) - [取消团课](#取消团课) - [团课签到](#团课签到) - [删除团课](#删除团课) 4. [团课预约接口](#团课预约接口) - [预约团课](#预约团课) - [取消预约](#取消预约) - [查询会员预约记录](#查询会员预约记录) - [查询预约详情](#查询预约详情) - [查询课程预约记录](#查询课程预约记录) 5. [团课类型管理接口](#团课类型管理接口) - [获取所有团课类型](#获取所有团课类型) - [根据ID获取团课类型](#根据ID获取团课类型) - [搜索团课类型](#搜索团课类型) - [根据分类获取团课类型](#根据分类获取团课类型) - [获取所有分类](#获取所有分类) - [创建团课类型](#创建团课类型) - [更新团课类型](#更新团课类型) - [删除团课类型](#删除团课类型) 6. [团课标签管理接口](#团课标签管理接口) - [获取所有标签](#获取所有标签) - [根据ID获取标签](#根据ID获取标签) - [搜索标签](#搜索标签) - [获取类型的标签](#获取类型的标签) - [创建标签](#创建标签) - [更新标签](#更新标签) - [删除标签](#删除标签) - [为类型添加标签](#为类型添加标签) - [从类型移除标签](#从类型移除标签) - [清空类型标签](#清空类型标签) 7. [数据模型](#数据模型) - [GroupCourse(团课)](#GroupCourse团课) - [GroupCourseBooking(团课预约)](#GroupCourseBooking团课预约) - [GroupCourseType(团课类型)](#GroupCourseType团课类型) 7. [状态码说明](#状态码说明) 8. [业务规则](#业务规则) --- ## 概述 团课管理模块提供团课的创建、编辑、查询、取消和签到功能,以及团课预约相关操作。采用 Spring WebFlux 响应式编程,支持高并发场景。 ## 基础路径 所有接口的基础路径为: `http://{host}:{port}/api/groupCourse` --- ## 团课管理接口 ### 获取所有团课 | 属性 | 值 | |------|-----| | **HTTP方法** | GET | | **接口路径** | `/api/groupCourse/list` | | **所属文件** | `GroupCourseHandler.java` | **请求参数**: | 参数名 | 类型 | 必填 | 默认值 | 说明 | |--------|------|------|--------|------| | includeDeleted | boolean | 否 | false | 是否包含已删除的团课 | **成功响应** (200 OK): ```json [ { "id": 1, "courseName": "瑜伽入门", "coachId": 1, "courseType": 1, "startTime": "2026-06-02T09:00:00", "endTime": "2026-06-02T10:00:00", "maxMembers": 20, "currentMembers": 15, "status": 0, "location": "健身房A区", "coverImage": "https://example.com/yoga.jpg", "description": "适合初学者的瑜伽课程", "createdAt": "2026-06-01T10:00:00", "updatedAt": "2026-06-01T10:00:00" } ] ``` --- ### 分页获取团课 | 属性 | 值 | |------|-----| | **HTTP方法** | POST | | **接口路径** | `/api/groupCourse/page` | | **所属文件** | `GroupCourseHandler.java` | **请求体**: ```json { "page": 0, "size": 10, "sort": "id", "order": "asc", "keyword": "瑜伽" } ``` | 参数名 | 类型 | 必填 | 默认值 | 说明 | |--------|------|------|--------|------| | page | int | 否 | 0 | 页码,从0开始 | | size | int | 否 | 10 | 每页数量,最大100 | | sort | string | 否 | id | 排序字段 | | order | string | 否 | asc | 排序方式(asc/desc) | | keyword | string | 否 | - | 搜索关键词 | **请求参数**: | 参数名 | 类型 | 必填 | 默认值 | 说明 | |--------|------|------|--------|------| | includeDeleted | boolean | 否 | false | 是否包含已删除的团课 | **成功响应** (200 OK): ```json { "data": [...], "totalPages": 5, "totalElements": 45, "page": 0, "size": 10 } ``` --- ### 根据ID获取团课详情 | 属性 | 值 | |------|-----| | **HTTP方法** | GET | | **接口路径** | `/api/groupCourse/{id}` | | **所属文件** | `GroupCourseHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 团课ID | **成功响应** (200 OK): ```json { "id": 1, "courseName": "瑜伽入门", "coachId": 1, "courseType": 1, "startTime": "2026-06-02T09:00:00", "endTime": "2026-06-02T10:00:00", "maxMembers": 20, "currentMembers": 15, "status": 0, "location": "健身房A区", "coverImage": "https://example.com/yoga.jpg", "description": "适合初学者的瑜伽课程", "pointCardAmount": 1, "storedValueAmount": 50.00, "createdAt": "2026-06-01T10:00:00", "updatedAt": "2026-06-01T10:00:00" } ``` **失败响应** (404 Not Found): ```json {} ``` --- ### 根据ID获取团课完整信息 | 属性 | 值 | |------|-----| | **HTTP方法** | GET | | **接口路径** | `/api/groupCourse/{id}/detail` | | **所属文件** | `GroupCourseHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 团课ID | **成功响应** (200 OK): ```json { "id": 1, "courseName": "瑜伽入门", "coachId": 1, "courseType": 1, "startTime": "2026-06-02T09:00:00", "endTime": "2026-06-02T10:00:00", "maxMembers": 20, "currentMembers": 15, "status": 0, "location": "健身房A区", "coverImage": "https://example.com/yoga.jpg", "description": "适合初学者的瑜伽课程", "pointCardAmount": 1, "storedValueAmount": 50.00, "typeName": "瑜伽入门", "typeCategory": "柔韧与平衡类", "baseDifficulty": 2, "difficultyLevel": "初级", "calculatedDifficulty": 2, "typeInfo": { "id": 1, "typeName": "瑜伽入门", "baseDifficulty": 2, "calculatedDifficulty": 2, "difficultyLevel": "初级", "description": "适合初学者的瑜伽课程,注重基础体式", "category": "柔韧与平衡类", "labels": [ {"id": 1, "labelName": "适合新手", "color": "#52c41a"}, {"id": 3, "labelName": "减压放松", "color": "#1890ff"} ] }, "labels": [ {"id": 1, "labelName": "适合新手", "color": "#52c41a"}, {"id": 3, "labelName": "减压放松", "color": "#1890ff"} ], "createdAt": "2026-06-01T10:00:00", "updatedAt": "2026-06-01T10:00:00" } ``` **失败响应** (404 Not Found): ```json {} ``` **说明**: 此接口返回团课的完整信息,包括: - 团课基础信息 - 团课对应的类型信息(包含基础难度、综合难度、难度等级等) - 该类型的所有标签信息 --- ### 创建团课 | 属性 | 值 | |------|-----| | **HTTP方法** | POST | | **接口路径** | `/api/groupCourse` | | **所属文件** | `GroupCourseHandler.java` | **请求体**: ```json { "courseName": "动感单车", "coachId": 2, "courseType": 2, "startTime": "2026-06-05T18:00:00", "endTime": "2026-06-05T19:00:00", "maxMembers": 25, "location": "健身房B区", "coverImage": "https://example.com/spinning.jpg", "description": "高强度有氧运动课程", "pointCardAmount": 1, "storedValueAmount": 50.00 } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | courseName | String | **是** | 课程名称 | | coachId | Long | 否 | 教练ID | | courseType | Long | 否 | 课程类型 | | startTime | LocalDateTime | 否 | 开始时间 | | endTime | LocalDateTime | 否 | 结束时间 | | maxMembers | Integer | 否 | 最大参与人数,默认20 | | location | String | 否 | 上课地点 | | coverImage | String | 否 | 封面图URL | | description | String | 否 | 课程描述 | | pointCardAmount | Integer | 否 | 点卡额度(消耗次数),默认1 | | storedValueAmount | BigDecimal | 否 | 储值卡额度(消耗金额),默认0 | **成功响应** (200 OK): ```json { "success": true, "message": "团课创建成功", "data": { "id": 2, "courseName": "动感单车", "coachId": 2, "courseType": 2, "startTime": "2026-06-05T18:00:00", "endTime": "2026-06-05T19:00:00", "maxMembers": 25, "currentMembers": 0, "status": 0, "location": "健身房B区", "coverImage": "https://example.com/spinning.jpg", "description": "高强度有氧运动课程", "pointCardAmount": 1, "storedValueAmount": 50.00 } } ``` **失败响应** (400 Bad Request): ```json { "success": false, "message": "课程名称不能为空" } ``` --- ### 更新团课 | 属性 | 值 | |------|-----| | **HTTP方法** | PUT | | **接口路径** | `/api/groupCourse/{id}` | | **所属文件** | `GroupCourseHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 团课ID | **请求体**: ```json { "courseName": "动感单车升级版", "coachId": 2, "maxMembers": 30, "description": "升级版高强度有氧运动课程", "pointCardAmount": 2, "storedValueAmount": 80.00 } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | courseName | String | 否 | 课程名称 | | coachId | Long | 否 | 教练ID | | courseType | Long | 否 | 课程类型 | | startTime | LocalDateTime | 否 | 开始时间 | | endTime | LocalDateTime | 否 | 结束时间 | | maxMembers | Integer | 否 | 最大参与人数 | | location | String | 否 | 上课地点 | | coverImage | String | 否 | 封面图URL | | description | String | 否 | 课程描述 | | pointCardAmount | Integer | 否 | 点卡额度(消耗次数) | | storedValueAmount | BigDecimal | 否 | 储值卡额度(消耗金额) | **成功响应** (200 OK): ```json { "success": true, "message": "团课更新成功", "data": { "id": 2, "courseName": "动感单车升级版", "coachId": 2, "maxMembers": 30, "description": "升级版高强度有氧运动课程", "pointCardAmount": 2, "storedValueAmount": 80.00 } } ``` **失败响应** (400 Bad Request): ```json { "success": false, "message": "团课不存在" } ``` --- ### 取消团课 | 属性 | 值 | |------|-----| | **HTTP方法** | POST | | **接口路径** | `/api/groupCourse/{id}/cancel` | | **所属文件** | `GroupCourseHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 团课ID | **成功响应** (200 OK): ```json { "success": true, "message": "团课取消成功", "data": { "id": 2, "status": 1 } } ``` **失败响应** (400 Bad Request): ```json { "success": false, "message": "课程取消需提前24小时" } ``` --- ### 团课签到 | 属性 | 值 | |------|-----| | **HTTP方法** | POST | | **接口路径** | `/api/groupCourse/{courseId}/signin` | | **所属文件** | `GroupCourseHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | courseId | Long | 是 | 团课ID | **请求体**: ```json { "memberId": 1001 } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | memberId | Long | **是** | 会员ID | **成功响应** (200 OK): ```json { "success": true, "message": "签到成功", "data": { "id": 2, "currentMembers": 16 } } ``` **失败响应** (400 Bad Request): ```json { "success": false, "message": "课程已满员" } ``` --- ### 删除团课 | 属性 | 值 | |------|-----| | **HTTP方法** | DELETE | | **接口路径** | `/api/groupCourse/{id}` | | **所属文件** | `GroupCourseHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 团课ID | **成功响应** (200 OK): ```json { "success": true, "message": "团课删除成功" } ``` --- ## 团课预约接口 ### 预约团课 | 属性 | 值 | |------|-----| | **HTTP方法** | POST | | **接口路径** | `/api/groupCourse/book` | | **所属文件** | `GroupCourseBookingHandler.java` | **请求体**: ```json { "courseId": 1, "memberId": 1001, "memberCardRecordId": 5001 } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | courseId | Long | **是** | 团课ID | | memberId | Long | **是** | 会员ID | | memberCardRecordId | Long | **是** | 会员卡记录ID | **成功响应** (200 OK): ```json { "success": true, "message": "预约成功", "data": { "id": 100, "courseId": 1, "memberId": 1001, "memberCardRecordId": 5001, "bookingTime": "2026-06-02T08:00:00", "status": "0" } } ``` --- ### 取消预约 | 属性 | 值 | |------|-----| | **HTTP方法** | POST | | **接口路径** | `/api/groupCourse/booking/{bookingId}/cancel` | | **所属文件** | `GroupCourseBookingHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | bookingId | Long | 是 | 预约ID | **请求体**: ```json { "memberId": 1001 } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | memberId | Long | **是** | 会员ID | **成功响应** (200 OK): ```json { "success": true, "message": "取消成功", "data": { "id": 100, "status": "1", "cancelTime": "2026-06-02T09:00:00" } } ``` --- ### 查询会员预约记录 | 属性 | 值 | |------|-----| | **HTTP方法** | GET | | **接口路径** | `/api/groupCourse/bookings/member/{memberId}` | | **所属文件** | `GroupCourseBookingHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | memberId | Long | 是 | 会员ID | **成功响应** (200 OK): ```json [ { "id": 100, "courseId": 1, "courseName": "瑜伽入门", "memberId": 1001, "memberCardRecordId": 5001, "bookingTime": "2026-06-02T08:00:00", "status": "0", "courseStartTime": "2026-06-02T09:00:00", "location": "健身房A区" } ] ``` --- ### 查询预约详情 | 属性 | 值 | |------|-----| | **HTTP方法** | GET | | **接口路径** | `/api/groupCourse/bookings/{bookingId}` | | **所属文件** | `GroupCourseBookingHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | bookingId | Long | 是 | 预约ID | **成功响应** (200 OK): ```json { "id": 100, "courseId": 1, "courseName": "瑜伽入门", "memberId": 1001, "memberCardRecordId": 5001, "bookingTime": "2026-06-02T08:00:00", "status": "0", "courseStartTime": "2026-06-02T09:00:00", "courseEndTime": "2026-06-02T10:00:00", "location": "健身房A区" } ``` **失败响应** (404 Not Found): ```json {} ``` --- ### 查询课程预约记录 | 属性 | 值 | |------|-----| | **HTTP方法** | GET | | **接口路径** | `/api/groupCourse/bookings/course/{courseId}` | | **所属文件** | `GroupCourseBookingHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | courseId | Long | 是 | 团课ID | **成功响应** (200 OK): ```json [ { "id": 100, "courseId": 1, "courseName": "瑜伽入门", "memberId": 1001, "bookingTime": "2026-06-02T08:00:00", "status": "0" } ] ``` --- ## 团课类型管理接口 ### 获取所有团课类型 | 属性 | 值 | |------|-----| | **HTTP方法** | GET | | **接口路径** | `/api/groupCourse/types` | | **所属文件** | `GroupCourseTypeHandler.java` | **请求参数**: | 参数名 | 类型 | 必填 | 默认值 | 说明 | |--------|------|------|--------|------| | includeDeleted | boolean | 否 | false | 是否包含已删除的类型 | **成功响应** (200 OK): ```json [ { "id": 1, "typeName": "瑜伽入门", "baseDifficulty": 2, "calculatedDifficulty": 2, "difficultyLevel": "初级", "description": "适合初学者的瑜伽课程,注重基础体式", "category": "柔韧与平衡类", "createdAt": "2026-06-01T10:00:00", "updatedAt": "2026-06-01T10:00:00" } ] ``` --- ### 根据ID获取团课类型 | 属性 | 值 | |------|-----| | **HTTP方法** | GET | | **接口路径** | `/api/groupCourse/types/{id}` | | **所属文件** | `GroupCourseTypeHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 团课类型ID | **成功响应** (200 OK): ```json { "id": 1, "typeName": "瑜伽入门", "baseDifficulty": 2, "calculatedDifficulty": 2, "difficultyLevel": "初级", "description": "适合初学者的瑜伽课程,注重基础体式", "category": "柔韧与平衡类", "createdAt": "2026-06-01T10:00:00", "updatedAt": "2026-06-01T10:00:00" } ``` **失败响应** (404 Not Found): ```json {} ``` --- ### 搜索团课类型 | 属性 | 值 | |------|-----| | **HTTP方法** | GET | | **接口路径** | `/api/groupCourse/types/search` | | **所属文件** | `GroupCourseTypeHandler.java` | **请求参数**: | 参数名 | 类型 | 必填 | 默认值 | 说明 | |--------|------|------|--------|------| | keyword | string | 否 | - | 搜索关键词(匹配类型名称) | **成功响应** (200 OK): ```json [ { "id": 1, "typeName": "瑜伽入门", "baseDifficulty": 2, "difficultyLevel": "初级", "category": "柔韧与平衡类" } ] ``` --- ### 根据分类获取团课类型 | 属性 | 值 | |------|-----| | **HTTP方法** | GET | | **接口路径** | `/api/groupCourse/types/category/{category}` | | **所属文件** | `GroupCourseTypeHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | category | String | 是 | 分类名称 | **请求参数**: | 参数名 | 类型 | 必填 | 默认值 | 说明 | |--------|------|------|--------|------| | keyword | string | 否 | - | 搜索关键词 | **成功响应** (200 OK): ```json [ { "id": 1, "typeName": "瑜伽入门", "baseDifficulty": 2, "difficultyLevel": "初级", "category": "柔韧与平衡类" } ] ``` --- ### 获取所有分类 | 属性 | 值 | |------|-----| | **HTTP方法** | GET | | **接口路径** | `/api/groupCourse/types/categories` | | **所属文件** | `GroupCourseTypeHandler.java` | **成功响应** (200 OK): ```json ["基础有氧与热身", "固定器械训练", "自重基础动作", "自由重量杠铃/哑铃", "高强度与爆发力", "柔韧与平衡类"] ``` --- ### 创建团课类型 | 属性 | 值 | |------|-----| | **HTTP方法** | POST | | **接口路径** | `/api/groupCourse/types` | | **所属文件** | `GroupCourseTypeHandler.java` | **请求体**: ```json { "typeName": "核心力量训练", "baseDifficulty": 4, "description": "针对核心肌群的专项训练课程", "category": "自重基础动作" } ``` | 参数名 | 类型 | 必填 | 默认值 | 说明 | |--------|------|------|--------|------| | typeName | String | **是** | - | 类型名称 | | baseDifficulty | Integer | 否 | 1 | 基础难度(1-10) | | description | String | 否 | - | 类型描述 | | category | String | 否 | - | 分类 | **成功响应** (200 OK): ```json { "success": true, "message": "团课类型创建成功", "data": { "id": 40, "typeName": "核心力量训练", "baseDifficulty": 4, "calculatedDifficulty": 4, "difficultyLevel": "中级", "description": "针对核心肌群的专项训练课程", "category": "自重基础动作" } } ``` **失败响应** (400 Bad Request): ```json { "success": false, "message": "类型名称不能为空" } ``` --- ### 更新团课类型 | 属性 | 值 | |------|-----| | **HTTP方法** | PUT | | **接口路径** | `/api/groupCourse/types/{id}` | | **所属文件** | `GroupCourseTypeHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 团课类型ID | **请求体**: ```json { "typeName": "核心力量训练进阶", "baseDifficulty": 6, "description": "进阶核心训练课程" } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | typeName | String | 否 | 类型名称 | | baseDifficulty | Integer | 否 | 基础难度(1-10) | | description | String | 否 | 类型描述 | | category | String | 否 | 分类 | **成功响应** (200 OK): ```json { "success": true, "message": "团课类型更新成功", "data": { "id": 40, "typeName": "核心力量训练进阶", "baseDifficulty": 6, "calculatedDifficulty": 6, "difficultyLevel": "中高级", "description": "进阶核心训练课程", "category": "自重基础动作" } } ``` --- ### 删除团课类型 | 属性 | 值 | |------|-----| | **HTTP方法** | DELETE | | **接口路径** | `/api/groupCourse/types/{id}` | | **所属文件** | `GroupCourseTypeHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 团课类型ID | **成功响应** (200 OK): ```json { "success": true, "message": "团课类型删除成功" } ``` --- ## 团课标签管理接口 ### 获取所有标签 | 属性 | 值 | |------|-----| | **HTTP方法** | GET | | **接口路径** | `/api/groupCourse/labels` | | **所属文件** | `CourseLabelHandler.java` | **成功响应** (200 OK): ```json [ { "id": 1, "labelName": "适合新手", "color": "#52c41a", "createdAt": "2026-06-01T10:00:00", "updatedAt": "2026-06-01T10:00:00" }, { "id": 2, "labelName": "中级过渡", "color": "#faad14", "createdAt": "2026-06-01T10:00:00", "updatedAt": "2026-06-01T10:00:00" } ] ``` --- ### 根据ID获取标签 | 属性 | 值 | |------|-----| | **HTTP方法** | GET | | **接口路径** | `/api/groupCourse/labels/{id}` | | **所属文件** | `CourseLabelHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 标签ID | **成功响应** (200 OK): ```json { "id": 1, "labelName": "适合新手", "color": "#52c41a", "createdAt": "2026-06-01T10:00:00", "updatedAt": "2026-06-01T10:00:00" } ``` **失败响应** (404 Not Found): ```json {} ``` --- ### 搜索标签 | 属性 | 值 | |------|-----| | **HTTP方法** | GET | | **接口路径** | `/api/groupCourse/labels/search` | | **所属文件** | `CourseLabelHandler.java` | **请求参数**: | 参数名 | 类型 | 必填 | 默认值 | 说明 | |--------|------|------|--------|------| | keyword | string | 否 | - | 搜索关键词(匹配标签名称) | **成功响应** (200 OK): ```json [ { "id": 1, "labelName": "适合新手", "color": "#52c41a" } ] ``` --- ### 获取类型的标签 | 属性 | 值 | |------|-----| | **HTTP方法** | GET | | **接口路径** | `/api/groupCourse/types/{typeId}/labels` | | **所属文件** | `CourseLabelHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | typeId | Long | 是 | 团课类型ID | **成功响应** (200 OK): ```json [ { "id": 1, "labelName": "适合新手", "color": "#52c41a" }, { "id": 3, "labelName": "减压放松", "color": "#1890ff" } ] ``` --- ### 创建标签 | 属性 | 值 | |------|-----| | **HTTP方法** | POST | | **接口路径** | `/api/groupCourse/labels` | | **所属文件** | `CourseLabelHandler.java` | **请求体**: ```json { "labelName": "燃脂塑形", "color": "#f5222d" } ``` | 参数名 | 类型 | 必填 | 默认值 | 说明 | |--------|------|------|--------|------| | labelName | String | **是** | - | 标签名称(最大50字符) | | color | String | 否 | #1890ff | 标签颜色(十六进制颜色值) | **成功响应** (200 OK): ```json { "success": true, "message": "标签创建成功", "data": { "id": 15, "labelName": "燃脂塑形", "color": "#f5222d" } } ``` **失败响应** (400 Bad Request): ```json { "success": false, "message": "标签名称已存在" } ``` --- ### 更新标签 | 属性 | 值 | |------|-----| | **HTTP方法** | PUT | | **接口路径** | `/api/groupCourse/labels/{id}` | | **所属文件** | `CourseLabelHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 标签ID | **请求体**: ```json { "labelName": "燃脂塑形进阶", "color": "#fa541c" } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | labelName | String | 否 | 标签名称(最大50字符) | | color | String | 否 | 标签颜色(十六进制颜色值) | **成功响应** (200 OK): ```json { "success": true, "message": "标签更新成功", "data": { "id": 15, "labelName": "燃脂塑形进阶", "color": "#fa541c" } } ``` --- ### 删除标签 | 属性 | 值 | |------|-----| | **HTTP方法** | DELETE | | **接口路径** | `/api/groupCourse/labels/{id}` | | **所属文件** | `CourseLabelHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 标签ID | **成功响应** (200 OK): ```json { "success": true, "message": "标签删除成功" } ``` --- ### 为类型添加标签 | 属性 | 值 | |------|-----| | **HTTP方法** | POST | | **接口路径** | `/api/groupCourse/types/{typeId}/labels` | | **所属文件** | `CourseLabelHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | typeId | Long | 是 | 团课类型ID | **请求体**: ```json { "labelIds": [1, 3, 5] } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | labelIds | List\ | **是** | 要添加的标签ID列表 | **成功响应** (200 OK): ```json { "success": true, "message": "标签添加成功" } ``` --- ### 从类型移除标签 | 属性 | 值 | |------|-----| | **HTTP方法** | DELETE | | **接口路径** | `/api/groupCourse/types/{typeId}/labels/{labelId}` | | **所属文件** | `CourseLabelHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | typeId | Long | 是 | 团课类型ID | | labelId | Long | 是 | 标签ID | **成功响应** (200 OK): ```json { "success": true, "message": "标签移除成功" } ``` --- ### 清空类型标签 | 属性 | 值 | |------|-----| | **HTTP方法** | DELETE | | **接口路径** | `/api/groupCourse/types/{typeId}/labels` | | **所属文件** | `CourseLabelHandler.java` | **路径参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | typeId | Long | 是 | 团课类型ID | **成功响应** (200 OK): ```json { "success": true, "message": "标签清空成功" } ``` --- ## 数据模型 ### GroupCourse(团课) | 字段名 | 类型 | 说明 | |--------|------|------| | id | Long | 主键ID | | courseName | String | 课程名称 | | coachId | Long | 教练ID | | courseType | Long | 课程类型 | | startTime | LocalDateTime | 开始时间 | | endTime | LocalDateTime | 结束时间 | | maxMembers | Integer | 最大参与人数 | | currentMembers | Integer | 当前参与人数 | | status | Long | 状态(0-正常,1-已取消,2-已结束) | | location | String | 上课地点 | | coverImage | String | 封面图URL | | description | String | 课程描述 | | pointCardAmount | Integer | 点卡额度(消耗次数),默认1 | | storedValueAmount | BigDecimal | 储值卡额度(消耗金额),默认0 | | createdBy | String | 创建人 | | updatedBy | String | 更新人 | | createdAt | LocalDateTime | 创建时间 | | updatedAt | LocalDateTime | 更新时间 | | deletedAt | LocalDateTime | 删除时间(软删除) | ### GroupCourseBooking(团课预约) | 字段名 | 类型 | 说明 | |--------|------|------| | id | Long | 主键ID | | courseId | Long | 团课ID | | courseName | String | 团课名称 | | memberId | Long | 会员ID | | memberCardRecordId | Long | 会员卡记录ID | | bookingTime | LocalDateTime | 预约时间 | | status | String | 状态(0-已预约,1-已取消,2-已出席,3-缺席) | | cancelTime | LocalDateTime | 取消时间 | | courseStartTime | LocalDateTime | 课程开始时间 | | courseEndTime | LocalDateTime | 课程结束时间 | | location | String | 上课地点 | | createdBy | String | 创建人 | | updatedBy | String | 更新人 | | createdAt | LocalDateTime | 创建时间 | | updatedAt | LocalDateTime | 更新时间 | | deletedAt | LocalDateTime | 删除时间(软删除) | ### GroupCourseType(团课类型) | 字段名 | 类型 | 说明 | |--------|------|------| | id | Long | 主键ID | | typeName | String | 类型名称 | | baseDifficulty | Integer | 基础难度(1-10) | | calculatedDifficulty | Integer | 综合难度系数(预留扩展字段) | | difficultyLevel | String | 难度等级描述(初级/中级/中高级/高级/专家级) | | description | String | 类型描述 | | category | String | 分类(如:有氧、力量、柔韧等) | | labels | List\ | 标签列表 | | createdBy | String | 创建人 | | updatedBy | String | 更新人 | | createdAt | LocalDateTime | 创建时间 | | updatedAt | LocalDateTime | 更新时间 | | deletedAt | LocalDateTime | 删除时间(软删除) | ### CourseLabel(团课标签) | 字段名 | 类型 | 说明 | |--------|------|------| | id | Long | 主键ID | | labelName | String | 标签名称(最大50字符) | | color | String | 标签颜色(十六进制颜色值,默认#1890ff) | | createdBy | String | 创建人 | | updatedBy | String | 更新人 | | createdAt | LocalDateTime | 创建时间 | | updatedAt | LocalDateTime | 更新时间 | | deletedAt | LocalDateTime | 删除时间(软删除) | ### GroupCourseDetail(团课完整信息) | 字段名 | 类型 | 说明 | |--------|------|------| | id | Long | 主键ID | | courseName | String | 课程名称 | | coachId | Long | 教练ID | | courseType | Long | 课程类型ID | | startTime | LocalDateTime | 开始时间 | | endTime | LocalDateTime | 结束时间 | | maxMembers | Integer | 最大参与人数 | | currentMembers | Integer | 当前参与人数 | | status | Long | 状态(0-正常,1-已取消,2-已结束) | | location | String | 上课地点 | | coverImage | String | 封面图URL | | description | String | 课程描述 | | pointCardAmount | Integer | 点卡额度(消耗次数) | | storedValueAmount | BigDecimal | 储值卡额度(消耗金额) | | typeName | String | 类型名称(快捷访问) | | typeCategory | String | 类型分类(快捷访问) | | baseDifficulty | Integer | 基础难度(快捷访问) | | difficultyLevel | String | 难度等级描述(快捷访问) | | calculatedDifficulty | Integer | 综合难度系数(快捷访问) | | typeInfo | GroupCourseType | 类型信息 | | labels | List\ | 标签列表 | | createdAt | LocalDateTime | 创建时间 | | updatedAt | LocalDateTime | 更新时间 | **难度等级对应关系**: | 基础难度 | 难度等级 | |----------|----------| | 1-2 | 初级 | | 3-4 | 中级 | | 5-6 | 中高级 | | 7-8 | 高级 | | 9-10 | 专家级 | **难度扩展说明**: `calculatedDifficulty` 字段为预留扩展字段,当前实现仅返回 `baseDifficulty`。未来可扩展的影响因素包括: 1. **课程时长系数**:时长越长难度越高 2. **教练难度调整系数**:教练可根据实际情况微调 3. **会员等级适配系数**:根据会员等级动态调整显示难度 4. **课程强度系数**:高强度课程难度加成 --- ## 状态码说明 ### 团课状态 | 状态码 | 含义 | |--------|------| | 0 | 正常 | | 1 | 已取消 | | 2 | 已结束 | ### 预约状态 | 状态码 | 含义 | |--------|------| | 0 | 已预约 | | 1 | 已取消 | | 2 | 已出席 | | 3 | 缺席 | --- ## 业务规则 ### 团课管理 1. **创建团课**:课程名称为必填项 2. **取消团课**:需提前24小时通知,否则拒绝操作 3. **团课签到**:验证课程状态必须为正常,且未达最大人数限制 4. **删除团课**:采用软删除机制,数据保留可恢复 ### 团课预约 1. **预约团课**:需验证会员卡有效性和课程名额 2. **取消预约**:需在课程开始前至少2小时取消 --- ## 附录:错误响应格式 所有接口的错误响应统一格式: ```json { "success": false, "message": "错误描述信息" } ``` --- *文档结束*