From ffb3f2077429a7bd3dc2d16d2bb0e58ecdb32a56 Mon Sep 17 00:00:00 2001 From: liwentao Date: Thu, 30 Apr 2026 15:53:40 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=9B=A2=E8=AF=BE?= =?UTF-8?q?=E6=9F=A5=E6=89=BE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gym/manage/app/config/SystemRouter.java | 7 +- .../src/main/resources/application-dev.yml | 3 + .../src/main/resources/application.yml | 6 +- gym-manage-api/manage-db/pom.xml | 2 + .../db/converter/GroupCourseConverter.java | 55 +++++++ .../gym/manage/db/dao/GroupCourseDao.java | 23 +++ .../db/entity/GroupCourseBookingEntity.java | 75 +++++++++ .../manage/db/entity/GroupCourseEntity.java | 148 ++++++++++++++++++ .../db/repository/GroupCourseRepository.java | 57 +++++++ .../db/repository/SysUserRepository.java | 1 + .../V6__Create_GroupCourse_table.sql | 71 +++++++++ .../V7__Insert_GroupCourse_test_data.sql | 19 +++ .../gym/manage/sys/config/SecurityConfig.java | 6 +- .../manage/sys/core/domain/GroupCourse.java | 146 +++++++++++++++++ .../repository/IGroupCourseRepository.java | 14 ++ .../sys/core/service/IGroupCourseService.java | 11 ++ .../core/service/impl/GroupCourseService.java | 42 +++++ .../sys/core/service/impl/SysUserService.java | 1 + .../groupCourse/GroupCourseHandler.java | 40 +++++ gym-manage-api/pom.xml | 7 + 20 files changed, 730 insertions(+), 4 deletions(-) create mode 100644 gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/converter/GroupCourseConverter.java create mode 100644 gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/dao/GroupCourseDao.java create mode 100644 gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/entity/GroupCourseBookingEntity.java create mode 100644 gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/entity/GroupCourseEntity.java create mode 100644 gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/repository/GroupCourseRepository.java create mode 100644 gym-manage-api/manage-db/src/main/resources/db/migration/V6__Create_GroupCourse_table.sql create mode 100644 gym-manage-api/manage-db/src/main/resources/db/migration/V7__Insert_GroupCourse_test_data.sql create mode 100644 gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/domain/GroupCourse.java create mode 100644 gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/repository/IGroupCourseRepository.java create mode 100644 gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/service/IGroupCourseService.java create mode 100644 gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/service/impl/GroupCourseService.java create mode 100644 gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/handler/groupCourse/GroupCourseHandler.java 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 c869da3..98c3859 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 @@ -5,6 +5,7 @@ import cn.novalon.gym.manage.sys.handler.auth.PasswordDiagnosticHandler; import cn.novalon.gym.manage.sys.handler.config.SysConfigHandler; import cn.novalon.gym.manage.sys.handler.dictionary.DictionaryHandler; import cn.novalon.gym.manage.sys.handler.dict.SysDictHandler; +import cn.novalon.gym.manage.sys.handler.groupCourse.GroupCourseHandler; import cn.novalon.gym.manage.sys.handler.log.SysLogHandler; import cn.novalon.gym.manage.sys.handler.log.OperationLogHandler; import cn.novalon.gym.manage.sys.handler.menu.MenuHandler; @@ -51,7 +52,8 @@ public class SystemRouter { SysUserMessageHandler messageHandler, SysFileHandler fileHandler, SysPermissionHandler permissionHandler, - PasswordDiagnosticHandler passwordDiagnosticHandler) { + PasswordDiagnosticHandler passwordDiagnosticHandler, + GroupCourseHandler groupCourseHandler) { return route() // ========== 诊断路由 ========== @@ -192,6 +194,9 @@ public class SystemRouter { .POST("/api/permissions", permissionHandler::createPermission) .PUT("/api/permissions/{id}", permissionHandler::updatePermission) .DELETE("/api/permissions/{id}", permissionHandler::deletePermission) + + // ========== 团课路由 ========== + .GET("/api/groupCourse", groupCourseHandler::getAllGroupCourse) .build(); } diff --git a/gym-manage-api/manage-app/src/main/resources/application-dev.yml b/gym-manage-api/manage-app/src/main/resources/application-dev.yml index 8f5e8dc..9cfe50c 100644 --- a/gym-manage-api/manage-app/src/main/resources/application-dev.yml +++ b/gym-manage-api/manage-app/src/main/resources/application-dev.yml @@ -12,6 +12,9 @@ spring: max-life-time: 30m acquire-timeout: 3s flyway: + url: jdbc:postgresql://localhost:55432/manage_system + user: novalon + password: novalon123 enabled: true locations: classpath:db/migration baseline-on-migrate: true diff --git a/gym-manage-api/manage-app/src/main/resources/application.yml b/gym-manage-api/manage-app/src/main/resources/application.yml index 9305b16..0d7edda 100644 --- a/gym-manage-api/manage-app/src/main/resources/application.yml +++ b/gym-manage-api/manage-app/src/main/resources/application.yml @@ -25,8 +25,8 @@ spring: acquire-timeout: 5s datasource: url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:55432}/${DB_NAME:manage_system} - username: ${DB_USERNAME:postgres} - password: ${DB_PASSWORD:postgres} + username: ${DB_USERNAME:novalon} + password: ${DB_PASSWORD:novalon123} driver-class-name: org.postgresql.Driver flyway: enabled: true @@ -38,6 +38,8 @@ spring: user: name: disabled password: disabled + profiles: + active: dev management: endpoints: diff --git a/gym-manage-api/manage-db/pom.xml b/gym-manage-api/manage-db/pom.xml index 392f5e3..2c54f5b 100644 --- a/gym-manage-api/manage-db/pom.xml +++ b/gym-manage-api/manage-db/pom.xml @@ -99,6 +99,8 @@ spring-boot-starter-test test + + diff --git a/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/converter/GroupCourseConverter.java b/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/converter/GroupCourseConverter.java new file mode 100644 index 0000000..87b66ad --- /dev/null +++ b/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/converter/GroupCourseConverter.java @@ -0,0 +1,55 @@ +package cn.novalon.gym.manage.db.converter;/* + * @author:liwentao + * @date:2026/4/26-04-26-13:18 + */ + +import cn.hutool.core.bean.BeanUtil; +import cn.novalon.gym.manage.db.entity.GroupCourseEntity; +import cn.novalon.gym.manage.sys.core.domain.GroupCourse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@Slf4j +public class GroupCourseConverter { + public GroupCourse toDomain(GroupCourseEntity entity){ + if(entity == null){ + return null; + } + GroupCourse groupCourse = new GroupCourse(); + BeanUtil.copyProperties(entity,groupCourse); + log.info("转换bean,entity-domain:",groupCourse); + return groupCourse; + } + + public GroupCourseEntity toEntity(GroupCourse domain){ + if(domain == null){ + return null; + } + GroupCourseEntity entity = new GroupCourseEntity(); + BeanUtil.copyProperties(domain,entity); + log.info("转换bean,domain-entity:",entity); + return entity; + } + + public List toDomainList(List entities){ + if (entities == null) { + return null; + } + return entities.stream() + .map(this::toDomain) + .collect(Collectors.toList()); + } + + public List toEntityList(List groupCourses){ + if (groupCourses == null) { + return null; + } + return groupCourses.stream() + .map(this::toEntity) + .collect(Collectors.toList()); + } +} diff --git a/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/dao/GroupCourseDao.java b/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/dao/GroupCourseDao.java new file mode 100644 index 0000000..0855162 --- /dev/null +++ b/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/dao/GroupCourseDao.java @@ -0,0 +1,23 @@ +package cn.novalon.gym.manage.db.dao; + +import cn.novalon.gym.manage.db.entity.GroupCourseEntity; +import cn.novalon.gym.manage.db.entity.SysUserEntity; +import org.springframework.data.domain.Sort; +import org.springframework.data.r2dbc.repository.R2dbcRepository; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Repository +public interface GroupCourseDao extends R2dbcRepository { + + Mono findByIdIsAndDeletedAtIsNull(Long id); + + Flux findAll(); + + Flux findAll(Sort sort); + + Flux findAllByDeletedAtIsNull(); + + Flux findAllByDeletedAtIsNull(Sort sort); +} diff --git a/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/entity/GroupCourseBookingEntity.java b/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/entity/GroupCourseBookingEntity.java new file mode 100644 index 0000000..f414735 --- /dev/null +++ b/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/entity/GroupCourseBookingEntity.java @@ -0,0 +1,75 @@ +package cn.novalon.gym.manage.db.entity; + +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +import java.util.Date; + +/** + * @author:liwentao + * @date:2026/4/25-04-25-17:50 + * 团课预约记录表 + */ + +@Table("group_course_booking") +public class GroupCourseBookingEntity extends BaseEntity { + + //团课id + @Column("course_id") + private Long courseId; + + //用户id + @Column("user_id") + private Long userId; + + //预约时间 + @Column("booking_time") + private Date bookingTime; + + //状态:0-已预约,1-已取消,2-已出席,3-缺席 + @Column("status") + private Long status; + //取消时间 + @Column("cancel_time") + private Date cancelTime; + + public Long getCourseId() { + return courseId; + } + + public void setCourseId(Long courseId) { + this.courseId = courseId; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public Date getBookingTime() { + return bookingTime; + } + + public void setBookingTime(Date bookingTime) { + this.bookingTime = bookingTime; + } + + public Long getStatus() { + return status; + } + + public void setStatus(Long status) { + this.status = status; + } + + public Date getCancelTime() { + return cancelTime; + } + + public void setCancelTime(Date cancelTime) { + this.cancelTime = cancelTime; + } +} diff --git a/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/entity/GroupCourseEntity.java b/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/entity/GroupCourseEntity.java new file mode 100644 index 0000000..67cc612 --- /dev/null +++ b/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/entity/GroupCourseEntity.java @@ -0,0 +1,148 @@ +package cn.novalon.gym.manage.db.entity; +/** + * @author:liwentao + * @date:2026/4/25-04-25-17:34 + * 团课表 + */ + +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +import java.time.LocalDateTime; +import java.util.Date; + +@Table("group_course") +public class GroupCourseEntity extends BaseEntity { + + //课程名称 + @Column("course_name") + private String courseName; + + //教练id + @Column("coach_id") + private Long coachId; + + //课程类型 + @Column("course_type") + private Long courseType; + + //开始时间 + @Column("start_time") + private LocalDateTime startTime; + + //结束时间 + @Column("end_time") + private LocalDateTime endTime; + + //最大参与人数 + @Column("max_members") + private Integer maxMembers; + + //当前参与人数 + @Column("current_members") + private Integer currentMembers; + + //课程状态:0-正常,1-已取消,2-已结束 + @Column("status") + private Long status; + + //上课地点 + @Column("location") + private String location; + + //封面图URL + @Column("cover_image") + private String coverImage; + + //课程描述 + @Column("description") + private String description; + + public String getCourseName() { + return courseName; + } + + public void setCourseName(String courseName) { + this.courseName = courseName; + } + + public Long getCoachId() { + return coachId; + } + + public void setCoachId(Long coachId) { + this.coachId = coachId; + } + + public Long getCourseType() { + return courseType; + } + + public void setCourseType(Long courseType) { + this.courseType = courseType; + } + + public LocalDateTime getStartTime() { + return startTime; + } + + public void setStartTime(LocalDateTime startTime) { + this.startTime = startTime; + } + + public LocalDateTime getEndTime() { + return endTime; + } + + public void setEndTime(LocalDateTime endTime) { + this.endTime = endTime; + } + + public Integer getMaxMembers() { + return maxMembers; + } + + public void setMaxMembers(Integer maxMembers) { + this.maxMembers = maxMembers; + } + + public Integer getCurrentMembers() { + return currentMembers; + } + + public void setCurrentMembers(Integer currentMembers) { + this.currentMembers = currentMembers; + } + + public Long getStatus() { + return status; + } + + public void setStatus(Long status) { + this.status = status; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public String getCoverImage() { + return coverImage; + } + + public void setCoverImage(String coverImage) { + this.coverImage = coverImage; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/repository/GroupCourseRepository.java b/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/repository/GroupCourseRepository.java new file mode 100644 index 0000000..d4846b9 --- /dev/null +++ b/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/repository/GroupCourseRepository.java @@ -0,0 +1,57 @@ +package cn.novalon.gym.manage.db.repository; + +import cn.novalon.gym.manage.db.converter.GroupCourseConverter; +import cn.novalon.gym.manage.db.dao.GroupCourseDao; +import cn.novalon.gym.manage.sys.core.domain.GroupCourse; +import cn.novalon.gym.manage.sys.core.repository.IGroupCourseRepository; +import org.springframework.data.domain.Sort; +import org.springframework.data.r2dbc.core.R2dbcEntityTemplate; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** + * @author:liwentao + * @date:2026/4/26-04-26-14:16 + */ +@Repository +public class GroupCourseRepository implements IGroupCourseRepository { + private final GroupCourseDao groupCourseDao; + private final GroupCourseConverter groupCourseConverter; + private final R2dbcEntityTemplate r2dbcEntityTemplate; + + public GroupCourseRepository(GroupCourseDao groupCourseDao,GroupCourseConverter groupCourseConverter, + R2dbcEntityTemplate r2dbcEntityTemplate){ + this.groupCourseDao = groupCourseDao; + this.groupCourseConverter = groupCourseConverter; + this.r2dbcEntityTemplate = r2dbcEntityTemplate; + } + + @Override + public Mono findByIdAndDeletedAtIsNull(Long id) { + return groupCourseDao.findByIdIsAndDeletedAtIsNull(id) + .map(groupCourseConverter::toDomain); + } + + @Override + public Flux findAll() { + return groupCourseDao.findAll() + .map(groupCourseConverter::toDomain); + } + + public Flux findAll(Sort sort) { + return groupCourseDao.findAll(sort) + .map(groupCourseConverter::toDomain); + } + + @Override + public Flux findByDeletedAtIsNull() { + return groupCourseDao.findAllByDeletedAtIsNull() + .map(groupCourseConverter::toDomain); + } + + public Flux findByDeletedAtIsNull(Sort sort) { + return groupCourseDao.findAllByDeletedAtIsNull(sort) + .map(groupCourseConverter::toDomain); + } +} diff --git a/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/repository/SysUserRepository.java b/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/repository/SysUserRepository.java index c0feccc..2fb85ee 100644 --- a/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/repository/SysUserRepository.java +++ b/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/repository/SysUserRepository.java @@ -10,6 +10,7 @@ import cn.novalon.gym.manage.sys.core.query.SysUserQuery; import cn.novalon.gym.manage.sys.core.repository.ISysUserRepository; import cn.novalon.gym.manage.common.dto.PageRequest; import cn.novalon.gym.manage.common.dto.PageResponse; +import cn.novalon.gym.manage.sys.dto.response.UserResponse; import org.springframework.data.domain.Sort; import org.springframework.data.r2dbc.core.R2dbcEntityTemplate; import org.springframework.data.relational.core.query.Query; diff --git a/gym-manage-api/manage-db/src/main/resources/db/migration/V6__Create_GroupCourse_table.sql b/gym-manage-api/manage-db/src/main/resources/db/migration/V6__Create_GroupCourse_table.sql new file mode 100644 index 0000000..4b82d66 --- /dev/null +++ b/gym-manage-api/manage-db/src/main/resources/db/migration/V6__Create_GroupCourse_table.sql @@ -0,0 +1,71 @@ +-- ============================================ +-- 团课相关表 +-- ============================================ + +-- 团课课程表 +CREATE TABLE IF NOT EXISTS group_course ( + id BIGSERIAL PRIMARY KEY, + course_name VARCHAR(100) NOT NULL, + coach_id BIGINT, + course_type BIGINT, + start_time TIMESTAMP NOT NULL, + end_time TIMESTAMP NOT NULL, + max_members INTEGER DEFAULT 20, + current_members INTEGER DEFAULT 0, + status VARCHAR(1) DEFAULT '0', + location VARCHAR(255), + cover_image VARCHAR(500), + description TEXT, + create_by VARCHAR(50), + update_by VARCHAR(50), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted_at TIMESTAMP +); + +-- 团课预约记录表 +CREATE TABLE IF NOT EXISTS group_course_booking ( + id BIGSERIAL PRIMARY KEY, + course_id BIGINT NOT NULL, + user_id BIGINT NOT NULL, + booking_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + status VARCHAR(1) DEFAULT '0', + cancel_time TIMESTAMP, + create_by VARCHAR(50), + update_by VARCHAR(50), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted_at TIMESTAMP +); + +COMMENT ON TABLE group_course IS '团课课程表'; +COMMENT ON COLUMN group_course.id IS '主键ID'; +COMMENT ON COLUMN group_course.course_name IS '课程名称'; +COMMENT ON COLUMN group_course.coach_id IS '教练ID(关联sys_user)'; +COMMENT ON COLUMN group_course.course_type IS '课程类型(如瑜伽/普拉提/动感单车)'; +COMMENT ON COLUMN group_course.start_time IS '开始时间'; +COMMENT ON COLUMN group_course.end_time IS '结束时间'; +COMMENT ON COLUMN group_course.max_members IS '最大参与人数'; +COMMENT ON COLUMN group_course.current_members IS '当前参与人数'; +COMMENT ON COLUMN group_course.status IS '状态(0正常 1已取消 2已结束)'; +COMMENT ON COLUMN group_course.location IS '上课地点'; +COMMENT ON COLUMN group_course.cover_image IS '封面图URL'; +COMMENT ON COLUMN group_course.description IS '课程描述'; +COMMENT ON COLUMN group_course.create_by IS '创建人'; +COMMENT ON COLUMN group_course.update_by IS '更新人'; +COMMENT ON COLUMN group_course.created_at IS '创建时间'; +COMMENT ON COLUMN group_course.updated_at IS '更新时间'; +COMMENT ON COLUMN group_course.deleted_at IS '删除时间(软删除)'; + +COMMENT ON TABLE group_course_booking IS '团课预约记录表'; +COMMENT ON COLUMN group_course_booking.id IS '主键ID'; +COMMENT ON COLUMN group_course_booking.course_id IS '团课ID'; +COMMENT ON COLUMN group_course_booking.user_id IS '用户ID'; +COMMENT ON COLUMN group_course_booking.booking_time IS '预约时间'; +COMMENT ON COLUMN group_course_booking.status IS '状态(0已预约 1已取消 2已出席 3缺席)'; +COMMENT ON COLUMN group_course_booking.cancel_time IS '取消时间'; +COMMENT ON COLUMN group_course_booking.create_by IS '创建人'; +COMMENT ON COLUMN group_course_booking.update_by IS '更新人'; +COMMENT ON COLUMN group_course_booking.created_at IS '创建时间'; +COMMENT ON COLUMN group_course_booking.updated_at IS '更新时间'; +COMMENT ON COLUMN group_course_booking.deleted_at IS '删除时间(软删除)'; \ No newline at end of file diff --git a/gym-manage-api/manage-db/src/main/resources/db/migration/V7__Insert_GroupCourse_test_data.sql b/gym-manage-api/manage-db/src/main/resources/db/migration/V7__Insert_GroupCourse_test_data.sql new file mode 100644 index 0000000..30d85c7 --- /dev/null +++ b/gym-manage-api/manage-db/src/main/resources/db/migration/V7__Insert_GroupCourse_test_data.sql @@ -0,0 +1,19 @@ +-- 测试数据1: 进行中的瑜伽课程 (已有部分学员) +INSERT INTO group_course (course_name, coach_id, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, create_by, created_at, updated_at) VALUES + ('清晨流瑜伽', 101, 1, '2026-05-10 09:00:00', '2026-05-10 10:30:00', 15, 8, '1', 'A座3楼瑜伽教室', '/images/yoga_flow.jpg', '适合有一定基础的学员,通过流畅的体式连接呼吸,唤醒身体能量。', 'admin', '2026-05-01 10:00:00', '2026-05-01 10:00:00'); + +-- 测试数据2: 即将开始的搏击课 (几乎满员) +INSERT INTO group_course (course_name, coach_id, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, create_by, created_at, updated_at) VALUES + ('燃脂搏击', 102, 2, '2026-05-12 18:30:00', '2026-05-12 19:30:00', 20, 19, '1', '综合训练区', '/images/kickboxing.jpg', '高强度间歇训练,配合音乐快速燃脂,释放压力。', 'coach_zhang', '2026-05-02 14:30:00', '2026-05-02 14:30:00'); + +-- 测试数据3: 已结束的私教小团课 (课程号已满) +INSERT INTO group_course (course_name, coach_id, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, create_by, created_at, updated_at) VALUES + ('蜜桃臀塑造', 103, 3, '2026-04-25 19:00:00', '2026-04-25 20:00:00', 10, 10, '2', '私教专区', '/images/glute.jpg', '针对性训练臀部肌肉群,打造完美臀线。小班教学,动作一对一纠正。', 'coach_li', '2026-04-20 09:15:00', '2026-04-20 09:15:00'); + +-- 测试数据4: 即将开始的动感单车 (名额充足,尚未有人报名) +INSERT INTO group_course (course_name, coach_id, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, create_by, created_at, updated_at) VALUES + ('极速燃脂单车', 104, 2, '2026-05-15 19:30:00', '2026-05-15 20:20:00', 25, 0, '0', '单车房', '/images/spinning.jpg', '跟随音乐节奏变换阻力和速度,体验爬坡与冲刺的快感,一节课消耗800大卡。', 'admin', '2026-05-06 11:00:00', '2026-05-06 11:00:00'); + +-- 测试数据5: 已删除/作废的课程 (deleted_at 不为空) +INSERT INTO group_course (course_name, coach_id, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, create_by, created_at, updated_at, deleted_at) VALUES + ('周末冥想修复', 101, 1, '2026-05-03 15:00:00', '2026-05-03 16:00:00', 12, 3, '3', '冥想室', '/images/meditation.jpg', '通过呼吸和正念冥想,深度放松身心,缓解一周疲劳。', 'coach_wang', '2026-04-28 08:00:00', '2026-04-28 08:00:00', '2026-04-29 16:20:00'); \ No newline at end of file diff --git a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java index 4df2a4b..b68cf04 100644 --- a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java +++ b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java @@ -50,7 +50,11 @@ public class SecurityConfig { spec.pathMatchers("/api/auth/**").permitAll() .pathMatchers("/api/public/**").permitAll() .pathMatchers("/ws/**").permitAll() - .pathMatchers("/actuator/**").permitAll(); + .pathMatchers("/actuator/**").permitAll() + //========TODO lwt 以下是测试接口,生产时必关======== + .pathMatchers("/api/users/**").permitAll() + .pathMatchers("/api/groupCourse/**").permitAll(); + if (isDevOrTest) { spec.pathMatchers("/swagger-ui.html").permitAll() diff --git a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/domain/GroupCourse.java b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/domain/GroupCourse.java new file mode 100644 index 0000000..11b9949 --- /dev/null +++ b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/domain/GroupCourse.java @@ -0,0 +1,146 @@ +package cn.novalon.gym.manage.sys.core.domain; +/** + * @author:liwentao + * @date:2026/4/26-04-26-13:20 + */ + +import io.swagger.v3.oas.annotations.media.Schema; +import org.springframework.data.relational.core.mapping.Column; + +import java.time.LocalDateTime; +import java.util.Date; +@Schema(description = "") +public class GroupCourse extends BaseDomain{ + + //课程名称 + @Schema(description = "团课名", example = "Push-up") + private String courseName; + + //教练id + @Schema(description = "教练id", example = "1") + private Long coachId; + + //课程类型 + @Schema(description = "课程类型", example = "1") + private Long courseType; + + //开始时间 + @Schema(description = "开始时间", example = "2026-01-01") + private LocalDateTime startTime; + + //结束时间 + @Schema(description = "结束时间", example = "2026-01-02") + private LocalDateTime endTime; + + //最大参与人数 + @Schema(description = "最大参与人数", example = "20") + private Integer maxMembers; + + //当前参与人数 + @Schema(description = "当前参与人数", example = "2") + private Integer currentMembers; + + //课程状态:0-正常,1-已取消,2-已结束 + @Schema(description = "课程状态", example = "0") + private Long status; + + //上课地点 + @Schema(description = "上课地点", example = "龙泉驿区幸福路") + private String location; + + //封面图URL + @Schema(description = "封面图URL", example = "https://12345.com") + private String coverImage; + + //课程描述 + @Schema(description = "课程描述", example = "从入门到入土") + private String description; + + public String getCourseName() { + return courseName; + } + + public void setCourseName(String courseName) { + this.courseName = courseName; + } + + public Long getCoachId() { + return coachId; + } + + public void setCoachId(Long coachId) { + this.coachId = coachId; + } + + public Long getCourseType() { + return courseType; + } + + public void setCourseType(Long courseType) { + this.courseType = courseType; + } + + public LocalDateTime getStartTime() { + return startTime; + } + + public void setStartTime(LocalDateTime startTime) { + this.startTime = startTime; + } + + public LocalDateTime getEndTime() { + return endTime; + } + + public void setEndTime(LocalDateTime endTime) { + this.endTime = endTime; + } + + public Integer getMaxMembers() { + return maxMembers; + } + + public void setMaxMembers(Integer maxMembers) { + this.maxMembers = maxMembers; + } + + public Integer getCurrentMembers() { + return currentMembers; + } + + public void setCurrentMembers(Integer currentMembers) { + this.currentMembers = currentMembers; + } + + public Long getStatus() { + return status; + } + + public void setStatus(Long status) { + this.status = status; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public String getCoverImage() { + return coverImage; + } + + public void setCoverImage(String coverImage) { + this.coverImage = coverImage; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/repository/IGroupCourseRepository.java b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/repository/IGroupCourseRepository.java new file mode 100644 index 0000000..2d020d4 --- /dev/null +++ b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/repository/IGroupCourseRepository.java @@ -0,0 +1,14 @@ +package cn.novalon.gym.manage.sys.core.repository; + +import cn.novalon.gym.manage.sys.core.domain.GroupCourse; +import org.springframework.data.domain.Sort; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface IGroupCourseRepository { + Mono findByIdAndDeletedAtIsNull(Long id); + Flux findAll(); + Flux findAll(Sort sort); + Flux findByDeletedAtIsNull(); + Flux findByDeletedAtIsNull(Sort sort); +} diff --git a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/service/IGroupCourseService.java b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/service/IGroupCourseService.java new file mode 100644 index 0000000..28efd2e --- /dev/null +++ b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/service/IGroupCourseService.java @@ -0,0 +1,11 @@ +package cn.novalon.gym.manage.sys.core.service; + +import cn.novalon.gym.manage.sys.core.domain.GroupCourse; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface IGroupCourseService { + Mono findById(Long id); + Flux findAll(); + Flux findAll(boolean includeDeleted); +} diff --git a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/service/impl/GroupCourseService.java b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/service/impl/GroupCourseService.java new file mode 100644 index 0000000..2b1fcbf --- /dev/null +++ b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/service/impl/GroupCourseService.java @@ -0,0 +1,42 @@ +package cn.novalon.gym.manage.sys.core.service.impl; + +import cn.novalon.gym.manage.sys.audit.service.IAuditLogService; +import cn.novalon.gym.manage.sys.core.domain.GroupCourse; +import cn.novalon.gym.manage.sys.core.repository.IGroupCourseRepository; +import cn.novalon.gym.manage.sys.core.service.IGroupCourseService; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** + * @author:liwentao + * @date:2026/4/26-04-26-14:12 + */ +@Service +public class GroupCourseService implements IGroupCourseService { + private final IGroupCourseRepository groupCourseRepository; + private final IAuditLogService auditLogService; + public GroupCourseService(IGroupCourseRepository groupCourseRepository, IAuditLogService auditLogService){ + this.groupCourseRepository = groupCourseRepository; + this.auditLogService = auditLogService; + } + + @Override + public Mono findById(Long id) { + return groupCourseRepository.findByIdAndDeletedAtIsNull(id); + } + + @Override + public Flux findAll() { + return groupCourseRepository.findAll(); + } + + @Override + public Flux findAll(boolean includeDeleted) { + if(includeDeleted){ + return groupCourseRepository.findAll(); + }else{ + return groupCourseRepository.findByDeletedAtIsNull(); + } + } +} diff --git a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/service/impl/SysUserService.java b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/service/impl/SysUserService.java index 3d7bf64..ee1da91 100644 --- a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/service/impl/SysUserService.java +++ b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/service/impl/SysUserService.java @@ -15,6 +15,7 @@ import cn.novalon.gym.manage.sys.core.repository.IUserRoleRepository; import cn.novalon.gym.manage.sys.core.service.ISysUserService; import cn.novalon.gym.manage.sys.core.command.CreateUserCommand; import cn.novalon.gym.manage.sys.core.command.UpdateUserCommand; +import cn.novalon.gym.manage.sys.dto.response.UserResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Qualifier; diff --git a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/handler/groupCourse/GroupCourseHandler.java b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/handler/groupCourse/GroupCourseHandler.java new file mode 100644 index 0000000..b439351 --- /dev/null +++ b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/handler/groupCourse/GroupCourseHandler.java @@ -0,0 +1,40 @@ +package cn.novalon.gym.manage.sys.handler.groupCourse; + +import cn.novalon.gym.manage.sys.core.domain.GroupCourse; +import cn.novalon.gym.manage.sys.core.service.IGroupCourseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Validator; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.reactive.function.server.ServerResponse; +import reactor.core.publisher.Mono; + +/** + * @author:liwentao + * @date:2026/4/26-04-26-14:30 + */ +@Component +@Tag(name="团课管理",description = "团课相关操作") +public class GroupCourseHandler { + private final IGroupCourseService groupCourseService; + private final Validator validator; + public GroupCourseHandler(IGroupCourseService groupCourseService,Validator validator){ + this.groupCourseService = groupCourseService; + this.validator = validator; + } + + @Operation(summary = "获取所有用户", description = "获取系统中所有用户列表") + public Mono getAllGroupCourse(ServerRequest request){ + boolean includeDeleted = Boolean.valueOf(request.queryParam("includeDeleted").orElse("false")); + return ServerResponse.ok() + .body(groupCourseService.findAll(includeDeleted), GroupCourse.class); + } + + public Mono getGroupCourseById(ServerRequest request){ + Long id = Long.valueOf(request.pathVariable("id")); + return groupCourseService.findById(id) + .flatMap(groupCourse -> ServerResponse.ok().bodyValue(groupCourse)) + .switchIfEmpty(ServerResponse.notFound().build()); + } +} diff --git a/gym-manage-api/pom.xml b/gym-manage-api/pom.xml index df2e4c2..aec5848 100644 --- a/gym-manage-api/pom.xml +++ b/gym-manage-api/pom.xml @@ -221,6 +221,13 @@ lombok true + + + + cn.hutool + hutool-all + 5.8.38 + From 68fefae774d0683333879fd3493f31c5180b4b7e Mon Sep 17 00:00:00 2001 From: liwentao Date: Sun, 10 May 2026 18:26:33 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E5=B0=86=E5=9B=A2=E8=AF=BE=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E4=BB=A3=E7=A0=81=E8=BF=81=E7=A7=BB=E8=87=B3gym-Group?= =?UTF-8?q?Course=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.mvn/wrapper/maven-wrapper.properties | 3 + gym-manage-api/gym-groupCourse/pom.xml | 81 +++++++++++++++++++ .../converter/GroupCourseConverter.java | 16 ++-- .../groupcourse}/dao/GroupCourseDao.java | 8 +- .../groupcourse}/domain/GroupCourse.java | 12 +-- .../entity/GroupCourseEntity.java | 10 +-- .../handler}/GroupCourseHandler.java | 22 +++-- .../repository/IGroupCourseRepository.java | 5 +- .../impl}/GroupCourseRepository.java | 19 +++-- .../service/IGroupCourseService.java | 5 +- .../service/impl/GroupCourseService.java | 19 ++--- .../src/main/resources/application.yaml | 3 + .../GymGroupCourseApplicationTests.java | 13 +++ gym-manage-api/manage-app/pom.xml | 11 +++ .../gym/manage/app/ManageApplication.java | 4 +- .../gym/manage/app/config/SystemRouter.java | 43 +++++----- .../db/entity/GroupCourseBookingEntity.java | 75 ----------------- gym-manage-api/pom.xml | 1 + 18 files changed, 186 insertions(+), 164 deletions(-) create mode 100644 gym-manage-api/gym-groupCourse/.mvn/wrapper/maven-wrapper.properties create mode 100644 gym-manage-api/gym-groupCourse/pom.xml rename gym-manage-api/{manage-db/src/main/java/cn/novalon/gym/manage/db => gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse}/converter/GroupCourseConverter.java (81%) rename gym-manage-api/{manage-db/src/main/java/cn/novalon/gym/manage/db => gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse}/dao/GroupCourseDao.java (69%) rename gym-manage-api/{manage-sys/src/main/java/cn/novalon/gym/manage/sys/core => gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse}/domain/GroupCourse.java (93%) rename gym-manage-api/{manage-db/src/main/java/cn/novalon/gym/manage/db => gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse}/entity/GroupCourseEntity.java (95%) rename gym-manage-api/{manage-sys/src/main/java/cn/novalon/gym/manage/sys/handler/groupCourse => gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/handler}/GroupCourseHandler.java (67%) rename gym-manage-api/{manage-sys/src/main/java/cn/novalon/gym/manage/sys/core => gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse}/repository/IGroupCourseRepository.java (77%) rename gym-manage-api/{manage-db/src/main/java/cn/novalon/gym/manage/db/repository => gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/impl}/GroupCourseRepository.java (77%) rename gym-manage-api/{manage-sys/src/main/java/cn/novalon/gym/manage/sys/core => gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse}/service/IGroupCourseService.java (68%) rename gym-manage-api/{manage-sys/src/main/java/cn/novalon/gym/manage/sys/core => gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse}/service/impl/GroupCourseService.java (63%) create mode 100644 gym-manage-api/gym-groupCourse/src/main/resources/application.yaml create mode 100644 gym-manage-api/gym-groupCourse/src/test/java/cn/novalon/gym/manage/groupcourse/GymGroupCourseApplicationTests.java delete mode 100644 gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/entity/GroupCourseBookingEntity.java diff --git a/gym-manage-api/gym-groupCourse/.mvn/wrapper/maven-wrapper.properties b/gym-manage-api/gym-groupCourse/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..5291372 --- /dev/null +++ b/gym-manage-api/gym-groupCourse/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,3 @@ +wrapperVersion=3.3.4 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.15/apache-maven-3.9.15-bin.zip diff --git a/gym-manage-api/gym-groupCourse/pom.xml b/gym-manage-api/gym-groupCourse/pom.xml new file mode 100644 index 0000000..3fc53bb --- /dev/null +++ b/gym-manage-api/gym-groupCourse/pom.xml @@ -0,0 +1,81 @@ + + + 4.0.0 + + cn.novalon.gym.manage + gym-manage-api + 1.0.0 + ../pom.xml + + cn.novalon.gym.manage + gym-groupCourse + 1.0.0 + gym-groupCourse + Group Course Management Module + + + + + + + + + + + + + + + 21 + + + + cn.novalon.gym.manage + manage-common + ${project.version} + + + cn.novalon.gym.manage + manage-db + ${project.version} + + + org.springframework.boot + spring-boot-starter-webflux + + + org.springframework.boot + spring-boot-starter-data-r2dbc + + + org.springframework.boot + spring-boot-starter-validation + + + org.springdoc + springdoc-openapi-starter-webflux-ui + + + org.springframework.boot + spring-boot-starter-test + test + + + io.swagger.core.v3 + swagger-annotations-jakarta + 2.2.43 + compile + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/converter/GroupCourseConverter.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/converter/GroupCourseConverter.java similarity index 81% rename from gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/converter/GroupCourseConverter.java rename to gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/converter/GroupCourseConverter.java index 87b66ad..34e66c4 100644 --- a/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/converter/GroupCourseConverter.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/converter/GroupCourseConverter.java @@ -1,11 +1,9 @@ -package cn.novalon.gym.manage.db.converter;/* - * @author:liwentao - * @date:2026/4/26-04-26-13:18 - */ + +package cn.novalon.gym.manage.groupcourse.converter; import cn.hutool.core.bean.BeanUtil; -import cn.novalon.gym.manage.db.entity.GroupCourseEntity; -import cn.novalon.gym.manage.sys.core.domain.GroupCourse; +import cn.novalon.gym.manage.groupcourse.domain.GroupCourse; +import cn.novalon.gym.manage.groupcourse.entity.GroupCourseEntity; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -44,11 +42,11 @@ public class GroupCourseConverter { .collect(Collectors.toList()); } - public List toEntityList(List groupCourses){ - if (groupCourses == null) { + public List toEntityList(List domains){ + if (domains == null) { return null; } - return groupCourses.stream() + return domains.stream() .map(this::toEntity) .collect(Collectors.toList()); } diff --git a/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/dao/GroupCourseDao.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/dao/GroupCourseDao.java similarity index 69% rename from gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/dao/GroupCourseDao.java rename to gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/dao/GroupCourseDao.java index 0855162..688e2a6 100644 --- a/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/dao/GroupCourseDao.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/dao/GroupCourseDao.java @@ -1,7 +1,7 @@ -package cn.novalon.gym.manage.db.dao; -import cn.novalon.gym.manage.db.entity.GroupCourseEntity; -import cn.novalon.gym.manage.db.entity.SysUserEntity; +package cn.novalon.gym.manage.groupcourse.dao; + +import cn.novalon.gym.manage.groupcourse.entity.GroupCourseEntity; import org.springframework.data.domain.Sort; import org.springframework.data.r2dbc.repository.R2dbcRepository; import org.springframework.stereotype.Repository; @@ -9,7 +9,7 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @Repository -public interface GroupCourseDao extends R2dbcRepository { +public interface GroupCourseDao extends R2dbcRepository { Mono findByIdIsAndDeletedAtIsNull(Long id); diff --git a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/domain/GroupCourse.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/domain/GroupCourse.java similarity index 93% rename from gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/domain/GroupCourse.java rename to gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/domain/GroupCourse.java index 11b9949..ca40da8 100644 --- a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/domain/GroupCourse.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/domain/GroupCourse.java @@ -1,15 +1,11 @@ -package cn.novalon.gym.manage.sys.core.domain; -/** - * @author:liwentao - * @date:2026/4/26-04-26-13:20 - */ +package cn.novalon.gym.manage.groupcourse.domain; + +import cn.novalon.gym.manage.sys.core.domain.BaseDomain; import io.swagger.v3.oas.annotations.media.Schema; -import org.springframework.data.relational.core.mapping.Column; import java.time.LocalDateTime; -import java.util.Date; -@Schema(description = "") + public class GroupCourse extends BaseDomain{ //课程名称 diff --git a/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/entity/GroupCourseEntity.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/entity/GroupCourseEntity.java similarity index 95% rename from gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/entity/GroupCourseEntity.java rename to gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/entity/GroupCourseEntity.java index 67cc612..9ab5328 100644 --- a/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/entity/GroupCourseEntity.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/entity/GroupCourseEntity.java @@ -1,15 +1,11 @@ -package cn.novalon.gym.manage.db.entity; -/** - * @author:liwentao - * @date:2026/4/25-04-25-17:34 - * 团课表 - */ +package cn.novalon.gym.manage.groupcourse.entity; + +import cn.novalon.gym.manage.db.entity.BaseEntity; import org.springframework.data.relational.core.mapping.Column; import org.springframework.data.relational.core.mapping.Table; import java.time.LocalDateTime; -import java.util.Date; @Table("group_course") public class GroupCourseEntity extends BaseEntity { diff --git a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/handler/groupCourse/GroupCourseHandler.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/handler/GroupCourseHandler.java similarity index 67% rename from gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/handler/groupCourse/GroupCourseHandler.java rename to gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/handler/GroupCourseHandler.java index b439351..920786f 100644 --- a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/handler/groupCourse/GroupCourseHandler.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/handler/GroupCourseHandler.java @@ -1,7 +1,8 @@ -package cn.novalon.gym.manage.sys.handler.groupCourse; -import cn.novalon.gym.manage.sys.core.domain.GroupCourse; -import cn.novalon.gym.manage.sys.core.service.IGroupCourseService; +package cn.novalon.gym.manage.groupcourse.handler; + +import cn.novalon.gym.manage.groupcourse.domain.GroupCourse; +import cn.novalon.gym.manage.groupcourse.service.IGroupCourseService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Validator; @@ -10,31 +11,28 @@ import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; import reactor.core.publisher.Mono; -/** - * @author:liwentao - * @date:2026/4/26-04-26-14:30 - */ @Component @Tag(name="团课管理",description = "团课相关操作") public class GroupCourseHandler { private final IGroupCourseService groupCourseService; private final Validator validator; - public GroupCourseHandler(IGroupCourseService groupCourseService,Validator validator){ + + public GroupCourseHandler(IGroupCourseService groupCourseService, Validator validator){ this.groupCourseService = groupCourseService; this.validator = validator; } - @Operation(summary = "获取所有用户", description = "获取系统中所有用户列表") + @Operation(summary = "获取所有团课", description = "获取系统中所有团课列表") public Mono getAllGroupCourse(ServerRequest request){ boolean includeDeleted = Boolean.valueOf(request.queryParam("includeDeleted").orElse("false")); return ServerResponse.ok() .body(groupCourseService.findAll(includeDeleted), GroupCourse.class); } + @Operation(summary = "根据ID获取团课", description = "根据ID获取团课详情") public Mono getGroupCourseById(ServerRequest request){ Long id = Long.valueOf(request.pathVariable("id")); - return groupCourseService.findById(id) - .flatMap(groupCourse -> ServerResponse.ok().bodyValue(groupCourse)) - .switchIfEmpty(ServerResponse.notFound().build()); + return ServerResponse.ok() + .body(groupCourseService.findById(id), GroupCourse.class); } } diff --git a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/repository/IGroupCourseRepository.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/IGroupCourseRepository.java similarity index 77% rename from gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/repository/IGroupCourseRepository.java rename to gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/IGroupCourseRepository.java index 2d020d4..4ade673 100644 --- a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/repository/IGroupCourseRepository.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/IGroupCourseRepository.java @@ -1,6 +1,7 @@ -package cn.novalon.gym.manage.sys.core.repository; -import cn.novalon.gym.manage.sys.core.domain.GroupCourse; +package cn.novalon.gym.manage.groupcourse.repository; + +import cn.novalon.gym.manage.groupcourse.domain.GroupCourse; import org.springframework.data.domain.Sort; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; diff --git a/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/repository/GroupCourseRepository.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/impl/GroupCourseRepository.java similarity index 77% rename from gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/repository/GroupCourseRepository.java rename to gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/impl/GroupCourseRepository.java index d4846b9..5c11325 100644 --- a/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/repository/GroupCourseRepository.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/repository/impl/GroupCourseRepository.java @@ -1,26 +1,23 @@ -package cn.novalon.gym.manage.db.repository; -import cn.novalon.gym.manage.db.converter.GroupCourseConverter; -import cn.novalon.gym.manage.db.dao.GroupCourseDao; -import cn.novalon.gym.manage.sys.core.domain.GroupCourse; -import cn.novalon.gym.manage.sys.core.repository.IGroupCourseRepository; +package cn.novalon.gym.manage.groupcourse.repository.impl; + +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.repository.IGroupCourseRepository; import org.springframework.data.domain.Sort; import org.springframework.data.r2dbc.core.R2dbcEntityTemplate; import org.springframework.stereotype.Repository; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -/** - * @author:liwentao - * @date:2026/4/26-04-26-14:16 - */ @Repository public class GroupCourseRepository implements IGroupCourseRepository { private final GroupCourseDao groupCourseDao; private final GroupCourseConverter groupCourseConverter; private final R2dbcEntityTemplate r2dbcEntityTemplate; - public GroupCourseRepository(GroupCourseDao groupCourseDao,GroupCourseConverter groupCourseConverter, + public GroupCourseRepository(GroupCourseDao groupCourseDao, GroupCourseConverter groupCourseConverter, R2dbcEntityTemplate r2dbcEntityTemplate){ this.groupCourseDao = groupCourseDao; this.groupCourseConverter = groupCourseConverter; @@ -39,6 +36,7 @@ public class GroupCourseRepository implements IGroupCourseRepository { .map(groupCourseConverter::toDomain); } + @Override public Flux findAll(Sort sort) { return groupCourseDao.findAll(sort) .map(groupCourseConverter::toDomain); @@ -50,6 +48,7 @@ public class GroupCourseRepository implements IGroupCourseRepository { .map(groupCourseConverter::toDomain); } + @Override public Flux findByDeletedAtIsNull(Sort sort) { return groupCourseDao.findAllByDeletedAtIsNull(sort) .map(groupCourseConverter::toDomain); diff --git a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/service/IGroupCourseService.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/IGroupCourseService.java similarity index 68% rename from gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/service/IGroupCourseService.java rename to gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/IGroupCourseService.java index 28efd2e..d43b396 100644 --- a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/service/IGroupCourseService.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/IGroupCourseService.java @@ -1,6 +1,7 @@ -package cn.novalon.gym.manage.sys.core.service; -import cn.novalon.gym.manage.sys.core.domain.GroupCourse; +package cn.novalon.gym.manage.groupcourse.service; + +import cn.novalon.gym.manage.groupcourse.domain.GroupCourse; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; diff --git a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/service/impl/GroupCourseService.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/impl/GroupCourseService.java similarity index 63% rename from gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/service/impl/GroupCourseService.java rename to gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/impl/GroupCourseService.java index 2b1fcbf..6e409e3 100644 --- a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/core/service/impl/GroupCourseService.java +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/impl/GroupCourseService.java @@ -1,24 +1,19 @@ -package cn.novalon.gym.manage.sys.core.service.impl; -import cn.novalon.gym.manage.sys.audit.service.IAuditLogService; -import cn.novalon.gym.manage.sys.core.domain.GroupCourse; -import cn.novalon.gym.manage.sys.core.repository.IGroupCourseRepository; -import cn.novalon.gym.manage.sys.core.service.IGroupCourseService; +package cn.novalon.gym.manage.groupcourse.service.impl; + +import cn.novalon.gym.manage.groupcourse.domain.GroupCourse; +import cn.novalon.gym.manage.groupcourse.repository.IGroupCourseRepository; +import cn.novalon.gym.manage.groupcourse.service.IGroupCourseService; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -/** - * @author:liwentao - * @date:2026/4/26-04-26-14:12 - */ @Service public class GroupCourseService implements IGroupCourseService { private final IGroupCourseRepository groupCourseRepository; - private final IAuditLogService auditLogService; - public GroupCourseService(IGroupCourseRepository groupCourseRepository, IAuditLogService auditLogService){ + + public GroupCourseService(IGroupCourseRepository groupCourseRepository){ this.groupCourseRepository = groupCourseRepository; - this.auditLogService = auditLogService; } @Override diff --git a/gym-manage-api/gym-groupCourse/src/main/resources/application.yaml b/gym-manage-api/gym-groupCourse/src/main/resources/application.yaml new file mode 100644 index 0000000..2d60330 --- /dev/null +++ b/gym-manage-api/gym-groupCourse/src/main/resources/application.yaml @@ -0,0 +1,3 @@ +spring: + application: + name: gym-groupCourse diff --git a/gym-manage-api/gym-groupCourse/src/test/java/cn/novalon/gym/manage/groupcourse/GymGroupCourseApplicationTests.java b/gym-manage-api/gym-groupCourse/src/test/java/cn/novalon/gym/manage/groupcourse/GymGroupCourseApplicationTests.java new file mode 100644 index 0000000..b0d48f8 --- /dev/null +++ b/gym-manage-api/gym-groupCourse/src/test/java/cn/novalon/gym/manage/groupcourse/GymGroupCourseApplicationTests.java @@ -0,0 +1,13 @@ +package cn.novalon.gym.manage.groupcourse; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class GymGroupCourseApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/gym-manage-api/manage-app/pom.xml b/gym-manage-api/manage-app/pom.xml index 45fcc60..0d33560 100644 --- a/gym-manage-api/manage-app/pom.xml +++ b/gym-manage-api/manage-app/pom.xml @@ -18,6 +18,11 @@ Application module for Novalon Manage API + + cn.novalon.gym.manage + gym-groupCourse + ${project.version} + cn.novalon.gym.manage manage-sys @@ -133,6 +138,12 @@ org.springdoc springdoc-openapi-starter-webflux-ui + + cn.novalon.gym.manage + gym-groupCourse + 1.0.0 + compile + diff --git a/gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/ManageApplication.java b/gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/ManageApplication.java index f74c2f7..aa3c01f 100644 --- a/gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/ManageApplication.java +++ b/gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/ManageApplication.java @@ -15,10 +15,10 @@ import org.springframework.web.server.WebFilter; import java.util.List; -@SpringBootApplication(scanBasePackages = "cn.novalon.gym.manage", exclude = { +@SpringBootApplication(scanBasePackages = {"cn.novalon.gym.manage", "cn.novalon.gym.manage.groupcourse"}, exclude = { ReactiveUserDetailsServiceAutoConfiguration.class }) @EnableR2dbcRepositories(basePackages = { "cn.novalon.gym.manage.db.dao", - "cn.novalon.gym.manage.sys.audit.repository" }) + "cn.novalon.gym.manage.sys.audit.repository", "cn.novalon.gym.manage.groupcourse.dao" }) public class ManageApplication { private static final Logger logger = LoggerFactory.getLogger(ManageApplication.class); 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 98c3859..185540b 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 @@ -1,11 +1,12 @@ package cn.novalon.gym.manage.app.config; +import cn.novalon.gym.manage.groupcourse.handler.GroupCourseHandler; import cn.novalon.gym.manage.sys.handler.auth.SysAuthHandler; import cn.novalon.gym.manage.sys.handler.auth.PasswordDiagnosticHandler; import cn.novalon.gym.manage.sys.handler.config.SysConfigHandler; import cn.novalon.gym.manage.sys.handler.dictionary.DictionaryHandler; import cn.novalon.gym.manage.sys.handler.dict.SysDictHandler; -import cn.novalon.gym.manage.sys.handler.groupCourse.GroupCourseHandler; + import cn.novalon.gym.manage.sys.handler.log.SysLogHandler; import cn.novalon.gym.manage.sys.handler.log.OperationLogHandler; import cn.novalon.gym.manage.sys.handler.menu.MenuHandler; @@ -25,19 +26,19 @@ import static org.springframework.web.reactive.function.server.RouterFunctions.r /** * 系统路由配置类 - * + * * 文件定义:配置WebFlux函数式路由,将HTTP请求映射到对应的Handler方法 * 涉及业务:用户、角色、字典、菜单、公告、文件等所有RESTful API路由 * 算法:使用RouterFunctions.route()构建函数式路由规则 - * + * * @author 张翔 * @date 2026-03-13 */ @Configuration public class SystemRouter { - @Bean public RouterFunction systemRoutes( + GroupCourseHandler groupCourseHandler, DictionaryHandler dictionaryHandler, SysUserHandler userHandler, MenuHandler menuHandler, @@ -52,13 +53,12 @@ public class SystemRouter { SysUserMessageHandler messageHandler, SysFileHandler fileHandler, SysPermissionHandler permissionHandler, - PasswordDiagnosticHandler passwordDiagnosticHandler, - GroupCourseHandler groupCourseHandler) { - + PasswordDiagnosticHandler passwordDiagnosticHandler) { + return route() // ========== 诊断路由 ========== .GET("/api/diagnostic/password", passwordDiagnosticHandler::diagnose) - + // ========== 字典路由 ========== .GET("/api/dictionaries", dictionaryHandler::getAllDictionaries) .GET("/api/dictionaries/{id}", dictionaryHandler::getDictionaryById) @@ -67,7 +67,7 @@ public class SystemRouter { .POST("/api/dictionaries", dictionaryHandler::createDictionary) .PUT("/api/dictionaries/{id}", dictionaryHandler::updateDictionary) .DELETE("/api/dictionaries/{id}", dictionaryHandler::deleteDictionary) - + // ========== 用户路由 ========== .GET("/api/users", userHandler::getAllUsers) .GET("/api/users/page", userHandler::getUsersByPage) @@ -86,7 +86,7 @@ public class SystemRouter { .POST("/api/users/{id}/action/restore", userHandler::restoreUser) .GET("/api/users/{id}/roles", userHandler::getUserRoles) .POST("/api/users/{id}/roles", userHandler::assignRoles) - + // ========== 菜单路由 ========== .GET("/api/menus", menuHandler::getAllMenus) .GET("/api/menus/tree", menuHandler::getMenuTree) @@ -94,7 +94,7 @@ public class SystemRouter { .POST("/api/menus", menuHandler::createMenu) .PUT("/api/menus/{id}", menuHandler::updateMenu) .DELETE("/api/menus/{id}", menuHandler::deleteMenu) - + // ========== 角色路由 ========== .GET("/api/roles", roleHandler::getAllRoles) .GET("/api/roles/page", roleHandler::getRolesByPage) @@ -108,7 +108,7 @@ public class SystemRouter { .POST("/api/roles/{id}/restore", roleHandler::restoreRole) .GET("/api/roles/{id}/permissions", permissionHandler::getPermissionsByRoleId) .POST("/api/roles/{id}/permissions", permissionHandler::assignPermissionsToRole) - + // ========== 配置路由 ========== .GET("/api/config", configHandler::getAllConfigs) .GET("/api/config/{id}", configHandler::getConfigById) @@ -116,7 +116,7 @@ public class SystemRouter { .POST("/api/config", configHandler::createConfig) .PUT("/api/config/{id}", configHandler::updateConfig) .DELETE("/api/config/{id}", configHandler::deleteConfig) - + // ========== 日志路由 ========== .GET("/api/logs/login", logHandler::getAllLoginLogs) .GET("/api/logs/login/page", logHandler::getLoginLogsByPage) @@ -136,15 +136,15 @@ public class SystemRouter { .GET("/api/logs/operation/count", operationLogHandler::getOperationLogCount) .GET("/api/logs/operation/{id}", operationLogHandler::getOperationLogById) .POST("/api/logs/operation", operationLogHandler::createOperationLog) - + // ========== 认证路由 ========== .POST("/api/auth/login", authHandler::login) .POST("/api/auth/register", authHandler::register) .POST("/api/auth/logout", authHandler::logout) - + // ========== 统计路由 ========== .GET("/api/stats/overview", statsHandler::getOverview) - + // ========== 数据字典路由 ========== .GET("/api/dict/types", dictHandler::getAllDictTypes) .GET("/api/dict/types/{id}", dictHandler::getDictTypeById) @@ -158,7 +158,7 @@ public class SystemRouter { .POST("/api/dict/data", dictHandler::createDictData) .PUT("/api/dict/data/{id}", dictHandler::updateDictData) .DELETE("/api/dict/data/{id}", dictHandler::deleteDictData) - + // ========== 公告路由 ========== .GET("/api/notices", noticeHandler::getAllNotices) .GET("/api/notices/{id}", noticeHandler::getNoticeById) @@ -166,7 +166,7 @@ public class SystemRouter { .POST("/api/notices", noticeHandler::createNotice) .PUT("/api/notices/{id}", noticeHandler::updateNotice) .DELETE("/api/notices/{id}", noticeHandler::deleteNotice) - + // ========== 消息路由 ========== .GET("/api/messages/user/{userId}", messageHandler::getMessagesByUser) .GET("/api/messages/user/{userId}/unread", messageHandler::getUnreadCount) @@ -174,7 +174,7 @@ public class SystemRouter { .POST("/api/messages", messageHandler::createMessage) .PUT("/api/messages/{id}/read", messageHandler::markAsRead) .DELETE("/api/messages/{id}", messageHandler::deleteMessage) - + // ========== 文件路由 ========== .GET("/api/files", fileHandler::getAllFiles) .GET("/api/files/{id}", fileHandler::getFileById) @@ -184,7 +184,7 @@ public class SystemRouter { .GET("/api/files/{id}/preview", fileHandler::previewFile) .GET("/api/files/preview/{fileName}", fileHandler::previewFileByName) .DELETE("/api/files/{id}", fileHandler::deleteFile) - + // ========== 权限路由 ========== .GET("/api/permissions", permissionHandler::getAllPermissions) .GET("/api/permissions/{id}", permissionHandler::getPermissionById) @@ -197,7 +197,8 @@ public class SystemRouter { // ========== 团课路由 ========== .GET("/api/groupCourse", groupCourseHandler::getAllGroupCourse) - + .GET("/api/groupCourse/{id}", groupCourseHandler::getGroupCourseById) + .build(); } } diff --git a/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/entity/GroupCourseBookingEntity.java b/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/entity/GroupCourseBookingEntity.java deleted file mode 100644 index f414735..0000000 --- a/gym-manage-api/manage-db/src/main/java/cn/novalon/gym/manage/db/entity/GroupCourseBookingEntity.java +++ /dev/null @@ -1,75 +0,0 @@ -package cn.novalon.gym.manage.db.entity; - -import org.springframework.data.relational.core.mapping.Column; -import org.springframework.data.relational.core.mapping.Table; - -import java.util.Date; - -/** - * @author:liwentao - * @date:2026/4/25-04-25-17:50 - * 团课预约记录表 - */ - -@Table("group_course_booking") -public class GroupCourseBookingEntity extends BaseEntity { - - //团课id - @Column("course_id") - private Long courseId; - - //用户id - @Column("user_id") - private Long userId; - - //预约时间 - @Column("booking_time") - private Date bookingTime; - - //状态:0-已预约,1-已取消,2-已出席,3-缺席 - @Column("status") - private Long status; - //取消时间 - @Column("cancel_time") - private Date cancelTime; - - public Long getCourseId() { - return courseId; - } - - public void setCourseId(Long courseId) { - this.courseId = courseId; - } - - public Long getUserId() { - return userId; - } - - public void setUserId(Long userId) { - this.userId = userId; - } - - public Date getBookingTime() { - return bookingTime; - } - - public void setBookingTime(Date bookingTime) { - this.bookingTime = bookingTime; - } - - public Long getStatus() { - return status; - } - - public void setStatus(Long status) { - this.status = status; - } - - public Date getCancelTime() { - return cancelTime; - } - - public void setCancelTime(Date cancelTime) { - this.cancelTime = cancelTime; - } -} diff --git a/gym-manage-api/pom.xml b/gym-manage-api/pom.xml index aec5848..ff13cbc 100644 --- a/gym-manage-api/pom.xml +++ b/gym-manage-api/pom.xml @@ -42,6 +42,7 @@ manage-audit manage-notify manage-file + gym-groupCourse From 7340f02102b39948bc6ea709bcb98ccc6f517e59 Mon Sep 17 00:00:00 2001 From: liwentao Date: Fri, 15 May 2026 15:51:46 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E7=94=A8=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/novalon/gym/manage/sys/config/SecurityConfig.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java index b68cf04..a824830 100644 --- a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java +++ b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java @@ -50,10 +50,7 @@ public class SecurityConfig { spec.pathMatchers("/api/auth/**").permitAll() .pathMatchers("/api/public/**").permitAll() .pathMatchers("/ws/**").permitAll() - .pathMatchers("/actuator/**").permitAll() - //========TODO lwt 以下是测试接口,生产时必关======== - .pathMatchers("/api/users/**").permitAll() - .pathMatchers("/api/groupCourse/**").permitAll(); + .pathMatchers("/actuator/**").permitAll(); if (isDevOrTest) { From 493ecd302150359b16acb0910744cc3e0713a2ef Mon Sep 17 00:00:00 2001 From: liwentao Date: Fri, 15 May 2026 17:32:03 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Redis=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=20=E6=B3=A8=EF=BC=9A/api/groupCourse/cache/g?= =?UTF-8?q?et=E6=8E=A5=E5=8F=A3=E4=B8=BA=E6=B5=8B=E8=AF=95=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gym-manage-api/gym-groupCourse/pom.xml | 7 ++ .../handler/GroupCourseHandler.java | 92 ++++++++++++++- .../repository/IGroupCourseRepository.java | 5 + .../impl/GroupCourseRepository.java | 75 ++++++++++++ .../service/IGroupCourseService.java | 4 + .../groupcourse/service/RedisService.java | 76 +++++++++++++ .../service/impl/GroupCourseService.java | 107 +++++++++++++++++- .../gym/manage/app/config/RedisConfig.java | 43 +++++++ .../gym/manage/app/config/SystemRouter.java | 27 +---- .../src/main/resources/application.yml | 13 +++ .../gym/manage/sys/config/SecurityConfig.java | 3 +- 11 files changed, 422 insertions(+), 30 deletions(-) create mode 100644 gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/RedisService.java create mode 100644 gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/config/RedisConfig.java diff --git a/gym-manage-api/gym-groupCourse/pom.xml b/gym-manage-api/gym-groupCourse/pom.xml index 3fc53bb..a7bfc02 100644 --- a/gym-manage-api/gym-groupCourse/pom.xml +++ b/gym-manage-api/gym-groupCourse/pom.xml @@ -67,6 +67,13 @@ 2.2.43 compile + + + + + org.springframework.boot + spring-boot-starter-data-redis + 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 920786f..db6c601 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 @@ -1,8 +1,11 @@ package cn.novalon.gym.manage.groupcourse.handler; +import cn.novalon.gym.manage.common.dto.PageRequest; import cn.novalon.gym.manage.groupcourse.domain.GroupCourse; import cn.novalon.gym.manage.groupcourse.service.IGroupCourseService; +import cn.novalon.gym.manage.groupcourse.service.RedisService; +import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Validator; @@ -11,15 +14,25 @@ import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; import reactor.core.publisher.Mono; +import java.util.HashMap; +import java.util.Map; + @Component @Tag(name="团课管理",description = "团课相关操作") public class GroupCourseHandler { private final IGroupCourseService groupCourseService; private final Validator validator; + private final RedisService redisService; + private final ObjectMapper objectMapper; - public GroupCourseHandler(IGroupCourseService groupCourseService, Validator validator){ + public GroupCourseHandler(IGroupCourseService groupCourseService, + Validator validator, + RedisService redisService, + ObjectMapper objectMapper){ this.groupCourseService = groupCourseService; this.validator = validator; + this.redisService = redisService; + this.objectMapper = objectMapper; } @Operation(summary = "获取所有团课", description = "获取系统中所有团课列表") @@ -29,10 +42,87 @@ public class GroupCourseHandler { .body(groupCourseService.findAll(includeDeleted), GroupCourse.class); } + @Operation(summary = "分页获取团课", description = "根据分页参数获取团课列表") + public Mono getGroupCoursesByPage(ServerRequest request) { + return request.bodyToMono(PageRequest.class) + .flatMap(pageRequest -> { + boolean includeDeleted = request.queryParam("includeDeleted") + .map(Boolean::parseBoolean) + .orElse(false); + + if (pageRequest.getPage() < 0) { + pageRequest.setPage(0); + } + if (pageRequest.getSize() <= 0 || pageRequest.getSize() > 100) { + pageRequest.setSize(10); + } + if (pageRequest.getSort() == null || pageRequest.getSort().isEmpty()) { + pageRequest.setSort("id"); + } + if (pageRequest.getOrder() == null || pageRequest.getOrder().isEmpty()) { + pageRequest.setOrder("asc"); + } + + return groupCourseService.findByPage(pageRequest, includeDeleted) + .flatMap(response -> ServerResponse.ok().bodyValue(response)); + }); + } + @Operation(summary = "根据ID获取团课", description = "根据ID获取团课详情") public Mono getGroupCourseById(ServerRequest request){ Long id = Long.valueOf(request.pathVariable("id")); return ServerResponse.ok() .body(groupCourseService.findById(id), GroupCourse.class); } + + @Operation(summary = "测试-根据Key获取Redis缓存", description = "测试接口:根据传入的key值获取Redis中缓存的数据") + public Mono getCacheByKey(ServerRequest request) { + return request.bodyToMono(Map.class) + .flatMap(body -> { + String key = (String) body.get("key"); + + if (key == null || key.isEmpty()) { + Map error = new HashMap<>(); + error.put("success", false); + error.put("message", "key参数不能为空"); + return ServerResponse.badRequest().bodyValue(error); + } + + Object cachedValue = redisService.get(key); + + Map result = new HashMap<>(); + if (cachedValue != null) { + result.put("success", true); + result.put("key", key); + result.put("value", cachedValue); + result.put("message", "缓存命中"); + + try { + if (cachedValue instanceof String) { + Object jsonObject = objectMapper.readValue((String) cachedValue, Object.class); + result.put("parsedValue", jsonObject); + result.put("valueType", "JSON字符串"); + } else { + result.put("valueType", cachedValue.getClass().getSimpleName()); + } + } catch (Exception e) { + result.put("parsedValue", null); + result.put("valueType", "无法解析"); + } + } else { + result.put("success", false); + result.put("key", key); + result.put("value", null); + result.put("message", "缓存未命中"); + } + + return ServerResponse.ok().bodyValue(result); + }) + .onErrorResume(error -> { + Map errorResponse = new HashMap<>(); + errorResponse.put("success", false); + errorResponse.put("message", "请求处理失败: " + error.getMessage()); + return ServerResponse.status(500).bodyValue(errorResponse); + }); + } } 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 4ade673..1a2d402 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 @@ -1,6 +1,8 @@ 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 org.springframework.data.domain.Sort; import reactor.core.publisher.Flux; @@ -12,4 +14,7 @@ public interface IGroupCourseRepository { Flux findAll(Sort sort); Flux findByDeletedAtIsNull(); Flux findByDeletedAtIsNull(Sort sort); + + Mono> findByPage(PageRequest pageRequest); + Mono> findByPageAndNotDeleted(PageRequest pageRequest); } 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 5c11325..aa249d1 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 @@ -1,16 +1,22 @@ package cn.novalon.gym.manage.groupcourse.repository.impl; +import cn.novalon.gym.manage.common.dto.PageRequest; +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.entity.GroupCourseEntity; import cn.novalon.gym.manage.groupcourse.repository.IGroupCourseRepository; import org.springframework.data.domain.Sort; import org.springframework.data.r2dbc.core.R2dbcEntityTemplate; +import org.springframework.data.relational.core.query.Query; import org.springframework.stereotype.Repository; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.util.List; + @Repository public class GroupCourseRepository implements IGroupCourseRepository { private final GroupCourseDao groupCourseDao; @@ -53,4 +59,73 @@ public class GroupCourseRepository implements IGroupCourseRepository { return groupCourseDao.findAllByDeletedAtIsNull(sort) .map(groupCourseConverter::toDomain); } + + @Override + public Mono> findByPage(PageRequest pageRequest) { + int page = pageRequest.getPage(); + int size = pageRequest.getSize(); + String sort = pageRequest.getSort(); + String order = pageRequest.getOrder(); + + Sort sortObj = Sort.unsorted(); + if (sort != null && !sort.isEmpty()) { + sortObj = Sort.by(Sort.Direction.fromString(order), sort); + } + + org.springframework.data.domain.PageRequest pageable = org.springframework.data.domain.PageRequest.of(page, size, sortObj); + + Query query = Query.empty(); + + return r2dbcEntityTemplate.select(GroupCourseEntity.class) + .matching(query.with(pageable)) + .all() + .collectList() + .zipWith(r2dbcEntityTemplate.count(query, GroupCourseEntity.class)) + .map(tuple -> { + long total = tuple.getT2(); + int totalPages = (int) Math.ceil((double) total / size); + List courseList = tuple.getT1().stream() + .map(groupCourseConverter::toDomain) + .toList(); + return new PageResponse<>(courseList, totalPages, total, page, size); + }); + } + + @Override + public Mono> findByPageAndNotDeleted(PageRequest pageRequest) { + int page = pageRequest.getPage(); + int size = pageRequest.getSize(); + String sort = pageRequest.getSort(); + String order = pageRequest.getOrder(); + + Sort sortObj = Sort.unsorted(); + if (sort != null && !sort.isEmpty()) { + sortObj = Sort.by(Sort.Direction.fromString(order), sort); + } + + org.springframework.data.domain.PageRequest pageable = org.springframework.data.domain.PageRequest.of(page, size, sortObj); + + return groupCourseDao.findAllByDeletedAtIsNull(sortObj) + .collectList() + .zipWith(groupCourseDao.findAllByDeletedAtIsNull().count()) + .map(tuple -> { + List allEntities = tuple.getT1(); + long total = tuple.getT2(); + + int fromIndex = page * size; + int toIndex = Math.min(fromIndex + size, allEntities.size()); + + List courseList; + if (fromIndex < allEntities.size()) { + courseList = allEntities.subList(fromIndex, toIndex).stream() + .map(groupCourseConverter::toDomain) + .toList(); + } else { + courseList = List.of(); + } + + int totalPages = (int) Math.ceil((double) total / size); + return new PageResponse<>(courseList, totalPages, total, page, 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 d43b396..7fa0b70 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 @@ -1,6 +1,8 @@ package cn.novalon.gym.manage.groupcourse.service; +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 reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -9,4 +11,6 @@ public interface IGroupCourseService { Mono findById(Long id); Flux findAll(); Flux findAll(boolean includeDeleted); + + Mono> findByPage(PageRequest pageRequest, boolean includeDeleted); } diff --git a/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/RedisService.java b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/RedisService.java new file mode 100644 index 0000000..aa92e38 --- /dev/null +++ b/gym-manage-api/gym-groupCourse/src/main/java/cn/novalon/gym/manage/groupcourse/service/RedisService.java @@ -0,0 +1,76 @@ +package cn.novalon.gym.manage.groupcourse.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * @author:liwentao + * @date:2026/5/15-05-15-16:05 + */ +@Service +public class RedisService { + + @Autowired + private RedisTemplate redisTemplate; + + // 设置值 + public void set(String key, Object value) { + redisTemplate.opsForValue().set(key, value); + } + + // 设置值并指定过期时间(秒) + public void setWithExpire(String key, Object value, long timeout) { + redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS); + } + + // 获取值 + public Object get(String key) { + return redisTemplate.opsForValue().get(key); + } + + // 删除key + public Boolean delete(String key) { + return redisTemplate.delete(key); + } + + // 判断key是否存在 + public Boolean hasKey(String key) { + return redisTemplate.hasKey(key); + } + + // 设置过期时间 + public Boolean expire(String key, long timeout) { + return redisTemplate.expire(key, timeout, TimeUnit.SECONDS); + } + + // Hash操作 + public void putHash(String key, String hashKey, Object value) { + redisTemplate.opsForHash().put(key, hashKey, value); + } + + public Object getHash(String key, String hashKey) { + return redisTemplate.opsForHash().get(key, hashKey); + } + + // List操作 + public void leftPush(String key, Object value) { + redisTemplate.opsForList().leftPush(key, value); + } + + public Object rightPop(String key) { + return redisTemplate.opsForList().rightPop(key); + } + + // Set操作 + public void addToSet(String key, Object... values) { + redisTemplate.opsForSet().add(key, values); + } + + public Set getSet(String key) { + return redisTemplate.opsForSet().members(key); + } +} 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 6e409e3..70a43cc 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 @@ -1,24 +1,79 @@ package cn.novalon.gym.manage.groupcourse.service.impl; +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.repository.IGroupCourseRepository; import cn.novalon.gym.manage.groupcourse.service.IGroupCourseService; +import cn.novalon.gym.manage.groupcourse.service.RedisService; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.time.Duration; +import java.util.List; + @Service public class GroupCourseService implements IGroupCourseService { - private final IGroupCourseRepository groupCourseRepository; + private static final Logger logger = LoggerFactory.getLogger(GroupCourseService.class); - public GroupCourseService(IGroupCourseRepository groupCourseRepository){ + private final IGroupCourseRepository groupCourseRepository; + private final RedisService redisService; + private final ObjectMapper objectMapper; + + private static final String CACHE_KEY_PREFIX = "group_course:page:"; + private static final String CACHE_KEY_ID_PREFIX = "group_course:id:"; + private static final long CACHE_EXPIRE_SECONDS = 300; + + public GroupCourseService(IGroupCourseRepository groupCourseRepository, + RedisService redisService, + ObjectMapper objectMapper){ this.groupCourseRepository = groupCourseRepository; + this.redisService = redisService; + this.objectMapper = objectMapper; } @Override public Mono findById(Long id) { - return groupCourseRepository.findByIdAndDeletedAtIsNull(id); + String cacheKey = CACHE_KEY_ID_PREFIX + id; + + Object cachedData = redisService.get(cacheKey); + if (cachedData != null) { + try { + String json; + if (cachedData instanceof String) { + json = (String) cachedData; + } else { + json = objectMapper.writeValueAsString(cachedData); + } + + GroupCourse groupCourse = objectMapper.readValue(json, GroupCourse.class); + logger.info("缓存命中 - findById: id={}", id); + return Mono.just(groupCourse); + } catch (JsonProcessingException e) { + logger.warn("缓存解析失败,删除缓存 - id: {}, error: {}", id, e.getMessage()); + redisService.delete(cacheKey); + } + } + + logger.debug("缓存未命中,查询数据库 - findById: id={}", id); + return groupCourseRepository.findByIdAndDeletedAtIsNull(id) + .doOnSuccess(groupCourse -> { + if (groupCourse != null) { + try { + String jsonData = objectMapper.writeValueAsString(groupCourse); + redisService.setWithExpire(cacheKey, jsonData, CACHE_EXPIRE_SECONDS); + logger.debug("缓存已设置 - findById: id={}", id); + } catch (JsonProcessingException e) { + logger.error("缓存设置失败 - id: {}, error: {}", id, e.getMessage()); + } + } + }); } @Override @@ -34,4 +89,50 @@ public class GroupCourseService implements IGroupCourseService { return groupCourseRepository.findByDeletedAtIsNull(); } } + + @Override + public Mono> findByPage(PageRequest pageRequest, boolean includeDeleted) { + int page = pageRequest.getPage(); + int size = pageRequest.getSize(); + + String cacheKey = CACHE_KEY_PREFIX + page + ":" + size + ":" + includeDeleted; + + Object cachedData = redisService.get(cacheKey); + if (cachedData != null) { + try { + String json; + if (cachedData instanceof String) { + json = (String) cachedData; + } else { + json = objectMapper.writeValueAsString(cachedData); + } + + PageResponse pageResponse = objectMapper.readValue(json, + objectMapper.getTypeFactory().constructParametricType(PageResponse.class, GroupCourse.class)); + logger.info("缓存命中 - findByPage: key={}", cacheKey); + return Mono.just(pageResponse); + } catch (JsonProcessingException e) { + logger.warn("缓存解析失败,删除缓存 - key: {}, error: {}", cacheKey, e.getMessage()); + redisService.delete(cacheKey); + } + } + + logger.debug("缓存未命中,查询数据库 - findByPage: key={}", cacheKey); + Mono> resultMono; + if (includeDeleted) { + resultMono = groupCourseRepository.findByPage(pageRequest); + } else { + resultMono = groupCourseRepository.findByPageAndNotDeleted(pageRequest); + } + + return resultMono.doOnSuccess(pageResponse -> { + try { + String jsonData = objectMapper.writeValueAsString(pageResponse); + redisService.setWithExpire(cacheKey, jsonData, CACHE_EXPIRE_SECONDS); + logger.debug("缓存已设置 - findByPage: key={}", cacheKey); + } catch (JsonProcessingException e) { + logger.error("缓存设置失败 - key: {}, error: {}", cacheKey, e.getMessage()); + } + }); + } } diff --git a/gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/config/RedisConfig.java b/gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/config/RedisConfig.java new file mode 100644 index 0000000..12d804e --- /dev/null +++ b/gym-manage-api/manage-app/src/main/java/cn/novalon/gym/manage/app/config/RedisConfig.java @@ -0,0 +1,43 @@ +package cn.novalon.gym.manage.app.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @author:liwentao + * @date:2026/5/15-05-15-16:01 + */ +@Configuration +public class RedisConfig { + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(factory); + + // 创建ObjectMapper并配置 + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.activateDefaultTyping(om.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL); + + // 使用GenericJackson2JsonRedisSerializer替代已弃用的方式 + GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(om); + + // 使用StringRedisSerializer来序列化和反序列化redis的key值 + StringRedisSerializer stringSerializer = new StringRedisSerializer(); + template.setKeySerializer(stringSerializer); + template.setValueSerializer(genericJackson2JsonRedisSerializer); + template.setHashKeySerializer(stringSerializer); + template.setHashValueSerializer(genericJackson2JsonRedisSerializer); + + template.afterPropertiesSet(); + return template; + } +} \ No newline at end of file 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 185540b..ff82abc 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 @@ -24,16 +24,6 @@ import org.springframework.web.reactive.function.server.ServerResponse; import static org.springframework.web.reactive.function.server.RouterFunctions.route; -/** - * 系统路由配置类 - * - * 文件定义:配置WebFlux函数式路由,将HTTP请求映射到对应的Handler方法 - * 涉及业务:用户、角色、字典、菜单、公告、文件等所有RESTful API路由 - * 算法:使用RouterFunctions.route()构建函数式路由规则 - * - * @author 张翔 - * @date 2026-03-13 - */ @Configuration public class SystemRouter { @Bean @@ -56,10 +46,8 @@ public class SystemRouter { PasswordDiagnosticHandler passwordDiagnosticHandler) { return route() - // ========== 诊断路由 ========== .GET("/api/diagnostic/password", passwordDiagnosticHandler::diagnose) - // ========== 字典路由 ========== .GET("/api/dictionaries", dictionaryHandler::getAllDictionaries) .GET("/api/dictionaries/{id}", dictionaryHandler::getDictionaryById) .GET("/api/dictionaries/type/{type}", dictionaryHandler::getDictionariesByType) @@ -68,7 +56,6 @@ public class SystemRouter { .PUT("/api/dictionaries/{id}", dictionaryHandler::updateDictionary) .DELETE("/api/dictionaries/{id}", dictionaryHandler::deleteDictionary) - // ========== 用户路由 ========== .GET("/api/users", userHandler::getAllUsers) .GET("/api/users/page", userHandler::getUsersByPage) .GET("/api/users/count", userHandler::getUserCount) @@ -87,7 +74,6 @@ public class SystemRouter { .GET("/api/users/{id}/roles", userHandler::getUserRoles) .POST("/api/users/{id}/roles", userHandler::assignRoles) - // ========== 菜单路由 ========== .GET("/api/menus", menuHandler::getAllMenus) .GET("/api/menus/tree", menuHandler::getMenuTree) .GET("/api/menus/{id}", menuHandler::getMenuById) @@ -95,7 +81,6 @@ public class SystemRouter { .PUT("/api/menus/{id}", menuHandler::updateMenu) .DELETE("/api/menus/{id}", menuHandler::deleteMenu) - // ========== 角色路由 ========== .GET("/api/roles", roleHandler::getAllRoles) .GET("/api/roles/page", roleHandler::getRolesByPage) .GET("/api/roles/count", roleHandler::getRoleCount) @@ -109,7 +94,6 @@ public class SystemRouter { .GET("/api/roles/{id}/permissions", permissionHandler::getPermissionsByRoleId) .POST("/api/roles/{id}/permissions", permissionHandler::assignPermissionsToRole) - // ========== 配置路由 ========== .GET("/api/config", configHandler::getAllConfigs) .GET("/api/config/{id}", configHandler::getConfigById) .GET("/api/config/key/{configKey}", configHandler::getConfigByKey) @@ -117,7 +101,6 @@ public class SystemRouter { .PUT("/api/config/{id}", configHandler::updateConfig) .DELETE("/api/config/{id}", configHandler::deleteConfig) - // ========== 日志路由 ========== .GET("/api/logs/login", logHandler::getAllLoginLogs) .GET("/api/logs/login/page", logHandler::getLoginLogsByPage) .GET("/api/logs/login/count", logHandler::getLoginLogCount) @@ -137,15 +120,12 @@ public class SystemRouter { .GET("/api/logs/operation/{id}", operationLogHandler::getOperationLogById) .POST("/api/logs/operation", operationLogHandler::createOperationLog) - // ========== 认证路由 ========== .POST("/api/auth/login", authHandler::login) .POST("/api/auth/register", authHandler::register) .POST("/api/auth/logout", authHandler::logout) - // ========== 统计路由 ========== .GET("/api/stats/overview", statsHandler::getOverview) - // ========== 数据字典路由 ========== .GET("/api/dict/types", dictHandler::getAllDictTypes) .GET("/api/dict/types/{id}", dictHandler::getDictTypeById) .GET("/api/dict/types/type/{dictType}", dictHandler::getDictTypeByType) @@ -159,7 +139,6 @@ public class SystemRouter { .PUT("/api/dict/data/{id}", dictHandler::updateDictData) .DELETE("/api/dict/data/{id}", dictHandler::deleteDictData) - // ========== 公告路由 ========== .GET("/api/notices", noticeHandler::getAllNotices) .GET("/api/notices/{id}", noticeHandler::getNoticeById) .GET("/api/notices/status/{status}", noticeHandler::getNoticesByStatus) @@ -167,7 +146,6 @@ public class SystemRouter { .PUT("/api/notices/{id}", noticeHandler::updateNotice) .DELETE("/api/notices/{id}", noticeHandler::deleteNotice) - // ========== 消息路由 ========== .GET("/api/messages/user/{userId}", messageHandler::getMessagesByUser) .GET("/api/messages/user/{userId}/unread", messageHandler::getUnreadCount) .GET("/api/messages/user/{userId}/unread/list", messageHandler::getUnreadList) @@ -175,7 +153,6 @@ public class SystemRouter { .PUT("/api/messages/{id}/read", messageHandler::markAsRead) .DELETE("/api/messages/{id}", messageHandler::deleteMessage) - // ========== 文件路由 ========== .GET("/api/files", fileHandler::getAllFiles) .GET("/api/files/{id}", fileHandler::getFileById) .POST("/api/files/upload", fileHandler::uploadFile) @@ -185,7 +162,6 @@ public class SystemRouter { .GET("/api/files/preview/{fileName}", fileHandler::previewFileByName) .DELETE("/api/files/{id}", fileHandler::deleteFile) - // ========== 权限路由 ========== .GET("/api/permissions", permissionHandler::getAllPermissions) .GET("/api/permissions/{id}", permissionHandler::getPermissionById) .GET("/api/permissions/code/{code}", permissionHandler::getPermissionByCode) @@ -195,8 +171,9 @@ public class SystemRouter { .PUT("/api/permissions/{id}", permissionHandler::updatePermission) .DELETE("/api/permissions/{id}", permissionHandler::deletePermission) - // ========== 团课路由 ========== .GET("/api/groupCourse", groupCourseHandler::getAllGroupCourse) + .POST("/api/groupCourse/page", groupCourseHandler::getGroupCoursesByPage) + .POST("/api/groupCourse/cache/get", groupCourseHandler::getCacheByKey) .GET("/api/groupCourse/{id}", groupCourseHandler::getGroupCourseById) .build(); diff --git a/gym-manage-api/manage-app/src/main/resources/application.yml b/gym-manage-api/manage-app/src/main/resources/application.yml index 0d7edda..91f237f 100644 --- a/gym-manage-api/manage-app/src/main/resources/application.yml +++ b/gym-manage-api/manage-app/src/main/resources/application.yml @@ -38,9 +38,22 @@ spring: user: name: disabled password: disabled + data: + redis: + host: ${REDIS_HOST:localhost} + port: ${REDIS_PORT:6379} + password: ${REDIS_PASSWORD:novalon123} + timeout: 5000 + lettuce: + pool: + max-active: 8 # 最大连接数 + max-idle: 8 # 最大空闲连接 + min-idle: 0 # 最小空闲连接 + max-wait: -1ms # 连接等待时间 profiles: active: dev + management: endpoints: web: diff --git a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java index a824830..83ea7df 100644 --- a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java +++ b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java @@ -50,7 +50,8 @@ public class SecurityConfig { spec.pathMatchers("/api/auth/**").permitAll() .pathMatchers("/api/public/**").permitAll() .pathMatchers("/ws/**").permitAll() - .pathMatchers("/actuator/**").permitAll(); + .pathMatchers("/actuator/**").permitAll() + .pathMatchers("/api/groupCourse/**").permitAll(); if (isDevOrTest) {