diff --git a/ruoyi-site/README.md b/ruoyi-site/README.md
index 47f8aad84..b999214a1 100644
--- a/ruoyi-site/README.md
+++ b/ruoyi-site/README.md
@@ -1 +1,5 @@
所有站点
+
+
+
+后续:h5在线链接、在线抽奖系统。
\ No newline at end of file
diff --git a/ruoyi-site/pom.xml b/ruoyi-site/pom.xml
index ce4d87f4d..d0e964e5b 100644
--- a/ruoyi-site/pom.xml
+++ b/ruoyi-site/pom.xml
@@ -13,6 +13,7 @@
ruoyi-sso-server
ruoyi-h5
ruoyi-gateway
+ ruoyi-tams
ruoyi-site
diff --git a/ruoyi-site/ruoyi-tams/Dockerfile b/ruoyi-site/ruoyi-tams/Dockerfile
new file mode 100644
index 000000000..27583b090
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/Dockerfile
@@ -0,0 +1,20 @@
+FROM bellsoft/liberica-openjdk-debian:17.0.11-cds
+
+LABEL maintainer="lizhw"
+
+RUN mkdir -p /ruoyi/resource/logs \
+ /ruoyi/resource/temp \
+ /ruoyi/skywalking/agent
+
+WORKDIR /ruoyi/resource
+
+ENV SERVER_PORT=19201 LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS=""
+
+EXPOSE ${SERVER_PORT}
+
+ADD ./target/ruoyi-tams.jar ./app.jar
+
+ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Dserver.port=${SERVER_PORT} \
+ -XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC ${JAVA_OPTS} \
+ -jar app.jar
+
diff --git a/ruoyi-site/ruoyi-tams/pom.xml b/ruoyi-site/ruoyi-tams/pom.xml
new file mode 100644
index 000000000..411387d9c
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/pom.xml
@@ -0,0 +1,109 @@
+
+
+
+ org.dromara
+ ruoyi-site
+ ${revision}
+
+ 4.0.0
+
+ ruoyi-tams
+
+
+ ruoyi-tams 教培系统后台
+
+
+
+
+
+ org.dromara
+ ruoyi-common-core
+
+
+
+
+ org.dromara
+ ruoyi-common-tenant
+
+
+
+
+ org.dromara
+ ruoyi-common-mybatis
+
+
+
+ org.dromara
+ ruoyi-common-doc
+
+
+
+
+ org.dromara
+ ruoyi-api-system
+
+
+
+ org.dromara
+ ruoyi-common-log
+
+
+
+
+ com.mysql
+ mysql-connector-j
+
+
+
+ org.dromara
+ ruoyi-common-encrypt
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.apache.dubbo
+ dubbo-spring-boot-starter
+
+
+
+ org.apache.dubbo
+ dubbo-nacos-spring-boot-starter
+
+
+
+
+ org.apache.poi
+ poi-ooxml
+ 4.1.2
+
+
+
+
+
+
+ ${project.artifactId}
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring-boot.version}
+
+
+
+ repackage
+
+
+
+
+
+
+
+
diff --git a/ruoyi-site/ruoyi-tams/sql/init_ddl.sql b/ruoyi-site/ruoyi-tams/sql/init_ddl.sql
new file mode 100644
index 000000000..a04f93ab1
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/sql/init_ddl.sql
@@ -0,0 +1,95 @@
+create schema mall-tams-core;
+
+set
+character set utf8mb4;
+create table t_classroom
+(
+ id bigint auto_increment
+ primary key,
+ name varchar(30) default '' not null comment '名称',
+ enable_state int unsigned default 1 not null comment '停启用状态,1启用 2停用'
+) comment '教室';
+
+create table t_color
+(
+ id bigint auto_increment comment 'id'
+ primary key,
+ name varchar(30) default '' not null comment '名称',
+ value char(7) default '' not null comment '值'
+) comment '颜色';
+
+create table t_course
+(
+ id bigint auto_increment comment 'id'
+ primary key,
+ name varchar(30) default '' not null comment '名称',
+ enable_state int unsigned default 1 not null comment '停启用状态,1启用 2停用',
+ duration int unsigned null comment '课程时长,单位分钟',
+ background_color char(7) default '' not null comment '背景颜色'
+) comment '课程';
+
+create table t_course_scheduling
+(
+ id bigint auto_increment comment 'id'
+ primary key,
+ classroom_id bigint default 0 not null comment '教室id',
+ course_id bigint default 0 not null comment '课程id',
+ teacher_id bigint default 0 not null comment '教师id',
+ date date null comment '日期',
+ attend_time time null comment '上课时间',
+ finish_time time null comment '下课时间'
+) comment '排课';
+
+create table t_school
+(
+ id bigint auto_increment comment 'id'
+ primary key,
+ 名称 varchar(50) default '' not null comment '名称'
+) comment '学校';
+
+create table t_teacher
+(
+ id bigint auto_increment comment 'id'
+ primary key,
+ name varchar(10) default '' not null comment '姓名',
+ enable_state int unsigned default 1 not null comment '停启用状态,1启用 2停用'
+) comment '教师';
+
+create table t_course
+(
+ id bigint auto_increment comment 'id'
+ primary key,
+ name varchar(30) default '' not null comment '名称',
+ enable_state int unsigned default 1 not null comment '停启用状态,1启用 2停用',
+ duration int unsigned null comment '课程时长,单位分钟',
+ lesson double unsigned null comment '课时',
+ background_color char(7) default '' not null comment '背景颜色'
+) comment '课程';
+
+
+create table t_registration
+(
+ id bigint auto_increment comment 'id'
+ primary key,
+ student_id bigint not null comment '学员',
+ student_name varchar(50) null comment '学员名称',
+ student_phone varchar(20) null comment '学员电话',
+ course_id bigint not null comment '课程id',
+ course_name varchar(255) null comment '课程',
+ duration int null comment '课程时长,单位分钟',
+ lesson double null comment '课时',
+ class_time datetime null comment '上课时间',
+ create_time datetime null comment '创建时间',
+ enable_state int unsigned default 1 not null comment '停启用状态'
+) comment '登记';
+
+CREATE TABLE t_student
+(
+ id bigint auto_increment comment '学号',
+ name varchar(50) not null comment '姓名',
+ phone varchar(20) not null comment '电话',
+ create_time datetime comment '创建时间',
+ enable_state int unsigned default 1 not null comment '停启用状态',
+ PRIMARY KEY (id)
+) COMMENT ='学生信息表' CHARACTER SET utf8mb4
+ COLLATE utf8mb4_general_ci;
diff --git a/ruoyi-site/ruoyi-tams/sql/init_dml.sql b/ruoyi-site/ruoyi-tams/sql/init_dml.sql
new file mode 100644
index 000000000..6de15d91e
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/sql/init_dml.sql
@@ -0,0 +1,12 @@
+set character set utf8mb4;
+INSERT INTO t_color (name, value) VALUES ('GREEN SEA', '#16a085');
+INSERT INTO t_color (name, value) VALUES ('NEPHRITIS', '#27ae60');
+INSERT INTO t_color (name, value) VALUES ('BELIZE HOLE', '#2980b9');
+INSERT INTO t_color (name, value) VALUES ('MIDNIGHT', '#2c3e50');
+INSERT INTO t_color (name, value) VALUES ('ASBESTOS', '#7f8c8d');
+INSERT INTO t_color (name, value) VALUES ('WISTERIA', '#8e44ad');
+INSERT INTO t_color (name, value) VALUES ('SILVER', '#bdc3c7');
+INSERT INTO t_color (name, value) VALUES ('POMEGRANATE', '#c0392b');
+INSERT INTO t_color (name, value) VALUES ('PUMPKIN', '#d35400');
+INSERT INTO t_color (name, value) VALUES ('Dark Salmon', '#efa48b');
+INSERT INTO t_color (name, value) VALUES ('ORANGE', '#f39c12');
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/MallTamsApplication.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/MallTamsApplication.java
new file mode 100644
index 000000000..a5ee3fe8c
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/MallTamsApplication.java
@@ -0,0 +1,17 @@
+package com.lhd.tams;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+//import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+//import org.springframework.cloud.openfeign.EnableFeignClients;
+
+//@EnableFeignClients
+//@EnableDiscoveryClient
+@SpringBootApplication
+public class MallTamsApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(MallTamsApplication.class, args);
+ }
+
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/base/BaseController.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/base/BaseController.java
new file mode 100644
index 000000000..03969003c
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/base/BaseController.java
@@ -0,0 +1,24 @@
+package com.lhd.tams.common.base;
+
+import com.lhd.tams.common.model.ApiResult;
+import com.lhd.tams.common.util.ResponseEntityUtils;
+import org.springframework.http.ResponseEntity;
+
+public class BaseController {
+
+ protected static ResponseEntity> success() {
+ return ResponseEntityUtils.ok("");
+ }
+
+ protected static ResponseEntity> success(T data) {
+ return ResponseEntityUtils.ok(data);
+ }
+
+ protected static ResponseEntity> error(String msg) {
+ return ResponseEntityUtils.badRequest(msg);
+ }
+
+ protected static ResponseEntity> successOrFail(Boolean flag) {
+ return flag ? success() : ResponseEntityUtils.badRequest("操作失败,数据可能已被修改或删除");
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/consts/CommonConsts.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/consts/CommonConsts.java
new file mode 100644
index 000000000..f264099b6
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/consts/CommonConsts.java
@@ -0,0 +1,14 @@
+package com.lhd.tams.common.consts;
+
+/**
+ * 通用常量
+ */
+public class CommonConsts {
+
+ public static final Integer TRUE_VALUE_INT = 1;
+ public static final Integer FALSE_VALUE_INT = 0;
+
+ public static final String TIME_FORMATTER = "HH:mm:ss";
+ public static final String DATE_FORMATTER = "yyyy-MM-dd";
+ public static final String DATETIME_FORMATTER = "yyyy-MM-dd HH:mm:ss";
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/consts/EnableStateEnum.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/consts/EnableStateEnum.java
new file mode 100644
index 000000000..41c8876d5
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/consts/EnableStateEnum.java
@@ -0,0 +1,34 @@
+package com.lhd.tams.common.consts;
+
+/**
+ * 停启用状态
+ */
+public enum EnableStateEnum {
+
+ DISABLED(2, "停用"),
+ ENABLED(1, "启用");
+
+ private Integer code;
+ private String msg;
+
+ EnableStateEnum(Integer code, String msg) {
+ this.code = code;
+ this.msg = msg;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public void setCode(Integer code) {
+ this.code = code;
+ }
+
+ public String getMsg() {
+ return msg;
+ }
+
+ public void setMsg(String msg) {
+ this.msg = msg;
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/consts/ErrorCodeEnum.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/consts/ErrorCodeEnum.java
new file mode 100644
index 000000000..297d0b1a1
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/consts/ErrorCodeEnum.java
@@ -0,0 +1,46 @@
+package com.lhd.tams.common.consts;
+
+/**
+ * 详细错误码
+ * 起始值1000,每100个为一类
+ * 命名:类别_具体描述
+ */
+public enum ErrorCodeEnum {
+
+ /**
+ * 业务异常
+ */
+ BUSINESS_COURSE_SCHEDULING_DATE_CONFLICT(100001, "排课时间冲突"),
+ BUSINESS_ERROR(100000, "业务异常"),
+ /**
+ * 关系型数据库
+ */
+ DB_DATA_TOO_LONG(1101, "字段超长"),
+ DB_DATA_INTEGRITY_VIOLATION(1100, "数据完整性异常"),
+
+ UNKNOWN_ERROR(1000, "未知异常");
+
+ private Integer code;
+ private String msg;
+
+ ErrorCodeEnum(Integer code, String msg) {
+ this.code = code;
+ this.msg = msg;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public void setCode(Integer code) {
+ this.code = code;
+ }
+
+ public String getMsg() {
+ return msg;
+ }
+
+ public void setMsg(String msg) {
+ this.msg = msg;
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/consts/SheetNaingTypeEnum.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/consts/SheetNaingTypeEnum.java
new file mode 100644
index 000000000..e87273532
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/consts/SheetNaingTypeEnum.java
@@ -0,0 +1,34 @@
+package com.lhd.tams.common.consts;
+
+/**
+ * sheet命名方式
+ */
+public enum SheetNaingTypeEnum {
+
+ WEEK_NUM(2, "第几周"),
+ TIME_PERIOD(1, "时间段");
+
+ private Integer code;
+ private String msg;
+
+ SheetNaingTypeEnum(Integer code, String msg) {
+ this.code = code;
+ this.msg = msg;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public void setCode(Integer code) {
+ this.code = code;
+ }
+
+ public String getMsg() {
+ return msg;
+ }
+
+ public void setMsg(String msg) {
+ this.msg = msg;
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/exception/BusinessException.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/exception/BusinessException.java
new file mode 100644
index 000000000..78aed4448
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/exception/BusinessException.java
@@ -0,0 +1,61 @@
+package com.lhd.tams.common.exception;
+
+import com.lhd.tams.common.consts.ErrorCodeEnum;
+
+/**
+ * 业务异常
+ */
+public class BusinessException extends RuntimeException {
+
+ /**
+ * 错误编码
+ */
+ private Integer code;
+
+ /**
+ * 错误数据
+ */
+ private Object data;
+
+ public BusinessException(String msg) {
+ super(msg);
+ }
+
+ public BusinessException(String msg, Throwable t) {
+ super(msg, t);
+ }
+
+ public BusinessException(ErrorCodeEnum errorCodeEnum) {
+ this(errorCodeEnum.getCode(), errorCodeEnum.getMsg(), null);
+ }
+
+ public BusinessException(ErrorCodeEnum errorApiStatusEnum, Throwable t) {
+ this(errorApiStatusEnum.getCode(), errorApiStatusEnum.getMsg(), t);
+ }
+
+ public BusinessException(Integer code, String msg, Throwable t) {
+ this(code, null, msg, t);
+ }
+
+ public BusinessException(Integer code, Object data, String msg, Throwable t) {
+ super(msg, t);
+ this.code = code;
+ this.data = data;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public void setCode(Integer code) {
+ this.code = code;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/exception/GlobalExceptionHandler.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/exception/GlobalExceptionHandler.java
new file mode 100644
index 000000000..68b6e34a3
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/exception/GlobalExceptionHandler.java
@@ -0,0 +1,118 @@
+package com.lhd.tams.common.exception;
+
+import com.lhd.tams.common.consts.ErrorCodeEnum;
+import com.lhd.tams.common.model.ApiResult;
+import com.lhd.tams.common.util.ResponseEntityUtils;
+import com.mysql.cj.jdbc.exceptions.MysqlDataTruncation;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.validation.FieldError;
+import org.springframework.web.HttpMediaTypeNotSupportedException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import java.nio.file.AccessDeniedException;
+
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+
+ /**
+ * 参数校验异常
+ * @param e
+ * @return
+ */
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ public ResponseEntity> handle(MethodArgumentNotValidException e) {
+
+ String msgStr = "";
+ StringBuilder msgBuilder = new StringBuilder();
+ for (FieldError error : e.getBindingResult().getFieldErrors()) {
+ msgBuilder.append("【");
+ msgBuilder.append(error.getField());
+ msgBuilder.append("】");
+ msgBuilder.append(error.getDefaultMessage());
+ msgBuilder.append(";");
+ }
+
+ if (msgBuilder.length() > 0) {
+ msgStr = msgBuilder.substring(0, msgBuilder.length() - 1);
+ }
+
+ return ResponseEntityUtils.badRequest(msgStr);
+ }
+
+ /**
+ * 参数缺失异常
+ * @param e
+ * @return
+ */
+ @ExceptionHandler(HttpMessageNotReadableException.class)
+ public ResponseEntity> handle(HttpMessageNotReadableException e) {
+
+ return ResponseEntityUtils.badRequest("请求参数转换异常");
+ }
+
+ /**
+ * 媒体类型异常
+ * @param e
+ * @return
+ */
+ @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
+ public ResponseEntity> handle(HttpMediaTypeNotSupportedException e) {
+
+ return ResponseEntityUtils.badRequest("不支持的媒体类型");
+ }
+
+ /**
+ * 访问异常
+ * @param e
+ * @return
+ */
+ @ExceptionHandler(AccessDeniedException.class)
+ public ResponseEntity> handle(AccessDeniedException e) {
+
+ return ResponseEntityUtils.forbidden(e.getMessage());
+ }
+
+ /**
+ * 数据库-数据完整性异常
+ * @param e
+ * @return
+ */
+ @ExceptionHandler(DataIntegrityViolationException.class)
+ public ResponseEntity> handle(DataIntegrityViolationException e) {
+
+ if (((MysqlDataTruncation) e.getCause()).getErrorCode() == 1406) {
+ return ResponseEntityUtils.internalServerError(ErrorCodeEnum.DB_DATA_TOO_LONG, e);
+ }
+
+ return ResponseEntityUtils.internalServerError(ErrorCodeEnum.DB_DATA_INTEGRITY_VIOLATION, e);
+ }
+
+ /**
+ * 业务异常
+ * @param e
+ * @return
+ */
+ @ExceptionHandler(BusinessException.class)
+ public ResponseEntity> handle(BusinessException e) {
+
+ if (e.getCode() == null || e.getCode() >= ErrorCodeEnum.BUSINESS_ERROR.getCode()) {
+ return ResponseEntityUtils.badRequest(e.getCode(), e.getMessage(), e.getData());
+ }
+
+ return ResponseEntityUtils.internalServerError(e.getCode(), e.getMessage(), e);
+ }
+
+ /**
+ * 未知异常
+ * @param e
+ * @return
+ */
+ @ExceptionHandler(Exception.class)
+ public ResponseEntity> handle(Exception e) {
+ return ResponseEntityUtils.internalServerError(ErrorCodeEnum.UNKNOWN_ERROR, e);
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/model/ApiResult.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/model/ApiResult.java
new file mode 100644
index 000000000..ef91336cb
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/model/ApiResult.java
@@ -0,0 +1,63 @@
+package com.lhd.tams.common.model;
+
+/**
+ * 接口返回值结构
+ * @param
+ */
+public class ApiResult {
+
+ /**
+ * 错误编码
+ */
+ private Integer code;
+ /**
+ * 响应信息
+ */
+ private String msg;
+ /**
+ * 响应数据
+ */
+ private T data;
+
+ public ApiResult(String msg) {
+ this(msg, null);
+ }
+
+ public ApiResult(T data) {
+ this("", data);
+ }
+
+ public ApiResult(String msg, T data) {
+ this(null, msg, data);
+ }
+
+ public ApiResult(Integer code, String msg, T data) {
+ this.code = code;
+ this.msg = msg;
+ this.data = data;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public void setCode(Integer code) {
+ this.code = code;
+ }
+
+ public String getMsg() {
+ return msg;
+ }
+
+ public void setMsg(String msg) {
+ this.msg = msg;
+ }
+
+ public T getData() {
+ return data;
+ }
+
+ public void setData(T data) {
+ this.data = data;
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/model/BasePageQuery.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/model/BasePageQuery.java
new file mode 100644
index 000000000..1d5aed771
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/model/BasePageQuery.java
@@ -0,0 +1,34 @@
+package com.lhd.tams.common.model;
+
+public class BasePageQuery {
+
+ private final static int MAX_SIZE = 100;
+ private final static int DEFAULT_SIZE = 10;
+ private final static int FIRST_PAGE = 1;
+
+ /**
+ * 当前页码
+ */
+ private Integer current = 1;
+ /**
+ * 每页大小
+ */
+ private Integer size = 10;
+
+
+ public Integer getCurrent() {
+ return current == null || current <= 0 ? FIRST_PAGE : current;
+ }
+
+ public void setCurrent(Integer current) {
+ this.current = current;
+ }
+
+ public Integer getSize() {
+ return (size == null || size <= 0 || size > MAX_SIZE) ? DEFAULT_SIZE : size;
+ }
+
+ public void setSize(Integer size) {
+ this.size = size;
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/util/CollectionUtils.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/util/CollectionUtils.java
new file mode 100644
index 000000000..9db432ac2
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/util/CollectionUtils.java
@@ -0,0 +1,32 @@
+package com.lhd.tams.common.util;
+
+import java.util.Collection;
+import java.util.Map;
+
+public class CollectionUtils {
+
+ public static boolean isEmpty(Collection> collection) {
+ return collection == null || collection.isEmpty();
+ }
+
+ public static boolean isAnyEmpty(Collection>... collections) {
+ for (Collection> collection : collections) {
+ if (isEmpty(collection)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean isNotEmpty(Collection> collection) {
+ return collection != null && !collection.isEmpty();
+ }
+
+ public static boolean isEmpty(Map, ?> map) {
+ return map == null || map.isEmpty();
+ }
+
+ public static boolean isNotEmpty(Map, ?> map) {
+ return map != null && !map.isEmpty();
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/util/JacksonUtils.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/util/JacksonUtils.java
new file mode 100644
index 000000000..c82878bae
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/util/JacksonUtils.java
@@ -0,0 +1,127 @@
+package com.lhd.tams.common.util;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
+import com.lhd.tams.common.consts.CommonConsts;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * json 工具
+ *
+ * @author lhd
+ */
+public class JacksonUtils {
+
+ private static final Logger log = LoggerFactory.getLogger(JacksonUtils.class);
+
+ public final static Map SERIALIZER_MAP;
+ public final static Map DESERIALIZER_MAP;
+ static {
+ SERIALIZER_MAP = new LinkedHashMap<>();
+ SERIALIZER_MAP.put(Long.class, ToStringSerializer.instance);
+ SERIALIZER_MAP.put(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(CommonConsts.TIME_FORMATTER)));
+ SERIALIZER_MAP.put(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(CommonConsts.DATE_FORMATTER)));
+ SERIALIZER_MAP.put(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(CommonConsts.DATETIME_FORMATTER)));
+
+ DESERIALIZER_MAP = new LinkedHashMap<>();
+ DESERIALIZER_MAP.put(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(CommonConsts.TIME_FORMATTER)));
+ DESERIALIZER_MAP.put(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(CommonConsts.DATE_FORMATTER)));
+ DESERIALIZER_MAP.put(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(CommonConsts.DATETIME_FORMATTER)));
+ }
+
+ private final static ObjectMapper OBJECT_MAPPER;
+ static {
+ OBJECT_MAPPER = new ObjectMapper();
+
+ SimpleModule simpleModule = new SimpleModule();
+ SERIALIZER_MAP.forEach(simpleModule::addSerializer);
+ DESERIALIZER_MAP.forEach(simpleModule::addDeserializer);
+ OBJECT_MAPPER.registerModule(simpleModule);
+ }
+
+ /**
+ * 对象转换字符串
+ * @param obj
+ * @return
+ */
+ public static String toStr(Object obj) {
+ if (obj == null) {
+ return null;
+ }
+ try {
+ return OBJECT_MAPPER.writeValueAsString(obj);
+ } catch (Exception e) {
+ if (log.isDebugEnabled()) {
+ log.debug("转换为字符串出错", e);
+ }
+ }
+ return "";
+ }
+
+ /**
+ * 字符串转换对象
+ * @param str
+ * @return
+ */
+ public static Object toObj(String str) {
+ return toObj(str, Object.class);
+ }
+
+ /**
+ * 字符串转换指定类型
+ * @param str
+ * @param clazz
+ * @param
+ * @return
+ */
+ public static T toObj(String str, Class clazz) {
+
+ if (StringUtils.isEmpty(str) || clazz == null) {
+ return null;
+ }
+
+ try {
+ return OBJECT_MAPPER.readValue(str, clazz);
+ } catch (Exception e) {
+ if (log.isDebugEnabled()) {
+ log.debug("转换为指定类型出错,str: {} class: {}", str, clazz, e);
+ }
+ }
+ return null;
+ }
+
+ public static T toObj(String str, TypeReference typeReference) {
+
+ if (StringUtils.isEmpty(str) || typeReference == null) {
+ return null;
+ }
+
+ try {
+ return OBJECT_MAPPER.readValue(str, typeReference);
+ } catch (Exception e) {
+ if (log.isDebugEnabled()) {
+ log.debug("转换为指定范型出错,str: {}", str, e);
+ }
+ }
+ return null;
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/util/ResponseEntityUtils.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/util/ResponseEntityUtils.java
new file mode 100644
index 000000000..e07e8681f
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/common/util/ResponseEntityUtils.java
@@ -0,0 +1,57 @@
+package com.lhd.tams.common.util;
+
+import com.lhd.tams.common.consts.ErrorCodeEnum;
+import com.lhd.tams.common.model.ApiResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+
+/**
+ * HTTP响应结果构建器,HTTP状态码+接口返回值结构
+ */
+public class ResponseEntityUtils {
+
+ private static final String SERVER_ERROR = "服务器异常,请联系管理员。";
+
+ private static final Logger log = LoggerFactory.getLogger(ResponseEntityUtils.class);
+
+ public static ResponseEntity> ok(String msg) {
+ return ResponseEntity.ok(new ApiResult<>(msg));
+ }
+
+ public static ResponseEntity> ok(T data) {
+ return ResponseEntity.ok(new ApiResult<>(data));
+ }
+
+ public static ResponseEntity> badRequest(String msg) {
+ return new ResponseEntity<>(new ApiResult<>(msg), HttpStatus.BAD_REQUEST);
+ }
+
+ public static ResponseEntity> badRequest(Integer code, String msg, T data) {
+ return new ResponseEntity<>(new ApiResult<>(code, msg, data), HttpStatus.BAD_REQUEST);
+ }
+
+ public static ResponseEntity> unauthorized(String msg) {
+ return new ResponseEntity<>(new ApiResult<>(msg), HttpStatus.UNAUTHORIZED);
+ }
+
+ public static ResponseEntity> forbidden(String msg) {
+ return new ResponseEntity<>(new ApiResult<>(msg), HttpStatus.FORBIDDEN);
+ }
+
+ public static ResponseEntity> internalServerError(ErrorCodeEnum errorCodeEnum, Throwable throwable) {
+
+ log.error(errorCodeEnum.getMsg(), throwable);
+
+ return new ResponseEntity<>(new ApiResult<>(String.format("【%s】%s", errorCodeEnum.getCode(), SERVER_ERROR)), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ public static ResponseEntity> internalServerError(Integer code, String msg, Throwable throwable) {
+
+ log.error(msg, throwable);
+
+ return new ResponseEntity<>(new ApiResult<>(String.format("【%s】%s", code, SERVER_ERROR)), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/config/JacksonConfig.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/config/JacksonConfig.java
new file mode 100644
index 000000000..9ee9f82bf
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/config/JacksonConfig.java
@@ -0,0 +1,18 @@
+package com.lhd.tams.config;
+
+import com.lhd.tams.common.util.JacksonUtils;
+import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class JacksonConfig {
+
+ @Bean
+ public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
+ return (builder) -> {
+ JacksonUtils.SERIALIZER_MAP.forEach(builder::serializerByType);
+ JacksonUtils.DESERIALIZER_MAP.forEach(builder::deserializerByType);
+ };
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/config/MybatisPlusAutoConfigTenant.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/config/MybatisPlusAutoConfigTenant.java
new file mode 100644
index 000000000..2f9bcaa25
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/config/MybatisPlusAutoConfigTenant.java
@@ -0,0 +1,61 @@
+package com.lhd.tams.config;
+
+import cn.hutool.core.collection.ListUtil;
+import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
+import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
+import lombok.extern.slf4j.Slf4j;
+import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.expression.NullValue;
+import net.sf.jsqlparser.expression.StringValue;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.config.MybatisPlusConfig;
+import org.dromara.common.tenant.helper.TenantHelper;
+import org.dromara.common.tenant.properties.TenantProperties;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.List;
+
+@Configuration
+@ConditionalOnBean(MybatisPlusConfig.class)
+@AutoConfiguration(after = {MybatisPlusConfig.class})
+@Slf4j
+public class MybatisPlusAutoConfigTenant {
+
+ @Bean
+ public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantProperties tenantProperties) {
+ return new TenantLineInnerInterceptor(new TenantLineHandler() {
+
+ @Override
+ public Expression getTenantId() {
+ String tenantId = TenantHelper.getTenantId();
+ if (StringUtils.isBlank(tenantId)) {
+ log.error("无法获取有效的租户id -> Null");
+ return new NullValue();
+ }
+ // 返回固定租户
+ return new StringValue(tenantId);
+ }
+
+ @Override
+ public boolean ignoreTable(String tableName) {
+ String tenantId = TenantHelper.getTenantId();
+ // 判断是否有租户
+ if (StringUtils.isNotBlank(tenantId)) {
+ // 不需要过滤租户的表
+ List excludes = tenantProperties.getExcludes();
+ // 非业务表
+ List tables = ListUtil.toList(
+ "gen_table",
+ "gen_table_column"
+ );
+ tables.addAll(excludes);
+ return tables.contains(tableName);
+ }
+ return true;
+ }
+ });
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/config/WebConfiguration.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/config/WebConfiguration.java
new file mode 100644
index 000000000..9a4494bc3
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/config/WebConfiguration.java
@@ -0,0 +1,27 @@
+package com.lhd.tams.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpHeaders;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class WebConfiguration implements WebMvcConfigurer {
+ @Bean
+ public WebMvcConfigurer corsConfigurer() {
+ return new WebMvcConfigurer() {
+ @Override
+ public void addCorsMappings(CorsRegistry registry) {
+ registry.addMapping("/**").
+ allowedMethods(CorsConfiguration.ALL). //允许任何方法(post、get等)
+ allowedHeaders(CorsConfiguration.ALL). //允许任何请求头
+ allowCredentials(true).
+ allowedOriginPatterns(CorsConfiguration.ALL).//带上cookie信息
+ exposedHeaders(HttpHeaders.SET_COOKIE).maxAge(3600L); //maxAge(3600)表明在3600秒内,不需要再发送预检验请求,可以缓存该结果
+ }
+ };
+ }
+
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/Report2Controller.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/Report2Controller.java
new file mode 100644
index 000000000..ce508265b
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/Report2Controller.java
@@ -0,0 +1,37 @@
+package com.lhd.tams.module;
+
+import com.lhd.tams.common.base.BaseController;
+import com.lhd.tams.common.model.ApiResult;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+/**
+ * 测试feign 用的,后面删除
+ */
+@Tag(name = "报表")
+@RequestMapping()
+@RestController
+public class Report2Controller extends BaseController {
+
+ @Autowired
+ private TenantRpc tenantRpc;
+
+ //todo 测试rpc、然后在测试免权限rpc、在测试传递租户信息、用户信息、链路追踪id
+
+ @GetMapping("/resource/sms/code")
+ public ResponseEntity> getReportTeacherCount() {
+ return success(tenantRpc.emailCode());
+ }
+
+ @GetMapping("/system/client/{id}")
+ public ResponseEntity> getReportTeacherCount2(@PathVariable Long id) {
+ return success(tenantRpc.getInfo(id));
+ }
+
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/TenantRpc.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/TenantRpc.java
new file mode 100644
index 000000000..f50e4a266
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/TenantRpc.java
@@ -0,0 +1,22 @@
+package com.lhd.tams.module;
+
+//import com.lhd.tams.config.FeignInterceptor;
+//import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+
+//@FeignClient(
+// name = "saas-tenant-admin", // 服务名称
+// configuration = FeignInterceptor.class // 请求拦截器 (关键代码)
+//// fallbackFactory = SpCfgInterfaceFallback.class // 服务降级处理
+//)
+public interface TenantRpc {
+
+ @GetMapping(value = "/auth/code")
+ Object emailCode();
+
+
+ @GetMapping(value = "/system/client/{id}")
+ Object getInfo(@PathVariable Long id);
+
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/controller/ClassroomController.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/controller/ClassroomController.java
new file mode 100644
index 000000000..56f38b037
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/controller/ClassroomController.java
@@ -0,0 +1,68 @@
+package com.lhd.tams.module.classroom.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.lhd.tams.common.base.BaseController;
+import com.lhd.tams.common.model.ApiResult;
+import com.lhd.tams.module.classroom.model.dto.ClassroomPageQuery;
+import com.lhd.tams.module.classroom.model.dto.ClassroomSaveDTO;
+import com.lhd.tams.module.classroom.model.vo.ClassroomListVO;
+import com.lhd.tams.module.classroom.service.ClassroomService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Tag(name = "教室")
+@RequestMapping("classroom")
+@RestController
+public class ClassroomController extends BaseController {
+
+ @Autowired
+ private ClassroomService classroomService;
+
+ @Operation(summary = "分页列表")
+ @GetMapping
+ public ResponseEntity>> pageCourse(ClassroomPageQuery pageQuery) {
+
+ return success(classroomService.pageCourse(pageQuery));
+ }
+
+ @Operation(summary = "参照列表")
+ @GetMapping("list/ref")
+ public ResponseEntity>> refList() {
+
+ return success(classroomService.refList());
+ }
+
+ @Operation(summary = "详情")
+ @GetMapping("{id}")
+ public ResponseEntity> getCourseById(@PathVariable("id") Long id) {
+
+ return success(classroomService.getCourseById(id));
+ }
+
+ @Operation(summary = "新增")
+ @PostMapping
+ public ResponseEntity> saveCourse(@Validated @RequestBody ClassroomSaveDTO saveDTO) {
+
+ return successOrFail(classroomService.saveCourse(saveDTO));
+ }
+
+ @Operation(summary = "修改")
+ @PutMapping("{id}")
+ public ResponseEntity> updateCourseById(@PathVariable("id") Long id, @Validated @RequestBody ClassroomSaveDTO saveDTO) {
+
+ return successOrFail(classroomService.updateCourseById(id, saveDTO));
+ }
+
+ @Operation(summary = "停启用")
+ @PutMapping("{id}/enable-state/{enableState}")
+ public ResponseEntity> updateCourseEnableStateById(@PathVariable("id") Long id, @PathVariable("enableState") Integer enableState) {
+
+ return successOrFail(classroomService.updateCourseEnableStateById(id, enableState));
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/dao/ClassroomMapper.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/dao/ClassroomMapper.java
new file mode 100644
index 000000000..773405fd1
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/dao/ClassroomMapper.java
@@ -0,0 +1,7 @@
+package com.lhd.tams.module.classroom.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.lhd.tams.module.classroom.model.data.ClassroomDO;
+
+public interface ClassroomMapper extends BaseMapper {
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/model/convert/AbstractClassroomConverter.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/model/convert/AbstractClassroomConverter.java
new file mode 100644
index 000000000..ab9e41b00
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/model/convert/AbstractClassroomConverter.java
@@ -0,0 +1,26 @@
+package com.lhd.tams.module.classroom.model.convert;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.lhd.tams.module.classroom.model.data.ClassroomDO;
+import com.lhd.tams.module.classroom.model.dto.ClassroomSaveDTO;
+import com.lhd.tams.module.classroom.model.vo.ClassroomListVO;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+@Mapper
+public abstract class AbstractClassroomConverter {
+
+ public static AbstractClassroomConverter INSTANCE = Mappers.getMapper(AbstractClassroomConverter.class);
+
+ public abstract Page doPage2ListVoPage(IPage doPage);
+
+ public abstract List doList2ListVoList(List doList);
+
+ public abstract ClassroomListVO do2ListVO(ClassroomDO dataObj);
+
+ public abstract ClassroomDO saveDto2DO(ClassroomSaveDTO saveDTO);
+
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/model/data/ClassroomDO.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/model/data/ClassroomDO.java
new file mode 100644
index 000000000..3d9920557
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/model/data/ClassroomDO.java
@@ -0,0 +1,24 @@
+package com.lhd.tams.module.classroom.model.data;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@Data
+@TableName("t_classroom")
+public class ClassroomDO {
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 名称
+ */
+ private String name;
+
+ /**
+ * 停启用状态
+ */
+ private Integer enableState;
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/model/dto/ClassroomPageQuery.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/model/dto/ClassroomPageQuery.java
new file mode 100644
index 000000000..a2f570909
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/model/dto/ClassroomPageQuery.java
@@ -0,0 +1,13 @@
+package com.lhd.tams.module.classroom.model.dto;
+
+import com.lhd.tams.common.model.BasePageQuery;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "教室分页查询参数")
+@Data
+public class ClassroomPageQuery extends BasePageQuery {
+
+ @Schema(description = "停启用状态")
+ private Integer enableState;
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/model/dto/ClassroomSaveDTO.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/model/dto/ClassroomSaveDTO.java
new file mode 100644
index 000000000..fd039b8e1
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/model/dto/ClassroomSaveDTO.java
@@ -0,0 +1,12 @@
+package com.lhd.tams.module.classroom.model.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "教室新增参数")
+@Data
+public class ClassroomSaveDTO {
+
+ @Schema(description = "名称")
+ private String name;
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/model/vo/ClassroomListVO.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/model/vo/ClassroomListVO.java
new file mode 100644
index 000000000..20ffe36b3
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/model/vo/ClassroomListVO.java
@@ -0,0 +1,18 @@
+package com.lhd.tams.module.classroom.model.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "教室列表返回结果")
+@Data
+public class ClassroomListVO {
+
+ @Schema(description = "id")
+ private Long id;
+
+ @Schema(description = "名称")
+ private String name;
+
+ @Schema(description = "停启用状态")
+ private Integer enableState;
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/service/ClassroomService.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/service/ClassroomService.java
new file mode 100644
index 000000000..8a9273274
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/service/ClassroomService.java
@@ -0,0 +1,23 @@
+package com.lhd.tams.module.classroom.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.lhd.tams.module.classroom.model.dto.ClassroomPageQuery;
+import com.lhd.tams.module.classroom.model.dto.ClassroomSaveDTO;
+import com.lhd.tams.module.classroom.model.vo.ClassroomListVO;
+
+import java.util.List;
+
+public interface ClassroomService {
+
+ IPage pageCourse(ClassroomPageQuery pageQuery);
+
+ List refList();
+
+ ClassroomListVO getCourseById(Long id);
+
+ boolean saveCourse(ClassroomSaveDTO saveDTO);
+
+ boolean updateCourseById(Long id, ClassroomSaveDTO saveDTO);
+
+ boolean updateCourseEnableStateById(Long id, Integer enableState);
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/service/impl/ClassroomServiceImpl.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/service/impl/ClassroomServiceImpl.java
new file mode 100644
index 000000000..729551c4e
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/classroom/service/impl/ClassroomServiceImpl.java
@@ -0,0 +1,87 @@
+package com.lhd.tams.module.classroom.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.lhd.tams.common.consts.EnableStateEnum;
+import com.lhd.tams.module.classroom.dao.ClassroomMapper;
+import com.lhd.tams.module.classroom.model.convert.AbstractClassroomConverter;
+import com.lhd.tams.module.classroom.model.data.ClassroomDO;
+import com.lhd.tams.module.classroom.model.dto.ClassroomPageQuery;
+import com.lhd.tams.module.classroom.model.dto.ClassroomSaveDTO;
+import com.lhd.tams.module.classroom.model.vo.ClassroomListVO;
+import com.lhd.tams.module.classroom.service.ClassroomService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class ClassroomServiceImpl extends ServiceImpl implements ClassroomService {
+
+ @Override
+ public IPage pageCourse(ClassroomPageQuery pageQuery) {
+
+ LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery()
+ .eq(pageQuery.getEnableState() != null, ClassroomDO::getEnableState, pageQuery.getEnableState())
+ .orderByAsc(ClassroomDO::getName);
+
+ IPage doPage = page(new Page<>(pageQuery.getCurrent(), pageQuery.getSize()), queryWrapper);
+
+ IPage voPage = AbstractClassroomConverter.INSTANCE.doPage2ListVoPage(doPage);
+
+ return voPage;
+ }
+
+ @Override
+ public List refList() {
+
+ LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery()
+ .eq(ClassroomDO::getEnableState, EnableStateEnum.ENABLED.getCode())
+ .orderByAsc(ClassroomDO::getName);
+
+ List doList = list(queryWrapper);
+
+ List voList = AbstractClassroomConverter.INSTANCE.doList2ListVoList(doList);
+
+ return voList;
+ }
+
+ @Override
+ public ClassroomListVO getCourseById(Long id) {
+
+ ClassroomDO dataObj = getById(id);
+
+ ClassroomListVO vo = AbstractClassroomConverter.INSTANCE.do2ListVO(dataObj);
+
+ return vo;
+ }
+
+ @Override
+ public boolean saveCourse(ClassroomSaveDTO saveDTO) {
+
+ ClassroomDO dataObj = AbstractClassroomConverter.INSTANCE.saveDto2DO(saveDTO);
+
+ return save(dataObj);
+ }
+
+ @Override
+ public boolean updateCourseById(Long id, ClassroomSaveDTO saveDTO) {
+
+ ClassroomDO dataObj = AbstractClassroomConverter.INSTANCE.saveDto2DO(saveDTO);
+ dataObj.setId(id);
+
+ return updateById(dataObj);
+ }
+
+ @Override
+ public boolean updateCourseEnableStateById(Long id, Integer enableState) {
+
+ ClassroomDO dataObj = new ClassroomDO();
+ dataObj.setId(id);
+ dataObj.setEnableState(enableState);
+
+ return updateById(dataObj);
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/controller/ColorController.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/controller/ColorController.java
new file mode 100644
index 000000000..2ea1e2069
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/controller/ColorController.java
@@ -0,0 +1,30 @@
+package com.lhd.tams.module.color.controller;
+
+import com.lhd.tams.common.base.BaseController;
+import com.lhd.tams.common.model.ApiResult;
+import com.lhd.tams.module.color.service.ColorService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@Tag(name = "颜色")
+@RequestMapping("color")
+@RestController
+public class ColorController extends BaseController {
+
+ @Autowired
+ private ColorService colorService;
+
+ @Operation(summary = "有效颜色列表")
+ @GetMapping("list/effective")
+ public ResponseEntity>> getEffectiveList() {
+
+ return success(colorService.getEffectiveList());
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/dao/ColorMapper.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/dao/ColorMapper.java
new file mode 100644
index 000000000..993d5fee2
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/dao/ColorMapper.java
@@ -0,0 +1,7 @@
+package com.lhd.tams.module.color.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.lhd.tams.module.color.model.data.ColorDO;
+
+public interface ColorMapper extends BaseMapper {
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/model/convert/AbstractColorConverter.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/model/convert/AbstractColorConverter.java
new file mode 100644
index 000000000..5b4ec8daa
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/model/convert/AbstractColorConverter.java
@@ -0,0 +1,16 @@
+package com.lhd.tams.module.color.model.convert;
+
+import com.lhd.tams.module.color.model.data.ColorDO;
+import com.lhd.tams.module.color.model.vo.ColorListVO;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+@Mapper
+public abstract class AbstractColorConverter {
+
+ public static AbstractColorConverter INSTANCE = Mappers.getMapper(AbstractColorConverter.class);
+
+ public abstract List doList2ListVoList(List doList);
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/model/data/ColorDO.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/model/data/ColorDO.java
new file mode 100644
index 000000000..6c022c478
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/model/data/ColorDO.java
@@ -0,0 +1,24 @@
+package com.lhd.tams.module.color.model.data;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@Data
+@TableName("t_color")
+public class ColorDO {
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 名称
+ */
+ private String name;
+
+ /**
+ * 值
+ */
+ private String value;
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/model/vo/ColorListVO.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/model/vo/ColorListVO.java
new file mode 100644
index 000000000..72270baf1
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/model/vo/ColorListVO.java
@@ -0,0 +1,18 @@
+package com.lhd.tams.module.color.model.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "颜色列表返回结果")
+@Data
+public class ColorListVO {
+
+ @Schema(description = "id")
+ private Long id;
+
+ @Schema(description = "名称")
+ private String name;
+
+ @Schema(description = "值")
+ private String value;
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/service/ColorService.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/service/ColorService.java
new file mode 100644
index 000000000..94d67d113
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/service/ColorService.java
@@ -0,0 +1,8 @@
+package com.lhd.tams.module.color.service;
+
+import java.util.List;
+
+public interface ColorService {
+
+ List getEffectiveList();
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/service/impl/ColorServiceImpl.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/service/impl/ColorServiceImpl.java
new file mode 100644
index 000000000..8177c02f2
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/color/service/impl/ColorServiceImpl.java
@@ -0,0 +1,26 @@
+package com.lhd.tams.module.color.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.lhd.tams.module.color.dao.ColorMapper;
+import com.lhd.tams.module.color.model.data.ColorDO;
+import com.lhd.tams.module.color.service.ColorService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class ColorServiceImpl extends ServiceImpl implements ColorService {
+
+ @Override
+ public List getEffectiveList() {
+
+ LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery()
+ .select(ColorDO::getValue)
+ .notExists("select 1 from t_course course where course.background_color = t_color.value")
+ .orderByAsc(ColorDO::getValue);
+
+ return listObjs(queryWrapper, Object::toString);
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/controller/CourseController.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/controller/CourseController.java
new file mode 100644
index 000000000..f81f08cd1
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/controller/CourseController.java
@@ -0,0 +1,68 @@
+package com.lhd.tams.module.course.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.lhd.tams.common.base.BaseController;
+import com.lhd.tams.common.model.ApiResult;
+import com.lhd.tams.module.course.model.dto.CoursePageQuery;
+import com.lhd.tams.module.course.model.dto.CourseSaveDTO;
+import com.lhd.tams.module.course.model.vo.CourseListVO;
+import com.lhd.tams.module.course.service.CourseService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Tag(name = "课程")
+@RequestMapping("course")
+@RestController
+public class CourseController extends BaseController {
+
+ @Autowired
+ private CourseService courseService;
+
+ @Operation(summary = "分页列表")
+ @GetMapping
+ public ResponseEntity>> pageCourse(CoursePageQuery pageQuery) {
+
+ return success(courseService.pageCourse(pageQuery));
+ }
+
+ @Operation(summary = "参照列表")
+ @GetMapping("list/ref")
+ public ResponseEntity>> refList() {
+
+ return success(courseService.refList());
+ }
+
+ @Operation(summary = "详情")
+ @GetMapping("{id}")
+ public ResponseEntity> getCourseById(@PathVariable("id") Long id) {
+
+ return success(courseService.getCourseById(id));
+ }
+
+ @Operation(summary = "新增")
+ @PostMapping
+ public ResponseEntity> saveCourse(@Validated @RequestBody CourseSaveDTO saveDTO) {
+
+ return successOrFail(courseService.saveCourse(saveDTO));
+ }
+
+ @Operation(summary = "修改")
+ @PutMapping("{id}")
+ public ResponseEntity> updateCourseById(@PathVariable("id") Long id, @Validated @RequestBody CourseSaveDTO saveDTO) {
+
+ return successOrFail(courseService.updateCourseById(id, saveDTO));
+ }
+
+ @Operation(summary = "停启用")
+ @PutMapping("{id}/enable-state/{enableState}")
+ public ResponseEntity> updateCourseEnableStateById(@PathVariable("id") Long id, @PathVariable("enableState") Integer enableState) {
+
+ return successOrFail(courseService.updateCourseEnableStateById(id, enableState));
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/dao/CourseMapper.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/dao/CourseMapper.java
new file mode 100644
index 000000000..350079c32
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/dao/CourseMapper.java
@@ -0,0 +1,7 @@
+package com.lhd.tams.module.course.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.lhd.tams.module.course.model.data.CourseDO;
+
+public interface CourseMapper extends BaseMapper {
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/model/convert/AbstractCourseConverter.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/model/convert/AbstractCourseConverter.java
new file mode 100644
index 000000000..47ad33ce2
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/model/convert/AbstractCourseConverter.java
@@ -0,0 +1,26 @@
+package com.lhd.tams.module.course.model.convert;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.lhd.tams.module.course.model.data.CourseDO;
+import com.lhd.tams.module.course.model.dto.CourseSaveDTO;
+import com.lhd.tams.module.course.model.vo.CourseListVO;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+@Mapper
+public abstract class AbstractCourseConverter {
+
+ public static AbstractCourseConverter INSTANCE = Mappers.getMapper(AbstractCourseConverter.class);
+
+ public abstract Page doPage2ListVoPage(IPage doPage);
+
+ public abstract List doList2ListVoList(List doList);
+
+ public abstract CourseListVO do2ListVO(CourseDO dataObj);
+
+ public abstract CourseDO saveDto2DO(CourseSaveDTO saveDTO);
+
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/model/data/CourseDO.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/model/data/CourseDO.java
new file mode 100644
index 000000000..6909a828e
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/model/data/CourseDO.java
@@ -0,0 +1,39 @@
+package com.lhd.tams.module.course.model.data;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@Data
+@TableName("t_course")
+public class CourseDO {
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 名称
+ */
+ private String name;
+
+ /**
+ * 停启用状态
+ */
+ private Integer enableState;
+
+ /**
+ * 课程时长,单位分钟
+ */
+ private Integer duration;
+
+ /**
+ * 课时
+ */
+ private Double lesson;
+
+ /**
+ * 背景颜色
+ */
+ private String backgroundColor;
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/model/dto/CoursePageQuery.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/model/dto/CoursePageQuery.java
new file mode 100644
index 000000000..848298e19
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/model/dto/CoursePageQuery.java
@@ -0,0 +1,13 @@
+package com.lhd.tams.module.course.model.dto;
+
+import com.lhd.tams.common.model.BasePageQuery;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "课程分页查询参数")
+@Data
+public class CoursePageQuery extends BasePageQuery {
+
+ @Schema(description = "停启用状态")
+ private Integer enableState;
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/model/dto/CourseSaveDTO.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/model/dto/CourseSaveDTO.java
new file mode 100644
index 000000000..85aabc4f0
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/model/dto/CourseSaveDTO.java
@@ -0,0 +1,21 @@
+package com.lhd.tams.module.course.model.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "课程新增参数")
+@Data
+public class CourseSaveDTO {
+
+ @Schema(description = "名称")
+ private String name;
+
+ @Schema(description = "课程时长,单位分钟")
+ private Integer duration;
+
+ @Schema(description = "课时")
+ private Double lesson;
+
+ @Schema(description = "背景颜色")
+ private String backgroundColor;
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/model/vo/CourseListVO.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/model/vo/CourseListVO.java
new file mode 100644
index 000000000..e06b61473
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/model/vo/CourseListVO.java
@@ -0,0 +1,27 @@
+package com.lhd.tams.module.course.model.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "课程列表返回结果")
+@Data
+public class CourseListVO {
+
+ @Schema(description = "id")
+ private Long id;
+
+ @Schema(description = "名称")
+ private String name;
+
+ @Schema(description = "停启用状态")
+ private Integer enableState;
+
+ @Schema(description = "课程时长,单位分钟")
+ private Integer duration;
+
+ @Schema(description = "课时")
+ private Double lesson;
+
+ @Schema(description = "背景颜色")
+ private String backgroundColor;
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/service/CourseService.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/service/CourseService.java
new file mode 100644
index 000000000..0a9c8c651
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/service/CourseService.java
@@ -0,0 +1,23 @@
+package com.lhd.tams.module.course.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.lhd.tams.module.course.model.dto.CoursePageQuery;
+import com.lhd.tams.module.course.model.dto.CourseSaveDTO;
+import com.lhd.tams.module.course.model.vo.CourseListVO;
+
+import java.util.List;
+
+public interface CourseService {
+
+ IPage pageCourse(CoursePageQuery pageQuery);
+
+ List refList();
+
+ CourseListVO getCourseById(Long id);
+
+ boolean saveCourse(CourseSaveDTO saveDTO);
+
+ boolean updateCourseById(Long id, CourseSaveDTO saveDTO);
+
+ boolean updateCourseEnableStateById(Long id, Integer enableState);
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/service/impl/CourseServiceImpl.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/service/impl/CourseServiceImpl.java
new file mode 100644
index 000000000..178789ca6
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/course/service/impl/CourseServiceImpl.java
@@ -0,0 +1,87 @@
+package com.lhd.tams.module.course.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.lhd.tams.common.consts.EnableStateEnum;
+import com.lhd.tams.module.course.dao.CourseMapper;
+import com.lhd.tams.module.course.model.convert.AbstractCourseConverter;
+import com.lhd.tams.module.course.model.data.CourseDO;
+import com.lhd.tams.module.course.model.dto.CoursePageQuery;
+import com.lhd.tams.module.course.model.dto.CourseSaveDTO;
+import com.lhd.tams.module.course.model.vo.CourseListVO;
+import com.lhd.tams.module.course.service.CourseService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class CourseServiceImpl extends ServiceImpl implements CourseService {
+
+ @Override
+ public IPage pageCourse(CoursePageQuery pageQuery) {
+
+ LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery()
+ .eq(pageQuery.getEnableState() != null, CourseDO::getEnableState, pageQuery.getEnableState())
+ .orderByAsc(CourseDO::getName);
+
+ IPage doPage = page(new Page<>(pageQuery.getCurrent(), pageQuery.getSize()), queryWrapper);
+
+ IPage voPage = AbstractCourseConverter.INSTANCE.doPage2ListVoPage(doPage);
+
+ return voPage;
+ }
+
+ @Override
+ public List refList() {
+
+ LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery()
+ .eq(CourseDO::getEnableState, EnableStateEnum.ENABLED.getCode())
+ .orderByAsc(CourseDO::getName);
+
+ List doList = list(queryWrapper);
+
+ List voList = AbstractCourseConverter.INSTANCE.doList2ListVoList(doList);
+
+ return voList;
+ }
+
+ @Override
+ public CourseListVO getCourseById(Long id) {
+
+ CourseDO dataObj = getById(id);
+
+ CourseListVO vo = AbstractCourseConverter.INSTANCE.do2ListVO(dataObj);
+
+ return vo;
+ }
+
+ @Override
+ public boolean saveCourse(CourseSaveDTO saveDTO) {
+
+ CourseDO dataObj = AbstractCourseConverter.INSTANCE.saveDto2DO(saveDTO);
+
+ return save(dataObj);
+ }
+
+ @Override
+ public boolean updateCourseById(Long id, CourseSaveDTO saveDTO) {
+
+ CourseDO dataObj = AbstractCourseConverter.INSTANCE.saveDto2DO(saveDTO);
+ dataObj.setId(id);
+
+ return updateById(dataObj);
+ }
+
+ @Override
+ public boolean updateCourseEnableStateById(Long id, Integer enableState) {
+
+ CourseDO dataObj = new CourseDO();
+ dataObj.setId(id);
+ dataObj.setEnableState(enableState);
+
+ return updateById(dataObj);
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/coursescheduling/controller/CourseSchedulingController.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/coursescheduling/controller/CourseSchedulingController.java
new file mode 100644
index 000000000..73c83b5fe
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/coursescheduling/controller/CourseSchedulingController.java
@@ -0,0 +1,118 @@
+package com.lhd.tams.module.coursescheduling.controller;
+
+import com.lhd.tams.common.base.BaseController;
+import com.lhd.tams.common.model.ApiResult;
+import com.lhd.tams.module.coursescheduling.manager.CourseSchedulingExcelManager;
+import com.lhd.tams.module.coursescheduling.model.dto.*;
+import com.lhd.tams.module.coursescheduling.model.vo.CourseSchedulingListVO;
+import com.lhd.tams.module.coursescheduling.service.CourseSchedulingService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
+
+@Tag(name = "排课")
+@RequestMapping("course-scheduling")
+@RestController
+public class CourseSchedulingController extends BaseController {
+
+ @Autowired
+ private CourseSchedulingService courseSchedulingService;
+
+ @Autowired
+ private CourseSchedulingExcelManager courseSchedulingExcelManager;
+
+ @Operation(summary = "列表")
+ @PostMapping("list")
+ public ResponseEntity>> listCourseScheduling(@RequestBody CourseSchedulingQuery query) {
+
+ return success(courseSchedulingService.listCourseScheduling(query));
+ }
+
+ @Operation(summary = "详情")
+ @GetMapping("{id}")
+ public ResponseEntity> getCourseSchedulingById(@PathVariable("id") Long id) {
+
+ return success(courseSchedulingService.getCourseSchedulingById(id));
+ }
+
+ @Operation(summary = "课程数量")
+ @PostMapping("course/count")
+ public ResponseEntity>> getCourseSchedulingCourseCount(@RequestBody CourseSchedulingQuery query) {
+
+ return success(courseSchedulingService.getCourseSchedulingCourseCount(query));
+ }
+
+ @Operation(summary = "新增")
+ @PostMapping
+ public ResponseEntity> saveCourseScheduling(@Validated @RequestBody CourseSchedulingSaveDTO saveDTO) {
+
+ return successOrFail(courseSchedulingService.saveCourseScheduling(saveDTO));
+ }
+
+ @Operation(summary = "批量新增")
+ @PostMapping("batch")
+ public ResponseEntity> saveCourseScheduling(@Validated @RequestBody CourseSchedulingBatchSaveDTO saveDTO) {
+
+ courseSchedulingService.batchSaveCourseScheduling(saveDTO);
+
+ return success();
+ }
+
+ @Operation(summary = "修改排课时间")
+ @PutMapping("{id}/time")
+ public ResponseEntity> updateCourseSchedulingTimeById(@PathVariable("id") Long id, @Validated @RequestBody CourseSchedulingTimeUpdateDTO updateDTO) {
+
+ return successOrFail(courseSchedulingService.updateCourseSchedulingTimeById(id, updateDTO));
+ }
+
+ @Operation(summary = "修改")
+ @PutMapping("{id}")
+ public ResponseEntity> updateCourseSchedulingById(@PathVariable("id") Long id, @Validated @RequestBody CourseSchedulingSaveDTO saveDTO) {
+
+ return successOrFail(courseSchedulingService.updateCourseSchedulingById(id, saveDTO));
+ }
+
+ @Operation(summary = "删除")
+ @DeleteMapping("{id}")
+ public ResponseEntity> removeCourseSchedulingById(@PathVariable("id") Long id) {
+
+ return successOrFail(courseSchedulingService.removeCourseSchedulingById(id));
+ }
+
+ @Operation(summary = "批量删除")
+ @DeleteMapping("batch")
+ public ResponseEntity> removeCourseSchedulingByIdList(@RequestBody List idList) {
+
+ courseSchedulingService.removeCourseSchedulingByIdList(idList);
+
+ return success();
+ }
+
+ @Operation(summary = "导出excel")
+ @GetMapping("export/excel")
+ public void exportExcel(HttpServletResponse response, @Validated CourseSchedulingExportDTO dto) throws IOException {
+
+ Workbook workbook = courseSchedulingExcelManager.createExcel(dto);
+
+ String filename = (StringUtils.isEmpty(dto.getFilename()) ? "课表" : dto.getFilename()) + ".xlsx";
+ response.reset();
+ response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+ response.setHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes(), StandardCharsets.ISO_8859_1));
+
+ workbook.write(response.getOutputStream());
+ response.flushBuffer();
+
+ workbook.close();
+ }
+}
diff --git a/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/coursescheduling/dao/CourseSchedulingMapper.java b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/coursescheduling/dao/CourseSchedulingMapper.java
new file mode 100644
index 000000000..c77830fdb
--- /dev/null
+++ b/ruoyi-site/ruoyi-tams/src/main/java/com/lhd/tams/module/coursescheduling/dao/CourseSchedulingMapper.java
@@ -0,0 +1,31 @@
+package com.lhd.tams.module.coursescheduling.dao;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
+import com.lhd.tams.module.coursescheduling.model.data.CourseSchedulingDO;
+import com.lhd.tams.module.coursescheduling.model.vo.CourseSchedulingExportVO;
+import com.lhd.tams.module.coursescheduling.model.vo.CourseSchedulingListVO;
+import com.lhd.tams.module.coursescheduling.model.vo.CourseSchedulingReportVO;
+import org.apache.ibatis.annotations.Param;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Map;
+
+public interface CourseSchedulingMapper extends BaseMapper {
+
+ List selectCourseSchedulingList(@Param(Constants.WRAPPER) Wrapper> queryWrapper);
+
+ CourseSchedulingListVO selectCourseSchedulingById(Long id);
+
+ List