From b5c8a087dded78f437875dbcfaf6e3559c018e8b Mon Sep 17 00:00:00 2001 From: liwentao Date: Mon, 15 Jun 2026 14:09:19 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=9B=A2=E8=AF=BE=E5=A4=9A?= =?UTF-8?q?=E6=9D=A1=E4=BB=B6=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gym-manage-api/docs/groupcourse-api.md | 144 ++++++++++++++ .../groupcourse/dao/GroupCourseDao.java | 187 +++++++++++++++++- .../groupcourse/dto/GroupCourseQueryDto.java | 116 +++++++++++ .../handler/GroupCourseHandler.java | 22 +++ .../repository/IGroupCourseRepository.java | 3 + .../impl/GroupCourseRepository.java | 24 +++ .../service/IGroupCourseService.java | 3 + .../service/impl/GroupCourseService.java | 13 ++ .../gym/manage/app/config/SystemRouter.java | 1 + 9 files changed, 511 insertions(+), 2 deletions(-) create mode 100644 gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/dto/GroupCourseQueryDto.java diff --git a/gym-manage-api/docs/groupcourse-api.md b/gym-manage-api/docs/groupcourse-api.md index cad1497..124c171 100644 --- a/gym-manage-api/docs/groupcourse-api.md +++ b/gym-manage-api/docs/groupcourse-api.md @@ -14,6 +14,7 @@ 3. [团课管理接口](#团课管理接口) - [获取所有团课](#获取所有团课) - [分页获取团课](#分页获取团课) + - [多条件查询团课](#多条件查询团课) - [根据ID获取团课详情](#根据ID获取团课详情) - [创建团课](#创建团课) - [更新团课](#更新团课) @@ -154,6 +155,149 @@ --- +### 多条件查询团课 + +| 属性 | 值 | +|------|-----| +| **HTTP方法** | POST | +| **接口路径** | `/api/groupCourse/search` | +| **所属文件** | `GroupCourseHandler.java` | + +**功能说明**: 支持团课名称模糊查询、类型筛选、日期范围、时间段、价格排序、剩余名额排序等多条件组合查询,默认不查询不可预约的团课(已取消或已结束)。 + +**请求体**: + +```json +{ + "courseName": "瑜伽", + "courseType": 1, + "startDate": "2026-06-01T00:00:00", + "endDate": "2026-06-30T23:59:59", + "timePeriod": "morning", + "priceSort": "asc", + "remainingMost": true, + "page": 0, + "size": 10 +} +``` + +| 参数名 | 类型 | 必填 | 默认值 | 说明 | +|--------|------|------|--------|------| +| courseName | String | 否 | - | 课程名称(模糊查询,不区分大小写) | +| courseType | Long | 否 | - | 课程类型ID | +| startDate | LocalDateTime | 否 | - | 查询开始日期 | +| endDate | LocalDateTime | 否 | - | 查询结束日期 | +| timePeriod | String | 否 | - | 时间段:`morning`(6:00-12:00)、`afternoon`(12:00-18:00)、`evening`(18:00-24:00) | +| priceSort | String | 否 | - | 价格排序:`asc`(从低到高)、`desc`(从高到低) | +| remainingMost | Boolean | 否 | false | 是否按剩余名额最多排序 | +| page | Integer | 否 | 0 | 页码,从0开始 | +| size | Integer | 否 | 10 | 每页数量,最大100 | + +**查询条件优先级说明**: + +| 优先级 | 条件类型 | 说明 | +|--------|----------|------| +| 1 | 默认过滤 | 自动过滤已删除和不可预约的团课(status != 0) | +| 2 | 基础筛选 | courseName、courseType、startDate、endDate、timePeriod | +| 3 | 排序规则 | remainingMost优先,其次priceSort,默认按startTime升序 | + +**成功响应** (200 OK): + +```json +{ + "success": true, + "message": "查询成功", + "data": { + "content": [ + { + "id": 1, + "courseName": "瑜伽入门", + "coachId": 1, + "courseType": 1, + "startTime": "2026-06-15T09:00:00", + "endTime": "2026-06-15T10:00:00", + "maxMembers": 20, + "currentMembers": 5, + "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" + } + ], + "totalPages": 3, + "totalElements": 25, + "currentPage": 0, + "pageSize": 10, + "first": true, + "last": false + } +} +``` + +**失败响应** (400 Bad Request): + +```json +{ + "success": false, + "message": "查询失败的原因" +} +``` + +**使用示例**: + +1. **查询瑜伽课程** +```json +{ + "courseName": "瑜伽" +} +``` + +2. **查询特定类型的早晨课程** +```json +{ + "courseType": 1, + "timePeriod": "morning" +} +``` + +3. **查询下周的课程,按价格从低到高排序** +```json +{ + "startDate": "2026-06-16T00:00:00", + "endDate": "2026-06-22T23:59:59", + "priceSort": "asc" +} +``` + +4. **查询剩余名额最多的晚间课程** +```json +{ + "timePeriod": "evening", + "remainingMost": true +} +``` + +5. **多条件组合查询** +```json +{ + "courseName": "瑜伽", + "courseType": 1, + "startDate": "2026-06-01T00:00:00", + "endDate": "2026-06-30T23:59:59", + "timePeriod": "morning", + "priceSort": "asc", + "remainingMost": true, + "page": 0, + "size": 10 +} +``` + +--- + ### 根据ID获取团课详情 | 属性 | 值 | diff --git a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/dao/GroupCourseDao.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/dao/GroupCourseDao.java index e580d6c..dc0f318 100644 --- a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/dao/GroupCourseDao.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/dao/GroupCourseDao.java @@ -1,16 +1,19 @@ - package cn.novalon.gym.manage.groupcourse.dao; +import cn.novalon.gym.manage.groupcourse.dto.GroupCourseQueryDto; import cn.novalon.gym.manage.groupcourse.entity.GroupCourseEntity; import org.springframework.data.domain.Sort; import org.springframework.data.r2dbc.repository.Modifying; import org.springframework.data.r2dbc.repository.Query; import org.springframework.data.r2dbc.repository.R2dbcRepository; +import org.springframework.r2dbc.core.DatabaseClient; import org.springframework.stereotype.Repository; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; @Repository public interface GroupCourseDao extends R2dbcRepository { @@ -38,4 +41,184 @@ public interface GroupCourseDao extends R2dbcRepository Mono softDelete(Long id, LocalDateTime deletedAt); Flux findByCourseTypeAndDeletedAtIsNull(Long courseType); -} + + /** + * 多条件查询团课(使用 DatabaseClient 构建动态 SQL) + */ + default Flux searchGroupCourses(DatabaseClient databaseClient, GroupCourseQueryDto query) { + StringBuilder sql = new StringBuilder("SELECT * FROM group_course WHERE deleted_at IS NULL"); + List conditions = new ArrayList<>(); + + // 默认不查询不可预约的团课(仅查询 status = '0') + conditions.add("status = '0'"); + + // 1. 团课名称模糊查询 + if (query.getCourseName() != null && !query.getCourseName().isEmpty()) { + conditions.add("course_name ILIKE :courseName"); + } + + // 2. 基于团课类型查询 + if (query.getCourseType() != null) { + conditions.add("course_type = :courseType"); + } + + // 3. 基于日期时间段查询 + if (query.getStartDate() != null) { + conditions.add("start_time >= :startDate"); + } + if (query.getEndDate() != null) { + conditions.add("start_time <= :endDate"); + } + + // 4. 基于早晨/下午/夜晚时间段查询 + if (query.getTimePeriod() != null && !query.getTimePeriod().isEmpty()) { + switch (query.getTimePeriod().toLowerCase()) { + case "morning": + conditions.add("EXTRACT(HOUR FROM start_time) >= 6 AND EXTRACT(HOUR FROM start_time) < 12"); + break; + case "afternoon": + conditions.add("EXTRACT(HOUR FROM start_time) >= 12 AND EXTRACT(HOUR FROM start_time) < 18"); + break; + case "evening": + conditions.add("EXTRACT(HOUR FROM start_time) >= 18 AND EXTRACT(HOUR FROM start_time) < 24"); + break; + default: + break; + } + } + + sql.append(" AND ").append(String.join(" AND ", conditions)); + + // 5. 价格排序 / 6. 剩余名额最多排序 + boolean hasPriceSort = query.getPriceSort() != null && !query.getPriceSort().isEmpty(); + boolean hasRemainingMost = query.getRemainingMost() != null && query.getRemainingMost(); + + if (hasPriceSort || hasRemainingMost) { + sql.append(" ORDER BY"); + List orderClauses = new ArrayList<>(); + + if (hasRemainingMost) { + orderClauses.add(" (max_members - current_members) DESC"); + } + + if (hasPriceSort) { + if ("asc".equalsIgnoreCase(query.getPriceSort())) { + orderClauses.add(" stored_value_amount ASC"); + } else if ("desc".equalsIgnoreCase(query.getPriceSort())) { + orderClauses.add(" stored_value_amount DESC"); + } + } + + sql.append(String.join(",", orderClauses)); + } else { + sql.append(" ORDER BY start_time ASC"); + } + + // 分页 + int page = query.getPage() != null ? query.getPage() : 0; + int size = query.getSize() != null ? query.getSize() : 10; + if (size < 1) size = 10; + if (size > 100) size = 100; + int offset = page * size; + sql.append(" LIMIT :limit OFFSET :offset"); + + DatabaseClient.GenericExecuteSpec spec = databaseClient.sql(sql.toString()); + + if (query.getCourseName() != null && !query.getCourseName().isEmpty()) { + spec = spec.bind("courseName", "%" + query.getCourseName() + "%"); + } + if (query.getCourseType() != null) { + spec = spec.bind("courseType", query.getCourseType()); + } + if (query.getStartDate() != null) { + spec = spec.bind("startDate", query.getStartDate()); + } + if (query.getEndDate() != null) { + spec = spec.bind("endDate", query.getEndDate()); + } + spec = spec.bind("limit", size); + spec = spec.bind("offset", offset); + + return spec.map((row, meta) -> { + GroupCourseEntity entity = new GroupCourseEntity(); + entity.setId(row.get("id", Long.class)); + entity.setCourseName(row.get("course_name", String.class)); + entity.setCoachId(row.get("coach_id", Long.class)); + entity.setCourseType(row.get("course_type", Long.class)); + entity.setStartTime(row.get("start_time", LocalDateTime.class)); + entity.setEndTime(row.get("end_time", LocalDateTime.class)); + entity.setMaxMembers(row.get("max_members", Integer.class)); + entity.setCurrentMembers(row.get("current_members", Integer.class)); + String statusStr = row.get("status", String.class); + entity.setStatus(statusStr != null ? Long.parseLong(statusStr) : null); + entity.setLocation(row.get("location", String.class)); + entity.setCoverImage(row.get("cover_image", String.class)); + entity.setDescription(row.get("description", String.class)); + entity.setPointCardAmount(row.get("point_card_amount", Integer.class)); + entity.setStoredValueAmount(row.get("stored_value_amount", java.math.BigDecimal.class)); + entity.setCreateBy(row.get("create_by", String.class)); + entity.setUpdateBy(row.get("update_by", String.class)); + entity.setCreatedAt(row.get("created_at", LocalDateTime.class)); + entity.setUpdatedAt(row.get("updated_at", LocalDateTime.class)); + entity.setDeletedAt(row.get("deleted_at", LocalDateTime.class)); + return entity; + }).all(); + } + + /** + * 多条件查询团课总数 + */ + default Mono countSearchGroupCourses(DatabaseClient databaseClient, GroupCourseQueryDto query) { + StringBuilder sql = new StringBuilder("SELECT COUNT(*) FROM group_course WHERE deleted_at IS NULL"); + List conditions = new ArrayList<>(); + + conditions.add("status = '0'"); + + if (query.getCourseName() != null && !query.getCourseName().isEmpty()) { + conditions.add("course_name ILIKE :courseName"); + } + if (query.getCourseType() != null) { + conditions.add("course_type = :courseType"); + } + if (query.getStartDate() != null) { + conditions.add("start_time >= :startDate"); + } + if (query.getEndDate() != null) { + conditions.add("start_time <= :endDate"); + } + if (query.getTimePeriod() != null && !query.getTimePeriod().isEmpty()) { + switch (query.getTimePeriod().toLowerCase()) { + case "morning": + conditions.add("EXTRACT(HOUR FROM start_time) >= 6 AND EXTRACT(HOUR FROM start_time) < 12"); + break; + case "afternoon": + conditions.add("EXTRACT(HOUR FROM start_time) >= 12 AND EXTRACT(HOUR FROM start_time) < 18"); + break; + case "evening": + conditions.add("EXTRACT(HOUR FROM start_time) >= 18 AND EXTRACT(HOUR FROM start_time) < 24"); + break; + default: + break; + } + } + + sql.append(" AND ").append(String.join(" AND ", conditions)); + + DatabaseClient.GenericExecuteSpec spec = databaseClient.sql(sql.toString()); + + if (query.getCourseName() != null && !query.getCourseName().isEmpty()) { + spec = spec.bind("courseName", "%" + query.getCourseName() + "%"); + } + if (query.getCourseType() != null) { + spec = spec.bind("courseType", query.getCourseType()); + } + if (query.getStartDate() != null) { + spec = spec.bind("startDate", query.getStartDate()); + } + if (query.getEndDate() != null) { + spec = spec.bind("endDate", query.getEndDate()); + } + + return spec.map((row, meta) -> row.get(0, Long.class)).one(); + } +} \ No newline at end of file diff --git a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/dto/GroupCourseQueryDto.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/dto/GroupCourseQueryDto.java new file mode 100644 index 0000000..c38b800 --- /dev/null +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/dto/GroupCourseQueryDto.java @@ -0,0 +1,116 @@ +package cn.novalon.gym.manage.groupcourse.dto; + +import io.swagger.v3.oas.annotations.media.Schema; + +import java.time.LocalDateTime; + +/** + * 团课多条件查询请求DTO + * + * @author 张翔 + * @date 2026-06-14 + */ +@Schema(description = "团课多条件查询参数") +public class GroupCourseQueryDto { + + @Schema(description = "课程名称(模糊查询)", example = "瑜伽") + private String courseName; + + @Schema(description = "课程类型ID", example = "1") + private Long courseType; + + @Schema(description = "查询开始日期", example = "2026-06-01T00:00:00") + private LocalDateTime startDate; + + @Schema(description = "查询结束日期", example = "2026-06-30T23:59:59") + private LocalDateTime endDate; + + @Schema(description = "时间段:morning-早晨(6:00-12:00), afternoon-下午(12:00-18:00), evening-夜晚(18:00-24:00)", example = "morning") + private String timePeriod; + + @Schema(description = "价格排序:asc-从低到高, desc-从高到低", example = "asc") + private String priceSort; + + @Schema(description = "按剩余名额最多排序", example = "true") + private Boolean remainingMost; + + @Schema(description = "页码", example = "0") + private Integer page = 0; + + @Schema(description = "每页大小", example = "10") + private Integer size = 10; + + // ===== Getters and Setters ===== + + public String getCourseName() { + return courseName; + } + + public void setCourseName(String courseName) { + this.courseName = courseName; + } + + public Long getCourseType() { + return courseType; + } + + public void setCourseType(Long courseType) { + this.courseType = courseType; + } + + public LocalDateTime getStartDate() { + return startDate; + } + + public void setStartDate(LocalDateTime startDate) { + this.startDate = startDate; + } + + public LocalDateTime getEndDate() { + return endDate; + } + + public void setEndDate(LocalDateTime endDate) { + this.endDate = endDate; + } + + public String getTimePeriod() { + return timePeriod; + } + + public void setTimePeriod(String timePeriod) { + this.timePeriod = timePeriod; + } + + public String getPriceSort() { + return priceSort; + } + + public void setPriceSort(String priceSort) { + this.priceSort = priceSort; + } + + public Boolean getRemainingMost() { + return remainingMost; + } + + public void setRemainingMost(Boolean remainingMost) { + this.remainingMost = remainingMost; + } + + public Integer getPage() { + return page; + } + + public void setPage(Integer page) { + this.page = page; + } + + public Integer getSize() { + return size; + } + + public void setSize(Integer size) { + this.size = size; + } +} \ No newline at end of file diff --git a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/handler/GroupCourseHandler.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/handler/GroupCourseHandler.java index bc15e30..d0abac6 100644 --- a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/handler/GroupCourseHandler.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/handler/GroupCourseHandler.java @@ -5,6 +5,7 @@ import cn.novalon.gym.manage.common.dto.PageRequest; import cn.novalon.gym.manage.common.util.RedisUtil; import cn.novalon.gym.manage.groupcourse.domain.GroupCourse; import cn.novalon.gym.manage.groupcourse.domain.GroupCourseDetail; +import cn.novalon.gym.manage.groupcourse.dto.GroupCourseQueryDto; import cn.novalon.gym.manage.groupcourse.service.IGroupCourseService; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.oas.annotations.Operation; @@ -215,6 +216,27 @@ public class GroupCourseHandler { }); } + @Operation(summary = "多条件查询团课", description = "支持团课名称模糊查询、类型筛选、日期范围、时间段、价格排序、剩余名额排序等多条件组合查询") + public Mono searchGroupCourses(ServerRequest request) { + return request.bodyToMono(GroupCourseQueryDto.class) + .flatMap(query -> { + return groupCourseService.searchGroupCourses(query) + .flatMap(response -> { + Map result = new HashMap<>(); + result.put("success", true); + result.put("message", "查询成功"); + result.put("data", response); + return ServerResponse.ok().bodyValue(result); + }); + }) + .onErrorResume(error -> { + Map errorResponse = new HashMap<>(); + errorResponse.put("success", false); + errorResponse.put("message", error.getMessage()); + return ServerResponse.badRequest().bodyValue(errorResponse); + }); + } + @Operation(summary = "测试-根据Key获取Redis缓存", description = "测试接口:根据传入的key值获取Redis中缓存的数据") public Mono getCacheByKey(ServerRequest request) { return request.bodyToMono(Map.class) diff --git a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/IGroupCourseRepository.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/IGroupCourseRepository.java index 0a0d880..c7a3053 100644 --- a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/IGroupCourseRepository.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/IGroupCourseRepository.java @@ -4,6 +4,7 @@ package cn.novalon.gym.manage.groupcourse.repository; import cn.novalon.gym.manage.common.dto.PageRequest; import cn.novalon.gym.manage.common.dto.PageResponse; import cn.novalon.gym.manage.groupcourse.domain.GroupCourse; +import cn.novalon.gym.manage.groupcourse.dto.GroupCourseQueryDto; import org.springframework.data.domain.Sort; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -29,4 +30,6 @@ public interface IGroupCourseRepository { Mono updateCurrentMembers(Long id, Integer delta); Flux findByCourseType(Long courseType); + + Mono> searchGroupCourses(GroupCourseQueryDto query); } diff --git a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/impl/GroupCourseRepository.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/impl/GroupCourseRepository.java index eca5901..2519b5b 100644 --- a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/impl/GroupCourseRepository.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/impl/GroupCourseRepository.java @@ -6,6 +6,7 @@ import cn.novalon.gym.manage.common.dto.PageResponse; import cn.novalon.gym.manage.groupcourse.converter.GroupCourseConverter; import cn.novalon.gym.manage.groupcourse.dao.GroupCourseDao; import cn.novalon.gym.manage.groupcourse.domain.GroupCourse; +import cn.novalon.gym.manage.groupcourse.dto.GroupCourseQueryDto; import cn.novalon.gym.manage.groupcourse.entity.GroupCourseEntity; import cn.novalon.gym.manage.groupcourse.repository.IGroupCourseRepository; import org.springframework.data.domain.Sort; @@ -184,4 +185,27 @@ public class GroupCourseRepository implements IGroupCourseRepository { return groupCourseDao.findByCourseTypeAndDeletedAtIsNull(courseType) .map(groupCourseConverter::toDomain); } + + @Override + public Mono> searchGroupCourses(GroupCourseQueryDto query) { + return groupCourseDao.countSearchGroupCourses(r2dbcEntityTemplate.getDatabaseClient(), query) + .flatMap(total -> { + if (total == 0) { + return Mono.just(new PageResponse<>( + List.of(), 0, 0L, + query.getPage() != null ? query.getPage() : 0, + query.getSize() != null ? query.getSize() : 10)); + } + return groupCourseDao.searchGroupCourses(r2dbcEntityTemplate.getDatabaseClient(), query) + .map(groupCourseConverter::toDomain) + .collectList() + .map(courseList -> { + int size = query.getSize() != null ? query.getSize() : 10; + int totalPages = (int) Math.ceil((double) total / size); + return new PageResponse<>( + courseList, totalPages, total, + query.getPage() != null ? query.getPage() : 0, size); + }); + }); + } } diff --git a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/IGroupCourseService.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/IGroupCourseService.java index c312155..d50826b 100644 --- a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/IGroupCourseService.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/IGroupCourseService.java @@ -5,6 +5,7 @@ import cn.novalon.gym.manage.common.dto.PageRequest; import cn.novalon.gym.manage.common.dto.PageResponse; import cn.novalon.gym.manage.groupcourse.domain.GroupCourse; import cn.novalon.gym.manage.groupcourse.domain.GroupCourseDetail; +import cn.novalon.gym.manage.groupcourse.dto.GroupCourseQueryDto; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -25,4 +26,6 @@ public interface IGroupCourseService { Mono signIn(Long courseId, Long memberId); Mono delete(Long id); + + Mono> searchGroupCourses(GroupCourseQueryDto query); } diff --git a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/impl/GroupCourseService.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/impl/GroupCourseService.java index 3922ce6..037fe44 100644 --- a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/impl/GroupCourseService.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/impl/GroupCourseService.java @@ -9,6 +9,7 @@ import cn.novalon.gym.manage.groupcourse.domain.GroupCourse; import cn.novalon.gym.manage.groupcourse.domain.GroupCourseBooking; import cn.novalon.gym.manage.groupcourse.domain.GroupCourseDetail; import cn.novalon.gym.manage.groupcourse.domain.GroupCourseType; +import cn.novalon.gym.manage.groupcourse.dto.GroupCourseQueryDto; import cn.novalon.gym.manage.groupcourse.enums.CourseEvent; import cn.novalon.gym.manage.groupcourse.enums.CourseStatus; import cn.novalon.gym.manage.groupcourse.handler.GroupCourseStateMachine; @@ -488,6 +489,18 @@ public class GroupCourseService implements IGroupCourseService { }); } + @Override + public Mono> searchGroupCourses(GroupCourseQueryDto query) { + logger.info("多条件查询团课 - courseName={}, courseType={}, startDate={}, endDate={}, timePeriod={}, priceSort={}, remainingMost={}", + query.getCourseName(), query.getCourseType(), query.getStartDate(), query.getEndDate(), + query.getTimePeriod(), query.getPriceSort(), query.getRemainingMost()); + + return groupCourseRepository.searchGroupCourses(query) + .doOnSuccess(result -> logger.info("多条件查询结果 - total={}, page={}, size={}", + result.getTotalElements(), result.getCurrentPage(), result.getPageSize())) + .doOnError(error -> logger.error("多条件查询失败 - error: {}", error.getMessage())); + } + private Mono clearCache() { return redisUtil.deleteByPattern(CACHE_KEY_PREFIX + "*") .then(redisUtil.deleteByPattern(CACHE_KEY_ID_PREFIX + "*")) diff --git a/gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/config/SystemRouter.java b/gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/config/SystemRouter.java index 84512fa..5faa8ba 100644 --- a/gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/config/SystemRouter.java +++ b/gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/config/SystemRouter.java @@ -307,6 +307,7 @@ public class SystemRouter { .DELETE("/api/groupCourse/{id}", groupCourseHandler::deleteGroupCourse) .POST("/api/groupCourse/{id}/cancel", groupCourseHandler::cancelGroupCourse) .POST("/api/groupCourse/{courseId}/signin", groupCourseHandler::signIn) + .POST("/api/groupCourse/search", groupCourseHandler::searchGroupCourses) // ========= 签到模块路由 ========== // ===== 签到核心功能 ===== -- 2.52.0